@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
package/dist/index.d.ts CHANGED
@@ -90,29 +90,29 @@ declare class Dev extends Command {
90
90
  worker: {
91
91
  type: "option";
92
92
  name: string;
93
- char?: _oclif_core_lib_interfaces_alphabet_js.AlphabetLowercase | _oclif_core_lib_interfaces_alphabet_js.AlphabetUppercase | undefined;
94
- summary?: string | undefined;
95
- description?: string | undefined;
96
- helpLabel?: string | undefined;
97
- helpGroup?: string | undefined;
98
- env?: string | undefined;
99
- hidden?: boolean | undefined;
100
- required?: boolean | undefined;
101
- dependsOn?: string[] | undefined;
102
- exclusive?: string[] | undefined;
103
- exactlyOne?: string[] | undefined;
104
- relationships?: _oclif_core_lib_interfaces_parser_js.Relationship[] | undefined;
105
- deprecated?: true | _oclif_core_lib_interfaces_parser_js.Deprecation | undefined;
106
- aliases?: string[] | undefined;
107
- charAliases?: (_oclif_core_lib_interfaces_alphabet_js.AlphabetLowercase | _oclif_core_lib_interfaces_alphabet_js.AlphabetUppercase)[] | undefined;
108
- deprecateAliases?: boolean | undefined;
109
- noCacheDefault?: boolean | undefined;
110
- helpValue?: string | undefined;
111
- options?: readonly string[] | undefined;
112
- multiple?: boolean | undefined;
113
- multipleNonGreedy?: boolean | undefined;
114
- delimiter?: "," | undefined;
115
- allowStdin?: boolean | "only" | undefined;
93
+ char?: _oclif_core_lib_interfaces_alphabet_js.AlphabetLowercase | _oclif_core_lib_interfaces_alphabet_js.AlphabetUppercase;
94
+ summary?: string;
95
+ description?: string;
96
+ helpLabel?: string;
97
+ helpGroup?: string;
98
+ env?: string;
99
+ hidden?: boolean;
100
+ required?: boolean;
101
+ dependsOn?: string[];
102
+ exclusive?: string[];
103
+ exactlyOne?: string[];
104
+ relationships?: _oclif_core_lib_interfaces_parser_js.Relationship[];
105
+ deprecated?: true | _oclif_core_lib_interfaces_parser_js.Deprecation;
106
+ aliases?: string[];
107
+ charAliases?: (_oclif_core_lib_interfaces_alphabet_js.AlphabetLowercase | _oclif_core_lib_interfaces_alphabet_js.AlphabetUppercase)[];
108
+ deprecateAliases?: boolean;
109
+ noCacheDefault?: boolean;
110
+ helpValue?: string;
111
+ options?: readonly string[];
112
+ multiple?: boolean;
113
+ multipleNonGreedy?: boolean;
114
+ delimiter?: ",";
115
+ allowStdin?: boolean | "only";
116
116
  parse: _oclif_core_lib_interfaces_parser_js.FlagParser<unknown, string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
117
117
  defaultHelp?: unknown;
118
118
  input: string[];
@@ -262,29 +262,29 @@ declare class Preview extends Command {
262
262
  worker: {
263
263
  type: "option";
264
264
  name: string;
265
- char?: _oclif_core_lib_interfaces_alphabet_js.AlphabetLowercase | _oclif_core_lib_interfaces_alphabet_js.AlphabetUppercase | undefined;
266
- summary?: string | undefined;
267
- description?: string | undefined;
268
- helpLabel?: string | undefined;
269
- helpGroup?: string | undefined;
270
- env?: string | undefined;
271
- hidden?: boolean | undefined;
272
- required?: boolean | undefined;
273
- dependsOn?: string[] | undefined;
274
- exclusive?: string[] | undefined;
275
- exactlyOne?: string[] | undefined;
276
- relationships?: _oclif_core_lib_interfaces_parser_js.Relationship[] | undefined;
277
- deprecated?: true | _oclif_core_lib_interfaces_parser_js.Deprecation | undefined;
278
- aliases?: string[] | undefined;
279
- charAliases?: (_oclif_core_lib_interfaces_alphabet_js.AlphabetLowercase | _oclif_core_lib_interfaces_alphabet_js.AlphabetUppercase)[] | undefined;
280
- deprecateAliases?: boolean | undefined;
281
- noCacheDefault?: boolean | undefined;
282
- helpValue?: string | undefined;
283
- options?: readonly string[] | undefined;
284
- multiple?: boolean | undefined;
285
- multipleNonGreedy?: boolean | undefined;
286
- delimiter?: "," | undefined;
287
- allowStdin?: boolean | "only" | undefined;
265
+ char?: _oclif_core_lib_interfaces_alphabet_js.AlphabetLowercase | _oclif_core_lib_interfaces_alphabet_js.AlphabetUppercase;
266
+ summary?: string;
267
+ description?: string;
268
+ helpLabel?: string;
269
+ helpGroup?: string;
270
+ env?: string;
271
+ hidden?: boolean;
272
+ required?: boolean;
273
+ dependsOn?: string[];
274
+ exclusive?: string[];
275
+ exactlyOne?: string[];
276
+ relationships?: _oclif_core_lib_interfaces_parser_js.Relationship[];
277
+ deprecated?: true | _oclif_core_lib_interfaces_parser_js.Deprecation;
278
+ aliases?: string[];
279
+ charAliases?: (_oclif_core_lib_interfaces_alphabet_js.AlphabetLowercase | _oclif_core_lib_interfaces_alphabet_js.AlphabetUppercase)[];
280
+ deprecateAliases?: boolean;
281
+ noCacheDefault?: boolean;
282
+ helpValue?: string;
283
+ options?: readonly string[];
284
+ multiple?: boolean;
285
+ multipleNonGreedy?: boolean;
286
+ delimiter?: ",";
287
+ allowStdin?: boolean | "only";
288
288
  parse: _oclif_core_lib_interfaces_parser_js.FlagParser<unknown, string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
289
289
  defaultHelp?: unknown;
290
290
  input: string[];
package/dist/lib/auth.js CHANGED
@@ -21,8 +21,7 @@ async function login(root, shop) {
21
21
  if (typeof shop !== "string") {
22
22
  shop = existingConfig.shop;
23
23
  }
24
- if (shop)
25
- shop = await normalizeStoreFqdn(shop);
24
+ if (shop) shop = await normalizeStoreFqdn(shop);
26
25
  const hideLoginInfo = showLoginInfo();
27
26
  if (!shop || !shopName || !email || forcePrompt || shop !== existingConfig.shop) {
28
27
  const token = await ensureAuthenticatedBusinessPlatform().catch(() => {
package/dist/lib/build.js CHANGED
@@ -43,8 +43,7 @@ async function getTemplateAppFile(filepath, root) {
43
43
  return url.protocol === "file:" ? fileURLToPath(url) : url.toString();
44
44
  }
45
45
  function getStarterDir(useSource = !!process.env.SHOPIFY_UNIT_TEST) {
46
- if (useSource)
47
- return getSkeletonSourceDir();
46
+ if (useSource) return getSkeletonSourceDir();
48
47
  return getAssetsDir(ASSETS_STARTER_DIR);
49
48
  }
50
49
  function getSkeletonSourceDir() {
@@ -4,24 +4,25 @@ import colors from '@shopify/cli-kit/node/colors';
4
4
  import { renderWarning } from '@shopify/cli-kit/node/ui';
5
5
  import { getAssetsDir } from '../build.js';
6
6
 
7
- async function buildBundleAnalysis(buildPath) {
7
+ const BUNDLE_ANALYZER_JSON_FILE = "metafile.server.json";
8
+ const BUNDLE_ANALYZER_HTML_FILE = "server-bundle-analyzer.html";
9
+ async function classicBuildBundleAnalysis(buildPath) {
8
10
  const workerBuildPath = joinPath(buildPath, "worker");
9
- const serverMetafile = "metafile.server.json";
11
+ const serverMetafile = BUNDLE_ANALYZER_JSON_FILE;
10
12
  const clientMetafile = "metafile.js.json";
11
13
  const hasMetafile = (await Promise.all([
12
14
  fileExists(joinPath(workerBuildPath, serverMetafile)),
13
15
  fileExists(joinPath(workerBuildPath, clientMetafile))
14
16
  ])).every(Boolean);
15
- if (!hasMetafile)
16
- return null;
17
+ if (!hasMetafile) return null;
17
18
  try {
18
19
  await Promise.all([
19
- writeBundleAnalyzerFile(
20
+ classicWriteBundleAnalyzerFile(
20
21
  workerBuildPath,
21
22
  serverMetafile,
22
23
  "worker-bundle-analyzer.html"
23
24
  ),
24
- writeBundleAnalyzerFile(
25
+ classicWriteBundleAnalyzerFile(
25
26
  workerBuildPath,
26
27
  clientMetafile,
27
28
  "client-bundle-analyzer.html"
@@ -37,34 +38,48 @@ async function buildBundleAnalysis(buildPath) {
37
38
  return null;
38
39
  }
39
40
  }
40
- async function writeBundleAnalyzerFile(workerBuildPath, metafileName, outputFile) {
41
+ async function getAnalyzerTemplate() {
42
+ return readFile(await getAssetsDir("bundle", "analyzer.html"));
43
+ }
44
+ function injectAnalyzerTemplateData(analysisTemplate, metafile) {
45
+ return analysisTemplate.replace(
46
+ `globalThis.METAFILE = '';`,
47
+ `globalThis.METAFILE = '${Buffer.from(metafile, "utf-8").toString(
48
+ "base64"
49
+ )}';`
50
+ );
51
+ }
52
+ async function classicWriteBundleAnalyzerFile(workerBuildPath, metafileName, outputFile) {
41
53
  const metafile = await readFile(joinPath(workerBuildPath, metafileName), {
42
54
  encoding: "utf8"
43
55
  });
44
- const metafile64 = Buffer.from(metafile, "utf-8").toString("base64");
45
- const analysisTemplate = await readFile(
46
- await getAssetsDir("bundle", "analyzer.html")
56
+ await writeFile(
57
+ joinPath(workerBuildPath, outputFile),
58
+ injectAnalyzerTemplateData(await getAnalyzerTemplate(), metafile)
47
59
  );
48
- const templateWithMetafile = analysisTemplate.replace(
49
- `globalThis.METAFILE = '';`,
50
- `globalThis.METAFILE = '${metafile64}';`
51
- );
52
- await writeFile(joinPath(workerBuildPath, outputFile), templateWithMetafile);
53
60
  }
54
- async function getBundleAnalysisSummary(bundlePath) {
55
- const esbuild = await import('esbuild').catch(() => {
56
- });
57
- if (esbuild) {
58
- const metafilePath = joinPath(dirname(bundlePath), "metafile.server.json");
59
- return " \u2502\n " + (await esbuild.analyzeMetafile(await readFile(metafilePath), {
60
- color: true
61
- })).split("\n").filter((line) => {
61
+ async function getBundleAnalysisSummary(distPath) {
62
+ try {
63
+ const esbuild = await import('esbuild');
64
+ const metafileAnalysis = await esbuild.analyzeMetafile(
65
+ await readFile(joinPath(distPath, BUNDLE_ANALYZER_JSON_FILE)),
66
+ { color: true }
67
+ );
68
+ return " \u2502\n " + metafileAnalysis.split("\n").filter((line) => {
62
69
  const match = line.match(
63
70
  /(.*)(node_modules\/|server-assets-manifest:|server-entry-module:)(react-dom|@remix-run|@shopify\/hydrogen|react-router|react-router-dom)\/(.*)/g
64
71
  );
65
72
  return !match;
66
73
  }).slice(2, 12).join("\n").replace(/dist\/worker\/_assets\/.*$/ms, "\n").replace(/\n/g, "\n ").replace(/(\.\.\/)+node_modules\//g, (match) => colors.dim(match));
74
+ } catch (error) {
75
+ console.warn(
76
+ "Could not generate bundle analysis summary:",
77
+ error.message
78
+ );
67
79
  }
68
80
  }
81
+ function classicGetBundleAnalysisSummary(bundlePath) {
82
+ return getBundleAnalysisSummary(dirname(bundlePath));
83
+ }
69
84
 
70
- export { buildBundleAnalysis, getBundleAnalysisSummary };
85
+ export { BUNDLE_ANALYZER_HTML_FILE, BUNDLE_ANALYZER_JSON_FILE, classicBuildBundleAnalysis, classicGetBundleAnalysisSummary, getAnalyzerTemplate, getBundleAnalysisSummary, injectAnalyzerTemplateData };
@@ -0,0 +1,161 @@
1
+ import { relativePath, joinPath } from '@shopify/cli-kit/node/path';
2
+ import { getAnalyzerTemplate, BUNDLE_ANALYZER_JSON_FILE, BUNDLE_ANALYZER_HTML_FILE, injectAnalyzerTemplateData } from './analyzer.js';
3
+
4
+ function hydrogenBundleAnalyzer(pluginOptions) {
5
+ let config;
6
+ return {
7
+ name: "hydrogen:bundle-analyzer",
8
+ configResolved(_config) {
9
+ config = _config;
10
+ },
11
+ async generateBundle(options, bundle) {
12
+ if (!config.build.ssr) return;
13
+ const { root } = config;
14
+ const workerFile = Object.values(bundle).find(
15
+ (chunk) => chunk.type === "chunk"
16
+ );
17
+ if (!workerFile || workerFile.type !== "chunk" || !workerFile.facadeModuleId || !options.dir) {
18
+ return;
19
+ }
20
+ const analysisTemplate = await getAnalyzerTemplate().catch(() => null);
21
+ if (!analysisTemplate) {
22
+ console.warn("Bundle analyzer template not found");
23
+ return;
24
+ }
25
+ const allModIds = new Set(Object.keys(workerFile.modules));
26
+ const modsToAnalyze = [];
27
+ for (const modId of allModIds) {
28
+ if (isViteCjsHelper(modId) || isViteTransformHelper(modId)) continue;
29
+ const mod = this.getModuleInfo(modId);
30
+ if (!mod?.id) continue;
31
+ modsToAnalyze.push(mod);
32
+ for (const importedId of [
33
+ ...mod.importedIds,
34
+ ...mod.dynamicallyImportedIds
35
+ ]) {
36
+ if (!isViteCjsHelper(importedId) && !isViteTransformHelper(importedId)) {
37
+ allModIds.add(importedId);
38
+ }
39
+ }
40
+ }
41
+ const modsMeta = /* @__PURE__ */ new Map();
42
+ const renderedSizes = /* @__PURE__ */ new Map();
43
+ const resultError = await Promise.all(
44
+ modsToAnalyze.map(async (mod) => {
45
+ const relativeModId = relativePath(root, mod.id);
46
+ const modBundleInfo = workerFile.modules[mod.id];
47
+ const originalCodeBytes = modBundleInfo?.originalLength ?? mod.code?.length ?? 0;
48
+ let resultingCodeBytes = modBundleInfo?.renderedLength ?? 0;
49
+ if (pluginOptions?.minify && modBundleInfo?.code) {
50
+ const minifiedCode = await pluginOptions.minify(modBundleInfo.code, mod.id).catch(() => null);
51
+ if (minifiedCode) resultingCodeBytes = minifiedCode.length;
52
+ }
53
+ renderedSizes.set(relativeModId, resultingCodeBytes);
54
+ const resolveImportString = (importString) => this.resolve(importString, mod.id);
55
+ let isESM = !mod.code || /(^\s*export\s+[\w\{]|^\s*import\s+[\w\{'"]|\bimport\()|\bcreateRequire\(/ms.test(
56
+ mod.code
57
+ ) || !/((^|\b)exports\b|\brequire\()/.test(mod.code);
58
+ const staticImportsMeta = createImportsMeta(
59
+ mod.importedIds,
60
+ "import-statement",
61
+ root,
62
+ resolveImportString,
63
+ mod.code
64
+ );
65
+ const dynamicImportsMeta = createImportsMeta(
66
+ mod.dynamicallyImportedIds,
67
+ "dynamic-import",
68
+ root,
69
+ resolveImportString,
70
+ mod.code
71
+ );
72
+ const importsMeta = (await Promise.all([...staticImportsMeta, ...dynamicImportsMeta])).reduce((acc, { importedId, ...meta }) => {
73
+ if (isViteCjsHelper(importedId)) {
74
+ isESM = false;
75
+ } else if (!isViteTransformHelper(importedId)) {
76
+ acc.push(meta);
77
+ }
78
+ return acc;
79
+ }, []);
80
+ modsMeta.set(relativeModId, {
81
+ bytes: originalCodeBytes,
82
+ format: isESM ? "esm" : "cjs",
83
+ imports: importsMeta
84
+ });
85
+ })
86
+ ).then(() => null).catch((error) => error);
87
+ if (resultError) {
88
+ console.warn(
89
+ "Bundle analyzer failed to analyze the bundle:",
90
+ resultError
91
+ );
92
+ return;
93
+ }
94
+ const inputs = Object.fromEntries(modsMeta.entries());
95
+ const metafile = {
96
+ inputs,
97
+ outputs: {
98
+ [relativePath(root, joinPath(options.dir, workerFile.fileName))]: {
99
+ imports: workerFile.imports,
100
+ exports: workerFile.exports,
101
+ entryPoint: relativePath(root, workerFile.facadeModuleId),
102
+ bytes: workerFile.code.length ?? 0,
103
+ inputs: Object.entries(inputs).reduce((acc, [key, item]) => {
104
+ acc[key] = {
105
+ bytesInOutput: renderedSizes.get(key) ?? item.bytes ?? 0
106
+ };
107
+ return acc;
108
+ }, {})
109
+ }
110
+ }
111
+ };
112
+ bundle[BUNDLE_ANALYZER_JSON_FILE] = {
113
+ type: "asset",
114
+ fileName: BUNDLE_ANALYZER_JSON_FILE,
115
+ name: BUNDLE_ANALYZER_JSON_FILE,
116
+ needsCodeReference: false,
117
+ source: JSON.stringify(metafile, null, 2)
118
+ };
119
+ bundle[BUNDLE_ANALYZER_HTML_FILE] = {
120
+ type: "asset",
121
+ fileName: BUNDLE_ANALYZER_HTML_FILE,
122
+ name: BUNDLE_ANALYZER_HTML_FILE,
123
+ needsCodeReference: false,
124
+ source: injectAnalyzerTemplateData(
125
+ analysisTemplate,
126
+ JSON.stringify(metafile)
127
+ )
128
+ };
129
+ }
130
+ };
131
+ }
132
+ function isViteCjsHelper(id) {
133
+ return /(commonjsHelpers\.js$|\?commonjs\-)/.test(id);
134
+ }
135
+ function isViteTransformHelper(id) {
136
+ return id.endsWith("?transform-only");
137
+ }
138
+ async function findOriginalImportName(filepath, importerCode, resolve) {
139
+ const matches = importerCode.matchAll(/import\s[^'"]*?['"]([^'"]+)['"]/g) ?? [];
140
+ for (const [, match] of matches) {
141
+ if (match) {
142
+ const resolvedMod = await resolve(match);
143
+ if (resolvedMod?.id === filepath) {
144
+ return match;
145
+ }
146
+ }
147
+ }
148
+ return filepath;
149
+ }
150
+ function createImportsMeta(ids, kind, root, resolveImportString, code) {
151
+ return ids.map(async (importedId) => {
152
+ return {
153
+ importedId,
154
+ path: relativePath(root, importedId),
155
+ kind,
156
+ original: code ? await findOriginalImportName(importedId, code, resolveImportString) : importedId
157
+ };
158
+ });
159
+ }
160
+
161
+ export { hydrogenBundleAnalyzer };
@@ -0,0 +1,61 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import { findUpAndReadPackageJson, checkForNewVersion, packageManagerFromUserAgent } from '@shopify/cli-kit/node/node-package-manager';
3
+ import { renderInfo } from '@shopify/cli-kit/node/ui';
4
+ import { isHydrogenMonorepo } from './build.js';
5
+ import { inferPackageManagerForGlobalCLI } from '@shopify/cli-kit/node/is-global';
6
+
7
+ const UPGRADABLE_CLI_NAMES = {
8
+ cli: "@shopify/cli",
9
+ cliHydrogen: "@shopify/cli-hydrogen",
10
+ createApp: "@shopify/create-hydrogen"
11
+ };
12
+ async function checkCurrentCLIVersion() {
13
+ if (isHydrogenMonorepo && !process.env.SHOPIFY_UNIT_TEST) return;
14
+ const { content: pkgJson } = await findUpAndReadPackageJson(
15
+ fileURLToPath(import.meta.url)
16
+ ).catch(() => ({ content: void 0 }));
17
+ const pkgName = pkgJson?.name;
18
+ const currentVersion = pkgJson?.version;
19
+ if (!pkgName || !currentVersion || !Object.values(UPGRADABLE_CLI_NAMES).some((name) => name === pkgName) || currentVersion.includes("next") || currentVersion.includes("experimental") || currentVersion.includes("snapshot")) {
20
+ return;
21
+ }
22
+ const newVersionAvailable = await checkForNewVersion(pkgName, currentVersion);
23
+ if (!newVersionAvailable) return;
24
+ const reference = [
25
+ {
26
+ link: {
27
+ label: "Hydrogen releases",
28
+ url: "https://github.com/Shopify/hydrogen/releases"
29
+ }
30
+ }
31
+ ];
32
+ if (pkgName === UPGRADABLE_CLI_NAMES.cli) {
33
+ reference.push({
34
+ link: {
35
+ label: "Global CLI reference",
36
+ url: "https://shopify.dev/docs/api/shopify-cli/"
37
+ }
38
+ });
39
+ }
40
+ return (packageManager) => {
41
+ packageManager ??= packageManagerFromUserAgent();
42
+ if (packageManager === "unknown" || !packageManager) {
43
+ packageManager = inferPackageManagerForGlobalCLI();
44
+ }
45
+ if (packageManager === "unknown") {
46
+ packageManager = "npm";
47
+ }
48
+ const installMessage = pkgName === UPGRADABLE_CLI_NAMES.cli ? `Please install the latest Shopify CLI version with \`${packageManager === "yarn" ? `yarn global add ${UPGRADABLE_CLI_NAMES.cli}` : `${packageManager} install -g ${UPGRADABLE_CLI_NAMES.cli}`}\` and try again.` : `Please use the latest version with \`${packageManager} create @shopify/hydrogen@latest\``;
49
+ renderInfo({
50
+ headline: "Upgrade available",
51
+ body: `Version ${newVersionAvailable} of ${pkgName} is now available.
52
+ You are currently running v${currentVersion}.
53
+
54
+ ` + installMessage,
55
+ reference
56
+ });
57
+ return { currentVersion, newVersion: newVersionAvailable };
58
+ };
59
+ }
60
+
61
+ export { UPGRADABLE_CLI_NAMES, checkCurrentCLIVersion };
@@ -4,6 +4,7 @@ import { checkIfIgnoredInGitRepository } from '@shopify/cli-kit/node/git';
4
4
  import { renderWarning } from '@shopify/cli-kit/node/ui';
5
5
  import { AbortError } from '@shopify/cli-kit/node/error';
6
6
  import { packageManagers } from './package-managers.js';
7
+ import { isHydrogenMonorepo } from './build.js';
7
8
 
8
9
  function missingLockfileWarning(shouldExit) {
9
10
  const headline = "No lockfile found";
@@ -53,8 +54,7 @@ function lockfileIgnoredWarning(lockfile) {
53
54
  renderWarning({ headline, body, nextSteps });
54
55
  }
55
56
  async function checkLockfileStatus(directory, shouldExit = false) {
56
- if (process.env.LOCAL_DEV)
57
- return;
57
+ if (isHydrogenMonorepo && !process.env.SHOPIFY_UNIT_TEST) return;
58
58
  const foundPackageManagers = [];
59
59
  for (const packageManager of packageManagers) {
60
60
  if (await fileExists(resolvePath(directory, packageManager.lockfile))) {
@@ -8,7 +8,7 @@ import { checkLockfileStatus } from '../check-lockfile.js';
8
8
  import { findMissingRoutes } from '../missing-routes.js';
9
9
  import { muteRemixLogs, createRemixLogger } from '../log.js';
10
10
  import { codegen } from '../codegen.js';
11
- import { buildBundleAnalysis, getBundleAnalysisSummary } from '../bundle/analyzer.js';
11
+ import { classicBuildBundleAnalysis, classicGetBundleAnalysisSummary } from '../bundle/analyzer.js';
12
12
  import { isCI } from '../is-ci.js';
13
13
  import { importLocal } from '../import-utils.js';
14
14
 
@@ -76,7 +76,7 @@ async function runClassicCompilerBuild({
76
76
  ]);
77
77
  if (process.env.NODE_ENV !== "development") {
78
78
  console.timeEnd(LOG_WORKER_BUILT);
79
- const bundleAnalysisPath = await buildBundleAnalysis(buildPath);
79
+ const bundleAnalysisPath = await classicBuildBundleAnalysis(buildPath);
80
80
  const sizeMB = await fileSize(buildPathWorkerFile) / (1024 * 1024);
81
81
  const formattedSize = colors.yellow(sizeMB.toFixed(2) + " MB");
82
82
  outputInfo(
@@ -86,7 +86,7 @@ async function runClassicCompilerBuild({
86
86
  );
87
87
  if (bundleStats && bundleAnalysisPath) {
88
88
  outputInfo(
89
- outputContent`${await getBundleAnalysisSummary(buildPathWorkerFile) || "\n"}\n │\n └─── ${outputToken.link(
89
+ outputContent`${await classicGetBundleAnalysisSummary(buildPathWorkerFile) || "\n"}\n │\n └─── ${outputToken.link(
90
90
  "Complete analysis: " + bundleAnalysisPath,
91
91
  bundleAnalysisPath
92
92
  )}\n\n`
@@ -39,12 +39,9 @@ async function runClassicCompilerDev({
39
39
  cliConfig,
40
40
  verbose
41
41
  }) {
42
- if (!process.env.NODE_ENV)
43
- process.env.NODE_ENV = "development";
44
- if (verbose)
45
- setH2OVerbose();
46
- if (!isH2Verbose())
47
- muteDevLogs();
42
+ if (!process.env.NODE_ENV) process.env.NODE_ENV = "development";
43
+ if (verbose) setH2OVerbose();
44
+ if (!isH2Verbose()) muteDevLogs();
48
45
  const { root, publicPath, buildPathClient, buildPathWorkerFile } = getProjectPaths(appPath);
49
46
  const copyFilesPromise = copyPublicFiles(publicPath, buildPathClient);
50
47
  const cliCommandPromise = getCliCommand(root);
@@ -111,8 +108,7 @@ async function runClassicCompilerDev({
111
108
  let miniOxygen;
112
109
  let codegenProcess;
113
110
  async function safeStartMiniOxygen() {
114
- if (miniOxygen)
115
- return;
111
+ if (miniOxygen) return;
116
112
  const { allVariables, logInjectedVariables } = await envPromise;
117
113
  miniOxygen = await startMiniOxygen(
118
114
  {
@@ -183,8 +179,7 @@ async function runClassicCompilerDev({
183
179
  } else if (!skipRebuildLogs) {
184
180
  skipRebuildLogs = false;
185
181
  console.timeEnd(LOG_REBUILT);
186
- if (!miniOxygen)
187
- console.log("");
182
+ if (!miniOxygen) console.log("");
188
183
  }
189
184
  if (!miniOxygen && !await serverBundleExists()) {
190
185
  return renderFatalError({
@@ -22,8 +22,7 @@ function normalizeCodegenError(errorMessage, rootDirectory) {
22
22
  const parsedError = errorMessage.split("AbortError: ")[1] ?? "";
23
23
  const message2 = parsedError.split("\n")[0];
24
24
  const details2 = parsedError.match(/tryMessage: '(.*)',$/m)?.[1];
25
- if (message2)
26
- return { message: message2, details: details2 };
25
+ if (message2) return { message: message2, details: details2 };
27
26
  }
28
27
  const [first = "", ...rest] = errorMessage.replaceAll("[FAILED]", "").replace(/\s{2,}/g, "\n").replace(/\n,\n/, "\n").trim().split("\n");
29
28
  const message = "[Codegen] " + first;
@@ -66,15 +65,11 @@ function spawnCodegenProcess({
66
65
  const child = spawn(command, args, { stdio: ["inherit", "ignore", "pipe"] });
67
66
  child.stderr.on("data", (data) => {
68
67
  const dataString = typeof data === "string" ? data : data?.toString?.("utf8") ?? "";
69
- if (!dataString)
70
- return;
68
+ if (!dataString) return;
71
69
  const { message, details } = normalizeCodegenError(dataString, rootDirectory);
72
- if (/`punycode`/.test(message))
73
- return;
74
- if (/\.body\[\d\]/.test(message))
75
- return;
76
- if (/console\.time(End)?\(\)/.test(message))
77
- return;
70
+ if (/`punycode`/.test(message)) return;
71
+ if (/\.body\[\d\]/.test(message)) return;
72
+ if (/console\.time(End)?\(\)/.test(message)) return;
78
73
  console.log("");
79
74
  renderWarning({ headline: message, body: details });
80
75
  });
@@ -90,8 +85,7 @@ function spawnCodegenProcess({
90
85
  }
91
86
  function codegen(options) {
92
87
  return generateTypes(options).catch((error) => {
93
- if (error instanceof AbortError)
94
- throw error;
88
+ if (error instanceof AbortError) throw error;
95
89
  const { message, details } = normalizeCodegenError(
96
90
  error.message,
97
91
  options.rootDirectory
@@ -117,8 +111,7 @@ async function generateTypes({
117
111
  const { config: codegenConfig } = (
118
112
  // Load <root>/codegen.ts if available
119
113
  await loadCodegenConfig({
120
- configFilePath,
121
- searchPlaces: [dirs.rootDirectory]
114
+ configFilePath: configFilePath ?? dirs.rootDirectory
122
115
  }) || // Fall back to default config
123
116
  await generateDefaultConfig(dirs, forceSfapiVersion)
124
117
  );
@@ -223,8 +216,7 @@ async function generateDefaultConfig({
223
216
  };
224
217
  }
225
218
  function findGqlProject(schemaFilepath, gqlConfig) {
226
- if (!gqlConfig)
227
- return;
219
+ if (!gqlConfig) return;
228
220
  const schemaFilename = basename(schemaFilepath);
229
221
  return Object.values(gqlConfig.projects || {}).find(
230
222
  (project) => typeof project.schema === "string" && project.schema.endsWith(schemaFilename)
package/dist/lib/defer.js CHANGED
@@ -2,13 +2,11 @@ function deferPromise() {
2
2
  const deferred = { state: "pending" };
3
3
  deferred.promise = new Promise((resolve, reject) => {
4
4
  deferred.resolve = (value) => {
5
- if (deferred.state === "pending")
6
- deferred.state = "resolved";
5
+ if (deferred.state === "pending") deferred.state = "resolved";
7
6
  return resolve(value);
8
7
  };
9
8
  deferred.reject = (reason) => {
10
- if (deferred.state === "pending")
11
- deferred.state = "rejected";
9
+ if (deferred.state === "pending") deferred.state = "rejected";
12
10
  return reject(reason);
13
11
  };
14
12
  });
@@ -76,10 +76,8 @@ async function getRemoteVariables(root, envHandle, envBranch) {
76
76
  const remoteVariables = {};
77
77
  const remoteSecrets = {};
78
78
  for (const { key, value, isSecret } of envVariables) {
79
- if (isSecret)
80
- remoteSecrets[key] = value;
81
- else
82
- remoteVariables[key] = value;
79
+ if (isSecret) remoteSecrets[key] = value;
80
+ else remoteVariables[key] = value;
83
81
  }
84
82
  return { remoteVariables, remoteSecrets };
85
83
  }