-
Notifications
You must be signed in to change notification settings - Fork 286
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support Remix v2 in route generator (#756)
* Support v2_routeConvention when generating routes * Cleanup skeleton imports * Support v2_meta format in skeleton * Support v2_meta in hello-world template * Changeset * Fix double export keyword * Refactor * Enable flags automatically for Remix v2 * Fix: import config using ESM * Revert code that will be removed in another PR * Refactor * Extract v2flags logic * Default to v2_meta:true in generators and hello-world * Extract tests specific to Remix v2 flags * Support v2_errorBoundary in generators and enable it by default in hello-world * Enable v2_routeConvention by default in hello-world * Cleanup * Detect v1 route convention package * Allow function exports for meta en error boundaries * Add docs for v1-v2 interop in skeleton routes * Move V2_MetaFunction import to remix-run/react * Change where V2_MetaFunction is imported from in Remix 1.15.0 * Cleanup
- Loading branch information
Showing
15 changed files
with
363 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@shopify/cli-hydrogen': patch | ||
--- | ||
|
||
Add support for the Remix future flags `v2_meta`, `v2_errorBoundary` and `v2_routeConvention` to the `generate` command. If these flags are enabled in your project, the new generated files will follow the v2 conventions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import {describe, it, expect} from 'vitest'; | ||
import {convertTemplateToRemixVersion} from './remix-version-interop.js'; | ||
|
||
describe('remix-version-interop', () => { | ||
describe('v2_meta', () => { | ||
const META_TEMPLATE = ` | ||
import {type MetaFunction} from '@shopify/remix-oxygen'; | ||
import {type V2_MetaFunction} from '@remix-run/react'; | ||
export const metaV1: MetaFunction = ({data}) => { | ||
const title = 'title'; | ||
return {title}; | ||
}; | ||
export const meta: V2_MetaFunction = ({data}) => { | ||
const title = 'title'; | ||
return [{title}]; | ||
}; | ||
`.replace(/^\s{4}/gm, ''); | ||
|
||
it('transforms meta exports to v2', async () => { | ||
const result = convertTemplateToRemixVersion(META_TEMPLATE, { | ||
isV2Meta: true, | ||
}); | ||
|
||
expect(result).toContain('type V2_MetaFunction'); | ||
expect(result).not.toContain('type MetaFunction'); | ||
expect(result).not.toContain('@shopify/remix-oxygen'); | ||
expect(result).toMatch(/return \[\{title\}\];/); | ||
expect(result).not.toMatch(/return \{title\};/); | ||
}); | ||
|
||
it('transforms meta exports to v1', async () => { | ||
const result = convertTemplateToRemixVersion(META_TEMPLATE, { | ||
isV2Meta: false, | ||
}); | ||
|
||
expect(result).toContain('type MetaFunction'); | ||
expect(result).not.toContain('type V2_MetaFunction'); | ||
expect(result).not.toContain('@remix-run/react'); | ||
expect(result).toMatch(/return \{title\};/); | ||
expect(result).not.toMatch(/return \[\{title\}\];/); | ||
}); | ||
}); | ||
|
||
describe('v2_errorBoundary', () => { | ||
const ERROR_BOUNDARY_TEMPLATE = ` | ||
import {useCatch, isRouteErrorResponse, useRouteError} from "@remix-run/react"; | ||
import {type ErrorBoundaryComponent} from '@shopify/remix-oxygen'; | ||
export function CatchBoundary() { | ||
const caught = useCatch(); | ||
console.error(caught); | ||
return <div>stuff</div>; | ||
} | ||
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => { | ||
console.error(error); | ||
return <div>There was an error.</div>; | ||
}; | ||
export function ErrorBoundary() { | ||
const error = useRouteError(); | ||
if (isRouteErrorResponse(error)) { | ||
return <div>RouteError</div>; | ||
} else { | ||
return <h1>Unknown Error</h1>; | ||
} | ||
} | ||
`.replace(/^\s{4}/gm, ''); | ||
|
||
it('transforms ErrorBoundary exports to v2', async () => { | ||
const result = convertTemplateToRemixVersion(ERROR_BOUNDARY_TEMPLATE, { | ||
isV2ErrorBoundary: true, | ||
}); | ||
|
||
expect(result).toContain('export function ErrorBoundary'); | ||
expect(result).not.toContain('export const ErrorBoundary'); | ||
expect(result).not.toMatch('export function CatchBoundary'); | ||
expect(result).not.toContain('type ErrorBoundaryComponent'); | ||
expect(result).not.toContain('@shopify/remix-oxygen'); // Cleans empty up imports | ||
expect(result).toContain('useRouteError'); | ||
expect(result).toContain('isRouteErrorResponse'); | ||
expect(result).not.toContain('useCatch'); | ||
}); | ||
|
||
it('transforms ErrorBoundary exports to v1', async () => { | ||
const result = convertTemplateToRemixVersion(ERROR_BOUNDARY_TEMPLATE, { | ||
isV2ErrorBoundary: false, | ||
}); | ||
|
||
expect(result).toContain('export const ErrorBoundary'); | ||
expect(result).not.toContain('export function ErrorBoundary'); | ||
expect(result).toMatch('export function CatchBoundary'); | ||
expect(result).toContain('type ErrorBoundaryComponent'); | ||
expect(result).toContain('useCatch'); | ||
expect(result).not.toContain('useRouteError'); | ||
expect(result).not.toContain('isRouteErrorResponse'); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.