@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.
- package/adapters/static/vite.d.ts +1 -1
- package/lib/adapters/azure-swa/vite/index.d.ts +2 -2
- package/lib/adapters/azure-swa/vite/index.mjs +9 -9
- package/lib/adapters/bun-server/vite/index.d.ts +2 -2
- package/lib/adapters/bun-server/vite/index.mjs +9 -7
- package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
- package/lib/adapters/cloud-run/vite/index.mjs +9 -7
- package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
- package/lib/adapters/cloudflare-pages/vite/index.mjs +9 -24
- package/lib/adapters/deno-server/vite/index.d.ts +2 -2
- package/lib/adapters/deno-server/vite/index.mjs +9 -7
- package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
- package/lib/adapters/netlify-edge/vite/index.mjs +10 -14
- package/lib/adapters/node-server/vite/index.d.ts +2 -2
- package/lib/adapters/node-server/vite/index.mjs +9 -7
- package/lib/adapters/shared/vite/index.d.ts +13 -19
- package/lib/adapters/shared/vite/index.mjs +107 -139
- package/lib/adapters/ssg/vite/index.d.ts +13 -0
- package/lib/adapters/ssg/vite/index.mjs +18 -0
- package/lib/adapters/vercel-edge/vite/index.d.ts +3 -3
- package/lib/adapters/vercel-edge/vite/index.mjs +9 -11
- package/lib/chunks/error-handler.mjs +57 -0
- package/lib/chunks/format-error.mjs +137 -0
- package/lib/chunks/fs.mjs +254 -0
- package/lib/{static/node.mjs → chunks/index.mjs} +361 -563
- package/lib/chunks/mime-types.mjs +52 -0
- package/lib/chunks/routing.qwik.mjs +429 -0
- package/lib/chunks/types.qwik.mjs +22 -0
- package/lib/index.d.ts +240 -60
- package/lib/index.qwik.mjs +698 -983
- package/lib/middleware/aws-lambda/index.d.ts +3 -2
- package/lib/middleware/aws-lambda/index.mjs +8 -12
- package/lib/middleware/azure-swa/index.mjs +10 -216
- package/lib/middleware/bun/index.d.ts +11 -0
- package/lib/middleware/bun/index.mjs +24 -83
- package/lib/middleware/cloudflare-pages/index.mjs +10 -22
- package/lib/middleware/deno/index.d.ts +11 -0
- package/lib/middleware/deno/index.mjs +24 -83
- package/lib/middleware/firebase/index.mjs +7 -11
- package/lib/middleware/netlify-edge/index.mjs +10 -23
- package/lib/middleware/node/index.mjs +22 -87
- package/lib/middleware/request-handler/index.d.ts +89 -70
- package/lib/middleware/request-handler/index.mjs +584 -659
- package/lib/middleware/vercel-edge/index.mjs +15 -27
- package/lib/modules.d.ts +4 -12
- package/lib/service-worker/index.mjs +4 -0
- package/lib/{static → ssg}/index.d.ts +17 -17
- package/lib/ssg/index.mjs +14 -0
- package/lib/vite/index.d.ts +32 -10
- package/lib/vite/index.mjs +1524 -26934
- package/modules.d.ts +4 -12
- package/package.json +62 -68
- package/ssg.d.ts +2 -0
- package/static.d.ts +1 -1
- package/lib/adapters/azure-swa/vite/index.cjs +0 -96
- package/lib/adapters/bun-server/vite/index.cjs +0 -50
- package/lib/adapters/cloud-run/vite/index.cjs +0 -47
- package/lib/adapters/cloudflare-pages/vite/index.cjs +0 -115
- package/lib/adapters/deno-server/vite/index.cjs +0 -62
- package/lib/adapters/netlify-edge/vite/index.cjs +0 -129
- package/lib/adapters/node-server/vite/index.cjs +0 -50
- package/lib/adapters/shared/vite/index.cjs +0 -378
- package/lib/adapters/static/vite/index.cjs +0 -368
- package/lib/adapters/static/vite/index.d.ts +0 -10
- package/lib/adapters/static/vite/index.mjs +0 -331
- package/lib/adapters/vercel-edge/vite/index.cjs +0 -118
- package/lib/index.qwik.cjs +0 -1947
- package/lib/middleware/node/index.cjs +0 -314
- package/lib/middleware/request-handler/index.cjs +0 -1614
- package/lib/service-worker.cjs +0 -17
- package/lib/service-worker.mjs +0 -15
- package/lib/static/deno.mjs +0 -8
- package/lib/static/index.cjs +0 -67
- package/lib/static/index.mjs +0 -48
- package/lib/static/node.cjs +0 -1124
- package/lib/vite/index.cjs +0 -27445
- package/middleware/request-handler/generated/not-found-paths.ts +0 -7
- package/middleware/request-handler/generated/static-paths.ts +0 -35
|
@@ -1,317 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
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 =
|
|
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
|
|
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
|
-
|
|
51
|
+
const ext = extname(__filename) || ".js";
|
|
52
|
+
workerFilePath = join(dirname(__filename), `index${ext}`);
|
|
368
53
|
} else {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
134
|
+
const render = async (ssgRoute) => {
|
|
438
135
|
const ssgWorker = getNextWorker();
|
|
439
|
-
const result = await ssgWorker.render(
|
|
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(
|
|
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
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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
|
-
|
|
513
|
-
async function createSystem(opts) {
|
|
214
|
+
async function createSystem(opts, threadId) {
|
|
514
215
|
const createWriteStream = (filePath) => {
|
|
515
|
-
return
|
|
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
|
-
|
|
586
|
-
await
|
|
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
|
-
|
|
297
|
+
const access = async (path) => {
|
|
696
298
|
try {
|
|
697
|
-
|
|
299
|
+
await fs.promises.access(path);
|
|
300
|
+
return true;
|
|
698
301
|
} catch {
|
|
699
|
-
return
|
|
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(
|
|
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((
|
|
334
|
+
return new Promise((resolve) => {
|
|
809
335
|
const writer = sys.createWriteStream(filePath);
|
|
810
336
|
writer.write(html);
|
|
811
|
-
writer.end(
|
|
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(
|
|
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((
|
|
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(() =>
|
|
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 =
|
|
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":
|
|
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
|
-
|
|
1081
|
-
|
|
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
|
-
|
|
1085
|
-
|
|
1086
|
-
};
|
|
883
|
+
|
|
884
|
+
export { generate };
|