@shopify/cli-hydrogen 6.0.2 → 7.0.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.
Files changed (108) hide show
  1. package/dist/commands/hydrogen/build.js +40 -78
  2. package/dist/commands/hydrogen/codegen.js +8 -3
  3. package/dist/commands/hydrogen/deploy.js +173 -37
  4. package/dist/commands/hydrogen/deploy.test.js +192 -20
  5. package/dist/commands/hydrogen/dev.js +56 -31
  6. package/dist/commands/hydrogen/init.js +1 -1
  7. package/dist/commands/hydrogen/init.test.js +155 -53
  8. package/dist/commands/hydrogen/link.js +5 -21
  9. package/dist/commands/hydrogen/link.test.js +10 -10
  10. package/dist/commands/hydrogen/preview.js +22 -11
  11. package/dist/commands/hydrogen/setup.js +0 -4
  12. package/dist/commands/hydrogen/setup.test.js +0 -1
  13. package/dist/commands/hydrogen/shortcut.js +1 -0
  14. package/dist/commands/hydrogen/upgrade.js +720 -0
  15. package/dist/commands/hydrogen/upgrade.test.js +786 -0
  16. package/dist/generator-templates/starter/.graphqlrc.yml +12 -1
  17. package/dist/generator-templates/starter/CHANGELOG.md +126 -0
  18. package/dist/generator-templates/starter/README.md +23 -0
  19. package/dist/generator-templates/starter/app/components/Cart.tsx +1 -1
  20. package/dist/generator-templates/starter/app/components/Footer.tsx +3 -1
  21. package/dist/generator-templates/starter/app/components/Header.tsx +5 -1
  22. package/dist/generator-templates/starter/app/components/Layout.tsx +14 -11
  23. package/dist/generator-templates/starter/app/components/Search.tsx +1 -1
  24. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerAddressMutations.ts +61 -0
  25. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +39 -0
  26. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerOrderQuery.ts +87 -0
  27. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerOrdersQuery.ts +58 -0
  28. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerUpdateMutation.ts +24 -0
  29. package/dist/generator-templates/starter/app/lib/fragments.ts +102 -0
  30. package/dist/generator-templates/starter/app/lib/session.ts +67 -0
  31. package/dist/generator-templates/starter/app/root.tsx +11 -45
  32. package/dist/generator-templates/starter/app/routes/[robots.txt].tsx +0 -27
  33. package/dist/generator-templates/starter/app/routes/account.$.tsx +8 -4
  34. package/dist/generator-templates/starter/app/routes/account._index.tsx +5 -0
  35. package/dist/generator-templates/starter/app/routes/account.addresses.tsx +215 -206
  36. package/dist/generator-templates/starter/app/routes/account.orders.$id.tsx +56 -163
  37. package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +32 -109
  38. package/dist/generator-templates/starter/app/routes/account.profile.tsx +40 -180
  39. package/dist/generator-templates/starter/app/routes/account.tsx +20 -135
  40. package/dist/generator-templates/starter/app/routes/account_.authorize.tsx +5 -0
  41. package/dist/generator-templates/starter/app/routes/account_.login.tsx +3 -140
  42. package/dist/generator-templates/starter/app/routes/account_.logout.tsx +5 -24
  43. package/dist/generator-templates/starter/app/routes/cart.tsx +7 -5
  44. package/dist/generator-templates/starter/app/routes/collections.$handle.tsx +1 -1
  45. package/dist/generator-templates/starter/app/routes/products.$handle.tsx +2 -2
  46. package/dist/generator-templates/starter/app/routes/search.tsx +1 -1
  47. package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +506 -0
  48. package/dist/generator-templates/starter/package.json +11 -10
  49. package/dist/generator-templates/starter/remix.config.js +4 -0
  50. package/dist/generator-templates/starter/remix.env.d.ts +6 -11
  51. package/dist/generator-templates/starter/server.ts +24 -167
  52. package/dist/generator-templates/starter/storefrontapi.generated.d.ts +104 -881
  53. package/dist/hooks/init.js +4 -4
  54. package/dist/lib/auth.js +5 -10
  55. package/dist/lib/build.js +6 -1
  56. package/dist/lib/bundle/analyzer.js +36 -26
  57. package/dist/lib/check-lockfile.js +1 -0
  58. package/dist/lib/codegen.js +59 -18
  59. package/dist/lib/defer.js +12 -0
  60. package/dist/lib/file.js +52 -3
  61. package/dist/lib/flags.js +27 -9
  62. package/dist/lib/get-oxygen-deployment-data.test.js +4 -2
  63. package/dist/lib/graphql/admin/client.test.js +2 -2
  64. package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
  65. package/dist/lib/log.js +32 -14
  66. package/dist/lib/mini-oxygen/assets.js +118 -0
  67. package/dist/lib/mini-oxygen/common.js +2 -1
  68. package/dist/lib/mini-oxygen/index.js +7 -5
  69. package/dist/lib/mini-oxygen/mini-oxygen.test.js +214 -0
  70. package/dist/lib/mini-oxygen/node.js +19 -5
  71. package/dist/lib/mini-oxygen/workerd-inspector-logs.js +227 -0
  72. package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +200 -0
  73. package/dist/lib/mini-oxygen/workerd-inspector.js +62 -235
  74. package/dist/lib/mini-oxygen/workerd.js +74 -50
  75. package/dist/lib/missing-routes.js +6 -3
  76. package/dist/lib/onboarding/common.js +40 -9
  77. package/dist/lib/onboarding/local.js +19 -11
  78. package/dist/lib/onboarding/remote.js +48 -28
  79. package/dist/lib/render-errors.js +2 -0
  80. package/dist/lib/request-events.js +65 -31
  81. package/dist/lib/setups/css/assets.js +1 -46
  82. package/dist/lib/setups/css/css-modules.js +3 -2
  83. package/dist/lib/setups/css/postcss.js +4 -2
  84. package/dist/lib/setups/css/tailwind.js +4 -2
  85. package/dist/lib/setups/css/vanilla-extract.js +3 -2
  86. package/dist/lib/setups/i18n/replacers.test.js +56 -38
  87. package/dist/lib/shell.js +1 -1
  88. package/dist/lib/template-diff.js +89 -0
  89. package/dist/lib/template-downloader.js +3 -2
  90. package/dist/lib/transpile/project.js +1 -1
  91. package/dist/virtual-routes/assets/debug-network.css +592 -0
  92. package/dist/virtual-routes/assets/favicon-dark.svg +20 -0
  93. package/dist/virtual-routes/components/FlameChartWrapper.jsx +8 -10
  94. package/dist/virtual-routes/components/IconClose.jsx +38 -0
  95. package/dist/virtual-routes/components/IconDiscard.jsx +44 -0
  96. package/dist/virtual-routes/components/RequestDetails.jsx +179 -0
  97. package/dist/virtual-routes/components/RequestTable.jsx +92 -0
  98. package/dist/virtual-routes/components/RequestWaterfall.jsx +151 -0
  99. package/dist/virtual-routes/lib/useDebugNetworkServer.jsx +176 -0
  100. package/dist/virtual-routes/routes/subrequest-profiler.jsx +243 -0
  101. package/oclif.manifest.json +134 -59
  102. package/package.json +18 -26
  103. package/dist/generator-templates/starter/app/routes/account_.activate.$id.$activationToken.tsx +0 -161
  104. package/dist/generator-templates/starter/app/routes/account_.recover.tsx +0 -129
  105. package/dist/generator-templates/starter/app/routes/account_.register.tsx +0 -207
  106. package/dist/generator-templates/starter/app/routes/account_.reset.$id.$resetToken.tsx +0 -136
  107. package/dist/virtual-routes/routes/debug-network.jsx +0 -289
  108. /package/dist/generator-templates/starter/app/{utils.ts → lib/variants.ts} +0 -0
package/package.json CHANGED
@@ -4,18 +4,19 @@
4
4
  "access": "public",
5
5
  "@shopify:registry": "https://registry.npmjs.org"
6
6
  },
7
- "version": "6.0.2",
7
+ "version": "7.0.0",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "scripts": {
11
11
  "build": "tsup && node scripts/build-check.mjs",
12
- "dev": "tsup --watch",
12
+ "dev": "tsup --watch ./src",
13
13
  "typecheck": "tsc --noEmit",
14
14
  "generate:manifest": "node scripts/generate-manifest.mjs",
15
15
  "test": "cross-env SHOPIFY_UNIT_TEST=1 vitest run --test-timeout=20000",
16
16
  "test:watch": "cross-env SHOPIFY_UNIT_TEST=1 vitest --test-timeout=20000"
17
17
  },
18
18
  "devDependencies": {
19
+ "@remix-run/dev": "^2.5.1",
19
20
  "@types/diff": "^5.0.2",
20
21
  "@types/fs-extra": "^11.0.1",
21
22
  "@types/gunzip-maybe": "^1.4.0",
@@ -23,33 +24,36 @@
23
24
  "@types/recursive-readdir": "^2.2.1",
24
25
  "@types/stack-trace": "^0.0.30",
25
26
  "@types/tar-fs": "^2.0.1",
27
+ "@vitest/coverage-v8": "^1.0.4",
26
28
  "devtools-protocol": "^0.0.1177611",
27
- "get-port": "^7.0.0",
28
- "@vitest/coverage-v8": "^0.33.0",
29
29
  "fast-glob": "^3.2.12",
30
- "flame-chart-js": "2.3.1",
31
- "type-fest": "^3.6.0",
32
- "vitest": "^0.33.0"
30
+ "flame-chart-js": "2.3.2",
31
+ "get-port": "^7.0.0",
32
+ "type-fest": "^4.5.0",
33
+ "vitest": "^1.0.4"
33
34
  },
34
35
  "dependencies": {
35
36
  "@ast-grep/napi": "0.11.0",
36
37
  "@graphql-codegen/cli": "5.0.0",
37
38
  "@oclif/core": "2.11.7",
38
- "@shopify/cli-kit": "3.50.0",
39
- "@shopify/hydrogen-codegen": "^0.1.0",
40
- "@shopify/mini-oxygen": "^2.2.3",
41
- "@shopify/oxygen-cli": "^2.3.2",
39
+ "@shopify/cli-kit": "3.52.0",
40
+ "@shopify/hydrogen-codegen": "^0.2.0",
41
+ "@shopify/mini-oxygen": "^2.2.5",
42
+ "@shopify/oxygen-cli": "^4.0.0",
42
43
  "ansi-escapes": "^6.2.0",
44
+ "cli-truncate": "^4.0.0",
43
45
  "diff": "^5.1.0",
44
46
  "fs-extra": "^11.1.0",
45
47
  "get-port": "^7.0.0",
48
+ "graphql-config": "5.0.3",
46
49
  "gunzip-maybe": "^1.4.2",
47
- "miniflare": "3.20230918.0",
50
+ "miniflare": "3.20231218.2",
48
51
  "prettier": "^2.8.4",
49
52
  "semver": "^7.5.3",
50
53
  "source-map": "^0.7.4",
51
54
  "stack-trace": "^1.0.0-pre2",
52
55
  "tar-fs": "^2.1.1",
56
+ "tempy": "^3.0.0",
53
57
  "ts-morph": "20.0.0",
54
58
  "use-resize-observer": "^9.1.0",
55
59
  "ws": "^8.13.0"
@@ -58,23 +62,11 @@
58
62
  "@parcel/watcher": "^2.3.0"
59
63
  },
60
64
  "peerDependencies": {
61
- "@remix-run/dev": "^2.1.0",
62
- "@remix-run/react": "^2.1.0",
63
- "@shopify/hydrogen": "2023.10.2",
64
- "@shopify/remix-oxygen": "^2.0.0"
65
+ "@remix-run/dev": "^2.1.0"
65
66
  },
66
67
  "peerDependenciesMeta": {
67
68
  "@remix-run/dev": {
68
69
  "optional": true
69
- },
70
- "@remix-run/react": {
71
- "optional": true
72
- },
73
- "@shopify/hydrogen-react": {
74
- "optional": true
75
- },
76
- "@shopify/remix-oxygen": {
77
- "optional": true
78
70
  }
79
71
  },
80
72
  "bin": "dist/create-app.js",
@@ -87,7 +79,7 @@
87
79
  "oclif.manifest.json"
88
80
  ],
89
81
  "engines": {
90
- "node": ">=16.13"
82
+ "node": ">=18.0.0"
91
83
  },
92
84
  "oclif": {
93
85
  "commands": "dist/commands",
@@ -1,161 +0,0 @@
1
- import {
2
- json,
3
- redirect,
4
- type ActionFunctionArgs,
5
- type LoaderFunctionArgs,
6
- } from '@shopify/remix-oxygen';
7
- import {Form, useActionData, type MetaFunction} from '@remix-run/react';
8
-
9
- type ActionResponse = {
10
- error: string | null;
11
- };
12
-
13
- export const meta: MetaFunction = () => {
14
- return [{title: 'Activate Account'}];
15
- };
16
-
17
- export async function loader({context}: LoaderFunctionArgs) {
18
- if (await context.session.get('customerAccessToken')) {
19
- return redirect('/account');
20
- }
21
- return json({});
22
- }
23
-
24
- export async function action({request, context, params}: ActionFunctionArgs) {
25
- const {session, storefront} = context;
26
- const {id, activationToken} = params;
27
-
28
- if (request.method !== 'POST') {
29
- return json({error: 'Method not allowed'}, {status: 405});
30
- }
31
-
32
- try {
33
- if (!id || !activationToken) {
34
- throw new Error('Missing token. The link you followed might be wrong.');
35
- }
36
-
37
- const form = await request.formData();
38
- const password = form.has('password') ? String(form.get('password')) : null;
39
- const passwordConfirm = form.has('passwordConfirm')
40
- ? String(form.get('passwordConfirm'))
41
- : null;
42
-
43
- const validPasswords =
44
- password && passwordConfirm && password === passwordConfirm;
45
-
46
- if (!validPasswords) {
47
- throw new Error('Passwords do not match');
48
- }
49
-
50
- const {customerActivate} = await storefront.mutate(
51
- CUSTOMER_ACTIVATE_MUTATION,
52
- {
53
- variables: {
54
- id: `gid://shopify/Customer/${id}`,
55
- input: {
56
- password,
57
- activationToken,
58
- },
59
- },
60
- },
61
- );
62
-
63
- if (customerActivate?.customerUserErrors?.length) {
64
- throw new Error(customerActivate.customerUserErrors[0].message);
65
- }
66
-
67
- const {customerAccessToken} = customerActivate ?? {};
68
- if (!customerAccessToken) {
69
- throw new Error('Could not activate account.');
70
- }
71
- session.set('customerAccessToken', customerAccessToken);
72
-
73
- return redirect('/account', {
74
- headers: {
75
- 'Set-Cookie': await session.commit(),
76
- },
77
- });
78
- } catch (error: unknown) {
79
- if (error instanceof Error) {
80
- return json({error: error.message}, {status: 400});
81
- }
82
- return json({error}, {status: 400});
83
- }
84
- }
85
-
86
- export default function Activate() {
87
- const action = useActionData<ActionResponse>();
88
- const error = action?.error ?? null;
89
-
90
- return (
91
- <div className="account-activate">
92
- <h1>Activate Account.</h1>
93
- <p>Create your password to activate your account.</p>
94
- <Form method="POST">
95
- <fieldset>
96
- <label htmlFor="password">Password</label>
97
- <input
98
- id="password"
99
- name="password"
100
- type="password"
101
- autoComplete="current-password"
102
- placeholder="Password"
103
- aria-label="Password"
104
- minLength={8}
105
- required
106
- // eslint-disable-next-line jsx-a11y/no-autofocus
107
- autoFocus
108
- />
109
- <label htmlFor="passwordConfirm">Re-enter password</label>
110
- <input
111
- id="passwordConfirm"
112
- name="passwordConfirm"
113
- type="password"
114
- autoComplete="current-password"
115
- placeholder="Re-enter password"
116
- aria-label="Re-enter password"
117
- minLength={8}
118
- required
119
- />
120
- </fieldset>
121
- {error ? (
122
- <p>
123
- <mark>
124
- <small>{error}</small>
125
- </mark>
126
- </p>
127
- ) : (
128
- <br />
129
- )}
130
- <button
131
- className="bg-primary text-contrast rounded py-2 px-4 focus:shadow-outline block w-full"
132
- type="submit"
133
- >
134
- Save
135
- </button>
136
- </Form>
137
- </div>
138
- );
139
- }
140
-
141
- // NOTE: https://shopify.dev/docs/api/storefront/latest/mutations/customeractivate
142
- const CUSTOMER_ACTIVATE_MUTATION = `#graphql
143
- mutation customerActivate(
144
- $id: ID!,
145
- $input: CustomerActivateInput!,
146
- $country: CountryCode,
147
- $language: LanguageCode
148
- ) @inContext(country: $country, language: $language) {
149
- customerActivate(id: $id, input: $input) {
150
- customerAccessToken {
151
- accessToken
152
- expiresAt
153
- }
154
- customerUserErrors {
155
- code
156
- field
157
- message
158
- }
159
- }
160
- }
161
- ` as const;
@@ -1,129 +0,0 @@
1
- import {
2
- json,
3
- redirect,
4
- type LoaderFunctionArgs,
5
- type ActionFunctionArgs,
6
- } from '@shopify/remix-oxygen';
7
- import {Form, Link, useActionData} from '@remix-run/react';
8
-
9
- type ActionResponse = {
10
- error?: string;
11
- resetRequested?: boolean;
12
- };
13
-
14
- export async function loader({context}: LoaderFunctionArgs) {
15
- const customerAccessToken = await context.session.get('customerAccessToken');
16
- if (customerAccessToken) {
17
- return redirect('/account');
18
- }
19
-
20
- return json({});
21
- }
22
-
23
- export async function action({request, context}: ActionFunctionArgs) {
24
- const {storefront} = context;
25
- const form = await request.formData();
26
- const email = form.has('email') ? String(form.get('email')) : null;
27
-
28
- if (request.method !== 'POST') {
29
- return json({error: 'Method not allowed'}, {status: 405});
30
- }
31
-
32
- try {
33
- if (!email) {
34
- throw new Error('Please provide an email.');
35
- }
36
- await storefront.mutate(CUSTOMER_RECOVER_MUTATION, {
37
- variables: {email},
38
- });
39
-
40
- return json({resetRequested: true});
41
- } catch (error: unknown) {
42
- const resetRequested = false;
43
- if (error instanceof Error) {
44
- return json({error: error.message, resetRequested}, {status: 400});
45
- }
46
- return json({error, resetRequested}, {status: 400});
47
- }
48
- }
49
-
50
- export default function Recover() {
51
- const action = useActionData<ActionResponse>();
52
-
53
- return (
54
- <div className="account-recover">
55
- <div>
56
- {action?.resetRequested ? (
57
- <>
58
- <h1>Request Sent.</h1>
59
- <p>
60
- If that email address is in our system, you will receive an email
61
- with instructions about how to reset your password in a few
62
- minutes.
63
- </p>
64
- <br />
65
- <Link to="/account/login">Return to Login</Link>
66
- </>
67
- ) : (
68
- <>
69
- <h1>Forgot Password.</h1>
70
- <p>
71
- Enter the email address associated with your account to receive a
72
- link to reset your password.
73
- </p>
74
- <br />
75
- <Form method="POST">
76
- <fieldset>
77
- <label htmlFor="email">Email</label>
78
- <input
79
- aria-label="Email address"
80
- autoComplete="email"
81
- // eslint-disable-next-line jsx-a11y/no-autofocus
82
- autoFocus
83
- id="email"
84
- name="email"
85
- placeholder="Email address"
86
- required
87
- type="email"
88
- />
89
- </fieldset>
90
- {action?.error ? (
91
- <p>
92
- <mark>
93
- <small>{action.error}</small>
94
- </mark>
95
- </p>
96
- ) : (
97
- <br />
98
- )}
99
- <button type="submit">Request Reset Link</button>
100
- </Form>
101
- <div>
102
- <br />
103
- <p>
104
- <Link to="/account/login">Login →</Link>
105
- </p>
106
- </div>
107
- </>
108
- )}
109
- </div>
110
- </div>
111
- );
112
- }
113
-
114
- // NOTE: https://shopify.dev/docs/api/storefront/latest/mutations/customerrecover
115
- const CUSTOMER_RECOVER_MUTATION = `#graphql
116
- mutation customerRecover(
117
- $email: String!,
118
- $country: CountryCode,
119
- $language: LanguageCode
120
- ) @inContext(country: $country, language: $language) {
121
- customerRecover(email: $email) {
122
- customerUserErrors {
123
- code
124
- field
125
- message
126
- }
127
- }
128
- }
129
- ` as const;
@@ -1,207 +0,0 @@
1
- import {
2
- json,
3
- redirect,
4
- type ActionFunctionArgs,
5
- type LoaderFunctionArgs,
6
- } from '@shopify/remix-oxygen';
7
- import {Form, Link, useActionData} from '@remix-run/react';
8
- import type {CustomerCreateMutation} from 'storefrontapi.generated';
9
-
10
- type ActionResponse = {
11
- error: string | null;
12
- newCustomer:
13
- | NonNullable<CustomerCreateMutation['customerCreate']>['customer']
14
- | null;
15
- };
16
-
17
- export async function loader({context}: LoaderFunctionArgs) {
18
- const customerAccessToken = await context.session.get('customerAccessToken');
19
- if (customerAccessToken) {
20
- return redirect('/account');
21
- }
22
-
23
- return json({});
24
- }
25
-
26
- export async function action({request, context}: ActionFunctionArgs) {
27
- if (request.method !== 'POST') {
28
- return json({error: 'Method not allowed'}, {status: 405});
29
- }
30
-
31
- const {storefront, session} = context;
32
- const form = await request.formData();
33
- const email = String(form.has('email') ? form.get('email') : '');
34
- const password = form.has('password') ? String(form.get('password')) : null;
35
- const passwordConfirm = form.has('passwordConfirm')
36
- ? String(form.get('passwordConfirm'))
37
- : null;
38
-
39
- const validPasswords =
40
- password && passwordConfirm && password === passwordConfirm;
41
-
42
- const validInputs = Boolean(email && password);
43
- try {
44
- if (!validPasswords) {
45
- throw new Error('Passwords do not match');
46
- }
47
-
48
- if (!validInputs) {
49
- throw new Error('Please provide both an email and a password.');
50
- }
51
-
52
- const {customerCreate} = await storefront.mutate(CUSTOMER_CREATE_MUTATION, {
53
- variables: {
54
- input: {email, password},
55
- },
56
- });
57
-
58
- if (customerCreate?.customerUserErrors?.length) {
59
- throw new Error(customerCreate?.customerUserErrors[0].message);
60
- }
61
-
62
- const newCustomer = customerCreate?.customer;
63
- if (!newCustomer?.id) {
64
- throw new Error('Could not create customer');
65
- }
66
-
67
- // get an access token for the new customer
68
- const {customerAccessTokenCreate} = await storefront.mutate(
69
- REGISTER_LOGIN_MUTATION,
70
- {
71
- variables: {
72
- input: {
73
- email,
74
- password,
75
- },
76
- },
77
- },
78
- );
79
-
80
- if (!customerAccessTokenCreate?.customerAccessToken?.accessToken) {
81
- throw new Error('Missing access token');
82
- }
83
- session.set(
84
- 'customerAccessToken',
85
- customerAccessTokenCreate?.customerAccessToken,
86
- );
87
-
88
- return json(
89
- {error: null, newCustomer},
90
- {
91
- status: 302,
92
- headers: {
93
- 'Set-Cookie': await session.commit(),
94
- Location: '/account',
95
- },
96
- },
97
- );
98
- } catch (error: unknown) {
99
- if (error instanceof Error) {
100
- return json({error: error.message}, {status: 400});
101
- }
102
- return json({error}, {status: 400});
103
- }
104
- }
105
-
106
- export default function Register() {
107
- const data = useActionData<ActionResponse>();
108
- const error = data?.error || null;
109
- return (
110
- <div className="login">
111
- <h1>Register.</h1>
112
- <Form method="POST">
113
- <fieldset>
114
- <label htmlFor="email">Email address</label>
115
- <input
116
- id="email"
117
- name="email"
118
- type="email"
119
- autoComplete="email"
120
- required
121
- placeholder="Email address"
122
- aria-label="Email address"
123
- // eslint-disable-next-line jsx-a11y/no-autofocus
124
- autoFocus
125
- />
126
- <label htmlFor="password">Password</label>
127
- <input
128
- id="password"
129
- name="password"
130
- type="password"
131
- autoComplete="current-password"
132
- placeholder="Password"
133
- aria-label="Password"
134
- minLength={8}
135
- required
136
- />
137
- <label htmlFor="passwordConfirm">Re-enter password</label>
138
- <input
139
- id="passwordConfirm"
140
- name="passwordConfirm"
141
- type="password"
142
- autoComplete="current-password"
143
- placeholder="Re-enter password"
144
- aria-label="Re-enter password"
145
- minLength={8}
146
- required
147
- />
148
- </fieldset>
149
- {error ? (
150
- <p>
151
- <mark>
152
- <small>{error}</small>
153
- </mark>
154
- </p>
155
- ) : (
156
- <br />
157
- )}
158
- <button type="submit">Register</button>
159
- </Form>
160
- <br />
161
- <p>
162
- <Link to="/account/login">Login →</Link>
163
- </p>
164
- </div>
165
- );
166
- }
167
-
168
- // NOTE: https://shopify.dev/docs/api/storefront/latest/mutations/customerCreate
169
- const CUSTOMER_CREATE_MUTATION = `#graphql
170
- mutation customerCreate(
171
- $input: CustomerCreateInput!,
172
- $country: CountryCode,
173
- $language: LanguageCode
174
- ) @inContext(country: $country, language: $language) {
175
- customerCreate(input: $input) {
176
- customer {
177
- id
178
- }
179
- customerUserErrors {
180
- code
181
- field
182
- message
183
- }
184
- }
185
- }
186
- ` as const;
187
-
188
- // NOTE: https://shopify.dev/docs/api/storefront/latest/mutations/customeraccesstokencreate
189
- const REGISTER_LOGIN_MUTATION = `#graphql
190
- mutation registerLogin(
191
- $input: CustomerAccessTokenCreateInput!,
192
- $country: CountryCode,
193
- $language: LanguageCode
194
- ) @inContext(country: $country, language: $language) {
195
- customerAccessTokenCreate(input: $input) {
196
- customerUserErrors {
197
- code
198
- field
199
- message
200
- }
201
- customerAccessToken {
202
- accessToken
203
- expiresAt
204
- }
205
- }
206
- }
207
- ` as const;