@tanstack/router-core 1.131.3 → 1.131.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/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +7 -5
- package/dist/cjs/router.cjs +66 -74
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-client.cjs +22 -25
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
- package/dist/esm/Matches.d.ts +7 -5
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/router.js +66 -74
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/ssr/ssr-client.js +22 -25
- package/dist/esm/ssr/ssr-client.js.map +1 -1
- package/package.json +1 -1
- package/src/Matches.ts +13 -9
- package/src/router.ts +65 -76
- package/src/ssr/ssr-client.ts +25 -27
|
@@ -3,16 +3,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const invariant = require("tiny-invariant");
|
|
4
4
|
const store = require("@tanstack/store");
|
|
5
5
|
const utils = require("../utils.cjs");
|
|
6
|
-
function hydrateMatch(deyhydratedMatch) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
error: deyhydratedMatch.e
|
|
15
|
-
};
|
|
6
|
+
function hydrateMatch(match, deyhydratedMatch) {
|
|
7
|
+
match.id = deyhydratedMatch.i;
|
|
8
|
+
match.__beforeLoadContext = deyhydratedMatch.b;
|
|
9
|
+
match.loaderData = deyhydratedMatch.l;
|
|
10
|
+
match.status = deyhydratedMatch.s;
|
|
11
|
+
match.ssr = deyhydratedMatch.ssr;
|
|
12
|
+
match.updatedAt = deyhydratedMatch.u;
|
|
13
|
+
match.error = deyhydratedMatch.e;
|
|
16
14
|
}
|
|
17
15
|
async function hydrate(router) {
|
|
18
16
|
var _a, _b, _c;
|
|
@@ -36,15 +34,17 @@ async function hydrate(router) {
|
|
|
36
34
|
const pendingMinMs = route.options.pendingMinMs ?? router.options.defaultPendingMinMs;
|
|
37
35
|
if (pendingMinMs) {
|
|
38
36
|
const minPendingPromise = utils.createControlledPromise();
|
|
39
|
-
match.minPendingPromise = minPendingPromise;
|
|
37
|
+
match._nonReactive.minPendingPromise = minPendingPromise;
|
|
40
38
|
match._forcePending = true;
|
|
41
39
|
setTimeout(() => {
|
|
42
40
|
minPendingPromise.resolve();
|
|
43
|
-
router.updateMatch(match.id, (prev) =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
router.updateMatch(match.id, (prev) => {
|
|
42
|
+
prev._nonReactive.minPendingPromise = void 0;
|
|
43
|
+
return {
|
|
44
|
+
...prev,
|
|
45
|
+
_forcePending: void 0
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
48
|
}, pendingMinMs);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -54,15 +54,12 @@ async function hydrate(router) {
|
|
|
54
54
|
(d) => d.i === match.id
|
|
55
55
|
);
|
|
56
56
|
if (!dehydratedMatch) {
|
|
57
|
-
|
|
57
|
+
match._nonReactive.dehydrated = false;
|
|
58
|
+
match.ssr = false;
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
match._dehydrated = false;
|
|
63
|
-
} else {
|
|
64
|
-
match._dehydrated = true;
|
|
65
|
-
}
|
|
61
|
+
hydrateMatch(match, dehydratedMatch);
|
|
62
|
+
match._nonReactive.dehydrated = match.ssr !== false;
|
|
66
63
|
if (match.ssr === "data-only" || match.ssr === false) {
|
|
67
64
|
if (firstNonSsrMatchIndex === void 0) {
|
|
68
65
|
firstNonSsrMatchIndex = match.index;
|
|
@@ -120,7 +117,7 @@ async function hydrate(router) {
|
|
|
120
117
|
const hasSsrFalseMatches = matches.some((m) => m.ssr === false);
|
|
121
118
|
if (!hasSsrFalseMatches && !isSpaMode) {
|
|
122
119
|
matches.forEach((match) => {
|
|
123
|
-
match.
|
|
120
|
+
match._nonReactive.dehydrated = void 0;
|
|
124
121
|
});
|
|
125
122
|
return routeChunkPromise;
|
|
126
123
|
}
|
|
@@ -135,7 +132,7 @@ async function hydrate(router) {
|
|
|
135
132
|
);
|
|
136
133
|
setMatchForcePending(match);
|
|
137
134
|
match._displayPending = true;
|
|
138
|
-
match.displayPendingPromise = loadPromise;
|
|
135
|
+
match._nonReactive.displayPendingPromise = loadPromise;
|
|
139
136
|
loadPromise.then(() => {
|
|
140
137
|
store.batch(() => {
|
|
141
138
|
if (router.__store.state.status === "pending") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-client.cjs","sources":["../../../src/ssr/ssr-client.ts"],"sourcesContent":["import invariant from 'tiny-invariant'\nimport { batch } from '@tanstack/store'\nimport { createControlledPromise } from '../utils'\nimport type { AnyRouteMatch, MakeRouteMatch } from '../Matches'\nimport type { AnyRouter } from '../router'\nimport type { Manifest } from '../manifest'\nimport type { RouteContextOptions } from '../route'\nimport type { GLOBAL_TSR } from './ssr-server'\n\ndeclare global {\n interface Window {\n [GLOBAL_TSR]?: TsrSsrGlobal\n }\n}\n\nexport interface TsrSsrGlobal {\n router?: DehydratedRouter\n // clean scripts, shortened since this is sent for each streamed script\n c: () => void\n}\n\nfunction hydrateMatch(\n deyhydratedMatch: DehydratedMatch,\n): Partial<MakeRouteMatch> {\n return {\n id: deyhydratedMatch.i,\n __beforeLoadContext: deyhydratedMatch.b,\n loaderData: deyhydratedMatch.l,\n status: deyhydratedMatch.s,\n ssr: deyhydratedMatch.ssr,\n updatedAt: deyhydratedMatch.u,\n error: deyhydratedMatch.e,\n }\n}\nexport interface DehydratedMatch {\n i: MakeRouteMatch['id']\n b?: MakeRouteMatch['__beforeLoadContext']\n l?: MakeRouteMatch['loaderData']\n e?: MakeRouteMatch['error']\n u: MakeRouteMatch['updatedAt']\n s: MakeRouteMatch['status']\n ssr?: MakeRouteMatch['ssr']\n}\n\nexport interface DehydratedRouter {\n manifest: Manifest | undefined\n dehydratedData?: any\n lastMatchId?: string\n matches: Array<DehydratedMatch>\n}\n\nexport async function hydrate(router: AnyRouter): Promise<any> {\n invariant(\n window.$_TSR?.router,\n 'Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!',\n )\n\n const { manifest, dehydratedData, lastMatchId } = window.$_TSR.router\n\n router.ssr = {\n manifest,\n }\n\n // Hydrate the router state\n const matches = router.matchRoutes(router.state.location)\n\n // kick off loading the route chunks\n const routeChunkPromise = Promise.all(\n matches.map((match) => {\n const route = router.looseRoutesById[match.routeId]!\n return router.loadRouteChunk(route)\n }),\n )\n\n function setMatchForcePending(match: AnyRouteMatch) {\n // usually the minPendingPromise is created in the Match component if a pending match is rendered\n // however, this might be too late if the match synchronously resolves\n const route = router.looseRoutesById[match.routeId]!\n const pendingMinMs =\n route.options.pendingMinMs ?? router.options.defaultPendingMinMs\n if (pendingMinMs) {\n const minPendingPromise = createControlledPromise<void>()\n match.minPendingPromise = minPendingPromise\n match._forcePending = true\n\n setTimeout(() => {\n minPendingPromise.resolve()\n // We've handled the minPendingPromise, so we can delete it\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise: undefined,\n _forcePending: undefined,\n }))\n }, pendingMinMs)\n }\n }\n\n // Right after hydration and before the first render, we need to rehydrate each match\n // First step is to reyhdrate loaderData and __beforeLoadContext\n let firstNonSsrMatchIndex: number | undefined = undefined\n matches.forEach((match) => {\n const dehydratedMatch = window.$_TSR!.router!.matches.find(\n (d) => d.i === match.id,\n )\n if (!dehydratedMatch) {\n Object.assign(match, { dehydrated: false, ssr: false })\n return\n }\n\n Object.assign(match, hydrateMatch(dehydratedMatch))\n\n if (match.ssr === false) {\n match._dehydrated = false\n } else {\n match._dehydrated = true\n }\n\n if (match.ssr === 'data-only' || match.ssr === false) {\n if (firstNonSsrMatchIndex === undefined) {\n firstNonSsrMatchIndex = match.index\n setMatchForcePending(match)\n }\n }\n })\n\n router.__store.setState((s) => {\n return {\n ...s,\n matches,\n }\n })\n\n // Allow the user to handle custom hydration data\n await router.options.hydrate?.(dehydratedData)\n\n // now that all necessary data is hydrated:\n // 1) fully reconstruct the route context\n // 2) execute `head()` and `scripts()` for each match\n await Promise.all(\n router.state.matches.map(async (match) => {\n const route = router.looseRoutesById[match.routeId]!\n\n const parentMatch = router.state.matches[match.index - 1]\n const parentContext = parentMatch?.context ?? router.options.context ?? {}\n\n // `context()` was already executed by `matchRoutes`, however route context was not yet fully reconstructed\n // so run it again and merge route context\n const contextFnContext: RouteContextOptions<any, any, any, any> = {\n deps: match.loaderDeps,\n params: match.params,\n context: parentContext,\n location: router.state.location,\n navigate: (opts: any) =>\n router.navigate({ ...opts, _fromLocation: router.state.location }),\n buildLocation: router.buildLocation,\n cause: match.cause,\n abortController: match.abortController,\n preload: false,\n matches,\n }\n match.__routeContext = route.options.context?.(contextFnContext) ?? {}\n\n match.context = {\n ...parentContext,\n ...match.__routeContext,\n ...match.__beforeLoadContext,\n }\n\n const assetContext = {\n matches: router.state.matches,\n match,\n params: match.params,\n loaderData: match.loaderData,\n }\n const headFnContent = await route.options.head?.(assetContext)\n\n const scripts = await route.options.scripts?.(assetContext)\n\n match.meta = headFnContent?.meta\n match.links = headFnContent?.links\n match.headScripts = headFnContent?.scripts\n match.styles = headFnContent?.styles\n match.scripts = scripts\n }),\n )\n\n const isSpaMode = matches[matches.length - 1]!.id !== lastMatchId\n const hasSsrFalseMatches = matches.some((m) => m.ssr === false)\n // all matches have data from the server and we are not in SPA mode so we don't need to kick of router.load()\n if (!hasSsrFalseMatches && !isSpaMode) {\n matches.forEach((match) => {\n // remove the _dehydrate flag since we won't run router.load() which would remove it\n match._dehydrated = undefined\n })\n return routeChunkPromise\n }\n\n // schedule router.load() to run after the next tick so we can store the promise in the match before loading starts\n const loadPromise = Promise.resolve()\n .then(() => router.load())\n .catch((err) => {\n console.error('Error during router hydration:', err)\n })\n\n // in SPA mode we need to keep the first match below the root route pending until router.load() is finished\n // this will prevent that other pending components are rendered but hydration is not blocked\n if (isSpaMode) {\n const match = matches[1]\n invariant(\n match,\n 'Expected to find a match below the root match in SPA mode.',\n )\n setMatchForcePending(match)\n\n match._displayPending = true\n match.displayPendingPromise = loadPromise\n\n loadPromise.then(() => {\n batch(() => {\n // ensure router is not in status 'pending' anymore\n // this usually happens in Transitioner but if loading synchronously resolves,\n // Transitioner won't be rendered while loading so it cannot track the change from loading:true to loading:false\n if (router.__store.state.status === 'pending') {\n router.__store.setState((s) => ({\n ...s,\n status: 'idle',\n resolvedLocation: s.location,\n }))\n }\n // hide the pending component once the load is finished\n router.updateMatch(match.id, (prev) => {\n return {\n ...prev,\n _displayPending: undefined,\n displayPendingPromise: undefined,\n }\n })\n })\n })\n }\n return routeChunkPromise\n}\n"],"names":["createControlledPromise","_b","_a","_c","batch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ssr-client.cjs","sources":["../../../src/ssr/ssr-client.ts"],"sourcesContent":["import invariant from 'tiny-invariant'\nimport { batch } from '@tanstack/store'\nimport { createControlledPromise } from '../utils'\nimport type { AnyRouteMatch, MakeRouteMatch } from '../Matches'\nimport type { AnyRouter } from '../router'\nimport type { Manifest } from '../manifest'\nimport type { RouteContextOptions } from '../route'\nimport type { GLOBAL_TSR } from './ssr-server'\n\ndeclare global {\n interface Window {\n [GLOBAL_TSR]?: TsrSsrGlobal\n }\n}\n\nexport interface TsrSsrGlobal {\n router?: DehydratedRouter\n // clean scripts, shortened since this is sent for each streamed script\n c: () => void\n}\n\nfunction hydrateMatch(\n match: AnyRouteMatch,\n deyhydratedMatch: DehydratedMatch,\n): void {\n match.id = deyhydratedMatch.i\n match.__beforeLoadContext = deyhydratedMatch.b\n match.loaderData = deyhydratedMatch.l\n match.status = deyhydratedMatch.s\n match.ssr = deyhydratedMatch.ssr\n match.updatedAt = deyhydratedMatch.u\n match.error = deyhydratedMatch.e\n}\nexport interface DehydratedMatch {\n i: MakeRouteMatch['id']\n b?: MakeRouteMatch['__beforeLoadContext']\n l?: MakeRouteMatch['loaderData']\n e?: MakeRouteMatch['error']\n u: MakeRouteMatch['updatedAt']\n s: MakeRouteMatch['status']\n ssr?: MakeRouteMatch['ssr']\n}\n\nexport interface DehydratedRouter {\n manifest: Manifest | undefined\n dehydratedData?: any\n lastMatchId?: string\n matches: Array<DehydratedMatch>\n}\n\nexport async function hydrate(router: AnyRouter): Promise<any> {\n invariant(\n window.$_TSR?.router,\n 'Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!',\n )\n\n const { manifest, dehydratedData, lastMatchId } = window.$_TSR.router\n\n router.ssr = {\n manifest,\n }\n\n // Hydrate the router state\n const matches = router.matchRoutes(router.state.location)\n\n // kick off loading the route chunks\n const routeChunkPromise = Promise.all(\n matches.map((match) => {\n const route = router.looseRoutesById[match.routeId]!\n return router.loadRouteChunk(route)\n }),\n )\n\n function setMatchForcePending(match: AnyRouteMatch) {\n // usually the minPendingPromise is created in the Match component if a pending match is rendered\n // however, this might be too late if the match synchronously resolves\n const route = router.looseRoutesById[match.routeId]!\n const pendingMinMs =\n route.options.pendingMinMs ?? router.options.defaultPendingMinMs\n if (pendingMinMs) {\n const minPendingPromise = createControlledPromise<void>()\n match._nonReactive.minPendingPromise = minPendingPromise\n match._forcePending = true\n\n setTimeout(() => {\n minPendingPromise.resolve()\n // We've handled the minPendingPromise, so we can delete it\n router.updateMatch(match.id, (prev) => {\n prev._nonReactive.minPendingPromise = undefined\n return {\n ...prev,\n _forcePending: undefined,\n }\n })\n }, pendingMinMs)\n }\n }\n\n // Right after hydration and before the first render, we need to rehydrate each match\n // First step is to reyhdrate loaderData and __beforeLoadContext\n let firstNonSsrMatchIndex: number | undefined = undefined\n matches.forEach((match) => {\n const dehydratedMatch = window.$_TSR!.router!.matches.find(\n (d) => d.i === match.id,\n )\n if (!dehydratedMatch) {\n match._nonReactive.dehydrated = false\n match.ssr = false\n return\n }\n\n hydrateMatch(match, dehydratedMatch)\n\n match._nonReactive.dehydrated = match.ssr !== false\n\n if (match.ssr === 'data-only' || match.ssr === false) {\n if (firstNonSsrMatchIndex === undefined) {\n firstNonSsrMatchIndex = match.index\n setMatchForcePending(match)\n }\n }\n })\n\n router.__store.setState((s) => {\n return {\n ...s,\n matches,\n }\n })\n\n // Allow the user to handle custom hydration data\n await router.options.hydrate?.(dehydratedData)\n\n // now that all necessary data is hydrated:\n // 1) fully reconstruct the route context\n // 2) execute `head()` and `scripts()` for each match\n await Promise.all(\n router.state.matches.map(async (match) => {\n const route = router.looseRoutesById[match.routeId]!\n\n const parentMatch = router.state.matches[match.index - 1]\n const parentContext = parentMatch?.context ?? router.options.context ?? {}\n\n // `context()` was already executed by `matchRoutes`, however route context was not yet fully reconstructed\n // so run it again and merge route context\n const contextFnContext: RouteContextOptions<any, any, any, any> = {\n deps: match.loaderDeps,\n params: match.params,\n context: parentContext,\n location: router.state.location,\n navigate: (opts: any) =>\n router.navigate({ ...opts, _fromLocation: router.state.location }),\n buildLocation: router.buildLocation,\n cause: match.cause,\n abortController: match.abortController,\n preload: false,\n matches,\n }\n match.__routeContext = route.options.context?.(contextFnContext) ?? {}\n\n match.context = {\n ...parentContext,\n ...match.__routeContext,\n ...match.__beforeLoadContext,\n }\n\n const assetContext = {\n matches: router.state.matches,\n match,\n params: match.params,\n loaderData: match.loaderData,\n }\n const headFnContent = await route.options.head?.(assetContext)\n\n const scripts = await route.options.scripts?.(assetContext)\n\n match.meta = headFnContent?.meta\n match.links = headFnContent?.links\n match.headScripts = headFnContent?.scripts\n match.styles = headFnContent?.styles\n match.scripts = scripts\n }),\n )\n\n const isSpaMode = matches[matches.length - 1]!.id !== lastMatchId\n const hasSsrFalseMatches = matches.some((m) => m.ssr === false)\n // all matches have data from the server and we are not in SPA mode so we don't need to kick of router.load()\n if (!hasSsrFalseMatches && !isSpaMode) {\n matches.forEach((match) => {\n // remove the dehydrated flag since we won't run router.load() which would remove it\n match._nonReactive.dehydrated = undefined\n })\n return routeChunkPromise\n }\n\n // schedule router.load() to run after the next tick so we can store the promise in the match before loading starts\n const loadPromise = Promise.resolve()\n .then(() => router.load())\n .catch((err) => {\n console.error('Error during router hydration:', err)\n })\n\n // in SPA mode we need to keep the first match below the root route pending until router.load() is finished\n // this will prevent that other pending components are rendered but hydration is not blocked\n if (isSpaMode) {\n const match = matches[1]\n invariant(\n match,\n 'Expected to find a match below the root match in SPA mode.',\n )\n setMatchForcePending(match)\n\n match._displayPending = true\n match._nonReactive.displayPendingPromise = loadPromise\n\n loadPromise.then(() => {\n batch(() => {\n // ensure router is not in status 'pending' anymore\n // this usually happens in Transitioner but if loading synchronously resolves,\n // Transitioner won't be rendered while loading so it cannot track the change from loading:true to loading:false\n if (router.__store.state.status === 'pending') {\n router.__store.setState((s) => ({\n ...s,\n status: 'idle',\n resolvedLocation: s.location,\n }))\n }\n // hide the pending component once the load is finished\n router.updateMatch(match.id, (prev) => {\n return {\n ...prev,\n _displayPending: undefined,\n displayPendingPromise: undefined,\n }\n })\n })\n })\n }\n return routeChunkPromise\n}\n"],"names":["createControlledPromise","_b","_a","_c","batch"],"mappings":";;;;;AAqBA,SAAS,aACP,OACA,kBACM;AACN,QAAM,KAAK,iBAAiB;AAC5B,QAAM,sBAAsB,iBAAiB;AAC7C,QAAM,aAAa,iBAAiB;AACpC,QAAM,SAAS,iBAAiB;AAChC,QAAM,MAAM,iBAAiB;AAC7B,QAAM,YAAY,iBAAiB;AACnC,QAAM,QAAQ,iBAAiB;AACjC;AAkBA,eAAsB,QAAQ,QAAiC;;AAC7D;AAAA,KACE,YAAO,UAAP,mBAAc;AAAA,IACd;AAAA,EACF;AAEA,QAAM,EAAE,UAAU,gBAAgB,YAAY,IAAI,OAAO,MAAM;AAE/D,SAAO,MAAM;AAAA,IACX;AAAA,EACF;AAGA,QAAM,UAAU,OAAO,YAAY,OAAO,MAAM,QAAQ;AAGxD,QAAM,oBAAoB,QAAQ;AAAA,IAChC,QAAQ,IAAI,CAAC,UAAU;AACrB,YAAM,QAAQ,OAAO,gBAAgB,MAAM,OAAO;AAC3C,aAAA,OAAO,eAAe,KAAK;AAAA,IACnC,CAAA;AAAA,EACH;AAEA,WAAS,qBAAqB,OAAsB;AAGlD,UAAM,QAAQ,OAAO,gBAAgB,MAAM,OAAO;AAClD,UAAM,eACJ,MAAM,QAAQ,gBAAgB,OAAO,QAAQ;AAC/C,QAAI,cAAc;AAChB,YAAM,oBAAoBA,MAAAA,wBAA8B;AACxD,YAAM,aAAa,oBAAoB;AACvC,YAAM,gBAAgB;AAEtB,iBAAW,MAAM;AACf,0BAAkB,QAAQ;AAE1B,eAAO,YAAY,MAAM,IAAI,CAAC,SAAS;AACrC,eAAK,aAAa,oBAAoB;AAC/B,iBAAA;AAAA,YACL,GAAG;AAAA,YACH,eAAe;AAAA,UACjB;AAAA,QAAA,CACD;AAAA,SACA,YAAY;AAAA,IAAA;AAAA,EACjB;AAKF,MAAI,wBAA4C;AACxC,UAAA,QAAQ,CAAC,UAAU;AACzB,UAAM,kBAAkB,OAAO,MAAO,OAAQ,QAAQ;AAAA,MACpD,CAAC,MAAM,EAAE,MAAM,MAAM;AAAA,IACvB;AACA,QAAI,CAAC,iBAAiB;AACpB,YAAM,aAAa,aAAa;AAChC,YAAM,MAAM;AACZ;AAAA,IAAA;AAGF,iBAAa,OAAO,eAAe;AAE7B,UAAA,aAAa,aAAa,MAAM,QAAQ;AAE9C,QAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,OAAO;AACpD,UAAI,0BAA0B,QAAW;AACvC,gCAAwB,MAAM;AAC9B,6BAAqB,KAAK;AAAA,MAAA;AAAA,IAC5B;AAAA,EACF,CACD;AAEM,SAAA,QAAQ,SAAS,CAAC,MAAM;AACtB,WAAA;AAAA,MACL,GAAG;AAAA,MACH;AAAA,IACF;AAAA,EAAA,CACD;AAGK,UAAA,kBAAO,SAAQ,YAAf,4BAAyB;AAK/B,QAAM,QAAQ;AAAA,IACZ,OAAO,MAAM,QAAQ,IAAI,OAAO,UAAU;;AACxC,YAAM,QAAQ,OAAO,gBAAgB,MAAM,OAAO;AAElD,YAAM,cAAc,OAAO,MAAM,QAAQ,MAAM,QAAQ,CAAC;AACxD,YAAM,iBAAgB,2CAAa,YAAW,OAAO,QAAQ,WAAW,CAAC;AAIzE,YAAM,mBAA4D;AAAA,QAChE,MAAM,MAAM;AAAA,QACZ,QAAQ,MAAM;AAAA,QACd,SAAS;AAAA,QACT,UAAU,OAAO,MAAM;AAAA,QACvB,UAAU,CAAC,SACT,OAAO,SAAS,EAAE,GAAG,MAAM,eAAe,OAAO,MAAM,SAAA,CAAU;AAAA,QACnE,eAAe,OAAO;AAAA,QACtB,OAAO,MAAM;AAAA,QACb,iBAAiB,MAAM;AAAA,QACvB,SAAS;AAAA,QACT;AAAA,MACF;AACA,YAAM,mBAAiBC,OAAAC,MAAA,MAAM,SAAQ,YAAd,gBAAAD,IAAA,KAAAC,KAAwB,sBAAqB,CAAC;AAErE,YAAM,UAAU;AAAA,QACd,GAAG;AAAA,QACH,GAAG,MAAM;AAAA,QACT,GAAG,MAAM;AAAA,MACX;AAEA,YAAM,eAAe;AAAA,QACnB,SAAS,OAAO,MAAM;AAAA,QACtB;AAAA,QACA,QAAQ,MAAM;AAAA,QACd,YAAY,MAAM;AAAA,MACpB;AACA,YAAM,gBAAgB,QAAM,MAAAC,MAAA,MAAM,SAAQ,SAAd,wBAAAA,KAAqB;AAEjD,YAAM,UAAU,QAAM,iBAAM,SAAQ,YAAd,4BAAwB;AAE9C,YAAM,OAAO,+CAAe;AAC5B,YAAM,QAAQ,+CAAe;AAC7B,YAAM,cAAc,+CAAe;AACnC,YAAM,SAAS,+CAAe;AAC9B,YAAM,UAAU;AAAA,IACjB,CAAA;AAAA,EACH;AAEA,QAAM,YAAY,QAAQ,QAAQ,SAAS,CAAC,EAAG,OAAO;AACtD,QAAM,qBAAqB,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAQ,KAAK;AAE1D,MAAA,CAAC,sBAAsB,CAAC,WAAW;AAC7B,YAAA,QAAQ,CAAC,UAAU;AAEzB,YAAM,aAAa,aAAa;AAAA,IAAA,CACjC;AACM,WAAA;AAAA,EAAA;AAIT,QAAM,cAAc,QAAQ,QAAQ,EACjC,KAAK,MAAM,OAAO,KAAM,CAAA,EACxB,MAAM,CAAC,QAAQ;AACN,YAAA,MAAM,kCAAkC,GAAG;AAAA,EAAA,CACpD;AAIH,MAAI,WAAW;AACP,UAAA,QAAQ,QAAQ,CAAC;AACvB;AAAA,MACE;AAAA,MACA;AAAA,IACF;AACA,yBAAqB,KAAK;AAE1B,UAAM,kBAAkB;AACxB,UAAM,aAAa,wBAAwB;AAE3C,gBAAY,KAAK,MAAM;AACrBC,YAAAA,MAAM,MAAM;AAIV,YAAI,OAAO,QAAQ,MAAM,WAAW,WAAW;AACtC,iBAAA,QAAQ,SAAS,CAAC,OAAO;AAAA,YAC9B,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,kBAAkB,EAAE;AAAA,UAAA,EACpB;AAAA,QAAA;AAGJ,eAAO,YAAY,MAAM,IAAI,CAAC,SAAS;AAC9B,iBAAA;AAAA,YACL,GAAG;AAAA,YACH,iBAAiB;AAAA,YACjB,uBAAuB;AAAA,UACzB;AAAA,QAAA,CACD;AAAA,MAAA,CACF;AAAA,IAAA,CACF;AAAA,EAAA;AAEI,SAAA;AACT;;"}
|
package/dist/esm/Matches.d.ts
CHANGED
|
@@ -52,7 +52,12 @@ export interface RouteMatch<out TRouteId, out TFullPath, out TAllParams, out TFu
|
|
|
52
52
|
paramsError: unknown;
|
|
53
53
|
searchError: unknown;
|
|
54
54
|
updatedAt: number;
|
|
55
|
-
|
|
55
|
+
_nonReactive: {
|
|
56
|
+
loadPromise?: ControlledPromise<void>;
|
|
57
|
+
displayPendingPromise?: Promise<void>;
|
|
58
|
+
minPendingPromise?: ControlledPromise<void>;
|
|
59
|
+
dehydrated?: boolean;
|
|
60
|
+
};
|
|
56
61
|
loaderData?: TLoaderData;
|
|
57
62
|
context: TAllContext;
|
|
58
63
|
search: TFullSearchSchema;
|
|
@@ -66,12 +71,9 @@ export interface RouteMatch<out TRouteId, out TFullPath, out TAllParams, out TFu
|
|
|
66
71
|
headers?: Record<string, string>;
|
|
67
72
|
globalNotFound?: boolean;
|
|
68
73
|
staticData: StaticDataRouteOption;
|
|
69
|
-
|
|
70
|
-
pendingTimeout?: ReturnType<typeof setTimeout>;
|
|
74
|
+
/** This attribute is not reactive */
|
|
71
75
|
ssr?: boolean | 'data-only';
|
|
72
|
-
_dehydrated?: boolean;
|
|
73
76
|
_forcePending?: boolean;
|
|
74
|
-
displayPendingPromise?: Promise<void>;
|
|
75
77
|
_displayPending?: boolean;
|
|
76
78
|
}
|
|
77
79
|
export interface PreValidationErrorHandlingRouteMatch<TRouteId, TFullPath, TAllParams, TFullSearchSchema> {
|
package/dist/esm/Matches.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Matches.js","sources":["../../src/Matches.ts"],"sourcesContent":["import type { AnyRoute, StaticDataRouteOption } from './route'\nimport type {\n AllContext,\n AllLoaderData,\n AllParams,\n FullSearchSchema,\n ParseRoute,\n RouteById,\n RouteIds,\n} from './routeInfo'\nimport type { AnyRouter, RegisteredRouter } from './router'\nimport type { Constrain, ControlledPromise } from './utils'\n\nexport type AnyMatchAndValue = { match: any; value: any }\n\nexport type FindValueByIndex<\n TKey,\n TValue extends ReadonlyArray<any>,\n> = TKey extends `${infer TIndex extends number}` ? TValue[TIndex] : never\n\nexport type FindValueByKey<TKey, TValue> =\n TValue extends ReadonlyArray<any>\n ? FindValueByIndex<TKey, TValue>\n : TValue[TKey & keyof TValue]\n\nexport type CreateMatchAndValue<TMatch, TValue> = TValue extends any\n ? {\n match: TMatch\n value: TValue\n }\n : never\n\nexport type NextMatchAndValue<\n TKey,\n TMatchAndValue extends AnyMatchAndValue,\n> = TMatchAndValue extends any\n ? CreateMatchAndValue<\n TMatchAndValue['match'],\n FindValueByKey<TKey, TMatchAndValue['value']>\n >\n : never\n\nexport type IsMatchKeyOf<TValue> =\n TValue extends ReadonlyArray<any>\n ? number extends TValue['length']\n ? `${number}`\n : keyof TValue & `${number}`\n : TValue extends object\n ? keyof TValue & string\n : never\n\nexport type IsMatchPath<\n TParentPath extends string,\n TMatchAndValue extends AnyMatchAndValue,\n> = `${TParentPath}${IsMatchKeyOf<TMatchAndValue['value']>}`\n\nexport type IsMatchResult<\n TKey,\n TMatchAndValue extends AnyMatchAndValue,\n> = TMatchAndValue extends any\n ? TKey extends keyof TMatchAndValue['value']\n ? TMatchAndValue['match']\n : never\n : never\n\nexport type IsMatchParse<\n TPath,\n TMatchAndValue extends AnyMatchAndValue,\n TParentPath extends string = '',\n> = TPath extends `${string}.${string}`\n ? TPath extends `${infer TFirst}.${infer TRest}`\n ? IsMatchParse<\n TRest,\n NextMatchAndValue<TFirst, TMatchAndValue>,\n `${TParentPath}${TFirst}.`\n >\n : never\n : {\n path: IsMatchPath<TParentPath, TMatchAndValue>\n result: IsMatchResult<TPath, TMatchAndValue>\n }\n\nexport type IsMatch<TMatch, TPath> = IsMatchParse<\n TPath,\n TMatch extends any ? { match: TMatch; value: TMatch } : never\n>\n\n/**\n * Narrows matches based on a path\n * @experimental\n */\nexport const isMatch = <TMatch, TPath extends string>(\n match: TMatch,\n path: Constrain<TPath, IsMatch<TMatch, TPath>['path']>,\n): match is IsMatch<TMatch, TPath>['result'] => {\n const parts = (path as string).split('.')\n let part\n let value: any = match\n\n while ((part = parts.shift()) != null && value != null) {\n value = value[part]\n }\n\n return value != null\n}\n\nexport interface DefaultRouteMatchExtensions {\n scripts?: unknown\n links?: unknown\n headScripts?: unknown\n meta?: unknown\n styles?: unknown\n}\n\nexport interface RouteMatchExtensions extends DefaultRouteMatchExtensions {}\n\nexport interface RouteMatch<\n out TRouteId,\n out TFullPath,\n out TAllParams,\n out TFullSearchSchema,\n out TLoaderData,\n out TAllContext,\n out TLoaderDeps,\n> extends RouteMatchExtensions {\n id: string\n routeId: TRouteId\n fullPath: TFullPath\n index: number\n pathname: string\n params: TAllParams\n _strictParams: TAllParams\n status: 'pending' | 'success' | 'error' | 'redirected' | 'notFound'\n isFetching: false | 'beforeLoad' | 'loader'\n error: unknown\n paramsError: unknown\n searchError: unknown\n updatedAt: number\n
|
|
1
|
+
{"version":3,"file":"Matches.js","sources":["../../src/Matches.ts"],"sourcesContent":["import type { AnyRoute, StaticDataRouteOption } from './route'\nimport type {\n AllContext,\n AllLoaderData,\n AllParams,\n FullSearchSchema,\n ParseRoute,\n RouteById,\n RouteIds,\n} from './routeInfo'\nimport type { AnyRouter, RegisteredRouter } from './router'\nimport type { Constrain, ControlledPromise } from './utils'\n\nexport type AnyMatchAndValue = { match: any; value: any }\n\nexport type FindValueByIndex<\n TKey,\n TValue extends ReadonlyArray<any>,\n> = TKey extends `${infer TIndex extends number}` ? TValue[TIndex] : never\n\nexport type FindValueByKey<TKey, TValue> =\n TValue extends ReadonlyArray<any>\n ? FindValueByIndex<TKey, TValue>\n : TValue[TKey & keyof TValue]\n\nexport type CreateMatchAndValue<TMatch, TValue> = TValue extends any\n ? {\n match: TMatch\n value: TValue\n }\n : never\n\nexport type NextMatchAndValue<\n TKey,\n TMatchAndValue extends AnyMatchAndValue,\n> = TMatchAndValue extends any\n ? CreateMatchAndValue<\n TMatchAndValue['match'],\n FindValueByKey<TKey, TMatchAndValue['value']>\n >\n : never\n\nexport type IsMatchKeyOf<TValue> =\n TValue extends ReadonlyArray<any>\n ? number extends TValue['length']\n ? `${number}`\n : keyof TValue & `${number}`\n : TValue extends object\n ? keyof TValue & string\n : never\n\nexport type IsMatchPath<\n TParentPath extends string,\n TMatchAndValue extends AnyMatchAndValue,\n> = `${TParentPath}${IsMatchKeyOf<TMatchAndValue['value']>}`\n\nexport type IsMatchResult<\n TKey,\n TMatchAndValue extends AnyMatchAndValue,\n> = TMatchAndValue extends any\n ? TKey extends keyof TMatchAndValue['value']\n ? TMatchAndValue['match']\n : never\n : never\n\nexport type IsMatchParse<\n TPath,\n TMatchAndValue extends AnyMatchAndValue,\n TParentPath extends string = '',\n> = TPath extends `${string}.${string}`\n ? TPath extends `${infer TFirst}.${infer TRest}`\n ? IsMatchParse<\n TRest,\n NextMatchAndValue<TFirst, TMatchAndValue>,\n `${TParentPath}${TFirst}.`\n >\n : never\n : {\n path: IsMatchPath<TParentPath, TMatchAndValue>\n result: IsMatchResult<TPath, TMatchAndValue>\n }\n\nexport type IsMatch<TMatch, TPath> = IsMatchParse<\n TPath,\n TMatch extends any ? { match: TMatch; value: TMatch } : never\n>\n\n/**\n * Narrows matches based on a path\n * @experimental\n */\nexport const isMatch = <TMatch, TPath extends string>(\n match: TMatch,\n path: Constrain<TPath, IsMatch<TMatch, TPath>['path']>,\n): match is IsMatch<TMatch, TPath>['result'] => {\n const parts = (path as string).split('.')\n let part\n let value: any = match\n\n while ((part = parts.shift()) != null && value != null) {\n value = value[part]\n }\n\n return value != null\n}\n\nexport interface DefaultRouteMatchExtensions {\n scripts?: unknown\n links?: unknown\n headScripts?: unknown\n meta?: unknown\n styles?: unknown\n}\n\nexport interface RouteMatchExtensions extends DefaultRouteMatchExtensions {}\n\nexport interface RouteMatch<\n out TRouteId,\n out TFullPath,\n out TAllParams,\n out TFullSearchSchema,\n out TLoaderData,\n out TAllContext,\n out TLoaderDeps,\n> extends RouteMatchExtensions {\n id: string\n routeId: TRouteId\n fullPath: TFullPath\n index: number\n pathname: string\n params: TAllParams\n _strictParams: TAllParams\n status: 'pending' | 'success' | 'error' | 'redirected' | 'notFound'\n isFetching: false | 'beforeLoad' | 'loader'\n error: unknown\n paramsError: unknown\n searchError: unknown\n updatedAt: number\n _nonReactive: {\n /** @internal */\n beforeLoadPromise?: ControlledPromise<void>\n /** @internal */\n loaderPromise?: ControlledPromise<void>\n /** @internal */\n pendingTimeout?: ReturnType<typeof setTimeout>\n loadPromise?: ControlledPromise<void>\n displayPendingPromise?: Promise<void>\n minPendingPromise?: ControlledPromise<void>\n dehydrated?: boolean\n }\n loaderData?: TLoaderData\n /** @internal */\n __routeContext: Record<string, unknown>\n /** @internal */\n __beforeLoadContext?: Record<string, unknown>\n context: TAllContext\n search: TFullSearchSchema\n _strictSearch: TFullSearchSchema\n fetchCount: number\n abortController: AbortController\n cause: 'preload' | 'enter' | 'stay'\n loaderDeps: TLoaderDeps\n preload: boolean\n invalid: boolean\n headers?: Record<string, string>\n globalNotFound?: boolean\n staticData: StaticDataRouteOption\n /** This attribute is not reactive */\n ssr?: boolean | 'data-only'\n _forcePending?: boolean\n _displayPending?: boolean\n}\n\nexport interface PreValidationErrorHandlingRouteMatch<\n TRouteId,\n TFullPath,\n TAllParams,\n TFullSearchSchema,\n> {\n id: string\n routeId: TRouteId\n fullPath: TFullPath\n index: number\n pathname: string\n search:\n | { status: 'success'; value: TFullSearchSchema }\n | { status: 'error'; error: unknown }\n params:\n | { status: 'success'; value: TAllParams }\n | { status: 'error'; error: unknown }\n staticData: StaticDataRouteOption\n ssr?: boolean | 'data-only'\n}\n\nexport type MakePreValidationErrorHandlingRouteMatchUnion<\n TRouter extends AnyRouter = RegisteredRouter,\n TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>,\n> = TRoute extends any\n ? PreValidationErrorHandlingRouteMatch<\n TRoute['id'],\n TRoute['fullPath'],\n TRoute['types']['allParams'],\n TRoute['types']['fullSearchSchema']\n >\n : never\n\nexport type MakeRouteMatchFromRoute<TRoute extends AnyRoute> = RouteMatch<\n TRoute['types']['id'],\n TRoute['types']['fullPath'],\n TRoute['types']['allParams'],\n TRoute['types']['fullSearchSchema'],\n TRoute['types']['loaderData'],\n TRoute['types']['allContext'],\n TRoute['types']['loaderDeps']\n>\n\nexport type MakeRouteMatch<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TRouteId = RouteIds<TRouteTree>,\n TStrict extends boolean = true,\n> = RouteMatch<\n TRouteId,\n RouteById<TRouteTree, TRouteId>['types']['fullPath'],\n TStrict extends false\n ? AllParams<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['allParams'],\n TStrict extends false\n ? FullSearchSchema<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema'],\n TStrict extends false\n ? AllLoaderData<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['loaderData'],\n TStrict extends false\n ? AllContext<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['allContext'],\n RouteById<TRouteTree, TRouteId>['types']['loaderDeps']\n>\n\nexport type AnyRouteMatch = RouteMatch<any, any, any, any, any, any, any>\n\nexport type MakeRouteMatchUnion<\n TRouter extends AnyRouter = RegisteredRouter,\n TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>,\n> = TRoute extends any\n ? RouteMatch<\n TRoute['id'],\n TRoute['fullPath'],\n TRoute['types']['allParams'],\n TRoute['types']['fullSearchSchema'],\n TRoute['types']['loaderData'],\n TRoute['types']['allContext'],\n TRoute['types']['loaderDeps']\n >\n : never\n\n/**\n * The `MatchRouteOptions` type is used to describe the options that can be used when matching a route.\n *\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/MatchRouteOptionsType#matchrouteoptions-type)\n */\nexport interface MatchRouteOptions {\n /**\n * If `true`, will match against pending location instead of the current location.\n *\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/MatchRouteOptionsType#pending-property)\n */\n pending?: boolean\n /**\n * If `true`, will match against the current location with case sensitivity.\n *\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/MatchRouteOptionsType#casesensitive-property)\n */\n caseSensitive?: boolean\n /**\n * If `true`, will match against the current location's search params using a deep inclusive check. e.g. `{ a: 1 }` will match for a current location of `{ a: 1, b: 2 }`.\n *\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/MatchRouteOptionsType#includesearch-property)\n */\n includeSearch?: boolean\n /**\n * If `true`, will match against the current location using a fuzzy match. e.g. `/posts` will match for a current location of `/posts/123`.\n *\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/MatchRouteOptionsType#fuzzy-property)\n */\n fuzzy?: boolean\n}\n"],"names":[],"mappings":"AA2Fa,MAAA,UAAU,CACrB,OACA,SAC8C;AACxC,QAAA,QAAS,KAAgB,MAAM,GAAG;AACpC,MAAA;AACJ,MAAI,QAAa;AAEjB,UAAQ,OAAO,MAAM,MAAY,MAAA,QAAQ,SAAS,MAAM;AACtD,YAAQ,MAAM,IAAI;AAAA,EAAA;AAGpB,SAAO,SAAS;AAClB;"}
|
package/dist/esm/router.js
CHANGED
|
@@ -217,13 +217,8 @@ class RouterCore {
|
|
|
217
217
|
const match = this.getMatch(id);
|
|
218
218
|
if (!match) return;
|
|
219
219
|
match.abortController.abort();
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return {
|
|
223
|
-
...prev,
|
|
224
|
-
pendingTimeout: void 0
|
|
225
|
-
};
|
|
226
|
-
});
|
|
220
|
+
match._nonReactive.pendingTimeout = void 0;
|
|
221
|
+
clearTimeout(match._nonReactive.pendingTimeout);
|
|
227
222
|
};
|
|
228
223
|
this.cancelMatches = () => {
|
|
229
224
|
var _a;
|
|
@@ -743,20 +738,20 @@ class RouterCore {
|
|
|
743
738
|
}
|
|
744
739
|
}
|
|
745
740
|
}
|
|
746
|
-
(_a = match.beforeLoadPromise) == null ? void 0 : _a.resolve();
|
|
747
|
-
(_b = match.loaderPromise) == null ? void 0 : _b.resolve();
|
|
741
|
+
(_a = match._nonReactive.beforeLoadPromise) == null ? void 0 : _a.resolve();
|
|
742
|
+
(_b = match._nonReactive.loaderPromise) == null ? void 0 : _b.resolve();
|
|
743
|
+
match._nonReactive.beforeLoadPromise = void 0;
|
|
744
|
+
match._nonReactive.loaderPromise = void 0;
|
|
748
745
|
updateMatch(match.id, (prev) => ({
|
|
749
746
|
...prev,
|
|
750
747
|
status: isRedirect(err) ? "redirected" : isNotFound(err) ? "notFound" : "error",
|
|
751
748
|
isFetching: false,
|
|
752
|
-
error: err
|
|
753
|
-
beforeLoadPromise: void 0,
|
|
754
|
-
loaderPromise: void 0
|
|
749
|
+
error: err
|
|
755
750
|
}));
|
|
756
751
|
if (!err.routeId) {
|
|
757
752
|
err.routeId = match.routeId;
|
|
758
753
|
}
|
|
759
|
-
(_c = match.loadPromise) == null ? void 0 : _c.resolve();
|
|
754
|
+
(_c = match._nonReactive.loadPromise) == null ? void 0 : _c.resolve();
|
|
760
755
|
if (isRedirect(err)) {
|
|
761
756
|
rendered = true;
|
|
762
757
|
err.options._fromLocation = location;
|
|
@@ -773,7 +768,7 @@ class RouterCore {
|
|
|
773
768
|
};
|
|
774
769
|
const shouldSkipLoader = (matchId) => {
|
|
775
770
|
const match = this.getMatch(matchId);
|
|
776
|
-
if (!this.isServer && match.
|
|
771
|
+
if (!this.isServer && match._nonReactive.dehydrated) {
|
|
777
772
|
return true;
|
|
778
773
|
}
|
|
779
774
|
if (this.isServer) {
|
|
@@ -807,16 +802,16 @@ class RouterCore {
|
|
|
807
802
|
}
|
|
808
803
|
updateMatch(matchId, (prev) => {
|
|
809
804
|
var _a3, _b3;
|
|
810
|
-
(_a3 = prev.beforeLoadPromise) == null ? void 0 : _a3.resolve();
|
|
811
|
-
|
|
805
|
+
(_a3 = prev._nonReactive.beforeLoadPromise) == null ? void 0 : _a3.resolve();
|
|
806
|
+
prev._nonReactive.beforeLoadPromise = void 0;
|
|
807
|
+
(_b3 = prev._nonReactive.loadPromise) == null ? void 0 : _b3.resolve();
|
|
812
808
|
return {
|
|
813
809
|
...prev,
|
|
814
810
|
error: err,
|
|
815
811
|
status: "error",
|
|
816
812
|
isFetching: false,
|
|
817
813
|
updatedAt: Date.now(),
|
|
818
|
-
abortController: new AbortController()
|
|
819
|
-
beforeLoadPromise: void 0
|
|
814
|
+
abortController: new AbortController()
|
|
820
815
|
};
|
|
821
816
|
});
|
|
822
817
|
};
|
|
@@ -873,10 +868,7 @@ class RouterCore {
|
|
|
873
868
|
}
|
|
874
869
|
}
|
|
875
870
|
}
|
|
876
|
-
|
|
877
|
-
...prev,
|
|
878
|
-
ssr
|
|
879
|
-
}));
|
|
871
|
+
existingMatch.ssr = ssr;
|
|
880
872
|
}
|
|
881
873
|
if (shouldSkipLoader(matchId)) {
|
|
882
874
|
continue;
|
|
@@ -884,26 +876,24 @@ class RouterCore {
|
|
|
884
876
|
const shouldPending = !!(onReady && !this.isServer && !resolvePreload(matchId) && (route.options.loader || route.options.beforeLoad || routeNeedsPreload(route)) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? ((_b = this.options) == null ? void 0 : _b.defaultPendingComponent)));
|
|
885
877
|
let executeBeforeLoad = true;
|
|
886
878
|
const setupPendingTimeout = () => {
|
|
887
|
-
|
|
879
|
+
const match = this.getMatch(matchId);
|
|
880
|
+
if (shouldPending && match._nonReactive.pendingTimeout === void 0) {
|
|
888
881
|
const pendingTimeout = setTimeout(() => {
|
|
889
882
|
try {
|
|
890
883
|
triggerOnReady();
|
|
891
884
|
} catch {
|
|
892
885
|
}
|
|
893
886
|
}, pendingMs);
|
|
894
|
-
|
|
895
|
-
...prev,
|
|
896
|
-
pendingTimeout
|
|
897
|
-
}));
|
|
887
|
+
match._nonReactive.pendingTimeout = pendingTimeout;
|
|
898
888
|
}
|
|
899
889
|
};
|
|
900
890
|
if (
|
|
901
891
|
// If we are in the middle of a load, either of these will be present
|
|
902
892
|
// (not to be confused with `loadPromise`, which is always defined)
|
|
903
|
-
existingMatch.beforeLoadPromise || existingMatch.loaderPromise
|
|
893
|
+
existingMatch._nonReactive.beforeLoadPromise || existingMatch._nonReactive.loaderPromise
|
|
904
894
|
) {
|
|
905
895
|
setupPendingTimeout();
|
|
906
|
-
await existingMatch.beforeLoadPromise;
|
|
896
|
+
await existingMatch._nonReactive.beforeLoadPromise;
|
|
907
897
|
const match = this.getMatch(matchId);
|
|
908
898
|
if (match.status === "error") {
|
|
909
899
|
executeBeforeLoad = true;
|
|
@@ -913,15 +903,11 @@ class RouterCore {
|
|
|
913
903
|
}
|
|
914
904
|
if (executeBeforeLoad) {
|
|
915
905
|
try {
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
prevLoadPromise == null ? void 0 : prevLoadPromise.resolve();
|
|
922
|
-
}),
|
|
923
|
-
beforeLoadPromise: createControlledPromise()
|
|
924
|
-
};
|
|
906
|
+
const match = this.getMatch(matchId);
|
|
907
|
+
match._nonReactive.beforeLoadPromise = createControlledPromise();
|
|
908
|
+
const prevLoadPromise = match._nonReactive.loadPromise;
|
|
909
|
+
match._nonReactive.loadPromise = createControlledPromise(() => {
|
|
910
|
+
prevLoadPromise == null ? void 0 : prevLoadPromise.resolve();
|
|
925
911
|
});
|
|
926
912
|
const { paramsError, searchError } = this.getMatch(matchId);
|
|
927
913
|
if (paramsError) {
|
|
@@ -978,10 +964,10 @@ class RouterCore {
|
|
|
978
964
|
}
|
|
979
965
|
updateMatch(matchId, (prev) => {
|
|
980
966
|
var _a2;
|
|
981
|
-
(_a2 = prev.beforeLoadPromise) == null ? void 0 : _a2.resolve();
|
|
967
|
+
(_a2 = prev._nonReactive.beforeLoadPromise) == null ? void 0 : _a2.resolve();
|
|
968
|
+
prev._nonReactive.beforeLoadPromise = void 0;
|
|
982
969
|
return {
|
|
983
970
|
...prev,
|
|
984
|
-
beforeLoadPromise: void 0,
|
|
985
971
|
isFetching: false
|
|
986
972
|
};
|
|
987
973
|
});
|
|
@@ -992,11 +978,12 @@ class RouterCore {
|
|
|
992
978
|
validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
|
|
993
979
|
matchPromises.push(
|
|
994
980
|
(async () => {
|
|
981
|
+
var _a2, _b2;
|
|
995
982
|
let loaderShouldRunAsync = false;
|
|
996
983
|
let loaderIsRunningAsync = false;
|
|
997
984
|
const route = this.looseRoutesById[routeId];
|
|
998
985
|
const executeHead = async () => {
|
|
999
|
-
var
|
|
986
|
+
var _a3, _b3, _c2, _d2, _e, _f;
|
|
1000
987
|
const match = this.getMatch(matchId);
|
|
1001
988
|
if (!match) {
|
|
1002
989
|
return;
|
|
@@ -1007,7 +994,7 @@ class RouterCore {
|
|
|
1007
994
|
params: match.params,
|
|
1008
995
|
loaderData: match.loaderData
|
|
1009
996
|
};
|
|
1010
|
-
const headFnContent = await ((
|
|
997
|
+
const headFnContent = await ((_b3 = (_a3 = route.options).head) == null ? void 0 : _b3.call(_a3, assetContext));
|
|
1011
998
|
const meta = headFnContent == null ? void 0 : headFnContent.meta;
|
|
1012
999
|
const links = headFnContent == null ? void 0 : headFnContent.links;
|
|
1013
1000
|
const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
|
|
@@ -1025,8 +1012,8 @@ class RouterCore {
|
|
|
1025
1012
|
};
|
|
1026
1013
|
const potentialPendingMinPromise = async () => {
|
|
1027
1014
|
const latestMatch = this.getMatch(matchId);
|
|
1028
|
-
if (latestMatch.minPendingPromise) {
|
|
1029
|
-
await latestMatch.minPendingPromise;
|
|
1015
|
+
if (latestMatch._nonReactive.minPendingPromise) {
|
|
1016
|
+
await latestMatch._nonReactive.minPendingPromise;
|
|
1030
1017
|
}
|
|
1031
1018
|
};
|
|
1032
1019
|
const prevMatch = this.getMatch(matchId);
|
|
@@ -1039,11 +1026,11 @@ class RouterCore {
|
|
|
1039
1026
|
}));
|
|
1040
1027
|
return this.getMatch(matchId);
|
|
1041
1028
|
}
|
|
1042
|
-
} else if (prevMatch.loaderPromise) {
|
|
1029
|
+
} else if (prevMatch._nonReactive.loaderPromise) {
|
|
1043
1030
|
if (prevMatch.status === "success" && !sync && !prevMatch.preload) {
|
|
1044
1031
|
return this.getMatch(matchId);
|
|
1045
1032
|
}
|
|
1046
|
-
await prevMatch.loaderPromise;
|
|
1033
|
+
await prevMatch._nonReactive.loaderPromise;
|
|
1047
1034
|
const match = this.getMatch(matchId);
|
|
1048
1035
|
if (match.error) {
|
|
1049
1036
|
handleRedirectAndNotFound(match, match.error);
|
|
@@ -1077,13 +1064,15 @@ class RouterCore {
|
|
|
1077
1064
|
const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
1078
1065
|
const shouldReloadOption = route.options.shouldReload;
|
|
1079
1066
|
const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext()) : shouldReloadOption;
|
|
1080
|
-
updateMatch(matchId, (prev) =>
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1067
|
+
updateMatch(matchId, (prev) => {
|
|
1068
|
+
prev._nonReactive.loaderPromise = createControlledPromise();
|
|
1069
|
+
return {
|
|
1070
|
+
...prev,
|
|
1071
|
+
preload: !!preload && !this.state.matches.some((d) => d.id === matchId)
|
|
1072
|
+
};
|
|
1073
|
+
});
|
|
1085
1074
|
const runLoader = async () => {
|
|
1086
|
-
var
|
|
1075
|
+
var _a3, _b3, _c2, _d2;
|
|
1087
1076
|
try {
|
|
1088
1077
|
try {
|
|
1089
1078
|
if (!this.isServer || this.isServer && this.getMatch(matchId).ssr === true) {
|
|
@@ -1093,7 +1082,7 @@ class RouterCore {
|
|
|
1093
1082
|
...prev,
|
|
1094
1083
|
isFetching: "loader"
|
|
1095
1084
|
}));
|
|
1096
|
-
const loaderData = await ((
|
|
1085
|
+
const loaderData = await ((_b3 = (_a3 = route.options).loader) == null ? void 0 : _b3.call(_a3, getLoaderContext()));
|
|
1097
1086
|
handleRedirectAndNotFound(
|
|
1098
1087
|
this.getMatch(matchId),
|
|
1099
1088
|
loaderData
|
|
@@ -1138,11 +1127,13 @@ class RouterCore {
|
|
|
1138
1127
|
}
|
|
1139
1128
|
} catch (err) {
|
|
1140
1129
|
const head = await executeHead();
|
|
1141
|
-
updateMatch(matchId, (prev) =>
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1130
|
+
updateMatch(matchId, (prev) => {
|
|
1131
|
+
prev._nonReactive.loaderPromise = void 0;
|
|
1132
|
+
return {
|
|
1133
|
+
...prev,
|
|
1134
|
+
...head
|
|
1135
|
+
};
|
|
1136
|
+
});
|
|
1146
1137
|
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
1147
1138
|
}
|
|
1148
1139
|
};
|
|
@@ -1152,15 +1143,13 @@ class RouterCore {
|
|
|
1152
1143
|
} else if (loaderShouldRunAsync && !sync) {
|
|
1153
1144
|
loaderIsRunningAsync = true;
|
|
1154
1145
|
(async () => {
|
|
1146
|
+
var _a3, _b3;
|
|
1155
1147
|
try {
|
|
1156
1148
|
await runLoader();
|
|
1157
|
-
const
|
|
1158
|
-
loaderPromise == null ? void 0 :
|
|
1159
|
-
loadPromise == null ? void 0 :
|
|
1160
|
-
|
|
1161
|
-
...prev,
|
|
1162
|
-
loaderPromise: void 0
|
|
1163
|
-
}));
|
|
1149
|
+
const match = this.getMatch(matchId);
|
|
1150
|
+
(_a3 = match._nonReactive.loaderPromise) == null ? void 0 : _a3.resolve();
|
|
1151
|
+
(_b3 = match._nonReactive.loadPromise) == null ? void 0 : _b3.resolve();
|
|
1152
|
+
match._nonReactive.loaderPromise = void 0;
|
|
1164
1153
|
} catch (err) {
|
|
1165
1154
|
if (isRedirect(err)) {
|
|
1166
1155
|
await this.navigate(err.options);
|
|
@@ -1178,19 +1167,20 @@ class RouterCore {
|
|
|
1178
1167
|
}
|
|
1179
1168
|
}
|
|
1180
1169
|
if (!loaderIsRunningAsync) {
|
|
1181
|
-
const
|
|
1182
|
-
loaderPromise == null ? void 0 :
|
|
1183
|
-
loadPromise == null ? void 0 :
|
|
1170
|
+
const match = this.getMatch(matchId);
|
|
1171
|
+
(_a2 = match._nonReactive.loaderPromise) == null ? void 0 : _a2.resolve();
|
|
1172
|
+
(_b2 = match._nonReactive.loadPromise) == null ? void 0 : _b2.resolve();
|
|
1184
1173
|
}
|
|
1185
1174
|
updateMatch(matchId, (prev) => {
|
|
1186
|
-
clearTimeout(prev.pendingTimeout);
|
|
1175
|
+
clearTimeout(prev._nonReactive.pendingTimeout);
|
|
1176
|
+
prev._nonReactive.pendingTimeout = void 0;
|
|
1177
|
+
if (!loaderIsRunningAsync)
|
|
1178
|
+
prev._nonReactive.loaderPromise = void 0;
|
|
1179
|
+
prev._nonReactive.dehydrated = void 0;
|
|
1187
1180
|
return {
|
|
1188
1181
|
...prev,
|
|
1189
1182
|
isFetching: loaderIsRunningAsync ? prev.isFetching : false,
|
|
1190
|
-
|
|
1191
|
-
invalid: false,
|
|
1192
|
-
pendingTimeout: void 0,
|
|
1193
|
-
_dehydrated: void 0
|
|
1183
|
+
invalid: false
|
|
1194
1184
|
};
|
|
1195
1185
|
});
|
|
1196
1186
|
return this.getMatch(matchId);
|
|
@@ -1606,6 +1596,9 @@ class RouterCore {
|
|
|
1606
1596
|
error: void 0,
|
|
1607
1597
|
paramsError: parseErrors[index],
|
|
1608
1598
|
__routeContext: {},
|
|
1599
|
+
_nonReactive: {
|
|
1600
|
+
loadPromise: createControlledPromise()
|
|
1601
|
+
},
|
|
1609
1602
|
__beforeLoadContext: void 0,
|
|
1610
1603
|
context: {},
|
|
1611
1604
|
abortController: new AbortController(),
|
|
@@ -1619,7 +1612,6 @@ class RouterCore {
|
|
|
1619
1612
|
headScripts: void 0,
|
|
1620
1613
|
meta: void 0,
|
|
1621
1614
|
staticData: route.options.staticData || {},
|
|
1622
|
-
loadPromise: createControlledPromise(),
|
|
1623
1615
|
fullPath: route.fullPath
|
|
1624
1616
|
};
|
|
1625
1617
|
}
|