@qwik.dev/router 2.0.0-beta.2 → 2.0.0-beta.4
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/index.d.ts +5 -2
- package/lib/index.qwik.cjs +188 -113
- package/lib/index.qwik.mjs +190 -115
- package/lib/middleware/request-handler/index.cjs +138 -61
- package/lib/middleware/request-handler/index.d.ts +7 -0
- package/lib/middleware/request-handler/index.mjs +139 -61
- package/lib/static/node.cjs +4 -2
- package/lib/static/node.mjs +5 -3
- package/lib/vite/index.cjs +141 -61
- package/lib/vite/index.d.ts +3 -0
- package/lib/vite/index.mjs +143 -61
- package/package.json +6 -7
package/lib/index.qwik.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from "@qwik.dev/core/jsx-runtime";
|
|
2
|
-
import { component$, useErrorBoundary, useOnWindow, $, Slot, isBrowser, createContextId, implicit$FirstArg, useContext, useVisibleTask$, noSerialize, useServerData, useSignal, untrack, sync$, isDev, withLocale, event$, useStyles$, isServer, useStore, useContextProvider, useTask$, getLocale, jsx as jsx$1, SkipRender } from "@qwik.dev/core";
|
|
2
|
+
import { component$, useErrorBoundary, useOnWindow, $, Slot, createAsyncComputed$, isBrowser, createContextId, implicit$FirstArg, useContext, useVisibleTask$, noSerialize, useServerData, useSignal, untrack, sync$, isDev, withLocale, event$, useStyles$, isServer, useStore, useContextProvider, useTask$, getLocale, jsx as jsx$1, SkipRender } from "@qwik.dev/core";
|
|
3
3
|
import { p } from "@qwik.dev/core/preloader";
|
|
4
|
-
import { _deserialize,
|
|
4
|
+
import { _deserialize, _UNINITIALIZED, _getContextContainer, SerializerSymbol, _getContextElement, _getQContainerElement, _waitUntilRendered, _useInvokeContext, _getContextEvent, _serialize } from "@qwik.dev/core/internal";
|
|
5
5
|
import * as qwikRouterConfig from "@qwik-router-config";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { z as z2 } from "zod";
|
|
@@ -21,100 +21,19 @@ const ErrorBoundary = component$((props) => {
|
|
|
21
21
|
const MODULE_CACHE = /* @__PURE__ */ new WeakMap();
|
|
22
22
|
const CLIENT_DATA_CACHE = /* @__PURE__ */ new Map();
|
|
23
23
|
const QACTION_KEY = "qaction";
|
|
24
|
+
const QLOADER_KEY = "qloaders";
|
|
24
25
|
const QFN_KEY = "qfunc";
|
|
25
26
|
const QDATA_KEY = "qdata";
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const isSamePathname = ({ pathname: a }, { pathname: b }) => {
|
|
31
|
-
const lDiff = Math.abs(a.length - b.length);
|
|
32
|
-
return lDiff === 0 ? a === b : lDiff === 1 && withSlash(a) === withSlash(b);
|
|
33
|
-
};
|
|
34
|
-
const isSameSearchQuery = (a, b) => a.search === b.search;
|
|
35
|
-
const isSamePath = (a, b) => isSameSearchQuery(a, b) && isSamePathname(a, b);
|
|
36
|
-
const getClientDataPath = (pathname, pageSearch, action) => {
|
|
37
|
-
let search = pageSearch ?? "";
|
|
38
|
-
if (action) {
|
|
39
|
-
search += (search ? "&" : "?") + QACTION_KEY + "=" + encodeURIComponent(action.id);
|
|
40
|
-
}
|
|
41
|
-
return pathname + (pathname.endsWith("/") ? "" : "/") + "q-data.json" + search;
|
|
42
|
-
};
|
|
43
|
-
const getClientNavPath = (props, baseUrl) => {
|
|
44
|
-
const href = props.href;
|
|
45
|
-
if (typeof href === "string" && typeof props.target !== "string" && !props.reload) {
|
|
46
|
-
try {
|
|
47
|
-
const linkUrl = toUrl(href.trim(), baseUrl.url);
|
|
48
|
-
const currentUrl = toUrl("", baseUrl.url);
|
|
49
|
-
if (isSameOrigin(linkUrl, currentUrl)) {
|
|
50
|
-
return toPath(linkUrl);
|
|
51
|
-
}
|
|
52
|
-
} catch (e) {
|
|
53
|
-
console.error(e);
|
|
54
|
-
}
|
|
55
|
-
} else if (props.reload) {
|
|
56
|
-
return toPath(toUrl("", baseUrl.url));
|
|
57
|
-
}
|
|
58
|
-
return null;
|
|
59
|
-
};
|
|
60
|
-
const shouldPreload = (clientNavPath, currentLoc) => {
|
|
61
|
-
if (clientNavPath) {
|
|
62
|
-
const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
|
|
63
|
-
const currentUrl = toUrl("", currentLoc.url);
|
|
64
|
-
return !isSamePathname(prefetchUrl, currentUrl);
|
|
65
|
-
}
|
|
66
|
-
return false;
|
|
67
|
-
};
|
|
68
|
-
const isPromise = (value) => {
|
|
69
|
-
return value && typeof value.then === "function";
|
|
70
|
-
};
|
|
71
|
-
const deepFreeze = (obj) => {
|
|
72
|
-
if (obj == null) {
|
|
73
|
-
return obj;
|
|
74
|
-
}
|
|
75
|
-
Object.getOwnPropertyNames(obj).forEach((prop) => {
|
|
76
|
-
const value = obj[prop];
|
|
77
|
-
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
78
|
-
deepFreeze(value);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
return Object.freeze(obj);
|
|
82
|
-
};
|
|
83
|
-
const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
|
|
84
|
-
if (navType !== "popstate") {
|
|
85
|
-
const samePath = isSamePath(fromURL, toURL);
|
|
86
|
-
const sameHash = fromURL.hash === toURL.hash;
|
|
87
|
-
if (!samePath || !sameHash) {
|
|
88
|
-
const newState = {
|
|
89
|
-
_qRouterScroll: newScrollState()
|
|
90
|
-
};
|
|
91
|
-
if (replaceState) {
|
|
92
|
-
win.history.replaceState(newState, "", toPath(toURL));
|
|
93
|
-
} else {
|
|
94
|
-
win.history.pushState(newState, "", toPath(toURL));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
const newScrollState = () => {
|
|
100
|
-
return {
|
|
101
|
-
x: 0,
|
|
102
|
-
y: 0,
|
|
103
|
-
w: 0,
|
|
104
|
-
h: 0
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
const prefetchSymbols = (path) => {
|
|
108
|
-
if (isBrowser) {
|
|
109
|
-
path = path.endsWith("/") ? path : path + "/";
|
|
110
|
-
path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
|
|
111
|
-
p(path, 0.8);
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
const loadClientData = async (url, element, opts) => {
|
|
27
|
+
const Q_ROUTE = "q:route";
|
|
28
|
+
const DEFAULT_LOADERS_SERIALIZATION_STRATEGY = globalThis.__DEFAULT_LOADERS_SERIALIZATION_STRATEGY__ || "never";
|
|
29
|
+
const MAX_Q_DATA_RETRY_COUNT = 3;
|
|
30
|
+
const loadClientData = async (url, element, opts, retryCount = 0) => {
|
|
115
31
|
const pagePathname = url.pathname;
|
|
116
32
|
const pageSearch = url.search;
|
|
117
|
-
const clientDataPath = getClientDataPath(pagePathname, pageSearch,
|
|
33
|
+
const clientDataPath = getClientDataPath(pagePathname, pageSearch, {
|
|
34
|
+
actionId: opts?.action?.id,
|
|
35
|
+
loaderIds: opts?.loaderIds
|
|
36
|
+
});
|
|
118
37
|
let qData;
|
|
119
38
|
if (!opts?.action) {
|
|
120
39
|
qData = CLIENT_DATA_CACHE.get(clientDataPath);
|
|
@@ -129,6 +48,10 @@ const loadClientData = async (url, element, opts) => {
|
|
|
129
48
|
opts.action.data = void 0;
|
|
130
49
|
}
|
|
131
50
|
qData = fetch(clientDataPath, fetchOptions).then((rsp) => {
|
|
51
|
+
if (rsp.status === 404 && opts?.loaderIds && retryCount < MAX_Q_DATA_RETRY_COUNT) {
|
|
52
|
+
opts.loaderIds = void 0;
|
|
53
|
+
return loadClientData(url, element, opts, retryCount + 1);
|
|
54
|
+
}
|
|
132
55
|
if (rsp.redirected) {
|
|
133
56
|
const redirectedURL = new URL(rsp.url);
|
|
134
57
|
const isQData = redirectedURL.pathname.endsWith("/q-data.json");
|
|
@@ -209,6 +132,115 @@ const getFetchOptions = (action, noCache) => {
|
|
|
209
132
|
};
|
|
210
133
|
}
|
|
211
134
|
};
|
|
135
|
+
const toPath = (url) => url.pathname + url.search + url.hash;
|
|
136
|
+
const toUrl = (url, baseUrl) => new URL(url, baseUrl.href);
|
|
137
|
+
const isSameOrigin = (a, b) => a.origin === b.origin;
|
|
138
|
+
const withSlash = (path) => path.endsWith("/") ? path : path + "/";
|
|
139
|
+
const isSamePathname = ({ pathname: a }, { pathname: b }) => {
|
|
140
|
+
const lDiff = Math.abs(a.length - b.length);
|
|
141
|
+
return lDiff === 0 ? a === b : lDiff === 1 && withSlash(a) === withSlash(b);
|
|
142
|
+
};
|
|
143
|
+
const isSameSearchQuery = (a, b) => a.search === b.search;
|
|
144
|
+
const isSamePath = (a, b) => isSameSearchQuery(a, b) && isSamePathname(a, b);
|
|
145
|
+
const getClientDataPath = (pathname, pageSearch, options) => {
|
|
146
|
+
let search = pageSearch ?? "";
|
|
147
|
+
if (options?.actionId) {
|
|
148
|
+
search += (search ? "&" : "?") + QACTION_KEY + "=" + encodeURIComponent(options.actionId);
|
|
149
|
+
}
|
|
150
|
+
if (options?.loaderIds) {
|
|
151
|
+
for (const loaderId of options.loaderIds) {
|
|
152
|
+
search += (search ? "&" : "?") + QLOADER_KEY + "=" + encodeURIComponent(loaderId);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return pathname + (pathname.endsWith("/") ? "" : "/") + "q-data.json" + search;
|
|
156
|
+
};
|
|
157
|
+
const getClientNavPath = (props, baseUrl) => {
|
|
158
|
+
const href = props.href;
|
|
159
|
+
if (typeof href === "string" && typeof props.target !== "string" && !props.reload) {
|
|
160
|
+
try {
|
|
161
|
+
const linkUrl = toUrl(href.trim(), baseUrl.url);
|
|
162
|
+
const currentUrl = toUrl("", baseUrl.url);
|
|
163
|
+
if (isSameOrigin(linkUrl, currentUrl)) {
|
|
164
|
+
return toPath(linkUrl);
|
|
165
|
+
}
|
|
166
|
+
} catch (e) {
|
|
167
|
+
console.error(e);
|
|
168
|
+
}
|
|
169
|
+
} else if (props.reload) {
|
|
170
|
+
return toPath(toUrl("", baseUrl.url));
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
};
|
|
174
|
+
const shouldPreload = (clientNavPath, currentLoc) => {
|
|
175
|
+
if (clientNavPath) {
|
|
176
|
+
const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
|
|
177
|
+
const currentUrl = toUrl("", currentLoc.url);
|
|
178
|
+
return !isSamePathname(prefetchUrl, currentUrl);
|
|
179
|
+
}
|
|
180
|
+
return false;
|
|
181
|
+
};
|
|
182
|
+
const isPromise = (value) => {
|
|
183
|
+
return value && typeof value.then === "function";
|
|
184
|
+
};
|
|
185
|
+
const deepFreeze = (obj) => {
|
|
186
|
+
if (obj == null) {
|
|
187
|
+
return obj;
|
|
188
|
+
}
|
|
189
|
+
Object.getOwnPropertyNames(obj).forEach((prop) => {
|
|
190
|
+
const value = obj[prop];
|
|
191
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
192
|
+
deepFreeze(value);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
return Object.freeze(obj);
|
|
196
|
+
};
|
|
197
|
+
const createLoaderSignal = (loadersObject, loaderId, url, serializationStrategy, container) => {
|
|
198
|
+
return createAsyncComputed$(async () => {
|
|
199
|
+
if (isBrowser && loadersObject[loaderId] === _UNINITIALIZED) {
|
|
200
|
+
const data = await loadClientData(url, void 0, {
|
|
201
|
+
loaderIds: [
|
|
202
|
+
loaderId
|
|
203
|
+
]
|
|
204
|
+
});
|
|
205
|
+
loadersObject[loaderId] = data?.loaders[loaderId] ?? _UNINITIALIZED;
|
|
206
|
+
}
|
|
207
|
+
return loadersObject[loaderId];
|
|
208
|
+
}, {
|
|
209
|
+
container,
|
|
210
|
+
serializationStrategy
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
|
|
214
|
+
if (navType !== "popstate") {
|
|
215
|
+
const samePath = isSamePath(fromURL, toURL);
|
|
216
|
+
const sameHash = fromURL.hash === toURL.hash;
|
|
217
|
+
if (!samePath || !sameHash) {
|
|
218
|
+
const newState = {
|
|
219
|
+
_qRouterScroll: newScrollState()
|
|
220
|
+
};
|
|
221
|
+
if (replaceState) {
|
|
222
|
+
win.history.replaceState(newState, "", toPath(toURL));
|
|
223
|
+
} else {
|
|
224
|
+
win.history.pushState(newState, "", toPath(toURL));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
const newScrollState = () => {
|
|
230
|
+
return {
|
|
231
|
+
x: 0,
|
|
232
|
+
y: 0,
|
|
233
|
+
w: 0,
|
|
234
|
+
h: 0
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
const prefetchSymbols = (path) => {
|
|
238
|
+
if (isBrowser) {
|
|
239
|
+
path = path.endsWith("/") ? path : path + "/";
|
|
240
|
+
path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
|
|
241
|
+
p(path, 0.8);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
212
244
|
const RouteStateContext = /* @__PURE__ */ createContextId("qc-s");
|
|
213
245
|
const ContentContext = /* @__PURE__ */ createContextId("qc-c");
|
|
214
246
|
const ContentInternalContext = /* @__PURE__ */ createContextId("qc-ic");
|
|
@@ -260,7 +292,7 @@ const Link = component$((props) => {
|
|
|
260
292
|
}
|
|
261
293
|
}
|
|
262
294
|
}) : void 0;
|
|
263
|
-
const preventDefault = clientNavPath ? sync$((event
|
|
295
|
+
const preventDefault = clientNavPath ? sync$((event) => {
|
|
264
296
|
if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {
|
|
265
297
|
event.preventDefault();
|
|
266
298
|
}
|
|
@@ -490,18 +522,30 @@ function lastIndexOf(text, start, match, searchIdx, notFoundIdx) {
|
|
|
490
522
|
}
|
|
491
523
|
return idx > start ? idx : notFoundIdx;
|
|
492
524
|
}
|
|
525
|
+
var RouteDataProp = /* @__PURE__ */ function(RouteDataProp2) {
|
|
526
|
+
RouteDataProp2[RouteDataProp2["RouteName"] = 0] = "RouteName";
|
|
527
|
+
RouteDataProp2[RouteDataProp2["Loaders"] = 1] = "Loaders";
|
|
528
|
+
RouteDataProp2[RouteDataProp2["OriginalPathname"] = 2] = "OriginalPathname";
|
|
529
|
+
RouteDataProp2[RouteDataProp2["RouteBundleNames"] = 3] = "RouteBundleNames";
|
|
530
|
+
return RouteDataProp2;
|
|
531
|
+
}({});
|
|
532
|
+
var MenuDataProp = /* @__PURE__ */ function(MenuDataProp2) {
|
|
533
|
+
MenuDataProp2[MenuDataProp2["Pathname"] = 0] = "Pathname";
|
|
534
|
+
MenuDataProp2[MenuDataProp2["MenuLoader"] = 1] = "MenuLoader";
|
|
535
|
+
return MenuDataProp2;
|
|
536
|
+
}({});
|
|
493
537
|
const loadRoute = async (routes, menus, cacheModules, pathname) => {
|
|
494
538
|
if (!Array.isArray(routes)) {
|
|
495
539
|
return null;
|
|
496
540
|
}
|
|
497
541
|
for (const routeData of routes) {
|
|
498
|
-
const routeName = routeData[
|
|
542
|
+
const routeName = routeData[RouteDataProp.RouteName];
|
|
499
543
|
const params = matchRoute(routeName, pathname);
|
|
500
544
|
if (!params) {
|
|
501
545
|
continue;
|
|
502
546
|
}
|
|
503
|
-
const loaders = routeData[
|
|
504
|
-
const routeBundleNames = routeData[
|
|
547
|
+
const loaders = routeData[RouteDataProp.Loaders];
|
|
548
|
+
const routeBundleNames = routeData[RouteDataProp.RouteBundleNames];
|
|
505
549
|
const modules = new Array(loaders.length);
|
|
506
550
|
const pendingLoads = [];
|
|
507
551
|
loaders.forEach((moduleLoader, i) => {
|
|
@@ -546,9 +590,9 @@ const loadModule = (moduleLoader, pendingLoads, moduleSetter, cacheModules) => {
|
|
|
546
590
|
const getMenuLoader = (menus, pathname) => {
|
|
547
591
|
if (menus) {
|
|
548
592
|
pathname = pathname.endsWith("/") ? pathname : pathname + "/";
|
|
549
|
-
const menu = menus.find((m) => m[
|
|
593
|
+
const menu = menus.find((m) => m[MenuDataProp.Pathname] === pathname || pathname.startsWith(m[MenuDataProp.Pathname] + (pathname.endsWith("/") ? "" : "/")));
|
|
550
594
|
if (menu) {
|
|
551
|
-
return menu[
|
|
595
|
+
return menu[MenuDataProp.MenuLoader];
|
|
552
596
|
}
|
|
553
597
|
}
|
|
554
598
|
};
|
|
@@ -815,9 +859,23 @@ const QwikRouterProvider = component$((props) => {
|
|
|
815
859
|
deep: false
|
|
816
860
|
});
|
|
817
861
|
const navResolver = {};
|
|
818
|
-
const
|
|
819
|
-
|
|
820
|
-
|
|
862
|
+
const container = _getContextContainer();
|
|
863
|
+
const getSerializationStrategy = (loaderId) => {
|
|
864
|
+
return env.response.loadersSerializationStrategy.get(loaderId) || DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
|
|
865
|
+
};
|
|
866
|
+
const loadersObject = {};
|
|
867
|
+
const loaderState = {};
|
|
868
|
+
for (const [key, value] of Object.entries(env.response.loaders)) {
|
|
869
|
+
loadersObject[key] = value;
|
|
870
|
+
loaderState[key] = createLoaderSignal(loadersObject, key, url, getSerializationStrategy(key), container);
|
|
871
|
+
}
|
|
872
|
+
loadersObject[SerializerSymbol] = (obj) => {
|
|
873
|
+
const loadersSerializationObject = {};
|
|
874
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
875
|
+
loadersSerializationObject[k] = getSerializationStrategy(k) === "always" ? v : _UNINITIALIZED;
|
|
876
|
+
}
|
|
877
|
+
return loadersSerializationObject;
|
|
878
|
+
};
|
|
821
879
|
const routeInternal = useSignal({
|
|
822
880
|
type: "initial",
|
|
823
881
|
dest: url,
|
|
@@ -910,7 +968,7 @@ const QwikRouterProvider = component$((props) => {
|
|
|
910
968
|
let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
|
|
911
969
|
if (!scroller) {
|
|
912
970
|
scroller = document.getElementById(QWIK_CITY_SCROLLER);
|
|
913
|
-
if (scroller) {
|
|
971
|
+
if (scroller && isDev) {
|
|
914
972
|
console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
|
|
915
973
|
}
|
|
916
974
|
}
|
|
@@ -1051,11 +1109,21 @@ const QwikRouterProvider = component$((props) => {
|
|
|
1051
1109
|
document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
|
|
1052
1110
|
}
|
|
1053
1111
|
const loaders = clientPageData?.loaders;
|
|
1054
|
-
const win = window;
|
|
1055
1112
|
if (loaders) {
|
|
1056
|
-
|
|
1113
|
+
const container2 = _getContextContainer();
|
|
1114
|
+
for (const [key, value] of Object.entries(loaders)) {
|
|
1115
|
+
const signal = loaderState[key];
|
|
1116
|
+
const awaitedValue = await value;
|
|
1117
|
+
loadersObject[key] = awaitedValue;
|
|
1118
|
+
if (!signal) {
|
|
1119
|
+
loaderState[key] = createLoaderSignal(loadersObject, key, trackUrl, DEFAULT_LOADERS_SERIALIZATION_STRATEGY, container2);
|
|
1120
|
+
} else {
|
|
1121
|
+
signal.invalidate();
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1057
1124
|
}
|
|
1058
1125
|
CLIENT_DATA_CACHE.clear();
|
|
1126
|
+
const win = window;
|
|
1059
1127
|
if (!win._qRouterSPA) {
|
|
1060
1128
|
win._qRouterSPA = true;
|
|
1061
1129
|
history.scrollRestoration = "manual";
|
|
@@ -1185,8 +1253,8 @@ const QwikRouterProvider = component$((props) => {
|
|
|
1185
1253
|
}
|
|
1186
1254
|
};
|
|
1187
1255
|
_waitNextPage().then(() => {
|
|
1188
|
-
const
|
|
1189
|
-
|
|
1256
|
+
const container2 = _getQContainerElement(elm);
|
|
1257
|
+
container2.setAttribute(Q_ROUTE, routeName);
|
|
1190
1258
|
const scrollState2 = currentScrollState(scroller);
|
|
1191
1259
|
saveScrollHistory(scrollState2);
|
|
1192
1260
|
win._qRouterScrollEnabled = true;
|
|
@@ -1219,7 +1287,7 @@ const QwikRouterMockProvider = component$((props) => {
|
|
|
1219
1287
|
}, {
|
|
1220
1288
|
deep: false
|
|
1221
1289
|
});
|
|
1222
|
-
const loaderState =
|
|
1290
|
+
const loaderState = {};
|
|
1223
1291
|
const routeInternal = useSignal({
|
|
1224
1292
|
type: "initial",
|
|
1225
1293
|
dest: url
|
|
@@ -1464,24 +1532,26 @@ const globalActionQrl = (actionQrl, ...rest) => {
|
|
|
1464
1532
|
const routeAction$ = /* @__PURE__ */ implicit$FirstArg(routeActionQrl);
|
|
1465
1533
|
const globalAction$ = /* @__PURE__ */ implicit$FirstArg(globalActionQrl);
|
|
1466
1534
|
const routeLoaderQrl = (loaderQrl, ...rest) => {
|
|
1467
|
-
const { id, validators } = getValidators(rest, loaderQrl);
|
|
1535
|
+
const { id, validators, serializationStrategy } = getValidators(rest, loaderQrl);
|
|
1468
1536
|
function loader() {
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1537
|
+
const iCtx = _useInvokeContext();
|
|
1538
|
+
const state = iCtx.$container$.resolveContext(iCtx.$hostElement$, RouteStateContext);
|
|
1539
|
+
if (!(id in state)) {
|
|
1540
|
+
throw new Error(`routeLoader$ "${loaderQrl.getSymbol()}" was invoked in a route where it was not declared.
|
|
1472
1541
|
This is because the routeLoader$ was not exported in a 'layout.tsx' or 'index.tsx' file of the existing route.
|
|
1473
1542
|
For more information check: https://qwik.dev/docs/route-loader/
|
|
1474
1543
|
|
|
1475
1544
|
If your are managing reusable logic or a library it is essential that this function is re-exported from within 'layout.tsx' or 'index.tsx file of the existing route otherwise it will not run or throw exception.
|
|
1476
1545
|
For more information check: https://qwik.dev/docs/re-exporting-loaders/`);
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1546
|
+
}
|
|
1547
|
+
untrack(() => state[id].value);
|
|
1548
|
+
return state[id];
|
|
1480
1549
|
}
|
|
1481
1550
|
loader.__brand = "server_loader";
|
|
1482
1551
|
loader.__qrl = loaderQrl;
|
|
1483
1552
|
loader.__validators = validators;
|
|
1484
1553
|
loader.__id = id;
|
|
1554
|
+
loader.__serializationStrategy = serializationStrategy;
|
|
1485
1555
|
Object.freeze(loader);
|
|
1486
1556
|
return loader;
|
|
1487
1557
|
};
|
|
@@ -1710,6 +1780,7 @@ const serverQrl = (qrl, options) => {
|
|
|
1710
1780
|
const server$ = /* @__PURE__ */ implicit$FirstArg(serverQrl);
|
|
1711
1781
|
const getValidators = (rest, qrl) => {
|
|
1712
1782
|
let id;
|
|
1783
|
+
let serializationStrategy = DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
|
|
1713
1784
|
const validators = [];
|
|
1714
1785
|
if (rest.length === 1) {
|
|
1715
1786
|
const options = rest[0];
|
|
@@ -1718,6 +1789,9 @@ const getValidators = (rest, qrl) => {
|
|
|
1718
1789
|
validators.push(options);
|
|
1719
1790
|
} else {
|
|
1720
1791
|
id = options.id;
|
|
1792
|
+
if (options.serializationStrategy) {
|
|
1793
|
+
serializationStrategy = options.serializationStrategy;
|
|
1794
|
+
}
|
|
1721
1795
|
if (options.validation) {
|
|
1722
1796
|
validators.push(...options.validation);
|
|
1723
1797
|
}
|
|
@@ -1738,7 +1812,8 @@ const getValidators = (rest, qrl) => {
|
|
|
1738
1812
|
}
|
|
1739
1813
|
return {
|
|
1740
1814
|
validators: validators.reverse(),
|
|
1741
|
-
id
|
|
1815
|
+
id,
|
|
1816
|
+
serializationStrategy
|
|
1742
1817
|
};
|
|
1743
1818
|
};
|
|
1744
1819
|
const deserializeStream = async function* (stream, ctxElm, abortSignal) {
|