@qwik.dev/router 2.0.0-beta.43 → 2.0.0-beta.47
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/lib/adapters/azure-swa/vite/index.d.ts +2 -2
- package/lib/adapters/azure-swa/vite/index.mjs +2 -1
- package/lib/adapters/bun-server/vite/index.d.ts +2 -2
- package/lib/adapters/bun-server/vite/index.mjs +2 -1
- package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
- package/lib/adapters/cloud-run/vite/index.mjs +2 -1
- package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
- package/lib/adapters/cloudflare-pages/vite/index.mjs +2 -1
- package/lib/adapters/deno-server/vite/index.d.ts +2 -2
- package/lib/adapters/deno-server/vite/index.mjs +2 -1
- package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
- package/lib/adapters/netlify-edge/vite/index.mjs +2 -1
- package/lib/adapters/node-server/vite/index.d.ts +2 -2
- package/lib/adapters/node-server/vite/index.mjs +2 -1
- package/lib/adapters/shared/vite/index.d.ts +1 -1
- package/lib/adapters/shared/vite/index.mjs +36 -32
- package/lib/adapters/ssg/vite/index.d.ts +1 -1
- package/lib/adapters/ssg/vite/index.mjs +4 -2
- package/lib/adapters/vercel-edge/vite/index.d.ts +2 -2
- package/lib/adapters/vercel-edge/vite/index.mjs +18 -15
- package/lib/chunks/fs.mjs +28 -25
- package/lib/chunks/head.qwik.mjs +731 -448
- package/lib/chunks/http-error.qwik.mjs +8 -7
- package/lib/chunks/pathname.mjs +9 -8
- package/lib/chunks/request-path.mjs +8 -4
- package/lib/chunks/route-trie-key.mjs +10 -0
- package/lib/chunks/routes.mjs +14 -14
- package/lib/chunks/server-error.mjs +28 -6
- package/lib/chunks/{url.mjs → static-file.mjs} +12 -2
- package/lib/chunks/system.mjs +31 -25
- package/lib/chunks/user-response.mjs +455 -348
- package/lib/chunks/worker-thread.mjs +90 -88
- package/lib/index.d.ts +94 -63
- package/lib/index.qwik.mjs +615 -523
- package/lib/middleware/aws-lambda/index.mjs +6 -3
- package/lib/middleware/azure-swa/index.mjs +4 -2
- package/lib/middleware/bun/index.mjs +12 -12
- package/lib/middleware/cloudflare-pages/index.mjs +19 -4
- package/lib/middleware/deno/index.mjs +12 -12
- package/lib/middleware/firebase/index.mjs +4 -2
- package/lib/middleware/netlify-edge/index.mjs +4 -2
- package/lib/middleware/node/index.mjs +16 -15
- package/lib/middleware/request-handler/index.d.ts +102 -2
- package/lib/middleware/request-handler/index.mjs +30 -34
- package/lib/middleware/vercel-edge/index.mjs +4 -2
- package/lib/service-worker/index.mjs +2 -1
- package/lib/ssg/index.mjs +23 -18
- package/lib/vite/index.d.ts +1 -1
- package/lib/vite/index.mjs +669 -604
- package/package.json +5 -5
|
@@ -4,13 +4,14 @@ var _hf0 = (p0) => p0.status || 500;
|
|
|
4
4
|
var _hf0_str = "p0.status||500";
|
|
5
5
|
var _hf1 = (p0) => p0.message || "";
|
|
6
6
|
var _hf1_str = "p0.message||\"\"";
|
|
7
|
-
/** Cache error pages per status code so all 404s (or 500s) share one cache entry. */
|
|
7
|
+
/** Cache error pages per status code so all 404s (or 500s) share one cache entry. */
|
|
8
|
+
var cacheKey = (ev) => String(ev.status);
|
|
8
9
|
var COLOR_400 = "#006ce9";
|
|
9
10
|
var COLOR_500 = "#713fc2";
|
|
10
11
|
var DisplayHttpStatus = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(() => {
|
|
11
|
-
const
|
|
12
|
-
const width =
|
|
13
|
-
const color =
|
|
12
|
+
const httpStatus = useHttpStatus();
|
|
13
|
+
const width = httpStatus.message ? "600px" : "300px";
|
|
14
|
+
const color = httpStatus.status < 500 ? COLOR_400 : COLOR_500;
|
|
14
15
|
const style = `
|
|
15
16
|
body { color: ${color}; background-color: #fafafa; padding: 30px; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Roboto, sans-serif; }
|
|
16
17
|
p { max-width: ${width}; margin: 60px auto 30px auto; background: white; border-radius: 4px; box-shadow: 0px 0px 50px -20px ${color}; overflow: hidden; }
|
|
@@ -19,9 +20,9 @@ var DisplayHttpStatus = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(() =
|
|
|
19
20
|
`;
|
|
20
21
|
return /*#__PURE__*/ _jsxSorted("p", null, null, [
|
|
21
22
|
/*#__PURE__*/ _jsxSorted("style", { dangerouslySetInnerHTML: style }, null, null, 3, null),
|
|
22
|
-
/*#__PURE__*/ _jsxSorted("strong", null, null, _fnSignal(_hf0, [
|
|
23
|
+
/*#__PURE__*/ _jsxSorted("strong", null, null, _fnSignal(_hf0, [httpStatus], _hf0_str), 3, null),
|
|
23
24
|
" ",
|
|
24
|
-
/*#__PURE__*/ _jsxSorted("span", null, null, _fnSignal(_hf1, [
|
|
25
|
-
], 1, "
|
|
25
|
+
/*#__PURE__*/ _jsxSorted("span", null, null, _fnSignal(_hf1, [httpStatus], _hf1_str), 3, null)
|
|
26
|
+
], 1, "Ds_0");
|
|
26
27
|
}, "DisplayHttpStatus_component_PJf4K4PL7Oc"));
|
|
27
28
|
export { cacheKey, DisplayHttpStatus as default };
|
package/lib/chunks/pathname.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/** Ensures the pathname ends with a slash */
|
|
1
|
+
/** Ensures the pathname ends with a slash */
|
|
2
|
+
var ensureSlash = (pathname) => pathname.endsWith("/") ? pathname : pathname + "/";
|
|
2
3
|
function normalizePathname(pathname, basePathname) {
|
|
3
4
|
if (typeof pathname === "string") {
|
|
4
5
|
pathname = pathname.trim();
|
|
@@ -32,13 +33,6 @@ function getPathnameForDynamicRoute(originalPathname, paramNames, params) {
|
|
|
32
33
|
}
|
|
33
34
|
return pathname;
|
|
34
35
|
}
|
|
35
|
-
var PROTOCOLS = {
|
|
36
|
-
https: true,
|
|
37
|
-
http: true,
|
|
38
|
-
about: true,
|
|
39
|
-
javascript: true,
|
|
40
|
-
file: true
|
|
41
|
-
};
|
|
42
36
|
function isSameOriginUrl(url) {
|
|
43
37
|
if (typeof url === "string") {
|
|
44
38
|
url = url.trim();
|
|
@@ -54,4 +48,11 @@ function isSameOriginUrl(url) {
|
|
|
54
48
|
}
|
|
55
49
|
return false;
|
|
56
50
|
}
|
|
51
|
+
var PROTOCOLS = {
|
|
52
|
+
https: true,
|
|
53
|
+
http: true,
|
|
54
|
+
about: true,
|
|
55
|
+
javascript: true,
|
|
56
|
+
file: true
|
|
57
|
+
};
|
|
57
58
|
export { normalizePathname as i, getPathnameForDynamicRoute as n, isSameOriginUrl as r, ensureSlash as t };
|
|
@@ -3,14 +3,16 @@ var IsQLoader = "@isQLoader";
|
|
|
3
3
|
var IsQAction = "@isQAction";
|
|
4
4
|
var QLoaderId = "@loaderId";
|
|
5
5
|
var QActionId = "@actionId";
|
|
6
|
-
/** Matches the final `/q-loader-{loaderId}.{manifestHash}.json` path segment. */
|
|
6
|
+
/** Matches the final `/q-loader-{loaderId}.{manifestHash}.json` path segment. */
|
|
7
|
+
var LOADER_REGEX = /\/(q-loader-([^/.]+)\.([^/.]+)\.json)$/;
|
|
7
8
|
var getLoaderName = (loaderId, manifestHash) => `q-loader-${loaderId}.${manifestHash}.json`;
|
|
8
9
|
/**
|
|
9
10
|
* Recognize internal request types from the URL pathname.
|
|
10
11
|
*
|
|
11
12
|
* Returns the request type, how many characters to trim from the pathname, and any extracted data
|
|
12
13
|
* (e.g. loaderId for loader requests).
|
|
13
|
-
*/
|
|
14
|
+
*/
|
|
15
|
+
function recognizeRequest(pathname) {
|
|
14
16
|
if (pathname.length < 10) return null;
|
|
15
17
|
const loaderMatch = pathname.match(LOADER_REGEX);
|
|
16
18
|
if (loaderMatch) return {
|
|
@@ -23,12 +25,14 @@ var getLoaderName = (loaderId, manifestHash) => `q-loader-${loaderId}.${manifest
|
|
|
23
25
|
};
|
|
24
26
|
return null;
|
|
25
27
|
}
|
|
26
|
-
/** Trim a recognized internal URL suffix from a pathname, returning the clean route pathname. */
|
|
28
|
+
/** Trim a recognized internal URL suffix from a pathname, returning the clean route pathname. */
|
|
29
|
+
function trimRecognizedInternalPathname(pathname, recognized) {
|
|
27
30
|
let trimmed = pathname.slice(0, pathname.length - recognized.trimLength) || "/";
|
|
28
31
|
if (!globalThis.__NO_TRAILING_SLASH__ && !trimmed.endsWith("/")) trimmed = ensureSlash(trimmed);
|
|
29
32
|
return trimmed;
|
|
30
33
|
}
|
|
31
|
-
/** Trim any recognized internal URL suffix from a pathname, returning the clean route pathname. */
|
|
34
|
+
/** Trim any recognized internal URL suffix from a pathname, returning the clean route pathname. */
|
|
35
|
+
function trimInternalPathname(pathname) {
|
|
32
36
|
const recognized = recognizeRequest(pathname);
|
|
33
37
|
if (recognized) return trimRecognizedInternalPathname(pathname, recognized);
|
|
34
38
|
return pathname;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route trie metadata keys start with `_` (`_4`, `_W`, …), so static segments that start with `_`
|
|
3
|
+
* are stored with an extra `_` to keep the two apart.
|
|
4
|
+
*/
|
|
5
|
+
var escapeStaticTrieKey = (segment) => segment.startsWith("_") ? "_" + segment : segment;
|
|
6
|
+
/** The URL segment for a static trie key. */
|
|
7
|
+
var unescapeStaticTrieKey = (key) => key.startsWith("_") ? key.slice(1) : key;
|
|
8
|
+
/** Whether a trie key is a static segment rather than metadata. */
|
|
9
|
+
var isStaticTrieKey = (key) => !key.startsWith("_") || key.startsWith("__");
|
|
10
|
+
export { isStaticTrieKey as n, unescapeStaticTrieKey as r, escapeStaticTrieKey as t };
|
package/lib/chunks/routes.mjs
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
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
1
|
function createRouteTester(basePathname, includeRoutes, excludeRoutes) {
|
|
16
2
|
const includes = routesToRegExps(includeRoutes);
|
|
17
3
|
const excludes = routesToRegExps(excludeRoutes);
|
|
@@ -23,4 +9,18 @@ function createRouteTester(basePathname, includeRoutes, excludeRoutes) {
|
|
|
23
9
|
return false;
|
|
24
10
|
};
|
|
25
11
|
}
|
|
12
|
+
function routesToRegExps(routes) {
|
|
13
|
+
if (!Array.isArray(routes)) return [];
|
|
14
|
+
return routes.filter((r) => typeof r === "string").map(routeToRegExp);
|
|
15
|
+
}
|
|
16
|
+
function routeToRegExp(rule) {
|
|
17
|
+
let transformedRule;
|
|
18
|
+
if (rule === "/" || rule === "/*") transformedRule = rule;
|
|
19
|
+
else if (rule.endsWith("/*")) transformedRule = `${rule.substring(0, rule.length - 2)}(/*)?`;
|
|
20
|
+
else if (rule.endsWith("/")) transformedRule = `${rule.substring(0, rule.length - 1)}(/)?`;
|
|
21
|
+
else if (rule.endsWith("*")) transformedRule = rule;
|
|
22
|
+
else transformedRule = `${rule}(/)?`;
|
|
23
|
+
transformedRule = `^${transformedRule.replace(/\*/g, ".*")}$`;
|
|
24
|
+
return new RegExp(transformedRule);
|
|
25
|
+
}
|
|
26
26
|
export { createRouteTester as t };
|
|
@@ -1,16 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
|
|
1
|
+
import { _qwikSymbol } from "@qwik.dev/core/internal";
|
|
2
|
+
/**
|
|
3
|
+
* Makes `instanceof cls` also match instances made by another copy of the router, such as the one a
|
|
4
|
+
* Qwik library kept external on the server evaluates. Subclasses need their own call.
|
|
5
|
+
*/
|
|
6
|
+
var shareClassIdentity = (cls, name) => {
|
|
7
|
+
const tag = _qwikSymbol(`router.${name}`);
|
|
8
|
+
cls.prototype[tag] = true;
|
|
9
|
+
Object.defineProperty(cls, Symbol.hasInstance, { value(value) {
|
|
10
|
+
if (this !== cls) return Function.prototype[Symbol.hasInstance].call(this, value);
|
|
11
|
+
return value != null && typeof value === "object" && tag in value;
|
|
12
|
+
} });
|
|
13
|
+
};
|
|
14
|
+
/** @public */
|
|
15
|
+
var AbortMessage = class {};
|
|
16
|
+
shareClassIdentity(AbortMessage, "AbortMessage");
|
|
17
|
+
/** @public */
|
|
18
|
+
var RedirectMessage = class extends AbortMessage {};
|
|
19
|
+
shareClassIdentity(RedirectMessage, "RedirectMessage");
|
|
20
|
+
/** @public */
|
|
21
|
+
var ServerError = class extends Error {
|
|
4
22
|
status;
|
|
5
23
|
data;
|
|
6
24
|
constructor(status, data) {
|
|
7
|
-
super(typeof data === "string" ? data : void 0)
|
|
25
|
+
super(typeof data === "string" ? data : void 0);
|
|
26
|
+
this.status = status;
|
|
27
|
+
this.data = data;
|
|
8
28
|
}
|
|
9
29
|
};
|
|
30
|
+
shareClassIdentity(ServerError, "ServerError");
|
|
10
31
|
/**
|
|
11
32
|
* `ev.redirect()`, `ev.error()`, etc. return a control-flow signal meant to be thrown. Throw it for
|
|
12
33
|
* the user when they return it instead, so returning and throwing behave the same.
|
|
13
|
-
*/
|
|
34
|
+
*/
|
|
35
|
+
var throwIfControlFlowSignal = (value) => {
|
|
14
36
|
if (value instanceof AbortMessage || value instanceof ServerError) throw value;
|
|
15
37
|
};
|
|
16
|
-
export { RedirectMessage as i, throwIfControlFlowSignal as n, AbortMessage as r, ServerError as t };
|
|
38
|
+
export { shareClassIdentity as a, RedirectMessage as i, throwIfControlFlowSignal as n, AbortMessage as r, ServerError as t };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { t as ensureSlash } from "./pathname.mjs";
|
|
2
|
+
/** Common mime types mapped to Content-Type headers */
|
|
3
|
+
var MIME_TYPES = {
|
|
2
4
|
"3gp": "video/3gpp",
|
|
3
5
|
"3gpp": "video/3gpp",
|
|
4
6
|
asf: "video/x-ms-asf",
|
|
@@ -57,4 +59,12 @@ function normalizeRequestUrl(url, base) {
|
|
|
57
59
|
const suffix = queryOrHashIndex === -1 ? "" : url.slice(queryOrHashIndex);
|
|
58
60
|
return new URL(`${path.replace(LEADING_DOUBLE_SLASH_REG, "/").replace(DOUBLE_SLASH_REG, "/")}${suffix}`, base);
|
|
59
61
|
}
|
|
60
|
-
|
|
62
|
+
function getStaticFilePath(pathname) {
|
|
63
|
+
const basePathname = globalThis.__QWIK_ROUTER_BASE_PATHNAME__ || "/";
|
|
64
|
+
if (pathname === basePathname.slice(0, -1)) return "/index.html";
|
|
65
|
+
if (!pathname.startsWith(basePathname)) return;
|
|
66
|
+
const relativePathname = pathname.slice(basePathname.length - 1);
|
|
67
|
+
if (relativePathname.slice(relativePathname.lastIndexOf("/") + 1).includes(".")) return relativePathname;
|
|
68
|
+
return ensureSlash(relativePathname) + "index.html";
|
|
69
|
+
}
|
|
70
|
+
export { normalizeRequestUrl as n, MIME_TYPES as r, getStaticFilePath as t };
|
package/lib/chunks/system.mjs
CHANGED
|
@@ -5,11 +5,6 @@ import fs from "node:fs";
|
|
|
5
5
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
6
6
|
import { cpus } from "node:os";
|
|
7
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
8
|
async function createWorkerPool(sys, opts) {
|
|
14
9
|
const log = await sys.createLogger();
|
|
15
10
|
const ssgWorkers = [];
|
|
@@ -36,6 +31,10 @@ async function createWorkerPool(sys, opts) {
|
|
|
36
31
|
let terminateResolve = null;
|
|
37
32
|
const mainTasks = /* @__PURE__ */ new Map();
|
|
38
33
|
let terminateTimeout = null;
|
|
34
|
+
let markWorkerReady;
|
|
35
|
+
const workerReady = new Promise((resolve) => {
|
|
36
|
+
markWorkerReady = resolve;
|
|
37
|
+
});
|
|
39
38
|
const nodeWorker = new Worker(workerFilePath, { workerData });
|
|
40
39
|
nodeWorker.unref();
|
|
41
40
|
const ssgWorker = {
|
|
@@ -43,16 +42,14 @@ async function createWorkerPool(sys, opts) {
|
|
|
43
42
|
totalTasks: 0,
|
|
44
43
|
render: (staticRoute) => {
|
|
45
44
|
return new Promise((resolve, reject) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
nodeWorker.postMessage(staticRoute);
|
|
51
|
-
} catch (e) {
|
|
45
|
+
ssgWorker.activeTasks++;
|
|
46
|
+
ssgWorker.totalTasks++;
|
|
47
|
+
mainTasks.set(staticRoute.pathname, resolve);
|
|
48
|
+
workerReady.then(() => nodeWorker.postMessage(staticRoute)).catch((e) => {
|
|
52
49
|
ssgWorker.activeTasks--;
|
|
53
50
|
mainTasks.delete(staticRoute.pathname);
|
|
54
51
|
reject(e);
|
|
55
|
-
}
|
|
52
|
+
});
|
|
56
53
|
});
|
|
57
54
|
},
|
|
58
55
|
terminate: async () => {
|
|
@@ -68,7 +65,7 @@ async function createWorkerPool(sys, opts) {
|
|
|
68
65
|
await nodeWorker.terminate();
|
|
69
66
|
resolve();
|
|
70
67
|
}, 1e3);
|
|
71
|
-
nodeWorker.postMessage(msg);
|
|
68
|
+
workerReady.then(() => nodeWorker.postMessage(msg));
|
|
72
69
|
});
|
|
73
70
|
if (terminateTimeout) {
|
|
74
71
|
clearTimeout(terminateTimeout);
|
|
@@ -78,6 +75,9 @@ async function createWorkerPool(sys, opts) {
|
|
|
78
75
|
};
|
|
79
76
|
nodeWorker.on("message", (msg) => {
|
|
80
77
|
switch (msg.type) {
|
|
78
|
+
case "ready":
|
|
79
|
+
markWorkerReady();
|
|
80
|
+
break;
|
|
81
81
|
case "render": {
|
|
82
82
|
const mainTask = mainTasks.get(msg.pathname);
|
|
83
83
|
if (mainTask) {
|
|
@@ -186,18 +186,13 @@ async function createWorkerPool(sys, opts) {
|
|
|
186
186
|
close
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
} catch {
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
/** @public */ async function createSystem(opts, threadId) {
|
|
189
|
+
function ssgWorkerCompare(a, b) {
|
|
190
|
+
if (a.activeTasks < b.activeTasks) return -1;
|
|
191
|
+
if (a.activeTasks > b.activeTasks) return 1;
|
|
192
|
+
return a.totalTasks < b.totalTasks ? -1 : 1;
|
|
193
|
+
}
|
|
194
|
+
/** @public */
|
|
195
|
+
async function createSystem(opts, threadId) {
|
|
201
196
|
const createWriteStream = (filePath) => {
|
|
202
197
|
return fs.createWriteStream(filePath, { flags: "w" });
|
|
203
198
|
};
|
|
@@ -262,4 +257,15 @@ var access = async (path) => {
|
|
|
262
257
|
sys.createMainProcess = () => createWorkerPool(sys, opts);
|
|
263
258
|
return sys;
|
|
264
259
|
}
|
|
260
|
+
var ensureDir = async (filePath) => {
|
|
261
|
+
await fs.promises.mkdir(dirname(filePath), { recursive: true });
|
|
262
|
+
};
|
|
263
|
+
var access = async (path) => {
|
|
264
|
+
try {
|
|
265
|
+
await fs.promises.access(path);
|
|
266
|
+
return true;
|
|
267
|
+
} catch {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
};
|
|
265
271
|
export { createSystem };
|