@shopify/cli-hydrogen 6.0.2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/commands/hydrogen/build.js +40 -78
  2. package/dist/commands/hydrogen/codegen.js +8 -3
  3. package/dist/commands/hydrogen/deploy.js +173 -37
  4. package/dist/commands/hydrogen/deploy.test.js +192 -20
  5. package/dist/commands/hydrogen/dev.js +56 -31
  6. package/dist/commands/hydrogen/init.js +1 -1
  7. package/dist/commands/hydrogen/init.test.js +155 -53
  8. package/dist/commands/hydrogen/link.js +5 -21
  9. package/dist/commands/hydrogen/link.test.js +10 -10
  10. package/dist/commands/hydrogen/preview.js +22 -11
  11. package/dist/commands/hydrogen/setup.js +0 -4
  12. package/dist/commands/hydrogen/setup.test.js +0 -1
  13. package/dist/commands/hydrogen/shortcut.js +1 -0
  14. package/dist/commands/hydrogen/upgrade.js +720 -0
  15. package/dist/commands/hydrogen/upgrade.test.js +786 -0
  16. package/dist/generator-templates/starter/.graphqlrc.yml +12 -1
  17. package/dist/generator-templates/starter/CHANGELOG.md +126 -0
  18. package/dist/generator-templates/starter/README.md +23 -0
  19. package/dist/generator-templates/starter/app/components/Cart.tsx +1 -1
  20. package/dist/generator-templates/starter/app/components/Footer.tsx +3 -1
  21. package/dist/generator-templates/starter/app/components/Header.tsx +5 -1
  22. package/dist/generator-templates/starter/app/components/Layout.tsx +14 -11
  23. package/dist/generator-templates/starter/app/components/Search.tsx +1 -1
  24. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerAddressMutations.ts +61 -0
  25. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +39 -0
  26. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerOrderQuery.ts +87 -0
  27. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerOrdersQuery.ts +58 -0
  28. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerUpdateMutation.ts +24 -0
  29. package/dist/generator-templates/starter/app/lib/fragments.ts +102 -0
  30. package/dist/generator-templates/starter/app/lib/session.ts +67 -0
  31. package/dist/generator-templates/starter/app/root.tsx +11 -45
  32. package/dist/generator-templates/starter/app/routes/[robots.txt].tsx +0 -27
  33. package/dist/generator-templates/starter/app/routes/account.$.tsx +8 -4
  34. package/dist/generator-templates/starter/app/routes/account._index.tsx +5 -0
  35. package/dist/generator-templates/starter/app/routes/account.addresses.tsx +215 -206
  36. package/dist/generator-templates/starter/app/routes/account.orders.$id.tsx +56 -163
  37. package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +32 -109
  38. package/dist/generator-templates/starter/app/routes/account.profile.tsx +40 -180
  39. package/dist/generator-templates/starter/app/routes/account.tsx +20 -135
  40. package/dist/generator-templates/starter/app/routes/account_.authorize.tsx +5 -0
  41. package/dist/generator-templates/starter/app/routes/account_.login.tsx +3 -140
  42. package/dist/generator-templates/starter/app/routes/account_.logout.tsx +5 -24
  43. package/dist/generator-templates/starter/app/routes/cart.tsx +7 -5
  44. package/dist/generator-templates/starter/app/routes/collections.$handle.tsx +1 -1
  45. package/dist/generator-templates/starter/app/routes/products.$handle.tsx +2 -2
  46. package/dist/generator-templates/starter/app/routes/search.tsx +1 -1
  47. package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +506 -0
  48. package/dist/generator-templates/starter/package.json +11 -10
  49. package/dist/generator-templates/starter/remix.config.js +4 -0
  50. package/dist/generator-templates/starter/remix.env.d.ts +6 -11
  51. package/dist/generator-templates/starter/server.ts +24 -167
  52. package/dist/generator-templates/starter/storefrontapi.generated.d.ts +104 -881
  53. package/dist/hooks/init.js +4 -4
  54. package/dist/lib/auth.js +5 -10
  55. package/dist/lib/build.js +6 -1
  56. package/dist/lib/bundle/analyzer.js +36 -26
  57. package/dist/lib/check-lockfile.js +1 -0
  58. package/dist/lib/codegen.js +59 -18
  59. package/dist/lib/defer.js +12 -0
  60. package/dist/lib/file.js +52 -3
  61. package/dist/lib/flags.js +27 -9
  62. package/dist/lib/get-oxygen-deployment-data.test.js +4 -2
  63. package/dist/lib/graphql/admin/client.test.js +2 -2
  64. package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
  65. package/dist/lib/log.js +32 -14
  66. package/dist/lib/mini-oxygen/assets.js +118 -0
  67. package/dist/lib/mini-oxygen/common.js +2 -1
  68. package/dist/lib/mini-oxygen/index.js +7 -5
  69. package/dist/lib/mini-oxygen/mini-oxygen.test.js +214 -0
  70. package/dist/lib/mini-oxygen/node.js +19 -5
  71. package/dist/lib/mini-oxygen/workerd-inspector-logs.js +227 -0
  72. package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +200 -0
  73. package/dist/lib/mini-oxygen/workerd-inspector.js +62 -235
  74. package/dist/lib/mini-oxygen/workerd.js +74 -50
  75. package/dist/lib/missing-routes.js +6 -3
  76. package/dist/lib/onboarding/common.js +40 -9
  77. package/dist/lib/onboarding/local.js +19 -11
  78. package/dist/lib/onboarding/remote.js +48 -28
  79. package/dist/lib/render-errors.js +2 -0
  80. package/dist/lib/request-events.js +65 -31
  81. package/dist/lib/setups/css/assets.js +1 -46
  82. package/dist/lib/setups/css/css-modules.js +3 -2
  83. package/dist/lib/setups/css/postcss.js +4 -2
  84. package/dist/lib/setups/css/tailwind.js +4 -2
  85. package/dist/lib/setups/css/vanilla-extract.js +3 -2
  86. package/dist/lib/setups/i18n/replacers.test.js +56 -38
  87. package/dist/lib/shell.js +1 -1
  88. package/dist/lib/template-diff.js +89 -0
  89. package/dist/lib/template-downloader.js +3 -2
  90. package/dist/lib/transpile/project.js +1 -1
  91. package/dist/virtual-routes/assets/debug-network.css +592 -0
  92. package/dist/virtual-routes/assets/favicon-dark.svg +20 -0
  93. package/dist/virtual-routes/components/FlameChartWrapper.jsx +8 -10
  94. package/dist/virtual-routes/components/IconClose.jsx +38 -0
  95. package/dist/virtual-routes/components/IconDiscard.jsx +44 -0
  96. package/dist/virtual-routes/components/RequestDetails.jsx +179 -0
  97. package/dist/virtual-routes/components/RequestTable.jsx +92 -0
  98. package/dist/virtual-routes/components/RequestWaterfall.jsx +151 -0
  99. package/dist/virtual-routes/lib/useDebugNetworkServer.jsx +176 -0
  100. package/dist/virtual-routes/routes/subrequest-profiler.jsx +243 -0
  101. package/oclif.manifest.json +134 -59
  102. package/package.json +18 -26
  103. package/dist/generator-templates/starter/app/routes/account_.activate.$id.$activationToken.tsx +0 -161
  104. package/dist/generator-templates/starter/app/routes/account_.recover.tsx +0 -129
  105. package/dist/generator-templates/starter/app/routes/account_.register.tsx +0 -207
  106. package/dist/generator-templates/starter/app/routes/account_.reset.$id.$resetToken.tsx +0 -136
  107. package/dist/virtual-routes/routes/debug-network.jsx +0 -289
  108. /package/dist/generator-templates/starter/app/{utils.ts → lib/variants.ts} +0 -0
@@ -1,7 +1,6 @@
1
1
  import { readFile, writeFile, fileExists } from '@shopify/cli-kit/node/fs';
2
2
  import { joinPath } from '@shopify/cli-kit/node/path';
3
3
  import { renderConfirmationPrompt } from '@shopify/cli-kit/node/ui';
4
- import { readAndParsePackageJson, writePackageJSON } from '@shopify/cli-kit/node/node-package-manager';
5
4
  import { GENERATOR_SETUP_ASSETS_SUB_DIRS, getAssetDir } from '../../build.js';
6
5
 
7
6
  const SETUP_CSS_STRATEGIES = GENERATOR_SETUP_ASSETS_SUB_DIRS;
@@ -41,49 +40,5 @@ async function canWriteFiles(assetMap, directory, force) {
41
40
  }
42
41
  return true;
43
42
  }
44
- const MANAGED_PACKAGE_JSON_KEYS = Object.freeze([
45
- "dependencies",
46
- "devDependencies",
47
- "peerDependencies"
48
- ]);
49
- async function mergePackageJson(feature, projectDir) {
50
- const targetPkgJson = await readAndParsePackageJson(
51
- joinPath(projectDir, "package.json")
52
- );
53
- const sourcePkgJson = await readAndParsePackageJson(
54
- joinPath(getAssetDir(feature), "package.json")
55
- );
56
- delete sourcePkgJson.comment;
57
- const unmanagedKeys = Object.keys(sourcePkgJson).filter(
58
- (key) => !MANAGED_PACKAGE_JSON_KEYS.includes(key)
59
- );
60
- for (const key of unmanagedKeys) {
61
- const sourceValue = sourcePkgJson[key];
62
- const targetValue = targetPkgJson[key];
63
- const newValue = Array.isArray(sourceValue) && Array.isArray(targetValue) ? [...targetValue, ...sourceValue] : typeof sourceValue === "object" && typeof targetValue === "object" ? { ...targetValue, ...sourceValue } : sourceValue;
64
- targetPkgJson[key] = newValue;
65
- }
66
- const remixVersion = Object.entries(targetPkgJson.dependencies || {}).find(
67
- ([dep]) => dep.startsWith("@remix-run/")
68
- )?.[1];
69
- for (const key of MANAGED_PACKAGE_JSON_KEYS) {
70
- if (sourcePkgJson[key]) {
71
- targetPkgJson[key] = [
72
- .../* @__PURE__ */ new Set([
73
- ...Object.keys(targetPkgJson[key] ?? {}),
74
- ...Object.keys(sourcePkgJson[key] ?? {})
75
- ])
76
- ].sort().reduce((acc, dep) => {
77
- let version = sourcePkgJson[key]?.[dep] ?? targetPkgJson[key]?.[dep];
78
- if (dep.startsWith("@remix-run/") && remixVersion) {
79
- version = remixVersion;
80
- }
81
- acc[dep] = version;
82
- return acc;
83
- }, {});
84
- }
85
- }
86
- await writePackageJSON(projectDir, targetPkgJson);
87
- }
88
43
 
89
- export { SETUP_CSS_STRATEGIES, canWriteFiles, copyAssets, mergePackageJson };
44
+ export { SETUP_CSS_STRATEGIES, canWriteFiles, copyAssets };
@@ -1,13 +1,14 @@
1
- import { mergePackageJson } from './assets.js';
1
+ import { mergePackageJson } from '../../file.js';
2
2
  import { getCodeFormatOptions } from '../../format-code.js';
3
3
  import { injectCssBundlingLink } from './replacers.js';
4
+ import { getAssetDir } from '../../build.js';
4
5
 
5
6
  async function setupCssModules({
6
7
  rootDirectory,
7
8
  appDirectory
8
9
  }) {
9
10
  const workPromise = Promise.all([
10
- mergePackageJson("css-modules", rootDirectory),
11
+ mergePackageJson(getAssetDir("css-modules"), rootDirectory),
11
12
  getCodeFormatOptions(rootDirectory).then(
12
13
  (formatConfig) => injectCssBundlingLink(appDirectory, formatConfig)
13
14
  )
@@ -1,5 +1,7 @@
1
1
  import { outputInfo } from '@shopify/cli-kit/node/output';
2
- import { canWriteFiles, mergePackageJson, copyAssets } from './assets.js';
2
+ import { mergePackageJson } from '../../file.js';
3
+ import { canWriteFiles, copyAssets } from './assets.js';
4
+ import { getAssetDir } from '../../build.js';
3
5
 
4
6
  async function setupPostCss({ rootDirectory, appDirectory, ...futureOptions }, force = false) {
5
7
  const assetMap = {
@@ -16,7 +18,7 @@ async function setupPostCss({ rootDirectory, appDirectory, ...futureOptions }, f
16
18
  return;
17
19
  }
18
20
  const workPromise = Promise.all([
19
- mergePackageJson("postcss", rootDirectory),
21
+ mergePackageJson(getAssetDir("postcss"), rootDirectory),
20
22
  copyAssets("postcss", assetMap, rootDirectory)
21
23
  ]);
22
24
  return {
@@ -1,8 +1,10 @@
1
1
  import { outputInfo } from '@shopify/cli-kit/node/output';
2
2
  import { relativePath, joinPath } from '@shopify/cli-kit/node/path';
3
- import { canWriteFiles, mergePackageJson, copyAssets } from './assets.js';
3
+ import { mergePackageJson } from '../../file.js';
4
+ import { canWriteFiles, copyAssets } from './assets.js';
4
5
  import { getCodeFormatOptions } from '../../format-code.js';
5
6
  import { replaceRootLinks } from './replacers.js';
7
+ import { getAssetDir } from '../../build.js';
6
8
 
7
9
  const tailwindCssPath = "styles/tailwind.css";
8
10
  async function setupTailwind({ rootDirectory, appDirectory, ...futureOptions }, force = false) {
@@ -23,7 +25,7 @@ async function setupTailwind({ rootDirectory, appDirectory, ...futureOptions },
23
25
  return;
24
26
  }
25
27
  const workPromise = Promise.all([
26
- mergePackageJson("tailwind", rootDirectory),
28
+ mergePackageJson(getAssetDir("tailwind"), rootDirectory),
27
29
  copyAssets(
28
30
  "tailwind",
29
31
  assetMap,
@@ -1,13 +1,14 @@
1
- import { mergePackageJson } from './assets.js';
1
+ import { mergePackageJson } from '../../file.js';
2
2
  import { getCodeFormatOptions } from '../../format-code.js';
3
3
  import { injectCssBundlingLink } from './replacers.js';
4
+ import { getAssetDir } from '../../build.js';
4
5
 
5
6
  async function setupVanillaExtract({
6
7
  rootDirectory,
7
8
  appDirectory
8
9
  }) {
9
10
  const workPromise = Promise.all([
10
- mergePackageJson("vanilla-extract", rootDirectory),
11
+ mergePackageJson(getAssetDir("vanilla-extract"), rootDirectory),
11
12
  getCodeFormatOptions(rootDirectory).then(
12
13
  (formatConfig) => injectCssBundlingLink(appDirectory, formatConfig)
13
14
  )
@@ -41,26 +41,29 @@ describe("i18n replacers", () => {
41
41
  const newContent = await readFile(joinPath(tmpDir, remixDts));
42
42
  expect(() => checkTypes(newContent)).not.toThrow();
43
43
  expect(newContent).toMatchInlineSnapshot(`
44
- "/// <reference types=\\"@remix-run/dev\\" />
45
- /// <reference types=\\"@shopify/remix-oxygen\\" />
46
- /// <reference types=\\"@shopify/oxygen-workers-types\\" />
44
+ "/// <reference types="@remix-run/dev" />
45
+ /// <reference types="@shopify/remix-oxygen" />
46
+ /// <reference types="@shopify/oxygen-workers-types" />
47
47
 
48
48
  // Enhance TypeScript's built-in typings.
49
- import \\"@total-typescript/ts-reset\\";
49
+ import "@total-typescript/ts-reset";
50
50
 
51
- import type { Storefront, HydrogenCart } from \\"@shopify/hydrogen\\";
51
+ import type {
52
+ Storefront,
53
+ CustomerClient,
54
+ HydrogenCart,
55
+ } from "@shopify/hydrogen";
52
56
  import type {
53
57
  LanguageCode,
54
58
  CountryCode,
55
- } from \\"@shopify/hydrogen/storefront-api-types\\";
56
- import type { CustomerAccessToken } from \\"@shopify/hydrogen/storefront-api-types\\";
57
- import type { HydrogenSession } from \\"./server\\";
59
+ } from "@shopify/hydrogen/storefront-api-types";
60
+ import type { AppSession } from "~/lib/session";
58
61
 
59
62
  declare global {
60
63
  /**
61
64
  * A global \`process\` object is only available during build to access NODE_ENV.
62
65
  */
63
- const process: { env: { NODE_ENV: \\"production\\" | \\"development\\" } };
66
+ const process: { env: { NODE_ENV: "production" | "development" } };
64
67
 
65
68
  /**
66
69
  * Declare expected Env parameter in fetch handler.
@@ -71,6 +74,8 @@ describe("i18n replacers", () => {
71
74
  PRIVATE_STOREFRONT_API_TOKEN: string;
72
75
  PUBLIC_STORE_DOMAIN: string;
73
76
  PUBLIC_STOREFRONT_ID: string;
77
+ PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID: string;
78
+ PUBLIC_CUSTOMER_ACCOUNT_API_URL: string;
74
79
  }
75
80
 
76
81
  /**
@@ -79,7 +84,7 @@ describe("i18n replacers", () => {
79
84
  type I18nLocale = { language: LanguageCode; country: CountryCode };
80
85
  }
81
86
 
82
- declare module \\"@shopify/remix-oxygen\\" {
87
+ declare module "@shopify/remix-oxygen" {
83
88
  /**
84
89
  * Declare local additions to the Remix loader context.
85
90
  */
@@ -87,15 +92,9 @@ describe("i18n replacers", () => {
87
92
  env: Env;
88
93
  cart: HydrogenCart;
89
94
  storefront: Storefront<I18nLocale>;
90
- session: HydrogenSession;
91
- waitUntil: ExecutionContext[\\"waitUntil\\"];
92
- }
93
-
94
- /**
95
- * Declare the data we expect to access via \`context.session\`.
96
- */
97
- export interface SessionData {
98
- customerAccessToken: CustomerAccessToken;
95
+ customerAccount: CustomerClient;
96
+ session: AppSession;
97
+ waitUntil: ExecutionContext["waitUntil"];
99
98
  }
100
99
  }
101
100
  "
@@ -107,7 +106,7 @@ describe("i18n replacers", () => {
107
106
  const skeletonDir = getSkeletonSourceDir();
108
107
  await writeFile(
109
108
  joinPath(tmpDir, serverTs),
110
- // Remove the part that is not needed for this test (HydrogenSession, Cart query, etc);
109
+ // Remove the part that is not needed for this test (AppSession, Cart query, etc);
111
110
  (await readFile(joinPath(skeletonDir, serverTs))).replace(/^};$.*/ms, "};")
112
111
  );
113
112
  await replaceServerI18n(
@@ -122,21 +121,22 @@ describe("i18n replacers", () => {
122
121
  expect(() => checkTypes(newContent)).not.toThrow();
123
122
  expect(newContent).toMatchInlineSnapshot(`
124
123
  "// Virtual entry point for the app
125
- import * as remixBuild from \\"@remix-run/dev/server-build\\";
124
+ import * as remixBuild from "@remix-run/dev/server-build";
126
125
  import {
127
126
  cartGetIdDefault,
128
127
  cartSetIdDefault,
129
128
  createCartHandler,
130
129
  createStorefrontClient,
131
130
  storefrontRedirect,
132
- } from \\"@shopify/hydrogen\\";
131
+ createCustomerAccountClient,
132
+ } from "@shopify/hydrogen";
133
133
  import {
134
134
  createRequestHandler,
135
135
  getStorefrontHeaders,
136
- createCookieSessionStorage,
137
- type SessionStorage,
138
- type Session,
139
- } from \\"@shopify/remix-oxygen\\";
136
+ type AppLoadContext,
137
+ } from "@shopify/remix-oxygen";
138
+ import { AppSession } from "~/lib/session";
139
+ import { CART_QUERY_FRAGMENT } from "~/lib/fragments";
140
140
 
141
141
  /**
142
142
  * Export a fetch handler in module format.
@@ -152,13 +152,13 @@ describe("i18n replacers", () => {
152
152
  * Open a cache instance in the worker and a custom session instance.
153
153
  */
154
154
  if (!env?.SESSION_SECRET) {
155
- throw new Error(\\"SESSION_SECRET environment variable is not set\\");
155
+ throw new Error("SESSION_SECRET environment variable is not set");
156
156
  }
157
157
 
158
158
  const waitUntil = executionContext.waitUntil.bind(executionContext);
159
159
  const [cache, session] = await Promise.all([
160
- caches.open(\\"hydrogen\\"),
161
- HydrogenSession.init(request, [env.SESSION_SECRET]),
160
+ caches.open("hydrogen"),
161
+ AppSession.init(request, [env.SESSION_SECRET]),
162
162
  ]);
163
163
 
164
164
  /**
@@ -175,6 +175,17 @@ describe("i18n replacers", () => {
175
175
  storefrontHeaders: getStorefrontHeaders(request),
176
176
  });
177
177
 
178
+ /**
179
+ * Create a client for Customer Account API.
180
+ */
181
+ const customerAccount = createCustomerAccountClient({
182
+ waitUntil,
183
+ request,
184
+ session,
185
+ customerAccountId: env.PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID,
186
+ customerAccountUrl: env.PUBLIC_CUSTOMER_ACCOUNT_API_URL,
187
+ });
188
+
178
189
  /*
179
190
  * Create a cart handler that will be used to
180
191
  * create and update the cart in the session.
@@ -193,7 +204,14 @@ describe("i18n replacers", () => {
193
204
  const handleRequest = createRequestHandler({
194
205
  build: remixBuild,
195
206
  mode: process.env.NODE_ENV,
196
- getLoadContext: () => ({ session, storefront, cart, env, waitUntil }),
207
+ getLoadContext: (): AppLoadContext => ({
208
+ session,
209
+ storefront,
210
+ customerAccount,
211
+ cart,
212
+ env,
213
+ waitUntil,
214
+ }),
197
215
  });
198
216
 
199
217
  const response = await handleRequest(request);
@@ -211,23 +229,23 @@ describe("i18n replacers", () => {
211
229
  } catch (error) {
212
230
  // eslint-disable-next-line no-console
213
231
  console.error(error);
214
- return new Response(\\"An unexpected error occurred\\", { status: 500 });
232
+ return new Response("An unexpected error occurred", { status: 500 });
215
233
  }
216
234
  },
217
235
  };
218
236
 
219
237
  function getLocaleFromRequest(request: Request): I18nLocale {
220
- const defaultLocale: I18nLocale = { language: \\"EN\\", country: \\"US\\" };
238
+ const defaultLocale: I18nLocale = { language: "EN", country: "US" };
221
239
  const supportedLocales = {
222
- ES: \\"ES\\",
223
- FR: \\"FR\\",
224
- DE: \\"DE\\",
225
- JP: \\"JA\\",
226
- } as Record<I18nLocale[\\"country\\"], I18nLocale[\\"language\\"]>;
240
+ ES: "ES",
241
+ FR: "FR",
242
+ DE: "DE",
243
+ JP: "JA",
244
+ } as Record<I18nLocale["country"], I18nLocale["language"]>;
227
245
 
228
246
  const url = new URL(request.url);
229
247
  const domain = url.hostname
230
- .split(\\".\\")
248
+ .split(".")
231
249
  .pop()
232
250
  ?.toUpperCase() as keyof typeof supportedLocales;
233
251
 
package/dist/lib/shell.js CHANGED
@@ -160,7 +160,7 @@ async function getCliCommand(directory = process.cwd(), forcePkgManager) {
160
160
  }
161
161
  let cli = "npx";
162
162
  const pkgManager = forcePkgManager ?? await getPackageManager(directory).catch(() => null);
163
- if (pkgManager === "pnpm" || pkgManager === "yarn")
163
+ if (pkgManager === "bun" || pkgManager === "pnpm" || pkgManager === "yarn")
164
164
  cli = pkgManager;
165
165
  return `${cli} shopify hydrogen`;
166
166
  }
@@ -0,0 +1,89 @@
1
+ import { rmdirSync } from 'node:fs';
2
+ import { temporaryDirectory } from 'tempy';
3
+ import { createSymlink, copy, remove } from 'fs-extra/esm';
4
+ import { copyFile, removeFile } from '@shopify/cli-kit/node/fs';
5
+ import { joinPath, relativePath } from '@shopify/cli-kit/node/path';
6
+ import colors from '@shopify/cli-kit/node/colors';
7
+ import { getRepoNodeModules, getStarterDir } from './build.js';
8
+ import { mergePackageJson } from './file.js';
9
+
10
+ async function prepareDiffDirectory(diffDirectory, watch) {
11
+ const targetDirectory = temporaryDirectory({ prefix: "tmp-hydrogen-diff-" });
12
+ process.on("exit", () => rmdirSync(targetDirectory, { recursive: true }));
13
+ console.info(
14
+ `
15
+ -- Applying diff to starter template in
16
+ ${colors.dim(
17
+ targetDirectory
18
+ )}
19
+ `
20
+ );
21
+ await applyTemplateDiff(targetDirectory, diffDirectory);
22
+ await createSymlink(
23
+ await getRepoNodeModules(),
24
+ joinPath(targetDirectory, "node_modules")
25
+ );
26
+ if (watch) {
27
+ const pw = await import('@parcel/watcher').catch((error) => {
28
+ console.log("Could not watch for file changes.", error);
29
+ });
30
+ pw?.subscribe(
31
+ targetDirectory,
32
+ (error, events) => {
33
+ if (error) {
34
+ console.error(error);
35
+ return;
36
+ }
37
+ events.map((event) => {
38
+ return copyFile(
39
+ event.path,
40
+ joinPath(diffDirectory, relativePath(targetDirectory, event.path))
41
+ );
42
+ });
43
+ },
44
+ { ignore: ["!*.generated.d.ts"] }
45
+ );
46
+ pw?.subscribe(
47
+ diffDirectory,
48
+ async (error, events) => {
49
+ if (error) {
50
+ console.error(error);
51
+ return;
52
+ }
53
+ await events.map((event) => {
54
+ const targetFile = joinPath(
55
+ targetDirectory,
56
+ relativePath(diffDirectory, event.path)
57
+ );
58
+ return event.type === "delete" ? removeFile(targetFile).catch(() => {
59
+ }) : copyFile(event.path, targetFile);
60
+ });
61
+ },
62
+ { ignore: ["*.generated.d.ts", "package.json", "tsconfig.json"] }
63
+ );
64
+ }
65
+ return targetDirectory;
66
+ }
67
+ async function applyTemplateDiff(targetDirectory, diffDirectory, templateDir = getStarterDir()) {
68
+ const createFilter = (re) => (filepath) => !re.test(relativePath(templateDir, filepath));
69
+ await copy(templateDir, targetDirectory, {
70
+ filter: createFilter(/[\/\\](dist|node_modules|\.cache)(\/|\\|$)/i)
71
+ });
72
+ await copy(diffDirectory, targetDirectory, {
73
+ filter: createFilter(
74
+ /[\/\\](dist|node_modules|\.cache|package\.json|tsconfig\.json)(\/|\\|$)/i
75
+ )
76
+ });
77
+ await mergePackageJson(diffDirectory, targetDirectory, {
78
+ ignoredKeys: ["scripts"]
79
+ });
80
+ }
81
+ async function copyDiffBuild(targetDirectory, diffDirectory) {
82
+ const targetDist = joinPath(diffDirectory, "dist");
83
+ await remove(targetDist);
84
+ await copy(joinPath(targetDirectory, "dist"), targetDist, {
85
+ overwrite: true
86
+ });
87
+ }
88
+
89
+ export { applyTemplateDiff, copyDiffBuild, prepareDiffDirectory };
@@ -42,7 +42,7 @@ async function downloadTarball(url, storageDir, signal) {
42
42
  strip: 1,
43
43
  filter: (name) => {
44
44
  name = name.replace(storageDir, "");
45
- return !name.startsWith(path.normalize("/templates/")) || name.startsWith(path.normalize("/templates/skeleton/"));
45
+ return !name.startsWith(path.normalize("/templates/")) && !name.startsWith(path.normalize("/examples/"));
46
46
  }
47
47
  })
48
48
  );
@@ -64,7 +64,8 @@ async function getLatestTemplates({
64
64
  }
65
65
  return {
66
66
  version,
67
- templatesDir: path.join(templateStorageVersionPath, "templates")
67
+ templatesDir: path.join(templateStorageVersionPath, "templates"),
68
+ examplesDir: path.join(templateStorageVersionPath, "examples")
68
69
  };
69
70
  } catch (e) {
70
71
  const error = e;
@@ -102,7 +102,7 @@ async function transpileProject(projectDir, keepTypes = true) {
102
102
  delete pkgJson.devDependencies[key];
103
103
  }
104
104
  }
105
- const codegenFlag = /\s*--codegen(-unstable)?/;
105
+ const codegenFlag = /\s*--codegen/;
106
106
  if (pkgJson.scripts?.dev) {
107
107
  pkgJson.scripts.dev = pkgJson.scripts.dev.replace(codegenFlag, "");
108
108
  }