@solidjs/router 0.17.0-next.4 → 0.17.0-next.6
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/dist/data/action.d.ts +13 -1
- package/dist/data/action.js +65 -26
- package/dist/data/flash.d.ts +25 -0
- package/dist/data/flash.js +86 -0
- package/dist/data/index.d.ts +0 -1
- package/dist/data/index.js +0 -1
- package/dist/data/query.js +29 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +493 -396
- package/dist/routers/components.jsx +9 -2
- package/dist/routing.d.ts +9 -0
- package/dist/routing.js +31 -4
- package/dist/server.d.ts +65 -0
- package/dist/server.js +228 -0
- package/dist/types.d.ts +3 -10
- package/package.json +10 -8
- package/dist/data/response.d.ts +0 -4
- package/dist/data/response.js +0 -42
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { isServer, getRequestEvent, createComponent as createComponent$1, memo, delegateEvents, spread, mergeProps, template } from '@solidjs/web';
|
|
2
|
-
import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, createSignal, flush, createComponent,
|
|
1
|
+
import { isServer, getRequestEvent, isResponseEnvelope, createComponent as createComponent$1, memo, delegateEvents, spread, mergeProps, template } from '@solidjs/web';
|
|
2
|
+
import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, children, createSignal, flush, createComponent, getObserver, sharedConfig, $TRACK, action as action$1, merge, createRoot, omit } from 'solid-js';
|
|
3
|
+
import { isServerFunction, getServerFunctionMetadata, GET, decodeResponse, subscribeFlightData } from '@solidjs/web/server-functions';
|
|
3
4
|
|
|
4
5
|
function createBeforeLeave() {
|
|
5
6
|
let listeners = new Set();
|
|
@@ -257,6 +258,63 @@ function setFunctionName(obj, value) {
|
|
|
257
258
|
return obj;
|
|
258
259
|
}
|
|
259
260
|
|
|
261
|
+
// The no-JS form convention's cookie codec. When a form posts to a server
|
|
262
|
+
// function without the client runtime (no instance header), the server
|
|
263
|
+
// handler redirects back carrying the outcome in a one-shot "flash" cookie;
|
|
264
|
+
// the next SSR pass reads it here and seeds the router's submission state so
|
|
265
|
+
// useSubmission() renders the result exactly as a scripted submission would.
|
|
266
|
+
// Both halves live in this module so the write (src/server.ts, the handler's
|
|
267
|
+
// handleNoJS) and the read (src/routing.ts, SSR initialization) can never
|
|
268
|
+
// drift apart.
|
|
269
|
+
|
|
270
|
+
const FLASH_COOKIE = "flash";
|
|
271
|
+
function decodeInputValue(value) {
|
|
272
|
+
if (value && typeof value === "object") {
|
|
273
|
+
if (Array.isArray(value.$f)) {
|
|
274
|
+
const form = new FormData();
|
|
275
|
+
for (const [k, v] of value.$f) form.append(k, v);
|
|
276
|
+
return form;
|
|
277
|
+
}
|
|
278
|
+
if (Array.isArray(value.$u)) return new URLSearchParams(value.$u);
|
|
279
|
+
}
|
|
280
|
+
return value;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/** The Set-Cookie value clearing the flash cookie after it has been read. */
|
|
284
|
+
function clearFlashCookie() {
|
|
285
|
+
return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
|
|
286
|
+
}
|
|
287
|
+
const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
|
|
288
|
+
|
|
289
|
+
/** Whether a Cookie header carries a flash cookie (readable or not). */
|
|
290
|
+
function hasFlashCookie(cookieHeader) {
|
|
291
|
+
return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Decodes the flash cookie out of a request's Cookie header. Returns
|
|
296
|
+
* undefined when absent or unreadable (a malformed cookie must never take
|
|
297
|
+
* down SSR — it is cleared either way).
|
|
298
|
+
*/
|
|
299
|
+
function decodeFlashCookie(cookieHeader) {
|
|
300
|
+
if (!cookieHeader) return;
|
|
301
|
+
const match = cookieHeader.match(FLASH_MATCHER);
|
|
302
|
+
if (!match) return;
|
|
303
|
+
try {
|
|
304
|
+
const payload = JSON.parse(decodeURIComponent(match[1]));
|
|
305
|
+
if (!payload || !payload.result) return;
|
|
306
|
+
const result = payload.error ? new Error(payload.result) : payload.result;
|
|
307
|
+
return {
|
|
308
|
+
input: Array.isArray(payload.input) ? payload.input.map(decodeInputValue) : [],
|
|
309
|
+
url: payload.url,
|
|
310
|
+
result: payload.thrown ? undefined : result,
|
|
311
|
+
error: payload.thrown ? result : undefined
|
|
312
|
+
};
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.error(error);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
260
318
|
const MAX_REDIRECTS = 100;
|
|
261
319
|
|
|
262
320
|
/** Consider this API opaque and internal. It is likely to change in the future. */
|
|
@@ -547,6 +605,17 @@ function createBranch(routes, index = 0) {
|
|
|
547
605
|
function asArray(value) {
|
|
548
606
|
return Array.isArray(value) ? value : [value];
|
|
549
607
|
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Resolves the route tree an app hands the router — JSX `<Route>` children
|
|
611
|
+
* (`Route` is a data-holder component, evaluating to its merged props),
|
|
612
|
+
* config objects, arrays, or thunks producing either — into route
|
|
613
|
+
* definitions. Shared by the `<Router>` component (which keeps the
|
|
614
|
+
* resolution live) and the server integration's preload runner (one-shot).
|
|
615
|
+
*/
|
|
616
|
+
function resolveRouteDefinitions(routes) {
|
|
617
|
+
return children(() => routes);
|
|
618
|
+
}
|
|
550
619
|
function createBranches(routeDef, base = "", stack = [], branches = []) {
|
|
551
620
|
const routeDefs = asArray(routeDef);
|
|
552
621
|
for (let i = 0, len = routeDefs.length; i < len; i++) {
|
|
@@ -837,11 +906,26 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
837
906
|
}
|
|
838
907
|
intent = prevIntent;
|
|
839
908
|
}
|
|
909
|
+
|
|
910
|
+
// Seeds the initial submission from a no-JS form post: the server
|
|
911
|
+
// function handler redirected back with the outcome in a one-shot flash
|
|
912
|
+
// cookie (see src/server.ts's handleNoJS), which is read here — and
|
|
913
|
+
// cleared — so the post-redirect SSR renders useSubmission() state
|
|
914
|
+
// exactly as a scripted submission would. An explicitly pre-seeded
|
|
915
|
+
// `event.router.submission` (framework integrations) takes precedence.
|
|
840
916
|
function initFromFlash() {
|
|
841
917
|
const e = getRequestEvent();
|
|
842
|
-
if (!
|
|
918
|
+
if (!e) return [];
|
|
919
|
+
let submission = e.router && e.router.submission;
|
|
920
|
+
if (!submission) {
|
|
921
|
+
const cookieHeader = e.request.headers.get("cookie");
|
|
922
|
+
submission = decodeFlashCookie(cookieHeader);
|
|
923
|
+
// one-shot: clear it even when unreadable so it can't haunt later renders
|
|
924
|
+
if (hasFlashCookie(cookieHeader) && e.response && e.response.headers) e.response.headers.append("Set-Cookie", clearFlashCookie());
|
|
925
|
+
}
|
|
926
|
+
if (!submission) return [];
|
|
843
927
|
return [{
|
|
844
|
-
...
|
|
928
|
+
...submission,
|
|
845
929
|
clear() {},
|
|
846
930
|
retry() {}
|
|
847
931
|
}];
|
|
@@ -891,327 +975,99 @@ function createRouteContext(router, parent, outlet, match, matches = () => [matc
|
|
|
891
975
|
return route;
|
|
892
976
|
}
|
|
893
977
|
|
|
894
|
-
const
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
rootPreload: props.rootPreload,
|
|
908
|
-
routeChildren: props.children
|
|
909
|
-
}));
|
|
910
|
-
const routeDefs = children(() => routeChildren);
|
|
911
|
-
const branches = createMemo(() => createBranches(routeDefs(), base || ""));
|
|
912
|
-
let context;
|
|
913
|
-
const routerState = createRouterContext(router, branches, () => context, {
|
|
914
|
-
base,
|
|
915
|
-
singleFlight,
|
|
916
|
-
transformUrl
|
|
917
|
-
});
|
|
918
|
-
router.create && router.create(routerState);
|
|
919
|
-
return createComponent$1(RouterContextObj, {
|
|
920
|
-
value: routerState,
|
|
921
|
-
get children() {
|
|
922
|
-
return createComponent$1(Root, {
|
|
923
|
-
routerState: routerState,
|
|
924
|
-
root: root,
|
|
925
|
-
preload: rootPreload,
|
|
926
|
-
get children() {
|
|
927
|
-
return [memo(() => (context = getOwner()) && null), createComponent$1(Routes, {
|
|
928
|
-
routerState: routerState,
|
|
929
|
-
get branches() {
|
|
930
|
-
return branches();
|
|
931
|
-
}
|
|
932
|
-
})];
|
|
933
|
-
}
|
|
934
|
-
});
|
|
978
|
+
const LocationHeader = "Location";
|
|
979
|
+
const PRELOAD_TIMEOUT = 5000;
|
|
980
|
+
const CACHE_TIMEOUT = 180000;
|
|
981
|
+
let cacheMap = new Map();
|
|
982
|
+
|
|
983
|
+
// cleanup forward/back cache
|
|
984
|
+
if (!isServer) {
|
|
985
|
+
setInterval(() => {
|
|
986
|
+
const now = Date.now();
|
|
987
|
+
for (let [k, v] of cacheMap.entries()) {
|
|
988
|
+
if (!v[4].count && now - v[0] > CACHE_TIMEOUT) {
|
|
989
|
+
cacheMap.delete(k);
|
|
990
|
+
}
|
|
935
991
|
}
|
|
992
|
+
}, 300000);
|
|
993
|
+
}
|
|
994
|
+
function getCache() {
|
|
995
|
+
if (!isServer) return cacheMap;
|
|
996
|
+
const req = getRequestEvent();
|
|
997
|
+
if (!req) throw new Error("Cannot find cache context");
|
|
998
|
+
return (req.router || (req.router = {})).cache || (req.router.cache = new Map());
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* Revalidates the given cache entry/entries.
|
|
1003
|
+
*/
|
|
1004
|
+
function revalidate(key, force = true) {
|
|
1005
|
+
const now = Date.now();
|
|
1006
|
+
cacheKeyOp(key, entry => {
|
|
1007
|
+
force && (entry[0] = 0); //force cache miss
|
|
1008
|
+
entry[4][1](now); // retrigger live signals
|
|
936
1009
|
});
|
|
937
|
-
}
|
|
938
|
-
function
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
setInPreloadFn(true);
|
|
943
|
-
props.preload({
|
|
944
|
-
params,
|
|
945
|
-
location,
|
|
946
|
-
intent: getIntent() || "initial"
|
|
947
|
-
});
|
|
948
|
-
setInPreloadFn(false);
|
|
949
|
-
}));
|
|
950
|
-
const RootComp = props.root;
|
|
951
|
-
if (RootComp) {
|
|
952
|
-
return createComponent$1(RootComp, {
|
|
953
|
-
params: params,
|
|
954
|
-
location: location,
|
|
955
|
-
get data() {
|
|
956
|
-
return data();
|
|
957
|
-
},
|
|
958
|
-
get children() {
|
|
959
|
-
return props.children;
|
|
960
|
-
}
|
|
961
|
-
});
|
|
1010
|
+
}
|
|
1011
|
+
function cacheKeyOp(key, fn) {
|
|
1012
|
+
key && !Array.isArray(key) && (key = [key]);
|
|
1013
|
+
for (let k of cacheMap.keys()) {
|
|
1014
|
+
if (key === undefined || matchKey(k, key)) fn(cacheMap.get(k));
|
|
962
1015
|
}
|
|
963
|
-
return props.children;
|
|
964
1016
|
}
|
|
965
|
-
function
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
params
|
|
976
|
-
}) => ({
|
|
977
|
-
path: route.originalPath,
|
|
978
|
-
pattern: route.pattern,
|
|
979
|
-
match: path,
|
|
980
|
-
params,
|
|
981
|
-
info: route.info
|
|
982
|
-
}))));
|
|
1017
|
+
function query(fn, name) {
|
|
1018
|
+
// query implies GET: the router primitive is the declaration site, so a
|
|
1019
|
+
// server function handed to query() is wrapped with core `GET(fn)` here,
|
|
1020
|
+
// at query-creation (module scope) — the server half records the method
|
|
1021
|
+
// declaration for dispatch, the client half swaps in the GET transport.
|
|
1022
|
+
// An explicit `GET(fn)` already carries the declaration on the metadata
|
|
1023
|
+
// channel (`getServerFunctionMetadata(fn)?.method === "GET"`) and passes
|
|
1024
|
+
// through; non-server functions are untouched.
|
|
1025
|
+
if (isServerFunction(fn) && !getServerFunctionMetadata(fn)?.method) {
|
|
1026
|
+
fn = GET(fn);
|
|
983
1027
|
}
|
|
984
|
-
const
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
equal = false;
|
|
1006
|
-
if (disposers[i]) {
|
|
1007
|
-
disposers[i]();
|
|
1028
|
+
const cachedFn = (...args) => {
|
|
1029
|
+
const cache = getCache();
|
|
1030
|
+
const intent = getIntent();
|
|
1031
|
+
const inPreloadFn = getInPreloadFn();
|
|
1032
|
+
const owner = getOwner();
|
|
1033
|
+
const navigate = owner ? useNavigate() : undefined;
|
|
1034
|
+
const now = Date.now();
|
|
1035
|
+
const key = name + hashKey(args);
|
|
1036
|
+
let cached = cache.get(key);
|
|
1037
|
+
let tracking;
|
|
1038
|
+
if (isServer) {
|
|
1039
|
+
const e = getRequestEvent();
|
|
1040
|
+
if (e) {
|
|
1041
|
+
const dataOnly = (e.router || (e.router = {})).dataOnly;
|
|
1042
|
+
if (dataOnly) {
|
|
1043
|
+
const data = e && (e.router.data || (e.router.data = {}));
|
|
1044
|
+
if (data && key in data) return data[key];
|
|
1045
|
+
if (Array.isArray(dataOnly) && !matchKey(key, dataOnly)) {
|
|
1046
|
+
data[key] = undefined;
|
|
1047
|
+
return Promise.resolve();
|
|
1048
|
+
}
|
|
1008
1049
|
}
|
|
1009
|
-
runWithOwner(owner, () => createRoot(dispose => {
|
|
1010
|
-
disposers[i] = dispose;
|
|
1011
|
-
const routeKey = nextMatch.route.key;
|
|
1012
|
-
// Retain the last matches in which this route participated so
|
|
1013
|
-
// that its components and preloads never observe another
|
|
1014
|
-
// route's params/path while this route is being torn down.
|
|
1015
|
-
const matchesAtLevel = createMemo(prev => {
|
|
1016
|
-
const routeMatches = props.routerState.matches();
|
|
1017
|
-
const m = routeMatches[i];
|
|
1018
|
-
return m && m.route.key === routeKey ? routeMatches : prev || nextMatches;
|
|
1019
|
-
});
|
|
1020
|
-
next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()?.[i + 1]), () => matchesAtLevel()[i], matchesAtLevel);
|
|
1021
|
-
}));
|
|
1022
1050
|
}
|
|
1023
1051
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
return prev;
|
|
1028
|
-
}
|
|
1029
|
-
root = next[0];
|
|
1030
|
-
prevMatches = nextMatches;
|
|
1031
|
-
return next;
|
|
1032
|
-
});
|
|
1033
|
-
const outlet = createOutlet(() => routeStates() && root);
|
|
1034
|
-
return memo(outlet);
|
|
1035
|
-
}
|
|
1036
|
-
const createOutlet = child => {
|
|
1037
|
-
return () => {
|
|
1038
|
-
const c = child();
|
|
1039
|
-
if (c) {
|
|
1040
|
-
return createComponent$1(RouteContextObj, {
|
|
1041
|
-
value: c,
|
|
1042
|
-
get children() {
|
|
1043
|
-
return c.outlet();
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1052
|
+
if (getObserver() && !isServer) {
|
|
1053
|
+
tracking = true;
|
|
1054
|
+
onCleanup(() => cached[4].count--);
|
|
1046
1055
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
const prevMatches = getRouteMatches(branches, new URL(event.router.previousUrl || event.request.url).pathname);
|
|
1063
|
-
const matches = getRouteMatches(branches, url.pathname);
|
|
1064
|
-
for (let match = 0; match < matches.length; match++) {
|
|
1065
|
-
if (!prevMatches[match] || matches[match].route !== prevMatches[match].route) event.router.dataOnly = true;
|
|
1066
|
-
const {
|
|
1067
|
-
route,
|
|
1068
|
-
params
|
|
1069
|
-
} = matches[match];
|
|
1070
|
-
route.preload && route.preload({
|
|
1071
|
-
params,
|
|
1072
|
-
location: routerState.location,
|
|
1073
|
-
intent: "preload"
|
|
1074
|
-
});
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
function createRouter(config) {
|
|
1079
|
-
let ignore = false;
|
|
1080
|
-
const wrap = value => typeof value === "string" ? {
|
|
1081
|
-
value
|
|
1082
|
-
} : value;
|
|
1083
|
-
const [read, write] = createSignal(wrap(config.get()), {
|
|
1084
|
-
equals: (a, b) => a.value === b.value && a.state === b.state,
|
|
1085
|
-
ownedWrite: true
|
|
1086
|
-
});
|
|
1087
|
-
const signal = [read, next => {
|
|
1088
|
-
!ignore && config.set(next);
|
|
1089
|
-
if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = true;
|
|
1090
|
-
write(next);
|
|
1091
|
-
}];
|
|
1092
|
-
config.init && onCleanup(config.init((value = config.get()) => {
|
|
1093
|
-
ignore = true;
|
|
1094
|
-
signal[1](wrap(value));
|
|
1095
|
-
ignore = false;
|
|
1096
|
-
}));
|
|
1097
|
-
return createRouterComponent({
|
|
1098
|
-
signal,
|
|
1099
|
-
create: config.create,
|
|
1100
|
-
utils: config.utils
|
|
1101
|
-
});
|
|
1102
|
-
}
|
|
1103
|
-
function bindEvent(target, type, handler) {
|
|
1104
|
-
target.addEventListener(type, handler);
|
|
1105
|
-
return () => target.removeEventListener(type, handler);
|
|
1106
|
-
}
|
|
1107
|
-
function scrollToHash(hash, fallbackTop) {
|
|
1108
|
-
const el = hash && document.getElementById(hash);
|
|
1109
|
-
if (el) {
|
|
1110
|
-
el.scrollIntoView();
|
|
1111
|
-
} else if (fallbackTop) {
|
|
1112
|
-
window.scrollTo(0, 0);
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
function getPath(url) {
|
|
1117
|
-
const u = new URL(url);
|
|
1118
|
-
return u.pathname + u.search;
|
|
1119
|
-
}
|
|
1120
|
-
function StaticRouter(props) {
|
|
1121
|
-
let e;
|
|
1122
|
-
const obj = {
|
|
1123
|
-
value: props.url || (e = getRequestEvent()) && getPath(e.request.url) || ""
|
|
1124
|
-
};
|
|
1125
|
-
return createRouterComponent({
|
|
1126
|
-
signal: [() => obj, next => Object.assign(obj, next)]
|
|
1127
|
-
})(props);
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
const LocationHeader = "Location";
|
|
1131
|
-
const PRELOAD_TIMEOUT = 5000;
|
|
1132
|
-
const CACHE_TIMEOUT = 180000;
|
|
1133
|
-
let cacheMap = new Map();
|
|
1134
|
-
|
|
1135
|
-
// cleanup forward/back cache
|
|
1136
|
-
if (!isServer) {
|
|
1137
|
-
setInterval(() => {
|
|
1138
|
-
const now = Date.now();
|
|
1139
|
-
for (let [k, v] of cacheMap.entries()) {
|
|
1140
|
-
if (!v[4].count && now - v[0] > CACHE_TIMEOUT) {
|
|
1141
|
-
cacheMap.delete(k);
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
}, 300000);
|
|
1145
|
-
}
|
|
1146
|
-
function getCache() {
|
|
1147
|
-
if (!isServer) return cacheMap;
|
|
1148
|
-
const req = getRequestEvent();
|
|
1149
|
-
if (!req) throw new Error("Cannot find cache context");
|
|
1150
|
-
return (req.router || (req.router = {})).cache || (req.router.cache = new Map());
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
/**
|
|
1154
|
-
* Revalidates the given cache entry/entries.
|
|
1155
|
-
*/
|
|
1156
|
-
function revalidate(key, force = true) {
|
|
1157
|
-
const now = Date.now();
|
|
1158
|
-
cacheKeyOp(key, entry => {
|
|
1159
|
-
force && (entry[0] = 0); //force cache miss
|
|
1160
|
-
entry[4][1](now); // retrigger live signals
|
|
1161
|
-
});
|
|
1162
|
-
}
|
|
1163
|
-
function cacheKeyOp(key, fn) {
|
|
1164
|
-
key && !Array.isArray(key) && (key = [key]);
|
|
1165
|
-
for (let k of cacheMap.keys()) {
|
|
1166
|
-
if (key === undefined || matchKey(k, key)) fn(cacheMap.get(k));
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
function query(fn, name) {
|
|
1170
|
-
// prioritize GET for server functions
|
|
1171
|
-
if (fn.GET) fn = fn.GET;
|
|
1172
|
-
const cachedFn = (...args) => {
|
|
1173
|
-
const cache = getCache();
|
|
1174
|
-
const intent = getIntent();
|
|
1175
|
-
const inPreloadFn = getInPreloadFn();
|
|
1176
|
-
const owner = getOwner();
|
|
1177
|
-
const navigate = owner ? useNavigate() : undefined;
|
|
1178
|
-
const now = Date.now();
|
|
1179
|
-
const key = name + hashKey(args);
|
|
1180
|
-
let cached = cache.get(key);
|
|
1181
|
-
let tracking;
|
|
1182
|
-
if (isServer) {
|
|
1183
|
-
const e = getRequestEvent();
|
|
1184
|
-
if (e) {
|
|
1185
|
-
const dataOnly = (e.router || (e.router = {})).dataOnly;
|
|
1186
|
-
if (dataOnly) {
|
|
1187
|
-
const data = e && (e.router.data || (e.router.data = {}));
|
|
1188
|
-
if (data && key in data) return data[key];
|
|
1189
|
-
if (Array.isArray(dataOnly) && !matchKey(key, dataOnly)) {
|
|
1190
|
-
data[key] = undefined;
|
|
1191
|
-
return Promise.resolve();
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
if (getObserver() && !isServer) {
|
|
1197
|
-
tracking = true;
|
|
1198
|
-
onCleanup(() => cached[4].count--);
|
|
1199
|
-
}
|
|
1200
|
-
if (cached && cached[0] && (isServer || intent === "native" || cached[4].count || Date.now() - cached[0] < PRELOAD_TIMEOUT)) {
|
|
1201
|
-
if (tracking) {
|
|
1202
|
-
cached[4].count++;
|
|
1203
|
-
cached[4][0](); // track
|
|
1204
|
-
}
|
|
1205
|
-
if (cached[3] === "preload" && intent !== "preload") {
|
|
1206
|
-
cached[0] = now;
|
|
1207
|
-
}
|
|
1208
|
-
let res = cached[1];
|
|
1209
|
-
if (intent !== "preload") {
|
|
1210
|
-
res = "then" in cached[1] ? cached[1].then(handleResponse(false), handleResponse(true)) : handleResponse(false)(cached[1]);
|
|
1211
|
-
!isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
|
|
1212
|
-
}
|
|
1213
|
-
inPreloadFn && "then" in res && res.catch(() => {});
|
|
1214
|
-
return res;
|
|
1056
|
+
if (cached && cached[0] && (isServer || intent === "native" || cached[4].count || Date.now() - cached[0] < PRELOAD_TIMEOUT)) {
|
|
1057
|
+
if (tracking) {
|
|
1058
|
+
cached[4].count++;
|
|
1059
|
+
cached[4][0](); // track
|
|
1060
|
+
}
|
|
1061
|
+
if (cached[3] === "preload" && intent !== "preload") {
|
|
1062
|
+
cached[0] = now;
|
|
1063
|
+
}
|
|
1064
|
+
let res = cached[1];
|
|
1065
|
+
if (intent !== "preload") {
|
|
1066
|
+
res = "then" in cached[1] ? cached[1].then(handleResponse(false), handleResponse(true)) : handleResponse(false)(cached[1]);
|
|
1067
|
+
!isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
|
|
1068
|
+
}
|
|
1069
|
+
inPreloadFn && "then" in res && res.catch(() => {});
|
|
1070
|
+
return res;
|
|
1215
1071
|
}
|
|
1216
1072
|
let res;
|
|
1217
1073
|
if (!isServer && sharedConfig.has && sharedConfig.has(key)) {
|
|
@@ -1250,6 +1106,14 @@ function query(fn, name) {
|
|
|
1250
1106
|
return res;
|
|
1251
1107
|
function handleResponse(error) {
|
|
1252
1108
|
return async v => {
|
|
1109
|
+
let enveloped;
|
|
1110
|
+
let hasEnveloped = false;
|
|
1111
|
+
if (isResponseEnvelope(v)) {
|
|
1112
|
+
// respond(): the value rides in memory beside the metadata
|
|
1113
|
+
enveloped = v.value;
|
|
1114
|
+
hasEnveloped = true;
|
|
1115
|
+
v = v.response;
|
|
1116
|
+
}
|
|
1253
1117
|
if (v instanceof Response) {
|
|
1254
1118
|
const e = getRequestEvent();
|
|
1255
1119
|
if (e) {
|
|
@@ -1265,7 +1129,12 @@ function query(fn, name) {
|
|
|
1265
1129
|
});else if (!isServer) window.location.href = url;else if (e) e.response.status = 302;
|
|
1266
1130
|
return;
|
|
1267
1131
|
}
|
|
1268
|
-
if (
|
|
1132
|
+
if (hasEnveloped) v = enveloped;else if (v.body) {
|
|
1133
|
+
// responses the transport hands over whole (revalidation) carry a
|
|
1134
|
+
// codec-encoded body; anything else (a raw user Response) stays whole
|
|
1135
|
+
const decoded = await decodeResponse(v);
|
|
1136
|
+
if (decoded !== undefined) v = decoded;
|
|
1137
|
+
}
|
|
1269
1138
|
}
|
|
1270
1139
|
if (error) throw v;
|
|
1271
1140
|
cached[2] = v;
|
|
@@ -1348,11 +1217,10 @@ function actionImpl(fn, options = {}) {
|
|
|
1348
1217
|
const form = this.f;
|
|
1349
1218
|
const submitHooks = current[submitHooksSymbol];
|
|
1350
1219
|
const settledHooks = current[settledHooksSymbol];
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
}) : fn)(...variables);
|
|
1220
|
+
// Single-flight opt-in is no longer per call: the router's registered
|
|
1221
|
+
// flight-data consumer (see setupFlightDataConsumer) makes the transport
|
|
1222
|
+
// send the request header itself, so the mutation is just called.
|
|
1223
|
+
const runMutation = () => fn(...variables);
|
|
1356
1224
|
const run = action$1(async function* (context) {
|
|
1357
1225
|
context.optimistic?.();
|
|
1358
1226
|
try {
|
|
@@ -1466,43 +1334,325 @@ async function settleActionResult(result) {
|
|
|
1466
1334
|
}
|
|
1467
1335
|
return result;
|
|
1468
1336
|
}
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1337
|
+
|
|
1338
|
+
/**
|
|
1339
|
+
* Registers the router as the single-flight consumer of the server function
|
|
1340
|
+
* transport. Subscribing is the opt-in: while registered, the transport
|
|
1341
|
+
* sends the `X-Single-Flight` request header on mutations and delivers the
|
|
1342
|
+
* folded payload here — fresh route data is seeded into the `query` cache
|
|
1343
|
+
* and the envelope metadata (redirect `Location`, `X-Revalidate` keys) is
|
|
1344
|
+
* applied, all before the action sees its plain return value. Called by the
|
|
1345
|
+
* Router component on the client unless `singleFlight={false}`, which now
|
|
1346
|
+
* simply means "never subscribe" — no consumer, no request header, no
|
|
1347
|
+
* collection work on the server. Returns the unsubscribe function.
|
|
1348
|
+
*/
|
|
1349
|
+
function setupFlightDataConsumer(router) {
|
|
1350
|
+
return subscribeFlightData((data, {
|
|
1351
|
+
response
|
|
1352
|
+
}) => applyResponseMetadata(response, router.navigatorFactory(), data));
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* Applies a server function response's integration metadata: `X-Revalidate`
|
|
1357
|
+
* keys invalidate, `Location` navigates (hard for absolute urls), flight
|
|
1358
|
+
* data seeds the query cache, and matching entries revalidate. Shared by
|
|
1359
|
+
* the flight-data consumer and the action response path (which still sees
|
|
1360
|
+
* metadata-bearing responses when no flight data was collected).
|
|
1361
|
+
*/
|
|
1362
|
+
async function applyResponseMetadata(metadata, navigate, flightData) {
|
|
1472
1363
|
let keys;
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
if (
|
|
1476
|
-
|
|
1477
|
-
data = custom = await response.customBody();
|
|
1478
|
-
if (response.headers.has("X-Single-Flight")) {
|
|
1479
|
-
data = data._$value;
|
|
1480
|
-
delete custom._$value;
|
|
1481
|
-
flightKeys = Object.keys(custom);
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
if (response.headers.has("Location")) {
|
|
1485
|
-
const locationUrl = response.headers.get("Location") || "/";
|
|
1364
|
+
if (metadata) {
|
|
1365
|
+
if (metadata.headers.has("X-Revalidate")) keys = metadata.headers.get("X-Revalidate").split(",");
|
|
1366
|
+
if (metadata.headers.has("Location")) {
|
|
1367
|
+
const locationUrl = metadata.headers.get("Location") || "/";
|
|
1486
1368
|
if (locationUrl.startsWith("http")) {
|
|
1487
1369
|
window.location.href = locationUrl;
|
|
1488
1370
|
} else {
|
|
1489
1371
|
navigate(locationUrl);
|
|
1490
1372
|
}
|
|
1491
1373
|
}
|
|
1492
|
-
}
|
|
1493
|
-
error: response
|
|
1494
|
-
};else data = response;
|
|
1374
|
+
}
|
|
1495
1375
|
// invalidate
|
|
1496
1376
|
cacheKeyOp(keys, entry => entry[0] = 0);
|
|
1497
1377
|
// set cache
|
|
1498
|
-
|
|
1378
|
+
flightData && Object.keys(flightData).forEach(k => query.set(k, flightData[k]));
|
|
1499
1379
|
// trigger revalidation
|
|
1500
1380
|
await revalidate(keys, false);
|
|
1381
|
+
}
|
|
1382
|
+
async function handleResponse(response, error, navigate) {
|
|
1383
|
+
let data;
|
|
1384
|
+
let flightData;
|
|
1385
|
+
let metadata;
|
|
1386
|
+
if (isResponseEnvelope(response)) {
|
|
1387
|
+
// client-only respond(): the value rides in memory beside the metadata
|
|
1388
|
+
data = response.value;
|
|
1389
|
+
metadata = response.response;
|
|
1390
|
+
} else if (response instanceof Response) {
|
|
1391
|
+
metadata = response;
|
|
1392
|
+
// responses the transport hands over whole (redirects, revalidation)
|
|
1393
|
+
// carry a codec-encoded body the router decodes itself. With the
|
|
1394
|
+
// flight-data consumer registered single-flight payloads never reach
|
|
1395
|
+
// this path, but a manually opted-in call (no consumer) still can —
|
|
1396
|
+
// unwrap the standardized { value, data } shape for it too.
|
|
1397
|
+
if (response.body) {
|
|
1398
|
+
data = await decodeResponse(response);
|
|
1399
|
+
if (response.headers.has("X-Single-Flight")) {
|
|
1400
|
+
const payload = data;
|
|
1401
|
+
data = payload.value;
|
|
1402
|
+
flightData = payload.data;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
} else if (error) return {
|
|
1406
|
+
error: response
|
|
1407
|
+
};else data = response;
|
|
1408
|
+
await applyResponseMetadata(metadata, navigate, flightData);
|
|
1501
1409
|
return data != null ? {
|
|
1502
1410
|
data
|
|
1503
1411
|
} : undefined;
|
|
1504
1412
|
}
|
|
1505
1413
|
|
|
1414
|
+
const createRouterComponent = router => function IntegratedRouter(props) {
|
|
1415
|
+
const {
|
|
1416
|
+
base,
|
|
1417
|
+
singleFlight,
|
|
1418
|
+
transformUrl,
|
|
1419
|
+
root,
|
|
1420
|
+
rootPreload,
|
|
1421
|
+
routeChildren
|
|
1422
|
+
} = untrack(() => ({
|
|
1423
|
+
base: props.base,
|
|
1424
|
+
singleFlight: props.singleFlight,
|
|
1425
|
+
transformUrl: props.transformUrl,
|
|
1426
|
+
root: props.root,
|
|
1427
|
+
rootPreload: props.rootPreload,
|
|
1428
|
+
routeChildren: props.children
|
|
1429
|
+
}));
|
|
1430
|
+
const routeDefs = resolveRouteDefinitions(routeChildren);
|
|
1431
|
+
const branches = createMemo(() => createBranches(routeDefs(), base || ""));
|
|
1432
|
+
let context;
|
|
1433
|
+
const routerState = createRouterContext(router, branches, () => context, {
|
|
1434
|
+
base,
|
|
1435
|
+
singleFlight,
|
|
1436
|
+
transformUrl
|
|
1437
|
+
});
|
|
1438
|
+
router.create && router.create(routerState);
|
|
1439
|
+
if (!isServer && routerState.singleFlight) {
|
|
1440
|
+
// Registering the consumer IS the single-flight opt-in: the transport
|
|
1441
|
+
// sends the request header while one is subscribed. `singleFlight={false}`
|
|
1442
|
+
// simply never subscribes, so the server is never asked to collect.
|
|
1443
|
+
onCleanup(setupFlightDataConsumer(routerState));
|
|
1444
|
+
}
|
|
1445
|
+
return createComponent$1(RouterContextObj, {
|
|
1446
|
+
value: routerState,
|
|
1447
|
+
get children() {
|
|
1448
|
+
return createComponent$1(Root, {
|
|
1449
|
+
routerState: routerState,
|
|
1450
|
+
root: root,
|
|
1451
|
+
preload: rootPreload,
|
|
1452
|
+
get children() {
|
|
1453
|
+
return [memo(() => (context = getOwner()) && null), createComponent$1(Routes, {
|
|
1454
|
+
routerState: routerState,
|
|
1455
|
+
get branches() {
|
|
1456
|
+
return branches();
|
|
1457
|
+
}
|
|
1458
|
+
})];
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
});
|
|
1463
|
+
};
|
|
1464
|
+
function Root(props) {
|
|
1465
|
+
const location = props.routerState.location;
|
|
1466
|
+
const params = props.routerState.params;
|
|
1467
|
+
const data = createMemo(() => props.preload && untrack(() => {
|
|
1468
|
+
setInPreloadFn(true);
|
|
1469
|
+
props.preload({
|
|
1470
|
+
params,
|
|
1471
|
+
location,
|
|
1472
|
+
intent: getIntent() || "initial"
|
|
1473
|
+
});
|
|
1474
|
+
setInPreloadFn(false);
|
|
1475
|
+
}));
|
|
1476
|
+
const RootComp = props.root;
|
|
1477
|
+
if (RootComp) {
|
|
1478
|
+
return createComponent$1(RootComp, {
|
|
1479
|
+
params: params,
|
|
1480
|
+
location: location,
|
|
1481
|
+
get data() {
|
|
1482
|
+
return data();
|
|
1483
|
+
},
|
|
1484
|
+
get children() {
|
|
1485
|
+
return props.children;
|
|
1486
|
+
}
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
return props.children;
|
|
1490
|
+
}
|
|
1491
|
+
function Routes(props) {
|
|
1492
|
+
if (isServer) {
|
|
1493
|
+
const e = getRequestEvent();
|
|
1494
|
+
if (e && e.router && e.router.dataOnly) {
|
|
1495
|
+
dataOnly(e, props.routerState, props.branches);
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
e && ((e.router || (e.router = {})).matches || (e.router.matches = props.routerState.matches().map(({
|
|
1499
|
+
route,
|
|
1500
|
+
path,
|
|
1501
|
+
params
|
|
1502
|
+
}) => ({
|
|
1503
|
+
path: route.originalPath,
|
|
1504
|
+
pattern: route.pattern,
|
|
1505
|
+
match: path,
|
|
1506
|
+
params,
|
|
1507
|
+
info: route.info
|
|
1508
|
+
}))));
|
|
1509
|
+
}
|
|
1510
|
+
const disposers = [];
|
|
1511
|
+
let root;
|
|
1512
|
+
let prevMatches;
|
|
1513
|
+
// dispose the detached per-route roots when this component unmounts, otherwise
|
|
1514
|
+
// they stay subscribed to `matches` and crash on a later navigation (#451)
|
|
1515
|
+
onCleanup(() => disposers.forEach(dispose => dispose()));
|
|
1516
|
+
// Route roots must outlive re-runs of the `routeStates` memo below, so they
|
|
1517
|
+
// are created under the owner of this component rather than the memo's
|
|
1518
|
+
// computation (which disposes its children every time it re-runs).
|
|
1519
|
+
const owner = getOwner();
|
|
1520
|
+
const routeStates = createMemo(prev => {
|
|
1521
|
+
const nextMatches = props.routerState.matches();
|
|
1522
|
+
const previousMatches = prevMatches;
|
|
1523
|
+
let equal = previousMatches && nextMatches.length === previousMatches.length;
|
|
1524
|
+
const next = [];
|
|
1525
|
+
for (let i = 0, len = nextMatches.length; i < len; i++) {
|
|
1526
|
+
const prevMatch = previousMatches && previousMatches[i];
|
|
1527
|
+
const nextMatch = nextMatches[i];
|
|
1528
|
+
if (prev && prevMatch && nextMatch.route.key === prevMatch.route.key) {
|
|
1529
|
+
next[i] = prev[i];
|
|
1530
|
+
} else {
|
|
1531
|
+
equal = false;
|
|
1532
|
+
if (disposers[i]) {
|
|
1533
|
+
disposers[i]();
|
|
1534
|
+
}
|
|
1535
|
+
runWithOwner(owner, () => createRoot(dispose => {
|
|
1536
|
+
disposers[i] = dispose;
|
|
1537
|
+
const routeKey = nextMatch.route.key;
|
|
1538
|
+
// Retain the last matches in which this route participated so
|
|
1539
|
+
// that its components and preloads never observe another
|
|
1540
|
+
// route's params/path while this route is being torn down.
|
|
1541
|
+
const matchesAtLevel = createMemo(prev => {
|
|
1542
|
+
const routeMatches = props.routerState.matches();
|
|
1543
|
+
const m = routeMatches[i];
|
|
1544
|
+
return m && m.route.key === routeKey ? routeMatches : prev || nextMatches;
|
|
1545
|
+
});
|
|
1546
|
+
next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()?.[i + 1]), () => matchesAtLevel()[i], matchesAtLevel);
|
|
1547
|
+
}));
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
disposers.splice(nextMatches.length).forEach(dispose => dispose());
|
|
1551
|
+
if (prev && equal) {
|
|
1552
|
+
prevMatches = nextMatches;
|
|
1553
|
+
return prev;
|
|
1554
|
+
}
|
|
1555
|
+
root = next[0];
|
|
1556
|
+
prevMatches = nextMatches;
|
|
1557
|
+
return next;
|
|
1558
|
+
});
|
|
1559
|
+
const outlet = createOutlet(() => routeStates() && root);
|
|
1560
|
+
return memo(outlet);
|
|
1561
|
+
}
|
|
1562
|
+
const createOutlet = child => {
|
|
1563
|
+
return () => {
|
|
1564
|
+
const c = child();
|
|
1565
|
+
if (c) {
|
|
1566
|
+
return createComponent$1(RouteContextObj, {
|
|
1567
|
+
value: c,
|
|
1568
|
+
get children() {
|
|
1569
|
+
return c.outlet();
|
|
1570
|
+
}
|
|
1571
|
+
});
|
|
1572
|
+
}
|
|
1573
|
+
return undefined;
|
|
1574
|
+
};
|
|
1575
|
+
};
|
|
1576
|
+
const Route = props => {
|
|
1577
|
+
const childRoutes = children(() => props.children);
|
|
1578
|
+
return merge(props, {
|
|
1579
|
+
get children() {
|
|
1580
|
+
return childRoutes();
|
|
1581
|
+
}
|
|
1582
|
+
});
|
|
1583
|
+
};
|
|
1584
|
+
|
|
1585
|
+
// for data only mode with single flight mutations
|
|
1586
|
+
function dataOnly(event, routerState, branches) {
|
|
1587
|
+
const url = new URL(event.request.url);
|
|
1588
|
+
const prevMatches = getRouteMatches(branches, new URL(event.router.previousUrl || event.request.url).pathname);
|
|
1589
|
+
const matches = getRouteMatches(branches, url.pathname);
|
|
1590
|
+
for (let match = 0; match < matches.length; match++) {
|
|
1591
|
+
if (!prevMatches[match] || matches[match].route !== prevMatches[match].route) event.router.dataOnly = true;
|
|
1592
|
+
const {
|
|
1593
|
+
route,
|
|
1594
|
+
params
|
|
1595
|
+
} = matches[match];
|
|
1596
|
+
route.preload && route.preload({
|
|
1597
|
+
params,
|
|
1598
|
+
location: routerState.location,
|
|
1599
|
+
intent: "preload"
|
|
1600
|
+
});
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
function createRouter(config) {
|
|
1605
|
+
let ignore = false;
|
|
1606
|
+
const wrap = value => typeof value === "string" ? {
|
|
1607
|
+
value
|
|
1608
|
+
} : value;
|
|
1609
|
+
const [read, write] = createSignal(wrap(config.get()), {
|
|
1610
|
+
equals: (a, b) => a.value === b.value && a.state === b.state,
|
|
1611
|
+
ownedWrite: true
|
|
1612
|
+
});
|
|
1613
|
+
const signal = [read, next => {
|
|
1614
|
+
!ignore && config.set(next);
|
|
1615
|
+
if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = true;
|
|
1616
|
+
write(next);
|
|
1617
|
+
}];
|
|
1618
|
+
config.init && onCleanup(config.init((value = config.get()) => {
|
|
1619
|
+
ignore = true;
|
|
1620
|
+
signal[1](wrap(value));
|
|
1621
|
+
ignore = false;
|
|
1622
|
+
}));
|
|
1623
|
+
return createRouterComponent({
|
|
1624
|
+
signal,
|
|
1625
|
+
create: config.create,
|
|
1626
|
+
utils: config.utils
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1629
|
+
function bindEvent(target, type, handler) {
|
|
1630
|
+
target.addEventListener(type, handler);
|
|
1631
|
+
return () => target.removeEventListener(type, handler);
|
|
1632
|
+
}
|
|
1633
|
+
function scrollToHash(hash, fallbackTop) {
|
|
1634
|
+
const el = hash && document.getElementById(hash);
|
|
1635
|
+
if (el) {
|
|
1636
|
+
el.scrollIntoView();
|
|
1637
|
+
} else if (fallbackTop) {
|
|
1638
|
+
window.scrollTo(0, 0);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
function getPath(url) {
|
|
1643
|
+
const u = new URL(url);
|
|
1644
|
+
return u.pathname + u.search;
|
|
1645
|
+
}
|
|
1646
|
+
function StaticRouter(props) {
|
|
1647
|
+
let e;
|
|
1648
|
+
const obj = {
|
|
1649
|
+
value: props.url || (e = getRequestEvent()) && getPath(e.request.url) || ""
|
|
1650
|
+
};
|
|
1651
|
+
return createRouterComponent({
|
|
1652
|
+
signal: [() => obj, next => Object.assign(obj, next)]
|
|
1653
|
+
})(props);
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1506
1656
|
function setupNativeEvents({
|
|
1507
1657
|
preload = true,
|
|
1508
1658
|
explicitLinks = false,
|
|
@@ -1840,57 +1990,4 @@ function Navigate(props) {
|
|
|
1840
1990
|
return null;
|
|
1841
1991
|
}
|
|
1842
1992
|
|
|
1843
|
-
|
|
1844
|
-
let responseInit;
|
|
1845
|
-
let revalidate;
|
|
1846
|
-
if (typeof init === "number") {
|
|
1847
|
-
responseInit = {
|
|
1848
|
-
status: init
|
|
1849
|
-
};
|
|
1850
|
-
} else {
|
|
1851
|
-
({
|
|
1852
|
-
revalidate,
|
|
1853
|
-
...responseInit
|
|
1854
|
-
} = init);
|
|
1855
|
-
if (typeof responseInit.status === "undefined") {
|
|
1856
|
-
responseInit.status = 302;
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
const headers = new Headers(responseInit.headers);
|
|
1860
|
-
headers.set("Location", url);
|
|
1861
|
-
revalidate !== undefined && headers.set("X-Revalidate", revalidate.toString());
|
|
1862
|
-
const response = new Response(null, {
|
|
1863
|
-
...responseInit,
|
|
1864
|
-
headers: headers
|
|
1865
|
-
});
|
|
1866
|
-
return response;
|
|
1867
|
-
}
|
|
1868
|
-
function reload(init = {}) {
|
|
1869
|
-
const {
|
|
1870
|
-
revalidate,
|
|
1871
|
-
...responseInit
|
|
1872
|
-
} = init;
|
|
1873
|
-
const headers = new Headers(responseInit.headers);
|
|
1874
|
-
revalidate !== undefined && headers.set("X-Revalidate", revalidate.toString());
|
|
1875
|
-
return new Response(null, {
|
|
1876
|
-
...responseInit,
|
|
1877
|
-
headers
|
|
1878
|
-
});
|
|
1879
|
-
}
|
|
1880
|
-
function json(data, init = {}) {
|
|
1881
|
-
const {
|
|
1882
|
-
revalidate,
|
|
1883
|
-
...responseInit
|
|
1884
|
-
} = init;
|
|
1885
|
-
const headers = new Headers(responseInit.headers);
|
|
1886
|
-
revalidate !== undefined && headers.set("X-Revalidate", revalidate.toString());
|
|
1887
|
-
headers.set("Content-Type", "application/json");
|
|
1888
|
-
const response = new Response(JSON.stringify(data), {
|
|
1889
|
-
...responseInit,
|
|
1890
|
-
headers
|
|
1891
|
-
});
|
|
1892
|
-
response.customBody = () => data;
|
|
1893
|
-
return response;
|
|
1894
|
-
}
|
|
1895
|
-
|
|
1896
|
-
export { A, HashRouter, MemoryRouter, Navigate, Route, Router, RouterContextObj as RouterContext, StaticRouter, mergeSearchString as _mergeSearchString, action, createBeforeLeave, createMemoryHistory, createRouter, json, keepDepth, notifyIfNotBlocked, query, redirect, reload, revalidate, saveCurrentDepth, useAction, useBeforeLeave, useCurrentMatches, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, usePreloadRoute, useResolvedPath, useSearchParams, useSubmissions };
|
|
1993
|
+
export { A, HashRouter, MemoryRouter, Navigate, Route, Router, RouterContextObj as RouterContext, StaticRouter, mergeSearchString as _mergeSearchString, action, createBeforeLeave, createMemoryHistory, createRouter, keepDepth, notifyIfNotBlocked, query, revalidate, saveCurrentDepth, useAction, useBeforeLeave, useCurrentMatches, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, usePreloadRoute, useResolvedPath, useSearchParams, useSubmissions };
|