@qwik.dev/router 2.0.0-beta.4 → 2.0.0-beta.40

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 (87) 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 +44 -58
  4. package/lib/adapters/bun-server/vite/index.d.ts +2 -2
  5. package/lib/adapters/bun-server/vite/index.mjs +16 -23
  6. package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
  7. package/lib/adapters/cloud-run/vite/index.mjs +15 -20
  8. package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
  9. package/lib/adapters/cloudflare-pages/vite/index.mjs +45 -77
  10. package/lib/adapters/deno-server/vite/index.d.ts +2 -2
  11. package/lib/adapters/deno-server/vite/index.mjs +25 -35
  12. package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
  13. package/lib/adapters/netlify-edge/vite/index.mjs +49 -89
  14. package/lib/adapters/node-server/vite/index.d.ts +2 -2
  15. package/lib/adapters/node-server/vite/index.mjs +16 -23
  16. package/lib/adapters/shared/vite/index.d.ts +9 -22
  17. package/lib/adapters/shared/vite/index.mjs +273 -333
  18. package/lib/adapters/ssg/vite/index.d.ts +13 -0
  19. package/lib/adapters/ssg/vite/index.mjs +13 -0
  20. package/lib/adapters/vercel-edge/vite/index.d.ts +3 -3
  21. package/lib/adapters/vercel-edge/vite/index.mjs +73 -80
  22. package/lib/chunks/dev-preloaded-route-loader.mjs +2 -0
  23. package/lib/chunks/format.mjs +24 -0
  24. package/lib/chunks/fs.mjs +133 -0
  25. package/lib/chunks/head.qwik.mjs +1217 -0
  26. package/lib/chunks/http-error.qwik.mjs +27 -0
  27. package/lib/chunks/pathname.mjs +57 -0
  28. package/lib/chunks/request-body-limit.mjs +27 -0
  29. package/lib/chunks/request-path.mjs +49 -0
  30. package/lib/chunks/routes.mjs +26 -0
  31. package/lib/chunks/server-error.mjs +16 -0
  32. package/lib/chunks/system.mjs +265 -0
  33. package/lib/chunks/url.mjs +59 -0
  34. package/lib/chunks/user-response.mjs +1707 -0
  35. package/lib/chunks/worker-thread.mjs +264 -0
  36. package/lib/index.d.ts +626 -170
  37. package/lib/index.qwik.mjs +1649 -1964
  38. package/lib/middleware/aws-lambda/index.d.ts +15 -16
  39. package/lib/middleware/aws-lambda/index.mjs +45 -54
  40. package/lib/middleware/azure-swa/index.mjs +85 -295
  41. package/lib/middleware/bun/index.d.ts +20 -5
  42. package/lib/middleware/bun/index.mjs +119 -205
  43. package/lib/middleware/cloudflare-pages/index.mjs +83 -105
  44. package/lib/middleware/deno/index.d.ts +22 -5
  45. package/lib/middleware/deno/index.mjs +105 -192
  46. package/lib/middleware/firebase/index.mjs +22 -35
  47. package/lib/middleware/netlify-edge/index.mjs +63 -81
  48. package/lib/middleware/node/index.d.ts +17 -5
  49. package/lib/middleware/node/index.mjs +299 -273
  50. package/lib/middleware/request-handler/index.d.ts +206 -99
  51. package/lib/middleware/request-handler/index.mjs +117 -1648
  52. package/lib/middleware/vercel-edge/index.mjs +76 -101
  53. package/lib/modules.d.ts +11 -16
  54. package/lib/service-worker/index.mjs +13 -0
  55. package/lib/{static → ssg}/index.d.ts +46 -22
  56. package/lib/ssg/index.mjs +257 -0
  57. package/lib/vite/index.d.ts +58 -10
  58. package/lib/vite/index.mjs +2459 -27446
  59. package/modules.d.ts +11 -16
  60. package/package.json +63 -67
  61. package/ssg.d.ts +2 -0
  62. package/static.d.ts +1 -1
  63. package/lib/adapters/azure-swa/vite/index.cjs +0 -96
  64. package/lib/adapters/bun-server/vite/index.cjs +0 -50
  65. package/lib/adapters/cloud-run/vite/index.cjs +0 -47
  66. package/lib/adapters/cloudflare-pages/vite/index.cjs +0 -115
  67. package/lib/adapters/deno-server/vite/index.cjs +0 -62
  68. package/lib/adapters/netlify-edge/vite/index.cjs +0 -129
  69. package/lib/adapters/node-server/vite/index.cjs +0 -50
  70. package/lib/adapters/shared/vite/index.cjs +0 -378
  71. package/lib/adapters/static/vite/index.cjs +0 -368
  72. package/lib/adapters/static/vite/index.d.ts +0 -10
  73. package/lib/adapters/static/vite/index.mjs +0 -331
  74. package/lib/adapters/vercel-edge/vite/index.cjs +0 -118
  75. package/lib/index.qwik.cjs +0 -2022
  76. package/lib/middleware/node/index.cjs +0 -314
  77. package/lib/middleware/request-handler/index.cjs +0 -1691
  78. package/lib/service-worker.cjs +0 -17
  79. package/lib/service-worker.mjs +0 -15
  80. package/lib/static/deno.mjs +0 -8
  81. package/lib/static/index.cjs +0 -67
  82. package/lib/static/index.mjs +0 -48
  83. package/lib/static/node.cjs +0 -1126
  84. package/lib/static/node.mjs +0 -1088
  85. package/lib/vite/index.cjs +0 -27525
  86. package/middleware/request-handler/generated/not-found-paths.ts +0 -7
  87. package/middleware/request-handler/generated/static-paths.ts +0 -35
@@ -0,0 +1,27 @@
1
+ import { useHttpStatus } from "../index.qwik.mjs";
2
+ import { _fnSignal, _jsxSorted, componentQrl, inlinedQrl } from "@qwik.dev/core";
3
+ var _hf0 = (p0) => p0.status || 500;
4
+ var _hf0_str = "p0.status||500";
5
+ var _hf1 = (p0) => p0.message || "";
6
+ var _hf1_str = "p0.message||\"\"";
7
+ /** Cache error pages per status code so all 404s (or 500s) share one cache entry. */ var cacheKey = (ev) => String(ev.status);
8
+ var COLOR_400 = "#006ce9";
9
+ var COLOR_500 = "#713fc2";
10
+ var DisplayHttpStatus = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(() => {
11
+ const httpstatus = useHttpStatus();
12
+ const width = httpstatus.message ? "600px" : "300px";
13
+ const color = httpstatus.status < 500 ? COLOR_400 : COLOR_500;
14
+ const style = `
15
+ body { color: ${color}; background-color: #fafafa; padding: 30px; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Roboto, sans-serif; }
16
+ p { max-width: ${width}; margin: 60px auto 30px auto; background: white; border-radius: 4px; box-shadow: 0px 0px 50px -20px ${color}; overflow: hidden; }
17
+ strong { display: inline-block; padding: 15px; background: ${color}; color: white; }
18
+ span { display: inline-block; padding: 15px; }
19
+ `;
20
+ return /*#__PURE__*/ _jsxSorted("p", null, null, [
21
+ /*#__PURE__*/ _jsxSorted("style", { dangerouslySetInnerHTML: style }, null, null, 3, null),
22
+ /*#__PURE__*/ _jsxSorted("strong", null, null, _fnSignal(_hf0, [httpstatus], _hf0_str), 3, null),
23
+ " ",
24
+ /*#__PURE__*/ _jsxSorted("span", null, null, _fnSignal(_hf1, [httpstatus], _hf1_str), 3, null)
25
+ ], 1, "vY_0");
26
+ }, "DisplayHttpStatus_component_PJf4K4PL7Oc"));
27
+ export { cacheKey, DisplayHttpStatus as default };
@@ -0,0 +1,57 @@
1
+ /** Ensures the pathname ends with a slash */ var ensureSlash = (pathname) => pathname.endsWith("/") ? pathname : pathname + "/";
2
+ function normalizePathname(pathname, basePathname) {
3
+ if (typeof pathname === "string") {
4
+ pathname = pathname.trim();
5
+ if (pathname !== "") try {
6
+ pathname = pathname.replace(/\/+/g, "/");
7
+ if (pathname.startsWith("/")) pathname = pathname.slice(1);
8
+ pathname = new URL(basePathname + pathname, `https://qwik.dev`).pathname;
9
+ if (pathname !== basePathname) {
10
+ if (!globalThis.__NO_TRAILING_SLASH__) {
11
+ if (!pathname.endsWith("/")) {
12
+ const segments = pathname.split("/");
13
+ if (!segments[segments.length - 1].includes(".")) pathname = ensureSlash(pathname);
14
+ }
15
+ } else if (pathname.endsWith("/")) pathname = pathname.slice(0, pathname.length - 1);
16
+ }
17
+ return pathname;
18
+ } catch (e) {
19
+ console.error(e);
20
+ }
21
+ }
22
+ return null;
23
+ }
24
+ function getPathnameForDynamicRoute(originalPathname, paramNames, params) {
25
+ let pathname = originalPathname;
26
+ if (paramNames && params) for (const paramName of paramNames) {
27
+ const paramKey = `[${paramName}]`;
28
+ const restParamKey = `[...${paramName}]`;
29
+ const paramValue = params[paramName];
30
+ pathname = pathname.replace(restParamKey, paramValue);
31
+ pathname = pathname.replace(paramKey, paramValue);
32
+ }
33
+ return pathname;
34
+ }
35
+ var PROTOCOLS = {
36
+ https: true,
37
+ http: true,
38
+ about: true,
39
+ javascript: true,
40
+ file: true
41
+ };
42
+ function isSameOriginUrl(url) {
43
+ if (typeof url === "string") {
44
+ url = url.trim();
45
+ if (url !== "") {
46
+ const firstChar = url.charAt(0);
47
+ if (firstChar !== "/" && firstChar !== ".") {
48
+ if (firstChar === "#") return false;
49
+ const i = url.indexOf(":");
50
+ if (i > -1) return !PROTOCOLS[url.slice(0, i).toLowerCase()];
51
+ }
52
+ return true;
53
+ }
54
+ }
55
+ return false;
56
+ }
57
+ export { normalizePathname as i, getPathnameForDynamicRoute as n, isSameOriginUrl as r, ensureSlash as t };
@@ -0,0 +1,27 @@
1
+ import { t as ServerError } from "./server-error.mjs";
2
+ var DEFAULT_REQUEST_BODY_LIMIT = 10485760;
3
+ var RequestBodyLimitError = class extends ServerError {
4
+ code = "QWIK_REQUEST_BODY_LIMIT";
5
+ statusCode = 413;
6
+ constructor(limit) {
7
+ super(413, `Request body exceeds ${limit} bytes`);
8
+ }
9
+ };
10
+ var validateRequestBodyLimit = (requestBodyLimit) => {
11
+ if (!Number.isSafeInteger(requestBodyLimit) || requestBodyLimit <= 0) throw new TypeError("requestBodyLimit must be a positive safe integer");
12
+ };
13
+ var limitRequestBody = (request, requestBodyLimit = DEFAULT_REQUEST_BODY_LIMIT) => {
14
+ validateRequestBodyLimit(requestBodyLimit);
15
+ if (!request.body) return request;
16
+ let received = 0;
17
+ const body = request.body.pipeThrough(new TransformStream({ transform(chunk, controller) {
18
+ if (chunk.byteLength > requestBodyLimit - received) throw new RequestBodyLimitError(requestBodyLimit);
19
+ received += chunk.byteLength;
20
+ controller.enqueue(chunk);
21
+ } }));
22
+ return new Request(request, {
23
+ body,
24
+ duplex: "half"
25
+ });
26
+ };
27
+ export { validateRequestBodyLimit as i, RequestBodyLimitError as n, limitRequestBody as r, DEFAULT_REQUEST_BODY_LIMIT as t };
@@ -0,0 +1,49 @@
1
+ import { t as ensureSlash } from "./pathname.mjs";
2
+ var IsQLoader = "@isQLoader";
3
+ var IsQAction = "@isQAction";
4
+ var QLoaderId = "@loaderId";
5
+ var QActionId = "@actionId";
6
+ /** Matches the final `/q-loader-{loaderId}.{manifestHash}.json` path segment. */ var LOADER_REGEX = /\/(q-loader-([^/.]+)\.([^/.]+)\.json)$/;
7
+ var getLoaderName = (loaderId, manifestHash) => `q-loader-${loaderId}.${manifestHash}.json`;
8
+ /**
9
+ * Recognize internal request types from the URL pathname.
10
+ *
11
+ * Returns the request type, how many characters to trim from the pathname, and any extracted data
12
+ * (e.g. loaderId for loader requests).
13
+ */ function recognizeRequest(pathname) {
14
+ if (pathname.length < 10) return null;
15
+ const loaderMatch = pathname.match(LOADER_REGEX);
16
+ if (loaderMatch) return {
17
+ type: IsQLoader,
18
+ trimLength: loaderMatch[1].length + 1,
19
+ data: {
20
+ loaderId: loaderMatch[2],
21
+ manifestHash: loaderMatch[3]
22
+ }
23
+ };
24
+ return null;
25
+ }
26
+ /** Trim a recognized internal URL suffix from a pathname, returning the clean route pathname. */ function trimRecognizedInternalPathname(pathname, recognized) {
27
+ let trimmed = pathname.slice(0, pathname.length - recognized.trimLength) || "/";
28
+ if (!globalThis.__NO_TRAILING_SLASH__ && !trimmed.endsWith("/")) trimmed = ensureSlash(trimmed);
29
+ return trimmed;
30
+ }
31
+ /** Trim any recognized internal URL suffix from a pathname, returning the clean route pathname. */ function trimInternalPathname(pathname) {
32
+ const recognized = recognizeRequest(pathname);
33
+ if (recognized) return trimRecognizedInternalPathname(pathname, recognized);
34
+ return pathname;
35
+ }
36
+ function resolveValidInternalFullPathname(loaderPathname, fullPath) {
37
+ if (!fullPath || !fullPath.startsWith("/") || fullPath.startsWith("//")) return;
38
+ try {
39
+ const pageUrl = new URL(fullPath, "http://qwik.internal");
40
+ if (pageUrl.origin !== "http://qwik.internal") return;
41
+ const pagePathname = pageUrl.pathname;
42
+ if (pagePathname === loaderPathname) return;
43
+ const loaderPrefix = ensureSlash(loaderPathname);
44
+ return pagePathname.startsWith(loaderPrefix) ? pagePathname : void 0;
45
+ } catch {
46
+ return;
47
+ }
48
+ }
49
+ export { QLoaderId as a, resolveValidInternalFullPathname as c, QActionId as i, trimInternalPathname as l, IsQLoader as n, getLoaderName as o, LOADER_REGEX as r, recognizeRequest as s, IsQAction as t, trimRecognizedInternalPathname as u };
@@ -0,0 +1,26 @@
1
+ function routeToRegExp(rule) {
2
+ let transformedRule;
3
+ if (rule === "/" || rule === "/*") transformedRule = rule;
4
+ else if (rule.endsWith("/*")) transformedRule = `${rule.substring(0, rule.length - 2)}(/*)?`;
5
+ else if (rule.endsWith("/")) transformedRule = `${rule.substring(0, rule.length - 1)}(/)?`;
6
+ else if (rule.endsWith("*")) transformedRule = rule;
7
+ else transformedRule = `${rule}(/)?`;
8
+ transformedRule = `^${transformedRule.replace(/\*/g, ".*")}$`;
9
+ return new RegExp(transformedRule);
10
+ }
11
+ function routesToRegExps(routes) {
12
+ if (!Array.isArray(routes)) return [];
13
+ return routes.filter((r) => typeof r === "string").map(routeToRegExp);
14
+ }
15
+ function createRouteTester(basePathname, includeRoutes, excludeRoutes) {
16
+ const includes = routesToRegExps(includeRoutes);
17
+ const excludes = routesToRegExps(excludeRoutes);
18
+ return (pathname) => {
19
+ if (basePathname !== "/") pathname = pathname.slice(basePathname.length - 1);
20
+ for (const exclude of excludes) if (exclude.test(pathname)) return false;
21
+ if (pathname.endsWith("/404.html")) return true;
22
+ for (const include of includes) if (include.test(pathname)) return true;
23
+ return false;
24
+ };
25
+ }
26
+ export { createRouteTester as t };
@@ -0,0 +1,16 @@
1
+ /** @public */ var AbortMessage = class {};
2
+ /** @public */ var RedirectMessage = class extends AbortMessage {};
3
+ /** @public */ var ServerError = class extends Error {
4
+ status;
5
+ data;
6
+ constructor(status, data) {
7
+ super(typeof data === "string" ? data : void 0), this.status = status, this.data = data;
8
+ }
9
+ };
10
+ /**
11
+ * `ev.redirect()`, `ev.error()`, etc. return a control-flow signal meant to be thrown. Throw it for
12
+ * the user when they return it instead, so returning and throwing behave the same.
13
+ */ var throwIfControlFlowSignal = (value) => {
14
+ if (value instanceof AbortMessage || value instanceof ServerError) throw value;
15
+ };
16
+ export { RedirectMessage as i, throwIfControlFlowSignal as n, AbortMessage as r, ServerError as t };
@@ -0,0 +1,265 @@
1
+ import { t as ensureSlash } from "./pathname.mjs";
2
+ import { o as getLoaderName } from "./request-path.mjs";
3
+ import { _ as normalizePath } from "./fs.mjs";
4
+ import fs from "node:fs";
5
+ import { dirname, isAbsolute, join, resolve } from "node:path";
6
+ import { cpus } from "node:os";
7
+ import { Worker } from "node:worker_threads";
8
+ function ssgWorkerCompare(a, b) {
9
+ if (a.activeTasks < b.activeTasks) return -1;
10
+ if (a.activeTasks > b.activeTasks) return 1;
11
+ return a.totalTasks < b.totalTasks ? -1 : 1;
12
+ }
13
+ async function createWorkerPool(sys, opts) {
14
+ const log = await sys.createLogger();
15
+ const ssgWorkers = [];
16
+ const sitemapBuffer = [];
17
+ let sitemapStream = null;
18
+ opts = { ...opts };
19
+ let outDir = opts.outDir;
20
+ if (typeof outDir !== "string") throw new Error(`Missing "outDir" option`);
21
+ if (!isAbsolute(outDir)) throw new Error(`"outDir" must be an absolute file path, received: ${outDir}`);
22
+ outDir = normalizePath(outDir);
23
+ let maxWorkers = cpus().length;
24
+ if (typeof opts.maxWorkers === "number") maxWorkers = Math.max(1, Math.min(opts.maxWorkers, maxWorkers));
25
+ let maxTasksPerWorker = 20;
26
+ if (typeof opts.maxTasksPerWorker === "number") maxTasksPerWorker = Math.max(1, Math.min(opts.maxTasksPerWorker, 50));
27
+ let sitemapOutFile = opts.sitemapOutFile;
28
+ if (sitemapOutFile !== null) {
29
+ if (typeof sitemapOutFile !== "string") sitemapOutFile = "sitemap.xml";
30
+ if (!isAbsolute(sitemapOutFile)) sitemapOutFile = resolve(outDir, sitemapOutFile);
31
+ }
32
+ if (!opts.workerFilePath) throw new Error("Missing \"workerFilePath\" option for SSG worker creation");
33
+ const workerFilePath = typeof opts.workerFilePath === "string" && opts.workerFilePath.startsWith("file://") ? new URL(opts.workerFilePath) : opts.workerFilePath;
34
+ const { render: _r, qwikRouterConfig: _c, workerFilePath: _w, ...workerData } = opts;
35
+ const createWorker = () => {
36
+ let terminateResolve = null;
37
+ const mainTasks = /* @__PURE__ */ new Map();
38
+ let terminateTimeout = null;
39
+ const nodeWorker = new Worker(workerFilePath, { workerData });
40
+ nodeWorker.unref();
41
+ const ssgWorker = {
42
+ activeTasks: 0,
43
+ totalTasks: 0,
44
+ render: (staticRoute) => {
45
+ return new Promise((resolve, reject) => {
46
+ try {
47
+ ssgWorker.activeTasks++;
48
+ ssgWorker.totalTasks++;
49
+ mainTasks.set(staticRoute.pathname, resolve);
50
+ nodeWorker.postMessage(staticRoute);
51
+ } catch (e) {
52
+ ssgWorker.activeTasks--;
53
+ mainTasks.delete(staticRoute.pathname);
54
+ reject(e);
55
+ }
56
+ });
57
+ },
58
+ terminate: async () => {
59
+ mainTasks.clear();
60
+ const msg = { type: "close" };
61
+ await new Promise((resolve) => {
62
+ terminateResolve = () => {
63
+ resolve();
64
+ };
65
+ terminateTimeout = setTimeout(async () => {
66
+ terminateTimeout = null;
67
+ terminateResolve = null;
68
+ await nodeWorker.terminate();
69
+ resolve();
70
+ }, 1e3);
71
+ nodeWorker.postMessage(msg);
72
+ });
73
+ if (terminateTimeout) {
74
+ clearTimeout(terminateTimeout);
75
+ terminateTimeout = null;
76
+ }
77
+ }
78
+ };
79
+ nodeWorker.on("message", (msg) => {
80
+ switch (msg.type) {
81
+ case "render": {
82
+ const mainTask = mainTasks.get(msg.pathname);
83
+ if (mainTask) {
84
+ mainTasks.delete(msg.pathname);
85
+ ssgWorker.activeTasks--;
86
+ mainTask(msg);
87
+ }
88
+ break;
89
+ }
90
+ case "close": if (terminateResolve) {
91
+ terminateResolve();
92
+ terminateResolve = null;
93
+ }
94
+ }
95
+ });
96
+ nodeWorker.on("error", (e) => {
97
+ log.error(`worker error`, e);
98
+ });
99
+ nodeWorker.on("exit", (code) => {
100
+ log.debug(`worker exit code=${code}`);
101
+ if (terminateTimeout) {
102
+ clearTimeout(terminateTimeout);
103
+ terminateTimeout = null;
104
+ }
105
+ if (mainTasks.size > 0) {
106
+ for (const [pathname, resolve] of mainTasks) {
107
+ ssgWorker.activeTasks--;
108
+ resolve({
109
+ type: "render",
110
+ pathname,
111
+ url: "",
112
+ ok: false,
113
+ error: {
114
+ message: `Worker exited with code ${code}`,
115
+ stack: void 0
116
+ },
117
+ filePath: null,
118
+ contentType: null,
119
+ resourceType: null
120
+ });
121
+ }
122
+ mainTasks.clear();
123
+ }
124
+ if (terminateResolve) {
125
+ terminateResolve();
126
+ terminateResolve = null;
127
+ }
128
+ if (code !== 0) console.error(`worker exit ${code}`);
129
+ });
130
+ return ssgWorker;
131
+ };
132
+ const getNextWorker = () => ssgWorkers.sort(ssgWorkerCompare)[0];
133
+ const hasAvailableWorker = () => {
134
+ return getNextWorker().activeTasks < maxTasksPerWorker;
135
+ };
136
+ const render = async (ssgRoute) => {
137
+ const result = await getNextWorker().render(ssgRoute);
138
+ const isNotFoundPage = result.pathname.endsWith("/404.html");
139
+ if (sitemapOutFile && result.ok && result.resourceType === "page" && !isNotFoundPage) {
140
+ sitemapBuffer.push(`<url><loc>${result.url}</loc></url>`);
141
+ if (sitemapBuffer.length > 50) {
142
+ const siteMapUrls = sitemapBuffer.join("\n") + "\n";
143
+ sitemapBuffer.length = 0;
144
+ if (sitemapStream) sitemapStream.write(siteMapUrls);
145
+ }
146
+ }
147
+ return result;
148
+ };
149
+ const close = async () => {
150
+ const promises = [];
151
+ if (sitemapStream) {
152
+ sitemapBuffer.push(`</urlset>`);
153
+ sitemapStream.write(sitemapBuffer.join("\n"));
154
+ sitemapBuffer.length = 0;
155
+ await new Promise((resolve, reject) => {
156
+ if (sitemapStream) sitemapStream.end((err) => {
157
+ if (err) reject(err);
158
+ else resolve();
159
+ });
160
+ else resolve();
161
+ });
162
+ sitemapStream = null;
163
+ }
164
+ for (const ssgWorker of ssgWorkers) try {
165
+ promises.push(ssgWorker.terminate());
166
+ } catch (e) {
167
+ console.error(e);
168
+ }
169
+ await Promise.all(promises);
170
+ ssgWorkers.length = 0;
171
+ if (process.platform === "win32") await new Promise((resolve) => setTimeout(resolve, 300));
172
+ };
173
+ if (sitemapOutFile) {
174
+ await sys.ensureDir(sitemapOutFile);
175
+ sitemapStream = fs.createWriteStream(sitemapOutFile, { flags: "w" });
176
+ sitemapStream.write(`<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n`);
177
+ }
178
+ log.debug(`creating ${maxWorkers} workers, ${maxTasksPerWorker} tasks each`);
179
+ for (let i = 0; i < maxWorkers; i++) {
180
+ ssgWorkers.push(createWorker());
181
+ if (process.platform === "win32" && i < maxWorkers - 1) await new Promise((resolve) => setTimeout(resolve, 100));
182
+ }
183
+ return {
184
+ hasAvailableWorker,
185
+ render,
186
+ close
187
+ };
188
+ }
189
+ var ensureDir = async (filePath) => {
190
+ await fs.promises.mkdir(dirname(filePath), { recursive: true });
191
+ };
192
+ var access = async (path) => {
193
+ try {
194
+ await fs.promises.access(path);
195
+ return true;
196
+ } catch {
197
+ return false;
198
+ }
199
+ };
200
+ /** @public */ async function createSystem(opts, threadId) {
201
+ const createWriteStream = (filePath) => {
202
+ return fs.createWriteStream(filePath, { flags: "w" });
203
+ };
204
+ const NS_PER_SEC = 1e9;
205
+ const MS_PER_NS = 1e-6;
206
+ const createTimer = () => {
207
+ const start = process.hrtime();
208
+ return () => {
209
+ const diff = process.hrtime(start);
210
+ return (diff[0] * NS_PER_SEC + diff[1]) * MS_PER_NS;
211
+ };
212
+ };
213
+ const noop = () => {};
214
+ const createLogger = async () => {
215
+ const isQuiet = opts.log === "quiet";
216
+ const isDebug = opts.log === "debug";
217
+ if (threadId !== void 0) return {
218
+ debug: isDebug ? console.debug.bind(console, `[${threadId}]`) : noop,
219
+ error: console.error.bind(console, `[${threadId}]`),
220
+ info: isQuiet ? noop : console.info.bind(console, `[${threadId}]`)
221
+ };
222
+ return {
223
+ debug: isDebug ? console.debug.bind(console) : noop,
224
+ error: console.error.bind(console),
225
+ info: isQuiet ? noop : console.info.bind(console)
226
+ };
227
+ };
228
+ const outDir = normalizePath(opts.outDir);
229
+ const basenameLen = (opts.basePathname || "/").length;
230
+ const getRouteFilePath = (pathname, isHtml) => {
231
+ pathname = decodeURIComponent(pathname.slice(basenameLen));
232
+ if (isHtml) {
233
+ if (!pathname.endsWith(".html")) {
234
+ if (pathname.endsWith("/")) pathname += "index.html";
235
+ else pathname += "/index.html";
236
+ }
237
+ } else if (pathname.endsWith("/")) pathname = pathname.slice(0, -1);
238
+ return join(outDir, pathname);
239
+ };
240
+ const getLoaderFilePath = (pathname, loaderId, manifestHash) => {
241
+ pathname = decodeURIComponent(pathname.slice(basenameLen));
242
+ const suffix = getLoaderName(loaderId, manifestHash);
243
+ pathname = ensureSlash(pathname) + suffix;
244
+ return join(outDir, pathname);
245
+ };
246
+ const sys = {
247
+ createMainProcess: null,
248
+ createLogger,
249
+ getOptions: () => opts,
250
+ ensureDir,
251
+ createWriteStream,
252
+ createTimer,
253
+ access,
254
+ getRouteFilePath,
255
+ getLoaderFilePath,
256
+ getEnv: (key) => process.env[key],
257
+ platform: {
258
+ static: true,
259
+ node: process.versions.node
260
+ }
261
+ };
262
+ sys.createMainProcess = () => createWorkerPool(sys, opts);
263
+ return sys;
264
+ }
265
+ export { createSystem };
@@ -0,0 +1,59 @@
1
+ /** Common mime types mapped to Content-Type headers */ var MIME_TYPES = {
2
+ "3gp": "video/3gpp",
3
+ "3gpp": "video/3gpp",
4
+ asf: "video/x-ms-asf",
5
+ asx: "video/x-ms-asf",
6
+ avi: "video/x-msvideo",
7
+ avif: "image/avif",
8
+ bmp: "image/x-ms-bmp",
9
+ css: "text/css",
10
+ flv: "video/x-flv",
11
+ gif: "image/gif",
12
+ htm: "text/html",
13
+ html: "text/html",
14
+ ico: "image/x-icon",
15
+ jng: "image/x-jng",
16
+ jpeg: "image/jpeg",
17
+ jpg: "image/jpeg",
18
+ js: "application/javascript",
19
+ json: "application/json",
20
+ kar: "audio/midi",
21
+ m4a: "audio/x-m4a",
22
+ m4v: "video/x-m4v",
23
+ mid: "audio/midi",
24
+ midi: "audio/midi",
25
+ mng: "video/x-mng",
26
+ mov: "video/quicktime",
27
+ mp3: "audio/mpeg",
28
+ mp4: "video/mp4",
29
+ mpeg: "video/mpeg",
30
+ mpg: "video/mpeg",
31
+ ogg: "audio/ogg",
32
+ pdf: "application/pdf",
33
+ png: "image/png",
34
+ rar: "application/x-rar-compressed",
35
+ shtml: "text/html",
36
+ svg: "image/svg+xml",
37
+ svgz: "image/svg+xml",
38
+ tif: "image/tiff",
39
+ tiff: "image/tiff",
40
+ ts: "video/mp2t",
41
+ txt: "text/plain",
42
+ wbmp: "image/vnd.wap.wbmp",
43
+ webm: "video/webm",
44
+ webp: "image/webp",
45
+ wmv: "video/x-ms-wmv",
46
+ woff: "font/woff",
47
+ woff2: "font/woff2",
48
+ xml: "text/xml",
49
+ zip: "application/zip"
50
+ };
51
+ var LEADING_DOUBLE_SLASH_REG = /^[\\/]{2,}/;
52
+ function normalizeRequestUrl(url, base) {
53
+ const DOUBLE_SLASH_REG = /\/\/|\\\\/g;
54
+ const queryOrHashIndex = url.search(/[?#]/);
55
+ const path = queryOrHashIndex === -1 ? url : url.slice(0, queryOrHashIndex);
56
+ const suffix = queryOrHashIndex === -1 ? "" : url.slice(queryOrHashIndex);
57
+ return new URL(`${path.replace(LEADING_DOUBLE_SLASH_REG, "/").replace(DOUBLE_SLASH_REG, "/")}${suffix}`, base);
58
+ }
59
+ export { MIME_TYPES as n, normalizeRequestUrl as t };