@shopify/cli-hydrogen 8.1.1 → 8.3.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 (105) hide show
  1. package/dist/assets/hydrogen/starter/.graphqlrc.ts +27 -0
  2. package/dist/assets/hydrogen/starter/CHANGELOG.md +166 -8
  3. package/dist/assets/hydrogen/starter/app/components/AddToCartButton.tsx +37 -0
  4. package/dist/assets/hydrogen/starter/app/components/CartLineItem.tsx +150 -0
  5. package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +68 -0
  6. package/dist/assets/hydrogen/starter/app/components/CartSummary.tsx +101 -0
  7. package/dist/assets/hydrogen/starter/app/components/Header.tsx +3 -3
  8. package/dist/assets/hydrogen/starter/app/components/PageLayout.tsx +2 -2
  9. package/dist/assets/hydrogen/starter/app/components/ProductForm.tsx +80 -0
  10. package/dist/assets/hydrogen/starter/app/components/ProductImage.tsx +23 -0
  11. package/dist/assets/hydrogen/starter/app/components/ProductPrice.tsx +27 -0
  12. package/dist/assets/hydrogen/starter/app/lib/session.ts +5 -0
  13. package/dist/assets/hydrogen/starter/app/root.tsx +23 -36
  14. package/dist/assets/hydrogen/starter/app/routes/account.$.tsx +1 -5
  15. package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +12 -70
  16. package/dist/assets/hydrogen/starter/app/routes/account.orders.$id.tsx +7 -14
  17. package/dist/assets/hydrogen/starter/app/routes/account.orders._index.tsx +1 -8
  18. package/dist/assets/hydrogen/starter/app/routes/account.profile.tsx +5 -22
  19. package/dist/assets/hydrogen/starter/app/routes/account.tsx +0 -1
  20. package/dist/assets/hydrogen/starter/app/routes/cart.tsx +1 -3
  21. package/dist/assets/hydrogen/starter/app/routes/products.$handle.tsx +51 -232
  22. package/dist/assets/hydrogen/starter/package.json +10 -11
  23. package/dist/assets/hydrogen/starter/server.ts +4 -0
  24. package/dist/assets/hydrogen/tailwind/package.json +1 -6
  25. package/dist/assets/hydrogen/tailwind/tailwind.css +6 -3
  26. package/dist/assets/hydrogen/vanilla-extract/package.json +2 -3
  27. package/dist/assets/hydrogen/virtual-routes/components/{Layout.jsx → PageLayout.jsx} +2 -2
  28. package/dist/assets/hydrogen/virtual-routes/components/RequestDetails.jsx +1 -2
  29. package/dist/assets/hydrogen/virtual-routes/components/RequestTable.jsx +1 -2
  30. package/dist/assets/hydrogen/virtual-routes/routes/index.jsx +1 -2
  31. package/dist/assets/hydrogen/virtual-routes/virtual-root.jsx +8 -30
  32. package/dist/commands/hydrogen/build.js +33 -10
  33. package/dist/commands/hydrogen/customer-account/push.js +3 -6
  34. package/dist/commands/hydrogen/debug/cpu.js +3 -3
  35. package/dist/commands/hydrogen/deploy.js +14 -3
  36. package/dist/commands/hydrogen/dev.js +3 -6
  37. package/dist/commands/hydrogen/env/list.js +1 -2
  38. package/dist/commands/hydrogen/env/pull.js +2 -4
  39. package/dist/commands/hydrogen/env/push.js +6 -12
  40. package/dist/commands/hydrogen/init.d.ts +18 -15
  41. package/dist/commands/hydrogen/init.js +12 -24
  42. package/dist/commands/hydrogen/link.js +1 -2
  43. package/dist/commands/hydrogen/login.js +4 -0
  44. package/dist/commands/hydrogen/logout.js +2 -0
  45. package/dist/commands/hydrogen/preview.js +4 -6
  46. package/dist/commands/hydrogen/setup/css.js +29 -12
  47. package/dist/commands/hydrogen/setup/vite.js +3 -6
  48. package/dist/commands/hydrogen/setup.js +8 -7
  49. package/dist/commands/hydrogen/upgrade.js +16 -32
  50. package/dist/hooks/init.js +53 -6
  51. package/dist/index.d.ts +46 -46
  52. package/dist/lib/auth.js +4 -65
  53. package/dist/lib/build.js +1 -2
  54. package/dist/lib/bundle/analyzer.js +39 -24
  55. package/dist/lib/bundle/vite-plugin.js +161 -0
  56. package/dist/lib/check-cli-version.js +61 -0
  57. package/dist/lib/check-lockfile.js +2 -2
  58. package/dist/lib/classic-compiler/build.js +3 -3
  59. package/dist/lib/classic-compiler/dev.js +5 -10
  60. package/dist/lib/codegen.js +75 -49
  61. package/dist/lib/defer.js +2 -4
  62. package/dist/lib/environment-variables.js +2 -4
  63. package/dist/lib/file.js +15 -7
  64. package/dist/lib/flags.js +10 -0
  65. package/dist/lib/get-oxygen-deployment-data.js +1 -2
  66. package/dist/lib/graphiql-url.js +1 -2
  67. package/dist/lib/import-utils.js +8 -2
  68. package/dist/lib/log.js +17 -53
  69. package/dist/lib/mini-oxygen/common.js +1 -2
  70. package/dist/lib/mini-oxygen/node.js +1 -2
  71. package/dist/lib/missing-routes.js +1 -2
  72. package/dist/lib/onboarding/common.js +62 -15
  73. package/dist/lib/onboarding/local.js +14 -13
  74. package/dist/lib/onboarding/remote.js +16 -9
  75. package/dist/lib/onboarding/setup-template.mocks.js +6 -3
  76. package/dist/lib/remix-config.js +2 -4
  77. package/dist/lib/remix-version-check.js +1 -2
  78. package/dist/lib/request-events.js +3 -6
  79. package/dist/lib/setups/css/assets.js +1 -1
  80. package/dist/lib/setups/css/index.js +17 -10
  81. package/dist/lib/setups/css/replacers.js +74 -76
  82. package/dist/lib/setups/css/tailwind.js +16 -20
  83. package/dist/lib/setups/css/vanilla-extract.js +8 -5
  84. package/dist/lib/setups/i18n/replacers.js +1 -2
  85. package/dist/lib/setups/routes/generate.js +18 -19
  86. package/dist/lib/shell.js +5 -10
  87. package/dist/lib/template-diff.js +83 -104
  88. package/dist/lib/template-downloader.js +2 -2
  89. package/dist/lib/transpile/morph/functions.js +3 -6
  90. package/dist/lib/transpile/morph/index.js +2 -4
  91. package/dist/lib/transpile/morph/typedefs.js +3 -6
  92. package/dist/lib/transpile/morph/utils.js +2 -4
  93. package/dist/lib/transpile/project.js +4 -3
  94. package/oclif.manifest.json +51 -4
  95. package/package.json +8 -12
  96. package/dist/assets/hydrogen/css-modules/package.json +0 -6
  97. package/dist/assets/hydrogen/postcss/package.json +0 -10
  98. package/dist/assets/hydrogen/postcss/postcss.config.js +0 -8
  99. package/dist/assets/hydrogen/starter/.graphqlrc.yml +0 -12
  100. package/dist/assets/hydrogen/starter/app/components/Cart.tsx +0 -364
  101. package/dist/assets/hydrogen/tailwind/postcss.config.js +0 -10
  102. package/dist/assets/hydrogen/tailwind/tailwind.config.js +0 -8
  103. package/dist/lib/check-version.js +0 -75
  104. package/dist/lib/setups/css/css-modules.js +0 -23
  105. package/dist/lib/setups/css/postcss.js +0 -31
@@ -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
  );
@@ -175,69 +168,102 @@ async function generateDefaultConfig({
175
168
  }).catch(() => void 0);
176
169
  const sfapiSchema = getSchema("storefront");
177
170
  const sfapiProject = findGqlProject(sfapiSchema, gqlConfig);
178
- const defaultGlob = "*!(*.d).{ts,tsx,js,jsx}";
179
- const appDirRelative = relativePath(rootDirectory, appDirectory);
180
171
  const caapiSchema = getSchema("customer-account", { throwIfMissing: false });
181
172
  const caapiProject = caapiSchema ? findGqlProject(caapiSchema, gqlConfig) : void 0;
182
- const customerAccountAPIConfig = caapiProject?.documents ? {
183
- ["customer-accountapi.generated.d.ts"]: {
184
- preset,
185
- schema: caapiSchema,
186
- documents: caapiProject?.documents
187
- }
188
- } : void 0;
173
+ const defaultGlob = "*!(*.d).{ts,tsx,js,jsx}";
174
+ const appDirRelative = relativePath(rootDirectory, appDirectory);
175
+ const isKnownSchema = (schema) => {
176
+ const baseSfapiSchema = basename(sfapiSchema);
177
+ const baseCaapiSchema = caapiSchema && basename(caapiSchema);
178
+ return Boolean(
179
+ schema.endsWith(baseSfapiSchema) || baseCaapiSchema && schema.endsWith(baseCaapiSchema)
180
+ );
181
+ };
182
+ const otherCodegenProjects = Object.values(gqlConfig?.projects ?? {}).filter(
183
+ (project) => project.hasExtension("codegen") && (typeof project.schema !== "string" || !isKnownSchema(project.schema))
184
+ );
189
185
  return {
190
186
  filepath: "virtual:codegen",
191
187
  config: {
192
188
  overwrite: true,
193
189
  pluckConfig,
194
190
  generates: {
195
- ["storefrontapi.generated.d.ts"]: {
196
- preset,
197
- schema: sfapiSchema,
198
- documents: sfapiProject?.documents ?? [
199
- defaultGlob,
200
- // E.g. ./server.(t|j)s
201
- joinPath(appDirRelative, "**", defaultGlob)
202
- // E.g. app/routes/_index.(t|j)sx
203
- ],
204
- ...!!forceSfapiVersion && {
205
- presetConfig: { importTypes: false },
206
- schema: {
207
- [`https://hydrogen-preview.myshopify.com/api/${forceSfapiVersion.split(":")[0]}/graphql.json`]: {
208
- headers: {
209
- "content-type": "application/json",
210
- "X-Shopify-Storefront-Access-Token": forceSfapiVersion.split(":")[1] ?? "3b580e70970c4528da70c98e097c2fa0"
191
+ // If the SFAPI project in GraphQL config has a codegen extension, use it.
192
+ // Otherwise, always fallback to our default config for SFAPI.
193
+ ...getCodegenFromGraphQLConfig(sfapiProject) ?? {
194
+ ["storefrontapi.generated.d.ts"]: {
195
+ preset,
196
+ schema: sfapiSchema,
197
+ documents: sfapiProject?.documents ?? [
198
+ defaultGlob,
199
+ // E.g. ./server.(t|j)s
200
+ joinPath(appDirRelative, "**", defaultGlob)
201
+ // E.g. app/routes/_index.(t|j)sx
202
+ ],
203
+ ...!!forceSfapiVersion && {
204
+ presetConfig: { importTypes: false },
205
+ schema: {
206
+ [`https://hydrogen-preview.myshopify.com/api/${forceSfapiVersion.split(":")[0]}/graphql.json`]: {
207
+ headers: {
208
+ "content-type": "application/json",
209
+ "X-Shopify-Storefront-Access-Token": forceSfapiVersion.split(":")[1] ?? "3b580e70970c4528da70c98e097c2fa0"
210
+ }
211
211
  }
212
+ },
213
+ config: {
214
+ defaultScalarType: "string",
215
+ scalars: { JSON: "unknown" }
212
216
  }
213
- },
214
- config: {
215
- defaultScalarType: "string",
216
- scalars: { JSON: "unknown" }
217
217
  }
218
218
  }
219
219
  },
220
- ...customerAccountAPIConfig
220
+ // If the CAAPI project in GraphQL config has a codegen extension, use it.
221
+ // Otherwise, check if the user provided a list of documents to scan for queries
222
+ // before falling back to our default config for CAAPI.
223
+ ...getCodegenFromGraphQLConfig(caapiProject) ?? (caapiProject?.documents ? {
224
+ ["customer-accountapi.generated.d.ts"]: {
225
+ preset,
226
+ schema: caapiSchema,
227
+ documents: caapiProject.documents
228
+ }
229
+ } : {}),
230
+ // Use other unknown codegen projects from the GraphQL config as they are.
231
+ ...otherCodegenProjects.reduce(
232
+ (acc, project) => ({ ...acc, ...getCodegenFromGraphQLConfig(project) }),
233
+ {}
234
+ )
221
235
  }
222
236
  }
223
237
  };
224
238
  }
239
+ function getCodegenFromGraphQLConfig(project) {
240
+ if (!project?.extensions?.codegen?.generates) return;
241
+ return Object.entries(
242
+ project.extensions.codegen.generates
243
+ ).reduce((acc, [key, value]) => {
244
+ acc[key] = { ...project, ...Array.isArray(value) ? value[0] : value };
245
+ return acc;
246
+ }, {});
247
+ }
225
248
  function findGqlProject(schemaFilepath, gqlConfig) {
226
- if (!gqlConfig)
227
- return;
249
+ if (!gqlConfig) return;
228
250
  const schemaFilename = basename(schemaFilepath);
229
251
  return Object.values(gqlConfig.projects || {}).find(
230
252
  (project) => typeof project.schema === "string" && project.schema.endsWith(schemaFilename)
231
253
  );
232
254
  }
233
255
  async function addHooksToHydrogenOptions(codegenConfig, { rootDirectory }) {
256
+ const name = Symbol.for("name");
234
257
  const hydrogenProjectsOptions = Object.values(codegenConfig.generates).filter(
235
258
  (value) => {
236
259
  const foundPreset = (Array.isArray(value) ? value[0] : value)?.preset;
237
260
  if (typeof foundPreset === "object") {
238
- const name = Symbol.for("name");
239
261
  if (name in foundPreset) {
240
- return foundPreset[name] === "hydrogen";
262
+ return (
263
+ // Preset from @shopify/hydrogen-codegen (e.g. SFAPI, CAAPI)
264
+ foundPreset[name] === "hydrogen" || // Preset from @shopify/graphql-codegen (e.g. Admin API)
265
+ foundPreset[name] === "@shopify/graphql-codegen"
266
+ );
241
267
  }
242
268
  }
243
269
  }
@@ -254,4 +280,4 @@ async function addHooksToHydrogenOptions(codegenConfig, { rootDirectory }) {
254
280
  }
255
281
  }
256
282
 
257
- export { codegen, spawnCodegenProcess };
283
+ export { codegen, generateDefaultConfig, spawnCodegenProcess };
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
  }
package/dist/lib/file.js CHANGED
@@ -6,8 +6,7 @@ import { formatCode } from './format-code.js';
6
6
 
7
7
  async function replaceFileContent(filepath, formatConfig, replacer) {
8
8
  let content = await replacer(await readFile(filepath));
9
- if (typeof content !== "string")
10
- return;
9
+ if (typeof content !== "string") return;
11
10
  if (formatConfig) {
12
11
  content = await formatCode(content, formatConfig, filepath);
13
12
  }
@@ -62,8 +61,7 @@ async function mergePackageJson(sourceDir, targetDir, options) {
62
61
  (key) => !MANAGED_PACKAGE_JSON_KEYS.includes(key)
63
62
  );
64
63
  for (const key of unmanagedKeys) {
65
- if (ignoredKeys.has(key))
66
- continue;
64
+ if (ignoredKeys.has(key)) continue;
67
65
  const sourceValue = sourcePkgJson[key];
68
66
  const targetValue = targetPkgJson[key];
69
67
  const newValue = Array.isArray(sourceValue) && Array.isArray(targetValue) ? [...targetValue, ...sourceValue] : typeof sourceValue === "object" && typeof targetValue === "object" ? { ...targetValue, ...sourceValue } : sourceValue;
@@ -73,8 +71,7 @@ async function mergePackageJson(sourceDir, targetDir, options) {
73
71
  ([dep]) => dep.startsWith("@remix-run/")
74
72
  )?.[1];
75
73
  for (const key of MANAGED_PACKAGE_JSON_KEYS) {
76
- if (ignoredKeys.has(key))
77
- continue;
74
+ if (ignoredKeys.has(key)) continue;
78
75
  if (sourcePkgJson[key]) {
79
76
  targetPkgJson[key] = [
80
77
  .../* @__PURE__ */ new Set([
@@ -96,5 +93,16 @@ async function mergePackageJson(sourceDir, targetDir, options) {
96
93
  options?.onResult?.(targetPkgJson) ?? targetPkgJson
97
94
  );
98
95
  }
96
+ async function mergeTsConfig(sourceDir, targetDir) {
97
+ const sourceTsConfig = await readFile(joinPath(sourceDir, "tsconfig.json"));
98
+ const sourceTsTypes = sourceTsConfig.match(/"types": \[(.*?)\]/)?.[1];
99
+ if (sourceTsTypes) {
100
+ replaceFileContent(
101
+ joinPath(targetDir, "tsconfig.json"),
102
+ false,
103
+ (content) => content.replace(/"types":\s*\[[^\]]*\]/, `"types": [${sourceTsTypes}]`)
104
+ );
105
+ }
106
+ }
99
107
 
100
- export { findFileWithExtension, mergePackageJson, replaceFileContent };
108
+ export { findFileWithExtension, mergePackageJson, mergeTsConfig, replaceFileContent };
package/dist/lib/flags.js CHANGED
@@ -3,6 +3,7 @@ import { camelize } from '@shopify/cli-kit/common/string';
3
3
  import { renderInfo } from '@shopify/cli-kit/node/ui';
4
4
  import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
5
5
  import colors from '@shopify/cli-kit/node/colors';
6
+ import { STYLING_CHOICES } from './setups/css/index.js';
6
7
  import { I18N_CHOICES } from './setups/i18n/index.js';
7
8
 
8
9
  const DEFAULT_APP_PORT = 3e3;
@@ -86,6 +87,15 @@ const commonFlags = {
86
87
  dependsOn: ["codegen"]
87
88
  })
88
89
  },
90
+ styling: {
91
+ styling: Flags.string({
92
+ description: `Sets the styling strategy to use. One of ${STYLING_CHOICES.map(
93
+ (item) => `\`${item}\``
94
+ ).join(", ")}.`,
95
+ choices: STYLING_CHOICES,
96
+ env: "SHOPIFY_HYDROGEN_FLAG_STYLING"
97
+ })
98
+ },
89
99
  markets: {
90
100
  markets: Flags.string({
91
101
  description: `Sets the URL structure to support multiple markets. Must be one of: ${I18N_CHOICES.map(
@@ -18,8 +18,7 @@ async function getOxygenDeploymentData({
18
18
  config,
19
19
  cliCommand
20
20
  });
21
- if (!linkedStorefront)
22
- return;
21
+ if (!linkedStorefront) return;
23
22
  config.storefront = linkedStorefront;
24
23
  const { storefront } = await getOxygenData(session, config.storefront.id);
25
24
  if (!storefront) {
@@ -5,8 +5,7 @@ function getGraphiQLUrl({
5
5
  let url = `${host.endsWith("/") ? host.slice(0, -1) : host}/graphiql`;
6
6
  if (graphql) {
7
7
  let { query, variables } = graphql;
8
- if (typeof variables !== "string")
9
- variables = JSON.stringify(variables);
8
+ if (typeof variables !== "string") variables = JSON.stringify(variables);
10
9
  url += `?query=${encodeURIComponent(query)}${variables ? `&variables=${encodeURIComponent(variables)}` : ""}`;
11
10
  if (graphql.schema) {
12
11
  url += `&schema=${graphql.schema}`;
@@ -5,7 +5,10 @@ import { joinPath, dirname } from '@shopify/cli-kit/node/path';
5
5
 
6
6
  const require2 = createRequire(import.meta.url);
7
7
  async function importVite(root) {
8
- const vitePath = require2.resolve("vite", { paths: [root] });
8
+ const vitePath = require2.resolve(
9
+ "vite",
10
+ process.env.SHOPIFY_UNIT_TEST ? void 0 : { paths: [root] }
11
+ );
9
12
  const vitePackageJson = await findUpAndReadPackageJson(vitePath);
10
13
  const viteNodeIndexFile = vitePackageJson.content.exports?.["."].import.default;
11
14
  const viteNodePath = joinPath(
@@ -15,7 +18,10 @@ async function importVite(root) {
15
18
  return import(pathToFileURL(viteNodePath).href);
16
19
  }
17
20
  function importLocal(packageName, path) {
18
- const realPath = require2.resolve(packageName, { paths: [path] });
21
+ const realPath = require2.resolve(
22
+ packageName,
23
+ process.env.SHOPIFY_UNIT_TEST ? void 0 : { paths: [path] }
24
+ );
19
25
  return import(pathToFileURL(realPath).href);
20
26
  }
21
27
 
package/dist/lib/log.js CHANGED
@@ -2,6 +2,7 @@ import { renderFatalError, renderWarning, renderInfo } from '@shopify/cli-kit/no
2
2
  import { BugError } from '@shopify/cli-kit/node/error';
3
3
  import { outputContent, outputToken } from '@shopify/cli-kit/node/output';
4
4
  import colors from '@shopify/cli-kit/node/colors';
5
+ import ansiEscapes from 'ansi-escapes';
5
6
  import { getGraphiQLUrl } from './graphiql-url.js';
6
7
  import { importLocal } from './import-utils.js';
7
8
 
@@ -25,8 +26,7 @@ function debounceMessage(args, debounceFor) {
25
26
  const message = item?.message ?? item;
26
27
  return typeof message === "string" ? message : "";
27
28
  }).filter(Boolean).join("");
28
- if (printedMessages.has(key))
29
- return true;
29
+ if (printedMessages.has(key)) return true;
30
30
  printedMessages.add(key);
31
31
  if (debounceFor !== true) {
32
32
  setTimeout(() => printedMessages.delete(key), debounceFor ?? 1e3);
@@ -47,18 +47,15 @@ function injectLogReplacer(method, debouncer) {
47
47
  return;
48
48
  }
49
49
  const replacers = messageReplacers.reduce((acc, [matcher, replacer]) => {
50
- if (matcher(args, acc.length))
51
- acc.push(replacer);
50
+ if (matcher(args, acc.length)) acc.push(replacer);
52
51
  return acc;
53
52
  }, []);
54
- if (replacers.length === 0)
55
- return originalConsole[method](...args);
53
+ if (replacers.length === 0) return originalConsole[method](...args);
56
54
  const result = replacers.reduce(
57
55
  (resultArgs, replacer) => resultArgs && replacer(resultArgs),
58
56
  args
59
57
  );
60
- if (result)
61
- return originalConsole[method](...result);
58
+ if (result) return originalConsole[method](...result);
62
59
  };
63
60
  }
64
61
  }
@@ -192,61 +189,30 @@ function muteDevLogs({ workerReload } = {}) {
192
189
  return processStderrWrite.apply(process.stderr, args);
193
190
  };
194
191
  }
195
- const originalWrite = process.stdout.write;
196
- function muteAuthLogs({
197
- onPressKey,
198
- onKeyTimeout
199
- }) {
200
- if (process.stdout.write === originalWrite) {
201
- const write = originalWrite.bind(process.stdout);
202
- process.stdout.write = (item, cb) => {
203
- if (typeof item !== "string")
204
- return write(item, cb);
205
- const replacers = messageReplacers.reduce((acc, [matcher, replacer]) => {
206
- if (matcher([item], acc.length))
207
- acc.push(replacer);
208
- return acc;
209
- }, []);
210
- if (replacers.length === 0)
211
- return write(item, cb);
212
- const result = replacers.reduce(
213
- (resultArgs, replacer) => resultArgs && replacer(resultArgs),
214
- [item]
215
- );
216
- if (result)
217
- return write(result[0], cb);
218
- };
219
- }
192
+ function enhanceAuthLogs(hideInitialLog = false) {
193
+ injectLogReplacer("log", warningDebouncer);
220
194
  addMessageReplacers(
221
195
  "auth",
222
196
  [
223
- ([first]) => typeof first === "string" && first.includes("Auto-open"),
197
+ ([first]) => hideInitialLog && typeof first === "string" && first.includes("To run this command,"),
224
198
  ([first]) => {
225
- const content = first.replace(" to Shopify Partners", "");
226
- const link = content.match(/(https?:\/\/.*)Log in/)?.[1];
227
- onKeyTimeout(link);
228
- if (link)
229
- return;
230
- return [content];
199
+ return;
231
200
  }
232
201
  ],
233
202
  [
234
- ([first]) => typeof first === "string" && first.includes("\u{1F449}"),
235
- () => {
236
- onPressKey();
237
- return;
203
+ ([first]) => typeof first === "string" && first.includes("Open this link to start the auth process"),
204
+ ([first]) => {
205
+ return [first.replace("\u{1F449} ", "").replace(": ", ":\n")];
238
206
  }
239
207
  ],
240
208
  [
241
- ([first]) => typeof first === "string" && (first.includes("Shopify Partners") || first.includes("Logged in")),
209
+ ([first]) => typeof first === "string" && first.includes("Logged in."),
242
210
  () => {
211
+ process.stdout.write(ansiEscapes.eraseLines(hideInitialLog ? 4 : 5));
243
212
  return;
244
213
  }
245
214
  ]
246
215
  );
247
- return () => {
248
- process.stdout.write = originalWrite;
249
- };
250
216
  }
251
217
  function enhanceH2Logs(options) {
252
218
  injectLogReplacer("error");
@@ -266,8 +232,7 @@ function enhanceH2Logs(options) {
266
232
  stringArg += "\nRun `h2 link` to link your store.";
267
233
  }
268
234
  const [, type, scope, message] = stringArg.match(/\[h2:([^:]+):([^\]]+)\]\s+(.*)$/ims) || [];
269
- if (!type || !scope || !message)
270
- return args;
235
+ if (!type || !scope || !message) return args;
271
236
  const headline = `In Hydrogen's \`${scope.trim()}\`:
272
237
 
273
238
  `;
@@ -281,8 +246,7 @@ function enhanceH2Logs(options) {
281
246
  colors.magentaBright(`\`${options.cliCommand ?? "$1"} $2\``)
282
247
  );
283
248
  }
284
- if (hasLinks || hasCommands)
285
- lines.pop();
249
+ if (hasLinks || hasCommands) lines.pop();
286
250
  if (type === "error" || errorObject) {
287
251
  let tryMessage = hasLinks || hasCommands ? lastLine : void 0;
288
252
  let stack = errorObject?.stack;
@@ -394,4 +358,4 @@ function isH2Verbose() {
394
358
  return !!(process.env.DEBUG === "*" || process.env.DEBUG?.includes("h2:*"));
395
359
  }
396
360
 
397
- export { addMessageReplacers, createRemixLogger, enhanceH2Logs, isH2Verbose, muteAuthLogs, muteDevLogs, muteRemixLogs, resetAllLogs, setH2OVerbose, warnOnce };
361
+ export { addMessageReplacers, createRemixLogger, enhanceAuthLogs, enhanceH2Logs, isH2Verbose, muteDevLogs, muteRemixLogs, resetAllLogs, setH2OVerbose, warnOnce };
@@ -18,8 +18,7 @@ function logRequestLine({
18
18
  }) {
19
19
  try {
20
20
  const url = new URL(request.url);
21
- if (DEV_ROUTES.has(url.pathname) || url.pathname === "/favicon.ico")
22
- return;
21
+ if (DEV_ROUTES.has(url.pathname) || url.pathname === "/favicon.ico") return;
23
22
  const isDataRequest = url.searchParams.has("_data");
24
23
  let route = request.url.replace(url.origin, "");
25
24
  let info = "";
@@ -42,8 +42,7 @@ async function startNodeServer({
42
42
  }
43
43
  };
44
44
  if (debug) {
45
- if (!inspectorPort)
46
- inspectorPort = await findPort(DEFAULT_INSPECTOR_PORT);
45
+ if (!inspectorPort) inspectorPort = await findPort(DEFAULT_INSPECTOR_PORT);
47
46
  (await import('node:inspector')).open(inspectorPort);
48
47
  }
49
48
  const readWorkerFile = () => readFile(buildPathWorkerFile).catch((error) => {
@@ -51,8 +51,7 @@ function findMissingRoutes(config, requiredRoutes = REQUIRED_ROUTES) {
51
51
  const parentRoute = userRoutes.find(
52
52
  (r) => r.id === currentRoute.parentId
53
53
  );
54
- if (!parentRoute)
55
- break;
54
+ if (!parentRoute) break;
56
55
  currentRoute.path = `${parentRoute.path}/${currentRoute.path}`;
57
56
  currentRoute.parentId = parentRoute.parentId;
58
57
  }