@shopify/cli-hydrogen 11.1.8 → 11.1.10

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 (37) hide show
  1. package/dist/assets/hydrogen/starter/CHANGELOG.md +30 -0
  2. package/dist/assets/hydrogen/starter/app/components/MockShopNotice.tsx +20 -0
  3. package/dist/assets/hydrogen/starter/app/entry.client.tsx +2 -3
  4. package/dist/assets/hydrogen/starter/app/routes/_index.tsx +4 -5
  5. package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +12 -12
  6. package/dist/assets/hydrogen/starter/app/routes/account.tsx +4 -7
  7. package/dist/assets/hydrogen/starter/app/routes/blogs.$blogHandle._index.tsx +2 -9
  8. package/dist/assets/hydrogen/starter/app/routes/blogs._index.tsx +1 -4
  9. package/dist/assets/hydrogen/starter/app/routes/cart.tsx +1 -5
  10. package/dist/assets/hydrogen/starter/app/routes/collections.all.tsx +1 -3
  11. package/dist/assets/hydrogen/starter/app/routes/pages.$handle.tsx +2 -8
  12. package/dist/assets/hydrogen/starter/app/routes/policies.$handle.tsx +1 -4
  13. package/dist/assets/hydrogen/starter/app/routes/policies._index.tsx +1 -1
  14. package/dist/assets/hydrogen/starter/app/routes/products.$handle.tsx +2 -9
  15. package/dist/assets/hydrogen/starter/app/routes/search.tsx +18 -12
  16. package/dist/assets/hydrogen/starter/app/styles/app.css +51 -0
  17. package/dist/assets/hydrogen/starter/guides/predictiveSearch/predictiveSearch.md +3 -3
  18. package/dist/assets/hydrogen/starter/guides/search/search.md +1 -1
  19. package/dist/assets/hydrogen/starter/package.json +9 -9
  20. package/dist/commands/hydrogen/dev.js +0 -4
  21. package/dist/commands/hydrogen/init.d.ts +2 -4
  22. package/dist/commands/hydrogen/init.js +2 -8
  23. package/dist/commands/hydrogen/preview.js +1 -1
  24. package/dist/commands/hydrogen/setup/css.js +1 -1
  25. package/dist/commands/hydrogen/setup/vite.js +1 -1
  26. package/dist/commands/hydrogen/setup.js +31 -33
  27. package/dist/commands/hydrogen/upgrade.js +7 -0
  28. package/dist/lib/build.js +4 -5
  29. package/dist/lib/codegen.js +2 -2
  30. package/dist/lib/format-code.js +3 -3
  31. package/dist/lib/mini-oxygen/workerd.js +3 -5
  32. package/dist/lib/onboarding/common.js +19 -26
  33. package/dist/lib/onboarding/local.js +46 -59
  34. package/dist/lib/template-pack.js +84 -0
  35. package/oclif.manifest.json +2 -9
  36. package/package.json +18 -15
  37. package/dist/lib/react-router-version-check.js +0 -82
@@ -3,7 +3,7 @@ import { AbortController } from '@shopify/cli-kit/node/abort';
3
3
  import { renderTasks } from '@shopify/cli-kit/node/ui';
4
4
  import { resolvePath, basename, joinPath } from '@shopify/cli-kit/node/path';
5
5
  import { fileExists, glob, copyFile } from '@shopify/cli-kit/node/fs';
6
- import { overrideFlag, commonFlags, flagsToCamelObject } from '../../lib/flags.js';
6
+ import { commonFlags, overrideFlag, flagsToCamelObject } from '../../lib/flags.js';
7
7
  import { renderI18nPrompt, setupI18nStrategy } from '../../lib/setups/i18n/index.js';
8
8
  import { getRemixConfig } from '../../lib/remix-config.js';
9
9
  import { handleRouteGeneration, generateProjectEntries, handleCliShortcut, renderProjectReady } from '../../lib/onboarding/common.js';
@@ -49,39 +49,37 @@ async function runSetup(options) {
49
49
  extraChoices: { none: "Set up later" }
50
50
  });
51
51
  const i18n = i18nStrategy === "none" ? void 0 : i18nStrategy;
52
- const { needsRouteGeneration, setupRoutes } = await handleRouteGeneration(controller);
52
+ const { setupRoutes } = handleRouteGeneration(controller);
53
53
  let routes;
54
- if (needsRouteGeneration) {
55
- const templateRoot = await getTemplateAppFile("..");
56
- const [typescript, dtsFiles] = await Promise.all([
57
- fileExists(joinPath(rootDirectory, "tsconfig.json")),
58
- glob("*.d.ts", { cwd: templateRoot })
59
- ]);
60
- backgroundWorkPromise = backgroundWorkPromise.then(
61
- () => Promise.all([
62
- ...dtsFiles.map(
63
- (filename) => copyFile(
64
- joinPath(templateRoot, filename),
65
- resolvePath(rootDirectory, filename)
66
- )
67
- ),
68
- // Copy app entries
69
- generateProjectEntries({
70
- rootDirectory,
71
- appDirectory,
72
- typescript
73
- })
74
- ])
75
- ).then(async () => {
76
- routes = await setupRoutes(rootDirectory, typescript ? "ts" : "js", {
77
- i18nStrategy: i18n,
78
- // User might have added files before running this command.
79
- // We should overwrite them to ensure the routes are set up correctly.
80
- // Relies on Git to restore the files if needed.
81
- overwriteFileDeps: true
82
- });
54
+ const templateRoot = await getTemplateAppFile("..");
55
+ const [typescript, dtsFiles] = await Promise.all([
56
+ fileExists(joinPath(rootDirectory, "tsconfig.json")),
57
+ glob("*.d.ts", { cwd: templateRoot })
58
+ ]);
59
+ backgroundWorkPromise = backgroundWorkPromise.then(
60
+ () => Promise.all([
61
+ ...dtsFiles.map(
62
+ (filename) => copyFile(
63
+ joinPath(templateRoot, filename),
64
+ resolvePath(rootDirectory, filename)
65
+ )
66
+ ),
67
+ // Copy app entries
68
+ generateProjectEntries({
69
+ rootDirectory,
70
+ appDirectory,
71
+ typescript
72
+ })
73
+ ])
74
+ ).then(async () => {
75
+ routes = await setupRoutes(rootDirectory, typescript ? "ts" : "js", {
76
+ i18nStrategy: i18n,
77
+ // User might have added files before running this command.
78
+ // We should overwrite them to ensure the routes are set up correctly.
79
+ // Relies on Git to restore the files if needed.
80
+ overwriteFileDeps: true
83
81
  });
84
- }
82
+ });
85
83
  if (i18n) {
86
84
  backgroundWorkPromise = backgroundWorkPromise.then(
87
85
  () => setupI18nStrategy(i18n, { rootDirectory })
@@ -93,7 +91,7 @@ async function runSetup(options) {
93
91
  cliCommand,
94
92
  options.shortcut
95
93
  );
96
- if (!i18n && !needsRouteGeneration && !createShortcut) return;
94
+ if (!i18n && !createShortcut) return;
97
95
  if (createShortcut) {
98
96
  backgroundWorkPromise = backgroundWorkPromise.then(async () => {
99
97
  if (await createShortcut()) {
@@ -859,6 +859,13 @@ async function displayDevUpgradeNotice({
859
859
  const { currentVersion, currentDependencies } = await getHydrogenVersion({
860
860
  appPath
861
861
  });
862
+ if (currentVersion.startsWith("workspace:")) {
863
+ renderInfo({
864
+ headline: "Using monorepo @shopify/hydrogen dependency",
865
+ body: "This project uses the workspace protocol for @shopify/hydrogen, so upgrade notices are skipped during local monorepo development."
866
+ });
867
+ return;
868
+ }
862
869
  const isPrerelease = semver.prerelease(currentVersion);
863
870
  if (isPrerelease || /^[a-z]+$/i.test(currentVersion)) {
864
871
  return;
package/dist/lib/build.js CHANGED
@@ -69,12 +69,11 @@ function getSkeletonNodeModules() {
69
69
  return joinPath(getSkeletonSourceDir(), "node_modules");
70
70
  }
71
71
  async function getRepoNodeModules() {
72
- const { stdout } = await execAsync("npm root");
73
- let nodeModulesPath = stdout.trim();
74
- if (!nodeModulesPath && isHydrogenMonorepo) {
75
- nodeModulesPath = joinPath(dirname(monorepoPackagesPath), "node_modules");
72
+ if (isHydrogenMonorepo) {
73
+ return getSkeletonNodeModules();
76
74
  }
77
- return nodeModulesPath;
75
+ const { stdout } = await execAsync("npm root");
76
+ return stdout.trim();
78
77
  }
79
78
 
80
79
  export { ASSETS_DIR_PREFIX, ASSETS_STARTER_DIR, ASSETS_STARTER_DIR_ROUTES, getAssetsDir, getPkgJsonPath, getRepoNodeModules, getSkeletonNodeModules, getSkeletonSourceDir, getStarterDir, getTemplateAppFile, hydrogenPackagesPath, isHydrogenMonorepo };
@@ -2,7 +2,7 @@ import { spawn } from 'node:child_process';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { getCodeFormatOptions, formatCode } from './format-code.js';
4
4
  import { renderInfo, renderWarning } from '@shopify/cli-kit/node/ui';
5
- import { relativePath, resolvePath, joinPath, basename } from '@shopify/cli-kit/node/path';
5
+ import { relativePath, joinPath, resolvePath, basename } from '@shopify/cli-kit/node/path';
6
6
  import { AbortError } from '@shopify/cli-kit/node/error';
7
7
  import { importLocal } from './import-utils.js';
8
8
 
@@ -283,7 +283,7 @@ function findGqlProject(schemaFilepath, gqlConfig) {
283
283
  );
284
284
  }
285
285
  async function addHooksToHydrogenOptions(codegenConfig, { rootDirectory }) {
286
- const name = Symbol.for("name");
286
+ const name = /* @__PURE__ */ Symbol.for("name");
287
287
  const hydrogenProjectsOptions = Object.values(codegenConfig.generates).filter(
288
288
  (value) => {
289
289
  const foundPreset = (Array.isArray(value) ? value[0] : value)?.preset;
@@ -1,5 +1,5 @@
1
1
  import { extname } from '@shopify/cli-kit/node/path';
2
- import * as prettier from 'prettier';
2
+ import { resolveConfig, format } from 'prettier';
3
3
  import * as FS from 'fs/promises';
4
4
  import * as Path from 'path';
5
5
 
@@ -12,14 +12,14 @@ const DEFAULT_PRETTIER_CONFIG = {
12
12
  async function getCodeFormatOptions(filePath = process.cwd()) {
13
13
  const pathToUse = (await FS.lstat(filePath)).isFile() ? filePath : Path.resolve(filePath, "prettier.file");
14
14
  try {
15
- return await prettier.resolveConfig(pathToUse) || DEFAULT_PRETTIER_CONFIG;
15
+ return await resolveConfig(pathToUse) || DEFAULT_PRETTIER_CONFIG;
16
16
  } catch {
17
17
  return DEFAULT_PRETTIER_CONFIG;
18
18
  }
19
19
  }
20
20
  async function formatCode(content, config = DEFAULT_PRETTIER_CONFIG, filePath = "") {
21
21
  const ext = extname(filePath);
22
- return prettier.format(content, {
22
+ return format(content, {
23
23
  // Specify the TypeScript parser for ts/tsx files. Otherwise
24
24
  // we need to use the babel parser instead of the default parser,
25
25
  // because prettier will print a warning.
@@ -1,13 +1,13 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { resolvePath, dirname } from '@shopify/cli-kit/node/path';
3
- import { readFile, createFileReadStream } from '@shopify/cli-kit/node/fs';
3
+ import { createFileReadStream, readFile } from '@shopify/cli-kit/node/fs';
4
4
  import { renderSuccess } from '@shopify/cli-kit/node/ui';
5
5
  import { outputNewline } from '@shopify/cli-kit/node/output';
6
6
  import { AbortError } from '@shopify/cli-kit/node/error';
7
7
  import colors from '@shopify/cli-kit/node/colors';
8
8
  import { handleMiniOxygenImportFail, SUBREQUEST_PROFILER_ENDPOINT, logRequestLine } from './common.js';
9
9
  import { TUNNEL_DOMAIN, getUtilityBannerlines, getDebugBannerLine } from '../dev-shared.js';
10
- import { setConstructors, handleDebugNetworkRequest, createLogRequestEvent, H2O_BINDING_NAME } from '../request-events.js';
10
+ import { setConstructors, handleDebugNetworkRequest, H2O_BINDING_NAME, createLogRequestEvent } from '../request-events.js';
11
11
  import { importLocal } from '../import-utils.js';
12
12
 
13
13
  async function startWorkerdServer({
@@ -28,9 +28,7 @@ async function startWorkerdServer({
28
28
  setConstructors({ Response });
29
29
  async function handleCustomerAccountSchema() {
30
30
  const require2 = createRequire(import.meta.url);
31
- const filePath = require2.resolve(
32
- "@shopify/hydrogen/customer-account.schema.json"
33
- );
31
+ const filePath = require2.resolve("@shopify/hydrogen/customer-account.schema.json");
34
32
  return new Response(createFileReadStream(filePath), {
35
33
  headers: { "Content-Type": "application/json" }
36
34
  });
@@ -1,6 +1,6 @@
1
1
  import { symlink, readdir } from 'node:fs/promises';
2
2
  import { packageManagerFromUserAgent, installNodeModules } from '@shopify/cli-kit/node/node-package-manager';
3
- import { renderConfirmationPrompt, renderInfo, renderTextPrompt, renderSelectPrompt, renderWarning, renderSuccess, renderFatalError } from '@shopify/cli-kit/node/ui';
3
+ import { renderConfirmationPrompt, renderInfo, renderTextPrompt, renderSelectPrompt, renderFatalError, renderWarning, renderSuccess } from '@shopify/cli-kit/node/ui';
4
4
  import { hyphenate, capitalize } from '@shopify/cli-kit/common/string';
5
5
  import { joinPath, resolvePath, basename } from '@shopify/cli-kit/node/path';
6
6
  import { initializeGitRepository, addAllToGitFromDirectory, createGitCommit } from '@shopify/cli-kit/node/git';
@@ -15,7 +15,7 @@ import { titleize } from '../string.js';
15
15
  import { ALIAS_NAME, createPlatformShortcut } from '../shell.js';
16
16
  import { transpileProject } from '../transpile/index.js';
17
17
  import { renderCssPrompt, setupCssStrategy, CSS_STRATEGY_NAME_MAP } from '../setups/css/index.js';
18
- import { renderRoutePrompt, generateRoutes, generateProjectFile } from '../setups/routes/generate.js';
18
+ import { generateRoutes, generateProjectFile } from '../setups/routes/generate.js';
19
19
  import { execAsync } from '../process.js';
20
20
  import { getStorefronts } from '../graphql/admin/link-storefront.js';
21
21
  import { isHydrogenMonorepo, getSkeletonSourceDir, getRepoNodeModules } from '../build.js';
@@ -42,32 +42,25 @@ async function handleI18n(controller, cliCommand, flagI18n) {
42
42
  }
43
43
  };
44
44
  }
45
- async function handleRouteGeneration(controller, flagRoutes) {
46
- const routesToScaffold = flagRoutes === true ? "all" : flagRoutes === false ? [] : await renderRoutePrompt({
47
- abortSignal: controller.signal
48
- });
49
- const needsRouteGeneration = routesToScaffold === "all" || routesToScaffold.length > 0;
45
+ function handleRouteGeneration(controller) {
50
46
  return {
51
- needsRouteGeneration,
52
47
  setupRoutes: async (directory, language, options) => {
53
- if (needsRouteGeneration) {
54
- const result = await generateRoutes(
55
- {
56
- routeName: routesToScaffold,
57
- directory,
58
- force: true,
59
- typescript: language === "ts",
60
- localePrefix: options?.i18nStrategy === "subfolders" ? "locale" : false,
61
- signal: controller.signal,
62
- ...options
63
- },
64
- {
65
- rootDirectory: directory,
66
- appDirectory: joinPath(directory, "app")
67
- }
68
- );
69
- return result.routeGroups;
70
- }
48
+ const result = await generateRoutes(
49
+ {
50
+ routeName: "all",
51
+ directory,
52
+ force: true,
53
+ typescript: language === "ts",
54
+ localePrefix: options?.i18nStrategy === "subfolders" ? "locale" : false,
55
+ signal: controller.signal,
56
+ ...options
57
+ },
58
+ {
59
+ rootDirectory: directory,
60
+ appDirectory: joinPath(directory, "app")
61
+ }
62
+ );
63
+ return result.routeGroups;
71
64
  }
72
65
  };
73
66
  }
@@ -2,8 +2,7 @@ import { cp } from 'node:fs/promises';
2
2
  import { writeFile } from '@shopify/cli-kit/node/fs';
3
3
  import { relativePath, joinPath } from '@shopify/cli-kit/node/path';
4
4
  import { hyphenate } from '@shopify/cli-kit/common/string';
5
- import colors from '@shopify/cli-kit/node/colors';
6
- import { renderSelectPrompt, renderSuccess, renderConfirmationPrompt, renderTasks } from '@shopify/cli-kit/node/ui';
5
+ import { renderSelectPrompt, renderSuccess, renderTasks } from '@shopify/cli-kit/node/ui';
7
6
  import { handleStorefrontLink, handleProjectLocation, createAbortHandler, generateProjectEntries, handleLanguage, createInitialCommit, handleCssStrategy, commitAll, handleDependencies, handleCliShortcut, handleI18n, handleRouteGeneration, renderProjectReady } from './common.js';
8
7
  import { createStorefront } from '../graphql/admin/create-storefront.js';
9
8
  import { waitForJob } from '../graphql/admin/fetch-job.js';
@@ -49,7 +48,7 @@ async function setupLocalStarterTemplate(options, controller) {
49
48
  {
50
49
  force: true,
51
50
  recursive: true,
52
- filter: (filepath) => !/^(app\/|dist\/|node_modules\/|server\.ts|\.shopify\/)/i.test(
51
+ filter: (filepath) => !/^(app(\/|$)|dist(\/|$)|node_modules(\/|$)|server\.ts$|\.shopify(\/|$))/i.test(
53
52
  relativePath(templateDir, filepath)
54
53
  )
55
54
  }
@@ -217,65 +216,53 @@ async function setupLocalStarterTemplate(options, controller) {
217
216
  ]
218
217
  });
219
218
  }
220
- const continueWithSetup = (options.i18n ?? options.routes) !== void 0 || await renderConfirmationPrompt({
221
- message: "Do you want to scaffold routes and core functionality?",
222
- confirmationMessage: "Yes, set up now",
223
- cancellationMessage: "No, set up later " + colors.dim(`(run \`${setupSummary.cliCommand} setup\`)`),
224
- abortSignal: controller.signal
225
- });
226
- if (continueWithSetup) {
227
- const { i18nStrategy, setupI18n } = await handleI18n(
228
- controller,
229
- setupSummary.cliCommand,
230
- options.i18n
231
- );
232
- const { setupRoutes } = await handleRouteGeneration(
233
- controller,
234
- options.routes ?? true
235
- // TODO: Remove default value when multi-select UI component is available
236
- );
237
- setupSummary.i18n = i18nStrategy;
238
- backgroundWorkPromise = backgroundWorkPromise.then(async () => {
239
- await setupI18n({
240
- rootDirectory: project.directory,
241
- contextCreate: language === "ts" ? "app/lib/context.ts" : "app/lib/context.js"
242
- }).then(
243
- () => options.git ? commitAll(
244
- project.directory,
245
- `Setup markets support using ${i18nStrategy}`
246
- ) : void 0
247
- ).catch((error) => {
248
- setupSummary.i18nError = error;
249
- });
250
- await setupRoutes(project.directory, language, {
251
- i18nStrategy,
252
- // The init process might have added and modified files. Do not overwrite them.
253
- // E.g. CSS imports might have been added to the root.
254
- overwriteFileDeps: false
255
- }).then(async (routes) => {
256
- setupSummary.routes = routes;
257
- if (language === "ts" && setupSummary.depsInstalled) {
258
- try {
259
- await execAsync("npx react-router typegen", {
260
- cwd: project.directory
261
- });
262
- } catch (error) {
263
- outputWarn(
264
- "Failed to generate React Router types after route generation. You may need to run `npx react-router typegen` manually."
265
- );
266
- }
267
- }
268
- if (options.git && routes) {
269
- return commitAll(
270
- project.directory,
271
- `Generate routes for core functionality`
219
+ const { i18nStrategy, setupI18n } = await handleI18n(
220
+ controller,
221
+ setupSummary.cliCommand,
222
+ options.i18n
223
+ );
224
+ const { setupRoutes } = handleRouteGeneration(controller);
225
+ setupSummary.i18n = i18nStrategy;
226
+ backgroundWorkPromise = backgroundWorkPromise.then(async () => {
227
+ await setupI18n({
228
+ rootDirectory: project.directory,
229
+ contextCreate: language === "ts" ? "app/lib/context.ts" : "app/lib/context.js"
230
+ }).then(
231
+ () => options.git ? commitAll(
232
+ project.directory,
233
+ `Setup markets support using ${i18nStrategy}`
234
+ ) : void 0
235
+ ).catch((error) => {
236
+ setupSummary.i18nError = error;
237
+ });
238
+ await setupRoutes(project.directory, language, {
239
+ i18nStrategy,
240
+ // The init process might have added and modified files. Do not overwrite them.
241
+ // E.g. CSS imports might have been added to the root.
242
+ overwriteFileDeps: false
243
+ }).then(async (routes) => {
244
+ setupSummary.routes = routes;
245
+ if (language === "ts" && setupSummary.depsInstalled) {
246
+ try {
247
+ await execAsync("npx react-router typegen", {
248
+ cwd: project.directory
249
+ });
250
+ } catch (error) {
251
+ outputWarn(
252
+ "Failed to generate React Router types after route generation. You may need to run `npx react-router typegen` manually."
272
253
  );
273
254
  }
274
- }).catch((error) => {
275
- setupSummary.routesError = error;
276
- });
255
+ }
256
+ if (options.git && routes) {
257
+ return commitAll(
258
+ project.directory,
259
+ `Generate routes for core functionality`
260
+ );
261
+ }
262
+ }).catch((error) => {
263
+ setupSummary.routesError = error;
277
264
  });
278
- }
265
+ });
279
266
  await renderTasks(tasks);
280
267
  if (options.git) {
281
268
  await commitAll(project.directory, "Lockfile");
@@ -0,0 +1,84 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { readFile, writeFile, mkdtemp, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+
6
+ const DEPENDENCY_SECTIONS = [
7
+ "dependencies",
8
+ "devDependencies",
9
+ "peerDependencies",
10
+ "optionalDependencies"
11
+ ];
12
+ function hasReplaceableProtocol(version) {
13
+ return version.startsWith("workspace:") || version.startsWith("catalog:");
14
+ }
15
+ async function getPackedTemplatePackageJson(sourceTemplateDir) {
16
+ const tempDir = await mkdtemp(join(tmpdir(), "hydrogen-template-pack-"));
17
+ try {
18
+ const rawPackResult = execFileSync(
19
+ "pnpm",
20
+ ["pack", "--pack-destination", tempDir, "--json"],
21
+ {
22
+ cwd: sourceTemplateDir,
23
+ encoding: "utf8"
24
+ }
25
+ );
26
+ const parsedResult = JSON.parse(rawPackResult.trim());
27
+ const packedTarball = Array.isArray(parsedResult) ? parsedResult[0]?.filename : parsedResult.filename;
28
+ if (!packedTarball) {
29
+ throw new Error("pnpm pack did not return a tarball filename.");
30
+ }
31
+ const packedManifestRaw = execFileSync(
32
+ "tar",
33
+ [
34
+ "-xOf",
35
+ packedTarball.startsWith("/") ? packedTarball : join(tempDir, packedTarball),
36
+ "package/package.json"
37
+ ],
38
+ { encoding: "utf8" }
39
+ );
40
+ return JSON.parse(packedManifestRaw);
41
+ } finally {
42
+ await rm(tempDir, { recursive: true, force: true });
43
+ }
44
+ }
45
+ function replaceWorkspaceProtocolVersionsInPackageJson({
46
+ packedManifest,
47
+ targetPackageJson
48
+ }) {
49
+ for (const section of DEPENDENCY_SECTIONS) {
50
+ const targetDeps = targetPackageJson[section];
51
+ if (!targetDeps) continue;
52
+ for (const [name, version] of Object.entries(targetDeps)) {
53
+ if (!hasReplaceableProtocol(version)) continue;
54
+ const packedVersion = packedManifest[section]?.[name];
55
+ if (!packedVersion) {
56
+ throw new Error(
57
+ `Unable to resolve ${name} from ${section} in packed template manifest.`
58
+ );
59
+ }
60
+ targetDeps[name] = packedVersion;
61
+ }
62
+ }
63
+ }
64
+ async function replaceWorkspaceProtocolVersions({
65
+ sourceTemplateDir,
66
+ targetTemplateDir
67
+ }) {
68
+ const packedManifest = await getPackedTemplatePackageJson(sourceTemplateDir);
69
+ const targetPackageJsonPath = join(targetTemplateDir, "package.json");
70
+ const targetPackageJson = JSON.parse(
71
+ await readFile(targetPackageJsonPath, "utf8")
72
+ );
73
+ replaceWorkspaceProtocolVersionsInPackageJson({
74
+ packedManifest,
75
+ targetPackageJson
76
+ });
77
+ await writeFile(
78
+ targetPackageJsonPath,
79
+ `${JSON.stringify(targetPackageJson, null, 2)}
80
+ `
81
+ );
82
+ }
83
+
84
+ export { replaceWorkspaceProtocolVersions };
@@ -1048,13 +1048,6 @@
1048
1048
  "allowNo": true,
1049
1049
  "type": "boolean"
1050
1050
  },
1051
- "routes": {
1052
- "description": "Generate routes for all pages.",
1053
- "env": "SHOPIFY_HYDROGEN_FLAG_ROUTES",
1054
- "name": "routes",
1055
- "allowNo": true,
1056
- "type": "boolean"
1057
- },
1058
1051
  "git": {
1059
1052
  "description": "Init Git and create initial commits.",
1060
1053
  "env": "SHOPIFY_HYDROGEN_FLAG_GIT",
@@ -1063,7 +1056,7 @@
1063
1056
  "type": "boolean"
1064
1057
  },
1065
1058
  "quickstart": {
1066
- "description": "Scaffolds a new Hydrogen project with a set of sensible defaults. Equivalent to `shopify hydrogen init --path hydrogen-quickstart --mock-shop --language js --shortcut --routes --markets none`",
1059
+ "description": "Scaffolds a new Hydrogen project with a set of sensible defaults. Equivalent to `shopify hydrogen init --path hydrogen-quickstart --mock-shop --language js --shortcut --markets none`",
1067
1060
  "env": "SHOPIFY_HYDROGEN_FLAG_QUICKSTART",
1068
1061
  "name": "quickstart",
1069
1062
  "allowNo": false,
@@ -1683,5 +1676,5 @@
1683
1676
  ]
1684
1677
  }
1685
1678
  },
1686
- "version": "11.1.8"
1679
+ "version": "11.1.10"
1687
1680
  }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public",
5
5
  "@shopify:registry": "https://registry.npmjs.org"
6
6
  },
7
- "version": "11.1.8",
7
+ "version": "11.1.10",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "repository": {
@@ -12,18 +12,12 @@
12
12
  "url": "git+https://github.com/Shopify/hydrogen.git",
13
13
  "directory": "packages/cli-hydrogen"
14
14
  },
15
- "scripts": {
16
- "build": "tsup && node scripts/build-check.mjs",
17
- "dev": "tsup --watch ./src --watch ../../templates/skeleton",
18
- "typecheck": "tsc --noEmit",
19
- "generate:manifest": "node scripts/generate-manifest.mjs",
20
- "test": "cross-env SHOPIFY_UNIT_TEST=1 LANG=en-US.UTF-8 vitest run --test-timeout=60000",
21
- "test:watch": "cross-env SHOPIFY_UNIT_TEST=1 LANG=en-US.UTF-8 vitest --test-timeout=60000"
22
- },
23
15
  "devDependencies": {
24
16
  "@react-router/dev": "7.12.0",
25
17
  "@types/diff": "^5.0.2",
26
18
  "@types/gunzip-maybe": "^1.4.0",
19
+ "@types/node": "^22",
20
+ "esbuild": "^0.25.0",
27
21
  "@types/prettier": "^2.7.2",
28
22
  "@types/source-map-support": "^0.5.10",
29
23
  "@types/tar-fs": "^2.0.1",
@@ -46,10 +40,11 @@
46
40
  "chokidar": "3.5.3",
47
41
  "cli-truncate": "^4.0.0",
48
42
  "diff": "^5.1.0",
43
+ "esbuild": "^0.25.12",
49
44
  "get-east-asian-width": "^1.3.0",
50
45
  "get-port": "^7.0.0",
51
46
  "gunzip-maybe": "^1.4.2",
52
- "prettier": "^2.8.4",
47
+ "prettier": "^3.4.2",
53
48
  "semver": "^7.7.1",
54
49
  "source-map": "^0.7.4",
55
50
  "source-map-support": "^0.5.21",
@@ -61,10 +56,10 @@
61
56
  "peerDependencies": {
62
57
  "@graphql-codegen/cli": "^5.0.2",
63
58
  "@react-router/dev": "7.12.0",
64
- "@shopify/hydrogen-codegen": "^0.3.3",
65
- "@shopify/mini-oxygen": "^4.0.0",
66
59
  "graphql-config": "^5.0.3",
67
- "vite": "^5.1.0 || ^6.2.0"
60
+ "vite": "^5.1.0 || ^6.2.0",
61
+ "@shopify/hydrogen-codegen": "0.3.3",
62
+ "@shopify/mini-oxygen": "4.0.1"
68
63
  },
69
64
  "peerDependenciesMeta": {
70
65
  "@graphql-codegen/cli": {
@@ -103,7 +98,7 @@
103
98
  "oclif.manifest.json"
104
99
  ],
105
100
  "engines": {
106
- "node": ">=18.0.0"
101
+ "node": "^20 || ^22 || ^24"
107
102
  },
108
103
  "oclif": {
109
104
  "commands": "dist/commands",
@@ -130,5 +125,13 @@
130
125
  "plugins": [
131
126
  "@shopify/plugin-cloudflare"
132
127
  ]
128
+ },
129
+ "scripts": {
130
+ "build": "tsup && node scripts/build-check.mjs",
131
+ "dev": "tsup --watch ./src --watch ../../templates/skeleton",
132
+ "typecheck": "tsc --noEmit",
133
+ "generate:manifest": "node scripts/generate-manifest.mjs",
134
+ "test": "cross-env SHOPIFY_UNIT_TEST=1 LANG=en-US.UTF-8 vitest run --test-timeout=60000",
135
+ "test:watch": "cross-env SHOPIFY_UNIT_TEST=1 LANG=en-US.UTF-8 vitest --test-timeout=60000"
133
136
  }
134
- }
137
+ }