@shopify/cli-hydrogen 7.1.2 → 8.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 (136) hide show
  1. package/dist/commands/hydrogen/build-vite.js +19 -10
  2. package/dist/commands/hydrogen/build.js +10 -2
  3. package/dist/commands/hydrogen/check.js +1 -0
  4. package/dist/commands/hydrogen/codegen.js +1 -0
  5. package/dist/commands/hydrogen/customer-account/push.js +170 -0
  6. package/dist/commands/hydrogen/debug/cpu.js +3 -0
  7. package/dist/commands/hydrogen/deploy.js +121 -36
  8. package/dist/commands/hydrogen/dev-vite.js +128 -59
  9. package/dist/commands/hydrogen/dev.js +108 -51
  10. package/dist/commands/hydrogen/env/list.js +7 -8
  11. package/dist/commands/hydrogen/env/pull.js +17 -1
  12. package/dist/commands/hydrogen/env/{push__unstable.js → push.js} +23 -50
  13. package/dist/commands/hydrogen/generate/route.js +1 -0
  14. package/dist/commands/hydrogen/init.js +45 -17
  15. package/dist/commands/hydrogen/link.js +20 -4
  16. package/dist/commands/hydrogen/list.js +1 -0
  17. package/dist/commands/hydrogen/login.js +1 -0
  18. package/dist/commands/hydrogen/logout.js +1 -0
  19. package/dist/commands/hydrogen/preview.js +31 -16
  20. package/dist/commands/hydrogen/setup/css.js +8 -1
  21. package/dist/commands/hydrogen/setup/markets.js +1 -0
  22. package/dist/commands/hydrogen/setup/vite.js +244 -138
  23. package/dist/commands/hydrogen/setup.js +21 -22
  24. package/dist/commands/hydrogen/shortcut.js +10 -0
  25. package/dist/commands/hydrogen/unlink.js +1 -0
  26. package/dist/commands/hydrogen/upgrade.js +2 -1
  27. package/dist/generator-templates/assets/vite/package.json +3 -4
  28. package/dist/generator-templates/assets/vite/vite.config.js +10 -2
  29. package/dist/generator-templates/starter/CHANGELOG.md +89 -0
  30. package/dist/generator-templates/starter/README.md +3 -44
  31. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +1 -0
  32. package/dist/generator-templates/starter/app/lib/fragments.ts +2 -0
  33. package/dist/generator-templates/starter/app/root.tsx +2 -5
  34. package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +1 -1
  35. package/dist/generator-templates/starter/app/routes/account.tsx +1 -1
  36. package/dist/generator-templates/starter/app/routes/collections.all.tsx +160 -0
  37. package/dist/generator-templates/starter/app/routes/products.$handle.tsx +1 -2
  38. package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +6 -3
  39. package/dist/generator-templates/starter/{remix.env.d.ts → env.d.ts} +8 -2
  40. package/dist/generator-templates/starter/package.json +14 -9
  41. package/dist/generator-templates/starter/server.ts +2 -1
  42. package/dist/generator-templates/starter/storefrontapi.generated.d.ts +59 -3
  43. package/dist/generator-templates/starter/vite.config.ts +21 -0
  44. package/dist/{commands/hydrogen/init.d.ts → init.d.ts} +11 -3
  45. package/dist/lib/check-lockfile.js +12 -18
  46. package/dist/lib/codegen.js +37 -13
  47. package/dist/lib/common.js +50 -0
  48. package/dist/lib/cpu-profiler.js +4 -1
  49. package/dist/lib/dev-shared.js +97 -0
  50. package/dist/lib/environment-variables.js +51 -30
  51. package/dist/lib/file.js +8 -1
  52. package/dist/lib/flags.js +37 -16
  53. package/dist/lib/graphql/admin/customer-application-update.js +29 -0
  54. package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
  55. package/dist/lib/graphql/admin/list-environments.js +1 -0
  56. package/dist/lib/graphql/admin/pull-variables.js +4 -4
  57. package/dist/lib/graphql/admin/test-helper.js +37 -0
  58. package/dist/lib/log.js +86 -13
  59. package/dist/lib/mini-oxygen/common.js +19 -33
  60. package/dist/lib/mini-oxygen/index.js +6 -2
  61. package/dist/lib/mini-oxygen/node.js +43 -31
  62. package/dist/lib/mini-oxygen/workerd.js +72 -165
  63. package/dist/lib/missing-routes.js +1 -1
  64. package/dist/lib/onboarding/common.js +82 -70
  65. package/dist/lib/onboarding/local.js +19 -9
  66. package/dist/lib/onboarding/remote.js +35 -30
  67. package/dist/lib/package-managers.js +24 -0
  68. package/dist/lib/remix-config.js +17 -1
  69. package/dist/lib/request-events.js +6 -1
  70. package/dist/lib/setups/i18n/replacers.js +9 -6
  71. package/dist/lib/setups/routes/generate.js +1 -0
  72. package/dist/lib/shell.js +2 -1
  73. package/dist/lib/shopify-config.js +19 -1
  74. package/dist/lib/template-diff.js +36 -15
  75. package/dist/lib/template-downloader.js +35 -5
  76. package/dist/lib/transpile/morph/typedefs.js +5 -2
  77. package/dist/lib/transpile/project.js +8 -4
  78. package/dist/lib/tunneling.js +44 -0
  79. package/dist/lib/virtual-routes.js +1 -1
  80. package/dist/lib/vite-config.js +39 -9
  81. package/oclif.manifest.json +711 -498
  82. package/package.json +32 -24
  83. package/dist/commands/hydrogen/deploy.test.js +0 -553
  84. package/dist/commands/hydrogen/env/list.test.js +0 -148
  85. package/dist/commands/hydrogen/env/pull.test.js +0 -207
  86. package/dist/commands/hydrogen/env/push__unstable.test.js +0 -383
  87. package/dist/commands/hydrogen/generate/route.test.js +0 -43
  88. package/dist/commands/hydrogen/init.test.js +0 -641
  89. package/dist/commands/hydrogen/link.test.js +0 -187
  90. package/dist/commands/hydrogen/list.test.js +0 -111
  91. package/dist/commands/hydrogen/setup.test.js +0 -61
  92. package/dist/commands/hydrogen/shortcut.test.js +0 -30
  93. package/dist/commands/hydrogen/unlink.test.js +0 -36
  94. package/dist/commands/hydrogen/upgrade.test.js +0 -786
  95. package/dist/generator-templates/starter/remix.config.js +0 -24
  96. package/dist/lib/auth.test.js +0 -157
  97. package/dist/lib/check-lockfile.test.js +0 -81
  98. package/dist/lib/check-version.test.js +0 -86
  99. package/dist/lib/environment-variables.test.js +0 -149
  100. package/dist/lib/file.test.js +0 -68
  101. package/dist/lib/flags.test.js +0 -43
  102. package/dist/lib/get-oxygen-deployment-data.test.js +0 -120
  103. package/dist/lib/gid.test.js +0 -15
  104. package/dist/lib/graphql/admin/client.test.js +0 -76
  105. package/dist/lib/graphql/admin/create-storefront.test.js +0 -64
  106. package/dist/lib/graphql/admin/link-storefront.test.js +0 -38
  107. package/dist/lib/graphql/admin/list-environments.test.js +0 -44
  108. package/dist/lib/graphql/admin/list-storefronts.test.js +0 -44
  109. package/dist/lib/graphql/admin/pull-variables.test.js +0 -43
  110. package/dist/lib/graphql/business-platform/user-account.test.js +0 -80
  111. package/dist/lib/log.test.js +0 -92
  112. package/dist/lib/mini-oxygen/assets.js +0 -134
  113. package/dist/lib/mini-oxygen/mini-oxygen.test.js +0 -214
  114. package/dist/lib/mini-oxygen/workerd-inspector-logs.js +0 -227
  115. package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +0 -200
  116. package/dist/lib/mini-oxygen/workerd-inspector.js +0 -219
  117. package/dist/lib/missing-routes.test.js +0 -45
  118. package/dist/lib/remix-version-check.test.js +0 -39
  119. package/dist/lib/remix-version-interop.test.js +0 -13
  120. package/dist/lib/setups/i18n/domains.test.js +0 -39
  121. package/dist/lib/setups/i18n/replacers.test.js +0 -261
  122. package/dist/lib/setups/i18n/subdomains.test.js +0 -39
  123. package/dist/lib/setups/i18n/subfolders.test.js +0 -39
  124. package/dist/lib/setups/routes/generate.test.js +0 -296
  125. package/dist/lib/shell.test.js +0 -111
  126. package/dist/lib/shopify-config.test.js +0 -199
  127. package/dist/lib/string.test.js +0 -16
  128. package/dist/lib/virtual-routes.test.js +0 -49
  129. package/dist/lib/vite/hydrogen-middleware.js +0 -82
  130. package/dist/lib/vite/mini-oxygen.js +0 -152
  131. package/dist/lib/vite/plugins.d.ts +0 -27
  132. package/dist/lib/vite/plugins.js +0 -139
  133. package/dist/lib/vite/shared.js +0 -10
  134. package/dist/lib/vite/utils.js +0 -55
  135. package/dist/lib/vite/worker-entry.js +0 -1518
  136. /package/dist/generator-templates/starter/{.eslintrc.js → .eslintrc.cjs} +0 -0
@@ -1,10 +1,10 @@
1
1
  import { adminRequest } from './client.js';
2
2
 
3
3
  const PullVariablesQuery = `#graphql
4
- query PullVariables($id: ID!, $branch: String) {
4
+ query PullVariables($id: ID!, $handle: String) {
5
5
  hydrogenStorefront(id: $id) {
6
6
  id
7
- environmentVariables(branchName: $branch) {
7
+ environmentVariables(handle: $handle) {
8
8
  id
9
9
  isSecret
10
10
  readOnly
@@ -14,13 +14,13 @@ const PullVariablesQuery = `#graphql
14
14
  }
15
15
  }
16
16
  `;
17
- async function getStorefrontEnvVariables(adminSession, storefrontId, envBranch) {
17
+ async function getStorefrontEnvVariables(adminSession, storefrontId, envHandle) {
18
18
  const { hydrogenStorefront } = await adminRequest(
19
19
  PullVariablesQuery,
20
20
  adminSession,
21
21
  {
22
22
  id: storefrontId,
23
- branch: envBranch
23
+ handle: envHandle
24
24
  }
25
25
  );
26
26
  return hydrogenStorefront;
@@ -0,0 +1,37 @@
1
+ function dummyListEnvironments(storefrontId) {
2
+ return {
3
+ id: storefrontId,
4
+ productionUrl: "https://my-shop.myshopify.com",
5
+ environments: [
6
+ {
7
+ id: "gid://shopify/HydrogenStorefrontEnvironment/1",
8
+ branch: "main",
9
+ type: "PRODUCTION",
10
+ name: "Production",
11
+ handle: "production",
12
+ createdAt: "2023-02-16T22:35:42Z",
13
+ url: "https://oxygen-123.example.com"
14
+ },
15
+ {
16
+ id: "gid://shopify/HydrogenStorefrontEnvironment/2",
17
+ branch: null,
18
+ type: "PREVIEW",
19
+ name: "Preview",
20
+ handle: "preview",
21
+ createdAt: "2023-02-16T22:35:42Z",
22
+ url: null
23
+ },
24
+ {
25
+ id: "gid://shopify/HydrogenStorefrontEnvironment/3",
26
+ branch: "staging",
27
+ type: "CUSTOM",
28
+ name: "Staging",
29
+ handle: "staging",
30
+ createdAt: "2023-05-08T20:52:29Z",
31
+ url: "https://oxygen-456.example.com"
32
+ }
33
+ ]
34
+ };
35
+ }
36
+
37
+ export { dummyListEnvironments };
package/dist/lib/log.js CHANGED
@@ -34,16 +34,19 @@ function debounceMessage(args, debounceFor) {
34
34
  }
35
35
  function warningDebouncer([first]) {
36
36
  return typeof first === "string" && // Show these warnings only once.
37
- (first.includes("[h2:warn:createStorefrontClient]") || first.includes("[h2:warn:createCustomerAccountClient]")) ? true : void 0;
37
+ /\[h2:(warn|info):(createStorefrontClient|createCustomerAccountClient)\]/.test(
38
+ first
39
+ ) ? true : void 0;
38
40
  }
39
41
  function injectLogReplacer(method, debouncer) {
40
42
  if (!methodsReplaced.has(method)) {
41
43
  methodsReplaced.add(method);
42
44
  console[method] = (...args) => {
43
- if (debounceMessage(args, debouncer?.(args)))
45
+ if (debouncer !== false && debounceMessage(args, debouncer?.(args))) {
44
46
  return;
47
+ }
45
48
  const replacers = messageReplacers.reduce((acc, [matcher, replacer]) => {
46
- if (matcher(args))
49
+ if (matcher(args, acc.length))
47
50
  acc.push(replacer);
48
51
  return acc;
49
52
  }, []);
@@ -62,6 +65,7 @@ function muteDevLogs({ workerReload } = {}) {
62
65
  injectLogReplacer("log");
63
66
  injectLogReplacer("error");
64
67
  injectLogReplacer("warn", warningDebouncer);
68
+ injectLogReplacer("debug", false);
65
69
  let isFirstWorkerReload = true;
66
70
  addMessageReplacers("dev-node", [
67
71
  ([first]) => typeof first === "string" && first.includes("[mf:"),
@@ -114,6 +118,60 @@ function muteDevLogs({ workerReload } = {}) {
114
118
  }
115
119
  ]
116
120
  );
121
+ let isLastLineBlank = false;
122
+ let isLastLineRequestLog = false;
123
+ addMessageReplacers(
124
+ "dev-vite",
125
+ // Vite logs
126
+ [
127
+ // This log must come from Rollup and does not go through Vite's customLogger
128
+ ([first]) => typeof first === "string" && /^Sourcemap for .*@remix-run/i.test(first),
129
+ () => {
130
+ }
131
+ ],
132
+ [
133
+ // Log generated from Workerd HMR connection to Vite
134
+ ([first]) => typeof first === "string" && /^\[vite\] (connected|program reload)/i.test(first),
135
+ () => {
136
+ }
137
+ ],
138
+ [
139
+ // Log that gets entangled with our initial dev logs
140
+ ([first]) => typeof first === "string" && /^Re-optimizing dependencies because/i.test(first),
141
+ () => {
142
+ }
143
+ ],
144
+ [
145
+ // This error is fixed in new Remix versions:
146
+ // https://github.com/remix-run/remix/pull/9194
147
+ ([first]) => {
148
+ const message = first?.message ?? first;
149
+ return /virtual-routes/.test(message) && /(Failed to load url|Could not resolve module for file)/i.test(
150
+ message
151
+ );
152
+ },
153
+ () => {
154
+ }
155
+ ],
156
+ [
157
+ // Log new lines between Request logs and other logs
158
+ ([first], existingMatches) => {
159
+ if (existingMatches === 0 && typeof first === "string") {
160
+ const isRequestLog = /^\s+[A-Z]+\s+\d{3}\s+[a-z]+\s+\//.test(
161
+ // Clear ANSI colors before matching
162
+ first.replace(/\u001b\[.*?m/g, "")
163
+ );
164
+ if (!isLastLineBlank && (isRequestLog && !isLastLineRequestLog || !isRequestLog && isLastLineRequestLog)) {
165
+ process.stdout.write("\n");
166
+ }
167
+ isLastLineRequestLog = isRequestLog;
168
+ isLastLineBlank = /\n$/.test(first);
169
+ }
170
+ return false;
171
+ },
172
+ (params) => params
173
+ ]
174
+ );
117
175
  }
118
176
  const originalWrite = process.stdout.write;
119
177
  function muteAuthLogs({
@@ -126,7 +184,7 @@ function muteAuthLogs({
126
184
  if (typeof item !== "string")
127
185
  return write(item, cb);
128
186
  const replacers = messageReplacers.reduce((acc, [matcher, replacer]) => {
129
- if (matcher([item]))
187
+ if (matcher([item], acc.length))
130
188
  acc.push(replacer);
131
189
  return acc;
132
190
  }, []);
@@ -175,6 +233,7 @@ function enhanceH2Logs(options) {
175
233
  injectLogReplacer("error");
176
234
  injectLogReplacer("warn", warningDebouncer);
177
235
  injectLogReplacer("log", warningDebouncer);
236
+ injectLogReplacer("info", warningDebouncer);
178
237
  addMessageReplacers("h2-warn", [
179
238
  ([first]) => {
180
239
  const message = first?.message ?? first;
@@ -183,7 +242,10 @@ function enhanceH2Logs(options) {
183
242
  (args) => {
184
243
  const firstArg = args[0];
185
244
  const errorObject = typeof firstArg === "object" && !!firstArg.stack ? firstArg : void 0;
186
- const stringArg = errorObject?.message ?? firstArg;
245
+ let stringArg = errorObject?.message ?? firstArg;
246
+ if (stringArg.startsWith("[h2:info:createStorefrontClient]") && stringArg.includes("defaulting to mock.shop")) {
247
+ stringArg += "\nRun `h2 link` to link your store.";
248
+ }
187
249
  const [, type, scope, message] = stringArg.match(/\[h2:([^:]+):([^\]]+)\]\s+(.*)$/ims) || [];
188
250
  if (!type || !scope || !message)
189
251
  return args;
@@ -191,9 +253,15 @@ function enhanceH2Logs(options) {
191
253
 
192
254
  `;
193
255
  const lines = message.split("\n");
194
- const lastLine = lines.at(-1) ?? "";
256
+ let lastLine = lines.at(-1) ?? "";
195
257
  const hasLinks = /https?:\/\//.test(lastLine);
196
258
  const hasCommands = /`h2 [^`]+`/.test(lastLine);
259
+ if (hasCommands && lastLine) {
260
+ lastLine = lastLine.replace(
261
+ /`(h2) ([^`]+)`/g,
262
+ colors.magentaBright(`\`${options.cliCommand ?? "$1"} $2\``)
263
+ );
264
+ }
197
265
  if (hasLinks || hasCommands)
198
266
  lines.pop();
199
267
  if (type === "error" || errorObject) {
@@ -248,12 +316,7 @@ function enhanceH2Logs(options) {
248
316
  render({
249
317
  body: headline + colors.bold(lines.join("\n")),
250
318
  reference,
251
- nextSteps: hasCommands ? [
252
- lastLine.replace(
253
- /`h2 [^`]+`/g,
254
- (cmd) => colors.bold(colors.yellow(cmd))
255
- )
256
- ] : void 0
319
+ nextSteps: hasCommands ? [lastLine] : void 0
257
320
  });
258
321
  return;
259
322
  }
@@ -298,5 +361,15 @@ async function muteRemixLogs() {
298
361
  } catch {
299
362
  }
300
363
  }
364
+ function setH2OVerbose() {
365
+ if (!process.env.DEBUG || process.env.DEBUG === "*") {
366
+ process.env.DEBUG = "h2:*,o2:*";
367
+ } else {
368
+ process.env.DEBUG += ",h2:*,o2:*";
369
+ }
370
+ }
371
+ function isH2Verbose() {
372
+ return !!(process.env.DEBUG === "*" || process.env.DEBUG?.includes("h2:*"));
373
+ }
301
374
 
302
- export { addMessageReplacers, createRemixLogger, enhanceH2Logs, muteAuthLogs, muteDevLogs, muteRemixLogs, resetAllLogs, warnOnce };
375
+ export { addMessageReplacers, createRemixLogger, enhanceH2Logs, isH2Verbose, muteAuthLogs, muteDevLogs, muteRemixLogs, resetAllLogs, setH2OVerbose, warnOnce };
@@ -1,16 +1,24 @@
1
1
  import { outputToken, outputInfo, outputContent } from '@shopify/cli-kit/node/output';
2
2
  import colors from '@shopify/cli-kit/node/colors';
3
3
  import { DEV_ROUTES } from '../request-events.js';
4
+ import { AbortError } from '@shopify/cli-kit/node/error';
4
5
 
5
6
  const DEFAULT_INSPECTOR_PORT = 9229;
6
7
  const SUBREQUEST_PROFILER_ENDPOINT = "/debug-network-server";
7
- function logRequestLine(request, {
8
- responseStatus = 200,
9
- durationMs = 0
10
- } = {}) {
8
+ function handleMiniOxygenImportFail() {
9
+ throw new AbortError(
10
+ "Could not load MiniOxygen.",
11
+ "Please make sure you have `@shopify/mini-oxygen` installed."
12
+ );
13
+ }
14
+ function logRequestLine({
15
+ request,
16
+ response,
17
+ meta
18
+ }) {
11
19
  try {
12
20
  const url = new URL(request.url);
13
- if (DEV_ROUTES.has(url.pathname))
21
+ if (DEV_ROUTES.has(url.pathname) || url.pathname === "/favicon.ico")
14
22
  return;
15
23
  const isDataRequest = url.searchParams.has("_data");
16
24
  let route = request.url.replace(url.origin, "");
@@ -22,39 +30,17 @@ function logRequestLine(request, {
22
30
  route = url.pathname;
23
31
  info = `[${dataParam}]`;
24
32
  }
25
- const colorizeStatus = responseStatus < 300 ? outputToken.green : responseStatus < 400 ? outputToken.cyan : outputToken.errorText;
33
+ const colorizeStatus = response.status < 300 ? outputToken.green : response.status < 400 ? outputToken.cyan : outputToken.errorText;
26
34
  outputInfo(
27
35
  outputContent`${request.method.padStart(6)} ${colorizeStatus(
28
- String(responseStatus)
29
- )} ${outputToken.italic(type.padEnd(7, " "))} ${route} ${durationMs > 0 ? colors.dim(` ${durationMs}ms`) : ""}${info ? " " + colors.dim(info) : ""}${request.headers.get("purpose") === "prefetch" ? outputToken.italic(colors.dim(" prefetch")) : ""}`
36
+ String(response.status)
37
+ )} ${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")) : ""}`
30
38
  );
31
39
  } catch {
32
- if (request && responseStatus) {
33
- outputInfo(`${request.method} ${responseStatus} ${request.url}`);
40
+ if (request && response?.status) {
41
+ outputInfo(`${request.method} ${response.status} ${request.url}`);
34
42
  }
35
43
  }
36
44
  }
37
- const OXYGEN_HEADERS_MAP = {
38
- ip: { name: "oxygen-buyer-ip", defaultValue: "127.0.0.1" },
39
- longitude: { name: "oxygen-buyer-longitude", defaultValue: "-122.40140" },
40
- latitude: { name: "oxygen-buyer-latitude", defaultValue: "37.78855" },
41
- continent: { name: "oxygen-buyer-continent", defaultValue: "NA" },
42
- country: { name: "oxygen-buyer-country", defaultValue: "US" },
43
- region: { name: "oxygen-buyer-region", defaultValue: "California" },
44
- regionCode: { name: "oxygen-buyer-region-code", defaultValue: "CA" },
45
- city: { name: "oxygen-buyer-city", defaultValue: "San Francisco" },
46
- isEuCountry: { name: "oxygen-buyer-is-eu-country", defaultValue: "" },
47
- timezone: {
48
- name: "oxygen-buyer-timezone",
49
- defaultValue: "America/Los_Angeles"
50
- },
51
- // Not documented but available in Oxygen:
52
- deploymentId: { name: "oxygen-buyer-deployment-id", defaultValue: "local" },
53
- shopId: { name: "oxygen-buyer-shop-id", defaultValue: "development" },
54
- storefrontId: {
55
- name: "oxygen-buyer-storefront-id",
56
- defaultValue: "development"
57
- }
58
- };
59
45
 
60
- export { DEFAULT_INSPECTOR_PORT, OXYGEN_HEADERS_MAP, SUBREQUEST_PROFILER_ENDPOINT, logRequestLine };
46
+ export { DEFAULT_INSPECTOR_PORT, SUBREQUEST_PROFILER_ENDPOINT, handleMiniOxygenImportFail, logRequestLine };
@@ -1,6 +1,10 @@
1
+ import { handleMiniOxygenImportFail } from './common.js';
1
2
  export { DEFAULT_INSPECTOR_PORT } from './common.js';
2
- export { buildAssetsUrl } from './assets.js';
3
3
 
4
+ async function buildAssetsUrl(port) {
5
+ const { buildAssetsUrl: _buildAssetsUrl } = await import('@shopify/mini-oxygen').catch(handleMiniOxygenImportFail);
6
+ return _buildAssetsUrl(port);
7
+ }
4
8
  async function startMiniOxygen(options, useNodeRuntime = false) {
5
9
  if (useNodeRuntime) {
6
10
  process.env.MINIFLARE_SUBREQUEST_LIMIT = 100;
@@ -11,4 +15,4 @@ async function startMiniOxygen(options, useNodeRuntime = false) {
11
15
  return startWorkerdServer(options);
12
16
  }
13
17
 
14
- export { startMiniOxygen };
18
+ export { buildAssetsUrl, startMiniOxygen };
@@ -1,14 +1,16 @@
1
- import { randomUUID } from 'node:crypto';
2
1
  import { AsyncLocalStorage } from 'node:async_hooks';
3
2
  import { readFile } from '@shopify/cli-kit/node/fs';
4
3
  import { renderSuccess } from '@shopify/cli-kit/node/ui';
5
- import { Response, startServer, Request } from '@shopify/mini-oxygen';
6
- import { DEFAULT_PORT } from '../flags.js';
7
- import { OXYGEN_HEADERS_MAP, SUBREQUEST_PROFILER_ENDPOINT, logRequestLine } from './common.js';
4
+ import colors from '@shopify/cli-kit/node/colors';
5
+ import { DEFAULT_INSPECTOR_PORT } from '../flags.js';
6
+ import { handleMiniOxygenImportFail, SUBREQUEST_PROFILER_ENDPOINT, logRequestLine } from './common.js';
8
7
  import { setConstructors, createLogRequestEvent, handleDebugNetworkRequest, H2O_BINDING_NAME } from '../request-events.js';
8
+ import { findPort } from '../find-port.js';
9
+ import { getUtilityBannerlines } from '../dev-shared.js';
10
+ import { outputNewline } from '@shopify/cli-kit/node/output';
9
11
 
10
12
  async function startNodeServer({
11
- port = DEFAULT_PORT,
13
+ appPort,
12
14
  watch = false,
13
15
  buildPathWorkerFile,
14
16
  buildPathClient,
@@ -16,11 +18,7 @@ async function startNodeServer({
16
18
  debug = false,
17
19
  inspectorPort
18
20
  }) {
19
- const oxygenHeaders = Object.fromEntries(
20
- Object.entries(OXYGEN_HEADERS_MAP).map(([key, value]) => {
21
- return [key, value.defaultValue];
22
- })
23
- );
21
+ const { startServer, Request, Response } = await import('@shopify/mini-oxygen/node').catch(handleMiniOxygenImportFail);
24
22
  setConstructors({ Response });
25
23
  const logRequestEvent = createLogRequestEvent();
26
24
  const asyncLocalStorage = new AsyncLocalStorage();
@@ -38,6 +36,8 @@ async function startNodeServer({
38
36
  }
39
37
  };
40
38
  if (debug) {
39
+ if (!inspectorPort)
40
+ inspectorPort = await findPort(DEFAULT_INSPECTOR_PORT);
41
41
  (await import('node:inspector')).open(inspectorPort);
42
42
  }
43
43
  const miniOxygen = await startServer({
@@ -45,7 +45,7 @@ async function startNodeServer({
45
45
  workerFile: buildPathWorkerFile,
46
46
  assetsDir: buildPathClient,
47
47
  publicPath: "",
48
- port,
48
+ port: appPort,
49
49
  watch,
50
50
  autoReload: watch,
51
51
  modules: true,
@@ -56,25 +56,34 @@ async function startNodeServer({
56
56
  },
57
57
  log: () => {
58
58
  },
59
- oxygenHeaders,
60
59
  async onRequest(request, defaultDispatcher) {
61
60
  const url = new URL(request.url);
62
61
  if (url.pathname === SUBREQUEST_PROFILER_ENDPOINT) {
63
62
  return handleDebugNetworkRequest(request);
64
63
  }
65
- let requestId = request.headers.get("request-id");
66
- if (!requestId) {
67
- requestId = randomUUID();
68
- request.headers.set("request-id", requestId);
69
- }
64
+ const requestId = request.headers.get("request-id");
70
65
  const startTimeMs = Date.now();
71
66
  const response = await asyncLocalStorage.run(
72
67
  { requestId, purpose: request.headers.get("purpose") },
73
68
  () => defaultDispatcher(request)
74
69
  );
75
- logRequestLine(request, {
76
- responseStatus: response.status,
77
- durationMs: startTimeMs > 0 ? Date.now() - startTimeMs : 0
70
+ const endTimeMs = Date.now();
71
+ logRequestLine({
72
+ request: {
73
+ url: request.url,
74
+ method: request.method,
75
+ headers: Object.fromEntries(request.headers.entries())
76
+ },
77
+ response: {
78
+ status: response.status,
79
+ statusText: response.statusText,
80
+ headers: Object.fromEntries(response.headers.entries())
81
+ },
82
+ meta: {
83
+ startTimeMs,
84
+ endTimeMs,
85
+ durationMs: startTimeMs > 0 ? endTimeMs - startTimeMs : 0
86
+ }
78
87
  });
79
88
  return response;
80
89
  }
@@ -95,20 +104,23 @@ async function startNodeServer({
95
104
  await miniOxygen.reload(nextOptions);
96
105
  },
97
106
  showBanner(options) {
98
- console.log("");
107
+ outputNewline();
108
+ const customSections = [];
109
+ if (options?.host) {
110
+ customSections.push({ body: getUtilityBannerlines(options.host) });
111
+ }
112
+ if (debug && inspectorPort) {
113
+ customSections.push({
114
+ body: { warn: `Debugger listening on ws://localhost:${inspectorPort}` }
115
+ });
116
+ }
99
117
  renderSuccess({
100
118
  headline: `${options?.headlinePrefix ?? ""}MiniOxygen (Node Sandbox) ${options?.mode ?? "development"} server running.`,
101
119
  body: [
102
- `View ${options?.appName ?? "Hydrogen"} app: ${listeningAt}`,
103
- ...options?.extraLines ?? [],
104
- ...debug ? [
105
- {
106
- warn: `
107
-
108
- Debugger listening on ws://localhost:${inspectorPort}`
109
- }
110
- ] : []
111
- ]
120
+ `View ${options?.appName ? colors.cyan(options?.appName) : "Hydrogen"} app:`,
121
+ { link: { url: options?.host || listeningAt } }
122
+ ],
123
+ customSections
112
124
  });
113
125
  console.log("");
114
126
  },