@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
package/lib/chunks/head.qwik.mjs
CHANGED
|
@@ -1,21 +1,34 @@
|
|
|
1
1
|
import { t as ensureSlash } from "./pathname.mjs";
|
|
2
2
|
import { o as getLoaderName } from "./request-path.mjs";
|
|
3
3
|
import { i as RedirectMessage, n as throwIfControlFlowSignal, t as ServerError } from "./server-error.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import { SerializerSymbol, _UNINITIALIZED, _deserialize, _getAsyncLocalStorage,
|
|
4
|
+
import { r as unescapeStaticTrieKey, t as escapeStaticTrieKey } from "./route-trie-key.mjs";
|
|
5
|
+
import { _capturesObj, createComputedQrl, createContextId, implicit$FirstArg, inlinedQrl, isBrowser, isDev, isServer, untrack, useServerData, withLocale } from "@qwik.dev/core";
|
|
6
|
+
import { SerializerSymbol, _UNINITIALIZED, _deserialize, _getAsyncLocalStorage, _injectAsyncSignalValue, _markSignalAsExternallyOwned, _qwikSymbol, _registerSingleton, _resolveContextWithoutSequentialScope, _verifySerializable } from "@qwik.dev/core/internal";
|
|
7
7
|
import { isServer as isServer$1 } from "@qwik.dev/core/build";
|
|
8
|
-
|
|
9
|
-
if (isServer$1) {
|
|
8
|
+
var createRequestStore = () => {
|
|
10
9
|
const AsyncLocalStorage = _getAsyncLocalStorage();
|
|
11
|
-
if (AsyncLocalStorage)
|
|
12
|
-
|
|
13
|
-
}
|
|
10
|
+
if (AsyncLocalStorage) return new AsyncLocalStorage();
|
|
11
|
+
console.warn("\n=====================\n Qwik Router Warning:\n AsyncLocalStorage is not available, continuing without it.\n This impacts concurrent async server calls, where they lose access to the ServerRequestEv object.\n=====================\n\n");
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Shared with the router copy of a Qwik library kept external on the server, so its
|
|
15
|
+
* `getRequestEvent()` and `server$` see the request the app is serving.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
var _asyncRequestStore = isServer$1 ? _registerSingleton("routerRequestStore", createRequestStore) : void 0;
|
|
20
|
+
/** The request event's key for the config of the app serving it. */
|
|
21
|
+
var RequestEvRouterConfig = /*#__PURE__*/ _qwikSymbol("router.config");
|
|
22
|
+
/** The config of the app serving the current request, for a router copy that holds none. */
|
|
23
|
+
var getServingRouterConfig = () => _asyncRequestStore?.getStore()?.[RequestEvRouterConfig];
|
|
14
24
|
var QACTION_KEY = "qaction";
|
|
15
25
|
var QFN_KEY = "qfunc";
|
|
16
26
|
var QDATA_KEY = "qdata";
|
|
17
|
-
/** @public */
|
|
18
|
-
var
|
|
27
|
+
/** @public */
|
|
28
|
+
var Q_ROUTE = "q:route";
|
|
29
|
+
function DEFAULT_LOADERS_SERIALIZATION_STRATEGY() {
|
|
30
|
+
return globalThis.__DEFAULT_LOADERS_SERIALIZATION_STRATEGY__ || "never";
|
|
31
|
+
}
|
|
19
32
|
var RouteStateContext = /*#__PURE__*/ createContextId("qr-s");
|
|
20
33
|
var RouteLoaderCtxContext = /*#__PURE__*/ createContextId("qr-lc");
|
|
21
34
|
var ContentContext = /*#__PURE__*/ createContextId("qr-c");
|
|
@@ -26,28 +39,97 @@ var RouteNavigateContext = /*#__PURE__*/ createContextId("qr-n");
|
|
|
26
39
|
var RouteActionContext = /*#__PURE__*/ createContextId("qr-a");
|
|
27
40
|
var RoutePreventNavigateContext = /*#__PURE__*/ createContextId("qr-p");
|
|
28
41
|
var HttpStatusContext = /*#__PURE__*/ createContextId("qr-hs");
|
|
42
|
+
var holder = {};
|
|
43
|
+
/** The config this router copy holds, else the one of the app serving the current request. */
|
|
44
|
+
var findRouterConfig = () => holder.config ?? getServingRouterConfig();
|
|
45
|
+
/**
|
|
46
|
+
* Registers the app's route config with the router copy bundled into the app. The generated
|
|
47
|
+
* `@qwik-router-config` module calls this on the server; the client loads that module lazily
|
|
48
|
+
* instead, since it is a separate chunk.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
var _setRouterConfig = (config) => {
|
|
53
|
+
holder.config = config;
|
|
54
|
+
holder.ready = void 0;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* The app's route config: the route trie, server plugins and build options that the Qwik Router
|
|
58
|
+
* Vite plugin generated. Resolves once the config is loaded and its `server$` modules are
|
|
59
|
+
* registered. On the server, the router copy of a Qwik library kept external reads the config of
|
|
60
|
+
* the app serving the current request.
|
|
61
|
+
*
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
var getRouterConfig = () => {
|
|
65
|
+
const servingConfig = !holder.config && getServingRouterConfig();
|
|
66
|
+
if (servingConfig) return Promise.resolve(servingConfig);
|
|
67
|
+
if (!holder.ready) holder.ready = loadRouterConfig().catch((error) => {
|
|
68
|
+
holder.ready = void 0;
|
|
69
|
+
throw error;
|
|
70
|
+
});
|
|
71
|
+
return holder.ready;
|
|
72
|
+
};
|
|
73
|
+
var loadRouterConfig = async () => {
|
|
74
|
+
if (!holder.config) {
|
|
75
|
+
const configModule = await import("@qwik-router-config").catch((error) => {
|
|
76
|
+
throw isBrowser ? error : new Error("Qwik Router config not found. Import \"@qwik-router-config\" in the server entry that the Qwik Router Vite plugin builds.", { cause: error });
|
|
77
|
+
});
|
|
78
|
+
holder.config ??= configModule;
|
|
79
|
+
}
|
|
80
|
+
await holder.config.importEagerModules?.();
|
|
81
|
+
return holder.config;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* The route trie of the app, as generated by the Qwik Router Vite plugin.
|
|
85
|
+
*
|
|
86
|
+
* @public
|
|
87
|
+
*/
|
|
88
|
+
var getRoutes = async () => (await getRouterConfig()).routes;
|
|
89
|
+
/**
|
|
90
|
+
* The base pathname the app is served under, such as `/` or `/docs/`.
|
|
91
|
+
*
|
|
92
|
+
* @public
|
|
93
|
+
*/
|
|
94
|
+
var getBasePathname = () => findRouterConfig()?.basePathname ?? globalThis.__QWIK_ROUTER_BASE_PATHNAME__ ?? "/";
|
|
95
|
+
/**
|
|
96
|
+
* Whether the app's URLs end with a trailing slash.
|
|
97
|
+
*
|
|
98
|
+
* @public
|
|
99
|
+
*/
|
|
100
|
+
var getTrailingSlash = () => findRouterConfig()?.trailingSlash ?? !globalThis.__NO_TRAILING_SLASH__;
|
|
101
|
+
/** @internal */
|
|
102
|
+
var _getServiceWorkerUrl = () => findRouterConfig()?.serviceWorkerUrl;
|
|
29
103
|
/**
|
|
30
104
|
* Route loaders read data before the route rendering starts, based on the route being navigated to.
|
|
31
105
|
* They automatically update when the route changes on the client.
|
|
32
106
|
*
|
|
33
107
|
* They are represented by a ComputedSignal.
|
|
34
|
-
*/
|
|
108
|
+
*/
|
|
109
|
+
var REQUEST_ROUTE_LOADER_STATE = "@routeLoaderState";
|
|
35
110
|
var REQUEST_LOADER_PATHS_STORE = "@loaderPathsStore";
|
|
111
|
+
var REQUEST_LOADER_PARAMS_STORE = "@loaderParamsStore";
|
|
36
112
|
var REQUEST_ROUTE_LOADERS = "@routeLoaders";
|
|
37
113
|
var REQUEST_ROUTE_LOADER_PROMISES = "@routeLoaderPromises";
|
|
38
114
|
var REQUEST_ROUTE_LOADER_EVENTS = "@routeLoaderEvents";
|
|
39
115
|
var REQUEST_ROUTE_LOADER_ROOT_EVENT = "@routeLoaderRootEvent";
|
|
40
116
|
var ROUTE_LOADER_VALUE_PREFIX = "__qwik_route_loader_value__";
|
|
41
|
-
/** Header name sent by client to tell the server the actual page URL for loader requests. */
|
|
42
|
-
|
|
117
|
+
/** Header name sent by client to tell the server the actual page URL for loader requests. */
|
|
118
|
+
var FULLPATH_HEADER = "X-Qwik-fullpath";
|
|
119
|
+
/** Dev route hint that preserves the loader URL. */
|
|
120
|
+
var ROUTE_PATH_HEADER = "X-Qwik-route-path";
|
|
43
121
|
/**
|
|
44
122
|
* Per-navigation fetch dedupe: shares in-flight and completed fetches (hover prefetch → click nav)
|
|
45
123
|
* and prevents repeat hover fetches. Cleared after each navigation kicks off its loader fetches;
|
|
46
124
|
* across navigations the browser HTTP cache is the freshness authority.
|
|
47
|
-
*/
|
|
48
|
-
var
|
|
125
|
+
*/
|
|
126
|
+
var navFetchCache = /* @__PURE__ */ new Map();
|
|
127
|
+
var clearNavFetchCache = () => {
|
|
128
|
+
navFetchCache = /* @__PURE__ */ new Map();
|
|
129
|
+
};
|
|
49
130
|
var isRedirectStatus = (status) => status >= 300 && status < 400;
|
|
50
|
-
/** We don't have aborts when preloading so we just pretend we do */
|
|
131
|
+
/** We don't have aborts when preloading so we just pretend we do */
|
|
132
|
+
var wrapWithAbort = (promise, signal) => {
|
|
51
133
|
if (signal.aborted) return Promise.reject(signal.reason);
|
|
52
134
|
return new Promise((resolve, reject) => {
|
|
53
135
|
const abort = () => reject(signal.reason);
|
|
@@ -55,14 +137,79 @@ var isRedirectStatus = (status) => status >= 300 && status < 400;
|
|
|
55
137
|
promise.finally(() => signal.removeEventListener("abort", abort)).then(resolve, reject);
|
|
56
138
|
});
|
|
57
139
|
};
|
|
140
|
+
var clientRouteLoaders = /* @__PURE__ */ new WeakMap();
|
|
141
|
+
function getClientRouteLoaders(ctx, pageUrl) {
|
|
142
|
+
let client = clientRouteLoaders.get(ctx);
|
|
143
|
+
if (!client) {
|
|
144
|
+
const current = {
|
|
145
|
+
requests: /* @__PURE__ */ new Map(),
|
|
146
|
+
paths: { ...ctx.loaderPaths },
|
|
147
|
+
pageUrl: pageUrl || location.href
|
|
148
|
+
};
|
|
149
|
+
client = {
|
|
150
|
+
current,
|
|
151
|
+
committed: current
|
|
152
|
+
};
|
|
153
|
+
clientRouteLoaders.set(ctx, client);
|
|
154
|
+
}
|
|
155
|
+
return client;
|
|
156
|
+
}
|
|
157
|
+
function getLoaderRequest(ctx, state, id, hash1) {
|
|
158
|
+
return untrack(() => {
|
|
159
|
+
const client = getClientRouteLoaders(ctx);
|
|
160
|
+
const { requests, paths, pageUrl } = client.current;
|
|
161
|
+
let request = requests.get(state[id]);
|
|
162
|
+
if (!request) {
|
|
163
|
+
const path = paths[id] || paths[hash1];
|
|
164
|
+
request = {
|
|
165
|
+
routePath: path || new URL(pageUrl).pathname,
|
|
166
|
+
pageUrl,
|
|
167
|
+
active: client.navCount === void 0 || !!path,
|
|
168
|
+
hash: hash1
|
|
169
|
+
};
|
|
170
|
+
requests.set(state[id], request);
|
|
171
|
+
}
|
|
172
|
+
return request;
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function assertCurrentLoaderRequest(ctx, signal, request, abortSignal) {
|
|
176
|
+
abortSignal.throwIfAborted();
|
|
177
|
+
if (!request.active || clientRouteLoaders.get(ctx)?.current.requests.get(signal) !== request) throw new DOMException(isDev ? "Route loader navigation was superseded" : "", "AbortError");
|
|
178
|
+
}
|
|
58
179
|
var getRouteLoaderValueStateKey = (loaderId) => `${ROUTE_LOADER_VALUE_PREFIX}${loaderId}`;
|
|
180
|
+
var ServerRouteLoaderCapture = class {
|
|
181
|
+
hash;
|
|
182
|
+
qrl;
|
|
183
|
+
validators;
|
|
184
|
+
blockSSR;
|
|
185
|
+
requestEv;
|
|
186
|
+
constructor(hash2, qrl1, validators1, blockSSR1, requestEv1) {
|
|
187
|
+
this.hash = hash2;
|
|
188
|
+
this.qrl = qrl1;
|
|
189
|
+
this.validators = validators1;
|
|
190
|
+
this.blockSSR = blockSSR1;
|
|
191
|
+
this.requestEv = requestEv1;
|
|
192
|
+
}
|
|
193
|
+
load() {
|
|
194
|
+
const requestEv2 = this.requestEv;
|
|
195
|
+
if (!requestEv2) throw new Error("Unable to determine the current RequestEvent.");
|
|
196
|
+
const values = getRouteLoaderValues(requestEv2);
|
|
197
|
+
if (this.hash in values) return values[this.hash];
|
|
198
|
+
const ev = this.blockSSR ? requestEv2 : detachResponseFromEvent(requestEv2);
|
|
199
|
+
return loadRouteLoaderByQrl(this.hash, this.qrl, this.validators, ev);
|
|
200
|
+
}
|
|
201
|
+
[SerializerSymbol]() {
|
|
202
|
+
return this.hash;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
59
205
|
var isRequestEvent = (value) => !!value && typeof value === "object" && Object.prototype.hasOwnProperty.call(value, "sharedMap") && Object.prototype.hasOwnProperty.call(value, "cookie");
|
|
60
206
|
var isLoaderInternal = (value) => typeof value === "function" && value.__brand === "server_loader";
|
|
61
207
|
/**
|
|
62
208
|
* Fetch a single loader's raw JSON response from the server.
|
|
63
209
|
*
|
|
64
210
|
* URL pattern: `{basePath}{routePath}/q-loader-{loaderId}.{manifestHash}.json`
|
|
65
|
-
*/
|
|
211
|
+
*/
|
|
212
|
+
var fetchRouteLoaderData = async (loaderId, routePath, manifestHash, opts) => {
|
|
66
213
|
if (!routePath) return;
|
|
67
214
|
let resolvedPath = routePath;
|
|
68
215
|
const basePath = opts?.basePath ?? "/";
|
|
@@ -77,40 +224,120 @@ var isLoaderInternal = (value) => typeof value === "function" && value.__brand =
|
|
|
77
224
|
else if (isDev) headers[ROUTE_PATH_HEADER] = pageUrl.pathname;
|
|
78
225
|
}
|
|
79
226
|
const cacheKey = `${url}\n${headers["X-Qwik-fullpath"] ?? ""}`;
|
|
227
|
+
const cache = navFetchCache;
|
|
80
228
|
if (!opts?.ignoreCache) {
|
|
81
|
-
const entry =
|
|
229
|
+
const entry = cache.get(cacheKey);
|
|
82
230
|
if (entry) return opts?.signal ? wrapWithAbort(entry, opts.signal) : entry;
|
|
83
231
|
}
|
|
84
232
|
const request = async () => {
|
|
233
|
+
opts?.signal?.throwIfAborted();
|
|
85
234
|
const response = await fetch(url, {
|
|
86
235
|
signal: opts?.signal,
|
|
87
236
|
cache: opts?.ignoreCache ? "reload" : "default",
|
|
88
237
|
headers
|
|
89
238
|
});
|
|
239
|
+
opts?.signal?.throwIfAborted();
|
|
90
240
|
if (response.redirected) return { r: response.url };
|
|
91
241
|
if (isRedirectStatus(response.status)) {
|
|
92
242
|
const location1 = response.headers.get("Location");
|
|
93
243
|
if (location1) return { r: location1 };
|
|
94
244
|
}
|
|
95
245
|
if (!response.ok) return;
|
|
96
|
-
|
|
246
|
+
const raw = await response.text();
|
|
247
|
+
opts?.signal?.throwIfAborted();
|
|
248
|
+
return { raw };
|
|
97
249
|
};
|
|
98
250
|
if (opts?.ignoreCache) return request();
|
|
99
251
|
if (opts?.signal) return request().then((value) => {
|
|
100
|
-
|
|
252
|
+
opts.signal.throwIfAborted();
|
|
253
|
+
if (value !== void 0 && !cache.has(cacheKey)) cache.set(cacheKey, Promise.resolve(value));
|
|
101
254
|
return value;
|
|
102
255
|
});
|
|
103
256
|
const promise = request().then((value) => {
|
|
104
|
-
if (value === void 0)
|
|
257
|
+
if (value === void 0) cache.delete(cacheKey);
|
|
105
258
|
return value;
|
|
106
259
|
}, (err) => {
|
|
107
|
-
|
|
260
|
+
cache.delete(cacheKey);
|
|
108
261
|
throw err;
|
|
109
262
|
});
|
|
110
|
-
|
|
263
|
+
cache.set(cacheKey, promise);
|
|
111
264
|
return promise;
|
|
112
265
|
};
|
|
113
|
-
|
|
266
|
+
var createRouteLoaderSignal = (loader, routeLoaderCtx, state, requestEv3) => {
|
|
267
|
+
const id = loader.__id;
|
|
268
|
+
const stateValues = state;
|
|
269
|
+
const resumeValueKey = getRouteLoaderValueStateKey(id);
|
|
270
|
+
const capture = isServer ? new ServerRouteLoaderCapture(id, loader.__qrl, loader.__validators, loader.__blockSSR, requestEv3 ?? useServerData("qwikrouter")?.ev) : id;
|
|
271
|
+
const searchFilter = loader.__search;
|
|
272
|
+
const loaderHash = isDev ? loader.__qrl.getHash() : id;
|
|
273
|
+
const signal = createComputedQrl(/*#__PURE__*/ inlinedQrl(async (ctx) => {
|
|
274
|
+
let capture = _capturesObj._[0], id = _capturesObj._[1], lastFetch = _capturesObj._[2], loaderHash = _capturesObj._[3], resumeValueKey = _capturesObj._[4], routeLoaderCtx = _capturesObj._[5], searchFilter = _capturesObj._[6], state = _capturesObj._[7], stateValues = _capturesObj._[8];
|
|
275
|
+
if (!!ctx.info && typeof ctx.info === "object" && "__v" in ctx.info) {
|
|
276
|
+
const value = ctx.info.__v;
|
|
277
|
+
if (!isServer && resumeValueKey in stateValues) stateValues[resumeValueKey] = value;
|
|
278
|
+
lastFetch.raw = void 0;
|
|
279
|
+
return value;
|
|
280
|
+
}
|
|
281
|
+
if (isServer) return capture.load();
|
|
282
|
+
const request = getLoaderRequest(routeLoaderCtx, state, id, loaderHash);
|
|
283
|
+
if (!request.active) {
|
|
284
|
+
if (ctx.previous === void 0) return new Promise((_, reject) => {
|
|
285
|
+
ctx.abortSignal.throwIfAborted();
|
|
286
|
+
ctx.abortSignal.addEventListener("abort", () => reject(ctx.abortSignal.reason), { once: true });
|
|
287
|
+
});
|
|
288
|
+
return ctx.previous;
|
|
289
|
+
}
|
|
290
|
+
const pageUrl = new URL(request.pageUrl);
|
|
291
|
+
const mHash = untrack(() => routeLoaderCtx.manifestHash) || "dev";
|
|
292
|
+
const basePath = getBasePathname();
|
|
293
|
+
const needsResumeFetch = stateValues[resumeValueKey] === _UNINITIALIZED;
|
|
294
|
+
let fetchUrl = pageUrl;
|
|
295
|
+
if (searchFilter) {
|
|
296
|
+
fetchUrl = new URL(pageUrl.href);
|
|
297
|
+
fetchUrl.search = filterSearchParams(pageUrl.searchParams, searchFilter);
|
|
298
|
+
}
|
|
299
|
+
const result = await fetchRouteLoaderData(id, request.routePath, mHash, {
|
|
300
|
+
pageUrl: fetchUrl,
|
|
301
|
+
basePath,
|
|
302
|
+
ignoreCache: ctx.info === true,
|
|
303
|
+
signal: ctx.abortSignal
|
|
304
|
+
});
|
|
305
|
+
assertCurrentLoaderRequest(routeLoaderCtx, state[id], request, ctx.abortSignal);
|
|
306
|
+
if (!result) throw new Error(`Loader ${id} returned empty response`);
|
|
307
|
+
let response;
|
|
308
|
+
if (result.raw === void 0) response = result;
|
|
309
|
+
else {
|
|
310
|
+
if (result.raw === lastFetch.raw && ctx.previous !== void 0) return ctx.previous;
|
|
311
|
+
response = await _deserialize(result.raw);
|
|
312
|
+
if (!response) throw new Error(`Loader ${id} returned empty response`);
|
|
313
|
+
}
|
|
314
|
+
assertCurrentLoaderRequest(routeLoaderCtx, state[id], request, ctx.abortSignal);
|
|
315
|
+
if (response.r) {
|
|
316
|
+
const goto = routeLoaderCtx.goto;
|
|
317
|
+
if (goto) goto(response.r, { replaceState: true });
|
|
318
|
+
else location.href = response.r;
|
|
319
|
+
return ctx.previous;
|
|
320
|
+
}
|
|
321
|
+
if (response.e) throw response.e;
|
|
322
|
+
lastFetch.raw = result.raw;
|
|
323
|
+
if (needsResumeFetch) stateValues[resumeValueKey] = response.d;
|
|
324
|
+
return response.d;
|
|
325
|
+
}, "createRouteLoaderSignal_signal_createComputed_4s4ZDCYhDOA", [
|
|
326
|
+
capture,
|
|
327
|
+
id,
|
|
328
|
+
{},
|
|
329
|
+
loaderHash,
|
|
330
|
+
resumeValueKey,
|
|
331
|
+
routeLoaderCtx,
|
|
332
|
+
searchFilter,
|
|
333
|
+
state,
|
|
334
|
+
stateValues
|
|
335
|
+
]), { serializationStrategy: loader.__serializationStrategy });
|
|
336
|
+
_markSignalAsExternallyOwned(signal);
|
|
337
|
+
return signal;
|
|
338
|
+
};
|
|
339
|
+
/** Build a sorted, stable search string from only the allowed param names. */
|
|
340
|
+
var filterSearchParams = (params, allowed) => {
|
|
114
341
|
const filtered = new URLSearchParams();
|
|
115
342
|
for (let i = 0; i < allowed.length; i++) {
|
|
116
343
|
const name = allowed[i];
|
|
@@ -120,23 +347,23 @@ var isLoaderInternal = (value) => typeof value === "function" && value.__brand =
|
|
|
120
347
|
filtered.sort();
|
|
121
348
|
return filtered.toString() ? `?${filtered.toString()}` : "";
|
|
122
349
|
};
|
|
123
|
-
|
|
350
|
+
function getLoaderOptions(rest) {
|
|
124
351
|
let id;
|
|
125
|
-
let serializationStrategy = DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
|
|
352
|
+
let serializationStrategy = DEFAULT_LOADERS_SERIALIZATION_STRATEGY();
|
|
126
353
|
let cacheControl;
|
|
127
354
|
let eTag;
|
|
128
355
|
let cacheKey;
|
|
129
356
|
let search;
|
|
130
|
-
let
|
|
131
|
-
const
|
|
357
|
+
let blockSSR2 = true;
|
|
358
|
+
const validators2 = [];
|
|
132
359
|
if (rest.length === 1) {
|
|
133
360
|
const options = rest[0];
|
|
134
361
|
if (options && typeof options === "object") {
|
|
135
|
-
if ("validate" in options)
|
|
362
|
+
if ("validate" in options) validators2.push(options);
|
|
136
363
|
else {
|
|
137
364
|
if (options.id) id = options.id;
|
|
138
365
|
if (options.serializationStrategy) serializationStrategy = options.serializationStrategy;
|
|
139
|
-
if (options.validation)
|
|
366
|
+
if (options.validation) validators2.push(...options.validation);
|
|
140
367
|
if ("cacheControl" in options) cacheControl = options.cacheControl;
|
|
141
368
|
if ("eTag" in options) eTag = options.eTag;
|
|
142
369
|
if ("cacheKey" in options) cacheKey = options.cacheKey;
|
|
@@ -144,77 +371,84 @@ var getLoaderOptions = (rest) => {
|
|
|
144
371
|
else if (globalThis.__STRICT_LOADERS__) search = [];
|
|
145
372
|
if (options.blockSSR === false) {
|
|
146
373
|
if (!__EXPERIMENTAL__.blockSSR) throw new Error("`blockSSR: false` is an experimental feature and is not enabled. Please enable the feature flag by adding `experimental: [\"blockSSR\"]` to your qwikVite plugin options.");
|
|
147
|
-
|
|
374
|
+
blockSSR2 = false;
|
|
148
375
|
}
|
|
149
376
|
}
|
|
150
377
|
}
|
|
151
|
-
} else if (rest.length > 1)
|
|
378
|
+
} else if (rest.length > 1) validators2.push(...rest.filter(Boolean));
|
|
152
379
|
return {
|
|
153
380
|
id,
|
|
154
|
-
validators:
|
|
381
|
+
validators: validators2.reverse(),
|
|
155
382
|
serializationStrategy,
|
|
156
383
|
cacheControl,
|
|
157
384
|
eTag,
|
|
158
385
|
cacheKey,
|
|
159
386
|
search,
|
|
160
|
-
blockSSR
|
|
387
|
+
blockSSR: blockSSR2
|
|
161
388
|
};
|
|
162
|
-
}
|
|
389
|
+
}
|
|
163
390
|
/**
|
|
164
391
|
* Returns the current RequestEvent if possible. Only usable on the server, and only during request
|
|
165
392
|
* processing.
|
|
166
393
|
*
|
|
167
394
|
* @public
|
|
168
|
-
*/
|
|
395
|
+
*/
|
|
396
|
+
var getRequestEvent = (thisArg) => {
|
|
169
397
|
if (!isServer) throw new Error("getRequestEvent() can only be used on the server.");
|
|
170
|
-
return _asyncRequestStore?.getStore()
|
|
398
|
+
return _asyncRequestStore?.getStore() ?? (isRequestEvent(thisArg) ? thisArg : void 0);
|
|
171
399
|
};
|
|
172
400
|
var REQUEST_ROUTE_LOADER_VALUES = "@routeLoaderValues";
|
|
173
|
-
/** Get/create the record of pre-loaded loader values (used by middleware before component). */
|
|
174
|
-
|
|
401
|
+
/** Get/create the record of pre-loaded loader values (used by middleware before component). */
|
|
402
|
+
function getRouteLoaderValues(requestEv5) {
|
|
403
|
+
let values = requestEv5.sharedMap.get(REQUEST_ROUTE_LOADER_VALUES);
|
|
175
404
|
if (!values) {
|
|
176
405
|
values = {};
|
|
177
|
-
|
|
406
|
+
requestEv5.sharedMap.set(REQUEST_ROUTE_LOADER_VALUES, values);
|
|
178
407
|
}
|
|
179
408
|
return values;
|
|
180
409
|
}
|
|
181
|
-
function getRouteLoaderPromises(
|
|
182
|
-
let promises =
|
|
410
|
+
function getRouteLoaderPromises(requestEv6) {
|
|
411
|
+
let promises = requestEv6.sharedMap.get(REQUEST_ROUTE_LOADER_PROMISES);
|
|
183
412
|
if (!promises) {
|
|
184
413
|
promises = {};
|
|
185
|
-
|
|
414
|
+
requestEv6.sharedMap.set(REQUEST_ROUTE_LOADER_PROMISES, promises);
|
|
186
415
|
}
|
|
187
416
|
return promises;
|
|
188
417
|
}
|
|
189
|
-
/** Clear loader state before rendering a route-independent error boundary. */
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
418
|
+
/** Clear loader state before rendering a route-independent error boundary. */
|
|
419
|
+
function clearRouteLoaderData(requestEv7) {
|
|
420
|
+
requestEv7.sharedMap.delete(REQUEST_ROUTE_LOADER_STATE);
|
|
421
|
+
requestEv7.sharedMap.delete(REQUEST_ROUTE_LOADER_VALUES);
|
|
422
|
+
requestEv7.sharedMap.delete(REQUEST_ROUTE_LOADER_PROMISES);
|
|
423
|
+
requestEv7.sharedMap.delete(REQUEST_ROUTE_LOADER_EVENTS);
|
|
424
|
+
requestEv7.sharedMap.delete(REQUEST_ROUTE_LOADER_ROOT_EVENT);
|
|
425
|
+
requestEv7.sharedMap.delete(REQUEST_ROUTE_LOADERS);
|
|
196
426
|
}
|
|
197
|
-
/** Store the route loader internals on the request for SSG to read. */
|
|
198
|
-
|
|
427
|
+
/** Store the route loader internals on the request for SSG to read. */
|
|
428
|
+
function setRouteLoaders(requestEv8, loaders) {
|
|
429
|
+
requestEv8.sharedMap.set(REQUEST_ROUTE_LOADERS, loaders);
|
|
199
430
|
}
|
|
200
|
-
/** Get the route loader internals stored on the request. */
|
|
201
|
-
|
|
431
|
+
/** Get the route loader internals stored on the request. */
|
|
432
|
+
function getRouteLoaders(requestEv9) {
|
|
433
|
+
return requestEv9.sharedMap.get(REQUEST_ROUTE_LOADERS) ?? [];
|
|
202
434
|
}
|
|
203
|
-
function getRouteLoaderCtx(
|
|
204
|
-
let ctx =
|
|
435
|
+
function getRouteLoaderCtx(requestEv10) {
|
|
436
|
+
let ctx = requestEv10.sharedMap.get(REQUEST_LOADER_PATHS_STORE);
|
|
205
437
|
if (!ctx) {
|
|
206
438
|
ctx = { loaderPaths: {} };
|
|
207
|
-
|
|
439
|
+
requestEv10.sharedMap.set(REQUEST_LOADER_PATHS_STORE, ctx);
|
|
208
440
|
}
|
|
209
441
|
return ctx;
|
|
210
442
|
}
|
|
211
|
-
/**
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
443
|
+
/** Server-only loader ID → params matched at its loader path; never serialized to the client. */
|
|
444
|
+
function getRouteLoaderParams(requestEv11) {
|
|
445
|
+
let params = requestEv11.sharedMap.get(REQUEST_LOADER_PARAMS_STORE);
|
|
446
|
+
if (!params) {
|
|
447
|
+
params = {};
|
|
448
|
+
requestEv11.sharedMap.set(REQUEST_LOADER_PARAMS_STORE, params);
|
|
449
|
+
}
|
|
450
|
+
return params;
|
|
451
|
+
}
|
|
218
452
|
var getModuleRouteLoaders = (mods) => {
|
|
219
453
|
const routeLoaders = [];
|
|
220
454
|
const seen = /* @__PURE__ */ new Map();
|
|
@@ -238,22 +472,109 @@ var getModuleRouteLoaders = (mods) => {
|
|
|
238
472
|
};
|
|
239
473
|
/**
|
|
240
474
|
* Loader ids declared `cacheControl: 'immutable'`. Their data cannot change until a rebuild, so
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*/
|
|
475
|
+
* navigation skips them unless their request inputs change. Registered on every nav via
|
|
476
|
+
* ensureRouteLoaderSignal, so resumed signals are covered too.
|
|
477
|
+
*/
|
|
478
|
+
var immutableLoaderIds = /* @__PURE__ */ new Set();
|
|
244
479
|
var isImmutableLoader = (loaderId) => immutableLoaderIds.has(loaderId);
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
480
|
+
function abortRouteLoaderNavigation(ctx) {
|
|
481
|
+
for (const [signal, request] of clientRouteLoaders.get(ctx)?.current.requests ?? []) {
|
|
482
|
+
if (signal.untrackedPending) request.isAborted = true;
|
|
483
|
+
signal.abort();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/** Search-filtered loaders ignore changes to unlisted params. */
|
|
487
|
+
function hasSameListedSearch(previous, next, search) {
|
|
488
|
+
return !!search && previous.pathname === next.pathname && filterSearchParams(previous.searchParams, search) === filterSearchParams(next.searchParams, search);
|
|
489
|
+
}
|
|
490
|
+
function prepareRouteLoaders(mods, state, ctx, paths, pageUrl, previousUrl, navCount, forceIds, navigationKey) {
|
|
491
|
+
const client = getClientRouteLoaders(ctx, previousUrl.href);
|
|
492
|
+
if (navigationKey && client.navigationKey === navigationKey) return ensureRouteLoaderSignals(mods, state, ctx);
|
|
493
|
+
const previous = client.current;
|
|
494
|
+
if (client.navCount === void 0) {
|
|
495
|
+
for (const id in state) if (!id.startsWith(ROUTE_LOADER_VALUE_PREFIX)) getLoaderRequest(ctx, state, id, id);
|
|
496
|
+
}
|
|
497
|
+
client.navCount = navCount;
|
|
498
|
+
client.navigationKey = navigationKey;
|
|
499
|
+
const current = client.current = {
|
|
500
|
+
requests: /* @__PURE__ */ new Map(),
|
|
501
|
+
paths: { ...paths },
|
|
502
|
+
pageUrl: pageUrl.href
|
|
503
|
+
};
|
|
504
|
+
const loaders = ensureRouteLoaderSignals(mods, state, ctx);
|
|
505
|
+
const routeLoaders = /* @__PURE__ */ new Map();
|
|
506
|
+
for (const loader of loaders) {
|
|
507
|
+
routeLoaders.set(loader.__id, loader);
|
|
508
|
+
current.paths[loader.__id] ||= current.paths[loader.__qrl.getHash()] || pageUrl.pathname;
|
|
509
|
+
}
|
|
510
|
+
for (const id in state) {
|
|
511
|
+
if (id.startsWith(ROUTE_LOADER_VALUE_PREFIX)) continue;
|
|
512
|
+
const signal = state[id];
|
|
513
|
+
const old = previous.requests.get(signal);
|
|
514
|
+
const loader = routeLoaders.get(id);
|
|
515
|
+
const hash3 = loader?.__qrl.getHash() || old?.hash;
|
|
516
|
+
const routePath = current.paths[id] || hash3 && current.paths[hash3];
|
|
517
|
+
if (!routePath) {
|
|
518
|
+
if (old) current.requests.set(signal, {
|
|
519
|
+
...old,
|
|
520
|
+
active: false
|
|
521
|
+
});
|
|
522
|
+
signal.abort();
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
const keepRequest = old?.active && !old.isAborted && old.routePath === routePath && (old.pageUrl === pageUrl.href ? isImmutableLoader(id) : hasSameListedSearch(new URL(old.pageUrl), pageUrl, loader?.__search));
|
|
526
|
+
current.requests.set(signal, keepRequest ? old : {
|
|
527
|
+
routePath,
|
|
528
|
+
pageUrl: pageUrl.href,
|
|
529
|
+
active: true,
|
|
530
|
+
hash: hash3
|
|
531
|
+
});
|
|
532
|
+
ctx.loaderPaths[id] = routePath;
|
|
533
|
+
if (forceIds === null || forceIds?.some((value) => value === id || value === hash3)) signal.invalidate(true);
|
|
534
|
+
else if (old && !keepRequest) signal.invalidate();
|
|
535
|
+
}
|
|
536
|
+
return loaders;
|
|
537
|
+
}
|
|
538
|
+
function pruneRouteLoaders(state, ctx) {
|
|
539
|
+
const { requests } = clientRouteLoaders.get(ctx).current;
|
|
540
|
+
const paths = {};
|
|
541
|
+
for (const id in state) {
|
|
542
|
+
if (id.startsWith(ROUTE_LOADER_VALUE_PREFIX)) continue;
|
|
543
|
+
const signal = state[id];
|
|
544
|
+
const request = requests.get(signal);
|
|
545
|
+
if (request?.active) paths[id] = request.routePath;
|
|
546
|
+
else {
|
|
547
|
+
signal.$dispose();
|
|
548
|
+
requests.delete(signal);
|
|
549
|
+
delete state[id];
|
|
550
|
+
delete state[getRouteLoaderValueStateKey(id)];
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
ctx.loaderPaths = paths;
|
|
554
|
+
}
|
|
555
|
+
function commitRouteLoaders(state, ctx, navCount) {
|
|
556
|
+
const client = clientRouteLoaders.get(ctx);
|
|
557
|
+
if (!client || client.navCount !== navCount) return;
|
|
558
|
+
pruneRouteLoaders(state, ctx);
|
|
559
|
+
client.committed = client.current;
|
|
560
|
+
}
|
|
561
|
+
function restoreRouteLoaders(state, ctx, navCount) {
|
|
562
|
+
const client = clientRouteLoaders.get(ctx);
|
|
563
|
+
if (!client || client.navCount !== navCount) return;
|
|
564
|
+
client.navigationKey = void 0;
|
|
565
|
+
client.current = client.committed;
|
|
566
|
+
pruneRouteLoaders(state, ctx);
|
|
567
|
+
for (const signal of client.current.requests.keys()) signal.invalidate();
|
|
568
|
+
}
|
|
569
|
+
var ensureRouteLoaderSignal = (loader, state, routeLoaderCtx, requestEv12) => {
|
|
570
|
+
if (loader.__cacheControl === "immutable") immutableLoaderIds.add(loader.__id);
|
|
571
|
+
if (isServer && loader.__serializationStrategy === "never") state[getRouteLoaderValueStateKey(loader.__id)] = _UNINITIALIZED;
|
|
572
|
+
return state[loader.__id] ||= createRouteLoaderSignal(loader, routeLoaderCtx, state, requestEv12);
|
|
252
573
|
};
|
|
253
|
-
var
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
574
|
+
var ensureRouteLoaderSignals = (mods, state, routeLoaderCtx, requestEv13) => {
|
|
575
|
+
const loaders = getModuleRouteLoaders(mods);
|
|
576
|
+
for (let i = 0; i < loaders.length; i++) ensureRouteLoaderSignal(loaders[i], state, routeLoaderCtx, requestEv13);
|
|
577
|
+
return loaders;
|
|
257
578
|
};
|
|
258
579
|
/**
|
|
259
580
|
* Inject a pre-loaded value into a ComputedSignal while preserving subscriptions. Delegates to the
|
|
@@ -261,25 +582,56 @@ var applyClientRouteLoaderPath = (loaderId, ctx) => {
|
|
|
261
582
|
* synchronously and returns the pre-loaded value without fetching. Must go through the core helper
|
|
262
583
|
* because `$computeIfNeeded$` is mangled in core builds and not directly callable from this
|
|
263
584
|
* package.
|
|
264
|
-
*/
|
|
585
|
+
*/
|
|
586
|
+
var setLoaderSignalValue = (signal, value) => {
|
|
265
587
|
_injectAsyncSignalValue(signal, value);
|
|
266
588
|
};
|
|
589
|
+
var resolveRouteLoaderByHash = (routeLoaders, loaderId) => {
|
|
590
|
+
return routeLoaders.find((loader) => matchesRouteLoaderId(loader, loaderId));
|
|
591
|
+
};
|
|
267
592
|
var matchesRouteLoaderId = (loader, loaderId) => {
|
|
268
593
|
return typeof loaderId === "string" && (loader.__id === loaderId || isDev && loader.__qrl.getHash() === loaderId);
|
|
269
594
|
};
|
|
270
|
-
|
|
271
|
-
|
|
595
|
+
/** Run a loader and return its raw value. Errors/redirects propagate as exceptions. */
|
|
596
|
+
var getRouteLoaderData = async (loaderQrl, validators3, requestEv14) => {
|
|
597
|
+
const loaderRequestEv = requestEv14;
|
|
598
|
+
const result = await runValidators(requestEv14, validators3, void 0);
|
|
599
|
+
if (!result.success) return loaderRequestEv.fail(result.status ?? 500, result.error);
|
|
600
|
+
const resolved = await loaderQrl.call(loaderRequestEv, loaderRequestEv);
|
|
601
|
+
const value = typeof resolved === "function" ? resolved() : resolved;
|
|
602
|
+
throwIfControlFlowSignal(value);
|
|
603
|
+
if (isDev) verifySerializable(value, loaderQrl);
|
|
604
|
+
return value;
|
|
272
605
|
};
|
|
273
|
-
|
|
274
|
-
|
|
606
|
+
var loadRouteLoaderByQrl = (loaderId, loaderQrl, validators4, requestEv15) => {
|
|
607
|
+
const values = getRouteLoaderValues(requestEv15);
|
|
608
|
+
if (loaderId in values) return Promise.resolve(values[loaderId]);
|
|
609
|
+
const promises = getRouteLoaderPromises(requestEv15);
|
|
610
|
+
let promise = promises[loaderId];
|
|
611
|
+
if (!promise) {
|
|
612
|
+
promise = getRouteLoaderData(loaderQrl, validators4, requestEv15).then((value) => {
|
|
613
|
+
values[loaderId] = value;
|
|
614
|
+
return value;
|
|
615
|
+
}, (err) => {
|
|
616
|
+
delete promises[loaderId];
|
|
617
|
+
throw err;
|
|
618
|
+
});
|
|
619
|
+
promises[loaderId] = promise;
|
|
620
|
+
}
|
|
621
|
+
return promise;
|
|
622
|
+
};
|
|
623
|
+
/** @internal */
|
|
624
|
+
var getLoaderRequestEvent = (loader, requestEv16) => {
|
|
625
|
+
let rootRequestEv = requestEv16.sharedMap.get(REQUEST_ROUTE_LOADER_ROOT_EVENT);
|
|
275
626
|
if (!rootRequestEv) {
|
|
276
|
-
rootRequestEv =
|
|
277
|
-
|
|
627
|
+
rootRequestEv = requestEv16;
|
|
628
|
+
requestEv16.sharedMap.set(REQUEST_ROUTE_LOADER_ROOT_EVENT, rootRequestEv);
|
|
278
629
|
}
|
|
279
630
|
const url = new URL(rootRequestEv.url);
|
|
280
631
|
const pathname = globalThis.__STRICT_LOADERS__ ? getRouteLoaderCtx(rootRequestEv).loaderPaths[loader.__id] || rootRequestEv.url.pathname : rootRequestEv.url.pathname;
|
|
281
632
|
const filteredSearch = loader.__search ? filterSearchParams(url.searchParams, loader.__search) : rootRequestEv.url.search;
|
|
282
633
|
if (pathname === rootRequestEv.url.pathname && filteredSearch === rootRequestEv.url.search) return rootRequestEv;
|
|
634
|
+
const params = pathname === rootRequestEv.url.pathname ? rootRequestEv.params : getRouteLoaderParams(rootRequestEv)[loader.__id] || {};
|
|
283
635
|
let events = rootRequestEv.sharedMap.get(REQUEST_ROUTE_LOADER_EVENTS);
|
|
284
636
|
if (!events) {
|
|
285
637
|
events = /* @__PURE__ */ new Map();
|
|
@@ -297,7 +649,7 @@ var resolveRouteLoaderByHash = (routeLoaders, loaderId) => {
|
|
|
297
649
|
enumerable: true
|
|
298
650
|
},
|
|
299
651
|
params: {
|
|
300
|
-
value:
|
|
652
|
+
value: params,
|
|
301
653
|
enumerable: true
|
|
302
654
|
},
|
|
303
655
|
pathname: {
|
|
@@ -326,10 +678,11 @@ var resolveRouteLoaderByHash = (routeLoaders, loaderId) => {
|
|
|
326
678
|
* are captured locally, so a background (`blockSSR: false`) loader's status/redirect/error surfaces
|
|
327
679
|
* on its own signal instead of mutating the page response. The originals also call `check()`, which
|
|
328
680
|
* throws once SSR streaming has started — a background loader must fail on its signal, not crash.
|
|
329
|
-
*/
|
|
681
|
+
*/
|
|
682
|
+
var detachResponseFromEvent = (requestEv17) => {
|
|
330
683
|
let status = 200;
|
|
331
684
|
const headers = new Headers();
|
|
332
|
-
return Object.create(
|
|
685
|
+
return Object.create(requestEv17, {
|
|
333
686
|
headers: {
|
|
334
687
|
value: headers,
|
|
335
688
|
enumerable: true
|
|
@@ -372,174 +725,33 @@ var resolveRouteLoaderByHash = (routeLoaders, loaderId) => {
|
|
|
372
725
|
}
|
|
373
726
|
});
|
|
374
727
|
};
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
success: true,
|
|
378
|
-
data
|
|
379
|
-
};
|
|
380
|
-
if (validators) for (let i = 0; i < validators.length; i++) {
|
|
381
|
-
lastResult = await validators[i].validate(requestEv, data);
|
|
382
|
-
if (!lastResult.success) return lastResult;
|
|
383
|
-
data = lastResult.data;
|
|
384
|
-
}
|
|
385
|
-
return lastResult;
|
|
386
|
-
}
|
|
387
|
-
function verifySerializable(data, qrl) {
|
|
388
|
-
try {
|
|
389
|
-
_verifySerializable(data, void 0);
|
|
390
|
-
} catch (error) {
|
|
391
|
-
if (error instanceof Error && qrl.dev) error.loc = qrl.dev;
|
|
392
|
-
throw error;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
/** Run a loader and return its raw value. Errors/redirects propagate as exceptions. */ var getRouteLoaderData = async (loaderQrl, validators, requestEv) => {
|
|
396
|
-
const loaderRequestEv = requestEv;
|
|
397
|
-
const result = await runValidators(requestEv, validators, void 0);
|
|
398
|
-
if (!result.success) return loaderRequestEv.fail(result.status ?? 500, result.error);
|
|
399
|
-
const resolved = await loaderQrl.call(loaderRequestEv, loaderRequestEv);
|
|
400
|
-
const value = typeof resolved === "function" ? resolved() : resolved;
|
|
401
|
-
throwIfControlFlowSignal(value);
|
|
402
|
-
if (isDev) verifySerializable(value, loaderQrl);
|
|
403
|
-
return value;
|
|
404
|
-
};
|
|
405
|
-
var loadRouteLoaderByQrl = (loaderId, loaderQrl, validators, requestEv) => {
|
|
406
|
-
const values = getRouteLoaderValues(requestEv);
|
|
407
|
-
if (loaderId in values) return Promise.resolve(values[loaderId]);
|
|
408
|
-
const promises = getRouteLoaderPromises(requestEv);
|
|
409
|
-
let promise = promises[loaderId];
|
|
410
|
-
if (!promise) {
|
|
411
|
-
promise = getRouteLoaderData(loaderQrl, validators, requestEv).then((value) => {
|
|
412
|
-
values[loaderId] = value;
|
|
413
|
-
return value;
|
|
414
|
-
}, (err) => {
|
|
415
|
-
delete promises[loaderId];
|
|
416
|
-
throw err;
|
|
417
|
-
});
|
|
418
|
-
promises[loaderId] = promise;
|
|
419
|
-
}
|
|
420
|
-
return promise;
|
|
421
|
-
};
|
|
422
|
-
var ServerRouteLoaderCapture = class {
|
|
423
|
-
hash;
|
|
424
|
-
qrl;
|
|
425
|
-
validators;
|
|
426
|
-
blockSSR;
|
|
427
|
-
constructor(hash, qrl, validators, blockSSR) {
|
|
428
|
-
this.hash = hash;
|
|
429
|
-
this.qrl = qrl;
|
|
430
|
-
this.validators = validators;
|
|
431
|
-
this.blockSSR = blockSSR;
|
|
432
|
-
}
|
|
433
|
-
load() {
|
|
434
|
-
const requestEv = getRequestEvent();
|
|
435
|
-
if (!requestEv) throw new Error("Unable to determine the current RequestEvent.");
|
|
436
|
-
const values = getRouteLoaderValues(requestEv);
|
|
437
|
-
if (this.hash in values) return values[this.hash];
|
|
438
|
-
const ev = this.blockSSR ? requestEv : detachResponseFromEvent(requestEv);
|
|
439
|
-
return loadRouteLoaderByQrl(this.hash, this.qrl, this.validators, ev);
|
|
440
|
-
}
|
|
441
|
-
[SerializerSymbol]() {
|
|
442
|
-
return this.hash;
|
|
443
|
-
}
|
|
444
|
-
};
|
|
445
|
-
var createRouteLoaderSignal = (loader, routeLoaderCtx, state) => {
|
|
446
|
-
const id = loader.__id;
|
|
447
|
-
const stateValues = state;
|
|
448
|
-
const resumeValueKey = getRouteLoaderValueStateKey(id);
|
|
449
|
-
const capture = isServer ? new ServerRouteLoaderCapture(id, loader.__qrl, loader.__validators, loader.__blockSSR) : id;
|
|
450
|
-
const searchFilter = loader.__search;
|
|
451
|
-
const signal = createComputedQrl(/*#__PURE__*/ inlinedQrl(async (ctx) => {
|
|
452
|
-
const capture = _captures[0], id = _captures[1], lastFetch = _captures[2], resumeValueKey = _captures[3], routeLoaderCtx = _captures[4], searchFilter = _captures[5], stateValues = _captures[6];
|
|
453
|
-
const hasInjectedValue = !!ctx.info && typeof ctx.info === "object" && "__v" in ctx.info;
|
|
454
|
-
const trackedRoutePath = ctx.track(routeLoaderCtx.loaderPaths, id);
|
|
455
|
-
const trackedPagePathname = ctx.track(routeLoaderCtx, "pagePathname");
|
|
456
|
-
const trackedPageSearch = ctx.track(routeLoaderCtx, "pageSearch");
|
|
457
|
-
if (hasInjectedValue) {
|
|
458
|
-
const value = ctx.info.__v;
|
|
459
|
-
if (!isServer && resumeValueKey in stateValues) stateValues[resumeValueKey] = value;
|
|
460
|
-
lastFetch.raw = void 0;
|
|
461
|
-
return value;
|
|
462
|
-
}
|
|
463
|
-
if (isServer) return capture.load();
|
|
464
|
-
const pagePathname = trackedPagePathname || location.pathname;
|
|
465
|
-
const pageSearch = trackedPageSearch || location.search;
|
|
466
|
-
const pageUrl = new URL(pagePathname + pageSearch, location.href);
|
|
467
|
-
const mHash = routeLoaderCtx.manifestHash || "dev";
|
|
468
|
-
const basePath = qwikRouterConfig.basePathname ?? "/";
|
|
469
|
-
const needsResumeFetch = stateValues[resumeValueKey] === _UNINITIALIZED;
|
|
470
|
-
const fetchRoutePath = trackedRoutePath || (needsResumeFetch ? pageUrl.pathname : void 0);
|
|
471
|
-
if (!fetchRoutePath) return ctx.previous;
|
|
472
|
-
let fetchUrl = pageUrl;
|
|
473
|
-
if (searchFilter) {
|
|
474
|
-
fetchUrl = new URL(pageUrl.href);
|
|
475
|
-
fetchUrl.search = filterSearchParams(pageUrl.searchParams, searchFilter);
|
|
476
|
-
}
|
|
477
|
-
const result = await fetchRouteLoaderData(id, fetchRoutePath, mHash, {
|
|
478
|
-
pageUrl: fetchUrl,
|
|
479
|
-
basePath,
|
|
480
|
-
ignoreCache: ctx.info === true,
|
|
481
|
-
signal: ctx.abortSignal
|
|
482
|
-
});
|
|
483
|
-
if (!result) throw new Error(`Loader ${id} returned empty response`);
|
|
484
|
-
let response;
|
|
485
|
-
if (result.raw === void 0) response = result;
|
|
486
|
-
else {
|
|
487
|
-
if (result.raw === lastFetch.raw && ctx.previous !== void 0) return ctx.previous;
|
|
488
|
-
response = await _deserialize(result.raw);
|
|
489
|
-
if (!response) throw new Error(`Loader ${id} returned empty response`);
|
|
490
|
-
}
|
|
491
|
-
if (response.r) {
|
|
492
|
-
const goto = routeLoaderCtx.goto;
|
|
493
|
-
if (goto) goto(response.r, { replaceState: true });
|
|
494
|
-
else location.href = response.r;
|
|
495
|
-
return ctx.previous;
|
|
496
|
-
}
|
|
497
|
-
if (response.e) throw response.e;
|
|
498
|
-
lastFetch.raw = result.raw;
|
|
499
|
-
if (needsResumeFetch) stateValues[resumeValueKey] = response.d;
|
|
500
|
-
return response.d;
|
|
501
|
-
}, "createRouteLoaderSignal_signal_createComputed_4s4ZDCYhDOA", [
|
|
502
|
-
capture,
|
|
503
|
-
id,
|
|
504
|
-
{},
|
|
505
|
-
resumeValueKey,
|
|
506
|
-
routeLoaderCtx,
|
|
507
|
-
searchFilter,
|
|
508
|
-
stateValues
|
|
509
|
-
]), { serializationStrategy: loader.__serializationStrategy });
|
|
510
|
-
_markSignalAsExternallyOwned(signal);
|
|
511
|
-
return signal;
|
|
512
|
-
};
|
|
513
|
-
var ensureRouteLoaderSignal = (loader, state, routeLoaderCtx) => {
|
|
514
|
-
if (!isServer && routeLoaderCtx.pagePathname) applyClientRouteLoaderPath(loader.__id, routeLoaderCtx);
|
|
515
|
-
if (loader.__cacheControl === "immutable") immutableLoaderIds.add(loader.__id);
|
|
516
|
-
if (isServer && loader.__serializationStrategy === "never") state[getRouteLoaderValueStateKey(loader.__id)] = _UNINITIALIZED;
|
|
517
|
-
return state[loader.__id] ||= createRouteLoaderSignal(loader, routeLoaderCtx, state);
|
|
518
|
-
};
|
|
519
|
-
var ensureRouteLoaderSignals = (mods, state, routeLoaderCtx) => {
|
|
520
|
-
const loaders = getModuleRouteLoaders(mods);
|
|
521
|
-
for (let i = 0; i < loaders.length; i++) ensureRouteLoaderSignal(loaders[i], state, routeLoaderCtx);
|
|
522
|
-
return loaders;
|
|
523
|
-
};
|
|
524
|
-
var loadRouteLoader = (loader, requestEv) => {
|
|
525
|
-
const loaderEv = getLoaderRequestEvent(loader, requestEv);
|
|
728
|
+
var loadRouteLoader = (loader, requestEv18) => {
|
|
729
|
+
const loaderEv = getLoaderRequestEvent(loader, requestEv18);
|
|
526
730
|
return loadRouteLoaderByQrl(loader.__id, loader.__qrl, loader.__validators, loader.__blockSSR ? loaderEv : detachResponseFromEvent(loaderEv));
|
|
527
731
|
};
|
|
528
|
-
/** Run a loader and wrap the result in a LoaderResponse envelope. Catches redirects/errors. */
|
|
732
|
+
/** Run a loader and wrap the result in a LoaderResponse envelope. Catches redirects/errors. */
|
|
733
|
+
var getRouteLoaderResponse = async (loaderQrl, validators5, requestEv19) => {
|
|
529
734
|
try {
|
|
530
|
-
return { d: await getRouteLoaderData(loaderQrl,
|
|
735
|
+
return { d: await getRouteLoaderData(loaderQrl, validators5, requestEv19) };
|
|
531
736
|
} catch (err) {
|
|
532
737
|
if (err instanceof RedirectMessage) {
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
return { r:
|
|
738
|
+
const location2 = requestEv19.headers.get("Location") || "/";
|
|
739
|
+
requestEv19.headers.delete("Location");
|
|
740
|
+
return { r: location2 };
|
|
536
741
|
}
|
|
537
742
|
if (err instanceof ServerError) return { e: err };
|
|
538
743
|
throw err;
|
|
539
744
|
}
|
|
540
745
|
};
|
|
541
|
-
/**
|
|
542
|
-
|
|
746
|
+
/**
|
|
747
|
+
* A hoisted function declaration on purpose: the app's route modules call `routeLoaderQrl` at their
|
|
748
|
+
* own eval, and a bundle may execute them before this module, where a `const` binding would throw a
|
|
749
|
+
* TDZ ReferenceError.
|
|
750
|
+
*
|
|
751
|
+
* @internal
|
|
752
|
+
*/
|
|
753
|
+
function routeLoaderQrl(loaderQrl, ...rest) {
|
|
754
|
+
const { id, validators: validators6, serializationStrategy, cacheControl, eTag, cacheKey, search, blockSSR: blockSSR3 } = getLoaderOptions(rest);
|
|
543
755
|
function loader() {
|
|
544
756
|
const signal = ensureRouteLoaderSignal(loader, _resolveContextWithoutSequentialScope(RouteStateContext), _resolveContextWithoutSequentialScope(RouteLoaderCtxContext));
|
|
545
757
|
signal.promise();
|
|
@@ -547,17 +759,17 @@ var loadRouteLoader = (loader, requestEv) => {
|
|
|
547
759
|
}
|
|
548
760
|
loader.__brand = "server_loader";
|
|
549
761
|
loader.__qrl = loaderQrl;
|
|
550
|
-
loader.__validators =
|
|
762
|
+
loader.__validators = validators6;
|
|
551
763
|
loader.__id = id ?? loaderQrl.getHash();
|
|
552
764
|
loader.__serializationStrategy = serializationStrategy;
|
|
553
765
|
loader.__cacheControl = cacheControl;
|
|
554
766
|
loader.__eTag = eTag;
|
|
555
767
|
loader.__cacheKey = cacheKey;
|
|
556
768
|
loader.__search = search;
|
|
557
|
-
loader.__blockSSR =
|
|
769
|
+
loader.__blockSSR = blockSSR3;
|
|
558
770
|
Object.freeze(loader);
|
|
559
771
|
return loader;
|
|
560
|
-
}
|
|
772
|
+
}
|
|
561
773
|
/**
|
|
562
774
|
* Define a route loader that fetches data before the route renders.
|
|
563
775
|
*
|
|
@@ -584,7 +796,28 @@ var loadRouteLoader = (loader, requestEv) => {
|
|
|
584
796
|
* specify an explicit `search` option.
|
|
585
797
|
*
|
|
586
798
|
* @public
|
|
587
|
-
*/
|
|
799
|
+
*/
|
|
800
|
+
var routeLoader$ = /*#__PURE__*/ implicit$FirstArg(routeLoaderQrl);
|
|
801
|
+
async function runValidators(requestEv20, validators7, data) {
|
|
802
|
+
let lastResult = {
|
|
803
|
+
success: true,
|
|
804
|
+
data
|
|
805
|
+
};
|
|
806
|
+
if (validators7) for (let i = 0; i < validators7.length; i++) {
|
|
807
|
+
lastResult = await validators7[i].validate(requestEv20, data);
|
|
808
|
+
if (!lastResult.success) return lastResult;
|
|
809
|
+
data = lastResult.data;
|
|
810
|
+
}
|
|
811
|
+
return lastResult;
|
|
812
|
+
}
|
|
813
|
+
function verifySerializable(data, qrl2) {
|
|
814
|
+
try {
|
|
815
|
+
_verifySerializable(data, void 0);
|
|
816
|
+
} catch (error) {
|
|
817
|
+
if (error instanceof Error && qrl2.dev) error.loc = qrl2.dev;
|
|
818
|
+
throw error;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
588
821
|
var deepFreeze = (obj) => {
|
|
589
822
|
if (obj == null) return obj;
|
|
590
823
|
Object.getOwnPropertyNames(obj).forEach((prop) => {
|
|
@@ -597,52 +830,119 @@ var deepFreeze = (obj) => {
|
|
|
597
830
|
});
|
|
598
831
|
return Object.freeze(obj);
|
|
599
832
|
};
|
|
600
|
-
/** LoadRoute() runs in both client and server. */
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
833
|
+
/** LoadRoute() runs in both client and server. */
|
|
834
|
+
var MODULE_CACHE = /*#__PURE__*/ new WeakMap();
|
|
835
|
+
var loadRoute = async (routes, cacheModules, pathname) => {
|
|
836
|
+
const { loaders, params, routeParts, notFound, routeBundleNames, loaderPathsByHash, loaderParamsByHash, menuLoader, errorLoader } = matchRouteTree(routes, pathname);
|
|
837
|
+
const routeName = "/" + routeParts.join("/");
|
|
838
|
+
const modules = new Array(loaders.length);
|
|
839
|
+
const pendingLoads = [];
|
|
840
|
+
for (let i = 0; i < loaders.length; i++) {
|
|
841
|
+
const moduleLoader = loaders[i];
|
|
842
|
+
loadModule(moduleLoader, pendingLoads, (routeModule) => modules[i] = routeModule, cacheModules);
|
|
843
|
+
}
|
|
844
|
+
let menu = void 0;
|
|
845
|
+
loadModule(menuLoader, pendingLoads, (menuModule) => menu = menuModule?.default, cacheModules);
|
|
846
|
+
if (pendingLoads.length > 0) await Promise.all(pendingLoads);
|
|
847
|
+
return {
|
|
848
|
+
$routeName$: routeName,
|
|
849
|
+
$params$: params,
|
|
850
|
+
$mods$: modules,
|
|
851
|
+
$menu$: deepFreeze(menu),
|
|
852
|
+
$routeBundleNames$: routeBundleNames,
|
|
853
|
+
$notFound$: notFound,
|
|
854
|
+
$errorLoader$: errorLoader,
|
|
855
|
+
$loaders$: loaderPathsByHash && Object.keys(loaderPathsByHash),
|
|
856
|
+
$loaderPaths$: loaderPathsByHash,
|
|
857
|
+
$loaderParams$: loaderParamsByHash
|
|
858
|
+
};
|
|
859
|
+
};
|
|
860
|
+
/** Built-in fallback error component loader */
|
|
861
|
+
var httpErrorLoader = (() => import("./http-error.qwik.mjs"));
|
|
862
|
+
/** Collect the rewrite target's layouts, loader endpoint paths, and params at those paths. */
|
|
863
|
+
function walkTrieKeys(root, keys, params) {
|
|
606
864
|
let node = root;
|
|
865
|
+
let pathname = "/";
|
|
866
|
+
let pathParams = {};
|
|
607
867
|
const layouts = [];
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
let next = node[key];
|
|
612
|
-
if (!next && node._M) for (let j = 0; j < node._M.length; j++) {
|
|
613
|
-
const group = node._M[j];
|
|
614
|
-
next = group[key];
|
|
615
|
-
if (next) {
|
|
616
|
-
if (group._L) layouts.push(group._L);
|
|
617
|
-
break;
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
if (!next) return;
|
|
621
|
-
node = next;
|
|
868
|
+
const loaderPaths = {};
|
|
869
|
+
const loaderParams = {};
|
|
870
|
+
const collect = (node) => {
|
|
622
871
|
if (node._L) layouts.push(node._L);
|
|
872
|
+
for (const hash of node._R ?? []) {
|
|
873
|
+
loaderPaths[hash] = pathname;
|
|
874
|
+
loaderParams[hash] = pathParams;
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
collect(root);
|
|
878
|
+
for (const key of keys) {
|
|
879
|
+
const match = descendGroups(node, (candidate) => candidate[key]);
|
|
880
|
+
if (!match) return;
|
|
881
|
+
for (const group of match.groups) collect(group);
|
|
882
|
+
node = match.value;
|
|
883
|
+
const segment = node._P ? `${node._0 ?? ""}${params[node._P] ?? ""}${node._9 ?? ""}` : unescapeStaticTrieKey(key);
|
|
884
|
+
const segments = key === "_A" ? segment.split("/") : [segment];
|
|
885
|
+
pathname = ensureSlash(pathname + segments.map(encodeURIComponent).join("/"));
|
|
886
|
+
if (node._P) pathParams = {
|
|
887
|
+
...pathParams,
|
|
888
|
+
[node._P]: params[node._P] ?? ""
|
|
889
|
+
};
|
|
890
|
+
collect(node);
|
|
891
|
+
}
|
|
892
|
+
if (!node._I && node._G == null) {
|
|
893
|
+
const index = findIndexNode(node);
|
|
894
|
+
if (index) {
|
|
895
|
+
for (const group of index.groups) collect(group);
|
|
896
|
+
node = index.target;
|
|
897
|
+
collect(node);
|
|
898
|
+
}
|
|
623
899
|
}
|
|
624
900
|
return {
|
|
625
901
|
node,
|
|
626
|
-
layouts
|
|
902
|
+
layouts,
|
|
903
|
+
loaderPaths,
|
|
904
|
+
loaderParams
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
/** Resolve the page and its modules, following rewrite targets. */
|
|
908
|
+
function resolveLoaders(root, node, gatheredLayouts, params) {
|
|
909
|
+
if (node._G != null) {
|
|
910
|
+
const target = walkTrieKeys(root, node._G.split("/").filter((p) => p.length > 0), params);
|
|
911
|
+
if (!target) return;
|
|
912
|
+
const resolved = resolveLoaders(root, target.node, target.layouts, params);
|
|
913
|
+
if (resolved && !resolved.loaderPaths) {
|
|
914
|
+
resolved.loaderPaths = target.loaderPaths;
|
|
915
|
+
resolved.loaderParams = target.loaderParams;
|
|
916
|
+
}
|
|
917
|
+
return resolved;
|
|
918
|
+
}
|
|
919
|
+
const index = node._I;
|
|
920
|
+
if (!index) return;
|
|
921
|
+
if (Array.isArray(index)) return {
|
|
922
|
+
loaders: index,
|
|
923
|
+
node
|
|
924
|
+
};
|
|
925
|
+
return {
|
|
926
|
+
loaders: [...gatheredLayouts, index],
|
|
927
|
+
node
|
|
627
928
|
};
|
|
628
929
|
}
|
|
629
930
|
/**
|
|
630
931
|
* The full chain to render for a boundary: a bare loader in its snapshot layouts, an override
|
|
631
932
|
* as-is.
|
|
632
|
-
*/
|
|
933
|
+
*/
|
|
934
|
+
var boundaryChain = (ref) => ref.v ? Array.isArray(ref.v) ? ref.v : [...ref.layouts, ref.v] : void 0;
|
|
633
935
|
/**
|
|
634
936
|
* Collect layouts, the nearest error (`_E`) and not-found (`_4`) boundaries, and the menu from a
|
|
635
937
|
* node and the group ancestors entered to reach it.
|
|
636
|
-
*/
|
|
938
|
+
*/
|
|
939
|
+
function collectNodeMeta(node, groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderPathsByHash, matchedPathname = "/", loaderParamsByHash, matchedParams = {}) {
|
|
637
940
|
for (let j = 0; j < groups.length; j++) {
|
|
638
941
|
const g = groups[j];
|
|
639
942
|
if (g._L) layouts.push(g._L);
|
|
640
|
-
if (g._R &&
|
|
641
|
-
|
|
642
|
-
if (
|
|
643
|
-
const hash = g._R[i];
|
|
644
|
-
loaderPathsByHash[hash] = matchedPathname;
|
|
645
|
-
}
|
|
943
|
+
if (g._R && loaderPathsByHash) for (const hash of g._R) {
|
|
944
|
+
loaderPathsByHash[hash] = matchedPathname;
|
|
945
|
+
if (loaderParamsByHash) loaderParamsByHash[hash] = matchedParams;
|
|
646
946
|
}
|
|
647
947
|
if (g._E) {
|
|
648
948
|
errorLoaderRef.v = g._E;
|
|
@@ -655,12 +955,9 @@ var deepFreeze = (obj) => {
|
|
|
655
955
|
if (g._N) menuLoaderRef.v = g._N;
|
|
656
956
|
}
|
|
657
957
|
if (node._L) layouts.push(node._L);
|
|
658
|
-
if (node._R &&
|
|
659
|
-
|
|
660
|
-
if (
|
|
661
|
-
const hash = node._R[i];
|
|
662
|
-
loaderPathsByHash[hash] = matchedPathname;
|
|
663
|
-
}
|
|
958
|
+
if (node._R && loaderPathsByHash) for (const hash of node._R) {
|
|
959
|
+
loaderPathsByHash[hash] = matchedPathname;
|
|
960
|
+
if (loaderParamsByHash) loaderParamsByHash[hash] = matchedParams;
|
|
664
961
|
}
|
|
665
962
|
if (node._E) {
|
|
666
963
|
errorLoaderRef.v = node._E;
|
|
@@ -672,7 +969,45 @@ var deepFreeze = (obj) => {
|
|
|
672
969
|
}
|
|
673
970
|
if (node._N) menuLoaderRef.v = node._N;
|
|
674
971
|
}
|
|
675
|
-
|
|
972
|
+
var ChildMatchKind = /* @__PURE__ */ function(ChildMatchKind) {
|
|
973
|
+
ChildMatchKind[ChildMatchKind["Exact"] = 0] = "Exact";
|
|
974
|
+
ChildMatchKind[ChildMatchKind["Wildcard"] = 1] = "Wildcard";
|
|
975
|
+
ChildMatchKind[ChildMatchKind["Rest"] = 2] = "Rest";
|
|
976
|
+
return ChildMatchKind;
|
|
977
|
+
}(ChildMatchKind || {});
|
|
978
|
+
/**
|
|
979
|
+
* Try to find a child matching `partLower` in `node`, including inside group children (_M). Returns
|
|
980
|
+
* the matched child node, the groups entered to reach it, what to push to routeParts, and which
|
|
981
|
+
* kind of edge matched. Returns undefined if no match.
|
|
982
|
+
*
|
|
983
|
+
* Priority: exact match → _M groups (recursively) → _W wildcard → _A rest wildcard. This ensures
|
|
984
|
+
* exact matches inside nested groups take precedence over wildcards at parent level.
|
|
985
|
+
*/
|
|
986
|
+
function findChild(node, part, partLower, parts, partIndex) {
|
|
987
|
+
const exact = node[escapeStaticTrieKey(partLower)];
|
|
988
|
+
if (exact) return {
|
|
989
|
+
next: exact,
|
|
990
|
+
groups: [],
|
|
991
|
+
routePart: part,
|
|
992
|
+
done: false,
|
|
993
|
+
kind: ChildMatchKind.Exact
|
|
994
|
+
};
|
|
995
|
+
if (node._M) for (let j = 0; j < node._M.length; j++) {
|
|
996
|
+
const group = node._M[j];
|
|
997
|
+
const groupResult = findChild(group, part, partLower, parts, partIndex);
|
|
998
|
+
if (groupResult) {
|
|
999
|
+
groupResult.groups.unshift(group);
|
|
1000
|
+
return groupResult;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
const wildcard = tryWildcardMatch(node, part, partLower, parts, partIndex);
|
|
1004
|
+
if (wildcard) return {
|
|
1005
|
+
...wildcard,
|
|
1006
|
+
groups: []
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
/** Try to match a segment against a node's wildcard children (_W, _A). */
|
|
1010
|
+
function tryWildcardMatch(node, part, partLower, parts, partIndex) {
|
|
676
1011
|
let next = node._W;
|
|
677
1012
|
if (next) {
|
|
678
1013
|
const prefix = next._0;
|
|
@@ -687,7 +1022,7 @@ var deepFreeze = (obj) => {
|
|
|
687
1022
|
next,
|
|
688
1023
|
routePart: `${pre}[${paramName}]${suf}`,
|
|
689
1024
|
done: false,
|
|
690
|
-
kind:
|
|
1025
|
+
kind: ChildMatchKind.Wildcard,
|
|
691
1026
|
paramName,
|
|
692
1027
|
paramValue: value
|
|
693
1028
|
};
|
|
@@ -698,7 +1033,7 @@ var deepFreeze = (obj) => {
|
|
|
698
1033
|
next,
|
|
699
1034
|
routePart: `[${paramName}]`,
|
|
700
1035
|
done: false,
|
|
701
|
-
kind:
|
|
1036
|
+
kind: ChildMatchKind.Wildcard,
|
|
702
1037
|
paramName,
|
|
703
1038
|
paramValue: part
|
|
704
1039
|
};
|
|
@@ -712,47 +1047,18 @@ var deepFreeze = (obj) => {
|
|
|
712
1047
|
next,
|
|
713
1048
|
routePart: `[...${paramName}]`,
|
|
714
1049
|
done: true,
|
|
715
|
-
kind:
|
|
1050
|
+
kind: ChildMatchKind.Rest,
|
|
716
1051
|
paramName,
|
|
717
1052
|
paramValue: restValue
|
|
718
1053
|
};
|
|
719
1054
|
}
|
|
720
1055
|
}
|
|
721
1056
|
/**
|
|
722
|
-
* Try to find a child matching `partLower` in `node`, including inside group children (_M). Returns
|
|
723
|
-
* the matched child node, the groups entered to reach it, what to push to routeParts, and which
|
|
724
|
-
* kind of edge matched. Returns undefined if no match.
|
|
725
|
-
*
|
|
726
|
-
* Priority: exact match → _M groups (recursively) → _W wildcard → _A rest wildcard. This ensures
|
|
727
|
-
* exact matches inside nested groups take precedence over wildcards at parent level.
|
|
728
|
-
*/ function findChild(node, part, partLower, parts, partIndex) {
|
|
729
|
-
const exact = node[partLower];
|
|
730
|
-
if (exact) return {
|
|
731
|
-
next: exact,
|
|
732
|
-
groups: [],
|
|
733
|
-
routePart: part,
|
|
734
|
-
done: false,
|
|
735
|
-
kind: 0
|
|
736
|
-
};
|
|
737
|
-
if (node._M) for (let j = 0; j < node._M.length; j++) {
|
|
738
|
-
const group = node._M[j];
|
|
739
|
-
const groupResult = findChild(group, part, partLower, parts, partIndex);
|
|
740
|
-
if (groupResult) {
|
|
741
|
-
groupResult.groups.unshift(group);
|
|
742
|
-
return groupResult;
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
const wildcard = tryWildcardMatch(node, part, partLower, parts, partIndex);
|
|
746
|
-
if (wildcard) return {
|
|
747
|
-
...wildcard,
|
|
748
|
-
groups: []
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
|
-
/**
|
|
752
1057
|
* Descend through a node and its pathless `_M` groups (depth-first, in `_M` order), returning the
|
|
753
1058
|
* first node for which `hit` yields a value, plus the chain of groups entered to reach it. The
|
|
754
1059
|
* shared traversal behind the index / rest / boundary lookups inside groups.
|
|
755
|
-
*/
|
|
1060
|
+
*/
|
|
1061
|
+
function descendGroups(node, hit) {
|
|
756
1062
|
const value = hit(node);
|
|
757
1063
|
if (value !== void 0) return {
|
|
758
1064
|
value,
|
|
@@ -772,7 +1078,8 @@ var deepFreeze = (obj) => {
|
|
|
772
1078
|
* Find a node with `_I`/`_G` at the current level, including inside `_M` groups. Returns it and the
|
|
773
1079
|
* groups entered to reach it — excluding the target itself, whose `_L` the caller applies (so it
|
|
774
1080
|
* isn't double-counted).
|
|
775
|
-
*/
|
|
1081
|
+
*/
|
|
1082
|
+
function findIndexNode(node) {
|
|
776
1083
|
const r = descendGroups(node, (n) => n._I || n._G != null ? n : void 0);
|
|
777
1084
|
return r ? {
|
|
778
1085
|
target: r.node,
|
|
@@ -780,39 +1087,10 @@ var deepFreeze = (obj) => {
|
|
|
780
1087
|
} : void 0;
|
|
781
1088
|
}
|
|
782
1089
|
/**
|
|
783
|
-
* Given a matched node that has `_I` or `_G`, resolve the final loaders array.
|
|
784
|
-
*
|
|
785
|
-
* - `_G`: re-walk from root to gather target's layouts and `_I`
|
|
786
|
-
* - `_I` array: use as-is (override, e.g. layout stop)
|
|
787
|
-
* - `_I` function: prepend gathered layouts
|
|
788
|
-
*/ function resolveLoaders(root, node, gatheredLayouts) {
|
|
789
|
-
if (node._G != null) {
|
|
790
|
-
const target = walkTrieKeys(root, node._G.split("/").filter((p) => p.length > 0));
|
|
791
|
-
if (!target) return;
|
|
792
|
-
let targetNode = target.node;
|
|
793
|
-
const targetLayouts = target.layouts;
|
|
794
|
-
if (!targetNode._I && targetNode._G == null) {
|
|
795
|
-
const indexResult = findIndexNode(targetNode);
|
|
796
|
-
if (indexResult) {
|
|
797
|
-
for (let j = 0; j < indexResult.groups.length; j++) {
|
|
798
|
-
const g = indexResult.groups[j];
|
|
799
|
-
if (g._L) targetLayouts.push(g._L);
|
|
800
|
-
}
|
|
801
|
-
targetNode = indexResult.target;
|
|
802
|
-
if (targetNode._L) targetLayouts.push(targetNode._L);
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
return resolveLoaders(root, targetNode, targetLayouts);
|
|
806
|
-
}
|
|
807
|
-
const index = node._I;
|
|
808
|
-
if (!index) return;
|
|
809
|
-
if (Array.isArray(index)) return index;
|
|
810
|
-
return [...gatheredLayouts, index];
|
|
811
|
-
}
|
|
812
|
-
/**
|
|
813
1090
|
* Find a rest wildcard (`_A`) at the current node or inside its `_M` groups, with the groups
|
|
814
1091
|
* entered to reach it. Used to save fallback checkpoints during matching.
|
|
815
|
-
*/
|
|
1092
|
+
*/
|
|
1093
|
+
function findRestNode(node) {
|
|
816
1094
|
const r = descendGroups(node, (n) => n._A);
|
|
817
1095
|
return r ? {
|
|
818
1096
|
next: r.value,
|
|
@@ -822,7 +1100,8 @@ var deepFreeze = (obj) => {
|
|
|
822
1100
|
/**
|
|
823
1101
|
* Find a `_4`/`_E` boundary inside a node's pathless `_M` groups (first in `_M` order), wrapped in
|
|
824
1102
|
* those groups' layouts.
|
|
825
|
-
*/
|
|
1103
|
+
*/
|
|
1104
|
+
function findGroupBoundary(node, layouts, kind) {
|
|
826
1105
|
const r = descendGroups(node, (n) => n[kind]);
|
|
827
1106
|
if (!r) return;
|
|
828
1107
|
const groupLayouts = [...layouts];
|
|
@@ -841,13 +1120,14 @@ var deepFreeze = (obj) => {
|
|
|
841
1120
|
* Group nodes (in `_M` arrays) are pathless — they don't consume a URL segment but contribute their
|
|
842
1121
|
* `_L` layout to the chain. The matcher transparently enters groups when searching for a matching
|
|
843
1122
|
* child.
|
|
844
|
-
*/
|
|
1123
|
+
*/
|
|
1124
|
+
function matchRouteTree(root = {}, pathname) {
|
|
845
1125
|
let node = root;
|
|
846
1126
|
const params = {};
|
|
847
1127
|
const routeParts = [];
|
|
848
1128
|
const layouts = [];
|
|
849
|
-
const loaderHashes = [];
|
|
850
1129
|
const loaderPathsByHash = {};
|
|
1130
|
+
const loaderParamsByHash = {};
|
|
851
1131
|
const errorLoaderRef = {
|
|
852
1132
|
v: void 0,
|
|
853
1133
|
layouts: []
|
|
@@ -858,7 +1138,7 @@ var deepFreeze = (obj) => {
|
|
|
858
1138
|
};
|
|
859
1139
|
const menuLoaderRef = { v: void 0 };
|
|
860
1140
|
const groupNodes = [];
|
|
861
|
-
collectNodeMeta(root, [], layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef,
|
|
1141
|
+
collectNodeMeta(root, [], layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderPathsByHash, "/", loaderParamsByHash);
|
|
862
1142
|
if (root._M) groupNodes.push({
|
|
863
1143
|
node: root,
|
|
864
1144
|
depth: layouts.length
|
|
@@ -877,7 +1157,7 @@ var deepFreeze = (obj) => {
|
|
|
877
1157
|
matched = false;
|
|
878
1158
|
break;
|
|
879
1159
|
}
|
|
880
|
-
const restInfo = found.kind ===
|
|
1160
|
+
const restInfo = found.kind === ChildMatchKind.Wildcard ? findRestNode(node) : void 0;
|
|
881
1161
|
if (restInfo) restFallback = {
|
|
882
1162
|
aNode: restInfo.next,
|
|
883
1163
|
groups: restInfo.groups,
|
|
@@ -887,6 +1167,7 @@ var deepFreeze = (obj) => {
|
|
|
887
1167
|
params: { ...params },
|
|
888
1168
|
layouts: [...layouts],
|
|
889
1169
|
loaderPathsByHash: { ...loaderPathsByHash },
|
|
1170
|
+
loaderParamsByHash: { ...loaderParamsByHash },
|
|
890
1171
|
errorLoader: errorLoaderRef.v,
|
|
891
1172
|
errorLayouts: errorLoaderRef.layouts,
|
|
892
1173
|
notFoundLoader: notFoundLoaderRef.v,
|
|
@@ -898,7 +1179,7 @@ var deepFreeze = (obj) => {
|
|
|
898
1179
|
done = found.done;
|
|
899
1180
|
node = found.next;
|
|
900
1181
|
const matchedPathname = `/${parts.slice(0, found.done ? len : i + 1).join("/")}/`;
|
|
901
|
-
collectNodeMeta(node, found.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef,
|
|
1182
|
+
collectNodeMeta(node, found.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderPathsByHash, matchedPathname, loaderParamsByHash, { ...params });
|
|
902
1183
|
if (node._M) groupNodes.push({
|
|
903
1184
|
node,
|
|
904
1185
|
depth: layouts.length
|
|
@@ -908,7 +1189,7 @@ var deepFreeze = (obj) => {
|
|
|
908
1189
|
if (!node._I && node._G == null) {
|
|
909
1190
|
const indexResult = findIndexNode(node);
|
|
910
1191
|
if (indexResult) {
|
|
911
|
-
collectNodeMeta(indexResult.target, indexResult.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef,
|
|
1192
|
+
collectNodeMeta(indexResult.target, indexResult.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderPathsByHash, pathname, loaderParamsByHash, { ...params });
|
|
912
1193
|
node = indexResult.target;
|
|
913
1194
|
}
|
|
914
1195
|
}
|
|
@@ -919,12 +1200,13 @@ var deepFreeze = (obj) => {
|
|
|
919
1200
|
const paramName = next._P;
|
|
920
1201
|
params[paramName] = "";
|
|
921
1202
|
routeParts.push(`[...${paramName}]`);
|
|
922
|
-
collectNodeMeta(next, restInfo.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef,
|
|
1203
|
+
collectNodeMeta(next, restInfo.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderPathsByHash, pathname, loaderParamsByHash, { ...params });
|
|
923
1204
|
node = next;
|
|
924
1205
|
}
|
|
925
1206
|
}
|
|
926
1207
|
}
|
|
927
|
-
const
|
|
1208
|
+
const resolved = matched && (done || i >= len) ? resolveLoaders(root, node, layouts, params) : void 0;
|
|
1209
|
+
const loaders = resolved?.loaders;
|
|
928
1210
|
if (!loaders && restFallback) {
|
|
929
1211
|
const fb = restFallback;
|
|
930
1212
|
const fbParams = {
|
|
@@ -934,6 +1216,7 @@ var deepFreeze = (obj) => {
|
|
|
934
1216
|
const fbRouteParts = [...fb.routeParts, `[...${fb.paramName}]`];
|
|
935
1217
|
const fbLayouts = [...fb.layouts];
|
|
936
1218
|
const fbLoaderPathsByHash = { ...fb.loaderPathsByHash };
|
|
1219
|
+
const fbLoaderParamsByHash = { ...fb.loaderParamsByHash };
|
|
937
1220
|
const fbErrorRef = {
|
|
938
1221
|
v: fb.errorLoader,
|
|
939
1222
|
layouts: fb.errorLayouts
|
|
@@ -943,20 +1226,22 @@ var deepFreeze = (obj) => {
|
|
|
943
1226
|
layouts: fb.notFoundLayouts
|
|
944
1227
|
};
|
|
945
1228
|
const fbMenuRef = { v: fb.menuLoader };
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1229
|
+
collectNodeMeta(fb.aNode, fb.groups, fbLayouts, fbErrorRef, fbNotFoundRef, fbMenuRef, fbLoaderPathsByHash, pathname, fbLoaderParamsByHash, fbParams);
|
|
1230
|
+
const fallback = resolveLoaders(root, fb.aNode, fbLayouts, fbParams);
|
|
1231
|
+
if (fallback) {
|
|
1232
|
+
collectPageLoaders(fallback, fbLoaderPathsByHash, fbLoaderParamsByHash, pathname, fbParams);
|
|
1233
|
+
return {
|
|
1234
|
+
loaders: fallback.loaders,
|
|
1235
|
+
params: fbParams,
|
|
1236
|
+
routeParts: fbRouteParts,
|
|
1237
|
+
notFound: false,
|
|
1238
|
+
routeBundleNames: fb.aNode._B,
|
|
1239
|
+
loaderPathsByHash: Object.keys(fbLoaderPathsByHash).length > 0 ? fbLoaderPathsByHash : void 0,
|
|
1240
|
+
loaderParamsByHash: Object.keys(fbLoaderParamsByHash).length > 0 ? fbLoaderParamsByHash : void 0,
|
|
1241
|
+
menuLoader: fbMenuRef.v,
|
|
1242
|
+
errorLoader: boundaryChain(fbErrorRef)
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
960
1245
|
errorLoaderRef.v = fbErrorRef.v;
|
|
961
1246
|
errorLoaderRef.layouts = fbErrorRef.layouts;
|
|
962
1247
|
notFoundLoaderRef.v = fbNotFoundRef.v;
|
|
@@ -993,28 +1278,21 @@ var deepFreeze = (obj) => {
|
|
|
993
1278
|
routeParts,
|
|
994
1279
|
notFound: true,
|
|
995
1280
|
routeBundleNames: void 0,
|
|
996
|
-
loaderHashes: void 0,
|
|
997
1281
|
loaderPathsByHash: void 0,
|
|
1282
|
+
loaderParamsByHash: void 0,
|
|
998
1283
|
menuLoader: menuLoaderRef.v,
|
|
999
1284
|
errorLoader: boundaryChain(errorLoaderRef)
|
|
1000
1285
|
};
|
|
1001
1286
|
}
|
|
1002
|
-
|
|
1003
|
-
loaderHashes.push(...node._R);
|
|
1004
|
-
const matchedPathname = ensureSlash(pathname);
|
|
1005
|
-
for (let i = 0; i < node._R.length; i++) {
|
|
1006
|
-
const hash = node._R[i];
|
|
1007
|
-
loaderPathsByHash[hash] = matchedPathname;
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1287
|
+
collectPageLoaders(resolved, loaderPathsByHash, loaderParamsByHash, pathname, params);
|
|
1010
1288
|
return {
|
|
1011
1289
|
loaders,
|
|
1012
1290
|
params,
|
|
1013
1291
|
routeParts,
|
|
1014
1292
|
notFound: false,
|
|
1015
1293
|
routeBundleNames: node._B,
|
|
1016
|
-
loaderHashes: loaderHashes.length > 0 ? loaderHashes : void 0,
|
|
1017
1294
|
loaderPathsByHash: Object.keys(loaderPathsByHash).length > 0 ? loaderPathsByHash : void 0,
|
|
1295
|
+
loaderParamsByHash: Object.keys(loaderParamsByHash).length > 0 ? loaderParamsByHash : void 0,
|
|
1018
1296
|
menuLoader: menuLoaderRef.v,
|
|
1019
1297
|
errorLoader: boundaryChain(errorLoaderRef)
|
|
1020
1298
|
};
|
|
@@ -1033,39 +1311,42 @@ var loadModule = (moduleLoader, pendingLoads, moduleSetter, cacheModules) => {
|
|
|
1033
1311
|
}
|
|
1034
1312
|
}
|
|
1035
1313
|
};
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1314
|
+
function collectPageLoaders({ node, loaderPaths, loaderParams }, paths, pathParams, pathname, params) {
|
|
1315
|
+
if (loaderPaths) {
|
|
1316
|
+
for (const hash in paths) {
|
|
1317
|
+
delete paths[hash];
|
|
1318
|
+
delete pathParams[hash];
|
|
1319
|
+
}
|
|
1320
|
+
Object.assign(paths, loaderPaths);
|
|
1321
|
+
Object.assign(pathParams, loaderParams);
|
|
1044
1322
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
/**
|
|
1062
|
-
|
|
1063
|
-
/** Checks only if the pathnames are the same for the URLs (doesn't include search and hash) */
|
|
1323
|
+
const pageHashes = node._D ?? [];
|
|
1324
|
+
if (Array.isArray(node._I)) {
|
|
1325
|
+
for (const hash in paths) if (!pageHashes.includes(hash)) {
|
|
1326
|
+
delete paths[hash];
|
|
1327
|
+
delete pathParams[hash];
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
for (const hash of pageHashes) if (!paths[hash]) {
|
|
1331
|
+
paths[hash] = ensureSlash(pathname);
|
|
1332
|
+
pathParams[hash] = { ...params };
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
/** Gets an absolute url path string (url.pathname + url.search + url.hash) */
|
|
1336
|
+
var toPath = (url) => url.pathname + url.search + url.hash;
|
|
1337
|
+
/** Create a URL from a string and baseUrl */
|
|
1338
|
+
var toUrl = (url, baseUrl) => new URL(url, baseUrl.href);
|
|
1339
|
+
/** Checks only if the origins are the same. */
|
|
1340
|
+
var isSameOrigin = (a, b) => a.origin === b.origin;
|
|
1341
|
+
/** Checks only if the pathnames are the same for the URLs (doesn't include search and hash) */
|
|
1342
|
+
var isSamePathname = ({ pathname: a }, { pathname: b }) => {
|
|
1064
1343
|
const lDiff = Math.abs(a.length - b.length);
|
|
1065
1344
|
return lDiff === 0 ? a === b : lDiff === 1 && ensureSlash(a) === ensureSlash(b);
|
|
1066
1345
|
};
|
|
1067
|
-
/** Checks only if the search query strings are the same for the URLs */
|
|
1068
|
-
|
|
1346
|
+
/** Checks only if the search query strings are the same for the URLs */
|
|
1347
|
+
var isSameSearchQuery = (a, b) => a.search === b.search;
|
|
1348
|
+
/** Checks only if the pathname + search are the same for the URLs. */
|
|
1349
|
+
var isSamePath = (a, b) => isSameSearchQuery(a, b) && isSamePathname(a, b);
|
|
1069
1350
|
var getClientNavPath = (props, baseUrl) => {
|
|
1070
1351
|
const href = props.href;
|
|
1071
1352
|
if (typeof href === "string" && typeof props.target !== "string" && !props.reload) try {
|
|
@@ -1084,40 +1365,12 @@ var shouldPreload = (clientNavPath, currentLoc) => {
|
|
|
1084
1365
|
var isPromise = (value) => {
|
|
1085
1366
|
return value && typeof value.then === "function";
|
|
1086
1367
|
};
|
|
1087
|
-
var mergeArray = (existingArr, newArr) => {
|
|
1088
|
-
if (Array.isArray(newArr)) for (const newItem of newArr) {
|
|
1089
|
-
if (typeof newItem.key === "string") {
|
|
1090
|
-
const existingIndex = existingArr.findIndex((i) => i.key === newItem.key);
|
|
1091
|
-
if (existingIndex > -1) {
|
|
1092
|
-
existingArr[existingIndex] = newItem;
|
|
1093
|
-
continue;
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
existingArr.push(newItem);
|
|
1097
|
-
}
|
|
1098
|
-
};
|
|
1099
|
-
var resolveDocumentHead = (resolvedHead, updatedHead) => {
|
|
1100
|
-
if (typeof updatedHead.title === "string") resolvedHead.title = updatedHead.title;
|
|
1101
|
-
mergeArray(resolvedHead.meta, updatedHead.meta);
|
|
1102
|
-
mergeArray(resolvedHead.links, updatedHead.links);
|
|
1103
|
-
mergeArray(resolvedHead.styles, updatedHead.styles);
|
|
1104
|
-
mergeArray(resolvedHead.scripts, updatedHead.scripts);
|
|
1105
|
-
Object.assign(resolvedHead.frontmatter, updatedHead.frontmatter);
|
|
1106
|
-
};
|
|
1107
|
-
var createDocumentHead = (defaults, manifestHash) => ({
|
|
1108
|
-
title: defaults?.title || "",
|
|
1109
|
-
meta: [...defaults?.meta || []],
|
|
1110
|
-
links: [...defaults?.links || []],
|
|
1111
|
-
styles: [...defaults?.styles || []],
|
|
1112
|
-
scripts: [...defaults?.scripts || []],
|
|
1113
|
-
frontmatter: { ...defaults?.frontmatter },
|
|
1114
|
-
manifestHash: manifestHash || "dev"
|
|
1115
|
-
});
|
|
1116
1368
|
/**
|
|
1117
1369
|
* Resolve the full route config (head + eTag + cacheKey) from all content modules. Uses the same
|
|
1118
1370
|
* resolution rules as DocumentHead: objects are merged immediately, functions are queued and
|
|
1119
1371
|
* executed inner-before-outer.
|
|
1120
|
-
*/
|
|
1372
|
+
*/
|
|
1373
|
+
var resolveRouteConfig = (resolveValue, routeLocation, contentModules, locale, status, defaults) => withLocale(locale, () => {
|
|
1121
1374
|
const head = createDocumentHead(defaults);
|
|
1122
1375
|
let eTag;
|
|
1123
1376
|
let cacheKey;
|
|
@@ -1190,13 +1443,43 @@ var createDocumentHead = (defaults, manifestHash) => ({
|
|
|
1190
1443
|
*
|
|
1191
1444
|
* Signal values may throw a promise on the client when still loading — callers should wrap this in
|
|
1192
1445
|
* `retryOnPromise` to handle that.
|
|
1193
|
-
*/
|
|
1194
|
-
|
|
1446
|
+
*/
|
|
1447
|
+
var resolveHead = (actionData, loaderState, routeLocation, contentModules, locale, defaults) => {
|
|
1448
|
+
const getData = ((loaderOrAction) => {
|
|
1195
1449
|
const id = loaderOrAction.__id;
|
|
1196
1450
|
const signal = loaderState?.[id];
|
|
1197
1451
|
if (signal) return signal.value;
|
|
1198
1452
|
if (actionData?.action === id) return actionData.actionResult;
|
|
1199
|
-
};
|
|
1453
|
+
});
|
|
1200
1454
|
return resolveRouteConfig(getData, routeLocation, contentModules, locale, actionData?.status ?? 200, defaults).head;
|
|
1201
1455
|
};
|
|
1202
|
-
|
|
1456
|
+
var resolveDocumentHead = (resolvedHead, updatedHead) => {
|
|
1457
|
+
if (typeof updatedHead.title === "string") resolvedHead.title = updatedHead.title;
|
|
1458
|
+
mergeArray(resolvedHead.meta, updatedHead.meta);
|
|
1459
|
+
mergeArray(resolvedHead.links, updatedHead.links);
|
|
1460
|
+
mergeArray(resolvedHead.styles, updatedHead.styles);
|
|
1461
|
+
mergeArray(resolvedHead.scripts, updatedHead.scripts);
|
|
1462
|
+
Object.assign(resolvedHead.frontmatter, updatedHead.frontmatter);
|
|
1463
|
+
};
|
|
1464
|
+
var mergeArray = (existingArr, newArr) => {
|
|
1465
|
+
if (Array.isArray(newArr)) for (const newItem of newArr) {
|
|
1466
|
+
if (typeof newItem.key === "string") {
|
|
1467
|
+
const existingIndex = existingArr.findIndex((i) => i.key === newItem.key);
|
|
1468
|
+
if (existingIndex > -1) {
|
|
1469
|
+
existingArr[existingIndex] = newItem;
|
|
1470
|
+
continue;
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
existingArr.push(newItem);
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
var createDocumentHead = (defaults, manifestHash) => ({
|
|
1477
|
+
title: defaults?.title || "",
|
|
1478
|
+
meta: [...defaults?.meta || []],
|
|
1479
|
+
links: [...defaults?.links || []],
|
|
1480
|
+
styles: [...defaults?.styles || []],
|
|
1481
|
+
scripts: [...defaults?.scripts || []],
|
|
1482
|
+
frontmatter: { ...defaults?.frontmatter },
|
|
1483
|
+
manifestHash: manifestHash || "dev"
|
|
1484
|
+
});
|
|
1485
|
+
export { RoutePreventNavigateContext as $, loadRouteLoader as A, _setRouterConfig as B, getRequestEvent as C, getRouteLoaderValues as D, getRouteLoaderResponse as E, routeLoader$ as F, ContentContext as G, getRouterConfig as H, routeLoaderQrl as I, HttpStatusContext as J, ContentInternalContext as K, setLoaderSignalValue as L, prepareRouteLoaders as M, resolveRouteLoaderByHash as N, getRouteLoaders as O, restoreRouteLoaders as P, RouteNavigateContext as Q, setRouteLoaders as R, getModuleRouteLoaders as S, getRouteLoaderParams as T, getRoutes as U, getBasePathname as V, getTrailingSlash as W, RouteLoaderCtxContext as X, RouteActionContext as Y, RouteLocationContext as Z, commitRouteLoaders as _, isPromise as a, RequestEvRouterConfig as at, getClientRouteLoaders as b, shouldPreload as c, loadRoute as d, RouteStateContext as et, FULLPATH_HEADER as f, clearRouteLoaderData as g, clearNavFetchCache as h, getClientNavPath as i, Q_ROUTE as it, matchesRouteLoaderId as j, isImmutableLoader as k, toPath as l, abortRouteLoaderNavigation as m, resolveHead as n, QDATA_KEY as nt, isSameOrigin as o, _asyncRequestStore as ot, ROUTE_PATH_HEADER as p, DocumentHeadContext as q, resolveRouteConfig as r, QFN_KEY as rt, isSamePath as s, createDocumentHead as t, QACTION_KEY as tt, toUrl as u, ensureRouteLoaderSignals as v, getRouteLoaderCtx as w, getLoaderRequestEvent as x, fetchRouteLoaderData as y, _getServiceWorkerUrl as z };
|