@shopify/cli-hydrogen 7.1.2 → 8.0.1

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 (145) 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 +10 -1
  7. package/dist/commands/hydrogen/deploy.js +110 -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 +20 -28
  11. package/dist/commands/hydrogen/env/pull.js +29 -19
  12. package/dist/commands/hydrogen/env/{push__unstable.js → push.js} +34 -68
  13. package/dist/commands/hydrogen/generate/route.js +1 -0
  14. package/dist/commands/hydrogen/init.js +39 -21
  15. package/dist/commands/hydrogen/link.js +25 -6
  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 -23
  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 +15 -2
  29. package/dist/generator-templates/starter/CHANGELOG.md +129 -0
  30. package/dist/generator-templates/starter/README.md +3 -44
  31. package/dist/generator-templates/starter/app/components/Footer.tsx +1 -1
  32. package/dist/generator-templates/starter/app/components/Header.tsx +1 -1
  33. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +1 -0
  34. package/dist/generator-templates/starter/app/lib/fragments.ts +2 -0
  35. package/dist/generator-templates/starter/app/lib/root-data.ts +11 -0
  36. package/dist/generator-templates/starter/app/root.tsx +4 -20
  37. package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +1 -1
  38. package/dist/generator-templates/starter/app/routes/account.tsx +1 -1
  39. package/dist/generator-templates/starter/app/routes/blogs.$blogHandle._index.tsx +3 -3
  40. package/dist/generator-templates/starter/app/routes/cart.tsx +1 -1
  41. package/dist/generator-templates/starter/app/routes/collections.all.tsx +160 -0
  42. package/dist/generator-templates/starter/app/routes/products.$handle.tsx +1 -2
  43. package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +6 -3
  44. package/dist/generator-templates/starter/{remix.env.d.ts → env.d.ts} +8 -2
  45. package/dist/generator-templates/starter/package.json +14 -9
  46. package/dist/generator-templates/starter/server.ts +2 -1
  47. package/dist/generator-templates/starter/storefrontapi.generated.d.ts +59 -3
  48. package/dist/generator-templates/starter/vite.config.ts +26 -0
  49. package/dist/{commands/hydrogen/init.d.ts → init.d.ts} +11 -4
  50. package/dist/lib/check-lockfile.js +12 -18
  51. package/dist/lib/codegen.js +37 -13
  52. package/dist/lib/common.js +50 -0
  53. package/dist/lib/cpu-profiler.js +4 -1
  54. package/dist/lib/dev-shared.js +99 -0
  55. package/dist/lib/environment-variables.js +51 -30
  56. package/dist/lib/file.js +8 -1
  57. package/dist/lib/flags.js +37 -26
  58. package/dist/lib/get-oxygen-deployment-data.js +10 -17
  59. package/dist/lib/graphql/admin/customer-application-update.js +29 -0
  60. package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
  61. package/dist/lib/graphql/admin/list-environments.js +1 -0
  62. package/dist/lib/graphql/admin/pull-variables.js +4 -4
  63. package/dist/lib/graphql/admin/test-helper.js +37 -0
  64. package/dist/lib/log.js +86 -13
  65. package/dist/lib/mini-oxygen/common.js +19 -33
  66. package/dist/lib/mini-oxygen/index.js +6 -2
  67. package/dist/lib/mini-oxygen/node.js +43 -31
  68. package/dist/lib/mini-oxygen/workerd.js +72 -165
  69. package/dist/lib/missing-routes.js +1 -1
  70. package/dist/lib/onboarding/common.js +85 -70
  71. package/dist/lib/onboarding/local.js +19 -9
  72. package/dist/lib/onboarding/remote.js +35 -30
  73. package/dist/lib/package-managers.js +24 -0
  74. package/dist/lib/remix-config.js +17 -1
  75. package/dist/lib/render-errors.js +17 -10
  76. package/dist/lib/request-events.js +6 -1
  77. package/dist/lib/setups/i18n/replacers.js +9 -6
  78. package/dist/lib/setups/routes/generate.js +1 -0
  79. package/dist/lib/shell.js +2 -1
  80. package/dist/lib/shopify-config.js +19 -1
  81. package/dist/lib/template-diff.js +36 -15
  82. package/dist/lib/template-downloader.js +35 -5
  83. package/dist/lib/transpile/morph/functions.js +26 -8
  84. package/dist/lib/transpile/morph/typedefs.js +6 -4
  85. package/dist/lib/transpile/project.js +8 -4
  86. package/dist/lib/tunneling.js +44 -0
  87. package/dist/lib/verify-linked-storefront.js +24 -0
  88. package/dist/lib/virtual-routes.js +1 -1
  89. package/dist/lib/vite-config.js +39 -9
  90. package/oclif.manifest.json +704 -508
  91. package/package.json +32 -24
  92. package/dist/commands/hydrogen/deploy.test.js +0 -553
  93. package/dist/commands/hydrogen/env/list.test.js +0 -148
  94. package/dist/commands/hydrogen/env/pull.test.js +0 -207
  95. package/dist/commands/hydrogen/env/push__unstable.test.js +0 -383
  96. package/dist/commands/hydrogen/generate/route.test.js +0 -43
  97. package/dist/commands/hydrogen/init.test.js +0 -641
  98. package/dist/commands/hydrogen/link.test.js +0 -187
  99. package/dist/commands/hydrogen/list.test.js +0 -111
  100. package/dist/commands/hydrogen/setup.test.js +0 -61
  101. package/dist/commands/hydrogen/shortcut.test.js +0 -30
  102. package/dist/commands/hydrogen/unlink.test.js +0 -36
  103. package/dist/commands/hydrogen/upgrade.test.js +0 -786
  104. package/dist/generator-templates/starter/remix.config.js +0 -24
  105. package/dist/lib/auth.test.js +0 -157
  106. package/dist/lib/check-lockfile.test.js +0 -81
  107. package/dist/lib/check-version.test.js +0 -86
  108. package/dist/lib/environment-variables.test.js +0 -149
  109. package/dist/lib/file.test.js +0 -68
  110. package/dist/lib/flags.test.js +0 -43
  111. package/dist/lib/get-oxygen-deployment-data.test.js +0 -120
  112. package/dist/lib/gid.test.js +0 -15
  113. package/dist/lib/graphql/admin/client.test.js +0 -76
  114. package/dist/lib/graphql/admin/create-storefront.test.js +0 -64
  115. package/dist/lib/graphql/admin/link-storefront.test.js +0 -38
  116. package/dist/lib/graphql/admin/list-environments.test.js +0 -44
  117. package/dist/lib/graphql/admin/list-storefronts.test.js +0 -44
  118. package/dist/lib/graphql/admin/pull-variables.test.js +0 -43
  119. package/dist/lib/graphql/business-platform/user-account.test.js +0 -80
  120. package/dist/lib/log.test.js +0 -92
  121. package/dist/lib/mini-oxygen/assets.js +0 -134
  122. package/dist/lib/mini-oxygen/mini-oxygen.test.js +0 -214
  123. package/dist/lib/mini-oxygen/workerd-inspector-logs.js +0 -227
  124. package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +0 -200
  125. package/dist/lib/mini-oxygen/workerd-inspector.js +0 -219
  126. package/dist/lib/missing-routes.test.js +0 -45
  127. package/dist/lib/remix-version-check.test.js +0 -39
  128. package/dist/lib/remix-version-interop.test.js +0 -13
  129. package/dist/lib/setups/i18n/domains.test.js +0 -39
  130. package/dist/lib/setups/i18n/replacers.test.js +0 -261
  131. package/dist/lib/setups/i18n/subdomains.test.js +0 -39
  132. package/dist/lib/setups/i18n/subfolders.test.js +0 -39
  133. package/dist/lib/setups/routes/generate.test.js +0 -296
  134. package/dist/lib/shell.test.js +0 -111
  135. package/dist/lib/shopify-config.test.js +0 -199
  136. package/dist/lib/string.test.js +0 -16
  137. package/dist/lib/virtual-routes.test.js +0 -49
  138. package/dist/lib/vite/hydrogen-middleware.js +0 -82
  139. package/dist/lib/vite/mini-oxygen.js +0 -152
  140. package/dist/lib/vite/plugins.d.ts +0 -27
  141. package/dist/lib/vite/plugins.js +0 -139
  142. package/dist/lib/vite/shared.js +0 -10
  143. package/dist/lib/vite/utils.js +0 -55
  144. package/dist/lib/vite/worker-entry.js +0 -1518
  145. /package/dist/generator-templates/starter/{.eslintrc.js → .eslintrc.cjs} +0 -0
@@ -1,200 +0,0 @@
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,219 +0,0 @@
1
- import { dirname } from 'node:path';
2
- import { readFile } from 'node:fs/promises';
3
- import { fetch } from '@shopify/cli-kit/node/http';
4
- import { SourceMapConsumer } from 'source-map';
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';
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
- }
36
- async function findInspectorUrl(inspectorPort) {
37
- try {
38
- const jsonUrl = `http://127.0.0.1:${inspectorPort}/json`;
39
- const body = await (await fetch(jsonUrl)).json();
40
- const url = body?.find(
41
- ({ id }) => id === "core:user:hydrogen" || id === "core:user:oxygen"
42
- )?.webSocketDebuggerUrl;
43
- if (!url) {
44
- throw new Error("Unable to find inspector URL");
45
- }
46
- return url;
47
- } catch (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;
54
- }
55
- }
56
- function connectToInspector({ inspectorUrl, sourceMapPath }) {
57
- const messageCounterRef = { value: -1 };
58
- const getMessageId = () => messageCounterRef.value--;
59
- const pendingMessages = /* @__PURE__ */ new Map();
60
- const ws = new WebSocket(inspectorUrl);
61
- let keepAliveInterval;
62
- const isClosed = () => ws.readyState === WebSocket.CLOSED || ws.readyState === WebSocket.CLOSING;
63
- const send = (method, params) => {
64
- if (!isClosed()) {
65
- const id = getMessageId();
66
- let promiseResolve = void 0;
67
- const promise = new Promise(
68
- (resolve) => promiseResolve = resolve
69
- );
70
- pendingMessages.set(id, promiseResolve);
71
- ws.send(JSON.stringify({ id, method, params }));
72
- return promise;
73
- }
74
- return Promise.resolve(void 0);
75
- };
76
- const cleanupMessageQueue = (data) => {
77
- try {
78
- if (data?.id < 0) {
79
- const resolve = pendingMessages.get(data.id);
80
- if (resolve !== void 0) {
81
- pendingMessages.delete(data.id);
82
- resolve(data.result);
83
- }
84
- return true;
85
- }
86
- } catch (error) {
87
- console.error(error);
88
- }
89
- return false;
90
- };
91
- function getPropertyValue(name, response) {
92
- return response?.result.find((prop) => prop.name === name)?.value;
93
- }
94
- async function reconstructError(initialProperties, ro) {
95
- let errorProperties = { ...initialProperties };
96
- const objectId = ro?.objectId;
97
- if (objectId) {
98
- const [sourceMapConsumer, getPropertiesResponse] = await Promise.all([
99
- getSourceMapConsumer(),
100
- send("Runtime.getProperties", {
101
- objectId,
102
- ownProperties: false,
103
- accessorPropertiesOnly: false,
104
- generatePreview: false,
105
- nonIndexedPropertiesOnly: false
106
- })
107
- ]);
108
- const message = getPropertyValue("message", getPropertiesResponse);
109
- if (message?.value) {
110
- errorProperties.message = message.value;
111
- }
112
- const stack = getPropertyValue("stack", getPropertiesResponse);
113
- if (stack?.value) {
114
- errorProperties.stack = sourceMapConsumer ? formatStack(sourceMapConsumer, stack.value) : stack.value;
115
- }
116
- const cause = getPropertyValue("cause", getPropertiesResponse);
117
- if (cause) {
118
- errorProperties.cause = cause.description ?? cause.value;
119
- if (cause.subtype === "error" && sourceMapConsumer && cause.description !== void 0) {
120
- errorProperties.stack = formatStack(
121
- sourceMapConsumer,
122
- cause.description
123
- );
124
- }
125
- }
126
- const isDomException = ro?.className === "DOMException";
127
- if (isDomException) {
128
- const stackDescriptor = getPropertiesResponse?.result.find(
129
- (prop) => prop.name === "stack"
130
- );
131
- const getObjectId = stackDescriptor?.get?.objectId;
132
- if (getObjectId !== void 0) {
133
- const callFunctionResponse = await send("Runtime.callFunctionOn", {
134
- objectId,
135
- functionDeclaration: "function invokeGetter(getter) { return Reflect.apply(getter, this, []); }",
136
- arguments: [{ objectId: getObjectId }],
137
- silent: true
138
- });
139
- if (callFunctionResponse !== void 0) {
140
- const stack2 = callFunctionResponse.result.value;
141
- if (typeof stack2 === "string" && sourceMapConsumer !== void 0) {
142
- errorProperties.stack = formatStack(sourceMapConsumer, stack2);
143
- } else {
144
- try {
145
- errorProperties.stack = JSON.stringify(stack2);
146
- } catch {
147
- }
148
- }
149
- }
150
- }
151
- }
152
- }
153
- const error = new Error(errorProperties.message);
154
- error.stack = errorProperties.stack;
155
- if (errorProperties.cause) {
156
- error.cause = errorProperties.cause;
157
- }
158
- return error;
159
- }
160
- const sourceMapAbortController = new AbortController();
161
- let sourceMapConsumerPromise;
162
- const getSourceMapConsumer = () => {
163
- return sourceMapConsumerPromise ??= (async () => {
164
- if (!sourceMapPath || sourceMapAbortController.signal.aborted) {
165
- return;
166
- }
167
- try {
168
- const mapContent = await readFile(sourceMapPath, "utf-8");
169
- if (sourceMapAbortController.signal.aborted)
170
- return;
171
- const map = JSON.parse(mapContent);
172
- map.sourceRoot = dirname(sourceMapPath);
173
- const sourceMapConsumer = await new SourceMapConsumer(map);
174
- if (sourceMapAbortController.signal.aborted) {
175
- sourceMapConsumer.destroy();
176
- return;
177
- }
178
- sourceMapAbortController.signal.addEventListener("abort", () => {
179
- sourceMapConsumerPromise = Promise.resolve(void 0);
180
- sourceMapConsumer.destroy();
181
- });
182
- return sourceMapConsumer;
183
- } catch {
184
- }
185
- })();
186
- };
187
- ws.once("open", () => {
188
- send("Runtime.enable");
189
- keepAliveInterval = setInterval(() => send("Runtime.getIsolateId"), 1e4);
190
- });
191
- ws.on("unexpected-response", () => {
192
- console.log("Waiting for connection...");
193
- });
194
- ws.once("close", () => {
195
- clearInterval(keepAliveInterval);
196
- sourceMapAbortController.abort();
197
- });
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) {
212
- }
213
- }
214
- sourceMapAbortController.abort();
215
- }
216
- };
217
- }
218
-
219
- export { createInspectorConnector };
@@ -1,45 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { findMissingRoutes } from './missing-routes.js';
3
-
4
- const createRoute = (path) => ({
5
- routes: {
6
- "route-id": {
7
- file: "a/file",
8
- id: "route-id",
9
- path
10
- }
11
- }
12
- });
13
- describe("missing-routes", () => {
14
- it("matches routes with dots", async () => {
15
- const requiredRoutes = ["sitemap.xml"];
16
- expect(findMissingRoutes({ routes: {} }, requiredRoutes)).toHaveLength(1);
17
- expect(
18
- findMissingRoutes(createRoute("sitemap.xml"), requiredRoutes)
19
- ).toHaveLength(0);
20
- });
21
- it("matches routes with different parameter names", async () => {
22
- const requiredRoutes = ["collections/:collectionHandle"];
23
- expect(findMissingRoutes({ routes: {} }, requiredRoutes)).toHaveLength(1);
24
- expect(
25
- findMissingRoutes(createRoute("collections/:param"), requiredRoutes)
26
- ).toHaveLength(0);
27
- });
28
- it("matches optional segments in different positions", async () => {
29
- const requiredRoutes = ["collections/products"];
30
- const validRoutes = [
31
- "segment?/collections/products",
32
- ":segment?/collections/products",
33
- "collections/segment?/products",
34
- "collections/:segment?/products",
35
- "collections/products/segment?",
36
- "collections/products/:segment?"
37
- ];
38
- expect(findMissingRoutes({ routes: {} }, requiredRoutes)).toHaveLength(1);
39
- for (const validRoute of validRoutes) {
40
- expect(
41
- findMissingRoutes(createRoute(validRoute), requiredRoutes)
42
- ).toHaveLength(0);
43
- }
44
- });
45
- });
@@ -1,39 +0,0 @@
1
- import { vi, describe, it, expect } from 'vitest';
2
- import { mockAndCaptureOutput } from '@shopify/cli-kit/node/testing/output';
3
- import { checkRemixVersions } from './remix-version-check.js';
4
-
5
- const requireMock = vi.fn();
6
- vi.mock("node:module", async () => {
7
- const { createRequire } = await vi.importActual(
8
- "node:module"
9
- );
10
- return {
11
- createRequire: (url) => {
12
- const actualRequire = createRequire(url);
13
- requireMock.mockImplementation((mod) => actualRequire(mod));
14
- const require2 = requireMock;
15
- require2.resolve = actualRequire.resolve.bind(actualRequire);
16
- return require2;
17
- }
18
- };
19
- });
20
- describe("remix-version-check", () => {
21
- it("does nothing when versions are in sync", () => {
22
- const outputMock = mockAndCaptureOutput();
23
- checkRemixVersions();
24
- expect(outputMock.warn()).toBe("");
25
- });
26
- it("warns when versions are out of sync", () => {
27
- const expectedVersion = "42.0.0-test";
28
- vi.mocked(requireMock).mockReturnValueOnce({
29
- // Hydrogen expected version
30
- peerDependencies: { "@remix-run/dev": expectedVersion }
31
- });
32
- const outputMock = mockAndCaptureOutput();
33
- checkRemixVersions();
34
- const output = outputMock.warn();
35
- expect(output).toMatch(`Hydrogen requires Remix @${expectedVersion}`);
36
- expect(output).toMatch(`@remix-run/dev@`);
37
- expect(output).toMatch(`@remix-run/react@`);
38
- });
39
- });
@@ -1,13 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { convertRouteToV1 } from './remix-version-interop.js';
3
-
4
- describe("remix-version-interop", () => {
5
- it("converts routes to v1", () => {
6
- expect(convertRouteToV1("_index")).toEqual("index");
7
- expect(convertRouteToV1("path.to.file")).toEqual("path/to/file");
8
- expect(convertRouteToV1("path.to._index")).toEqual("path/to/index");
9
- expect(convertRouteToV1("patht.to.[sitemap.xml]")).toEqual(
10
- "patht/to/[sitemap.xml]"
11
- );
12
- });
13
- });
@@ -1,39 +0,0 @@
1
- import { fileURLToPath } from 'node:url';
2
- import { describe, it, expect } from 'vitest';
3
- import { getLocaleFromRequest } from './templates/domains.js';
4
- import { readFile } from '@shopify/cli-kit/node/fs';
5
-
6
- describe("Setup i18n with domains", () => {
7
- it("extracts the locale from the domain", () => {
8
- expect(
9
- getLocaleFromRequest(new Request("https://example.com"))
10
- ).toMatchObject({
11
- language: "EN",
12
- country: "US"
13
- });
14
- expect(
15
- getLocaleFromRequest(new Request("https://example.jp"))
16
- ).toMatchObject({
17
- language: "JA",
18
- country: "JP"
19
- });
20
- expect(
21
- getLocaleFromRequest(new Request("https://www.example.es"))
22
- ).toMatchObject({
23
- language: "ES",
24
- country: "ES"
25
- });
26
- });
27
- it("does not access imported types directly", async () => {
28
- const template = await readFile(
29
- fileURLToPath(new URL("./templates/domains.ts", import.meta.url))
30
- );
31
- const typeImports = (template.match(/import\s+type\s+{([^}]+)}/)?.[1] || "").trim().split(/\s*,\s*/);
32
- expect(typeImports).not.toHaveLength(0);
33
- const fnCode = template.match(/function .*\n}$/ms)?.[0] || "";
34
- expect(fnCode).toBeTruthy();
35
- typeImports.forEach(
36
- (typeImport) => expect(fnCode).not.toContain(typeImport)
37
- );
38
- });
39
- });