@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
@@ -0,0 +1,200 @@
1
+ import crypto from 'node:crypto';
2
+ import { readFileSync } from 'node:fs';
3
+ import { createServer } from 'node:http';
4
+ import { WebSocketServer } from 'ws';
5
+ import { request } from 'undici';
6
+
7
+ const CFW_DEVTOOLS = "https://devtools.devprod.cloudflare.dev";
8
+ const H2_FAVICON_URL = "https://cdn.shopify.com/s/files/1/0598/4822/8886/files/favicon.svg";
9
+ function createInspectorProxy(port, sourceFilePath, newInspectorConnection) {
10
+ const sessionId = crypto.randomUUID();
11
+ let debuggerWs = void 0;
12
+ let inspector = newInspectorConnection;
13
+ let isDevToolsInBrowser = false;
14
+ const sourceMapPathname = "/__index.js.map";
15
+ const sourceMapURL = `http://localhost:${port}${sourceMapPathname}`;
16
+ const server = createServer((req, res) => {
17
+ const [url = "/", queryString = ""] = req.url?.split("?") || [];
18
+ switch (url) {
19
+ case "/json/version":
20
+ res.setHeader("Content-Type", "application/json");
21
+ res.end(
22
+ JSON.stringify({ Browser: "hydrogen/v2", "Protocol-Version": "1.3" })
23
+ );
24
+ break;
25
+ case "/json":
26
+ case "/json/list":
27
+ {
28
+ res.setHeader("Content-Type", "application/json");
29
+ const localHost = `localhost:${port}/ws`;
30
+ const devtoolsFrontendUrl = `devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=${localHost}`;
31
+ const devtoolsFrontendUrlCompat = `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=${localHost}`;
32
+ res.end(
33
+ JSON.stringify([
34
+ {
35
+ id: sessionId,
36
+ type: "node",
37
+ webSocketDebuggerUrl: `ws://${localHost}`,
38
+ devtoolsFrontendUrl,
39
+ devtoolsFrontendUrlCompat,
40
+ // Below are fields that are visible in the DevTools UI.
41
+ title: "Hydrogen / Oxygen Worker",
42
+ faviconUrl: H2_FAVICON_URL,
43
+ url: "https://" + new URL(inspector.ws.url).host
44
+ }
45
+ ])
46
+ );
47
+ }
48
+ return;
49
+ case sourceMapPathname:
50
+ res.setHeader("Content-Type", "text/plain");
51
+ res.setHeader("Cache-Control", "no-store");
52
+ res.setHeader(
53
+ "Access-Control-Allow-Origin",
54
+ req.headers.origin ?? "devtools://devtools"
55
+ );
56
+ res.end(readFileSync(sourceFilePath + ".map", "utf-8"));
57
+ break;
58
+ case "/favicon.ico":
59
+ proxyHttp(H2_FAVICON_URL, req.headers, res);
60
+ break;
61
+ case "/":
62
+ if (!queryString) {
63
+ res.statusCode = 302;
64
+ res.setHeader(
65
+ "Location",
66
+ `/?experiments=true&v8only=true&debugger=true&ws=localhost:${port}/ws`
67
+ );
68
+ res.end();
69
+ } else {
70
+ proxyHttp(
71
+ CFW_DEVTOOLS + "/js_app",
72
+ req.headers,
73
+ res,
74
+ (content) => (
75
+ // HTML from DevTools comes without closing <body> and <html> tags.
76
+ // The browser closes them automatically, then modifies the DOM with JS.
77
+ // This adds a loading indicator before the JS kicks in and modifies the DOM.
78
+ content + '<div style="display: flex; flex-direction: column; align-items: center; padding-top: 20px; font-family: Arial; color: white">Loading DevTools...</div></body></html>'
79
+ )
80
+ );
81
+ }
82
+ break;
83
+ default:
84
+ if (url === "/panels/sources/sources-meta.js" || url.startsWith("/core/i18n/locales/") && url.endsWith(".json")) {
85
+ proxyHttp(
86
+ CFW_DEVTOOLS + url,
87
+ req.headers,
88
+ res,
89
+ (content) => content.replace(/['"]Cloudflare['"]/g, '"Hydrogen"')
90
+ );
91
+ } else {
92
+ proxyHttp(CFW_DEVTOOLS + url, req.headers, res);
93
+ }
94
+ break;
95
+ }
96
+ });
97
+ const wsServer = new WebSocketServer({ server, clientTracking: true });
98
+ server.listen(port);
99
+ let messageBuffer = [];
100
+ wsServer.on("connection", (ws, req) => {
101
+ if (wsServer.clients.size > 1) {
102
+ console.error(
103
+ "Tried to open a new devtools window when a previous one was already open."
104
+ );
105
+ ws.close(1013, "Too many clients; only one can be connected at a time");
106
+ } else {
107
+ inspector.ws.send(
108
+ JSON.stringify({ id: 1e8, method: "Debugger.disable" })
109
+ );
110
+ debuggerWs?.removeEventListener("message", sendMessageToInspector);
111
+ debuggerWs = ws;
112
+ isDevToolsInBrowser = /mozilla/i.test(req.headers["user-agent"] ?? "");
113
+ debuggerWs.addEventListener("message", sendMessageToInspector);
114
+ debuggerWs.addEventListener("close", () => {
115
+ debuggerWs?.removeEventListener("message", sendMessageToInspector);
116
+ debuggerWs = void 0;
117
+ });
118
+ messageBuffer.forEach(sendMessageToDebugger);
119
+ messageBuffer = [];
120
+ }
121
+ });
122
+ if (inspector.ws)
123
+ onInspectorConnection();
124
+ function onInspectorConnection() {
125
+ inspector.ws.addEventListener("message", sendMessageToDebugger);
126
+ debuggerWs?.send(
127
+ JSON.stringify({
128
+ method: "Runtime.consoleAPICalled",
129
+ params: {
130
+ type: "warning",
131
+ args: [
132
+ {
133
+ type: "string",
134
+ value: "Source code changed. Please reload the DevTools to reconnect the debugger."
135
+ }
136
+ ],
137
+ executionContextId: Date.now(),
138
+ timestamp: Date.now()
139
+ }
140
+ })
141
+ );
142
+ debuggerWs?.close(1001, "Source code changed");
143
+ }
144
+ function sendMessageToInspector(event) {
145
+ inspector.ws.send(event.data);
146
+ }
147
+ function sendMessageToDebugger(event) {
148
+ if (isDevToolsInBrowser) {
149
+ event = enhanceDevToolsEvent(event, sourceMapURL);
150
+ }
151
+ if (debuggerWs) {
152
+ debuggerWs.send(event.data);
153
+ } else {
154
+ messageBuffer.push(event);
155
+ }
156
+ }
157
+ return {
158
+ updateInspectorConnection(newConnection) {
159
+ inspector = newConnection;
160
+ onInspectorConnection();
161
+ }
162
+ };
163
+ }
164
+ function enhanceDevToolsEvent(event, sourceMapUrl) {
165
+ const message = JSON.parse(event.data);
166
+ if (message.method === "Debugger.scriptParsed") {
167
+ if (message.params.sourceMapURL === "index.js.map") {
168
+ message.params.sourceMapURL = sourceMapUrl;
169
+ }
170
+ }
171
+ return { ...event, data: JSON.stringify(message) };
172
+ }
173
+ function proxyHttp(url, originalHeaders, nodeResponse, contentReplacer) {
174
+ const headers = Object.fromEntries(Object.entries(originalHeaders));
175
+ delete headers["host"];
176
+ delete headers["cookie"];
177
+ if (contentReplacer)
178
+ delete headers["accept-encoding"];
179
+ return request(url, { responseHeader: "raw", headers }).then((response) => {
180
+ nodeResponse.statusCode = response.statusCode;
181
+ if (nodeResponse.statusCode === 404) {
182
+ return nodeResponse.end("Not found");
183
+ }
184
+ Object.entries(response.headers).forEach(([key, value]) => {
185
+ if (value) {
186
+ nodeResponse.setHeader(key, value);
187
+ }
188
+ });
189
+ if (contentReplacer) {
190
+ return response.body?.text().then(contentReplacer).then(nodeResponse.end.bind(nodeResponse));
191
+ }
192
+ return response.body.pipe(nodeResponse);
193
+ }).catch((err) => {
194
+ console.error(err);
195
+ nodeResponse.statusCode = 500;
196
+ nodeResponse.end("Internal error");
197
+ });
198
+ }
199
+
200
+ export { createInspectorProxy };
@@ -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 { parse } from 'stack-trace';
5
- import WebSocket from 'ws';
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
- return body?.find(({ id }) => id === "core:user:hydrogen")?.webSocketDebuggerUrl;
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
- console.error("Error attempting to retrieve debugger URL:", error);
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
- clearInterval(keepAliveInterval);
199
- if (!isClosed()) {
200
- try {
201
- ws.close();
202
- } catch (err) {
203
- }
204
- }
205
- sourceMapAbortController.abort();
206
- };
207
- }
208
- const mapConsoleAPIMessageTypeToConsoleMethod = {
209
- log: "log",
210
- debug: "debug",
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
- } catch {
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 { connectToInspector, findInspectorUrl, mapConsoleAPIMessageTypeToConsoleMethod };
219
+ export { createInspectorConnector };