@tanstack/router-core 1.161.1 → 1.161.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/location.d.cts +2 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/router.cjs +30 -26
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/esm/location.d.ts +2 -1
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.js +30 -26
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/package.json +6 -5
- package/src/location.ts +2 -1
- package/src/route.ts +1 -1
- package/src/router.ts +40 -26
- package/src/ssr/createRequestHandler.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createRequestHandler.js","sources":["../../../src/ssr/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from './headers'\nimport {\n attachRouterServerSsrUtils,\n getNormalizedURL,\n getOrigin,\n} from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyHeaders } from './headers'\nimport type { AnyRouter } from '../router'\nimport type { Manifest } from '../manifest'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n createRouter,\n request,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n request: Request\n getRouterManifest?: () => Manifest | Promise<Manifest>\n}): RequestHandler<TRouter> {\n return async (cb) => {\n const router = createRouter()\n // Track whether the callback will handle cleanup\n let cbWillCleanup = false\n\n try {\n attachRouterServerSsrUtils({\n router,\n manifest: await getRouterManifest?.(),\n })\n\n // normalizing and sanitizing the pathname here for server, so we always deal with the same format during SSR.\n const { url } = getNormalizedURL(request.url, 'http://localhost')\n const origin = getOrigin(request)\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n // Update the router with the history and context\n router.update({\n history,\n origin: router.options.origin ?? origin,\n })\n\n await router.load()\n\n await router.serverSsr?.dehydrate()\n\n const responseHeaders = getRequestHeaders({\n router,\n })\n\n // Mark that the callback will handle cleanup\n cbWillCleanup = true\n return cb({\n request,\n router,\n responseHeaders,\n }
|
|
1
|
+
{"version":3,"file":"createRequestHandler.js","sources":["../../../src/ssr/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from './headers'\nimport {\n attachRouterServerSsrUtils,\n getNormalizedURL,\n getOrigin,\n} from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyHeaders } from './headers'\nimport type { AnyRouter } from '../router'\nimport type { Manifest } from '../manifest'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n createRouter,\n request,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n request: Request\n getRouterManifest?: () => Manifest | Promise<Manifest>\n}): RequestHandler<TRouter> {\n return async (cb) => {\n const router = createRouter()\n // Track whether the callback will handle cleanup\n let cbWillCleanup = false\n\n try {\n attachRouterServerSsrUtils({\n router,\n manifest: await getRouterManifest?.(),\n })\n\n // normalizing and sanitizing the pathname here for server, so we always deal with the same format during SSR.\n const { url } = getNormalizedURL(request.url, 'http://localhost')\n const origin = getOrigin(request)\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n // Update the router with the history and context\n router.update({\n history,\n origin: router.options.origin ?? origin,\n })\n\n await router.load()\n\n await router.serverSsr?.dehydrate()\n\n const responseHeaders = getRequestHeaders({\n router,\n })\n\n // Mark that the callback will handle cleanup\n cbWillCleanup = true\n return cb({\n request,\n router,\n responseHeaders,\n })\n } finally {\n if (!cbWillCleanup) {\n // Clean up router SSR state if the callback won't handle it\n // (e.g., if an error occurred before the callback was invoked).\n // When the callback runs, it handles cleanup (either via transformStreamWithRouter\n // for streaming, or directly in renderRouterToString for non-streaming).\n router.serverSsr?.cleanup()\n }\n }\n }\n}\n\nfunction getRequestHeaders(opts: { router: AnyRouter }): Headers {\n const matchHeaders = opts.router.state.matches.map<AnyHeaders>(\n (match) => match.headers,\n )\n\n // Handle Redirects\n const { redirect } = opts.router.state\n if (redirect) {\n matchHeaders.push(redirect.headers)\n }\n\n return mergeHeaders(\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...matchHeaders,\n )\n}\n"],"names":[],"mappings":";;;AAgBO,SAAS,qBAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,SAAO,OAAO,OAAO;AACnB,UAAM,SAAS,aAAA;AAEf,QAAI,gBAAgB;AAEpB,QAAI;AACF,iCAA2B;AAAA,QACzB;AAAA,QACA,UAAU,MAAM,oBAAA;AAAA,MAAoB,CACrC;AAGD,YAAM,EAAE,IAAA,IAAQ,iBAAiB,QAAQ,KAAK,kBAAkB;AAChE,YAAM,SAAS,UAAU,OAAO;AAChC,YAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAG5C,YAAM,UAAU,oBAAoB;AAAA,QAClC,gBAAgB,CAAC,IAAI;AAAA,MAAA,CACtB;AAGD,aAAO,OAAO;AAAA,QACZ;AAAA,QACA,QAAQ,OAAO,QAAQ,UAAU;AAAA,MAAA,CAClC;AAED,YAAM,OAAO,KAAA;AAEb,YAAM,OAAO,WAAW,UAAA;AAExB,YAAM,kBAAkB,kBAAkB;AAAA,QACxC;AAAA,MAAA,CACD;AAGD,sBAAgB;AAChB,aAAO,GAAG;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH,UAAA;AACE,UAAI,CAAC,eAAe;AAKlB,eAAO,WAAW,QAAA;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,MAAsC;AAC/D,QAAM,eAAe,KAAK,OAAO,MAAM,QAAQ;AAAA,IAC7C,CAAC,UAAU,MAAM;AAAA,EAAA;AAInB,QAAM,EAAE,SAAA,IAAa,KAAK,OAAO;AACjC,MAAI,UAAU;AACZ,iBAAa,KAAK,SAAS,OAAO;AAAA,EACpC;AAEA,SAAO;AAAA,IACL;AAAA,MACE,gBAAgB;AAAA,IAAA;AAAA,IAElB,GAAG;AAAA,EAAA;AAEP;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/router-core",
|
|
3
|
-
"version": "1.161.
|
|
3
|
+
"version": "1.161.4",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -141,19 +141,20 @@
|
|
|
141
141
|
"src"
|
|
142
142
|
],
|
|
143
143
|
"engines": {
|
|
144
|
-
"node": ">=
|
|
144
|
+
"node": ">=20.19"
|
|
145
145
|
},
|
|
146
146
|
"dependencies": {
|
|
147
|
-
"@tanstack/store": "^0.
|
|
147
|
+
"@tanstack/store": "^0.9.1",
|
|
148
148
|
"cookie-es": "^2.0.0",
|
|
149
149
|
"seroval": "^1.4.2",
|
|
150
150
|
"seroval-plugins": "^1.4.2",
|
|
151
151
|
"tiny-invariant": "^1.3.3",
|
|
152
152
|
"tiny-warning": "^1.0.3",
|
|
153
|
-
"@tanstack/history": "1.
|
|
153
|
+
"@tanstack/history": "1.161.4"
|
|
154
154
|
},
|
|
155
155
|
"devDependencies": {
|
|
156
|
-
"esbuild": "^0.25.0"
|
|
156
|
+
"esbuild": "^0.25.0",
|
|
157
|
+
"vite": "*"
|
|
157
158
|
},
|
|
158
159
|
"scripts": {
|
|
159
160
|
"clean": "rimraf ./dist && rimraf ./coverage",
|
package/src/location.ts
CHANGED
|
@@ -25,7 +25,8 @@ export interface ParsedLocation<TSearchObj extends AnySchema = {}> {
|
|
|
25
25
|
*/
|
|
26
26
|
state: ParsedHistoryState
|
|
27
27
|
/**
|
|
28
|
-
* The hash of the location,
|
|
28
|
+
* The hash of the location, excluding the leading hash character.
|
|
29
|
+
* (e.g., '123' instead of '#123')
|
|
29
30
|
*/
|
|
30
31
|
hash: string
|
|
31
32
|
/**
|
package/src/route.ts
CHANGED
package/src/router.ts
CHANGED
|
@@ -871,6 +871,13 @@ export function getLocationChangeInfo(routerState: {
|
|
|
871
871
|
return { fromLocation, toLocation, pathChanged, hrefChanged, hashChanged }
|
|
872
872
|
}
|
|
873
873
|
|
|
874
|
+
function filterRedirectedCachedMatches<T extends { status: string }>(
|
|
875
|
+
matches: Array<T>,
|
|
876
|
+
): Array<T> {
|
|
877
|
+
const filtered = matches.filter((d) => d.status !== 'redirected')
|
|
878
|
+
return filtered.length === matches.length ? matches : filtered
|
|
879
|
+
}
|
|
880
|
+
|
|
874
881
|
export type CreateRouterFn = <
|
|
875
882
|
TRouteTree extends AnyRoute,
|
|
876
883
|
TTrailingSlashOption extends TrailingSlashOption = 'never',
|
|
@@ -1123,16 +1130,7 @@ export class RouterCore<
|
|
|
1123
1130
|
getInitialRouterState(this.latestLocation),
|
|
1124
1131
|
) as unknown as Store<any>
|
|
1125
1132
|
} else {
|
|
1126
|
-
this.__store = new Store(getInitialRouterState(this.latestLocation)
|
|
1127
|
-
onUpdate: () => {
|
|
1128
|
-
this.__store.state = {
|
|
1129
|
-
...this.state,
|
|
1130
|
-
cachedMatches: this.state.cachedMatches.filter(
|
|
1131
|
-
(d) => !['redirected'].includes(d.status),
|
|
1132
|
-
),
|
|
1133
|
-
}
|
|
1134
|
-
},
|
|
1135
|
-
})
|
|
1133
|
+
this.__store = new Store(getInitialRouterState(this.latestLocation))
|
|
1136
1134
|
|
|
1137
1135
|
setupScrollRestoration(this)
|
|
1138
1136
|
}
|
|
@@ -1175,10 +1173,10 @@ export class RouterCore<
|
|
|
1175
1173
|
}
|
|
1176
1174
|
|
|
1177
1175
|
if (needsLocationUpdate && this.__store) {
|
|
1178
|
-
this.__store.
|
|
1179
|
-
...
|
|
1176
|
+
this.__store.setState((s) => ({
|
|
1177
|
+
...s,
|
|
1180
1178
|
location: this.latestLocation,
|
|
1181
|
-
}
|
|
1179
|
+
}))
|
|
1182
1180
|
}
|
|
1183
1181
|
|
|
1184
1182
|
if (
|
|
@@ -1885,8 +1883,16 @@ export class RouterCore<
|
|
|
1885
1883
|
const fn =
|
|
1886
1884
|
route.options.params?.stringify ?? route.options.stringifyParams
|
|
1887
1885
|
if (fn) {
|
|
1888
|
-
|
|
1889
|
-
|
|
1886
|
+
try {
|
|
1887
|
+
Object.assign(nextParams, fn(nextParams))
|
|
1888
|
+
changedParams = true
|
|
1889
|
+
} catch {
|
|
1890
|
+
// Ignore errors here. When a paired parseParams is defined,
|
|
1891
|
+
// extractStrictParams will re-throw during route matching,
|
|
1892
|
+
// storing the error on the match and allowing the route's
|
|
1893
|
+
// errorComponent to render. If no parseParams is defined,
|
|
1894
|
+
// the stringify error is silently dropped.
|
|
1895
|
+
}
|
|
1890
1896
|
}
|
|
1891
1897
|
}
|
|
1892
1898
|
}
|
|
@@ -2445,7 +2451,9 @@ export class RouterCore<
|
|
|
2445
2451
|
...s.cachedMatches,
|
|
2446
2452
|
...exitingMatches.filter(
|
|
2447
2453
|
(d) =>
|
|
2448
|
-
d.status !== 'error' &&
|
|
2454
|
+
d.status !== 'error' &&
|
|
2455
|
+
d.status !== 'notFound' &&
|
|
2456
|
+
d.status !== 'redirected',
|
|
2449
2457
|
),
|
|
2450
2458
|
],
|
|
2451
2459
|
}
|
|
@@ -2600,12 +2608,21 @@ export class RouterCore<
|
|
|
2600
2608
|
: ''
|
|
2601
2609
|
|
|
2602
2610
|
if (matchesKey) {
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2611
|
+
if (matchesKey === 'cachedMatches') {
|
|
2612
|
+
this.__store.setState((s) => ({
|
|
2613
|
+
...s,
|
|
2614
|
+
cachedMatches: filterRedirectedCachedMatches(
|
|
2615
|
+
s.cachedMatches.map((d) => (d.id === id ? updater(d) : d)),
|
|
2616
|
+
),
|
|
2617
|
+
}))
|
|
2618
|
+
} else {
|
|
2619
|
+
this.__store.setState((s) => ({
|
|
2620
|
+
...s,
|
|
2621
|
+
[matchesKey]: s[matchesKey]?.map((d) =>
|
|
2622
|
+
d.id === id ? updater(d) : d,
|
|
2623
|
+
),
|
|
2624
|
+
}))
|
|
2625
|
+
}
|
|
2609
2626
|
}
|
|
2610
2627
|
})
|
|
2611
2628
|
}
|
|
@@ -2839,10 +2856,7 @@ export class RouterCore<
|
|
|
2839
2856
|
const matchLocation = {
|
|
2840
2857
|
...location,
|
|
2841
2858
|
to: location.to
|
|
2842
|
-
? this.resolvePathWithBase(
|
|
2843
|
-
(location.from || '') as string,
|
|
2844
|
-
location.to as string,
|
|
2845
|
-
)
|
|
2859
|
+
? this.resolvePathWithBase(location.from || '', location.to as string)
|
|
2846
2860
|
: undefined,
|
|
2847
2861
|
params: location.params || {},
|
|
2848
2862
|
leaveParams: true,
|