@qwik.dev/router 2.0.0-beta.3 → 2.0.0-beta.31

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 (84) 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 +39 -44
  4. package/lib/adapters/bun-server/vite/index.d.ts +2 -2
  5. package/lib/adapters/bun-server/vite/index.mjs +6 -7
  6. package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
  7. package/lib/adapters/cloud-run/vite/index.mjs +6 -7
  8. package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
  9. package/lib/adapters/cloudflare-pages/vite/index.mjs +23 -32
  10. package/lib/adapters/deno-server/vite/index.d.ts +2 -2
  11. package/lib/adapters/deno-server/vite/index.mjs +13 -9
  12. package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
  13. package/lib/adapters/netlify-edge/vite/index.mjs +22 -36
  14. package/lib/adapters/node-server/vite/index.d.ts +2 -2
  15. package/lib/adapters/node-server/vite/index.mjs +6 -7
  16. package/lib/adapters/shared/vite/index.d.ts +7 -19
  17. package/lib/adapters/shared/vite/index.mjs +244 -233
  18. package/lib/adapters/ssg/vite/index.d.ts +13 -0
  19. package/lib/adapters/ssg/vite/index.mjs +17 -0
  20. package/lib/adapters/vercel-edge/vite/index.d.ts +3 -3
  21. package/lib/adapters/vercel-edge/vite/index.mjs +33 -19
  22. package/lib/chunks/deepFreeze.qwik.mjs +18 -0
  23. package/lib/chunks/error-handler.mjs +57 -0
  24. package/lib/chunks/fs.mjs +144 -0
  25. package/lib/chunks/http-error.qwik.mjs +35 -0
  26. package/lib/chunks/not-found-wrapper.qwik.mjs +25 -0
  27. package/lib/chunks/pathname.mjs +105 -0
  28. package/lib/chunks/redirect-handler.mjs +6 -0
  29. package/lib/chunks/routing.qwik.mjs +821 -0
  30. package/lib/chunks/system.mjs +333 -0
  31. package/lib/chunks/url.mjs +61 -0
  32. package/lib/chunks/use-functions.qwik.mjs +35 -0
  33. package/lib/chunks/worker-thread.qwik.mjs +2573 -0
  34. package/lib/index.d.ts +362 -142
  35. package/lib/index.qwik.mjs +949 -1244
  36. package/lib/middleware/aws-lambda/index.d.ts +0 -5
  37. package/lib/middleware/aws-lambda/index.mjs +14 -17
  38. package/lib/middleware/azure-swa/index.mjs +16 -221
  39. package/lib/middleware/bun/index.d.ts +11 -0
  40. package/lib/middleware/bun/index.mjs +50 -97
  41. package/lib/middleware/cloudflare-pages/index.mjs +22 -31
  42. package/lib/middleware/deno/index.d.ts +11 -0
  43. package/lib/middleware/deno/index.mjs +49 -97
  44. package/lib/middleware/firebase/index.mjs +6 -15
  45. package/lib/middleware/netlify-edge/index.mjs +22 -32
  46. package/lib/middleware/node/index.mjs +31 -105
  47. package/lib/middleware/request-handler/index.d.ts +163 -88
  48. package/lib/middleware/request-handler/index.mjs +1458 -1260
  49. package/lib/middleware/vercel-edge/index.mjs +27 -36
  50. package/lib/modules.d.ts +11 -16
  51. package/lib/service-worker/index.mjs +4 -0
  52. package/lib/{static → ssg}/index.d.ts +45 -13
  53. package/lib/ssg/index.mjs +336 -0
  54. package/lib/vite/index.d.ts +38 -10
  55. package/lib/vite/index.mjs +2067 -26841
  56. package/modules.d.ts +11 -16
  57. package/package.json +62 -67
  58. package/ssg.d.ts +2 -0
  59. package/static.d.ts +1 -1
  60. package/lib/adapters/azure-swa/vite/index.cjs +0 -96
  61. package/lib/adapters/bun-server/vite/index.cjs +0 -50
  62. package/lib/adapters/cloud-run/vite/index.cjs +0 -47
  63. package/lib/adapters/cloudflare-pages/vite/index.cjs +0 -115
  64. package/lib/adapters/deno-server/vite/index.cjs +0 -62
  65. package/lib/adapters/netlify-edge/vite/index.cjs +0 -129
  66. package/lib/adapters/node-server/vite/index.cjs +0 -50
  67. package/lib/adapters/shared/vite/index.cjs +0 -378
  68. package/lib/adapters/static/vite/index.cjs +0 -368
  69. package/lib/adapters/static/vite/index.d.ts +0 -10
  70. package/lib/adapters/static/vite/index.mjs +0 -331
  71. package/lib/adapters/vercel-edge/vite/index.cjs +0 -118
  72. package/lib/index.qwik.cjs +0 -1947
  73. package/lib/middleware/node/index.cjs +0 -314
  74. package/lib/middleware/request-handler/index.cjs +0 -1614
  75. package/lib/service-worker.cjs +0 -17
  76. package/lib/service-worker.mjs +0 -15
  77. package/lib/static/deno.mjs +0 -8
  78. package/lib/static/index.cjs +0 -67
  79. package/lib/static/index.mjs +0 -48
  80. package/lib/static/node.cjs +0 -1124
  81. package/lib/static/node.mjs +0 -1086
  82. package/lib/vite/index.cjs +0 -27445
  83. package/middleware/request-handler/generated/not-found-paths.ts +0 -7
  84. package/middleware/request-handler/generated/static-paths.ts +0 -35
@@ -0,0 +1,333 @@
1
+ import fs from 'node:fs';
2
+ import { isAbsolute, resolve, join, dirname } from 'node:path';
3
+ import { cpus } from 'node:os';
4
+ import { Worker } from 'node:worker_threads';
5
+ import { k as normalizePath } from './fs.mjs';
6
+
7
+ function ssgWorkerCompare(a, b) {
8
+ if (a.activeTasks < b.activeTasks) {
9
+ return -1;
10
+ }
11
+ if (a.activeTasks > b.activeTasks) {
12
+ return 1;
13
+ }
14
+ return a.totalTasks < b.totalTasks ? -1 : 1;
15
+ }
16
+ async function createWorkerPool(sys, opts) {
17
+ const log = await sys.createLogger();
18
+ const ssgWorkers = [];
19
+ const sitemapBuffer = [];
20
+ let sitemapStream = null;
21
+ opts = {
22
+ ...opts
23
+ };
24
+ let outDir = opts.outDir;
25
+ if (typeof outDir !== "string") {
26
+ throw new Error(`Missing "outDir" option`);
27
+ }
28
+ if (!isAbsolute(outDir)) {
29
+ throw new Error(`"outDir" must be an absolute file path, received: ${outDir}`);
30
+ }
31
+ outDir = normalizePath(outDir);
32
+ let maxWorkers = cpus().length;
33
+ if (typeof opts.maxWorkers === "number") {
34
+ maxWorkers = Math.max(1, Math.min(opts.maxWorkers, maxWorkers));
35
+ }
36
+ let maxTasksPerWorker = 20;
37
+ if (typeof opts.maxTasksPerWorker === "number") {
38
+ maxTasksPerWorker = Math.max(1, Math.min(opts.maxTasksPerWorker, 50));
39
+ }
40
+ let sitemapOutFile = opts.sitemapOutFile;
41
+ if (sitemapOutFile !== null) {
42
+ if (typeof sitemapOutFile !== "string") {
43
+ sitemapOutFile = "sitemap.xml";
44
+ }
45
+ if (!isAbsolute(sitemapOutFile)) {
46
+ sitemapOutFile = resolve(outDir, sitemapOutFile);
47
+ }
48
+ }
49
+ if (!opts.workerFilePath) {
50
+ throw new Error('Missing "workerFilePath" option for SSG worker creation');
51
+ }
52
+ const workerFilePath = typeof opts.workerFilePath === "string" && opts.workerFilePath.startsWith("file://") ? new URL(opts.workerFilePath) : opts.workerFilePath;
53
+ const { render: _r, qwikRouterConfig: _c, workerFilePath: _w, ...workerData } = opts;
54
+ const createWorker = () => {
55
+ let terminateResolve = null;
56
+ const mainTasks = /* @__PURE__ */ new Map();
57
+ let terminateTimeout = null;
58
+ const nodeWorker = new Worker(workerFilePath, {
59
+ workerData
60
+ });
61
+ nodeWorker.unref();
62
+ const ssgWorker = {
63
+ activeTasks: 0,
64
+ totalTasks: 0,
65
+ render: (staticRoute) => {
66
+ return new Promise((resolve2, reject) => {
67
+ try {
68
+ ssgWorker.activeTasks++;
69
+ ssgWorker.totalTasks++;
70
+ mainTasks.set(staticRoute.pathname, resolve2);
71
+ nodeWorker.postMessage(staticRoute);
72
+ } catch (e) {
73
+ ssgWorker.activeTasks--;
74
+ mainTasks.delete(staticRoute.pathname);
75
+ reject(e);
76
+ }
77
+ });
78
+ },
79
+ terminate: async () => {
80
+ mainTasks.clear();
81
+ const msg = {
82
+ type: "close"
83
+ };
84
+ await new Promise((resolve2) => {
85
+ terminateResolve = () => {
86
+ resolve2();
87
+ };
88
+ terminateTimeout = setTimeout(async () => {
89
+ terminateTimeout = null;
90
+ terminateResolve = null;
91
+ await nodeWorker.terminate();
92
+ resolve2();
93
+ }, 1e3);
94
+ nodeWorker.postMessage(msg);
95
+ });
96
+ if (terminateTimeout) {
97
+ clearTimeout(terminateTimeout);
98
+ terminateTimeout = null;
99
+ }
100
+ }
101
+ };
102
+ nodeWorker.on("message", (msg) => {
103
+ switch (msg.type) {
104
+ case "render": {
105
+ const mainTask = mainTasks.get(msg.pathname);
106
+ if (mainTask) {
107
+ mainTasks.delete(msg.pathname);
108
+ ssgWorker.activeTasks--;
109
+ mainTask(msg);
110
+ }
111
+ break;
112
+ }
113
+ case "close": {
114
+ if (terminateResolve) {
115
+ terminateResolve();
116
+ terminateResolve = null;
117
+ }
118
+ break;
119
+ }
120
+ }
121
+ });
122
+ nodeWorker.on("error", (e) => {
123
+ log.error(`worker error`, e);
124
+ });
125
+ nodeWorker.on("exit", (code) => {
126
+ log.debug(`worker exit code=${code}`);
127
+ if (terminateTimeout) {
128
+ clearTimeout(terminateTimeout);
129
+ terminateTimeout = null;
130
+ }
131
+ if (mainTasks.size > 0) {
132
+ for (const [pathname, resolve2] of mainTasks) {
133
+ ssgWorker.activeTasks--;
134
+ resolve2({
135
+ type: "render",
136
+ pathname,
137
+ url: "",
138
+ ok: false,
139
+ error: {
140
+ message: `Worker exited with code ${code}`,
141
+ stack: void 0
142
+ },
143
+ filePath: null,
144
+ contentType: null,
145
+ resourceType: null
146
+ });
147
+ }
148
+ mainTasks.clear();
149
+ }
150
+ if (terminateResolve) {
151
+ terminateResolve();
152
+ terminateResolve = null;
153
+ }
154
+ if (code !== 0) {
155
+ console.error(`worker exit ${code}`);
156
+ }
157
+ });
158
+ return ssgWorker;
159
+ };
160
+ const getNextWorker = () => ssgWorkers.sort(ssgWorkerCompare)[0];
161
+ const hasAvailableWorker = () => {
162
+ const ssgWorker = getNextWorker();
163
+ return ssgWorker.activeTasks < maxTasksPerWorker;
164
+ };
165
+ const render = async (ssgRoute) => {
166
+ const ssgWorker = getNextWorker();
167
+ const result = await ssgWorker.render(ssgRoute);
168
+ if (sitemapOutFile && result.ok && result.resourceType === "page") {
169
+ sitemapBuffer.push(`<url><loc>${result.url}</loc></url>`);
170
+ if (sitemapBuffer.length > 50) {
171
+ const siteMapUrls = sitemapBuffer.join("\n") + "\n";
172
+ sitemapBuffer.length = 0;
173
+ if (sitemapStream) {
174
+ sitemapStream.write(siteMapUrls);
175
+ }
176
+ }
177
+ }
178
+ return result;
179
+ };
180
+ const close = async () => {
181
+ const promises = [];
182
+ if (sitemapStream) {
183
+ sitemapBuffer.push(`</urlset>`);
184
+ sitemapStream.write(sitemapBuffer.join("\n"));
185
+ sitemapBuffer.length = 0;
186
+ await new Promise((resolve2, reject) => {
187
+ if (sitemapStream) {
188
+ sitemapStream.end((err) => {
189
+ if (err) {
190
+ reject(err);
191
+ } else {
192
+ resolve2();
193
+ }
194
+ });
195
+ } else {
196
+ resolve2();
197
+ }
198
+ });
199
+ sitemapStream = null;
200
+ }
201
+ for (const ssgWorker of ssgWorkers) {
202
+ try {
203
+ promises.push(ssgWorker.terminate());
204
+ } catch (e) {
205
+ console.error(e);
206
+ }
207
+ }
208
+ await Promise.all(promises);
209
+ ssgWorkers.length = 0;
210
+ if (process.platform === "win32") {
211
+ await new Promise((resolve2) => setTimeout(resolve2, 300));
212
+ }
213
+ };
214
+ if (sitemapOutFile) {
215
+ await sys.ensureDir(sitemapOutFile);
216
+ sitemapStream = fs.createWriteStream(sitemapOutFile, {
217
+ flags: "w"
218
+ });
219
+ sitemapStream.write(`<?xml version="1.0" encoding="UTF-8"?>
220
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
221
+ `);
222
+ }
223
+ log.debug(`creating ${maxWorkers} workers, ${maxTasksPerWorker} tasks each`);
224
+ for (let i = 0; i < maxWorkers; i++) {
225
+ ssgWorkers.push(createWorker());
226
+ if (process.platform === "win32" && i < maxWorkers - 1) {
227
+ await new Promise((resolve2) => setTimeout(resolve2, 100));
228
+ }
229
+ }
230
+ const mainCtx = {
231
+ hasAvailableWorker,
232
+ render,
233
+ close
234
+ };
235
+ return mainCtx;
236
+ }
237
+
238
+ const ensureDir = async (filePath) => {
239
+ await fs.promises.mkdir(dirname(filePath), {
240
+ recursive: true
241
+ });
242
+ };
243
+ const access = async (path) => {
244
+ try {
245
+ await fs.promises.access(path);
246
+ return true;
247
+ } catch {
248
+ return false;
249
+ }
250
+ };
251
+ async function createSystem(opts, threadId) {
252
+ const createWriteStream = (filePath) => {
253
+ return fs.createWriteStream(filePath, {
254
+ flags: "w"
255
+ });
256
+ };
257
+ const NS_PER_SEC = 1e9;
258
+ const MS_PER_NS = 1e-6;
259
+ const createTimer = () => {
260
+ const start = process.hrtime();
261
+ return () => {
262
+ const diff = process.hrtime(start);
263
+ return (diff[0] * NS_PER_SEC + diff[1]) * MS_PER_NS;
264
+ };
265
+ };
266
+ const noop = () => {
267
+ };
268
+ const createLogger = async () => {
269
+ const isQuiet = opts.log === "quiet";
270
+ const isDebug = opts.log === "debug";
271
+ if (threadId !== void 0) {
272
+ return {
273
+ debug: isDebug ? console.debug.bind(console, `[${threadId}]`) : noop,
274
+ error: console.error.bind(console, `[${threadId}]`),
275
+ info: isQuiet ? noop : console.info.bind(console, `[${threadId}]`)
276
+ };
277
+ }
278
+ return {
279
+ debug: isDebug ? console.debug.bind(console) : noop,
280
+ error: console.error.bind(console),
281
+ info: isQuiet ? noop : console.info.bind(console)
282
+ };
283
+ };
284
+ const outDir = normalizePath(opts.outDir);
285
+ const basePathname = opts.basePathname || "/";
286
+ const basenameLen = basePathname.length;
287
+ const getRouteFilePath = (pathname, isHtml) => {
288
+ pathname = decodeURIComponent(pathname.slice(basenameLen));
289
+ if (isHtml) {
290
+ if (!pathname.endsWith(".html")) {
291
+ if (pathname.endsWith("/")) {
292
+ pathname += "index.html";
293
+ } else {
294
+ pathname += "/index.html";
295
+ }
296
+ }
297
+ } else {
298
+ if (pathname.endsWith("/")) {
299
+ pathname = pathname.slice(0, -1);
300
+ }
301
+ }
302
+ return join(outDir, pathname);
303
+ };
304
+ const getDataFilePath = (pathname) => {
305
+ pathname = decodeURIComponent(pathname.slice(basenameLen));
306
+ if (pathname.endsWith("/")) {
307
+ pathname += "q-data.json";
308
+ } else {
309
+ pathname += "/q-data.json";
310
+ }
311
+ return join(outDir, pathname);
312
+ };
313
+ const sys = {
314
+ createMainProcess: null,
315
+ createLogger,
316
+ getOptions: () => opts,
317
+ ensureDir,
318
+ createWriteStream,
319
+ createTimer,
320
+ access,
321
+ getRouteFilePath,
322
+ getDataFilePath,
323
+ getEnv: (key) => process.env[key],
324
+ platform: {
325
+ static: true,
326
+ node: process.versions.node
327
+ }
328
+ };
329
+ sys.createMainProcess = () => createWorkerPool(sys, opts);
330
+ return sys;
331
+ }
332
+
333
+ export { access, createSystem, ensureDir };
@@ -0,0 +1,61 @@
1
+ const 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
+
52
+ const LEADING_DOUBLE_SLASH_REG = /^[\\/]{2,}/;
53
+ function normalizeRequestUrl(url, base) {
54
+ const DOUBLE_SLASH_REG = /\/\/|\\\\/g;
55
+ const queryOrHashIndex = url.search(/[?#]/);
56
+ const path = queryOrHashIndex === -1 ? url : url.slice(0, queryOrHashIndex);
57
+ const suffix = queryOrHashIndex === -1 ? "" : url.slice(queryOrHashIndex);
58
+ return new URL(`${path.replace(LEADING_DOUBLE_SLASH_REG, "/").replace(DOUBLE_SLASH_REG, "/")}${suffix}`, base);
59
+ }
60
+
61
+ export { MIME_TYPES as M, normalizeRequestUrl as n };
@@ -0,0 +1,35 @@
1
+ import { createContextId, useContext, implicit$FirstArg, useVisibleTaskQrl, inlinedQrl, _captures, noSerialize, useServerData } from '@qwik.dev/core';
2
+
3
+ const RouteStateContext = /* @__PURE__ */ createContextId("qr-s");
4
+ const ContentContext = /* @__PURE__ */ createContextId("qr-c");
5
+ const ContentInternalContext = /* @__PURE__ */ createContextId("qr-ic");
6
+ const DocumentHeadContext = /* @__PURE__ */ createContextId("qr-h");
7
+ const RouteLocationContext = /* @__PURE__ */ createContextId("qr-l");
8
+ const RouteNavigateContext = /* @__PURE__ */ createContextId("qr-n");
9
+ const RouteActionContext = /* @__PURE__ */ createContextId("qr-a");
10
+ const RoutePreventNavigateContext = /* @__PURE__ */ createContextId("qr-p");
11
+ const HttpStatusContext = /* @__PURE__ */ createContextId("qr-hs");
12
+
13
+ const useHttpStatus = () => useContext(HttpStatusContext).value;
14
+ const useContent = () => useContext(ContentContext);
15
+ const useDocumentHead = () => useContext(DocumentHeadContext);
16
+ const useLocation = () => useContext(RouteLocationContext);
17
+ const useNavigate = () => useContext(RouteNavigateContext);
18
+ const usePreventNavigateQrl = (fn) => {
19
+ if (!__EXPERIMENTAL__.preventNavigate) {
20
+ throw new Error('usePreventNavigate$ is experimental and must be enabled with `experimental: ["preventNavigate"]` in the `qwikVite` plugin.');
21
+ }
22
+ const registerPreventNav = useContext(RoutePreventNavigateContext);
23
+ useVisibleTaskQrl(/* @__PURE__ */ inlinedQrl(() => {
24
+ const fn2 = _captures[0], registerPreventNav2 = _captures[1];
25
+ return registerPreventNav2(fn2);
26
+ }, "usePreventNavigateQrl_useVisibleTask_BsYUaz9XhUs", [
27
+ fn,
28
+ registerPreventNav
29
+ ]));
30
+ };
31
+ const usePreventNavigate$ = implicit$FirstArg(usePreventNavigateQrl);
32
+ const useAction = () => useContext(RouteActionContext);
33
+ const useQwikRouterEnv = () => noSerialize(useServerData("qwikrouter"));
34
+
35
+ export { ContentContext as C, DocumentHeadContext as D, HttpStatusContext as H, RouteLocationContext as R, useLocation as a, useQwikRouterEnv as b, ContentInternalContext as c, RouteNavigateContext as d, RouteStateContext as e, RouteActionContext as f, RoutePreventNavigateContext as g, useAction as h, useDocumentHead as i, useContent as j, useHttpStatus as k, usePreventNavigate$ as l, usePreventNavigateQrl as m, useNavigate as u };