@qwik.dev/router 2.0.0-beta.2 → 2.0.0-beta.21

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 (78) hide show
  1. package/adapters/static/vite.d.ts +1 -1
  2. package/lib/adapters/azure-swa/vite/index.d.ts +2 -2
  3. package/lib/adapters/azure-swa/vite/index.mjs +9 -9
  4. package/lib/adapters/bun-server/vite/index.d.ts +2 -2
  5. package/lib/adapters/bun-server/vite/index.mjs +9 -7
  6. package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
  7. package/lib/adapters/cloud-run/vite/index.mjs +9 -7
  8. package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
  9. package/lib/adapters/cloudflare-pages/vite/index.mjs +9 -24
  10. package/lib/adapters/deno-server/vite/index.d.ts +2 -2
  11. package/lib/adapters/deno-server/vite/index.mjs +9 -7
  12. package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
  13. package/lib/adapters/netlify-edge/vite/index.mjs +10 -14
  14. package/lib/adapters/node-server/vite/index.d.ts +2 -2
  15. package/lib/adapters/node-server/vite/index.mjs +9 -7
  16. package/lib/adapters/shared/vite/index.d.ts +13 -19
  17. package/lib/adapters/shared/vite/index.mjs +107 -139
  18. package/lib/adapters/ssg/vite/index.d.ts +13 -0
  19. package/lib/adapters/ssg/vite/index.mjs +18 -0
  20. package/lib/adapters/vercel-edge/vite/index.d.ts +3 -3
  21. package/lib/adapters/vercel-edge/vite/index.mjs +9 -11
  22. package/lib/chunks/error-handler.mjs +57 -0
  23. package/lib/chunks/format-error.mjs +137 -0
  24. package/lib/chunks/fs.mjs +254 -0
  25. package/lib/{static/node.mjs → chunks/index.mjs} +361 -563
  26. package/lib/chunks/mime-types.mjs +52 -0
  27. package/lib/chunks/routing.qwik.mjs +429 -0
  28. package/lib/chunks/types.qwik.mjs +22 -0
  29. package/lib/index.d.ts +240 -60
  30. package/lib/index.qwik.mjs +698 -983
  31. package/lib/middleware/aws-lambda/index.d.ts +3 -2
  32. package/lib/middleware/aws-lambda/index.mjs +8 -12
  33. package/lib/middleware/azure-swa/index.mjs +10 -216
  34. package/lib/middleware/bun/index.d.ts +11 -0
  35. package/lib/middleware/bun/index.mjs +24 -83
  36. package/lib/middleware/cloudflare-pages/index.mjs +10 -22
  37. package/lib/middleware/deno/index.d.ts +11 -0
  38. package/lib/middleware/deno/index.mjs +24 -83
  39. package/lib/middleware/firebase/index.mjs +7 -11
  40. package/lib/middleware/netlify-edge/index.mjs +10 -23
  41. package/lib/middleware/node/index.mjs +22 -87
  42. package/lib/middleware/request-handler/index.d.ts +89 -70
  43. package/lib/middleware/request-handler/index.mjs +584 -659
  44. package/lib/middleware/vercel-edge/index.mjs +15 -27
  45. package/lib/modules.d.ts +4 -12
  46. package/lib/service-worker/index.mjs +4 -0
  47. package/lib/{static → ssg}/index.d.ts +17 -17
  48. package/lib/ssg/index.mjs +14 -0
  49. package/lib/vite/index.d.ts +32 -10
  50. package/lib/vite/index.mjs +1524 -26934
  51. package/modules.d.ts +4 -12
  52. package/package.json +62 -68
  53. package/ssg.d.ts +2 -0
  54. package/static.d.ts +1 -1
  55. package/lib/adapters/azure-swa/vite/index.cjs +0 -96
  56. package/lib/adapters/bun-server/vite/index.cjs +0 -50
  57. package/lib/adapters/cloud-run/vite/index.cjs +0 -47
  58. package/lib/adapters/cloudflare-pages/vite/index.cjs +0 -115
  59. package/lib/adapters/deno-server/vite/index.cjs +0 -62
  60. package/lib/adapters/netlify-edge/vite/index.cjs +0 -129
  61. package/lib/adapters/node-server/vite/index.cjs +0 -50
  62. package/lib/adapters/shared/vite/index.cjs +0 -378
  63. package/lib/adapters/static/vite/index.cjs +0 -368
  64. package/lib/adapters/static/vite/index.d.ts +0 -10
  65. package/lib/adapters/static/vite/index.mjs +0 -331
  66. package/lib/adapters/vercel-edge/vite/index.cjs +0 -118
  67. package/lib/index.qwik.cjs +0 -1947
  68. package/lib/middleware/node/index.cjs +0 -314
  69. package/lib/middleware/request-handler/index.cjs +0 -1614
  70. package/lib/service-worker.cjs +0 -17
  71. package/lib/service-worker.mjs +0 -15
  72. package/lib/static/deno.mjs +0 -8
  73. package/lib/static/index.cjs +0 -67
  74. package/lib/static/index.mjs +0 -48
  75. package/lib/static/node.cjs +0 -1124
  76. package/lib/vite/index.cjs +0 -27445
  77. package/middleware/request-handler/generated/not-found-paths.ts +0 -7
  78. package/middleware/request-handler/generated/static-paths.ts +0 -35
@@ -1,317 +1,17 @@
1
- // packages/qwik-router/src/static/node/node-system.ts
2
- import fs2 from "node:fs";
3
- import { dirname as dirname2, join } from "node:path";
1
+ import fs from 'node:fs';
2
+ import { isAbsolute, resolve, extname, join, dirname, relative } from 'node:path';
3
+ import { cpus } from 'node:os';
4
+ import { Worker, parentPort, isMainThread, workerData, threadId } from 'node:worker_threads';
5
+ import { l as normalizePath, w as msToString, x as getPathnameForDynamicRoute } from './fs.mjs';
6
+ import { bold, green, dim, red, magenta } from 'kleur/colors';
7
+ import { pathToFileURL } from 'node:url';
8
+ import { buildErrorMessage } from 'vite';
9
+ import { f as formatError } from './format-error.mjs';
10
+ import { getErrorHtml, RequestEvShareQData, requestHandler, RedirectMessage } from '@qwik.dev/router/middleware/request-handler';
11
+ import { R as RouteDataProp } from './types.qwik.mjs';
12
+ import { _serialize } from '@qwik.dev/core/internal';
13
+ import { WritableStream } from 'node:stream/web';
4
14
 
5
- // packages/qwik-router/src/static/node/node-main.ts
6
- import fs from "node:fs";
7
- import { cpus as nodeCpus } from "node:os";
8
- import { Worker } from "node:worker_threads";
9
- import { isAbsolute, resolve } from "node:path";
10
-
11
- // packages/qwik-router/src/utils/fs.ts
12
- import { basename, dirname, normalize, relative } from "node:path";
13
-
14
- // packages/qwik-router/src/utils/format.ts
15
- function msToString(ms) {
16
- if (ms < 1) {
17
- return ms.toFixed(2) + " ms";
18
- }
19
- if (ms < 1e3) {
20
- return ms.toFixed(1) + " ms";
21
- }
22
- if (ms < 6e4) {
23
- return (ms / 1e3).toFixed(1) + " s";
24
- }
25
- return (ms / 6e4).toFixed(1) + " m";
26
- }
27
-
28
- // packages/qwik-router/src/utils/pathname.ts
29
- function getPathnameForDynamicRoute(originalPathname, paramNames, params) {
30
- let pathname = originalPathname;
31
- if (paramNames && params) {
32
- for (const paramName of paramNames) {
33
- const paramKey = `[${paramName}]`;
34
- const restParamKey = `[...${paramName}]`;
35
- const paramValue = params[paramName];
36
- pathname = pathname.replace(restParamKey, paramValue);
37
- pathname = pathname.replace(paramKey, paramValue);
38
- }
39
- }
40
- return pathname;
41
- }
42
-
43
- // packages/qwik-router/src/utils/fs.ts
44
- function normalizePath(path) {
45
- return normalizePathSlash(normalize(path));
46
- }
47
- function normalizePathSlash(path) {
48
- const isExtendedLengthPath = /^\\\\\?\\/.test(path);
49
- const hasNonAscii = /[^\u0000-\u0080]+/.test(path);
50
- if (isExtendedLengthPath || hasNonAscii) {
51
- return path;
52
- }
53
- path = path.replace(/\\/g, "/");
54
- if (path.endsWith("/")) {
55
- path = path.slice(0, path.length - 1);
56
- }
57
- return path;
58
- }
59
-
60
- // packages/qwik-router/src/static/worker-thread.ts
61
- import { _deserialize, _serialize, _verifySerializable } from "@qwik.dev/core/internal";
62
- import { requestHandler } from "../middleware/request-handler/index.mjs";
63
- import { WritableStream } from "node:stream/web";
64
- import { pathToFileURL } from "node:url";
65
- async function workerThread(sys) {
66
- const ssgOpts = sys.getOptions();
67
- const pendingPromises = /* @__PURE__ */ new Set();
68
- const opts = {
69
- ...ssgOpts,
70
- render: (await import(pathToFileURL(ssgOpts.renderModulePath).href)).default,
71
- qwikRouterConfig: (await import(pathToFileURL(ssgOpts.qwikRouterConfigModulePath).href)).default
72
- };
73
- sys.createWorkerProcess(async (msg) => {
74
- switch (msg.type) {
75
- case "render": {
76
- return new Promise((resolve2) => {
77
- workerRender(sys, opts, msg, pendingPromises, resolve2);
78
- });
79
- }
80
- case "close": {
81
- const promises = Array.from(pendingPromises);
82
- pendingPromises.clear();
83
- await Promise.all(promises);
84
- return { type: "close" };
85
- }
86
- }
87
- });
88
- }
89
- async function createSingleThreadWorker(sys) {
90
- const ssgOpts = sys.getOptions();
91
- const pendingPromises = /* @__PURE__ */ new Set();
92
- const opts = {
93
- ...ssgOpts,
94
- render: (await import(pathToFileURL(ssgOpts.renderModulePath).href)).default,
95
- qwikRouterConfig: (await import(pathToFileURL(ssgOpts.qwikRouterConfigModulePath).href)).default
96
- };
97
- return (staticRoute) => {
98
- return new Promise((resolve2) => {
99
- workerRender(sys, opts, staticRoute, pendingPromises, resolve2);
100
- });
101
- };
102
- }
103
- async function workerRender(sys, opts, staticRoute, pendingPromises, callback) {
104
- const qwikSerializer = {
105
- _deserialize,
106
- _serialize,
107
- _verifySerializable
108
- };
109
- const url = new URL(staticRoute.pathname, opts.origin);
110
- const result = {
111
- type: "render",
112
- pathname: staticRoute.pathname,
113
- url: url.href,
114
- ok: false,
115
- error: null,
116
- filePath: null,
117
- contentType: null,
118
- resourceType: null
119
- };
120
- try {
121
- let routeWriter = null;
122
- let closeResolved;
123
- const closePromise = new Promise((closePromiseResolve) => {
124
- closeResolved = closePromiseResolve;
125
- });
126
- const request = new Request(url);
127
- const requestCtx = {
128
- mode: "static",
129
- locale: void 0,
130
- url,
131
- request,
132
- env: {
133
- get(key) {
134
- return sys.getEnv(key);
135
- }
136
- },
137
- platform: sys.platform,
138
- getClientConn: () => {
139
- return {};
140
- },
141
- getWritableStream: (status, headers, _, _r, requestEv) => {
142
- result.ok = status >= 200 && status < 300;
143
- if (!result.ok) {
144
- return noopWritableStream;
145
- }
146
- result.contentType = (headers.get("Content-Type") || "").toLowerCase();
147
- const isHtml = result.contentType.includes("text/html");
148
- const is404ErrorPage = url.pathname.endsWith("/404.html");
149
- const routeFilePath = sys.getRouteFilePath(url.pathname, isHtml);
150
- if (is404ErrorPage) {
151
- result.resourceType = "404";
152
- } else if (isHtml) {
153
- result.resourceType = "page";
154
- }
155
- const hasRouteWriter = isHtml ? opts.emitHtml !== false : true;
156
- const writeQDataEnabled = isHtml && opts.emitData !== false;
157
- const stream = new WritableStream({
158
- async start() {
159
- try {
160
- if (hasRouteWriter || writeQDataEnabled) {
161
- await sys.ensureDir(routeFilePath);
162
- }
163
- if (hasRouteWriter) {
164
- routeWriter = sys.createWriteStream(routeFilePath);
165
- routeWriter.on("error", (e) => {
166
- console.error(e);
167
- routeWriter = null;
168
- result.error = {
169
- message: e.message,
170
- stack: e.stack
171
- };
172
- });
173
- }
174
- } catch (e) {
175
- routeWriter = null;
176
- result.error = {
177
- message: String(e),
178
- stack: e.stack || ""
179
- };
180
- }
181
- },
182
- write(chunk) {
183
- try {
184
- if (routeWriter) {
185
- routeWriter.write(Buffer.from(chunk.buffer));
186
- }
187
- } catch (e) {
188
- routeWriter = null;
189
- result.error = {
190
- message: String(e),
191
- stack: e.stack || ""
192
- };
193
- }
194
- },
195
- async close() {
196
- const writePromises = [];
197
- try {
198
- if (writeQDataEnabled) {
199
- const qData = requestEv.sharedMap.get("qData");
200
- if (qData && !is404ErrorPage) {
201
- const qDataFilePath = sys.getDataFilePath(url.pathname);
202
- const dataWriter = sys.createWriteStream(qDataFilePath);
203
- dataWriter.on("error", (e) => {
204
- console.error(e);
205
- result.error = {
206
- message: e.message,
207
- stack: e.stack
208
- };
209
- });
210
- const serialized = await _serialize([qData]);
211
- dataWriter.write(serialized);
212
- writePromises.push(
213
- new Promise((resolve2) => {
214
- result.filePath = routeFilePath;
215
- dataWriter.end(resolve2);
216
- })
217
- );
218
- }
219
- }
220
- if (routeWriter) {
221
- writePromises.push(
222
- new Promise((resolve2) => {
223
- result.filePath = routeFilePath;
224
- routeWriter.end(resolve2);
225
- }).finally(closeResolved)
226
- );
227
- }
228
- if (writePromises.length > 0) {
229
- await Promise.all(writePromises);
230
- }
231
- } catch (e) {
232
- routeWriter = null;
233
- result.error = {
234
- message: String(e),
235
- stack: e.stack || ""
236
- };
237
- }
238
- }
239
- });
240
- return stream;
241
- }
242
- };
243
- const promise = requestHandler(requestCtx, opts, qwikSerializer).then((rsp) => {
244
- if (rsp != null) {
245
- return rsp.completion.then((r) => {
246
- if (routeWriter) {
247
- return closePromise.then(() => r);
248
- }
249
- return r;
250
- });
251
- }
252
- }).then((e) => {
253
- if (e !== void 0) {
254
- if (e instanceof Error) {
255
- result.error = {
256
- message: e.message,
257
- stack: e.stack
258
- };
259
- } else {
260
- result.error = {
261
- message: String(e),
262
- stack: void 0
263
- };
264
- }
265
- }
266
- }).finally(() => {
267
- pendingPromises.delete(promise);
268
- callback(result);
269
- });
270
- pendingPromises.add(promise);
271
- } catch (e) {
272
- if (e instanceof Error) {
273
- result.error = {
274
- message: e.message,
275
- stack: e.stack
276
- };
277
- } else {
278
- result.error = {
279
- message: String(e),
280
- stack: void 0
281
- };
282
- }
283
- callback(result);
284
- }
285
- }
286
- var noopWriter = {
287
- closed: Promise.resolve(void 0),
288
- ready: Promise.resolve(void 0),
289
- desiredSize: 0,
290
- async close() {
291
- },
292
- async abort() {
293
- },
294
- async write() {
295
- },
296
- releaseLock() {
297
- }
298
- };
299
- var noopWritableStream = {
300
- get locked() {
301
- return false;
302
- },
303
- set locked(_) {
304
- },
305
- async abort() {
306
- },
307
- async close() {
308
- },
309
- getWriter() {
310
- return noopWriter;
311
- }
312
- };
313
-
314
- // packages/qwik-router/src/static/node/node-main.ts
315
15
  async function createNodeMainProcess(sys, opts) {
316
16
  const ssgWorkers = [];
317
17
  const sitemapBuffer = [];
@@ -325,7 +25,7 @@ async function createNodeMainProcess(sys, opts) {
325
25
  throw new Error(`"outDir" must be an absolute file path, received: ${outDir}`);
326
26
  }
327
27
  outDir = normalizePath(outDir);
328
- let maxWorkers = nodeCpus().length;
28
+ let maxWorkers = cpus().length;
329
29
  if (typeof opts.maxWorkers === "number") {
330
30
  maxWorkers = Math.max(1, Math.min(opts.maxWorkers, maxWorkers));
331
31
  }
@@ -342,36 +42,27 @@ async function createNodeMainProcess(sys, opts) {
342
42
  sitemapOutFile = resolve(outDir, sitemapOutFile);
343
43
  }
344
44
  }
345
- const singleThreadWorker = await createSingleThreadWorker(sys);
346
- const createWorker = (workerIndex) => {
347
- if (workerIndex === 0) {
348
- const ssgSameThreadWorker = {
349
- activeTasks: 0,
350
- totalTasks: 0,
351
- render: async (staticRoute) => {
352
- ssgSameThreadWorker.activeTasks++;
353
- ssgSameThreadWorker.totalTasks++;
354
- const result = await singleThreadWorker(staticRoute);
355
- ssgSameThreadWorker.activeTasks--;
356
- return result;
357
- },
358
- terminate: async () => {
359
- }
360
- };
361
- return ssgSameThreadWorker;
362
- }
45
+ const createWorker = () => {
363
46
  let terminateResolve = null;
364
47
  const mainTasks = /* @__PURE__ */ new Map();
365
48
  let workerFilePath;
49
+ let terminateTimeout = null;
366
50
  if (typeof __filename === "string") {
367
- workerFilePath = __filename;
51
+ const ext = extname(__filename) || ".js";
52
+ workerFilePath = join(dirname(__filename), `index${ext}`);
368
53
  } else {
369
- workerFilePath = import.meta.url;
370
- }
371
- if (typeof workerFilePath === "string" && workerFilePath.startsWith("file://")) {
372
- workerFilePath = new URL(workerFilePath);
54
+ const thisUrl = new URL(import.meta.url);
55
+ const pathname = thisUrl.pathname || "";
56
+ let ext = ".js";
57
+ if (pathname.endsWith(".ts")) {
58
+ ext = ".ts";
59
+ } else if (pathname.endsWith(".mjs")) {
60
+ ext = ".mjs";
61
+ }
62
+ workerFilePath = new URL(`./index${ext}`, thisUrl);
373
63
  }
374
64
  const nodeWorker = new Worker(workerFilePath, { workerData: opts });
65
+ nodeWorker.unref();
375
66
  const ssgWorker = {
376
67
  activeTasks: 0,
377
68
  totalTasks: 0,
@@ -396,7 +87,9 @@ async function createNodeMainProcess(sys, opts) {
396
87
  terminateResolve = resolve2;
397
88
  nodeWorker.postMessage(msg);
398
89
  });
399
- await nodeWorker.terminate();
90
+ terminateTimeout = setTimeout(async () => {
91
+ await nodeWorker.terminate();
92
+ }, 1e3);
400
93
  }
401
94
  };
402
95
  nodeWorker.on("message", (msg) => {
@@ -423,7 +116,11 @@ async function createNodeMainProcess(sys, opts) {
423
116
  console.error(`worker error`, e);
424
117
  });
425
118
  nodeWorker.on("exit", (code) => {
426
- if (code !== 1) {
119
+ if (terminateTimeout) {
120
+ clearTimeout(terminateTimeout);
121
+ terminateTimeout = null;
122
+ }
123
+ if (code !== 0) {
427
124
  console.error(`worker exit ${code}`);
428
125
  }
429
126
  });
@@ -434,9 +131,9 @@ async function createNodeMainProcess(sys, opts) {
434
131
  const ssgWorker = getNextWorker();
435
132
  return ssgWorker.activeTasks < maxTasksPerWorker;
436
133
  };
437
- const render = async (staticRoute) => {
134
+ const render = async (ssgRoute) => {
438
135
  const ssgWorker = getNextWorker();
439
- const result = await ssgWorker.render(staticRoute);
136
+ const result = await ssgWorker.render(ssgRoute);
440
137
  if (sitemapOutFile && result.ok && result.resourceType === "page") {
441
138
  sitemapBuffer.push(`<url><loc>${result.url}</loc></url>`);
442
139
  if (sitemapBuffer.length > 50) {
@@ -467,8 +164,11 @@ async function createNodeMainProcess(sys, opts) {
467
164
  console.error(e);
468
165
  }
469
166
  }
470
- ssgWorkers.length = 0;
471
167
  await Promise.all(promises);
168
+ ssgWorkers.length = 0;
169
+ if (process.platform === "win32") {
170
+ await new Promise((resolve2) => setTimeout(resolve2, 300));
171
+ }
472
172
  };
473
173
  if (sitemapOutFile) {
474
174
  await ensureDir(sitemapOutFile);
@@ -480,7 +180,10 @@ async function createNodeMainProcess(sys, opts) {
480
180
  );
481
181
  }
482
182
  for (let i = 0; i < maxWorkers; i++) {
483
- ssgWorkers.push(createWorker(i));
183
+ ssgWorkers.push(createWorker());
184
+ if (process.platform === "win32" && i < maxWorkers - 1) {
185
+ await new Promise((resolve2) => setTimeout(resolve2, 100));
186
+ }
484
187
  }
485
188
  const mainCtx = {
486
189
  hasAvailableWorker,
@@ -499,20 +202,18 @@ function ssgWorkerCompare(a, b) {
499
202
  return a.totalTasks < b.totalTasks ? -1 : 1;
500
203
  }
501
204
 
502
- // packages/qwik-router/src/static/node/node-worker.ts
503
- import { parentPort } from "node:worker_threads";
504
205
  async function createNodeWorkerProcess(onMessage) {
505
- var _a;
506
- (_a = parentPort) == null ? void 0 : _a.on("message", async (msg) => {
507
- var _a2;
508
- (_a2 = parentPort) == null ? void 0 : _a2.postMessage(await onMessage(msg));
206
+ parentPort?.on("message", async (msg) => {
207
+ parentPort?.postMessage(await onMessage(msg));
208
+ if (msg.type === "close") {
209
+ parentPort?.close();
210
+ }
509
211
  });
510
212
  }
511
213
 
512
- // packages/qwik-router/src/static/node/node-system.ts
513
- async function createSystem(opts) {
214
+ async function createSystem(opts, threadId) {
514
215
  const createWriteStream = (filePath) => {
515
- return fs2.createWriteStream(filePath, {
216
+ return fs.createWriteStream(filePath, {
516
217
  flags: "w"
517
218
  });
518
219
  };
@@ -526,6 +227,14 @@ async function createSystem(opts) {
526
227
  };
527
228
  };
528
229
  const createLogger = async () => {
230
+ if (threadId !== void 0) {
231
+ return {
232
+ debug: opts.log === "debug" ? console.debug.bind(console, `[${threadId}]`) : () => {
233
+ },
234
+ error: console.error.bind(console, `[${threadId}]`),
235
+ info: console.info.bind(console, `[${threadId}]`)
236
+ };
237
+ }
529
238
  return {
530
239
  debug: opts.log === "debug" ? console.debug.bind(console) : () => {
531
240
  },
@@ -582,201 +291,18 @@ async function createSystem(opts) {
582
291
  sys.createMainProcess = () => createNodeMainProcess(sys, opts);
583
292
  return sys;
584
293
  }
585
- var ensureDir = async (filePath) => {
586
- await fs2.promises.mkdir(dirname2(filePath), { recursive: true });
587
- };
588
- var access = async (path) => {
589
- try {
590
- await fs2.promises.access(path);
591
- return true;
592
- } catch {
593
- return false;
594
- }
595
- };
596
-
597
- // packages/qwik-router/src/static/node/index.ts
598
- import { isMainThread, workerData } from "node:worker_threads";
599
-
600
- // node_modules/.pnpm/kleur@4.1.5/node_modules/kleur/colors.mjs
601
- var FORCE_COLOR;
602
- var NODE_DISABLE_COLORS;
603
- var NO_COLOR;
604
- var TERM;
605
- var isTTY = true;
606
- if (typeof process !== "undefined") {
607
- ({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});
608
- isTTY = process.stdout && process.stdout.isTTY;
609
- }
610
- var $ = {
611
- enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY)
612
- };
613
- function init(x, y) {
614
- let rgx = new RegExp(`\\x1b\\[${y}m`, "g");
615
- let open = `\x1B[${x}m`, close = `\x1B[${y}m`;
616
- return function(txt) {
617
- if (!$.enabled || txt == null) return txt;
618
- return open + (!!~("" + txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;
619
- };
620
- }
621
- var reset = init(0, 0);
622
- var bold = init(1, 22);
623
- var dim = init(2, 22);
624
- var italic = init(3, 23);
625
- var underline = init(4, 24);
626
- var inverse = init(7, 27);
627
- var hidden = init(8, 28);
628
- var strikethrough = init(9, 29);
629
- var black = init(30, 39);
630
- var red = init(31, 39);
631
- var green = init(32, 39);
632
- var yellow = init(33, 39);
633
- var blue = init(34, 39);
634
- var magenta = init(35, 39);
635
- var cyan = init(36, 39);
636
- var white = init(37, 39);
637
- var gray = init(90, 39);
638
- var grey = init(90, 39);
639
- var bgBlack = init(40, 49);
640
- var bgRed = init(41, 49);
641
- var bgGreen = init(42, 49);
642
- var bgYellow = init(43, 49);
643
- var bgBlue = init(44, 49);
644
- var bgMagenta = init(45, 49);
645
- var bgCyan = init(46, 49);
646
- var bgWhite = init(47, 49);
647
-
648
- // packages/qwik-router/src/static/main-thread.ts
649
- import { relative as relative2 } from "node:path";
650
- import { pathToFileURL as pathToFileURL2 } from "node:url";
651
- import { buildErrorMessage } from "vite";
652
-
653
- // packages/qwik/src/optimizer/src/plugins/vite-utils.ts
654
- var findLocation = (e) => {
655
- const stack = e.stack;
656
- if (typeof stack === "string") {
657
- const lines = stack.split("\n").filter((l) => !l.includes("/node_modules/") && !l.includes("(node:"));
658
- for (let i = 1; i < lines.length; i++) {
659
- const line = lines[i].replace("file:///", "/");
660
- if (/^\s+at/.test(line)) {
661
- const start = line.indexOf("/");
662
- const end = line.lastIndexOf(")", start);
663
- if (start > 0) {
664
- const path = line.slice(start, end);
665
- const parts = path.split(":");
666
- const nu0 = safeParseInt(parts[parts.length - 1]);
667
- const nu1 = safeParseInt(parts[parts.length - 2]);
668
- if (typeof nu0 === "number" && typeof nu1 === "number") {
669
- parts.length -= 2;
670
- return {
671
- file: parts.join(":"),
672
- line: nu1,
673
- column: nu0
674
- };
675
- } else if (typeof nu0 === "number") {
676
- parts.length -= 1;
677
- return {
678
- file: parts.join(":"),
679
- line: nu0,
680
- column: void 0
681
- };
682
- } else {
683
- return {
684
- file: parts.join(":"),
685
- line: void 0,
686
- column: void 0
687
- };
688
- }
689
- }
690
- }
691
- }
692
- }
693
- return void 0;
294
+ const ensureDir = async (filePath) => {
295
+ await fs.promises.mkdir(dirname(filePath), { recursive: true });
694
296
  };
695
- var safeParseInt = (nu) => {
297
+ const access = async (path) => {
696
298
  try {
697
- return parseInt(nu, 10);
299
+ await fs.promises.access(path);
300
+ return true;
698
301
  } catch {
699
- return void 0;
302
+ return false;
700
303
  }
701
304
  };
702
- var splitRE = /\r?\n/;
703
- var range = 2;
704
- function posToNumber(source, pos) {
705
- if (typeof pos === "number") {
706
- return pos;
707
- }
708
- if (pos.lo != null) {
709
- return pos.lo;
710
- }
711
- const lines = source.split(splitRE);
712
- const { line, column } = pos;
713
- let start = 0;
714
- for (let i = 0; i < line - 1 && i < lines.length; i++) {
715
- start += lines[i].length + 1;
716
- }
717
- return start + column;
718
- }
719
- function generateCodeFrame(source, start = 0, end) {
720
- start = posToNumber(source, start);
721
- end = end || start;
722
- const lines = source.split(splitRE);
723
- let count = 0;
724
- const res = [];
725
- for (let i = 0; i < lines.length; i++) {
726
- count += lines[i].length + 1;
727
- if (count >= start) {
728
- for (let j = i - range; j <= i + range || end > count; j++) {
729
- if (j < 0 || j >= lines.length) {
730
- continue;
731
- }
732
- const line = j + 1;
733
- res.push(`${line}${" ".repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`);
734
- const lineLength = lines[j].length;
735
- if (j === i) {
736
- const pad = Math.max(start - (count - lineLength) + 1, 0);
737
- const length = Math.max(1, end > count ? lineLength - pad : end - start);
738
- res.push(` | ` + " ".repeat(pad) + "^".repeat(length));
739
- } else if (j > i) {
740
- if (end > count) {
741
- const length = Math.max(Math.min(end - count, lineLength), 1);
742
- res.push(` | ` + "^".repeat(length));
743
- }
744
- count += lineLength + 1;
745
- }
746
- }
747
- break;
748
- }
749
- }
750
- return res.join("\n");
751
- }
752
-
753
- // packages/qwik-router/src/buildtime/vite/format-error.ts
754
- import fs3 from "node:fs";
755
- function formatError(e) {
756
- if (e instanceof Error) {
757
- const err = e;
758
- let loc = err.loc;
759
- if (!err.frame && !err.plugin) {
760
- if (!loc) {
761
- loc = findLocation(err);
762
- }
763
- if (loc) {
764
- err.loc = loc;
765
- if (loc.file) {
766
- err.id = normalizePath(err.loc.file);
767
- try {
768
- const code = fs3.readFileSync(err.loc.file, "utf-8");
769
- err.frame = generateCodeFrame(code, err.loc);
770
- } catch {
771
- }
772
- }
773
- }
774
- }
775
- }
776
- return e;
777
- }
778
305
 
779
- // packages/qwik-router/src/static/extract-params.ts
780
306
  function extractParamNames(routeName) {
781
307
  const params = [];
782
308
  let idx = 0;
@@ -794,27 +320,26 @@ function extractParamNames(routeName) {
794
320
  return params;
795
321
  }
796
322
 
797
- // packages/qwik-router/src/static/not-found.ts
798
- import { getErrorHtml } from "../middleware/request-handler/index.mjs";
799
323
  async function generateNotFoundPages(sys, opts, routes) {
800
324
  if (opts.emit404Pages !== false) {
801
325
  const basePathname = opts.basePathname || "/";
802
326
  const rootNotFoundPathname = basePathname + "404.html";
803
- const hasRootNotFound = routes.some((r) => r[2] === rootNotFoundPathname);
327
+ const hasRootNotFound = routes.some(
328
+ (r) => r[RouteDataProp.OriginalPathname] === rootNotFoundPathname
329
+ );
804
330
  if (!hasRootNotFound) {
805
331
  const filePath = sys.getRouteFilePath(rootNotFoundPathname, true);
806
332
  const html = getErrorHtml(404, "Resource Not Found");
807
333
  await sys.ensureDir(filePath);
808
- return new Promise((resolve2) => {
334
+ return new Promise((resolve) => {
809
335
  const writer = sys.createWriteStream(filePath);
810
336
  writer.write(html);
811
- writer.end(resolve2);
337
+ writer.end(resolve);
812
338
  });
813
339
  }
814
340
  }
815
341
  }
816
342
 
817
- // packages/qwik-router/src/static/routes.ts
818
343
  function createRouteTester(basePathname, includeRoutes, excludeRoutes) {
819
344
  const includes = routesToRegExps(includeRoutes);
820
345
  const excludes = routesToRegExps(excludeRoutes);
@@ -861,20 +386,19 @@ function routeToRegExp(rule) {
861
386
  return new RegExp(transformedRule);
862
387
  }
863
388
 
864
- // packages/qwik-router/src/static/main-thread.ts
865
389
  async function mainThread(sys) {
866
390
  const opts = sys.getOptions();
867
391
  validateOptions(opts);
868
392
  const main = await sys.createMainProcess();
869
393
  const log = await sys.createLogger();
870
394
  log.info("\n" + bold(green("Starting Qwik Router SSG...")));
871
- const qwikRouterConfig = (await import(pathToFileURL2(opts.qwikRouterConfigModulePath).href)).default;
395
+ const qwikRouterConfig = (await import(pathToFileURL(opts.qwikRouterConfigModulePath).href)).default;
872
396
  const queue = [];
873
397
  const active = /* @__PURE__ */ new Set();
874
398
  const routes = qwikRouterConfig.routes || [];
875
399
  const trailingSlash = !!qwikRouterConfig.trailingSlash;
876
400
  const includeRoute = createRouteTester(opts.basePathname || "/", opts.include, opts.exclude);
877
- return new Promise((resolve2, reject) => {
401
+ return new Promise((resolve, reject) => {
878
402
  try {
879
403
  const timer = sys.createTimer();
880
404
  const generatorResult = {
@@ -909,19 +433,23 @@ ${green("SSG results")}`);
909
433
  log.info(``);
910
434
  }
911
435
  closePromise.then(() => {
912
- setTimeout(() => resolve2(generatorResult));
436
+ setTimeout(() => resolve(generatorResult));
913
437
  }).catch(reject);
914
438
  };
915
439
  const next = () => {
916
440
  while (!isCompleted && main.hasAvailableWorker() && queue.length > 0) {
917
441
  const staticRoute = queue.shift();
918
442
  if (staticRoute) {
919
- render(staticRoute);
443
+ render(staticRoute).catch((e) => {
444
+ console.error(`render failed for ${staticRoute.pathname}`, e);
445
+ });
920
446
  }
921
447
  }
922
448
  if (!isCompleted && isRoutesLoaded && queue.length === 0 && active.size === 0) {
923
449
  isCompleted = true;
924
- completed();
450
+ completed().catch((e) => {
451
+ console.error("SSG completion failed", e);
452
+ });
925
453
  }
926
454
  };
927
455
  let isPendingDrain = false;
@@ -956,12 +484,13 @@ ${bold(red(`!!! ${result.pathname}: Error during SSG`))}`);
956
484
  generatorResult.rendered++;
957
485
  generatorResult.staticPaths.push(result.pathname);
958
486
  const base = opts.rootDir ?? opts.outDir;
959
- const path = relative2(base, result.filePath);
487
+ const path = relative(base, result.filePath);
960
488
  const lastSlash = path.lastIndexOf("/");
961
489
  log.info(`${dim(path.slice(0, lastSlash + 1))}${path.slice(lastSlash + 1)}`);
962
490
  }
963
491
  flushQueue();
964
492
  } catch (e) {
493
+ console.error(`render failed for ${staticRoute.pathname}`, e);
965
494
  isCompleted = true;
966
495
  reject(e);
967
496
  }
@@ -1030,8 +559,12 @@ ${bold(red(`!!! ${result.pathname}: Error during SSG`))}`);
1030
559
  isRoutesLoaded = true;
1031
560
  flushQueue();
1032
561
  };
1033
- loadStaticRoutes();
562
+ loadStaticRoutes().catch((e) => {
563
+ console.error("SSG route loading failed", e);
564
+ reject(e);
565
+ });
1034
566
  } catch (e) {
567
+ console.error("SSG main thread failed", e);
1035
568
  reject(e);
1036
569
  }
1037
570
  });
@@ -1062,11 +595,267 @@ function validateOptions(opts) {
1062
595
  try {
1063
596
  new URL(siteOrigin);
1064
597
  } catch (e) {
1065
- throw new Error(`Invalid "origin": ${e}`);
598
+ throw new Error(`Invalid "origin"`, { cause: e });
599
+ }
600
+ }
601
+
602
+ async function workerThread(sys) {
603
+ delete globalThis.__qwik;
604
+ const ssgOpts = sys.getOptions();
605
+ const pendingPromises = /* @__PURE__ */ new Set();
606
+ const log = await sys.createLogger();
607
+ const opts = {
608
+ ...ssgOpts,
609
+ // TODO export this from server
610
+ render: (await import(pathToFileURL(ssgOpts.renderModulePath).href)).default,
611
+ // TODO this should be built-in
612
+ qwikRouterConfig: (await import(pathToFileURL(ssgOpts.qwikRouterConfigModulePath).href)).default
613
+ };
614
+ sys.createWorkerProcess(async (msg) => {
615
+ switch (msg.type) {
616
+ case "render": {
617
+ log.debug(`Worker thread rendering: ${msg.pathname}`);
618
+ return new Promise((resolve) => {
619
+ workerRender(sys, opts, msg, pendingPromises, resolve).catch((e) => {
620
+ console.error("Error during render", msg.pathname, e);
621
+ });
622
+ });
623
+ }
624
+ case "close": {
625
+ if (pendingPromises.size) {
626
+ log.debug(`Worker thread closing, waiting for ${pendingPromises.size} pending renders`);
627
+ const promises = Array.from(pendingPromises);
628
+ pendingPromises.clear();
629
+ await Promise.all(promises);
630
+ }
631
+ log.debug(`Worker thread closed`);
632
+ return { type: "close" };
633
+ }
634
+ }
635
+ })?.catch((e) => {
636
+ console.error("Worker process creation failed", e);
637
+ });
638
+ }
639
+ async function workerRender(sys, opts, staticRoute, pendingPromises, callback) {
640
+ const url = new URL(staticRoute.pathname, opts.origin);
641
+ const result = {
642
+ type: "render",
643
+ pathname: staticRoute.pathname,
644
+ url: url.href,
645
+ ok: false,
646
+ error: null,
647
+ filePath: null,
648
+ contentType: null,
649
+ resourceType: null
650
+ };
651
+ try {
652
+ let routeWriter = null;
653
+ let closeResolved;
654
+ const closePromise = new Promise((closePromiseResolve) => {
655
+ closeResolved = closePromiseResolve;
656
+ });
657
+ const request = new Request(url);
658
+ const requestCtx = {
659
+ mode: "static",
660
+ locale: void 0,
661
+ url,
662
+ request,
663
+ env: {
664
+ get(key) {
665
+ return sys.getEnv(key);
666
+ }
667
+ },
668
+ platform: sys.platform,
669
+ getClientConn: () => {
670
+ return {};
671
+ },
672
+ getWritableStream: (status, headers, _, _r, requestEv) => {
673
+ result.ok = status >= 200 && status < 300;
674
+ if (!result.ok) {
675
+ return noopWritableStream;
676
+ }
677
+ result.contentType = (headers.get("Content-Type") || "").toLowerCase();
678
+ const isHtml = result.contentType.includes("text/html");
679
+ const is404ErrorPage = url.pathname.endsWith("/404.html");
680
+ const routeFilePath = sys.getRouteFilePath(url.pathname, isHtml);
681
+ if (is404ErrorPage) {
682
+ result.resourceType = "404";
683
+ } else if (isHtml) {
684
+ result.resourceType = "page";
685
+ }
686
+ const hasRouteWriter = isHtml ? opts.emitHtml !== false : true;
687
+ const writeQDataEnabled = isHtml && opts.emitData !== false;
688
+ const stream = new WritableStream({
689
+ async start() {
690
+ try {
691
+ if (hasRouteWriter || writeQDataEnabled) {
692
+ await sys.ensureDir(routeFilePath);
693
+ }
694
+ if (hasRouteWriter) {
695
+ routeWriter = sys.createWriteStream(routeFilePath);
696
+ routeWriter.on("error", (e) => {
697
+ console.error(e);
698
+ routeWriter = null;
699
+ result.error = {
700
+ message: e.message,
701
+ stack: e.stack
702
+ };
703
+ });
704
+ }
705
+ } catch (e) {
706
+ console.error("Error during stream start", staticRoute.pathname, e);
707
+ routeWriter = null;
708
+ result.error = {
709
+ message: String(e),
710
+ stack: e.stack || ""
711
+ };
712
+ }
713
+ },
714
+ write(chunk) {
715
+ try {
716
+ if (routeWriter) {
717
+ routeWriter.write(Buffer.from(chunk.buffer));
718
+ }
719
+ } catch (e) {
720
+ console.error("Error during stream write", staticRoute.pathname, e);
721
+ routeWriter = null;
722
+ result.error = {
723
+ message: String(e),
724
+ stack: e.stack || ""
725
+ };
726
+ }
727
+ },
728
+ async close() {
729
+ const writePromises = [];
730
+ try {
731
+ if (writeQDataEnabled) {
732
+ const qData = requestEv.sharedMap.get(RequestEvShareQData);
733
+ if (qData && !is404ErrorPage) {
734
+ const qDataFilePath = sys.getDataFilePath(url.pathname);
735
+ const dataWriter = sys.createWriteStream(qDataFilePath);
736
+ dataWriter.on("error", (e) => {
737
+ console.error(e);
738
+ result.error = {
739
+ message: e.message,
740
+ stack: e.stack
741
+ };
742
+ });
743
+ const serialized = await _serialize([qData]);
744
+ dataWriter.write(serialized);
745
+ writePromises.push(
746
+ new Promise((resolve) => {
747
+ result.filePath = routeFilePath;
748
+ dataWriter.end(resolve);
749
+ })
750
+ );
751
+ }
752
+ }
753
+ if (routeWriter) {
754
+ writePromises.push(
755
+ new Promise((resolve) => {
756
+ result.filePath = routeFilePath;
757
+ routeWriter.end(resolve);
758
+ }).finally(closeResolved)
759
+ );
760
+ }
761
+ if (writePromises.length > 0) {
762
+ await Promise.all(writePromises);
763
+ }
764
+ } catch (e) {
765
+ console.error("Error during stream close", staticRoute.pathname, e);
766
+ routeWriter = null;
767
+ result.error = {
768
+ message: String(e),
769
+ stack: e.stack || ""
770
+ };
771
+ }
772
+ }
773
+ });
774
+ return stream;
775
+ }
776
+ };
777
+ const promise = requestHandler(requestCtx, opts).then((rsp) => {
778
+ if (rsp != null) {
779
+ return rsp.completion.then((r) => {
780
+ if (routeWriter) {
781
+ return closePromise.then(() => r);
782
+ }
783
+ return r;
784
+ });
785
+ }
786
+ }).then((e) => {
787
+ if (e !== void 0) {
788
+ if (e instanceof RedirectMessage) {
789
+ return;
790
+ }
791
+ if (e instanceof Error) {
792
+ result.error = {
793
+ message: e.message,
794
+ stack: e.stack
795
+ };
796
+ } else {
797
+ result.error = {
798
+ message: String(e),
799
+ stack: void 0
800
+ };
801
+ }
802
+ console.error("Error during request handling", staticRoute.pathname, e);
803
+ }
804
+ }).catch((e) => {
805
+ console.error("Unhandled error during request handling", staticRoute.pathname, e);
806
+ result.error = {
807
+ message: String(e),
808
+ stack: e.stack || ""
809
+ };
810
+ }).finally(() => {
811
+ pendingPromises.delete(promise);
812
+ callback(result);
813
+ });
814
+ pendingPromises.add(promise);
815
+ } catch (e) {
816
+ console.error("Error during render", staticRoute.pathname, e);
817
+ if (e instanceof Error) {
818
+ result.error = {
819
+ message: e.message,
820
+ stack: e.stack
821
+ };
822
+ } else {
823
+ result.error = {
824
+ message: String(e),
825
+ stack: void 0
826
+ };
827
+ }
828
+ callback(result);
1066
829
  }
1067
830
  }
831
+ const noopWriter = {
832
+ closed: Promise.resolve(void 0),
833
+ ready: Promise.resolve(void 0),
834
+ desiredSize: 0,
835
+ async close() {
836
+ },
837
+ async abort() {
838
+ },
839
+ async write() {
840
+ },
841
+ releaseLock() {
842
+ }
843
+ };
844
+ const noopWritableStream = {
845
+ get locked() {
846
+ return false;
847
+ },
848
+ set locked(_) {
849
+ },
850
+ async abort() {
851
+ },
852
+ async close() {
853
+ },
854
+ getWriter() {
855
+ return noopWriter;
856
+ }
857
+ };
1068
858
 
1069
- // packages/qwik-router/src/static/node/index.ts
1070
859
  async function generate(opts) {
1071
860
  if (isMainThread) {
1072
861
  const sys = await createSystem(opts);
@@ -1076,11 +865,20 @@ async function generate(opts) {
1076
865
  throw new Error(`generate() cannot be called from a worker thread`);
1077
866
  }
1078
867
  if (!isMainThread && workerData) {
868
+ const opts = workerData;
1079
869
  (async () => {
1080
- const sys = await createSystem(workerData);
1081
- await workerThread(sys);
1082
- })();
870
+ try {
871
+ if (opts.log === "debug") {
872
+ console.debug(`Worker thread starting (ID: ${threadId})`);
873
+ }
874
+ const sys = await createSystem(opts, threadId);
875
+ await workerThread(sys);
876
+ } catch (error) {
877
+ console.error(`Error occurred in worker thread (ID: ${threadId}): ${error}`);
878
+ }
879
+ })().catch((e) => {
880
+ console.error(e);
881
+ });
1083
882
  }
1084
- export {
1085
- generate
1086
- };
883
+
884
+ export { generate };