@shopify/cli-hydrogen 8.1.0 → 8.2.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 (101) hide show
  1. package/dist/assets/hydrogen/starter/CHANGELOG.md +166 -0
  2. package/dist/assets/hydrogen/starter/app/components/AddToCartButton.tsx +37 -0
  3. package/dist/assets/hydrogen/starter/app/components/CartLineItem.tsx +150 -0
  4. package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +68 -0
  5. package/dist/assets/hydrogen/starter/app/components/CartSummary.tsx +101 -0
  6. package/dist/assets/hydrogen/starter/app/components/Header.tsx +3 -3
  7. package/dist/assets/hydrogen/starter/app/components/PageLayout.tsx +2 -2
  8. package/dist/assets/hydrogen/starter/app/components/ProductForm.tsx +80 -0
  9. package/dist/assets/hydrogen/starter/app/components/ProductImage.tsx +23 -0
  10. package/dist/assets/hydrogen/starter/app/components/ProductPrice.tsx +27 -0
  11. package/dist/assets/hydrogen/starter/app/lib/session.ts +5 -0
  12. package/dist/assets/hydrogen/starter/app/root.tsx +23 -36
  13. package/dist/assets/hydrogen/starter/app/routes/account.$.tsx +1 -5
  14. package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +12 -70
  15. package/dist/assets/hydrogen/starter/app/routes/account.orders.$id.tsx +7 -14
  16. package/dist/assets/hydrogen/starter/app/routes/account.orders._index.tsx +1 -8
  17. package/dist/assets/hydrogen/starter/app/routes/account.profile.tsx +5 -22
  18. package/dist/assets/hydrogen/starter/app/routes/account.tsx +0 -1
  19. package/dist/assets/hydrogen/starter/app/routes/cart.tsx +1 -3
  20. package/dist/assets/hydrogen/starter/app/routes/products.$handle.tsx +51 -232
  21. package/dist/assets/hydrogen/starter/package.json +10 -11
  22. package/dist/assets/hydrogen/starter/server.ts +4 -0
  23. package/dist/assets/hydrogen/tailwind/package.json +1 -6
  24. package/dist/assets/hydrogen/tailwind/tailwind.css +6 -3
  25. package/dist/assets/hydrogen/vanilla-extract/package.json +2 -3
  26. package/dist/assets/hydrogen/virtual-routes/components/{Layout.jsx → PageLayout.jsx} +2 -2
  27. package/dist/assets/hydrogen/virtual-routes/components/RequestDetails.jsx +1 -2
  28. package/dist/assets/hydrogen/virtual-routes/components/RequestTable.jsx +1 -2
  29. package/dist/assets/hydrogen/virtual-routes/routes/index.jsx +1 -2
  30. package/dist/assets/hydrogen/virtual-routes/virtual-root.jsx +8 -30
  31. package/dist/commands/hydrogen/build.js +33 -10
  32. package/dist/commands/hydrogen/customer-account/push.js +3 -6
  33. package/dist/commands/hydrogen/debug/cpu.js +3 -3
  34. package/dist/commands/hydrogen/deploy.js +14 -3
  35. package/dist/commands/hydrogen/dev.js +3 -6
  36. package/dist/commands/hydrogen/env/list.js +1 -2
  37. package/dist/commands/hydrogen/env/pull.js +2 -4
  38. package/dist/commands/hydrogen/env/push.js +6 -12
  39. package/dist/commands/hydrogen/init.d.ts +18 -15
  40. package/dist/commands/hydrogen/init.js +12 -24
  41. package/dist/commands/hydrogen/link.js +1 -2
  42. package/dist/commands/hydrogen/preview.js +4 -6
  43. package/dist/commands/hydrogen/setup/css.js +29 -12
  44. package/dist/commands/hydrogen/setup/vite.js +3 -6
  45. package/dist/commands/hydrogen/setup.js +8 -7
  46. package/dist/commands/hydrogen/upgrade.js +16 -32
  47. package/dist/hooks/init.js +50 -6
  48. package/dist/index.d.ts +46 -46
  49. package/dist/lib/auth.js +1 -2
  50. package/dist/lib/build.js +1 -2
  51. package/dist/lib/bundle/analyzer.js +39 -24
  52. package/dist/lib/bundle/vite-plugin.js +161 -0
  53. package/dist/lib/check-cli-version.js +61 -0
  54. package/dist/lib/check-lockfile.js +2 -2
  55. package/dist/lib/classic-compiler/build.js +3 -3
  56. package/dist/lib/classic-compiler/dev.js +5 -10
  57. package/dist/lib/codegen.js +8 -16
  58. package/dist/lib/defer.js +2 -4
  59. package/dist/lib/environment-variables.js +2 -4
  60. package/dist/lib/file.js +15 -7
  61. package/dist/lib/flags.js +10 -0
  62. package/dist/lib/get-oxygen-deployment-data.js +1 -2
  63. package/dist/lib/graphiql-url.js +1 -2
  64. package/dist/lib/import-utils.js +3 -2
  65. package/dist/lib/log.js +11 -22
  66. package/dist/lib/mini-oxygen/common.js +1 -2
  67. package/dist/lib/mini-oxygen/node.js +1 -2
  68. package/dist/lib/missing-routes.js +1 -2
  69. package/dist/lib/onboarding/common.js +60 -15
  70. package/dist/lib/onboarding/local.js +14 -13
  71. package/dist/lib/onboarding/remote.js +16 -9
  72. package/dist/lib/onboarding/setup-template.mocks.js +6 -3
  73. package/dist/lib/remix-config.js +2 -4
  74. package/dist/lib/remix-version-check.js +1 -2
  75. package/dist/lib/request-events.js +3 -6
  76. package/dist/lib/setups/css/assets.js +1 -1
  77. package/dist/lib/setups/css/index.js +17 -10
  78. package/dist/lib/setups/css/replacers.js +74 -76
  79. package/dist/lib/setups/css/tailwind.js +16 -20
  80. package/dist/lib/setups/css/vanilla-extract.js +8 -5
  81. package/dist/lib/setups/i18n/replacers.js +1 -2
  82. package/dist/lib/setups/routes/generate.js +18 -19
  83. package/dist/lib/shell.js +5 -10
  84. package/dist/lib/template-diff.js +83 -104
  85. package/dist/lib/template-downloader.js +2 -2
  86. package/dist/lib/transpile/morph/functions.js +3 -6
  87. package/dist/lib/transpile/morph/index.js +2 -4
  88. package/dist/lib/transpile/morph/typedefs.js +3 -6
  89. package/dist/lib/transpile/morph/utils.js +2 -4
  90. package/dist/lib/transpile/project.js +4 -3
  91. package/oclif.manifest.json +51 -4
  92. package/package.json +8 -12
  93. package/dist/assets/hydrogen/css-modules/package.json +0 -6
  94. package/dist/assets/hydrogen/postcss/package.json +0 -10
  95. package/dist/assets/hydrogen/postcss/postcss.config.js +0 -8
  96. package/dist/assets/hydrogen/starter/app/components/Cart.tsx +0 -364
  97. package/dist/assets/hydrogen/tailwind/postcss.config.js +0 -10
  98. package/dist/assets/hydrogen/tailwind/tailwind.config.js +0 -8
  99. package/dist/lib/check-version.js +0 -75
  100. package/dist/lib/setups/css/css-modules.js +0 -23
  101. package/dist/lib/setups/css/postcss.js +0 -31
@@ -1,364 +0,0 @@
1
- import {
2
- CartForm,
3
- Image,
4
- Money,
5
- useOptimisticCart,
6
- type OptimisticCart,
7
- } from '@shopify/hydrogen';
8
- import type {CartLineUpdateInput} from '@shopify/hydrogen/storefront-api-types';
9
- import {Link} from '@remix-run/react';
10
- import type {CartApiQueryFragment} from 'storefrontapi.generated';
11
- import {useVariantUrl} from '~/lib/variants';
12
-
13
- type CartLine = OptimisticCart<CartApiQueryFragment>['lines']['nodes'][0];
14
-
15
- type CartMainProps = {
16
- cart: CartApiQueryFragment | null;
17
- layout: 'page' | 'aside';
18
- };
19
-
20
- export function CartMain({layout, cart: originalCart}: CartMainProps) {
21
- const cart = useOptimisticCart(originalCart);
22
-
23
- const linesCount = Boolean(cart?.lines?.nodes?.length || 0);
24
- const withDiscount =
25
- cart &&
26
- Boolean(cart?.discountCodes?.filter((code) => code.applicable)?.length);
27
- const className = `cart-main ${withDiscount ? 'with-discount' : ''}`;
28
-
29
- return (
30
- <div className={className}>
31
- <CartEmpty hidden={linesCount} layout={layout} />
32
- <CartDetails cart={cart} layout={layout} />
33
- </div>
34
- );
35
- }
36
-
37
- function CartDetails({
38
- layout,
39
- cart,
40
- }: {
41
- cart: OptimisticCart<CartApiQueryFragment>;
42
- layout: 'page' | 'aside';
43
- }) {
44
- const cartHasItems = !!cart && cart.totalQuantity > 0;
45
-
46
- return (
47
- <div className="cart-details">
48
- <CartLines lines={cart?.lines?.nodes} layout={layout} />
49
- {cartHasItems && (
50
- <CartSummary cost={cart.cost} layout={layout}>
51
- <CartDiscounts discountCodes={cart.discountCodes} />
52
- <CartCheckoutActions checkoutUrl={cart.checkoutUrl} />
53
- </CartSummary>
54
- )}
55
- </div>
56
- );
57
- }
58
-
59
- function CartLines({
60
- lines,
61
- layout,
62
- }: {
63
- layout: CartMainProps['layout'];
64
- lines: CartLine[];
65
- }) {
66
- if (!lines) return null;
67
-
68
- return (
69
- <div aria-labelledby="cart-lines">
70
- <ul>
71
- {lines.map((line) => (
72
- <CartLineItem key={line.id} line={line} layout={layout} />
73
- ))}
74
- </ul>
75
- </div>
76
- );
77
- }
78
-
79
- function CartLineItem({
80
- layout,
81
- line,
82
- }: {
83
- layout: CartMainProps['layout'];
84
- line: CartLine;
85
- }) {
86
- const {id, merchandise} = line;
87
- const {product, title, image, selectedOptions} = merchandise;
88
- const lineItemUrl = useVariantUrl(product.handle, selectedOptions);
89
-
90
- return (
91
- <li key={id} className="cart-line">
92
- {image && (
93
- <Image
94
- alt={title}
95
- aspectRatio="1/1"
96
- data={image}
97
- height={100}
98
- loading="lazy"
99
- width={100}
100
- />
101
- )}
102
-
103
- <div>
104
- <Link
105
- prefetch="intent"
106
- to={lineItemUrl}
107
- onClick={() => {
108
- if (layout === 'aside') {
109
- // close the drawer
110
- window.location.href = lineItemUrl;
111
- }
112
- }}
113
- >
114
- <p>
115
- <strong>{product.title}</strong>
116
- </p>
117
- </Link>
118
- <CartLinePrice line={line} as="span" />
119
- <ul>
120
- {selectedOptions.map((option) => (
121
- <li key={option.name}>
122
- <small>
123
- {option.name}: {option.value}
124
- </small>
125
- </li>
126
- ))}
127
- </ul>
128
- <CartLineQuantity line={line} />
129
- </div>
130
- </li>
131
- );
132
- }
133
-
134
- function CartCheckoutActions({checkoutUrl}: {checkoutUrl: string}) {
135
- if (!checkoutUrl) return null;
136
-
137
- return (
138
- <div>
139
- <a href={checkoutUrl} target="_self">
140
- <p>Continue to Checkout &rarr;</p>
141
- </a>
142
- <br />
143
- </div>
144
- );
145
- }
146
-
147
- export function CartSummary({
148
- cost,
149
- layout,
150
- children = null,
151
- }: {
152
- children?: React.ReactNode;
153
- cost: CartApiQueryFragment['cost'];
154
- layout: CartMainProps['layout'];
155
- }) {
156
- const className =
157
- layout === 'page' ? 'cart-summary-page' : 'cart-summary-aside';
158
-
159
- return (
160
- <div aria-labelledby="cart-summary" className={className}>
161
- <h4>Totals</h4>
162
- <dl className="cart-subtotal">
163
- <dt>Subtotal</dt>
164
- <dd>
165
- {cost?.subtotalAmount?.amount ? (
166
- <Money data={cost?.subtotalAmount} />
167
- ) : (
168
- '-'
169
- )}
170
- </dd>
171
- </dl>
172
- {children}
173
- </div>
174
- );
175
- }
176
-
177
- function CartLineRemoveButton({
178
- lineIds,
179
- disabled,
180
- }: {
181
- lineIds: string[];
182
- disabled: boolean;
183
- }) {
184
- return (
185
- <CartForm
186
- route="/cart"
187
- action={CartForm.ACTIONS.LinesRemove}
188
- inputs={{lineIds}}
189
- >
190
- <button disabled={disabled} type="submit">
191
- Remove
192
- </button>
193
- </CartForm>
194
- );
195
- }
196
-
197
- function CartLineQuantity({line}: {line: CartLine}) {
198
- if (!line || typeof line?.quantity === 'undefined') return null;
199
- const {id: lineId, quantity, isOptimistic} = line;
200
- const prevQuantity = Number(Math.max(0, quantity - 1).toFixed(0));
201
- const nextQuantity = Number((quantity + 1).toFixed(0));
202
-
203
- return (
204
- <div className="cart-line-quantity">
205
- <small>Quantity: {quantity} &nbsp;&nbsp;</small>
206
- <CartLineUpdateButton lines={[{id: lineId, quantity: prevQuantity}]}>
207
- <button
208
- aria-label="Decrease quantity"
209
- disabled={quantity <= 1 || !!isOptimistic}
210
- name="decrease-quantity"
211
- value={prevQuantity}
212
- >
213
- <span>&#8722; </span>
214
- </button>
215
- </CartLineUpdateButton>
216
- &nbsp;
217
- <CartLineUpdateButton lines={[{id: lineId, quantity: nextQuantity}]}>
218
- <button
219
- aria-label="Increase quantity"
220
- name="increase-quantity"
221
- value={nextQuantity}
222
- disabled={!!isOptimistic}
223
- >
224
- <span>&#43;</span>
225
- </button>
226
- </CartLineUpdateButton>
227
- &nbsp;
228
- <CartLineRemoveButton lineIds={[lineId]} disabled={!!isOptimistic} />
229
- </div>
230
- );
231
- }
232
-
233
- function CartLinePrice({
234
- line,
235
- priceType = 'regular',
236
- ...passthroughProps
237
- }: {
238
- line: CartLine;
239
- priceType?: 'regular' | 'compareAt';
240
- [key: string]: any;
241
- }) {
242
- if (!line?.cost?.amountPerQuantity || !line?.cost?.totalAmount)
243
- return <div style={{visibility: 'hidden'}}>&nbsp;</div>;
244
-
245
- const moneyV2 =
246
- priceType === 'regular'
247
- ? line.cost.totalAmount
248
- : line.cost.compareAtAmountPerQuantity;
249
-
250
- if (moneyV2 == null) {
251
- return <div style={{visibility: 'hidden'}}>&nbsp;</div>;
252
- }
253
-
254
- return (
255
- <div>
256
- <Money withoutTrailingZeros {...passthroughProps} data={moneyV2} />
257
- </div>
258
- );
259
- }
260
-
261
- export function CartEmpty({
262
- hidden = false,
263
- layout = 'aside',
264
- }: {
265
- hidden: boolean;
266
- layout?: CartMainProps['layout'];
267
- }) {
268
- return (
269
- <div hidden={hidden}>
270
- <br />
271
- <p>
272
- Looks like you haven&rsquo;t added anything yet, let&rsquo;s get you
273
- started!
274
- </p>
275
- <br />
276
- <Link
277
- to="/collections"
278
- onClick={() => {
279
- if (layout === 'aside') {
280
- window.location.href = '/collections';
281
- }
282
- }}
283
- >
284
- Continue shopping →
285
- </Link>
286
- </div>
287
- );
288
- }
289
-
290
- function CartDiscounts({
291
- discountCodes,
292
- }: {
293
- discountCodes: CartApiQueryFragment['discountCodes'];
294
- }) {
295
- const codes: string[] =
296
- discountCodes
297
- ?.filter((discount) => discount.applicable)
298
- ?.map(({code}) => code) || [];
299
-
300
- return (
301
- <div>
302
- {/* Have existing discount, display it with a remove option */}
303
- <dl hidden={!codes.length}>
304
- <div>
305
- <dt>Discount(s)</dt>
306
- <UpdateDiscountForm>
307
- <div className="cart-discount">
308
- <code>{codes?.join(', ')}</code>
309
- &nbsp;
310
- <button>Remove</button>
311
- </div>
312
- </UpdateDiscountForm>
313
- </div>
314
- </dl>
315
-
316
- {/* Show an input to apply a discount */}
317
- <UpdateDiscountForm discountCodes={codes}>
318
- <div>
319
- <input type="text" name="discountCode" placeholder="Discount code" />
320
- &nbsp;
321
- <button type="submit">Apply</button>
322
- </div>
323
- </UpdateDiscountForm>
324
- </div>
325
- );
326
- }
327
-
328
- function UpdateDiscountForm({
329
- discountCodes,
330
- children,
331
- }: {
332
- discountCodes?: string[];
333
- children: React.ReactNode;
334
- }) {
335
- return (
336
- <CartForm
337
- route="/cart"
338
- action={CartForm.ACTIONS.DiscountCodesUpdate}
339
- inputs={{
340
- discountCodes: discountCodes || [],
341
- }}
342
- >
343
- {children}
344
- </CartForm>
345
- );
346
- }
347
-
348
- function CartLineUpdateButton({
349
- children,
350
- lines,
351
- }: {
352
- children: React.ReactNode;
353
- lines: CartLineUpdateInput[];
354
- }) {
355
- return (
356
- <CartForm
357
- route="/cart"
358
- action={CartForm.ACTIONS.LinesUpdate}
359
- inputs={{lines}}
360
- >
361
- {children}
362
- </CartForm>
363
- );
364
- }
@@ -1,10 +0,0 @@
1
- module.exports = {
2
- plugins: {
3
- 'postcss-import': {},
4
- 'tailwindcss/nesting': {},
5
- tailwindcss: {},
6
- 'postcss-preset-env': {
7
- features: {'nesting-rules': false},
8
- },
9
- },
10
- };
@@ -1,8 +0,0 @@
1
- import formsPlugin from '@tailwindcss/forms';
2
- import typographyPlugin from '@tailwindcss/typography';
3
-
4
- /** @type {import('tailwindcss').Config} */
5
- export default {
6
- content: ['./{src-dir}/**/*.{js,ts,jsx,tsx}'],
7
- plugins: [formsPlugin, typographyPlugin],
8
- };
@@ -1,75 +0,0 @@
1
- import path from 'node:path';
2
- import { createRequire } from 'node:module';
3
- import { checkForNewVersion } from '@shopify/cli-kit/node/node-package-manager';
4
- import { renderInfo } from '@shopify/cli-kit/node/ui';
5
- import { CLI_KIT_VERSION } from '@shopify/cli-kit/common/version';
6
-
7
- const PACKAGE_NAMES = {
8
- main: "@shopify/hydrogen",
9
- cliHydrogen: "@shopify/cli-hydrogen",
10
- cli: "@shopify/cli"
11
- };
12
- async function checkHydrogenVersion(resolveFrom, pkgKey = "main") {
13
- if (process.env.LOCAL_DEV)
14
- return;
15
- const pkgName = PACKAGE_NAMES[pkgKey];
16
- let currentVersion;
17
- if (pkgName === PACKAGE_NAMES.cli) {
18
- currentVersion = CLI_KIT_VERSION;
19
- } else {
20
- currentVersion = getCurrentVersionFromPackageJson(pkgName, resolveFrom);
21
- }
22
- if (!currentVersion || currentVersion.includes("next"))
23
- return;
24
- const newVersionAvailable = await checkForNewVersion(pkgName, currentVersion);
25
- if (!newVersionAvailable)
26
- return;
27
- const references = [
28
- {
29
- link: {
30
- label: "Hydrogen releases",
31
- url: "https://github.com/Shopify/hydrogen/releases"
32
- }
33
- }
34
- ];
35
- if (pkgName === PACKAGE_NAMES.cli) {
36
- references.push({
37
- link: {
38
- label: "Global CLI reference",
39
- url: "https://shopify.dev/docs/api/shopify-cli/"
40
- }
41
- });
42
- }
43
- return (extraMessage = "") => {
44
- renderInfo({
45
- headline: "Upgrade available",
46
- body: `Version ${newVersionAvailable} of ${pkgName} is now available.
47
- You are currently running v${currentVersion}.` + (extraMessage ? "\n\n" : "") + extraMessage,
48
- reference: references
49
- });
50
- return { currentVersion, newVersion: newVersionAvailable };
51
- };
52
- }
53
- function getCurrentVersionFromPackageJson(pkgName, resolveFrom) {
54
- const require2 = createRequire(import.meta.url);
55
- const pkgJsonPath = resolveFrom.endsWith("package.json") ? locateDependency(require2, resolveFrom) : locateDependency(
56
- require2,
57
- path.join(pkgName, "package.json"),
58
- resolveFrom
59
- );
60
- if (!pkgJsonPath)
61
- return;
62
- const currentVersion = require2(pkgJsonPath).version;
63
- return currentVersion;
64
- }
65
- function locateDependency(require2, nameToResolve, resolveFrom) {
66
- try {
67
- return require2.resolve(nameToResolve, {
68
- paths: [resolveFrom ?? process.cwd()]
69
- });
70
- } catch {
71
- return;
72
- }
73
- }
74
-
75
- export { checkHydrogenVersion };
@@ -1,23 +0,0 @@
1
- import { mergePackageJson } from '../../file.js';
2
- import { getCodeFormatOptions } from '../../format-code.js';
3
- import { injectCssBundlingLink } from './replacers.js';
4
- import { getAssetsDir } from '../../build.js';
5
-
6
- async function setupCssModules({
7
- rootDirectory,
8
- appDirectory
9
- }) {
10
- const workPromise = Promise.all([
11
- mergePackageJson(await getAssetsDir("css-modules"), rootDirectory),
12
- getCodeFormatOptions(rootDirectory).then(
13
- (formatConfig) => injectCssBundlingLink(appDirectory, formatConfig)
14
- )
15
- ]);
16
- return {
17
- workPromise,
18
- generatedAssets: [],
19
- helpUrl: "https://github.com/css-modules/css-modules"
20
- };
21
- }
22
-
23
- export { setupCssModules };
@@ -1,31 +0,0 @@
1
- import { outputInfo } from '@shopify/cli-kit/node/output';
2
- import { mergePackageJson } from '../../file.js';
3
- import { canWriteFiles, copyAssets } from './assets.js';
4
- import { getAssetsDir } from '../../build.js';
5
-
6
- async function setupPostCss({ rootDirectory, appDirectory, ...futureOptions }, force = false) {
7
- const assetMap = {
8
- "postcss.config.js": "postcss.config.js"
9
- };
10
- if (futureOptions.postcss) {
11
- outputInfo(`PostCSS is already setup in ${rootDirectory}.`);
12
- return;
13
- }
14
- if (!await canWriteFiles(assetMap, appDirectory, force)) {
15
- outputInfo(
16
- `Skipping CSS setup as some files already exist. You may use \`--force\` or \`-f\` to override it.`
17
- );
18
- return;
19
- }
20
- const workPromise = Promise.all([
21
- mergePackageJson(await getAssetsDir("postcss"), rootDirectory),
22
- copyAssets("postcss", assetMap, rootDirectory)
23
- ]);
24
- return {
25
- workPromise,
26
- generatedAssets: Object.values(assetMap),
27
- helpUrl: "https://postcss.org/"
28
- };
29
- }
30
-
31
- export { setupPostCss };