@shopify/cli-hydrogen 11.1.3 → 11.1.5

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 (95) hide show
  1. package/dist/assets/hydrogen/bundle/analyzer.html +155 -148
  2. package/dist/assets/hydrogen/starter/CHANGELOG.md +125 -49
  3. package/dist/assets/hydrogen/starter/app/components/AddToCartButton.tsx +1 -1
  4. package/dist/assets/hydrogen/starter/app/components/CartLineItem.tsx +1 -1
  5. package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +1 -1
  6. package/dist/assets/hydrogen/starter/app/components/CartSummary.tsx +62 -29
  7. package/dist/assets/hydrogen/starter/app/components/Header.tsx +1 -1
  8. package/dist/assets/hydrogen/starter/app/components/PageLayout.tsx +1 -1
  9. package/dist/assets/hydrogen/starter/app/components/ProductForm.tsx +2 -2
  10. package/dist/assets/hydrogen/starter/app/components/SearchForm.tsx +1 -1
  11. package/dist/assets/hydrogen/starter/app/components/SearchFormPredictive.tsx +8 -3
  12. package/dist/assets/hydrogen/starter/app/components/SearchResults.tsx +3 -11
  13. package/dist/assets/hydrogen/starter/app/components/SearchResultsPredictive.tsx +2 -6
  14. package/dist/assets/hydrogen/starter/app/entry.client.tsx +10 -2
  15. package/dist/assets/hydrogen/starter/app/entry.server.tsx +5 -3
  16. package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerAddressMutations.ts +7 -4
  17. package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +1 -1
  18. package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerOrderQuery.ts +4 -1
  19. package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerOrdersQuery.ts +10 -5
  20. package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerUpdateMutation.ts +3 -2
  21. package/dist/assets/hydrogen/starter/app/lib/context.ts +34 -17
  22. package/dist/assets/hydrogen/starter/app/lib/fragments.ts +1 -0
  23. package/dist/assets/hydrogen/starter/app/lib/orderFilters.ts +90 -0
  24. package/dist/assets/hydrogen/starter/app/lib/redirect.ts +1 -1
  25. package/dist/assets/hydrogen/starter/app/lib/session.ts +1 -1
  26. package/dist/assets/hydrogen/starter/app/lib/variants.ts +1 -1
  27. package/dist/assets/hydrogen/starter/app/root.tsx +23 -18
  28. package/dist/assets/hydrogen/starter/app/routes/$.tsx +2 -2
  29. package/dist/assets/hydrogen/starter/app/routes/[robots.txt].tsx +2 -2
  30. package/dist/assets/hydrogen/starter/app/routes/[sitemap.xml].tsx +2 -3
  31. package/dist/assets/hydrogen/starter/app/routes/_index.tsx +12 -8
  32. package/dist/assets/hydrogen/starter/app/routes/account.$.tsx +4 -3
  33. package/dist/assets/hydrogen/starter/app/routes/account._index.tsx +1 -1
  34. package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +15 -11
  35. package/dist/assets/hydrogen/starter/app/routes/account.orders.$id.tsx +47 -22
  36. package/dist/assets/hydrogen/starter/app/routes/account.orders._index.tsx +152 -23
  37. package/dist/assets/hydrogen/starter/app/routes/account.profile.tsx +11 -8
  38. package/dist/assets/hydrogen/starter/app/routes/account.tsx +16 -4
  39. package/dist/assets/hydrogen/starter/app/routes/account_.authorize.tsx +2 -2
  40. package/dist/assets/hydrogen/starter/app/routes/account_.login.tsx +5 -3
  41. package/dist/assets/hydrogen/starter/app/routes/account_.logout.tsx +3 -2
  42. package/dist/assets/hydrogen/starter/app/routes/api.$version.[graphql.json].tsx +2 -2
  43. package/dist/assets/hydrogen/starter/app/routes/blogs.$blogHandle.$articleHandle.tsx +6 -10
  44. package/dist/assets/hydrogen/starter/app/routes/blogs.$blogHandle._index.tsx +10 -7
  45. package/dist/assets/hydrogen/starter/app/routes/blogs._index.tsx +13 -7
  46. package/dist/assets/hydrogen/starter/app/routes/cart.$lines.tsx +3 -2
  47. package/dist/assets/hydrogen/starter/app/routes/cart.tsx +13 -9
  48. package/dist/assets/hydrogen/starter/app/routes/collections.$handle.tsx +8 -11
  49. package/dist/assets/hydrogen/starter/app/routes/collections._index.tsx +6 -6
  50. package/dist/assets/hydrogen/starter/app/routes/collections.all.tsx +10 -7
  51. package/dist/assets/hydrogen/starter/app/routes/discount.$code.tsx +3 -2
  52. package/dist/assets/hydrogen/starter/app/routes/pages.$handle.tsx +8 -6
  53. package/dist/assets/hydrogen/starter/app/routes/policies.$handle.tsx +7 -4
  54. package/dist/assets/hydrogen/starter/app/routes/policies._index.tsx +19 -13
  55. package/dist/assets/hydrogen/starter/app/routes/products.$handle.tsx +9 -6
  56. package/dist/assets/hydrogen/starter/app/routes/search.tsx +14 -14
  57. package/dist/assets/hydrogen/starter/app/routes/sitemap.$type.$page[.xml].tsx +2 -3
  58. package/dist/assets/hydrogen/starter/app/routes.ts +1 -1
  59. package/dist/assets/hydrogen/starter/app/styles/app.css +53 -1
  60. package/dist/assets/hydrogen/starter/customer-accountapi.generated.d.ts +47 -13
  61. package/dist/assets/hydrogen/starter/env.d.ts +1 -39
  62. package/dist/assets/hydrogen/starter/eslint.config.js +35 -52
  63. package/dist/assets/hydrogen/starter/package.json +14 -15
  64. package/dist/assets/hydrogen/starter/react-router.config.ts +9 -3
  65. package/dist/assets/hydrogen/starter/server.ts +7 -7
  66. package/dist/assets/hydrogen/starter/storefrontapi.generated.d.ts +1 -1
  67. package/dist/assets/hydrogen/starter/tsconfig.json +17 -13
  68. package/dist/assets/hydrogen/starter/vite.config.ts +3 -0
  69. package/dist/assets/hydrogen/virtual-routes/components/RequestDetails.jsx +13 -20
  70. package/dist/assets/hydrogen/virtual-routes/routes/[.]well-known.appspecific.com[.]chrome[.]devtools[.]json.jsx +37 -0
  71. package/dist/commands/hydrogen/build.js +2 -16
  72. package/dist/commands/hydrogen/codegen.js +2 -10
  73. package/dist/commands/hydrogen/debug/cpu.js +3 -7
  74. package/dist/commands/hydrogen/deploy.js +14 -9
  75. package/dist/commands/hydrogen/dev.js +6 -10
  76. package/dist/commands/hydrogen/env/pull.js +9 -1
  77. package/dist/commands/hydrogen/init.d.ts +1 -1
  78. package/dist/commands/hydrogen/preview.js +1 -16
  79. package/dist/commands/hydrogen/upgrade.js +145 -20
  80. package/dist/index.d.ts +1 -6
  81. package/dist/lib/build.js +17 -4
  82. package/dist/lib/flags.js +2 -10
  83. package/dist/lib/import-utils.js +4 -1
  84. package/dist/lib/live-reload.js +4 -4
  85. package/dist/lib/log.js +1 -1
  86. package/dist/lib/mini-oxygen/common.js +4 -1
  87. package/dist/lib/onboarding/local.js +25 -1
  88. package/dist/lib/onboarding/remote.js +4 -13
  89. package/dist/lib/onboarding/setup-template.mocks.js +4 -6
  90. package/dist/lib/react-router-version-check.js +82 -0
  91. package/dist/lib/setups/routes/generate.js +3 -0
  92. package/dist/lib/transpile/project.js +15 -7
  93. package/oclif.manifest.json +8 -53
  94. package/package.json +5 -5
  95. package/dist/lib/template-diff.js +0 -202
package/dist/lib/build.js CHANGED
@@ -1,13 +1,23 @@
1
1
  import { fileURLToPath } from 'node:url';
2
+ import { existsSync } from 'node:fs';
2
3
  import { findPathUp } from '@shopify/cli-kit/node/fs';
3
4
  import { AbortError } from '@shopify/cli-kit/node/error';
4
5
  import { joinPath, dirname } from '@shopify/cli-kit/node/path';
5
6
  import { execAsync } from './process.js';
6
7
 
7
8
  const monorepoPackagesPath = new URL("../../..", import.meta.url).pathname;
8
- const isHydrogenMonorepo = monorepoPackagesPath.endsWith(
9
- "/hydrogen/packages/"
10
- );
9
+ const isHydrogenMonorepo = (() => {
10
+ try {
11
+ const skeletonPath = joinPath(
12
+ dirname(monorepoPackagesPath),
13
+ "templates",
14
+ "skeleton"
15
+ );
16
+ return existsSync(skeletonPath);
17
+ } catch {
18
+ return false;
19
+ }
20
+ })();
11
21
  const hydrogenPackagesPath = isHydrogenMonorepo ? monorepoPackagesPath : void 0;
12
22
  const ASSETS_DIR_PREFIX = "assets/hydrogen";
13
23
  const ASSETS_STARTER_DIR = "starter";
@@ -55,6 +65,9 @@ function getSkeletonSourceDir() {
55
65
  }
56
66
  return joinPath(dirname(monorepoPackagesPath), "templates", "skeleton");
57
67
  }
68
+ function getSkeletonNodeModules() {
69
+ return joinPath(getSkeletonSourceDir(), "node_modules");
70
+ }
58
71
  async function getRepoNodeModules() {
59
72
  const { stdout } = await execAsync("npm root");
60
73
  let nodeModulesPath = stdout.trim();
@@ -64,4 +77,4 @@ async function getRepoNodeModules() {
64
77
  return nodeModulesPath;
65
78
  }
66
79
 
67
- export { ASSETS_DIR_PREFIX, ASSETS_STARTER_DIR, ASSETS_STARTER_DIR_ROUTES, getAssetsDir, getPkgJsonPath, getRepoNodeModules, getSkeletonSourceDir, getStarterDir, getTemplateAppFile, hydrogenPackagesPath, isHydrogenMonorepo };
80
+ export { ASSETS_DIR_PREFIX, ASSETS_STARTER_DIR, ASSETS_STARTER_DIR_ROUTES, getAssetsDir, getPkgJsonPath, getRepoNodeModules, getSkeletonNodeModules, getSkeletonSourceDir, getStarterDir, getTemplateAppFile, hydrogenPackagesPath, isHydrogenMonorepo };
package/dist/lib/flags.js CHANGED
@@ -125,13 +125,6 @@ const commonFlags = {
125
125
  env: "SHOPIFY_HYDROGEN_FLAG_INSPECTOR_PORT"
126
126
  })
127
127
  },
128
- diff: {
129
- diff: Flags.boolean({
130
- description: "Applies the current files on top of Hydrogen's starter template in a temporary directory.",
131
- required: false,
132
- hidden: true
133
- })
134
- },
135
128
  entry: {
136
129
  entry: Flags.string({
137
130
  description: "Entry file for the worker. Defaults to `./server`.",
@@ -153,9 +146,8 @@ const commonFlags = {
153
146
  })
154
147
  },
155
148
  customerAccountPush: {
156
- "customer-account-push__unstable": Flags.boolean({
157
- hidden: true,
158
- description: "Use tunneling for local development and push the tunneling domain to admin. Required to use Customer Account API's Oauth flow",
149
+ "customer-account-push": Flags.boolean({
150
+ description: "Use tunneling for local development and push the tunneling domain to admin. Required to use Customer Account API's OAuth flow",
159
151
  required: false,
160
152
  env: "SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH"
161
153
  })
@@ -10,7 +10,10 @@ async function importVite(root) {
10
10
  process.env.SHOPIFY_UNIT_TEST ? void 0 : { paths: [root] }
11
11
  );
12
12
  const vitePackageJson = await findUpAndReadPackageJson(vitePath);
13
- let viteNodeIndexFile = vitePackageJson.content.exports?.["."].import;
13
+ let viteNodeIndexFile = vitePackageJson.content.exports?.["."];
14
+ if (typeof viteNodeIndexFile !== "string") {
15
+ viteNodeIndexFile = viteNodeIndexFile?.import;
16
+ }
14
17
  if (typeof viteNodeIndexFile !== "string") {
15
18
  viteNodeIndexFile = viteNodeIndexFile.default;
16
19
  }
@@ -6,18 +6,18 @@ async function setupLiveReload(devServerPort, root) {
6
6
  try {
7
7
  const [{ updates: hmrUpdates }, { serve }, { detectLoaderChanges }, { ok, err }] = await Promise.all([
8
8
  importLocal(
9
- "@remix-run/dev/dist/devServer_unstable/hmr.js",
9
+ "@react-router/dev/dist/devServer_unstable/hmr.js",
10
10
  root
11
11
  ),
12
12
  importLocal(
13
- "@remix-run/dev/dist/devServer_unstable/socket.js",
13
+ "@react-router/dev/dist/devServer_unstable/socket.js",
14
14
  root
15
15
  ),
16
16
  importLocal(
17
- "@remix-run/dev/dist/devServer_unstable/hdr.js",
17
+ "@react-router/dev/dist/devServer_unstable/hdr.js",
18
18
  root
19
19
  ),
20
- importLocal("@remix-run/dev/dist/result.js", root)
20
+ importLocal("@react-router/dev/dist/result.js", root)
21
21
  ]).catch(handleRemixImportFail);
22
22
  const state = {};
23
23
  const server = http.createServer(function(req, res) {
package/dist/lib/log.js CHANGED
@@ -333,7 +333,7 @@ function createRemixLogger() {
333
333
  async function muteRemixLogs(root) {
334
334
  try {
335
335
  const { logger } = await importLocal(
336
- "@remix-run/dev/dist/tux/logger.js",
336
+ "@react-router/dev/dist/tux/logger.js",
337
337
  root
338
338
  );
339
339
  logger.warn = logger.debug = logger.info = () => {
@@ -18,6 +18,9 @@ function logRequestLine({
18
18
  }) {
19
19
  try {
20
20
  const url = new URL(request.url);
21
+ if (!meta.durationMs && meta.startTimeMs && meta.endTimeMs) {
22
+ meta.durationMs = meta.endTimeMs - meta.startTimeMs;
23
+ }
21
24
  if (DEV_ROUTES.has(url.pathname) || url.pathname === "/favicon.ico") return;
22
25
  const isDataRequest = url.searchParams.has("_data");
23
26
  let route = request.url.replace(url.origin, "");
@@ -33,7 +36,7 @@ function logRequestLine({
33
36
  outputInfo(
34
37
  outputContent`${request.method.padStart(6)} ${colorizeStatus(
35
38
  String(response.status)
36
- )} ${outputToken.italic(type.padEnd(7, " "))} ${route} ${meta.durationMs > 0 ? colors.dim(` ${meta.durationMs}ms`) : ""}${info ? " " + colors.dim(info) : ""}${request.headers["purpose"] === "prefetch" ? outputToken.italic(colors.dim(" prefetch")) : ""}`
39
+ )} ${outputToken.italic(type.padEnd(7, " "))} ${route} ${meta.durationMs && meta.durationMs > 0 ? colors.dim(` ${meta.durationMs}ms`) : ""}${info ? " " + colors.dim(info) : ""}${request.headers.purpose === "prefetch" ? colors.italic(colors.dim(" prefetch")) : ""}`
37
40
  );
38
41
  } catch {
39
42
  if (request && response?.status) {
@@ -12,6 +12,8 @@ import { replaceFileContent } from '../file.js';
12
12
  import { setUserAccount, setStorefront } from '../shopify-config.js';
13
13
  import { getCliCommand, ALIAS_NAME } from '../shell.js';
14
14
  import { CSS_STRATEGY_NAME_MAP } from '../setups/css/index.js';
15
+ import { execAsync } from '../process.js';
16
+ import { outputWarn } from '@shopify/cli-kit/node/output';
15
17
 
16
18
  async function setupLocalStarterTemplate(options, controller) {
17
19
  const templateAction = options.mockShop ? "mock" : await renderSelectPrompt({
@@ -170,6 +172,17 @@ async function setupLocalStarterTemplate(options, controller) {
170
172
  try {
171
173
  await installDeps();
172
174
  setupSummary.depsInstalled = true;
175
+ if (language === "ts") {
176
+ try {
177
+ await execAsync("npx react-router typegen", {
178
+ cwd: project.directory
179
+ });
180
+ } catch (error) {
181
+ outputWarn(
182
+ "Failed to generate React Router types. You may need to run `npx react-router typegen` manually."
183
+ );
184
+ }
185
+ }
173
186
  } catch (error) {
174
187
  setupSummary.depsError = error;
175
188
  }
@@ -239,8 +252,19 @@ async function setupLocalStarterTemplate(options, controller) {
239
252
  // The init process might have added and modified files. Do not overwrite them.
240
253
  // E.g. CSS imports might have been added to the root.
241
254
  overwriteFileDeps: false
242
- }).then((routes) => {
255
+ }).then(async (routes) => {
243
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
+ }
244
268
  if (options.git && routes) {
245
269
  return commitAll(
246
270
  project.directory,
@@ -1,33 +1,24 @@
1
1
  import { readdir } from 'node:fs/promises';
2
2
  import { AbortError } from '@shopify/cli-kit/node/error';
3
3
  import { copyFile, fileExists } from '@shopify/cli-kit/node/fs';
4
- import { readAndParsePackageJson } from '@shopify/cli-kit/node/node-package-manager';
5
4
  import { joinPath } from '@shopify/cli-kit/node/path';
6
5
  import { renderTasks, renderInfo } from '@shopify/cli-kit/node/ui';
7
6
  import { downloadExternalRepo, downloadMonorepoTemplates } from '../template-downloader.js';
8
- import { applyTemplateDiff } from '../template-diff.js';
9
7
  import { getCliCommand } from '../shell.js';
10
- import { createAbortHandler, handleProjectLocation, handleLanguage, createInitialCommit, handleDependencies, commitAll, renderProjectReady } from './common.js';
8
+ import { handleProjectLocation, createAbortHandler, handleLanguage, createInitialCommit, handleDependencies, commitAll, renderProjectReady } from './common.js';
11
9
 
12
10
  const DEMO_STORE_REPO = "shopify/hydrogen-demo-store";
13
11
  async function setupRemoteTemplate(options, controller) {
14
12
  const appTemplate = options.template === "demo-store" ? DEMO_STORE_REPO : options.template;
15
- let abort = createAbortHandler(controller);
16
- const backgroundDownloadPromise = appTemplate.includes("/") ? getExternalTemplate(appTemplate, controller.signal).catch(abort) : getMonorepoTemplate(appTemplate, controller.signal).catch(abort);
17
13
  const project = await handleProjectLocation({ ...options, controller });
18
14
  if (!project) return;
19
- abort = createAbortHandler(controller, project);
15
+ const abort = createAbortHandler(controller, project);
16
+ const backgroundDownloadPromise = appTemplate.includes("/") ? getExternalTemplate(appTemplate, controller.signal).catch(abort) : getMonorepoTemplate(appTemplate, controller.signal).catch(abort);
20
17
  const downloaded = await backgroundDownloadPromise;
21
18
  if (controller.signal.aborted) return;
22
19
  let backgroundWorkPromise = Promise.resolve().then(async () => {
23
20
  if (controller.signal.aborted) return;
24
- const { sourcePath, skeletonPath } = downloaded;
25
- const pkgJson = await readAndParsePackageJson(
26
- joinPath(sourcePath, "package.json")
27
- );
28
- if (pkgJson.scripts?.dev?.includes("--diff")) {
29
- return applyTemplateDiff(project.directory, sourcePath, skeletonPath);
30
- }
21
+ const { sourcePath } = downloaded;
31
22
  await copyFile(sourcePath, project.directory);
32
23
  }).catch(abort);
33
24
  const supportsTranspilation = await fileExists(
@@ -2,7 +2,7 @@ import { rm, symlink } from 'node:fs/promises';
2
2
  import { vi } from 'vitest';
3
3
  import { writeFile } from '@shopify/cli-kit/node/fs';
4
4
  import { dirname, joinPath } from '@shopify/cli-kit/node/path';
5
- import { getSkeletonSourceDir, getRepoNodeModules } from '../build.js';
5
+ import { getSkeletonSourceDir, getSkeletonNodeModules } from '../build.js';
6
6
 
7
7
  const { renderTasksHook } = vi.hoisted(() => ({ renderTasksHook: vi.fn() }));
8
8
  vi.mock("../template-downloader.js", async () => ({
@@ -43,15 +43,13 @@ vi.mock(
43
43
  renderTasksHook.mockImplementationOnce(async () => {
44
44
  await writeFile(`${directory}/package-lock.json`, "{}");
45
45
  });
46
- await rm(joinPath(directory, "node_modules"), {
46
+ const targetNodeModules = joinPath(directory, "node_modules");
47
+ await rm(targetNodeModules, {
47
48
  force: true,
48
49
  recursive: true
49
50
  }).catch(() => {
50
51
  });
51
- await symlink(
52
- await getRepoNodeModules(),
53
- joinPath(directory, "node_modules")
54
- );
52
+ await symlink(await getSkeletonNodeModules(), targetNodeModules);
55
53
  })
56
54
  };
57
55
  }
@@ -0,0 +1,82 @@
1
+ import { readFile } from '@shopify/cli-kit/node/fs';
2
+ import { joinPath } from '@shopify/cli-kit/node/path';
3
+ import { renderWarning } from '@shopify/cli-kit/node/ui';
4
+ import { outputDebug } from '@shopify/cli-kit/node/output';
5
+ import semver from 'semver';
6
+
7
+ const REACT_ROUTER_PACKAGES = [
8
+ "react-router",
9
+ "react-router-dom",
10
+ "@react-router/dev",
11
+ "@react-router/fs-routes"
12
+ ];
13
+ const EXPECTED_VERSION = "7.9.2";
14
+ async function checkReactRouterVersions(appPath) {
15
+ const mismatches = [];
16
+ const packageJsonPath = joinPath(appPath, "package.json");
17
+ let packageJson;
18
+ try {
19
+ packageJson = JSON.parse(await readFile(packageJsonPath));
20
+ } catch (error) {
21
+ outputDebug(
22
+ `Unable to read package.json for React Router version check: ${error}`
23
+ );
24
+ return;
25
+ }
26
+ const allDeps = {
27
+ ...packageJson.dependencies,
28
+ ...packageJson.devDependencies,
29
+ ...packageJson.peerDependencies
30
+ };
31
+ for (const pkg of REACT_ROUTER_PACKAGES) {
32
+ const installedVersion = allDeps[pkg];
33
+ if (!installedVersion) {
34
+ continue;
35
+ }
36
+ installedVersion.replace(/^[\^~]/, "");
37
+ if (!semver.satisfies(EXPECTED_VERSION, installedVersion)) {
38
+ mismatches.push({
39
+ package: pkg,
40
+ installed: installedVersion,
41
+ expected: EXPECTED_VERSION
42
+ });
43
+ }
44
+ }
45
+ if (mismatches.length > 0) {
46
+ const mismatchList = mismatches.map(
47
+ (m) => ` \u2022 ${m.package}: installed ${m.installed}, expected ${m.expected}`
48
+ ).join("\n");
49
+ const devPackages = ["@react-router/dev", "@react-router/fs-routes"];
50
+ const regularMismatches = mismatches.filter(
51
+ (m) => !devPackages.includes(m.package)
52
+ );
53
+ const devMismatches = mismatches.filter(
54
+ (m) => devPackages.includes(m.package)
55
+ );
56
+ const commands = [];
57
+ if (regularMismatches.length > 0) {
58
+ const regularList = regularMismatches.map((m) => `${m.package}@${EXPECTED_VERSION}`).join(" ");
59
+ commands.push(`npm install ${regularList}`);
60
+ }
61
+ if (devMismatches.length > 0) {
62
+ const devList = devMismatches.map((m) => `${m.package}@${EXPECTED_VERSION}`).join(" ");
63
+ commands.push(`npm install -D ${devList}`);
64
+ }
65
+ renderWarning({
66
+ headline: "React Router version mismatch detected",
67
+ body: [
68
+ "Hydrogen requires React Router 7.9.x for proper functionality.",
69
+ "",
70
+ "Version mismatches found:",
71
+ mismatchList,
72
+ "",
73
+ "To fix this issue, run:",
74
+ ...commands.map((cmd) => ` ${cmd}`),
75
+ "",
76
+ "This may cause issues with routing, code splitting, and other features."
77
+ ].join("\n")
78
+ });
79
+ }
80
+ }
81
+
82
+ export { checkReactRouterVersions };
@@ -209,6 +209,9 @@ async function findRouteDependencies(routeFilePath, appDirectory) {
209
209
  // import from '~/components/...'
210
210
  relativePath(dirname(filePath), appDirectory) || "."
211
211
  );
212
+ if (match.includes("/+types/")) {
213
+ continue;
214
+ }
212
215
  const resolvedMatchPath = resolvePath(dirname(filePath), match);
213
216
  const absoluteFilepath = (await findFileWithExtension(
214
217
  dirname(resolvedMatchPath),
@@ -1,4 +1,4 @@
1
- import { readFile, writeFile, glob, removeFile } from '@shopify/cli-kit/node/fs';
1
+ import { fileExists, readFile, writeFile, glob, removeFile } from '@shopify/cli-kit/node/fs';
2
2
  import { outputDebug } from '@shopify/cli-kit/node/output';
3
3
  import { joinPath } from '@shopify/cli-kit/node/path';
4
4
  import { getCodeFormatOptions, formatCode } from '../format-code.js';
@@ -45,12 +45,14 @@ function convertConfigToJS(tsConfig, keepTypes = false) {
45
45
  }
46
46
  async function transpileProject(projectDir, keepTypes = true) {
47
47
  const routesPath = joinPath(projectDir, "app/routes.ts");
48
- const routesFileContent = await readFile(routesPath);
49
- const replacedRoutesFileContent = routesFileContent.replace(
50
- "./layout.tsx",
51
- "./layout.jsx"
52
- );
53
- await writeFile(routesPath, replacedRoutesFileContent);
48
+ if (await fileExists(routesPath)) {
49
+ const routesFileContent = await readFile(routesPath);
50
+ const replacedRoutesFileContent = routesFileContent.replace(
51
+ "./layout.tsx",
52
+ "./layout.jsx"
53
+ );
54
+ await writeFile(routesPath, replacedRoutesFileContent);
55
+ }
54
56
  const entries = await glob("**/*.+(ts|tsx)", {
55
57
  absolute: true,
56
58
  cwd: projectDir,
@@ -103,6 +105,12 @@ async function transpileProject(projectDir, keepTypes = true) {
103
105
  await readFile(joinPath(projectDir, "package.json"))
104
106
  );
105
107
  delete pkgJson.scripts["typecheck"];
108
+ const typegenPattern = /react-router typegen\s*&&\s*/g;
109
+ for (const [key, value] of Object.entries(pkgJson.scripts || {})) {
110
+ if (typeof value === "string" && value.includes("react-router typegen")) {
111
+ pkgJson.scripts[key] = value.replace(typegenPattern, "");
112
+ }
113
+ }
106
114
  if (!keepTypes) {
107
115
  delete pkgJson.devDependencies["typescript"];
108
116
  delete pkgJson.devDependencies["@shopify/oxygen-workers-types"];
@@ -60,14 +60,6 @@
60
60
  "multiple": false,
61
61
  "type": "option"
62
62
  },
63
- "diff": {
64
- "description": "Applies the current files on top of Hydrogen's starter template in a temporary directory.",
65
- "hidden": true,
66
- "name": "diff",
67
- "required": false,
68
- "allowNo": false,
69
- "type": "boolean"
70
- },
71
63
  "watch": {
72
64
  "description": "Watches for changes and rebuilds the project writing output to disk.",
73
65
  "env": "SHOPIFY_HYDROGEN_FLAG_WATCH",
@@ -181,14 +173,6 @@
181
173
  "required": false,
182
174
  "allowNo": false,
183
175
  "type": "boolean"
184
- },
185
- "diff": {
186
- "description": "Applies the current files on top of Hydrogen's starter template in a temporary directory.",
187
- "hidden": true,
188
- "name": "diff",
189
- "required": false,
190
- "allowNo": false,
191
- "type": "boolean"
192
176
  }
193
177
  },
194
178
  "hasDynamicHelp": false,
@@ -281,14 +265,6 @@
281
265
  "multiple": false,
282
266
  "type": "option"
283
267
  },
284
- "diff": {
285
- "description": "Applies the current files on top of Hydrogen's starter template in a temporary directory.",
286
- "hidden": true,
287
- "name": "diff",
288
- "required": false,
289
- "allowNo": false,
290
- "type": "boolean"
291
- },
292
268
  "entry": {
293
269
  "description": "Entry file for the worker. Defaults to `./server`.",
294
270
  "env": "SHOPIFY_HYDROGEN_FLAG_ENTRY",
@@ -496,11 +472,10 @@
496
472
  "multiple": false,
497
473
  "type": "option"
498
474
  },
499
- "diff": {
500
- "description": "Applies the current files on top of Hydrogen's starter template in a temporary directory.",
501
- "hidden": true,
502
- "name": "diff",
503
- "required": false,
475
+ "force-client-sourcemap": {
476
+ "description": "Client sourcemapping is avoided by default because it makes backend code visible in the browser. Use this flag to force enabling it.",
477
+ "env": "SHOPIFY_HYDROGEN_FLAG_FORCE_CLIENT_SOURCEMAP",
478
+ "name": "force-client-sourcemap",
504
479
  "allowNo": false,
505
480
  "type": "boolean"
506
481
  }
@@ -630,19 +605,10 @@
630
605
  "allowNo": false,
631
606
  "type": "boolean"
632
607
  },
633
- "diff": {
634
- "description": "Applies the current files on top of Hydrogen's starter template in a temporary directory.",
635
- "hidden": true,
636
- "name": "diff",
637
- "required": false,
638
- "allowNo": false,
639
- "type": "boolean"
640
- },
641
- "customer-account-push__unstable": {
642
- "description": "Use tunneling for local development and push the tunneling domain to admin. Required to use Customer Account API's Oauth flow",
608
+ "customer-account-push": {
609
+ "description": "Use tunneling for local development and push the tunneling domain to admin. Required to use Customer Account API's OAuth flow",
643
610
  "env": "SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH",
644
- "hidden": true,
645
- "name": "customer-account-push__unstable",
611
+ "name": "customer-account-push",
646
612
  "required": false,
647
613
  "allowNo": false,
648
614
  "type": "boolean"
@@ -1405,17 +1371,6 @@
1405
1371
  "hasDynamicHelp": false,
1406
1372
  "multiple": false,
1407
1373
  "type": "option"
1408
- },
1409
- "diff": {
1410
- "dependsOn": [
1411
- "build"
1412
- ],
1413
- "description": "Applies the current files on top of Hydrogen's starter template in a temporary directory.",
1414
- "hidden": true,
1415
- "name": "diff",
1416
- "required": false,
1417
- "allowNo": false,
1418
- "type": "boolean"
1419
1374
  }
1420
1375
  },
1421
1376
  "hasDynamicHelp": false,
@@ -1728,5 +1683,5 @@
1728
1683
  ]
1729
1684
  }
1730
1685
  },
1731
- "version": "11.1.3"
1686
+ "version": "11.1.5"
1732
1687
  }
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.3",
7
+ "version": "11.1.5",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "repository": {
@@ -21,7 +21,7 @@
21
21
  "test:watch": "cross-env SHOPIFY_UNIT_TEST=1 LANG=en-US.UTF-8 vitest --test-timeout=60000"
22
22
  },
23
23
  "devDependencies": {
24
- "@react-router/dev": "7.6.0",
24
+ "@react-router/dev": "7.9.2",
25
25
  "@types/diff": "^5.0.2",
26
26
  "@types/gunzip-maybe": "^1.4.0",
27
27
  "@types/prettier": "^2.7.2",
@@ -37,7 +37,7 @@
37
37
  "vitest": "^1.0.4"
38
38
  },
39
39
  "dependencies": {
40
- "@ast-grep/napi": "0.11.0",
40
+ "@ast-grep/napi": "0.34.1",
41
41
  "@oclif/core": "3.26.5",
42
42
  "@shopify/cli-kit": "^3.80.4",
43
43
  "@shopify/oxygen-cli": "4.6.18",
@@ -60,9 +60,9 @@
60
60
  },
61
61
  "peerDependencies": {
62
62
  "@graphql-codegen/cli": "^5.0.2",
63
- "@react-router/dev": "7.6.0",
63
+ "@react-router/dev": "7.9.2",
64
64
  "@shopify/hydrogen-codegen": "^0.3.3",
65
- "@shopify/mini-oxygen": "^3.2.1",
65
+ "@shopify/mini-oxygen": "^4.0.0",
66
66
  "graphql-config": "^5.0.3",
67
67
  "vite": "^5.1.0 || ^6.2.0"
68
68
  },