@shopify/cli-hydrogen 4.0.9 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/hydrogen/build.d.ts +4 -4
- package/dist/commands/hydrogen/build.js +17 -16
- package/dist/commands/hydrogen/check.d.ts +3 -6
- package/dist/commands/hydrogen/check.js +10 -9
- package/dist/commands/hydrogen/dev.d.ts +3 -3
- package/dist/commands/hydrogen/dev.js +22 -21
- package/dist/commands/hydrogen/g.d.ts +10 -0
- package/dist/commands/hydrogen/g.js +17 -0
- package/dist/commands/hydrogen/generate/route.d.ts +7 -9
- package/dist/commands/hydrogen/generate/route.js +49 -47
- package/dist/commands/hydrogen/generate/route.test.js +48 -40
- package/dist/commands/hydrogen/generate/routes.d.ts +2 -2
- package/dist/commands/hydrogen/init.d.ts +3 -3
- package/dist/commands/hydrogen/init.js +74 -93
- package/dist/commands/hydrogen/init.test.js +71 -24
- package/dist/commands/hydrogen/preview.d.ts +2 -2
- package/dist/commands/hydrogen/preview.js +4 -4
- package/dist/commands/hydrogen/shortcut.d.ts +9 -0
- package/dist/commands/hydrogen/shortcut.js +74 -0
- package/dist/commands/hydrogen/shortcut.test.js +58 -0
- package/dist/generator-templates/routes/[robots.txt].tsx +35 -1
- package/dist/generator-templates/routes/[sitemap.xml].tsx +33 -2
- package/dist/generator-templates/routes/account/login.tsx +42 -13
- package/dist/generator-templates/routes/account/register.tsx +42 -13
- package/dist/generator-templates/routes/cart.tsx +42 -2
- package/dist/generator-templates/routes/collections/$collectionHandle.tsx +44 -5
- package/dist/generator-templates/routes/index.tsx +33 -0
- package/dist/generator-templates/routes/pages/$pageHandle.tsx +48 -10
- package/dist/generator-templates/routes/policies/$policyHandle.tsx +67 -14
- package/dist/generator-templates/routes/policies/index.tsx +54 -4
- package/dist/generator-templates/routes/products/$productHandle.tsx +44 -9
- package/dist/hooks/init.js +2 -2
- package/dist/{utils → lib}/check-lockfile.js +7 -4
- package/dist/{utils → lib}/check-lockfile.test.js +19 -28
- package/dist/{utils → lib}/check-version.test.js +3 -2
- package/dist/lib/colors.d.ts +8 -0
- package/dist/lib/colors.js +8 -0
- package/dist/{utils → lib}/config.js +9 -18
- package/dist/{utils → lib}/flags.d.ts +3 -3
- package/dist/{utils → lib}/flags.js +4 -4
- package/dist/{utils → lib}/mini-oxygen.js +14 -12
- package/dist/lib/remix-version-interop.d.ts +11 -0
- package/dist/lib/remix-version-interop.js +54 -0
- package/dist/lib/remix-version-interop.test.d.ts +1 -0
- package/dist/lib/remix-version-interop.test.js +93 -0
- package/dist/lib/shell.d.ts +12 -0
- package/dist/lib/shell.js +73 -0
- package/dist/lib/template-downloader.d.ts +6 -0
- package/dist/{utils → lib}/template-downloader.js +21 -16
- package/dist/{utils → lib}/transpile-ts.js +5 -5
- package/dist/lib/virtual-routes.test.d.ts +1 -0
- package/dist/virtual-routes/routes/index.jsx +2 -15
- package/dist/virtual-routes/virtual-root.jsx +5 -6
- package/oclif.manifest.json +1 -1
- package/package.json +11 -10
- package/dist/utils/template-downloader.d.ts +0 -11
- /package/dist/{utils/check-lockfile.test.d.ts → commands/hydrogen/shortcut.test.d.ts} +0 -0
- /package/dist/{utils → lib}/check-lockfile.d.ts +0 -0
- /package/dist/{utils/check-version.test.d.ts → lib/check-lockfile.test.d.ts} +0 -0
- /package/dist/{utils → lib}/check-version.d.ts +0 -0
- /package/dist/{utils → lib}/check-version.js +0 -0
- /package/dist/{utils/flags.test.d.ts → lib/check-version.test.d.ts} +0 -0
- /package/dist/{utils → lib}/config.d.ts +0 -0
- /package/dist/{utils/virtual-routes.test.d.ts → lib/flags.test.d.ts} +0 -0
- /package/dist/{utils → lib}/flags.test.js +0 -0
- /package/dist/{utils → lib}/log.d.ts +0 -0
- /package/dist/{utils → lib}/log.js +0 -0
- /package/dist/{utils → lib}/mini-oxygen.d.ts +0 -0
- /package/dist/{utils → lib}/missing-routes.d.ts +0 -0
- /package/dist/{utils → lib}/missing-routes.js +0 -0
- /package/dist/{utils → lib}/transpile-ts.d.ts +0 -0
- /package/dist/{utils → lib}/virtual-routes.d.ts +0 -0
- /package/dist/{utils → lib}/virtual-routes.js +0 -0
- /package/dist/{utils → lib}/virtual-routes.test.js +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type MetaFunction,
|
|
3
2
|
type ActionFunction,
|
|
4
3
|
type LoaderArgs,
|
|
4
|
+
type ErrorBoundaryComponent,
|
|
5
5
|
redirect,
|
|
6
|
-
json,
|
|
7
6
|
} from '@shopify/remix-oxygen';
|
|
8
|
-
import {
|
|
9
|
-
|
|
7
|
+
import {
|
|
8
|
+
Form,
|
|
9
|
+
useCatch,
|
|
10
|
+
useRouteError,
|
|
11
|
+
isRouteErrorResponse,
|
|
12
|
+
} from '@remix-run/react';
|
|
10
13
|
|
|
11
14
|
export async function loader({context, params}: LoaderArgs) {
|
|
12
15
|
const customerAccessToken = await context.session.get('customerAccessToken');
|
|
@@ -14,15 +17,11 @@ export async function loader({context, params}: LoaderArgs) {
|
|
|
14
17
|
if (customerAccessToken) {
|
|
15
18
|
return redirect(params.lang ? `${params.lang}/account` : '/account');
|
|
16
19
|
}
|
|
17
|
-
}
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const badRequest = (data: ActionData) => json(data, {status: 400});
|
|
21
|
+
return new Response(null);
|
|
22
|
+
}
|
|
24
23
|
|
|
25
|
-
export const action: ActionFunction = async ({request
|
|
24
|
+
export const action: ActionFunction = async ({request}) => {
|
|
26
25
|
const formData = await request.formData();
|
|
27
26
|
|
|
28
27
|
const email = formData.get('email');
|
|
@@ -34,8 +33,8 @@ export const action: ActionFunction = async ({request, context, params}) => {
|
|
|
34
33
|
typeof email !== 'string' ||
|
|
35
34
|
typeof password !== 'string'
|
|
36
35
|
) {
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
throw new Response('Please provide both an email and a password.', {
|
|
37
|
+
status: 400,
|
|
39
38
|
});
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -72,3 +71,33 @@ export default function Login() {
|
|
|
72
71
|
</Form>
|
|
73
72
|
);
|
|
74
73
|
}
|
|
74
|
+
|
|
75
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
76
|
+
console.error(error);
|
|
77
|
+
|
|
78
|
+
return <div>There was an error.</div>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export function CatchBoundary() {
|
|
82
|
+
const caught = useCatch();
|
|
83
|
+
console.error(caught);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<div>
|
|
87
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
88
|
+
{caught.data?.message}
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function ErrorBoundary() {
|
|
94
|
+
const error = useRouteError();
|
|
95
|
+
|
|
96
|
+
if (isRouteErrorResponse(error)) {
|
|
97
|
+
console.error(error.status, error.statusText, error.data);
|
|
98
|
+
return <div>Route Error</div>;
|
|
99
|
+
} else {
|
|
100
|
+
console.error((error as Error).message);
|
|
101
|
+
return <div>Thrown Error</div>;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type MetaFunction,
|
|
3
2
|
type ActionFunction,
|
|
4
3
|
type LoaderArgs,
|
|
4
|
+
type ErrorBoundaryComponent,
|
|
5
5
|
redirect,
|
|
6
|
-
json,
|
|
7
6
|
} from '@shopify/remix-oxygen';
|
|
8
|
-
import {
|
|
9
|
-
|
|
7
|
+
import {
|
|
8
|
+
Form,
|
|
9
|
+
useCatch,
|
|
10
|
+
useRouteError,
|
|
11
|
+
isRouteErrorResponse,
|
|
12
|
+
} from '@remix-run/react';
|
|
10
13
|
|
|
11
14
|
export async function loader({context, params}: LoaderArgs) {
|
|
12
15
|
const customerAccessToken = await context.session.get('customerAccessToken');
|
|
@@ -14,15 +17,11 @@ export async function loader({context, params}: LoaderArgs) {
|
|
|
14
17
|
if (customerAccessToken) {
|
|
15
18
|
return redirect(params.lang ? `${params.lang}/account` : '/account');
|
|
16
19
|
}
|
|
17
|
-
}
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const badRequest = (data: ActionData) => json(data, {status: 400});
|
|
21
|
+
return new Response(null);
|
|
22
|
+
}
|
|
24
23
|
|
|
25
|
-
export const action: ActionFunction = async ({request
|
|
24
|
+
export const action: ActionFunction = async ({request}) => {
|
|
26
25
|
const formData = await request.formData();
|
|
27
26
|
|
|
28
27
|
const email = formData.get('email');
|
|
@@ -34,8 +33,8 @@ export const action: ActionFunction = async ({request, context, params}) => {
|
|
|
34
33
|
typeof email !== 'string' ||
|
|
35
34
|
typeof password !== 'string'
|
|
36
35
|
) {
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
throw new Response('Please provide both an email and a password.', {
|
|
37
|
+
status: 404,
|
|
39
38
|
});
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -72,3 +71,33 @@ export default function Register() {
|
|
|
72
71
|
</Form>
|
|
73
72
|
);
|
|
74
73
|
}
|
|
74
|
+
|
|
75
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
76
|
+
console.error(error);
|
|
77
|
+
|
|
78
|
+
return <div>There was an error.</div>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export function CatchBoundary() {
|
|
82
|
+
const caught = useCatch();
|
|
83
|
+
console.error(caught);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<div>
|
|
87
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
88
|
+
{caught.data?.message}
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function ErrorBoundary() {
|
|
94
|
+
const error = useRouteError();
|
|
95
|
+
|
|
96
|
+
if (isRouteErrorResponse(error)) {
|
|
97
|
+
console.error(error.status, error.statusText, error.data);
|
|
98
|
+
return <div>Route Error</div>;
|
|
99
|
+
} else {
|
|
100
|
+
console.error((error as Error).message);
|
|
101
|
+
return <div>Thrown Error</div>;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Await,
|
|
3
|
+
useMatches,
|
|
4
|
+
useCatch,
|
|
5
|
+
useRouteError,
|
|
6
|
+
isRouteErrorResponse,
|
|
7
|
+
} from '@remix-run/react';
|
|
2
8
|
import {Suspense} from 'react';
|
|
3
9
|
import {flattenConnection} from '@shopify/hydrogen';
|
|
4
10
|
import type {Cart as CartType} from '@shopify/hydrogen/storefront-api-types';
|
|
11
|
+
import {type ErrorBoundaryComponent} from '@shopify/remix-oxygen';
|
|
5
12
|
|
|
6
13
|
export async function action() {
|
|
7
14
|
// @TODO implement cart action
|
|
@@ -11,7 +18,10 @@ export default function CartRoute() {
|
|
|
11
18
|
const [root] = useMatches();
|
|
12
19
|
return (
|
|
13
20
|
<Suspense fallback="loading">
|
|
14
|
-
<Await
|
|
21
|
+
<Await
|
|
22
|
+
resolve={root.data?.cart as CartType}
|
|
23
|
+
errorElement={<div>An error occurred</div>}
|
|
24
|
+
>
|
|
15
25
|
{(cart) => {
|
|
16
26
|
const linesCount = Boolean(cart?.lines?.edges?.length || 0);
|
|
17
27
|
if (!linesCount) {
|
|
@@ -39,3 +49,33 @@ export default function CartRoute() {
|
|
|
39
49
|
</Suspense>
|
|
40
50
|
);
|
|
41
51
|
}
|
|
52
|
+
|
|
53
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
54
|
+
console.error(error);
|
|
55
|
+
|
|
56
|
+
return <div>There was an error.</div>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export function CatchBoundary() {
|
|
60
|
+
const caught = useCatch();
|
|
61
|
+
console.error(caught);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div>
|
|
65
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
66
|
+
{caught.data?.message}
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function ErrorBoundary() {
|
|
72
|
+
const error = useRouteError();
|
|
73
|
+
|
|
74
|
+
if (isRouteErrorResponse(error)) {
|
|
75
|
+
console.error(error.status, error.statusText, error.data);
|
|
76
|
+
return <div>Route Error</div>;
|
|
77
|
+
} else {
|
|
78
|
+
console.error((error as Error).message);
|
|
79
|
+
return <div>Thrown Error</div>;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
json,
|
|
3
|
+
type LoaderArgs,
|
|
4
|
+
type ErrorBoundaryComponent,
|
|
5
|
+
} from '@shopify/remix-oxygen';
|
|
6
|
+
import {
|
|
7
|
+
useLoaderData,
|
|
8
|
+
Link,
|
|
9
|
+
useCatch,
|
|
10
|
+
useRouteError,
|
|
11
|
+
isRouteErrorResponse,
|
|
12
|
+
} from '@remix-run/react';
|
|
3
13
|
import type {Collection as CollectionType} from '@shopify/hydrogen/storefront-api-types';
|
|
4
|
-
import {Link} from '@remix-run/react';
|
|
5
14
|
|
|
6
|
-
export async function loader({params,
|
|
15
|
+
export async function loader({params, context}: LoaderArgs) {
|
|
7
16
|
const {collectionHandle} = params;
|
|
8
17
|
|
|
9
18
|
const {collection} = await context.storefront.query<{
|
|
@@ -38,8 +47,38 @@ export default function Collection() {
|
|
|
38
47
|
);
|
|
39
48
|
}
|
|
40
49
|
|
|
50
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
51
|
+
console.error(error);
|
|
52
|
+
|
|
53
|
+
return <div>There was an error.</div>;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export function CatchBoundary() {
|
|
57
|
+
const caught = useCatch();
|
|
58
|
+
console.error(caught);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
63
|
+
{caught.data?.message}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function ErrorBoundary() {
|
|
69
|
+
const error = useRouteError();
|
|
70
|
+
|
|
71
|
+
if (isRouteErrorResponse(error)) {
|
|
72
|
+
console.error(error.status, error.statusText, error.data);
|
|
73
|
+
return <div>Route Error</div>;
|
|
74
|
+
} else {
|
|
75
|
+
console.error((error as Error).message);
|
|
76
|
+
return <div>Thrown Error</div>;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
41
80
|
const COLLECTION_QUERY = `#graphql
|
|
42
|
-
query
|
|
81
|
+
query collection_details(
|
|
43
82
|
$handle: String!
|
|
44
83
|
$country: CountryCode
|
|
45
84
|
$language: LanguageCode
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {type ErrorBoundaryComponent} from '@shopify/remix-oxygen';
|
|
2
|
+
import {useCatch, useRouteError, isRouteErrorResponse} from '@remix-run/react';
|
|
3
|
+
|
|
1
4
|
export default function Index() {
|
|
2
5
|
return (
|
|
3
6
|
<p>
|
|
@@ -5,3 +8,33 @@ export default function Index() {
|
|
|
5
8
|
</p>
|
|
6
9
|
);
|
|
7
10
|
}
|
|
11
|
+
|
|
12
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
13
|
+
console.error(error);
|
|
14
|
+
|
|
15
|
+
return <div>There was an error.</div>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function CatchBoundary() {
|
|
19
|
+
const caught = useCatch();
|
|
20
|
+
console.error(caught);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div>
|
|
24
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
25
|
+
{caught.data?.message}
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function ErrorBoundary() {
|
|
31
|
+
const error = useRouteError();
|
|
32
|
+
|
|
33
|
+
if (isRouteErrorResponse(error)) {
|
|
34
|
+
console.error(error.status, error.statusText, error.data);
|
|
35
|
+
return <div>Route Error</div>;
|
|
36
|
+
} else {
|
|
37
|
+
console.error((error as Error).message);
|
|
38
|
+
return <div>Thrown Error</div>;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -2,15 +2,22 @@ import {
|
|
|
2
2
|
json,
|
|
3
3
|
type MetaFunction,
|
|
4
4
|
type LoaderArgs,
|
|
5
|
-
|
|
5
|
+
type ErrorBoundaryComponent,
|
|
6
6
|
} from '@shopify/remix-oxygen';
|
|
7
|
-
import {
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
useLoaderData,
|
|
9
|
+
type V2_MetaFunction,
|
|
10
|
+
useCatch,
|
|
11
|
+
useRouteError,
|
|
12
|
+
isRouteErrorResponse,
|
|
13
|
+
} from '@remix-run/react';
|
|
9
14
|
import type {Page as PageType} from '@shopify/hydrogen/storefront-api-types';
|
|
10
15
|
import type {SeoHandleFunction} from '@shopify/hydrogen';
|
|
11
16
|
|
|
12
17
|
export async function loader({params, context}: LoaderArgs) {
|
|
13
|
-
|
|
18
|
+
if (!params.pageHandle) {
|
|
19
|
+
throw new Error('Missing page handle');
|
|
20
|
+
}
|
|
14
21
|
|
|
15
22
|
const {page} = await context.storefront.query<{page: PageType}>(PAGE_QUERY, {
|
|
16
23
|
variables: {
|
|
@@ -36,13 +43,14 @@ export const handle = {
|
|
|
36
43
|
seo,
|
|
37
44
|
};
|
|
38
45
|
|
|
39
|
-
export const
|
|
46
|
+
export const metaV1: MetaFunction = ({data}) => {
|
|
40
47
|
const {title, description} = data?.page.seo ?? {};
|
|
48
|
+
return {title, description};
|
|
49
|
+
};
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
};
|
|
51
|
+
export const meta: V2_MetaFunction = ({data}) => {
|
|
52
|
+
const {title, description} = data?.page.seo ?? {};
|
|
53
|
+
return [{title}, {name: 'description', content: description}];
|
|
46
54
|
};
|
|
47
55
|
|
|
48
56
|
export default function Page() {
|
|
@@ -58,8 +66,38 @@ export default function Page() {
|
|
|
58
66
|
);
|
|
59
67
|
}
|
|
60
68
|
|
|
69
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
70
|
+
console.error(error);
|
|
71
|
+
|
|
72
|
+
return <div>There was an error.</div>;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export function CatchBoundary() {
|
|
76
|
+
const caught = useCatch();
|
|
77
|
+
console.error(caught);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div>
|
|
81
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
82
|
+
{caught.data?.message}
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function ErrorBoundary() {
|
|
88
|
+
const error = useRouteError();
|
|
89
|
+
|
|
90
|
+
if (isRouteErrorResponse(error)) {
|
|
91
|
+
console.error(error.status, error.statusText, error.data);
|
|
92
|
+
return <div>Route Error</div>;
|
|
93
|
+
} else {
|
|
94
|
+
console.error((error as Error).message);
|
|
95
|
+
return <div>Thrown Error</div>;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
61
99
|
const PAGE_QUERY = `#graphql
|
|
62
|
-
query
|
|
100
|
+
query page_details($language: LanguageCode, $handle: String!)
|
|
63
101
|
@inContext(language: $language) {
|
|
64
102
|
page(handle: $handle) {
|
|
65
103
|
id
|
|
@@ -1,21 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
json,
|
|
3
|
+
type MetaFunction,
|
|
4
|
+
type LoaderArgs,
|
|
5
|
+
type ErrorBoundaryComponent,
|
|
6
|
+
} from '@shopify/remix-oxygen';
|
|
7
|
+
import {
|
|
8
|
+
useLoaderData,
|
|
9
|
+
type V2_MetaFunction,
|
|
10
|
+
useCatch,
|
|
11
|
+
useRouteError,
|
|
12
|
+
isRouteErrorResponse,
|
|
13
|
+
} from '@remix-run/react';
|
|
14
|
+
import {Shop} from '@shopify/hydrogen/storefront-api-types';
|
|
3
15
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export async function loader({request, params, context}: LoaderArgs) {
|
|
16
|
+
export async function loader({params, context}: LoaderArgs) {
|
|
7
17
|
const handle = params.policyHandle;
|
|
8
18
|
|
|
9
19
|
if (!handle) {
|
|
10
|
-
throw new Response(
|
|
20
|
+
throw new Response('No handle was passed in', {status: 404});
|
|
11
21
|
}
|
|
12
22
|
|
|
13
23
|
const policyName = handle.replace(/-([a-z])/g, (_: unknown, m1: string) =>
|
|
14
24
|
m1.toUpperCase(),
|
|
15
|
-
);
|
|
25
|
+
) as SelectedPolicies;
|
|
16
26
|
|
|
17
27
|
const data = await context.storefront.query<{
|
|
18
|
-
shop:
|
|
28
|
+
shop: Pick<Shop, SelectedPolicies>;
|
|
19
29
|
}>(POLICY_CONTENT_QUERY, {
|
|
20
30
|
variables: {
|
|
21
31
|
privacyPolicy: false,
|
|
@@ -30,16 +40,20 @@ export async function loader({request, params, context}: LoaderArgs) {
|
|
|
30
40
|
const policy = data.shop?.[policyName];
|
|
31
41
|
|
|
32
42
|
if (!policy) {
|
|
33
|
-
throw new Response(
|
|
43
|
+
throw new Response('Could not find the policy', {status: 404});
|
|
34
44
|
}
|
|
35
45
|
|
|
36
46
|
return json({policy});
|
|
37
47
|
}
|
|
38
48
|
|
|
39
|
-
export const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
export const metaV1: MetaFunction<typeof loader> = ({data}) => {
|
|
50
|
+
const title = data?.policy?.title ?? 'Policies';
|
|
51
|
+
return {title};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const meta: V2_MetaFunction<typeof loader> = ({data}) => {
|
|
55
|
+
const title = data?.policy?.title ?? 'Policies';
|
|
56
|
+
return [{title}];
|
|
43
57
|
};
|
|
44
58
|
|
|
45
59
|
export default function Policies() {
|
|
@@ -53,6 +67,36 @@ export default function Policies() {
|
|
|
53
67
|
);
|
|
54
68
|
}
|
|
55
69
|
|
|
70
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
71
|
+
console.error(error);
|
|
72
|
+
|
|
73
|
+
return <div>There was an error.</div>;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export function CatchBoundary() {
|
|
77
|
+
const caught = useCatch();
|
|
78
|
+
console.error(caught);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<div>
|
|
82
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
83
|
+
{caught.data?.message}
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function ErrorBoundary() {
|
|
89
|
+
const error = useRouteError();
|
|
90
|
+
|
|
91
|
+
if (isRouteErrorResponse(error)) {
|
|
92
|
+
console.error(error.status, error.statusText, error.data);
|
|
93
|
+
return <div>Route Error</div>;
|
|
94
|
+
} else {
|
|
95
|
+
console.error((error as Error).message);
|
|
96
|
+
return <div>Thrown Error</div>;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
56
100
|
const POLICY_CONTENT_QUERY = `#graphql
|
|
57
101
|
fragment Policy on ShopPolicy {
|
|
58
102
|
body
|
|
@@ -62,7 +106,7 @@ const POLICY_CONTENT_QUERY = `#graphql
|
|
|
62
106
|
url
|
|
63
107
|
}
|
|
64
108
|
|
|
65
|
-
query
|
|
109
|
+
query policy_query(
|
|
66
110
|
$language: LanguageCode
|
|
67
111
|
$privacyPolicy: Boolean!
|
|
68
112
|
$shippingPolicy: Boolean!
|
|
@@ -85,3 +129,12 @@ const POLICY_CONTENT_QUERY = `#graphql
|
|
|
85
129
|
}
|
|
86
130
|
}
|
|
87
131
|
`;
|
|
132
|
+
|
|
133
|
+
const policies = [
|
|
134
|
+
'privacyPolicy',
|
|
135
|
+
'shippingPolicy',
|
|
136
|
+
'refundPolicy',
|
|
137
|
+
'termsOfService',
|
|
138
|
+
] as const;
|
|
139
|
+
|
|
140
|
+
type SelectedPolicies = (typeof policies)[number];
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
json,
|
|
3
|
+
type LoaderArgs,
|
|
4
|
+
type ErrorBoundaryComponent,
|
|
5
|
+
} from '@shopify/remix-oxygen';
|
|
6
|
+
import {
|
|
7
|
+
useLoaderData,
|
|
8
|
+
Link,
|
|
9
|
+
useCatch,
|
|
10
|
+
useRouteError,
|
|
11
|
+
isRouteErrorResponse,
|
|
12
|
+
} from '@remix-run/react';
|
|
13
|
+
import type {Shop} from '@shopify/hydrogen/storefront-api-types';
|
|
4
14
|
|
|
5
15
|
export async function loader({context: {storefront}}: LoaderArgs) {
|
|
6
16
|
const data = await storefront.query<{
|
|
7
|
-
shop:
|
|
17
|
+
shop: Pick<Shop, SelectedPolicies>;
|
|
8
18
|
}>(POLICIES_QUERY);
|
|
9
19
|
|
|
10
20
|
const policies = Object.values(data.shop || {});
|
|
@@ -36,6 +46,36 @@ export default function Policies() {
|
|
|
36
46
|
);
|
|
37
47
|
}
|
|
38
48
|
|
|
49
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
50
|
+
console.error(error);
|
|
51
|
+
|
|
52
|
+
return <div>There was an error.</div>;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function CatchBoundary() {
|
|
56
|
+
const caught = useCatch();
|
|
57
|
+
console.error(caught);
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div>
|
|
61
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
62
|
+
{caught.data?.message}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function ErrorBoundary() {
|
|
68
|
+
const error = useRouteError();
|
|
69
|
+
|
|
70
|
+
if (isRouteErrorResponse(error)) {
|
|
71
|
+
console.error(error.status, error.statusText, error.data);
|
|
72
|
+
return <div>Route Error</div>;
|
|
73
|
+
} else {
|
|
74
|
+
console.error((error as Error).message);
|
|
75
|
+
return <div>Thrown Error</div>;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
39
79
|
const POLICIES_QUERY = `#graphql
|
|
40
80
|
fragment Policy on ShopPolicy {
|
|
41
81
|
id
|
|
@@ -65,3 +105,13 @@ const POLICIES_QUERY = `#graphql
|
|
|
65
105
|
}
|
|
66
106
|
}
|
|
67
107
|
`;
|
|
108
|
+
|
|
109
|
+
const policies = [
|
|
110
|
+
'privacyPolicy',
|
|
111
|
+
'shippingPolicy',
|
|
112
|
+
'refundPolicy',
|
|
113
|
+
'termsOfService',
|
|
114
|
+
'subscriptionPolicy',
|
|
115
|
+
] as const;
|
|
116
|
+
|
|
117
|
+
type SelectedPolicies = (typeof policies)[number];
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import {
|
|
2
|
+
defer,
|
|
3
|
+
type LoaderArgs,
|
|
4
|
+
type ErrorBoundaryComponent,
|
|
5
|
+
} from '@shopify/remix-oxygen';
|
|
6
|
+
import {
|
|
7
|
+
useLoaderData,
|
|
8
|
+
useCatch,
|
|
9
|
+
useRouteError,
|
|
10
|
+
isRouteErrorResponse,
|
|
11
|
+
} from '@remix-run/react';
|
|
12
|
+
import type {Product as ProductType} from '@shopify/hydrogen/storefront-api-types';
|
|
7
13
|
|
|
8
14
|
export async function loader({params, context}: LoaderArgs) {
|
|
9
15
|
const {productHandle} = params;
|
|
10
16
|
|
|
11
17
|
const {product} = await context.storefront.query<{
|
|
12
|
-
product: ProductType
|
|
18
|
+
product: Pick<ProductType, 'id' | 'title' | 'descriptionHtml' | 'vendor'>;
|
|
13
19
|
}>(PRODUCT_QUERY, {
|
|
14
20
|
variables: {
|
|
15
21
|
handle: productHandle,
|
|
@@ -40,9 +46,38 @@ export default function Product() {
|
|
|
40
46
|
);
|
|
41
47
|
}
|
|
42
48
|
|
|
43
|
-
const
|
|
49
|
+
export const ErrorBoundaryV1: ErrorBoundaryComponent = ({error}) => {
|
|
50
|
+
console.error(error);
|
|
51
|
+
|
|
52
|
+
return <div>There was an error.</div>;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function CatchBoundary() {
|
|
56
|
+
const caught = useCatch();
|
|
57
|
+
console.error(caught);
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div>
|
|
61
|
+
There was an error. Status: {caught.status}. Message:{' '}
|
|
62
|
+
{caught.data?.message}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function ErrorBoundary() {
|
|
68
|
+
const error = useRouteError();
|
|
69
|
+
|
|
70
|
+
if (isRouteErrorResponse(error)) {
|
|
71
|
+
console.error(error.status, error.statusText, error.data);
|
|
72
|
+
return <div>Route Error</div>;
|
|
73
|
+
} else {
|
|
74
|
+
console.error((error as Error).message);
|
|
75
|
+
return <div>Thrown Error</div>;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
44
78
|
|
|
45
|
-
|
|
79
|
+
const PRODUCT_QUERY = `#graphql
|
|
80
|
+
query product_query(
|
|
46
81
|
$country: CountryCode
|
|
47
82
|
$language: LanguageCode
|
|
48
83
|
$handle: String!
|
package/dist/hooks/init.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { spawnSync } from 'child_process';
|
|
2
|
-
import {
|
|
2
|
+
import { outputDebug } from '@shopify/cli-kit/node/output';
|
|
3
3
|
|
|
4
4
|
const EXPERIMENTAL_VM_MODULES_FLAG = "--experimental-vm-modules";
|
|
5
5
|
const hook = async function(options) {
|
|
6
6
|
if (options.id && ["hydrogen:dev", "hydrogen:preview"].includes(options.id) && !process.execArgv.includes(EXPERIMENTAL_VM_MODULES_FLAG) && !(process.env.NODE_OPTIONS ?? "").includes(EXPERIMENTAL_VM_MODULES_FLAG)) {
|
|
7
|
-
|
|
7
|
+
outputDebug(
|
|
8
8
|
`Restarting CLI process with ${EXPERIMENTAL_VM_MODULES_FLAG} flag.`
|
|
9
9
|
);
|
|
10
10
|
const [command, ...args] = process.argv;
|