@shopify/cli-hydrogen 6.0.2 → 6.1.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.
- package/dist/commands/hydrogen/deploy.js +72 -8
- package/dist/commands/hydrogen/deploy.test.js +111 -9
- package/dist/commands/hydrogen/dev.js +33 -23
- package/dist/commands/hydrogen/preview.js +20 -10
- package/dist/commands/hydrogen/shortcut.js +1 -0
- package/dist/commands/hydrogen/upgrade.js +705 -0
- package/dist/commands/hydrogen/upgrade.test.js +786 -0
- package/dist/generator-templates/starter/CHANGELOG.md +70 -0
- package/dist/generator-templates/starter/app/components/Footer.tsx +3 -1
- package/dist/generator-templates/starter/app/components/Layout.tsx +13 -10
- package/dist/generator-templates/starter/app/routes/[robots.txt].tsx +0 -27
- package/dist/generator-templates/starter/package.json +10 -9
- package/dist/generator-templates/starter/remix.env.d.ts +2 -0
- package/dist/lib/check-lockfile.js +1 -0
- package/dist/lib/codegen.js +1 -0
- package/dist/lib/flags.js +13 -2
- package/dist/lib/log.js +1 -0
- package/dist/lib/mini-oxygen/assets.js +118 -0
- package/dist/lib/mini-oxygen/common.js +2 -1
- package/dist/lib/mini-oxygen/index.js +3 -0
- package/dist/lib/mini-oxygen/node.js +15 -3
- package/dist/lib/mini-oxygen/workerd-inspector-logs.js +227 -0
- package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +200 -0
- package/dist/lib/mini-oxygen/workerd-inspector.js +62 -235
- package/dist/lib/mini-oxygen/workerd.js +54 -47
- package/dist/lib/render-errors.js +2 -0
- package/dist/lib/setups/i18n/replacers.test.js +2 -0
- package/dist/lib/shell.js +1 -1
- package/oclif.manifest.json +90 -8
- package/package.json +10 -21
|
@@ -1,22 +1,59 @@
|
|
|
1
1
|
import { dirname } from 'node:path';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { fetch } from '@shopify/cli-kit/node/http';
|
|
3
4
|
import { SourceMapConsumer } from 'source-map';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
5
|
+
import { WebSocket } from 'ws';
|
|
6
|
+
import { addInspectorConsoleLogger, formatStack } from './workerd-inspector-logs.js';
|
|
7
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
8
|
+
import { createInspectorProxy } from './workerd-inspector-proxy.js';
|
|
6
9
|
|
|
10
|
+
function createInspectorConnector(options) {
|
|
11
|
+
let inspectorUrl;
|
|
12
|
+
let inspectorConnection;
|
|
13
|
+
let inspectorProxy;
|
|
14
|
+
return async (onBeforeConnect) => {
|
|
15
|
+
inspectorConnection?.close();
|
|
16
|
+
inspectorUrl ??= await findInspectorUrl(options.privateInspectorPort);
|
|
17
|
+
await onBeforeConnect?.();
|
|
18
|
+
inspectorConnection = connectToInspector({
|
|
19
|
+
inspectorUrl,
|
|
20
|
+
sourceMapPath: options.sourceMapPath
|
|
21
|
+
});
|
|
22
|
+
addInspectorConsoleLogger(inspectorConnection);
|
|
23
|
+
if (options.debug) {
|
|
24
|
+
if (inspectorProxy) {
|
|
25
|
+
inspectorProxy.updateInspectorConnection(inspectorConnection);
|
|
26
|
+
} else {
|
|
27
|
+
inspectorProxy = createInspectorProxy(
|
|
28
|
+
options.publicInspectorPort,
|
|
29
|
+
options.absoluteBundlePath,
|
|
30
|
+
inspectorConnection
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
7
36
|
async function findInspectorUrl(inspectorPort) {
|
|
8
37
|
try {
|
|
9
38
|
const jsonUrl = `http://127.0.0.1:${inspectorPort}/json`;
|
|
10
39
|
const body = await (await fetch(jsonUrl)).json();
|
|
11
|
-
|
|
40
|
+
const url = body?.find(
|
|
41
|
+
({ id }) => id === "core:user:hydrogen"
|
|
42
|
+
)?.webSocketDebuggerUrl;
|
|
43
|
+
if (!url) {
|
|
44
|
+
throw new Error("Unable to find inspector URL");
|
|
45
|
+
}
|
|
46
|
+
return url;
|
|
12
47
|
} catch (error) {
|
|
13
|
-
|
|
48
|
+
const abortError = new AbortError(
|
|
49
|
+
"Unable to connect to Worker inspector",
|
|
50
|
+
`Please report this issue. ${error.stack}`
|
|
51
|
+
);
|
|
52
|
+
abortError.stack = error.stack;
|
|
53
|
+
throw abortError;
|
|
14
54
|
}
|
|
15
55
|
}
|
|
16
|
-
function connectToInspector({
|
|
17
|
-
inspectorUrl,
|
|
18
|
-
sourceMapPath
|
|
19
|
-
}) {
|
|
56
|
+
function connectToInspector({ inspectorUrl, sourceMapPath }) {
|
|
20
57
|
const messageCounterRef = { value: -1 };
|
|
21
58
|
const getMessageId = () => messageCounterRef.value--;
|
|
22
59
|
const pendingMessages = /* @__PURE__ */ new Map();
|
|
@@ -147,42 +184,6 @@ function connectToInspector({
|
|
|
147
184
|
}
|
|
148
185
|
})();
|
|
149
186
|
};
|
|
150
|
-
ws.addEventListener("message", async (event) => {
|
|
151
|
-
if (typeof event.data === "string") {
|
|
152
|
-
const evt = JSON.parse(event.data);
|
|
153
|
-
cleanupMessageQueue(evt);
|
|
154
|
-
if (evt.method === "Runtime.exceptionThrown") {
|
|
155
|
-
const params = evt.params;
|
|
156
|
-
const errorProperties = {};
|
|
157
|
-
const sourceMapConsumer = await getSourceMapConsumer();
|
|
158
|
-
if (sourceMapConsumer !== void 0) {
|
|
159
|
-
const message = params.exceptionDetails.exception?.description?.split("\n")[0];
|
|
160
|
-
const stack = params.exceptionDetails.stackTrace?.callFrames;
|
|
161
|
-
const formatted = formatStructuredError(
|
|
162
|
-
sourceMapConsumer,
|
|
163
|
-
message,
|
|
164
|
-
stack
|
|
165
|
-
);
|
|
166
|
-
errorProperties.message = params.exceptionDetails.text;
|
|
167
|
-
errorProperties.stack = formatted;
|
|
168
|
-
} else {
|
|
169
|
-
errorProperties.message = params.exceptionDetails.text + " " + (params.exceptionDetails.exception?.description ?? "");
|
|
170
|
-
}
|
|
171
|
-
console.error(
|
|
172
|
-
await reconstructError(
|
|
173
|
-
errorProperties,
|
|
174
|
-
params.exceptionDetails.exception
|
|
175
|
-
)
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
if (evt.method === "Runtime.consoleAPICalled") {
|
|
179
|
-
const params = evt.params;
|
|
180
|
-
await logConsoleMessage(params, reconstructError);
|
|
181
|
-
}
|
|
182
|
-
} else {
|
|
183
|
-
console.error("Unrecognised devtools event:", event);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
187
|
ws.once("open", () => {
|
|
187
188
|
send("Runtime.enable");
|
|
188
189
|
keepAliveInterval = setInterval(() => send("Runtime.getIsolateId"), 1e4);
|
|
@@ -194,199 +195,25 @@ function connectToInspector({
|
|
|
194
195
|
clearInterval(keepAliveInterval);
|
|
195
196
|
sourceMapAbortController.abort();
|
|
196
197
|
});
|
|
197
|
-
return
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
info: "info",
|
|
212
|
-
warning: "warn",
|
|
213
|
-
error: "error",
|
|
214
|
-
dir: "dir",
|
|
215
|
-
dirxml: "dirxml",
|
|
216
|
-
table: "table",
|
|
217
|
-
trace: "trace",
|
|
218
|
-
clear: "clear",
|
|
219
|
-
count: "count",
|
|
220
|
-
assert: "assert",
|
|
221
|
-
profile: "profile",
|
|
222
|
-
profileEnd: "profileEnd",
|
|
223
|
-
timeEnd: "timeEnd",
|
|
224
|
-
startGroup: "group",
|
|
225
|
-
startGroupCollapsed: "groupCollapsed",
|
|
226
|
-
endGroup: "groupEnd"
|
|
227
|
-
};
|
|
228
|
-
async function logConsoleMessage(evt, reconstructError) {
|
|
229
|
-
const args = [];
|
|
230
|
-
for (const ro of evt.args) {
|
|
231
|
-
switch (ro.type) {
|
|
232
|
-
case "string":
|
|
233
|
-
case "number":
|
|
234
|
-
case "boolean":
|
|
235
|
-
case "undefined":
|
|
236
|
-
case "symbol":
|
|
237
|
-
case "bigint":
|
|
238
|
-
args.push(ro.value);
|
|
239
|
-
break;
|
|
240
|
-
case "function":
|
|
241
|
-
args.push(`[Function: ${ro.description ?? "<no-description>"}]`);
|
|
242
|
-
break;
|
|
243
|
-
case "object":
|
|
244
|
-
if (!ro.preview) {
|
|
245
|
-
args.push(
|
|
246
|
-
ro.subtype === "null" ? "null" : ro.description ?? "<no-description>"
|
|
247
|
-
);
|
|
248
|
-
} else {
|
|
249
|
-
if (ro.preview.description)
|
|
250
|
-
args.push(ro.preview.description);
|
|
251
|
-
switch (ro.preview.subtype) {
|
|
252
|
-
case "array":
|
|
253
|
-
args.push(
|
|
254
|
-
"[ " + ro.preview.properties.map(({ value }) => {
|
|
255
|
-
return value;
|
|
256
|
-
}).join(", ") + (ro.preview.overflow ? "..." : "") + " ]"
|
|
257
|
-
);
|
|
258
|
-
break;
|
|
259
|
-
case "weakmap":
|
|
260
|
-
case "map":
|
|
261
|
-
ro.preview.entries === void 0 ? args.push("{}") : args.push(
|
|
262
|
-
"{\n" + ro.preview.entries.map(({ key, value }) => {
|
|
263
|
-
return ` ${key?.description ?? "<unknown>"} => ${value.description}`;
|
|
264
|
-
}).join(",\n") + (ro.preview.overflow ? "\n ..." : "") + "\n}"
|
|
265
|
-
);
|
|
266
|
-
break;
|
|
267
|
-
case "weakset":
|
|
268
|
-
case "set":
|
|
269
|
-
ro.preview.entries === void 0 ? args.push("{}") : args.push(
|
|
270
|
-
"{ " + ro.preview.entries.map(({ value }) => {
|
|
271
|
-
return `${value.description}`;
|
|
272
|
-
}).join(", ") + (ro.preview.overflow ? ", ..." : "") + " }"
|
|
273
|
-
);
|
|
274
|
-
break;
|
|
275
|
-
case "regexp":
|
|
276
|
-
break;
|
|
277
|
-
case "date":
|
|
278
|
-
break;
|
|
279
|
-
case "generator":
|
|
280
|
-
args.push(ro.preview?.properties[0]?.value || "");
|
|
281
|
-
break;
|
|
282
|
-
case "promise":
|
|
283
|
-
if (ro.preview?.properties[0]?.value === "pending") {
|
|
284
|
-
args.push(`{<${ro.preview.properties[0].value}>}`);
|
|
285
|
-
} else {
|
|
286
|
-
args.push(
|
|
287
|
-
`{<${ro.preview?.properties[0]?.value}>: ${ro.preview?.properties[1]?.value}}`
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
break;
|
|
291
|
-
case "node":
|
|
292
|
-
case "iterator":
|
|
293
|
-
case "proxy":
|
|
294
|
-
case "typedarray":
|
|
295
|
-
case "arraybuffer":
|
|
296
|
-
case "dataview":
|
|
297
|
-
case "webassemblymemory":
|
|
298
|
-
case "wasmvalue":
|
|
299
|
-
break;
|
|
300
|
-
case "error":
|
|
301
|
-
const errorProperties = {
|
|
302
|
-
message: ro.preview.description?.split("\n").filter((line) => !/^\s+at\s/.test(line)).join("\n") ?? ro.preview.properties.find(({ name }) => name === "message")?.value ?? "",
|
|
303
|
-
stack: ro.preview.description ?? ro.description ?? ro.preview.properties.find(({ name }) => name === "stack")?.value,
|
|
304
|
-
cause: ro.preview.properties.find(({ name }) => name === "cause")?.value
|
|
305
|
-
};
|
|
306
|
-
const error = await reconstructError(errorProperties, ro);
|
|
307
|
-
args.splice(-1, 1, error);
|
|
308
|
-
break;
|
|
309
|
-
default:
|
|
310
|
-
args.push(
|
|
311
|
-
"{\n" + ro.preview.properties.map(({ name, value }) => {
|
|
312
|
-
return ` ${name}: ${value}`;
|
|
313
|
-
}).join(",\n") + (ro.preview.overflow ? "\n ..." : "") + "\n}"
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
break;
|
|
318
|
-
default:
|
|
319
|
-
args.push(ro.description || ro.unserializableValue || "\u{1F98B}");
|
|
320
|
-
break;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
const method = mapConsoleAPIMessageTypeToConsoleMethod[evt.type];
|
|
324
|
-
if (method in console) {
|
|
325
|
-
switch (method) {
|
|
326
|
-
case "dir":
|
|
327
|
-
console.dir(args);
|
|
328
|
-
break;
|
|
329
|
-
case "table":
|
|
330
|
-
console.table(args);
|
|
331
|
-
break;
|
|
332
|
-
default:
|
|
333
|
-
console[method].apply(console, args);
|
|
334
|
-
break;
|
|
335
|
-
}
|
|
336
|
-
} else {
|
|
337
|
-
console.warn(`Unsupported console method: ${method}`);
|
|
338
|
-
console.warn("console event:", evt);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
function formatStructuredError(sourceMapConsumer, message, frames) {
|
|
342
|
-
const lines = [];
|
|
343
|
-
if (message !== void 0)
|
|
344
|
-
lines.push(message);
|
|
345
|
-
frames?.forEach(({ functionName, lineNumber, columnNumber }, i) => {
|
|
346
|
-
try {
|
|
347
|
-
if (lineNumber) {
|
|
348
|
-
const pos = sourceMapConsumer.originalPositionFor({
|
|
349
|
-
line: lineNumber + 1,
|
|
350
|
-
column: columnNumber
|
|
351
|
-
});
|
|
352
|
-
if (i === 0 && pos.source && pos.line) {
|
|
353
|
-
const fileSource = sourceMapConsumer.sourceContentFor(pos.source);
|
|
354
|
-
const fileSourceLine = fileSource?.split("\n")[pos.line - 1] || "";
|
|
355
|
-
lines.push(fileSourceLine.trim());
|
|
356
|
-
if (pos.column) {
|
|
357
|
-
lines.push(
|
|
358
|
-
`${" ".repeat(pos.column - fileSourceLine.search(/\S/))}^`
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
if (pos && pos.line !== null && pos.column !== null) {
|
|
363
|
-
const convertedFnName = pos.name || functionName || "";
|
|
364
|
-
let convertedLocation = `${pos.source}:${pos.line}:${pos.column + 1}`;
|
|
365
|
-
if (convertedFnName === "") {
|
|
366
|
-
lines.push(` at ${convertedLocation}`);
|
|
367
|
-
} else {
|
|
368
|
-
lines.push(` at ${convertedFnName} (${convertedLocation})`);
|
|
369
|
-
}
|
|
198
|
+
return {
|
|
199
|
+
ws,
|
|
200
|
+
send,
|
|
201
|
+
reconstructError,
|
|
202
|
+
getSourceMapConsumer,
|
|
203
|
+
cleanupMessageQueue,
|
|
204
|
+
isClosed,
|
|
205
|
+
close: () => {
|
|
206
|
+
clearInterval(keepAliveInterval);
|
|
207
|
+
if (!isClosed()) {
|
|
208
|
+
try {
|
|
209
|
+
ws.removeAllListeners();
|
|
210
|
+
ws.close();
|
|
211
|
+
} catch (err) {
|
|
370
212
|
}
|
|
371
213
|
}
|
|
372
|
-
|
|
214
|
+
sourceMapAbortController.abort();
|
|
373
215
|
}
|
|
374
|
-
}
|
|
375
|
-
return lines.join("\n");
|
|
376
|
-
}
|
|
377
|
-
function formatStack(sourceMapConsumer, stack) {
|
|
378
|
-
const message = stack.split("\n")[0];
|
|
379
|
-
const callSites = parse({ stack });
|
|
380
|
-
const frames = callSites.map((site) => ({
|
|
381
|
-
functionName: site.getFunctionName() ?? "",
|
|
382
|
-
// `Protocol.Runtime.CallFrame`s line numbers are 0-indexed, hence `- 1`
|
|
383
|
-
lineNumber: (site.getLineNumber() ?? 1) - 1,
|
|
384
|
-
columnNumber: site.getColumnNumber() ?? 1,
|
|
385
|
-
// Unused by `formattedError`
|
|
386
|
-
scriptId: "",
|
|
387
|
-
url: ""
|
|
388
|
-
}));
|
|
389
|
-
return formatStructuredError(sourceMapConsumer, message, frames);
|
|
216
|
+
};
|
|
390
217
|
}
|
|
391
218
|
|
|
392
|
-
export {
|
|
219
|
+
export { createInspectorConnector };
|
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { Response, Miniflare, fetch, Request, NoOpLog } from 'miniflare';
|
|
3
|
+
import { resolvePath, dirname } from '@shopify/cli-kit/node/path';
|
|
4
|
+
import { readFile } from '@shopify/cli-kit/node/fs';
|
|
4
5
|
import { renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
5
|
-
import {
|
|
6
|
-
import { findInspectorUrl, connectToInspector } from './workerd-inspector.js';
|
|
7
|
-
import { DEFAULT_PORT } from '../flags.js';
|
|
6
|
+
import { createInspectorConnector } from './workerd-inspector.js';
|
|
8
7
|
import { findPort } from '../find-port.js';
|
|
9
8
|
import { OXYGEN_HEADERS_MAP, logRequestLine } from './common.js';
|
|
10
9
|
import { setConstructors, handleDebugNetworkRequest, H2O_BINDING_NAME, logRequestEvent } from '../request-events.js';
|
|
10
|
+
import { STATIC_ASSET_EXTENSIONS, createAssetsServer, buildAssetsUrl } from './assets.js';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const PRIVATE_WORKERD_INSPECTOR_PORT = 9222;
|
|
13
13
|
async function startWorkerdServer({
|
|
14
14
|
root,
|
|
15
|
-
port
|
|
15
|
+
port: appPort,
|
|
16
|
+
inspectorPort: publicInspectorPort,
|
|
17
|
+
assetsPort,
|
|
18
|
+
debug = false,
|
|
16
19
|
watch = false,
|
|
17
20
|
buildPathWorkerFile,
|
|
18
21
|
buildPathClient,
|
|
19
22
|
env
|
|
20
23
|
}) {
|
|
21
|
-
const
|
|
22
|
-
const inspectorPort = await findPort(DEFAULT_INSPECTOR_PORT);
|
|
24
|
+
const privateInspectorPort = await findPort(PRIVATE_WORKERD_INSPECTOR_PORT);
|
|
23
25
|
const oxygenHeadersMap = Object.values(OXYGEN_HEADERS_MAP).reduce(
|
|
24
26
|
(acc, item) => {
|
|
25
27
|
acc[item.name] = item.defaultValue;
|
|
@@ -28,11 +30,14 @@ async function startWorkerdServer({
|
|
|
28
30
|
{}
|
|
29
31
|
);
|
|
30
32
|
setConstructors({ Response });
|
|
33
|
+
const absoluteBundlePath = resolvePath(root, buildPathWorkerFile);
|
|
34
|
+
const handleAssets = createAssetHandler(assetsPort);
|
|
35
|
+
const staticAssetExtensions = STATIC_ASSET_EXTENSIONS.slice();
|
|
31
36
|
const buildMiniOxygenOptions = async () => ({
|
|
32
37
|
cf: false,
|
|
33
38
|
verbose: false,
|
|
34
39
|
port: appPort,
|
|
35
|
-
inspectorPort,
|
|
40
|
+
inspectorPort: privateInspectorPort,
|
|
36
41
|
log: new NoOpLog(),
|
|
37
42
|
liveReload: watch,
|
|
38
43
|
host: "localhost",
|
|
@@ -42,23 +47,24 @@ async function startWorkerdServer({
|
|
|
42
47
|
modules: true,
|
|
43
48
|
script: `export default { fetch: ${miniOxygenHandler.toString()} }`,
|
|
44
49
|
bindings: {
|
|
45
|
-
|
|
50
|
+
staticAssetExtensions,
|
|
46
51
|
oxygenHeadersMap
|
|
47
52
|
},
|
|
48
53
|
serviceBindings: {
|
|
49
54
|
hydrogen: "hydrogen",
|
|
50
|
-
assets:
|
|
55
|
+
assets: handleAssets,
|
|
51
56
|
debugNetwork: handleDebugNetworkRequest,
|
|
52
57
|
logRequest
|
|
53
58
|
}
|
|
54
59
|
},
|
|
55
60
|
{
|
|
56
61
|
name: "hydrogen",
|
|
62
|
+
modulesRoot: dirname(absoluteBundlePath),
|
|
57
63
|
modules: [
|
|
58
64
|
{
|
|
59
65
|
type: "ESModule",
|
|
60
|
-
path:
|
|
61
|
-
contents: await readFile(
|
|
66
|
+
path: absoluteBundlePath,
|
|
67
|
+
contents: await readFile(absoluteBundlePath)
|
|
62
68
|
}
|
|
63
69
|
],
|
|
64
70
|
compatibilityFlags: ["streams_enable_constructors"],
|
|
@@ -74,8 +80,16 @@ async function startWorkerdServer({
|
|
|
74
80
|
const miniOxygen = new Miniflare(miniOxygenOptions);
|
|
75
81
|
const listeningAt = (await miniOxygen.ready).origin;
|
|
76
82
|
const sourceMapPath = buildPathWorkerFile + ".map";
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
const reconnect = createInspectorConnector({
|
|
84
|
+
debug,
|
|
85
|
+
sourceMapPath,
|
|
86
|
+
absoluteBundlePath,
|
|
87
|
+
privateInspectorPort,
|
|
88
|
+
publicInspectorPort
|
|
89
|
+
});
|
|
90
|
+
await reconnect();
|
|
91
|
+
const assetsServer = createAssetsServer(buildPathClient);
|
|
92
|
+
assetsServer.listen(assetsPort);
|
|
79
93
|
return {
|
|
80
94
|
port: appPort,
|
|
81
95
|
listeningAt,
|
|
@@ -89,25 +103,27 @@ async function startWorkerdServer({
|
|
|
89
103
|
hydrogen.bindings = { ...nextOptions?.env ?? env };
|
|
90
104
|
}
|
|
91
105
|
}
|
|
92
|
-
|
|
93
|
-
await miniOxygen.setOptions(miniOxygenOptions);
|
|
94
|
-
inspectorUrl ??= await findInspectorUrl(inspectorPort);
|
|
95
|
-
if (inspectorUrl) {
|
|
96
|
-
cleanupInspector = connectToInspector({ inspectorUrl, sourceMapPath });
|
|
97
|
-
}
|
|
106
|
+
await reconnect(() => miniOxygen.setOptions(miniOxygenOptions));
|
|
98
107
|
},
|
|
99
108
|
showBanner(options) {
|
|
100
109
|
console.log("");
|
|
110
|
+
const debuggerMessage = `
|
|
111
|
+
|
|
112
|
+
Debug mode enabled. Attach a ${process.env.TERM_PROGRAM === "vscode" ? "VSCode " : ""}debugger to port ${publicInspectorPort}
|
|
113
|
+
or open DevTools in http://localhost:${publicInspectorPort}`;
|
|
101
114
|
renderSuccess({
|
|
102
|
-
headline: `${options?.headlinePrefix ?? ""}MiniOxygen (
|
|
115
|
+
headline: `${options?.headlinePrefix ?? ""}MiniOxygen (Worker Runtime) ${options?.mode ?? "development"} server running.`,
|
|
103
116
|
body: [
|
|
104
117
|
`View ${options?.appName ?? "Hydrogen"} app: ${listeningAt}`,
|
|
105
|
-
...options?.extraLines ?? []
|
|
118
|
+
...options?.extraLines ?? [],
|
|
119
|
+
...debug ? [{ warn: debuggerMessage }] : []
|
|
106
120
|
]
|
|
107
121
|
});
|
|
108
122
|
console.log("");
|
|
109
123
|
},
|
|
110
124
|
async close() {
|
|
125
|
+
assetsServer.closeAllConnections();
|
|
126
|
+
assetsServer.close();
|
|
111
127
|
await miniOxygen.dispose();
|
|
112
128
|
}
|
|
113
129
|
};
|
|
@@ -118,7 +134,11 @@ async function miniOxygenHandler(request, env, context) {
|
|
|
118
134
|
return env.debugNetwork.fetch(request);
|
|
119
135
|
}
|
|
120
136
|
if (request.method === "GET") {
|
|
121
|
-
|
|
137
|
+
const staticAssetExtensions = new Set(env.staticAssetExtensions);
|
|
138
|
+
const wellKnown = pathname.startsWith("/.well-known");
|
|
139
|
+
const extension = pathname.split(".").at(-1) ?? "";
|
|
140
|
+
const isAsset = wellKnown || !!staticAssetExtensions.has(extension.toUpperCase());
|
|
141
|
+
if (isAsset) {
|
|
122
142
|
const response2 = await env.assets.fetch(
|
|
123
143
|
new Request(request.url, {
|
|
124
144
|
signal: request.signal,
|
|
@@ -154,28 +174,15 @@ async function miniOxygenHandler(request, env, context) {
|
|
|
154
174
|
);
|
|
155
175
|
return response;
|
|
156
176
|
}
|
|
157
|
-
function createAssetHandler(
|
|
177
|
+
function createAssetHandler(assetsPort) {
|
|
178
|
+
const assetsServerOrigin = buildAssetsUrl(assetsPort);
|
|
158
179
|
return async (request) => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
);
|
|
166
|
-
return new Response(createFileReadStream(absoluteAssetPath), {
|
|
167
|
-
headers: {
|
|
168
|
-
"Content-Type": lookupMimeType(relativeAssetPath) || "text/plain",
|
|
169
|
-
"Content-Length": String(await fileSize(absoluteAssetPath))
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
} catch (error) {
|
|
173
|
-
if (error.code !== "ENOENT") {
|
|
174
|
-
throw error;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return new Response("Not Found", { status: 404 });
|
|
180
|
+
return fetch(
|
|
181
|
+
new Request(
|
|
182
|
+
request.url.replace(new URL(request.url).origin, assetsServerOrigin),
|
|
183
|
+
request
|
|
184
|
+
)
|
|
185
|
+
);
|
|
179
186
|
};
|
|
180
187
|
}
|
|
181
188
|
async function logRequest(request) {
|
|
@@ -14,6 +14,7 @@ function renderMissingStorefront({
|
|
|
14
14
|
message: outputContent`${outputToken.errorText(
|
|
15
15
|
"Couldn\u2019t find Hydrogen storefront."
|
|
16
16
|
)}`.value,
|
|
17
|
+
skipOclifErrorHandling: true,
|
|
17
18
|
tryMessage: outputContent`Couldn’t find ${storefront.title} (ID: ${parseGid(
|
|
18
19
|
storefront.id
|
|
19
20
|
)}) on ${session.storeFqdn}. Check that the storefront exists and run ${outputToken.genericShellCommand(
|
|
@@ -29,6 +30,7 @@ function renderMissingLink({ session, cliCommand }) {
|
|
|
29
30
|
name: "NoLinkedStorefrontError",
|
|
30
31
|
type: 0,
|
|
31
32
|
message: `No linked Hydrogen storefront on ${session.storeFqdn}`,
|
|
33
|
+
skipOclifErrorHandling: true,
|
|
32
34
|
tryMessage: [
|
|
33
35
|
"To pull environment variables or to deploy to Oxygen, link this project to a Hydrogen storefront. To select a storefront to link, run",
|
|
34
36
|
{ command: `${cliCommand} link` }
|
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
|
}
|