@tanstack/router-core 1.171.15 → 1.171.16
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 +3 -12
- package/dist/cjs/await-signal.cjs +21 -0
- package/dist/cjs/await-signal.cjs.map +1 -0
- package/dist/cjs/await-signal.d.cts +1 -0
- package/dist/cjs/index.cjs +3 -1
- package/dist/cjs/index.d.cts +3 -2
- package/dist/cjs/isServer/client.cjs +2 -0
- package/dist/cjs/isServer/client.cjs.map +1 -1
- package/dist/cjs/isServer/client.d.cts +1 -0
- package/dist/cjs/isServer/development.cjs +2 -0
- package/dist/cjs/isServer/development.cjs.map +1 -1
- package/dist/cjs/isServer/development.d.cts +1 -0
- package/dist/cjs/isServer/server.cjs +2 -0
- package/dist/cjs/isServer/server.cjs.map +1 -1
- package/dist/cjs/isServer/server.d.cts +1 -0
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +5 -3
- package/dist/cjs/load-client.cjs +1393 -0
- package/dist/cjs/load-client.cjs.map +1 -0
- package/dist/cjs/load-client.d.cts +118 -0
- package/dist/cjs/load-server.cjs +565 -0
- package/dist/cjs/load-server.cjs.map +1 -0
- package/dist/cjs/load-server.d.cts +16 -0
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/redirect.d.cts +0 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/router.cjs +204 -439
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +68 -54
- package/dist/cjs/ssr/client.cjs +2 -2
- package/dist/cjs/ssr/createRequestHandler.cjs +60 -9
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/ssr/createRequestHandler.d.cts +1 -0
- package/dist/cjs/ssr/handlerCallback.cjs +49 -4
- package/dist/cjs/ssr/handlerCallback.cjs.map +1 -1
- package/dist/cjs/ssr/handlerCallback.d.cts +3 -0
- package/dist/cjs/ssr/server.cjs +4 -0
- package/dist/cjs/ssr/server.d.cts +2 -2
- package/dist/cjs/ssr/ssr-client.d.cts +1 -10
- package/dist/cjs/ssr/ssr-match-id.cjs +2 -2
- package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.cjs +6 -6
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +27 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
- package/dist/cjs/ssr/transformStreamWithRouter.d.cts +2 -0
- package/dist/cjs/ssr/types.d.cts +0 -1
- package/dist/cjs/stores.cjs +30 -104
- package/dist/cjs/stores.cjs.map +1 -1
- package/dist/cjs/stores.d.cts +7 -32
- package/dist/cjs/utils.cjs +0 -4
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/esm/Matches.d.ts +3 -12
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/await-signal.d.ts +1 -0
- package/dist/esm/await-signal.js +21 -0
- package/dist/esm/await-signal.js.map +1 -0
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +3 -2
- package/dist/esm/isServer/client.d.ts +1 -0
- package/dist/esm/isServer/client.js +2 -1
- package/dist/esm/isServer/client.js.map +1 -1
- package/dist/esm/isServer/development.d.ts +1 -0
- package/dist/esm/isServer/development.js +2 -1
- package/dist/esm/isServer/development.js.map +1 -1
- package/dist/esm/isServer/server.d.ts +1 -0
- package/dist/esm/isServer/server.js +2 -1
- package/dist/esm/isServer/server.js.map +1 -1
- package/dist/esm/link.d.ts +5 -3
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/load-client.d.ts +118 -0
- package/dist/esm/load-client.js +1386 -0
- package/dist/esm/load-client.js.map +1 -0
- package/dist/esm/load-server.d.ts +16 -0
- package/dist/esm/load-server.js +565 -0
- package/dist/esm/load-server.js.map +1 -0
- package/dist/esm/redirect.d.ts +0 -1
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +68 -54
- package/dist/esm/router.js +207 -442
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/ssr/client.js +1 -1
- package/dist/esm/ssr/createRequestHandler.d.ts +1 -0
- package/dist/esm/ssr/createRequestHandler.js +61 -11
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/dist/esm/ssr/handlerCallback.d.ts +3 -0
- package/dist/esm/ssr/handlerCallback.js +47 -5
- package/dist/esm/ssr/handlerCallback.js.map +1 -1
- package/dist/esm/ssr/server.d.ts +2 -2
- package/dist/esm/ssr/server.js +3 -3
- package/dist/esm/ssr/ssr-client.d.ts +1 -10
- package/dist/esm/ssr/ssr-match-id.js +2 -2
- package/dist/esm/ssr/ssr-match-id.js.map +1 -1
- package/dist/esm/ssr/ssr-server.js +6 -6
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/transformStreamWithRouter.d.ts +2 -0
- package/dist/esm/ssr/transformStreamWithRouter.js +27 -1
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
- package/dist/esm/ssr/types.d.ts +0 -1
- package/dist/esm/stores.d.ts +7 -32
- package/dist/esm/stores.js +30 -104
- package/dist/esm/stores.js.map +1 -1
- package/dist/esm/utils.js +1 -4
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -3
- package/skills/router-core/SKILL.md +23 -4
- package/skills/router-core/auth-and-guards/SKILL.md +10 -10
- package/skills/router-core/code-splitting/SKILL.md +5 -4
- package/skills/router-core/data-loading/SKILL.md +30 -18
- package/skills/router-core/navigation/SKILL.md +5 -4
- package/skills/router-core/not-found-and-errors/SKILL.md +5 -4
- package/skills/router-core/path-params/SKILL.md +5 -4
- package/skills/router-core/search-params/SKILL.md +5 -4
- package/skills/router-core/ssr/SKILL.md +5 -4
- package/skills/router-core/type-safety/SKILL.md +11 -4
- package/src/Matches.ts +6 -21
- package/src/await-signal.ts +27 -0
- package/src/index.ts +1 -3
- package/src/isServer/client.ts +1 -0
- package/src/isServer/development.ts +1 -0
- package/src/isServer/server.ts +1 -0
- package/src/link.ts +5 -3
- package/src/load-client.ts +2651 -0
- package/src/load-server.ts +849 -0
- package/src/redirect.ts +0 -1
- package/src/route.ts +2 -11
- package/src/router.ts +426 -773
- package/src/ssr/createRequestHandler.ts +109 -16
- package/src/ssr/handlerCallback.ts +76 -10
- package/src/ssr/server.ts +4 -1
- package/src/ssr/ssr-client.ts +1 -310
- package/src/ssr/ssr-match-id.ts +11 -2
- package/src/ssr/ssr-server.ts +9 -8
- package/src/ssr/transformStreamWithRouter.ts +37 -1
- package/src/ssr/types.ts +0 -1
- package/src/stores.ts +46 -208
- package/dist/cjs/load-matches.cjs +0 -658
- package/dist/cjs/load-matches.cjs.map +0 -1
- package/dist/cjs/load-matches.d.cts +0 -18
- package/dist/cjs/ssr/ssr-client.cjs +0 -183
- package/dist/cjs/ssr/ssr-client.cjs.map +0 -1
- package/dist/esm/load-matches.d.ts +0 -18
- package/dist/esm/load-matches.js +0 -656
- package/dist/esm/load-matches.js.map +0 -1
- package/dist/esm/ssr/ssr-client.js +0 -183
- package/dist/esm/ssr/ssr-client.js.map +0 -1
- package/src/load-matches.ts +0 -1278
package/dist/cjs/router.d.cts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { loadRouteChunk } from './load-matches.cjs';
|
|
2
1
|
import { LRUCache } from './lru-cache.cjs';
|
|
3
2
|
import { ProcessRouteTreeResult, ProcessedTree } from './new-process-route-tree.cjs';
|
|
4
3
|
import { SearchParser, SearchSerializer } from './searchParams.cjs';
|
|
5
4
|
import { AnyRedirect, ResolvedRedirect } from './redirect.cjs';
|
|
5
|
+
import { LoadTransaction, LoaderFlight, PendingSession } from './load-client.cjs';
|
|
6
|
+
import { ServerLoadResult } from './load-server.cjs';
|
|
6
7
|
import { HistoryAction, HistoryLocation, HistoryState, ParsedHistoryState, RouterHistory } from '@tanstack/history';
|
|
7
|
-
import { Awaitable, Constrain,
|
|
8
|
+
import { Awaitable, Constrain, NoInfer, NonNullableUpdater, PickAsRequired, Updater } from './utils.cjs';
|
|
8
9
|
import { ParsedLocation } from './location.cjs';
|
|
9
|
-
import { AnyContext, AnyRoute, AnyRouteWithContext, LoaderStaleReloadMode, MakeRemountDepsOptionsUnion,
|
|
10
|
+
import { AnyContext, AnyRoute, AnyRouteWithContext, LoaderStaleReloadMode, MakeRemountDepsOptionsUnion, RouteMask } from './route.cjs';
|
|
10
11
|
import { FullSearchSchema, RouteById, RoutePaths, RoutesById, RoutesByPath } from './routeInfo.cjs';
|
|
11
12
|
import { AnyRouteMatch, MakeRouteMatchUnion, MatchRouteOptions } from './Matches.cjs';
|
|
12
13
|
import { BuildLocationFn, CommitLocationOptions, NavigateFn } from './RouterProvider.cjs';
|
|
@@ -135,9 +136,9 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption
|
|
|
135
136
|
*/
|
|
136
137
|
defaultPreloadStaleTime?: number;
|
|
137
138
|
/**
|
|
138
|
-
* The default `
|
|
139
|
+
* The default `preloadGcTime` a route should use if none is provided.
|
|
139
140
|
*
|
|
140
|
-
* @default
|
|
141
|
+
* @default 300_000 `(5 minutes)`
|
|
141
142
|
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#defaultpreloadgctime-property)
|
|
142
143
|
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/preloading)
|
|
143
144
|
*/
|
|
@@ -169,7 +170,7 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption
|
|
|
169
170
|
/**
|
|
170
171
|
* The default `gcTime` a route should use if no gcTime is provided.
|
|
171
172
|
*
|
|
172
|
-
* @default
|
|
173
|
+
* @default 300_000 `(5 minutes)`
|
|
173
174
|
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#defaultgctime-property)
|
|
174
175
|
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#key-options)
|
|
175
176
|
*/
|
|
@@ -389,14 +390,10 @@ export type LocationRewriteFunction = ({ url, }: {
|
|
|
389
390
|
}) => undefined | string | URL;
|
|
390
391
|
export interface RouterState<in out TRouteTree extends AnyRoute = AnyRoute, in out TRouteMatch = MakeRouteMatchUnion> {
|
|
391
392
|
status: 'pending' | 'idle';
|
|
392
|
-
loadedAt: number;
|
|
393
393
|
isLoading: boolean;
|
|
394
|
-
isTransitioning: boolean;
|
|
395
394
|
matches: Array<TRouteMatch>;
|
|
396
395
|
location: ParsedLocation<FullSearchSchema<TRouteTree>>;
|
|
397
396
|
resolvedLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>;
|
|
398
|
-
statusCode: number;
|
|
399
|
-
redirect?: AnyRedirect;
|
|
400
397
|
}
|
|
401
398
|
export interface BuildNextOptions {
|
|
402
399
|
to?: string | number | null;
|
|
@@ -453,9 +450,7 @@ export type RouterListener<TRouterEvent extends RouterEvent> = {
|
|
|
453
450
|
};
|
|
454
451
|
export type SubscribeFn = <TType extends keyof RouterEvents>(eventType: TType, fn: ListenerFn<RouterEvents[TType]>) => () => void;
|
|
455
452
|
export interface MatchRoutesOpts {
|
|
456
|
-
preload?: boolean;
|
|
457
453
|
throwOnError?: boolean;
|
|
458
|
-
dest?: BuildNextOptions;
|
|
459
454
|
}
|
|
460
455
|
export type InferRouterContext<TRouteTree extends AnyRoute> = TRouteTree['types']['routerContext'];
|
|
461
456
|
export type RouterContextOptions<TRouteTree extends AnyRoute> = AnyContext extends InferRouterContext<TRouteTree> ? {
|
|
@@ -486,9 +481,10 @@ export type LoadFn = (opts?: {
|
|
|
486
481
|
action?: {
|
|
487
482
|
type: HistoryAction;
|
|
488
483
|
};
|
|
484
|
+
_signal?: AbortSignal;
|
|
489
485
|
}) => Promise<void>;
|
|
490
486
|
export type CommitLocationFn = ({ viewTransition, ignoreBlocker, ...next }: ParsedLocation & CommitLocationOptions) => Promise<void>;
|
|
491
|
-
export type StartTransitionFn = (fn: () => void) =>
|
|
487
|
+
export type StartTransitionFn = (fn: () => void, expected: Array<AnyRouteMatch>) => Promise<boolean>;
|
|
492
488
|
export interface MatchRoutesFn {
|
|
493
489
|
(pathname: string, locationSearch?: AnySchema, opts?: MatchRoutesOpts): Array<MakeRouteMatchUnion>;
|
|
494
490
|
/**
|
|
@@ -497,8 +493,6 @@ export interface MatchRoutesFn {
|
|
|
497
493
|
(next: ParsedLocation, opts?: MatchRoutesOpts): Array<AnyRouteMatch>;
|
|
498
494
|
(pathnameOrNext: string | ParsedLocation, locationSearchOrOpts?: AnySchema | MatchRoutesOpts, opts?: MatchRoutesOpts): Array<AnyRouteMatch>;
|
|
499
495
|
}
|
|
500
|
-
export type GetMatchFn = (matchId: string) => AnyRouteMatch | undefined;
|
|
501
|
-
export type UpdateMatchFn = (id: string, updater: (match: AnyRouteMatch) => AnyRouteMatch) => void;
|
|
502
496
|
export type LoadRouteChunkFn = (route: AnyRoute) => Promise<Array<void>>;
|
|
503
497
|
export type ResolveRedirect = (err: AnyRedirect) => ResolvedRedirect;
|
|
504
498
|
export type ClearCacheFn<TRouter extends AnyRouter> = (opts?: {
|
|
@@ -585,6 +579,14 @@ export declare function getLocationChangeInfo(location: ParsedLocation, resolved
|
|
|
585
579
|
hrefChanged: boolean;
|
|
586
580
|
hashChanged: boolean;
|
|
587
581
|
};
|
|
582
|
+
/**
|
|
583
|
+
* Return only state owned by the application, excluding volatile history
|
|
584
|
+
* bookkeeping. Mask payloads (`__tempLocation`/`__tempKey`) are kept: they
|
|
585
|
+
* distinguish otherwise-identical locations.
|
|
586
|
+
*/
|
|
587
|
+
export declare function _getUserHistoryState({ key: _key, __TSR_key: _tsrKey, __TSR_index: _tsrIndex, __hashScrollIntoViewOptions: _hashScroll, ...state }: ParsedHistoryState): HistoryState;
|
|
588
|
+
/** Run route lifecycle callbacks in leave/enter/stay phases. */
|
|
589
|
+
export declare function runRouteLifecycle(router: AnyRouter, previous: Array<AnyRouteMatch>, matches: Array<AnyRouteMatch>, isCurrent?: () => boolean): void;
|
|
588
590
|
export type CreateRouterFn = <TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption = 'never', TDefaultStructuralSharingOption extends boolean = false, TRouterHistory extends RouterHistory = RouterHistory, TDehydrated extends Record<string, any> = Record<string, any>>(options: undefined extends number ? 'strictNullChecks must be enabled in tsconfig.json' : RouterConstructorOptions<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>) => RouterCore<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>;
|
|
589
591
|
declare global {
|
|
590
592
|
var __TSR_CACHE__: {
|
|
@@ -593,6 +595,36 @@ declare global {
|
|
|
593
595
|
resolvePathCache: LRUCache<string, string>;
|
|
594
596
|
} | undefined;
|
|
595
597
|
}
|
|
598
|
+
export interface RouterCore<in out TRouteTree extends AnyRoute, in out TTrailingSlashOption extends TrailingSlashOption, in out TDefaultStructuralSharingOption extends boolean, in out TRouterHistory extends RouterHistory = RouterHistory, in out TDehydrated extends Record<string, any> = Record<string, any>> {
|
|
599
|
+
shouldViewTransition?: boolean | ViewTransitionOptions;
|
|
600
|
+
/** Current client load transaction and owner of navigation writes. */
|
|
601
|
+
_tx?: LoadTransaction;
|
|
602
|
+
/** Joinable in-flight loader generations keyed by match ID. */
|
|
603
|
+
_flights?: Map<string, LoaderFlight>;
|
|
604
|
+
/** Active speculative lanes retained for cancellation, invalidation, and cache clearing. */
|
|
605
|
+
_preloads?: Map<AbortController, Array<AnyRouteMatch>>;
|
|
606
|
+
/** Owns cancellable work before a client transaction publishes. */
|
|
607
|
+
_preflight?: AbortController;
|
|
608
|
+
/** Transfers one reconstructed SSR prefix into its initial client load. */
|
|
609
|
+
_handoff?: HydrationHandoff;
|
|
610
|
+
/** Pending-boundary reveal and minimum-visible timing state. */
|
|
611
|
+
_pending?: PendingSession;
|
|
612
|
+
/** Result of the latest server load, used to render or redirect. */
|
|
613
|
+
_serverResult?: ServerLoadResult;
|
|
614
|
+
/** Framework publication waiting for an exact render acknowledgement. */
|
|
615
|
+
_rendered?: [
|
|
616
|
+
offered?: Array<AnyRouteMatch>,
|
|
617
|
+
settle?: (rendered: boolean) => void
|
|
618
|
+
];
|
|
619
|
+
/** Development-only HMR reload for a route and its descendants. */
|
|
620
|
+
_refreshRoute: (() => Promise<void>) | undefined;
|
|
621
|
+
/** Development-only replacement for a route's lazy chunk owner. */
|
|
622
|
+
_replaceRouteChunk: ((route: AnyRoute, lazyFn: AnyRoute['lazyFn']) => void) | undefined;
|
|
623
|
+
}
|
|
624
|
+
export type HydrationHandoff = [
|
|
625
|
+
claim: () => AbortController | undefined,
|
|
626
|
+
finish: (matches?: Array<AnyRouteMatch>) => number | undefined
|
|
627
|
+
];
|
|
596
628
|
/**
|
|
597
629
|
* Core, framework-agnostic router engine that powers TanStack Router.
|
|
598
630
|
*
|
|
@@ -611,10 +643,11 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
|
|
|
611
643
|
restoration?: boolean;
|
|
612
644
|
reset?: boolean;
|
|
613
645
|
};
|
|
614
|
-
shouldViewTransition?: boolean | ViewTransitionOptions;
|
|
615
|
-
isViewTransitionTypesSupported?: boolean;
|
|
616
646
|
subscribers: Set<RouterListener<RouterEvent>>;
|
|
617
|
-
|
|
647
|
+
/** Accepted off-screen loader generations keyed by match ID. */
|
|
648
|
+
_cache: Map<string, AnyRouteMatch>;
|
|
649
|
+
/** Accepted semantic lane, excluding temporary pending presentation. */
|
|
650
|
+
_committed: Array<AnyRouteMatch>;
|
|
618
651
|
stores: RouterStores<TRouteTree>;
|
|
619
652
|
private getStoreConfig;
|
|
620
653
|
batch: (fn: () => void) => void;
|
|
@@ -623,7 +656,7 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
|
|
|
623
656
|
rewrite?: LocationRewrite;
|
|
624
657
|
origin?: string;
|
|
625
658
|
latestLocation: ParsedLocation<FullSearchSchema<TRouteTree>>;
|
|
626
|
-
|
|
659
|
+
_pendingLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>;
|
|
627
660
|
basepath: string;
|
|
628
661
|
routeTree: TRouteTree;
|
|
629
662
|
routesById: RoutesById<TRouteTree>;
|
|
@@ -641,7 +674,6 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
|
|
|
641
674
|
constructor(options: RouterConstructorOptions<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>, getStoreConfig: GetStoreConfig);
|
|
642
675
|
startTransition: StartTransitionFn;
|
|
643
676
|
isShell(): boolean;
|
|
644
|
-
isPrerendering(): boolean;
|
|
645
677
|
update: UpdateFn<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>;
|
|
646
678
|
get state(): RouterState<TRouteTree>;
|
|
647
679
|
updateLatestLocation: () => void;
|
|
@@ -663,19 +695,15 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
|
|
|
663
695
|
/** Resolve a path using the router's trailing-slash policy. */
|
|
664
696
|
resolvePathWithBase: (from: string, path: string) => string;
|
|
665
697
|
private getRouteBranch;
|
|
666
|
-
get looseRoutesById(): Record<string, AnyRoute>;
|
|
667
698
|
matchRoutes: MatchRoutesFn;
|
|
668
|
-
private getParentContext;
|
|
669
699
|
private matchRoutesInternal;
|
|
670
700
|
getMatchedRoutes: GetMatchRoutesFn;
|
|
671
701
|
/**
|
|
672
702
|
* Lightweight route matching for buildLocation.
|
|
673
703
|
* Only computes fullPath, accumulated search, and params - skipping expensive
|
|
674
|
-
* operations like AbortController,
|
|
704
|
+
* operations like AbortController, loaderDeps, and full match objects.
|
|
675
705
|
*/
|
|
676
706
|
private matchRoutesLightweight;
|
|
677
|
-
cancelMatch: (id: string) => void;
|
|
678
|
-
cancelMatches: () => void;
|
|
679
707
|
/**
|
|
680
708
|
* Build the next ParsedLocation from navigation options without committing.
|
|
681
709
|
* Resolves `to`/`from`, params/search/hash/state, applies search validation
|
|
@@ -684,14 +712,18 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
|
|
|
684
712
|
* @link https://tanstack.com/router/latest/docs/framework/react/api/router/RouterType#buildlocation-method
|
|
685
713
|
*/
|
|
686
714
|
buildLocation: BuildLocationFn;
|
|
687
|
-
|
|
715
|
+
_commitPromise: (Promise<void> & {
|
|
716
|
+
resolve: () => void;
|
|
717
|
+
}) | undefined;
|
|
688
718
|
/**
|
|
689
719
|
* Commit a previously built location to history (push/replace), optionally
|
|
690
720
|
* using view transitions and scroll restoration options.
|
|
691
721
|
*/
|
|
692
722
|
commitLocation: CommitLocationFn;
|
|
693
723
|
/** Convenience helper: build a location from options, then commit it. */
|
|
694
|
-
buildAndCommitLocation: ({ replace, resetScroll, hashScrollIntoView, viewTransition, ignoreBlocker, href, ...rest }?: BuildNextOptions & CommitLocationOptions
|
|
724
|
+
buildAndCommitLocation: ({ replace, resetScroll, hashScrollIntoView, viewTransition, ignoreBlocker, _redirects, href, ...rest }?: BuildNextOptions & CommitLocationOptions & {
|
|
725
|
+
_redirects?: number;
|
|
726
|
+
}) => Promise<void>;
|
|
695
727
|
/**
|
|
696
728
|
* Imperatively navigate using standard `NavigateOptions`. When `reloadDocument`
|
|
697
729
|
* or an absolute `href` is provided, performs a full document navigation.
|
|
@@ -700,26 +732,22 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
|
|
|
700
732
|
* @link https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType
|
|
701
733
|
*/
|
|
702
734
|
navigate: NavigateFn;
|
|
703
|
-
latestLoadPromise: undefined | Promise<void>;
|
|
704
|
-
beforeLoad: () => void;
|
|
705
735
|
load: LoadFn;
|
|
706
|
-
startViewTransition: (fn: () => Promise<void>) =>
|
|
707
|
-
updateMatch: UpdateMatchFn;
|
|
708
|
-
getMatch: GetMatchFn;
|
|
736
|
+
startViewTransition: (fn: () => Promise<void>) => any;
|
|
709
737
|
/**
|
|
710
|
-
* Invalidate
|
|
738
|
+
* Invalidate selected match generations and optionally force current matches
|
|
739
|
+
* back into a pending state.
|
|
711
740
|
*
|
|
712
|
-
* - Marks
|
|
713
|
-
* -
|
|
714
|
-
*
|
|
715
|
-
*
|
|
741
|
+
* - Marks committed and cached matches whose IDs are selected as invalid.
|
|
742
|
+
* - Retires selected active preloads so older work cannot publish fresh data.
|
|
743
|
+
*
|
|
744
|
+
* The next load decides when to publish pending UI, so invalidation does not
|
|
745
|
+
* mutate the currently rendered status.
|
|
716
746
|
*/
|
|
717
747
|
invalidate: InvalidateFn<RouterCore<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>>;
|
|
718
|
-
getParsedLocationHref: (location: ParsedLocation) => string;
|
|
719
748
|
resolveRedirect: (redirect: AnyRedirect) => AnyRedirect;
|
|
720
749
|
clearCache: ClearCacheFn<this>;
|
|
721
|
-
|
|
722
|
-
loadRouteChunk: typeof loadRouteChunk;
|
|
750
|
+
loadRouteChunk: (route: AnyRoute, componentType?: 'errorComponent' | 'notFoundComponent' | false) => Promise<void> | undefined;
|
|
723
751
|
preloadRoute: PreloadRouteFn<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory>;
|
|
724
752
|
matchRoute: MatchRouteFn<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory>;
|
|
725
753
|
ssr?: {
|
|
@@ -727,7 +755,6 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
|
|
|
727
755
|
};
|
|
728
756
|
serverSsr?: ServerSsr;
|
|
729
757
|
serverSsrLifecycle?: RouterSsrLifecycle;
|
|
730
|
-
hasNotFoundMatch: () => boolean;
|
|
731
758
|
}
|
|
732
759
|
/** Error thrown when search parameter validation fails. */
|
|
733
760
|
export declare class SearchParamError extends Error {
|
|
@@ -742,17 +769,4 @@ export declare class PathParamError extends Error {
|
|
|
742
769
|
export declare function lazyFn<T extends Record<string, (...args: Array<any>) => any>, TKey extends keyof T = 'default'>(fn: () => Promise<T>, key?: TKey): (...args: Parameters<T[TKey]>) => Promise<Awaited<ReturnType<T[TKey]>>>;
|
|
743
770
|
/** Create an initial RouterState from a parsed location. */
|
|
744
771
|
export declare function getInitialRouterState(location: ParsedLocation): RouterState<any>;
|
|
745
|
-
/**
|
|
746
|
-
* Build the matched route chain and extract params for a pathname.
|
|
747
|
-
* Falls back to the root route if no specific route is found.
|
|
748
|
-
*/
|
|
749
|
-
export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathname, routesById, processedTree, }: {
|
|
750
|
-
pathname: string;
|
|
751
|
-
routesById: Record<string, TRouteLike>;
|
|
752
|
-
processedTree: ProcessedTree<any, any, any>;
|
|
753
|
-
}): {
|
|
754
|
-
matchedRoutes: readonly TRouteLike[];
|
|
755
|
-
routeParams: Record<string, string>;
|
|
756
|
-
foundRoute: TRouteLike | undefined;
|
|
757
|
-
};
|
|
758
772
|
export {};
|
package/dist/cjs/ssr/client.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_load_client = require("../load-client.cjs");
|
|
2
3
|
const require_headers = require("./headers.cjs");
|
|
3
4
|
const require_json = require("./json.cjs");
|
|
4
|
-
|
|
5
|
-
exports.hydrate = require_ssr_client.hydrate;
|
|
5
|
+
exports.hydrate = require_load_client.hydrate;
|
|
6
6
|
exports.json = require_json.json;
|
|
7
7
|
exports.mergeHeaders = require_headers.mergeHeaders;
|
|
@@ -1,16 +1,59 @@
|
|
|
1
|
+
const require_load_client = require("../load-client.cjs");
|
|
1
2
|
const require_headers = require("./headers.cjs");
|
|
2
3
|
const require_ssr_server = require("./ssr-server.cjs");
|
|
3
4
|
const require_handlerCallback = require("./handlerCallback.cjs");
|
|
4
5
|
let _tanstack_history = require("@tanstack/history");
|
|
5
6
|
//#region src/ssr/createRequestHandler.ts
|
|
7
|
+
const requestWaiters = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function removeRequestWaiter(waiters, index, reject) {
|
|
9
|
+
if (waiters[index] !== reject) return;
|
|
10
|
+
if (index !== waiters.length - 1) {
|
|
11
|
+
waiters[index] = void 0;
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
waiters.pop();
|
|
15
|
+
while (waiters.length && waiters[waiters.length - 1] === void 0) waiters.pop();
|
|
16
|
+
}
|
|
17
|
+
function waitForRequest(value, signal, onLate) {
|
|
18
|
+
const promise = Promise.resolve(value);
|
|
19
|
+
if (signal.aborted) {
|
|
20
|
+
promise.then(onLate, () => {});
|
|
21
|
+
return Promise.reject(signal.reason);
|
|
22
|
+
}
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
let waiters = requestWaiters.get(signal);
|
|
25
|
+
let index;
|
|
26
|
+
if (waiters) index = waiters.push(reject) - 1;
|
|
27
|
+
else {
|
|
28
|
+
const newWaiters = [reject];
|
|
29
|
+
waiters = newWaiters;
|
|
30
|
+
index = 0;
|
|
31
|
+
requestWaiters.set(signal, newWaiters);
|
|
32
|
+
signal.addEventListener("abort", () => {
|
|
33
|
+
requestWaiters.delete(signal);
|
|
34
|
+
for (const rejectWaiter of newWaiters) rejectWaiter?.(signal.reason);
|
|
35
|
+
newWaiters.length = 0;
|
|
36
|
+
}, { once: true });
|
|
37
|
+
}
|
|
38
|
+
promise.then((result) => {
|
|
39
|
+
removeRequestWaiter(waiters, index, reject);
|
|
40
|
+
if (signal.aborted) onLate?.(result);
|
|
41
|
+
else resolve(result);
|
|
42
|
+
}, (error) => {
|
|
43
|
+
removeRequestWaiter(waiters, index, reject);
|
|
44
|
+
reject(error);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
6
48
|
function createRequestHandler({ createRouter, request, getRouterManifest }) {
|
|
7
49
|
return async (cb) => {
|
|
50
|
+
request.signal.throwIfAborted();
|
|
8
51
|
const router = createRouter();
|
|
9
52
|
let responseOwnsCleanup = false;
|
|
10
53
|
try {
|
|
11
54
|
require_ssr_server.attachRouterServerSsrUtils({
|
|
12
55
|
router,
|
|
13
|
-
manifest: await getRouterManifest?.()
|
|
56
|
+
manifest: await waitForRequest(getRouterManifest?.(), request.signal)
|
|
14
57
|
});
|
|
15
58
|
const { url } = require_ssr_server.getNormalizedURL(request.url, "http://localhost");
|
|
16
59
|
const origin = require_ssr_server.getOrigin(request);
|
|
@@ -19,13 +62,22 @@ function createRequestHandler({ createRouter, request, getRouterManifest }) {
|
|
|
19
62
|
history,
|
|
20
63
|
origin: router.options.origin ?? origin
|
|
21
64
|
});
|
|
22
|
-
await router.load();
|
|
23
|
-
|
|
24
|
-
const
|
|
65
|
+
await router.load({ _signal: request.signal });
|
|
66
|
+
request.signal.throwIfAborted();
|
|
67
|
+
const result = router._serverResult;
|
|
68
|
+
if (result?.type === "redirect") return result.redirect;
|
|
69
|
+
await waitForRequest(router.serverSsr?.dehydrate(), request.signal);
|
|
70
|
+
request.signal.throwIfAborted();
|
|
71
|
+
const responseHeaders = getRequestHeaders({ router });
|
|
72
|
+
request.signal.throwIfAborted();
|
|
73
|
+
const ssrResponse = require_handlerCallback.bindSsrResponseToRequest(router, await waitForRequest(cb({
|
|
25
74
|
request,
|
|
26
75
|
router,
|
|
27
|
-
responseHeaders
|
|
28
|
-
}))
|
|
76
|
+
responseHeaders
|
|
77
|
+
}), request.signal, (late) => {
|
|
78
|
+
require_handlerCallback.disposeSsrResponseDetached(late, request.signal.reason);
|
|
79
|
+
}), request.signal);
|
|
80
|
+
request.signal.throwIfAborted();
|
|
29
81
|
responseOwnsCleanup = ssrResponse.serverSsrCleanup === "stream";
|
|
30
82
|
return ssrResponse.response;
|
|
31
83
|
} finally {
|
|
@@ -35,12 +87,11 @@ function createRequestHandler({ createRouter, request, getRouterManifest }) {
|
|
|
35
87
|
}
|
|
36
88
|
function getRequestHeaders(opts) {
|
|
37
89
|
const matchHeaders = [];
|
|
38
|
-
for (const match of opts.router.stores.matches.get()) matchHeaders.push(match.headers);
|
|
39
|
-
const redirect = opts.router.stores.redirect.get();
|
|
40
|
-
if (redirect) matchHeaders.push(redirect.headers);
|
|
90
|
+
for (const match of require_load_client._getRenderedMatches(opts.router.stores.matches.get())) matchHeaders.push(match.headers);
|
|
41
91
|
return require_headers.mergeHeaders({ "Content-Type": "text/html; charset=UTF-8" }, ...matchHeaders);
|
|
42
92
|
}
|
|
43
93
|
//#endregion
|
|
44
94
|
exports.createRequestHandler = createRequestHandler;
|
|
95
|
+
exports.waitForRequest = waitForRequest;
|
|
45
96
|
|
|
46
97
|
//# sourceMappingURL=createRequestHandler.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createRequestHandler.cjs","names":[],"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 {
|
|
1
|
+
{"version":3,"file":"createRequestHandler.cjs","names":[],"sources":["../../../src/ssr/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { _getRenderedMatches } from '../load-client'\nimport { mergeHeaders } from './headers'\nimport {\n attachRouterServerSsrUtils,\n getNormalizedURL,\n getOrigin,\n} from './ssr-server'\nimport {\n bindSsrResponseToRequest,\n disposeSsrResponseDetached,\n} from './handlerCallback'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyHeaders } from './headers'\nimport type { AnyRouter } from '../router'\nimport type { ServerManifest } from '../manifest'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\ntype RequestWaiter = ((reason: unknown) => void) | undefined\n\nconst requestWaiters = new WeakMap<AbortSignal, Array<RequestWaiter>>()\n\nfunction removeRequestWaiter(\n waiters: Array<RequestWaiter>,\n index: number,\n reject: (reason: unknown) => void,\n) {\n if (waiters[index] !== reject) {\n return\n }\n if (index !== waiters.length - 1) {\n waiters[index] = undefined\n return\n }\n\n waiters.pop()\n while (waiters.length && waiters[waiters.length - 1] === undefined) {\n waiters.pop()\n }\n}\n\nexport function waitForRequest<T>(\n value: T | PromiseLike<T>,\n signal: AbortSignal,\n onLate?: (value: T) => void,\n): Promise<T> {\n const promise = Promise.resolve(value)\n if (signal.aborted) {\n void promise.then(onLate, () => {})\n return Promise.reject(signal.reason)\n }\n\n return new Promise<T>((resolve, reject) => {\n let waiters = requestWaiters.get(signal)\n let index: number\n if (waiters) {\n index = waiters.push(reject) - 1\n } else {\n const newWaiters: Array<RequestWaiter> = [reject]\n waiters = newWaiters\n index = 0\n requestWaiters.set(signal, newWaiters)\n signal.addEventListener(\n 'abort',\n () => {\n requestWaiters.delete(signal)\n for (const rejectWaiter of newWaiters) {\n rejectWaiter?.(signal.reason)\n }\n newWaiters.length = 0\n },\n { once: true },\n )\n }\n void promise.then(\n (result) => {\n removeRequestWaiter(waiters, index, reject)\n if (signal.aborted) {\n onLate?.(result)\n } else {\n resolve(result)\n }\n },\n (error) => {\n removeRequestWaiter(waiters, index, reject)\n reject(error)\n },\n )\n })\n}\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n createRouter,\n request,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n request: Request\n getRouterManifest?: () => ServerManifest | Promise<ServerManifest>\n}): RequestHandler<TRouter> {\n return async (cb) => {\n request.signal.throwIfAborted()\n const router = createRouter()\n let responseOwnsCleanup = false\n\n try {\n attachRouterServerSsrUtils({\n router,\n manifest: await waitForRequest(getRouterManifest?.(), request.signal),\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 _signal: request.signal,\n })\n request.signal.throwIfAborted()\n\n const result = router._serverResult\n if (result?.type === 'redirect') {\n return result.redirect\n }\n\n await waitForRequest(router.serverSsr?.dehydrate(), request.signal)\n request.signal.throwIfAborted()\n\n const responseHeaders = getRequestHeaders({\n router,\n })\n\n request.signal.throwIfAborted()\n const response = await waitForRequest(\n cb({\n request,\n router,\n responseHeaders,\n }),\n request.signal,\n (late) => {\n disposeSsrResponseDetached(late, request.signal.reason)\n },\n )\n const ssrResponse = bindSsrResponseToRequest(\n router,\n response,\n request.signal,\n )\n request.signal.throwIfAborted()\n responseOwnsCleanup = ssrResponse.serverSsrCleanup === 'stream'\n return ssrResponse.response\n } finally {\n if (!responseOwnsCleanup) {\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 // Transformed streaming response bodies clean up when consumed/cancelled.\n router.serverSsr?.cleanup()\n }\n }\n }\n}\n\nfunction getRequestHeaders(opts: { router: AnyRouter }): Headers {\n const matchHeaders: Array<AnyHeaders> = []\n for (const match of _getRenderedMatches(opts.router.stores.matches.get())) {\n matchHeaders.push(match.headers)\n }\n\n return mergeHeaders(\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...matchHeaders,\n )\n}\n"],"mappings":";;;;;;AAuBA,MAAM,iCAAiB,IAAI,QAA2C;AAEtE,SAAS,oBACP,SACA,OACA,QACA;CACA,IAAI,QAAQ,WAAW,QACrB;CAEF,IAAI,UAAU,QAAQ,SAAS,GAAG;EAChC,QAAQ,SAAS,KAAA;EACjB;CACF;CAEA,QAAQ,IAAI;CACZ,OAAO,QAAQ,UAAU,QAAQ,QAAQ,SAAS,OAAO,KAAA,GACvD,QAAQ,IAAI;AAEhB;AAEA,SAAgB,eACd,OACA,QACA,QACY;CACZ,MAAM,UAAU,QAAQ,QAAQ,KAAK;CACrC,IAAI,OAAO,SAAS;EAClB,QAAa,KAAK,cAAc,CAAC,CAAC;EAClC,OAAO,QAAQ,OAAO,OAAO,MAAM;CACrC;CAEA,OAAO,IAAI,SAAY,SAAS,WAAW;EACzC,IAAI,UAAU,eAAe,IAAI,MAAM;EACvC,IAAI;EACJ,IAAI,SACF,QAAQ,QAAQ,KAAK,MAAM,IAAI;OAC1B;GACL,MAAM,aAAmC,CAAC,MAAM;GAChD,UAAU;GACV,QAAQ;GACR,eAAe,IAAI,QAAQ,UAAU;GACrC,OAAO,iBACL,eACM;IACJ,eAAe,OAAO,MAAM;IAC5B,KAAK,MAAM,gBAAgB,YACzB,eAAe,OAAO,MAAM;IAE9B,WAAW,SAAS;GACtB,GACA,EAAE,MAAM,KAAK,CACf;EACF;EACA,QAAa,MACV,WAAW;GACV,oBAAoB,SAAS,OAAO,MAAM;GAC1C,IAAI,OAAO,SACT,SAAS,MAAM;QAEf,QAAQ,MAAM;EAElB,IACC,UAAU;GACT,oBAAoB,SAAS,OAAO,MAAM;GAC1C,OAAO,KAAK;EACd,CACF;CACF,CAAC;AACH;AAEA,SAAgB,qBAAgD,EAC9D,cACA,SACA,qBAK0B;CAC1B,OAAO,OAAO,OAAO;EACnB,QAAQ,OAAO,eAAe;EAC9B,MAAM,SAAS,aAAa;EAC5B,IAAI,sBAAsB;EAE1B,IAAI;GACF,mBAAA,2BAA2B;IACzB;IACA,UAAU,MAAM,eAAe,oBAAoB,GAAG,QAAQ,MAAM;GACtE,CAAC;GAGD,MAAM,EAAE,QAAQ,mBAAA,iBAAiB,QAAQ,KAAK,kBAAkB;GAChE,MAAM,SAAS,mBAAA,UAAU,OAAO;GAIhC,MAAM,WAAA,GAAA,kBAAA,qBAA8B,EAClC,gBAAgB,CAJL,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAIvB,CAAI,EACvB,CAAC;GAGD,OAAO,OAAO;IACZ;IACA,QAAQ,OAAO,QAAQ,UAAU;GACnC,CAAC;GAED,MAAM,OAAO,KAAK,EAChB,SAAS,QAAQ,OACnB,CAAC;GACD,QAAQ,OAAO,eAAe;GAE9B,MAAM,SAAS,OAAO;GACtB,IAAI,QAAQ,SAAS,YACnB,OAAO,OAAO;GAGhB,MAAM,eAAe,OAAO,WAAW,UAAU,GAAG,QAAQ,MAAM;GAClE,QAAQ,OAAO,eAAe;GAE9B,MAAM,kBAAkB,kBAAkB,EACxC,OACF,CAAC;GAED,QAAQ,OAAO,eAAe;GAY9B,MAAM,cAAc,wBAAA,yBAClB,QACA,MAbqB,eACrB,GAAG;IACD;IACA;IACA;GACF,CAAC,GACD,QAAQ,SACP,SAAS;IACR,wBAAA,2BAA2B,MAAM,QAAQ,OAAO,MAAM;GACxD,CACF,GAIE,QAAQ,MACV;GACA,QAAQ,OAAO,eAAe;GAC9B,sBAAsB,YAAY,qBAAqB;GACvD,OAAO,YAAY;EACrB,UAAU;GACR,IAAI,CAAC,qBAIH,OAAO,WAAW,QAAQ;EAE9B;CACF;AACF;AAEA,SAAS,kBAAkB,MAAsC;CAC/D,MAAM,eAAkC,CAAC;CACzC,KAAK,MAAM,SAAS,oBAAA,oBAAoB,KAAK,OAAO,OAAO,QAAQ,IAAI,CAAC,GACtE,aAAa,KAAK,MAAM,OAAO;CAGjC,OAAO,gBAAA,aACL,EACE,gBAAgB,2BAClB,GACA,GAAG,YACL;AACF"}
|
|
@@ -2,6 +2,7 @@ import { HandlerCallback } from './handlerCallback.cjs';
|
|
|
2
2
|
import { AnyRouter } from '../router.cjs';
|
|
3
3
|
import { ServerManifest } from '../manifest.cjs';
|
|
4
4
|
export type RequestHandler<TRouter extends AnyRouter> = (cb: HandlerCallback<TRouter>) => Promise<Response>;
|
|
5
|
+
export declare function waitForRequest<T>(value: T | PromiseLike<T>, signal: AbortSignal, onLate?: (value: T) => void): Promise<T>;
|
|
5
6
|
export declare function createRequestHandler<TRouter extends AnyRouter>({ createRouter, request, getRouterManifest, }: {
|
|
6
7
|
createRouter: () => TRouter;
|
|
7
8
|
request: Request;
|
|
@@ -8,6 +8,26 @@ function normalizeSsrResponse(result) {
|
|
|
8
8
|
serverSsrCleanup: "none"
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
+
function disposeSsrResponse(response, reason) {
|
|
12
|
+
if (response.serverSsrCleanup !== "stream") return Promise.resolve();
|
|
13
|
+
try {
|
|
14
|
+
return Promise.resolve(response.dispose(reason));
|
|
15
|
+
} catch (error) {
|
|
16
|
+
return Promise.reject(error);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function disposeSsrResponseDetached(result, reason, onError = console.error) {
|
|
20
|
+
const ssrResponse = normalizeSsrResponse(result);
|
|
21
|
+
if (ssrResponse.serverSsrCleanup === "stream") {
|
|
22
|
+
disposeSsrResponse(ssrResponse, reason).catch(onError);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (ssrResponse.response.body) try {
|
|
26
|
+
ssrResponse.response.body.cancel(reason).catch(onError);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
onError(error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
11
31
|
function createSsrStreamResponse(router, response) {
|
|
12
32
|
if (!response.body) throw new Error("Invariant failed: SSR stream response requires a body");
|
|
13
33
|
let disposed = false;
|
|
@@ -17,16 +37,38 @@ function createSsrStreamResponse(router, response) {
|
|
|
17
37
|
async dispose(reason) {
|
|
18
38
|
if (disposed) return;
|
|
19
39
|
disposed = true;
|
|
40
|
+
router.serverSsr?.cleanup();
|
|
20
41
|
try {
|
|
21
42
|
await response.body.cancel(reason);
|
|
22
43
|
} catch {}
|
|
23
|
-
router.serverSsr?.cleanup();
|
|
24
44
|
}
|
|
25
45
|
};
|
|
26
46
|
}
|
|
27
|
-
|
|
47
|
+
function bindSsrResponseToRequest(router, result, signal) {
|
|
28
48
|
const ssrResponse = normalizeSsrResponse(result);
|
|
29
|
-
if (ssrResponse.serverSsrCleanup
|
|
49
|
+
if (ssrResponse.serverSsrCleanup !== "stream") {
|
|
50
|
+
if (signal.aborted) disposeSsrResponseDetached(result, signal.reason);
|
|
51
|
+
return ssrResponse;
|
|
52
|
+
}
|
|
53
|
+
const failed = (error) => {
|
|
54
|
+
router?.serverSsr?.cleanup();
|
|
55
|
+
console.error(error);
|
|
56
|
+
};
|
|
57
|
+
const abort = () => {
|
|
58
|
+
disposeSsrResponseDetached(ssrResponse, signal.reason, failed);
|
|
59
|
+
};
|
|
60
|
+
if (signal.aborted) {
|
|
61
|
+
abort();
|
|
62
|
+
return ssrResponse;
|
|
63
|
+
}
|
|
64
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
65
|
+
router?.serverSsr?.onCleanup(() => {
|
|
66
|
+
signal.removeEventListener("abort", abort);
|
|
67
|
+
});
|
|
68
|
+
return ssrResponse;
|
|
69
|
+
}
|
|
70
|
+
async function replaceSsrResponse(result, response, reason) {
|
|
71
|
+
await disposeSsrResponse(normalizeSsrResponse(result), reason);
|
|
30
72
|
return {
|
|
31
73
|
response,
|
|
32
74
|
serverSsrCleanup: "none"
|
|
@@ -34,7 +76,7 @@ async function replaceSsrResponse(result, response, reason) {
|
|
|
34
76
|
}
|
|
35
77
|
async function stripSsrResponseBody(result, reason) {
|
|
36
78
|
const ssrResponse = normalizeSsrResponse(result);
|
|
37
|
-
|
|
79
|
+
await disposeSsrResponse(ssrResponse, reason);
|
|
38
80
|
return {
|
|
39
81
|
response: new Response(null, ssrResponse.response),
|
|
40
82
|
serverSsrCleanup: "none"
|
|
@@ -44,8 +86,11 @@ function defineHandlerCallback(handler) {
|
|
|
44
86
|
return handler;
|
|
45
87
|
}
|
|
46
88
|
//#endregion
|
|
89
|
+
exports.bindSsrResponseToRequest = bindSsrResponseToRequest;
|
|
47
90
|
exports.createSsrStreamResponse = createSsrStreamResponse;
|
|
48
91
|
exports.defineHandlerCallback = defineHandlerCallback;
|
|
92
|
+
exports.disposeSsrResponse = disposeSsrResponse;
|
|
93
|
+
exports.disposeSsrResponseDetached = disposeSsrResponseDetached;
|
|
49
94
|
exports.isSsrResponse = isSsrResponse;
|
|
50
95
|
exports.normalizeSsrResponse = normalizeSsrResponse;
|
|
51
96
|
exports.replaceSsrResponse = replaceSsrResponse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlerCallback.cjs","names":[],"sources":["../../../src/ssr/handlerCallback.ts"],"sourcesContent":["import type { AnyRouter } from '../router'\n\nexport type SsrResponse =\n | {\n response: Response\n serverSsrCleanup: 'none'\n }\n | {\n response: Response\n serverSsrCleanup: 'stream'\n dispose: (reason?: unknown) => Promise<void>\n }\n\nexport type HandlerCallbackResult = Response | SsrResponse\n\nexport function isSsrResponse(value: unknown): value is SsrResponse {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'response' in value &&\n 'serverSsrCleanup' in value\n )\n}\n\nexport function normalizeSsrResponse(\n result: HandlerCallbackResult,\n): SsrResponse {\n return isSsrResponse(result)\n ? result\n : { response: result, serverSsrCleanup: 'none' }\n}\n\nexport function createSsrStreamResponse<TRouter extends AnyRouter>(\n router: TRouter,\n response: Response,\n): SsrResponse {\n if (!response.body) {\n throw new Error('Invariant failed: SSR stream response requires a body')\n }\n\n let disposed = false\n return {\n response,\n serverSsrCleanup: 'stream',\n async dispose(reason?: unknown) {\n if (disposed) return\n disposed = true\n\n try {\n await response.body!.cancel(reason)\n } catch {\n //
|
|
1
|
+
{"version":3,"file":"handlerCallback.cjs","names":[],"sources":["../../../src/ssr/handlerCallback.ts"],"sourcesContent":["import type { AnyRouter } from '../router'\n\nexport type SsrResponse =\n | {\n response: Response\n serverSsrCleanup: 'none'\n }\n | {\n response: Response\n serverSsrCleanup: 'stream'\n dispose: (reason?: unknown) => Promise<void>\n }\n\nexport type HandlerCallbackResult = Response | SsrResponse\n\nexport function isSsrResponse(value: unknown): value is SsrResponse {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'response' in value &&\n 'serverSsrCleanup' in value\n )\n}\n\nexport function normalizeSsrResponse(\n result: HandlerCallbackResult,\n): SsrResponse {\n return isSsrResponse(result)\n ? result\n : { response: result, serverSsrCleanup: 'none' }\n}\n\nexport function disposeSsrResponse(\n response: SsrResponse,\n reason?: unknown,\n): Promise<void> {\n if (response.serverSsrCleanup !== 'stream') {\n return Promise.resolve()\n }\n try {\n return Promise.resolve(response.dispose(reason))\n } catch (error) {\n return Promise.reject(error)\n }\n}\n\nexport function disposeSsrResponseDetached(\n result: HandlerCallbackResult,\n reason?: unknown,\n onError: (error: unknown) => void = console.error,\n): void {\n const ssrResponse = normalizeSsrResponse(result)\n if (ssrResponse.serverSsrCleanup === 'stream') {\n void disposeSsrResponse(ssrResponse, reason).catch(onError)\n return\n }\n\n if (ssrResponse.response.body) {\n try {\n void ssrResponse.response.body.cancel(reason).catch(onError)\n } catch (error) {\n onError(error)\n }\n }\n}\n\nexport function createSsrStreamResponse<TRouter extends AnyRouter>(\n router: TRouter,\n response: Response,\n): SsrResponse {\n if (!response.body) {\n throw new Error('Invariant failed: SSR stream response requires a body')\n }\n\n let disposed = false\n return {\n response,\n serverSsrCleanup: 'stream',\n async dispose(reason?: unknown) {\n if (disposed) {\n return\n }\n disposed = true\n\n // Sever router ownership before asking user/renderer stream machinery to\n // cancel. A custom stream is allowed to ignore cancellation forever.\n router.serverSsr?.cleanup()\n\n try {\n await response.body!.cancel(reason)\n } catch {\n // Cleanup above already released router SSR state.\n }\n },\n }\n}\n\nexport function bindSsrResponseToRequest(\n router: AnyRouter | undefined,\n result: HandlerCallbackResult,\n signal: AbortSignal,\n): SsrResponse {\n const ssrResponse = normalizeSsrResponse(result)\n if (ssrResponse.serverSsrCleanup !== 'stream') {\n if (signal.aborted) {\n disposeSsrResponseDetached(result, signal.reason)\n }\n return ssrResponse\n }\n\n const failed = (error: unknown) => {\n router?.serverSsr?.cleanup()\n console.error(error)\n }\n const abort = () => {\n disposeSsrResponseDetached(ssrResponse, signal.reason, failed)\n }\n if (signal.aborted) {\n abort()\n return ssrResponse\n }\n\n signal.addEventListener('abort', abort, { once: true })\n router?.serverSsr?.onCleanup(() => {\n signal.removeEventListener('abort', abort)\n })\n return ssrResponse\n}\n\nexport async function replaceSsrResponse(\n result: HandlerCallbackResult,\n response: Response,\n reason?: unknown,\n): Promise<SsrResponse> {\n const ssrResponse = normalizeSsrResponse(result)\n await disposeSsrResponse(ssrResponse, reason)\n return { response, serverSsrCleanup: 'none' }\n}\n\nexport async function stripSsrResponseBody(\n result: HandlerCallbackResult,\n reason?: unknown,\n): Promise<SsrResponse> {\n const ssrResponse = normalizeSsrResponse(result)\n await disposeSsrResponse(ssrResponse, reason)\n return {\n response: new Response(null, ssrResponse.response),\n serverSsrCleanup: 'none',\n }\n}\n\nexport interface HandlerCallback<TRouter extends AnyRouter> {\n (ctx: {\n request: Request\n router: TRouter\n responseHeaders: Headers\n }): HandlerCallbackResult | Promise<HandlerCallbackResult>\n}\n\nexport function defineHandlerCallback<TRouter extends AnyRouter>(\n handler: HandlerCallback<TRouter>,\n): HandlerCallback<TRouter> {\n return handler\n}\n"],"mappings":";AAeA,SAAgB,cAAc,OAAsC;CAClE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,SACd,sBAAsB;AAE1B;AAEA,SAAgB,qBACd,QACa;CACb,OAAO,cAAc,MAAM,IACvB,SACA;EAAE,UAAU;EAAQ,kBAAkB;CAAO;AACnD;AAEA,SAAgB,mBACd,UACA,QACe;CACf,IAAI,SAAS,qBAAqB,UAChC,OAAO,QAAQ,QAAQ;CAEzB,IAAI;EACF,OAAO,QAAQ,QAAQ,SAAS,QAAQ,MAAM,CAAC;CACjD,SAAS,OAAO;EACd,OAAO,QAAQ,OAAO,KAAK;CAC7B;AACF;AAEA,SAAgB,2BACd,QACA,QACA,UAAoC,QAAQ,OACtC;CACN,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UAAU;EAC7C,mBAAwB,aAAa,MAAM,EAAE,MAAM,OAAO;EAC1D;CACF;CAEA,IAAI,YAAY,SAAS,MACvB,IAAI;EACF,YAAiB,SAAS,KAAK,OAAO,MAAM,EAAE,MAAM,OAAO;CAC7D,SAAS,OAAO;EACd,QAAQ,KAAK;CACf;AAEJ;AAEA,SAAgB,wBACd,QACA,UACa;CACb,IAAI,CAAC,SAAS,MACZ,MAAM,IAAI,MAAM,uDAAuD;CAGzE,IAAI,WAAW;CACf,OAAO;EACL;EACA,kBAAkB;EAClB,MAAM,QAAQ,QAAkB;GAC9B,IAAI,UACF;GAEF,WAAW;GAIX,OAAO,WAAW,QAAQ;GAE1B,IAAI;IACF,MAAM,SAAS,KAAM,OAAO,MAAM;GACpC,QAAQ,CAER;EACF;CACF;AACF;AAEA,SAAgB,yBACd,QACA,QACA,QACa;CACb,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UAAU;EAC7C,IAAI,OAAO,SACT,2BAA2B,QAAQ,OAAO,MAAM;EAElD,OAAO;CACT;CAEA,MAAM,UAAU,UAAmB;EACjC,QAAQ,WAAW,QAAQ;EAC3B,QAAQ,MAAM,KAAK;CACrB;CACA,MAAM,cAAc;EAClB,2BAA2B,aAAa,OAAO,QAAQ,MAAM;CAC/D;CACA,IAAI,OAAO,SAAS;EAClB,MAAM;EACN,OAAO;CACT;CAEA,OAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;CACtD,QAAQ,WAAW,gBAAgB;EACjC,OAAO,oBAAoB,SAAS,KAAK;CAC3C,CAAC;CACD,OAAO;AACT;AAEA,eAAsB,mBACpB,QACA,UACA,QACsB;CAEtB,MAAM,mBADc,qBAAqB,MAChB,GAAa,MAAM;CAC5C,OAAO;EAAE;EAAU,kBAAkB;CAAO;AAC9C;AAEA,eAAsB,qBACpB,QACA,QACsB;CACtB,MAAM,cAAc,qBAAqB,MAAM;CAC/C,MAAM,mBAAmB,aAAa,MAAM;CAC5C,OAAO;EACL,UAAU,IAAI,SAAS,MAAM,YAAY,QAAQ;EACjD,kBAAkB;CACpB;AACF;AAUA,SAAgB,sBACd,SAC0B;CAC1B,OAAO;AACT"}
|
|
@@ -10,7 +10,10 @@ export type SsrResponse = {
|
|
|
10
10
|
export type HandlerCallbackResult = Response | SsrResponse;
|
|
11
11
|
export declare function isSsrResponse(value: unknown): value is SsrResponse;
|
|
12
12
|
export declare function normalizeSsrResponse(result: HandlerCallbackResult): SsrResponse;
|
|
13
|
+
export declare function disposeSsrResponse(response: SsrResponse, reason?: unknown): Promise<void>;
|
|
14
|
+
export declare function disposeSsrResponseDetached(result: HandlerCallbackResult, reason?: unknown, onError?: (error: unknown) => void): void;
|
|
13
15
|
export declare function createSsrStreamResponse<TRouter extends AnyRouter>(router: TRouter, response: Response): SsrResponse;
|
|
16
|
+
export declare function bindSsrResponseToRequest(router: AnyRouter | undefined, result: HandlerCallbackResult, signal: AbortSignal): SsrResponse;
|
|
14
17
|
export declare function replaceSsrResponse(result: HandlerCallbackResult, response: Response, reason?: unknown): Promise<SsrResponse>;
|
|
15
18
|
export declare function stripSsrResponseBody(result: HandlerCallbackResult, reason?: unknown): Promise<SsrResponse>;
|
|
16
19
|
export interface HandlerCallback<TRouter extends AnyRouter> {
|
package/dist/cjs/ssr/server.cjs
CHANGED
|
@@ -4,9 +4,12 @@ const require_handlerCallback = require("./handlerCallback.cjs");
|
|
|
4
4
|
const require_createRequestHandler = require("./createRequestHandler.cjs");
|
|
5
5
|
const require_transformStreamWithRouter = require("./transformStreamWithRouter.cjs");
|
|
6
6
|
exports.attachRouterServerSsrUtils = require_ssr_server.attachRouterServerSsrUtils;
|
|
7
|
+
exports.bindSsrResponseToRequest = require_handlerCallback.bindSsrResponseToRequest;
|
|
7
8
|
exports.createRequestHandler = require_createRequestHandler.createRequestHandler;
|
|
8
9
|
exports.createSsrStreamResponse = require_handlerCallback.createSsrStreamResponse;
|
|
9
10
|
exports.defineHandlerCallback = require_handlerCallback.defineHandlerCallback;
|
|
11
|
+
exports.disposeSsrResponse = require_handlerCallback.disposeSsrResponse;
|
|
12
|
+
exports.disposeSsrResponseDetached = require_handlerCallback.disposeSsrResponseDetached;
|
|
10
13
|
exports.getNormalizedURL = require_ssr_server.getNormalizedURL;
|
|
11
14
|
exports.getOrigin = require_ssr_server.getOrigin;
|
|
12
15
|
exports.isSsrResponse = require_handlerCallback.isSsrResponse;
|
|
@@ -16,3 +19,4 @@ exports.stripSsrResponseBody = require_handlerCallback.stripSsrResponseBody;
|
|
|
16
19
|
exports.transformPipeableStreamWithRouter = require_transformStreamWithRouter.transformPipeableStreamWithRouter;
|
|
17
20
|
exports.transformReadableStreamWithRouter = require_transformStreamWithRouter.transformReadableStreamWithRouter;
|
|
18
21
|
exports.transformStreamWithRouter = require_transformStreamWithRouter.transformStreamWithRouter;
|
|
22
|
+
exports.waitForRequest = require_createRequestHandler.waitForRequest;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { createRequestHandler } from './createRequestHandler.cjs';
|
|
1
|
+
export { createRequestHandler, waitForRequest } from './createRequestHandler.cjs';
|
|
2
2
|
export type { RequestHandler } from './createRequestHandler.cjs';
|
|
3
|
-
export { createSsrStreamResponse, defineHandlerCallback, isSsrResponse, normalizeSsrResponse, replaceSsrResponse, stripSsrResponseBody, } from './handlerCallback.cjs';
|
|
3
|
+
export { bindSsrResponseToRequest, createSsrStreamResponse, defineHandlerCallback, disposeSsrResponse, disposeSsrResponseDetached, isSsrResponse, normalizeSsrResponse, replaceSsrResponse, stripSsrResponseBody, } from './handlerCallback.cjs';
|
|
4
4
|
export type { HandlerCallback, HandlerCallbackResult, SsrResponse, } from './handlerCallback.cjs';
|
|
5
5
|
export { transformPipeableStreamWithRouter, transformStreamWithRouter, transformReadableStreamWithRouter, } from './transformStreamWithRouter.cjs';
|
|
6
6
|
export type { TransformStreamWithRouterOptions } from './transformStreamWithRouter.cjs';
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { TsrSsrGlobal } from './types.cjs';
|
|
3
|
-
import { AnyRouter } from '../router.cjs';
|
|
4
|
-
declare global {
|
|
5
|
-
interface Window {
|
|
6
|
-
[GLOBAL_TSR]?: TsrSsrGlobal;
|
|
7
|
-
[GLOBAL_SEROVAL]?: any;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
export declare function hydrate(router: AnyRouter): Promise<any>;
|
|
1
|
+
export { hydrate } from '../load-client.cjs';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
//#region src/ssr/ssr-match-id.ts
|
|
2
2
|
function dehydrateSsrMatchId(id) {
|
|
3
|
-
return id.replaceAll("/", "\0");
|
|
3
|
+
return id.replaceAll("~", "~~").replaceAll("\0", "~0").replaceAll("�", "~r").replaceAll("/", "\0");
|
|
4
4
|
}
|
|
5
5
|
function hydrateSsrMatchId(id) {
|
|
6
|
-
return id.replaceAll("\0", "/").replaceAll("�", "/");
|
|
6
|
+
return id.replaceAll("\0", "/").replaceAll("�", "/").replace(/~([~0r])/g, (_, code) => code === "0" ? "\0" : code === "r" ? "�" : code);
|
|
7
7
|
}
|
|
8
8
|
//#endregion
|
|
9
9
|
exports.dehydrateSsrMatchId = dehydrateSsrMatchId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-match-id.cjs","names":[],"sources":["../../../src/ssr/ssr-match-id.ts"],"sourcesContent":["export function dehydrateSsrMatchId(id: string): string {\n return id.replaceAll('/', '\\0')\n}\n\nexport function hydrateSsrMatchId(id: string): string {\n return id.replaceAll('\\0', '/').replaceAll('\\uFFFD', '/')\n}\n"],"mappings":";AAAA,SAAgB,oBAAoB,IAAoB;CACtD,OAAO,
|
|
1
|
+
{"version":3,"file":"ssr-match-id.cjs","names":[],"sources":["../../../src/ssr/ssr-match-id.ts"],"sourcesContent":["export function dehydrateSsrMatchId(id: string): string {\n return id\n .replaceAll('~', '~~')\n .replaceAll('\\0', '~0')\n .replaceAll('\\uFFFD', '~r')\n .replaceAll('/', '\\0')\n}\n\nexport function hydrateSsrMatchId(id: string): string {\n return id\n .replaceAll('\\0', '/')\n .replaceAll('\\uFFFD', '/')\n .replace(/~([~0r])/g, (_, code) =>\n code === '0' ? '\\0' : code === 'r' ? '\\uFFFD' : code,\n )\n}\n"],"mappings":";AAAA,SAAgB,oBAAoB,IAAoB;CACtD,OAAO,GACJ,WAAW,KAAK,IAAI,EACpB,WAAW,MAAM,IAAI,EACrB,WAAW,KAAU,IAAI,EACzB,WAAW,KAAK,IAAI;AACzB;AAEA,SAAgB,kBAAkB,IAAoB;CACpD,OAAO,GACJ,WAAW,MAAM,GAAG,EACpB,WAAW,KAAU,GAAG,EACxB,QAAQ,cAAc,GAAG,SACxB,SAAS,MAAM,OAAO,SAAS,MAAM,MAAW,IAClD;AACJ"}
|