@rangojs/router 0.30.1 → 0.32.0
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/bin/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/dist/bin/rango.js +7891 -197
- package/dist/types/browser/history-state.d.ts +13 -2
- package/dist/types/browser/react/Link.d.ts +10 -13
- package/dist/types/browser/react/location-state-shared.d.ts +2 -1
- package/dist/types/build/generate-route-types.d.ts +1 -1
- package/dist/types/build/route-types/include-resolution.d.ts +1 -1
- package/dist/types/build/route-types/router-processing.d.ts +3 -7
- package/dist/types/cache/document-cache-policy.d.ts +1 -1
- package/dist/types/route-definition/redirect.d.ts +5 -0
- package/dist/types/router/middleware-types.d.ts +6 -0
- package/dist/types/rsc/helpers.d.ts +5 -3
- package/dist/types/rsc/request-stages.d.ts +2 -0
- package/dist/types/server/document-location-state.d.ts +56 -0
- package/dist/types/server/request-context.d.ts +23 -6
- package/dist/types/testing/render-route.d.ts +17 -0
- package/dist/types/testing/serve-shell-request.d.ts +9 -0
- package/dist/types/types/handler-context.d.ts +18 -3
- package/dist/types/types/segments.d.ts +6 -0
- package/dist/types/vite/temp-rsc-server.d.ts +8 -4
- package/dist/types/vite/utils/forward-user-plugins.d.ts +33 -1
- package/dist/vite/index.js +121 -38
- package/package.json +2 -2
- package/skills/comparison/references/framework-comparison.md +3 -2
- package/skills/document-cache/SKILL.md +5 -0
- package/skills/hooks/state.md +110 -6
- package/skills/intercept/SKILL.md +2 -1
- package/skills/ppr/SKILL.md +12 -0
- package/skills/rango/SKILL.md +5 -5
- package/skills/server-actions/SKILL.md +8 -0
- package/skills/testing/client-components.md +44 -19
- package/skills/testing/serve-shell-request.md +38 -13
- package/skills/typesafety/generated-files-and-cli.md +2 -1
- package/skills/ux-architecture/SKILL.md +6 -3
- package/src/bin/rango.ts +13 -8
- package/src/browser/history-state.ts +24 -2
- package/src/browser/react/Link.tsx +10 -13
- package/src/browser/react/location-state-shared.ts +8 -1
- package/src/browser/rsc-router.tsx +5 -2
- package/src/build/generate-route-types.ts +0 -1
- package/src/build/route-types/include-resolution.ts +2 -1
- package/src/build/route-types/router-processing.ts +213 -49
- package/src/build/runtime-discovery.ts +128 -41
- package/src/cache/document-cache-policy.ts +10 -1
- package/src/cache/document-cache.ts +7 -0
- package/src/client-urls/server-projection.ts +3 -1
- package/src/route-definition/redirect.ts +5 -0
- package/src/router/match-middleware/cache-lookup.ts +23 -6
- package/src/router/match-result.ts +9 -1
- package/src/router/middleware-types.ts +6 -0
- package/src/router/revalidation.ts +23 -3
- package/src/rsc/helpers.ts +13 -4
- package/src/rsc/progressive-enhancement.ts +5 -0
- package/src/rsc/request-stages.ts +28 -1
- package/src/rsc/rsc-rendering.ts +39 -9
- package/src/server/document-location-state.ts +313 -0
- package/src/server/request-context.ts +24 -5
- package/src/testing/dispatch.ts +3 -0
- package/src/testing/render-route.tsx +40 -6
- package/src/testing/run-revalidate.ts +11 -1
- package/src/testing/serve-shell-request.ts +16 -0
- package/src/types/handler-context.ts +18 -3
- package/src/types/segments.ts +6 -0
- package/src/vite/temp-rsc-server.ts +9 -4
- package/src/vite/utils/forward-user-plugins.ts +15 -5
|
@@ -35,8 +35,9 @@ export declare function stripShellMissMarker(): void;
|
|
|
35
35
|
* the server rendered this document without them. One pass before hydration
|
|
36
36
|
* (initBrowserApp; renderRoute's `hydrate` mode), so no reader needs to know
|
|
37
37
|
* the page began as a document load, and a slot nobody reads is removed too.
|
|
38
|
-
*
|
|
39
|
-
* (
|
|
38
|
+
* Server-set state is not lost to it: the state a document response carries
|
|
39
|
+
* is merged after this pass (applyDocumentLocationState), so a `~r` slot the
|
|
40
|
+
* server set for this load survives this load and no later one.
|
|
40
41
|
*
|
|
41
42
|
* A slot is recognised by its key alone (the `~r` suffix): at start-up the
|
|
42
43
|
* module that defines it may not be loaded.
|
|
@@ -46,6 +47,16 @@ export declare function stripShellMissMarker(): void;
|
|
|
46
47
|
* is a full page for later Back/Forward.
|
|
47
48
|
*/
|
|
48
49
|
export declare function clearLocationStateOnDocumentLoad(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Merge the location state a document response carried (its bootstrap
|
|
52
|
+
* payload's `metadata.locationState`, server/document-location-state.ts)
|
|
53
|
+
* into the entry the document loaded on. Start-up runs it after
|
|
54
|
+
* clearLocationStateOnDocumentLoad and the version is set, before the entry
|
|
55
|
+
* is committed for readers (initBrowserApp; renderRoute's `hydrate` mode),
|
|
56
|
+
* so readers get it once they have hydrated, as stored state. Only typed
|
|
57
|
+
* slots are taken.
|
|
58
|
+
*/
|
|
59
|
+
export declare function applyDocumentLocationState(locationState: Record<string, unknown> | undefined): void;
|
|
49
60
|
/**
|
|
50
61
|
* Merge server-set location state into the current history entry and return
|
|
51
62
|
* the entry state written. Readers see it when the caller commits it
|
|
@@ -66,23 +66,20 @@ export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEle
|
|
|
66
66
|
* keyed on Rango state + target URL. This is correct for routes whose
|
|
67
67
|
* response shape doesn't depend on where the user navigates from.
|
|
68
68
|
*
|
|
69
|
-
* Set `":source"`
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* `currentUrl` / `currentParams`, and the wildcard entry would
|
|
73
|
-
* therefore serve the wrong diff to a navigation from a different
|
|
74
|
-
* source.
|
|
69
|
+
* Set `":source"` to scope every prefetch of this Link to the page that
|
|
70
|
+
* sent it, when its response would differ by source page in a way the
|
|
71
|
+
* server cannot see.
|
|
75
72
|
*
|
|
76
|
-
*
|
|
77
|
-
* (
|
|
78
|
-
*
|
|
79
|
-
* both source-specific
|
|
80
|
-
*
|
|
73
|
+
* The server scopes a prefetch to its source automatically
|
|
74
|
+
* (`x-rsc-prefetch-scope: source`) when an intercept targets the route,
|
|
75
|
+
* whether or not it applies from this page (the modal and the full page
|
|
76
|
+
* are both source-specific), and when a `revalidate()` of the target
|
|
77
|
+
* read `currentParams`, `currentUrl` or `fromRouteName` and kept the
|
|
78
|
+
* segment: that diff is the source page's (#1331). Every other response
|
|
79
|
+
* stays shared.
|
|
81
80
|
*
|
|
82
81
|
* @example
|
|
83
82
|
* ```tsx
|
|
84
|
-
* // Route uses a `revalidate()` that branches on currentUrl — opt in
|
|
85
|
-
* // so prefetches don't bleed across source pages.
|
|
86
83
|
* <Link to="/dashboard" prefetch="hover" prefetchKey=":source" />
|
|
87
84
|
* ```
|
|
88
85
|
*/
|
|
@@ -269,7 +269,8 @@ export declare function isLocationStateDefinition(value: unknown): value is Loca
|
|
|
269
269
|
*/
|
|
270
270
|
export declare function isLocationStateEntry(value: unknown): value is LocationStateEntry;
|
|
271
271
|
/**
|
|
272
|
-
* Resolve state entries into a flat object for history.state
|
|
272
|
+
* Resolve state entries into a flat object for history.state. One slot per
|
|
273
|
+
* definition: a later entry of the same definition replaces an earlier one.
|
|
273
274
|
*/
|
|
274
275
|
export declare function resolveLocationStateEntries(entries: LocationStateEntry[]): Record<string, unknown>;
|
|
275
276
|
export {};
|
|
@@ -4,5 +4,5 @@ export { generatePerModuleTypesSource, generateRouteTypesSource, } from "./route
|
|
|
4
4
|
export { DEFAULT_EXCLUDE_PATTERNS, type ScanFilter, createScanFilter, findTsFiles, isInSkippedScanDir, } from "./route-types/scan-filter.js";
|
|
5
5
|
export { writePerModuleRouteTypes, writePerModuleRouteTypesForFile, } from "./route-types/per-module-writer.js";
|
|
6
6
|
export { type UnresolvableReason, type UnresolvableInclude, extractIncludesWithDiagnostics, } from "./route-types/include-resolution.js";
|
|
7
|
-
export { extractUrlsFromRouter,
|
|
7
|
+
export { extractUrlsFromRouter, type UrlsExtractionResult, buildCombinedRouteMapForRouterFile, detectUnresolvableIncludes, detectUnresolvableIncludesForUrlsFile, findNestedRouterConflict, formatNestedRouterConflictError, findRouterFiles, findHostRouterFiles, writeCombinedRouteTypes, genFileTsPath, resolveSearchSchemas, } from "./route-types/router-processing.js";
|
|
8
8
|
export { findUrlsVariableNames } from "./route-types/per-module-writer.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
|
-
export type UnresolvableReason = "factory-call" | "dynamic-expression" | "unresolvable-import" | "file-not-found";
|
|
2
|
+
export type UnresolvableReason = "factory-call" | "dynamic-expression" | "unresolvable-import" | "file-not-found" | "unresolvable-basename";
|
|
3
3
|
export interface UnresolvableInclude {
|
|
4
4
|
pathPrefix: string;
|
|
5
5
|
namePrefix: string | null;
|
|
@@ -30,11 +30,6 @@ export type UrlsExtractionResult = {
|
|
|
30
30
|
* Returns either a variable name or an inline code block.
|
|
31
31
|
*/
|
|
32
32
|
export declare function extractUrlsFromRouter(code: string): UrlsExtractionResult | null;
|
|
33
|
-
/**
|
|
34
|
-
* Extract the `basename` string literal from createRouter({ basename: "..." }).
|
|
35
|
-
* Returns the basename value or undefined if not present.
|
|
36
|
-
*/
|
|
37
|
-
export declare function extractBasenameFromRouter(code: string): string | undefined;
|
|
38
33
|
export declare function genFileTsPath(sourceFile: string): string;
|
|
39
34
|
export declare function resolveSearchSchemas(publicRouteNames: string[], runtimeSchemas: Record<string, Record<string, string>> | undefined, sourceFile: string): Record<string, Record<string, string>> | undefined;
|
|
40
35
|
/**
|
|
@@ -47,8 +42,9 @@ export declare function buildCombinedRouteMapForRouterFile(routerFilePath: strin
|
|
|
47
42
|
};
|
|
48
43
|
/**
|
|
49
44
|
* Walk the full include tree starting from a router file and detect
|
|
50
|
-
* all includes that the static parser cannot resolve
|
|
51
|
-
*
|
|
45
|
+
* all includes that the static parser cannot resolve, plus an explicit
|
|
46
|
+
* createRouter `basename` it cannot read (every pattern would lack the
|
|
47
|
+
* prefix). Returns an array of diagnostics; empty means fully resolvable.
|
|
52
48
|
*/
|
|
53
49
|
export declare function detectUnresolvableIncludes(routerFilePath: string): UnresolvableInclude[];
|
|
54
50
|
/**
|
|
@@ -12,7 +12,7 @@ export interface CacheDirectives {
|
|
|
12
12
|
/**
|
|
13
13
|
* Check if response should be cached based on Cache-Control headers
|
|
14
14
|
*/
|
|
15
|
-
export declare function shouldCacheResponse(response: Response, requestCtx?: Pick<RequestContext, "_payloadVisitorTheme" | "_payloadDeferred" | "_payloadVisitorLocation">): CacheDirectives | null;
|
|
15
|
+
export declare function shouldCacheResponse(response: Response, requestCtx?: Pick<RequestContext, "_payloadVisitorTheme" | "_payloadDeferred" | "_payloadVisitorLocation" | "_documentLocationState">): CacheDirectives | null;
|
|
16
16
|
/**
|
|
17
17
|
* Whether this cache will store the response the current render produces, as
|
|
18
18
|
* far as the render can tell: the middleware runs it (a MISS or a stale
|
|
@@ -9,6 +9,11 @@ import type { LocationStateEntry } from "../browser/react/location-state-shared.
|
|
|
9
9
|
* Supports an optional state parameter to carry location state through the
|
|
10
10
|
* redirect. On the target page, state can be read via useLocationState()
|
|
11
11
|
* (use { flash: true } in createLocationState for read-once flash messages).
|
|
12
|
+
* On a client navigation or action the state travels in the redirect's
|
|
13
|
+
* payload. On a document request (a page load, a no-JS form post) it travels
|
|
14
|
+
* in a one-shot cookie the target's document request reads and clears, as
|
|
15
|
+
* JSON: give it plain JSON data there. `{ external: true }` carries none.
|
|
16
|
+
* Two entries of the same definition keep only the last.
|
|
12
17
|
*
|
|
13
18
|
* @param url - The URL to redirect to
|
|
14
19
|
* @param statusOrOptions - HTTP status code (default: 302) or options object
|
|
@@ -56,6 +56,12 @@ export interface MiddlewareContext<TEnv = any, TParams = Record<string, string |
|
|
|
56
56
|
*/
|
|
57
57
|
readonly theme?: Theme;
|
|
58
58
|
setTheme?: (theme: Theme) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Attach location state entries to this response (see the handler
|
|
61
|
+
* context's `setLocationState`). Entries accumulate across definitions;
|
|
62
|
+
* for one definition the last write wins. Set it here rather than in a
|
|
63
|
+
* handler on a `ppr` route: a shell HIT runs no handler.
|
|
64
|
+
*/
|
|
59
65
|
setLocationState(entries: LocationStateEntry | LocationStateEntry[]): void;
|
|
60
66
|
/** Global route names only; see {@link GlobalReverseFunction}. */
|
|
61
67
|
reverse: GlobalReverseFunction<DefaultReverseRouteMap>;
|
|
@@ -95,10 +95,12 @@ export declare function interceptRedirectForPartial(response: Response, createRe
|
|
|
95
95
|
/**
|
|
96
96
|
* Attach location state set during a request to a payload's metadata.
|
|
97
97
|
* No-op if no location state was set. Callers must ensure payload.metadata
|
|
98
|
-
* is populated (
|
|
99
|
-
* that
|
|
98
|
+
* is populated. A `document` payload (a page load's or a no-JS form post's
|
|
99
|
+
* bootstrap payload) that carries state marks the request
|
|
100
|
+
* `_documentLocationState`: it is the visitor's, so no shared cache keeps it
|
|
101
|
+
* (server/document-location-state.ts).
|
|
100
102
|
*/
|
|
101
|
-
export declare function attachLocationStateIfPresent(payload: RscPayload): void;
|
|
103
|
+
export declare function attachLocationStateIfPresent(payload: RscPayload, document?: boolean): void;
|
|
102
104
|
/**
|
|
103
105
|
* Only cache successful responses. Non-200 statuses (errors, redirects) are
|
|
104
106
|
* not cached -- notFound() produces 500 in response routes, and explicit
|
|
@@ -36,6 +36,8 @@ export interface StageRouter<TEnv = unknown> {
|
|
|
36
36
|
readonly telemetry?: TelemetrySink;
|
|
37
37
|
readonly timeouts?: ResolvedTimeouts;
|
|
38
38
|
readonly onTimeout?: OnTimeoutCallback<TEnv>;
|
|
39
|
+
/** Names the cookie location state crosses a document redirect in. */
|
|
40
|
+
readonly resolvedStateCookieName: string;
|
|
39
41
|
}
|
|
40
42
|
/** Report an error through the router's onError. */
|
|
41
43
|
export type ReportError<TEnv = unknown> = (error: unknown, phase: ErrorPhase, context: InvokeOnErrorContext<TEnv>) => void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Location state on document responses (#1330).
|
|
3
|
+
*
|
|
4
|
+
* A client navigation or an action carries server-set location state in its
|
|
5
|
+
* Flight payload, and a redirect on either becomes a Flight redirect that
|
|
6
|
+
* carries it too. A document request has no such channel for a 3xx: the
|
|
7
|
+
* browser follows it with a plain GET. This module carries the state across
|
|
8
|
+
* that one hop in a short-lived cookie:
|
|
9
|
+
*
|
|
10
|
+
* - `carryLocationStateAcrossRedirect` (rsc/request-stages.ts
|
|
11
|
+
* finalizeRequestResponse) writes it on a document request's same-origin
|
|
12
|
+
* 3xx when the request set location state;
|
|
13
|
+
* - `consumeDocumentLocationState` (rsc/request-stages.ts runRequestPasses)
|
|
14
|
+
* reads it on the next GET document request that navigates to the target
|
|
15
|
+
* pathname (`Sec-Fetch-Dest` a browsing context, where sent), seeds
|
|
16
|
+
* `_locationState` with its entries (so the render attaches them to the
|
|
17
|
+
* bootstrap payload, rsc/rsc-rendering.ts) and clears it.
|
|
18
|
+
*
|
|
19
|
+
* A document that carries location state is per visitor: it is marked
|
|
20
|
+
* `_documentLocationState`, never stored by the document cache or as a PPR
|
|
21
|
+
* shell, and leaves with `Cache-Control: private, no-store`
|
|
22
|
+
* (`markDocumentResponsePrivate`).
|
|
23
|
+
*
|
|
24
|
+
* The value is JSON, not Flight: a cookie holds text, and the client merges
|
|
25
|
+
* it as `history.state` would hold it. `Path=/` because the `__Host-` prefix
|
|
26
|
+
* (https) requires it, which keeps a sibling subdomain from planting state;
|
|
27
|
+
* the target pathname inside the value decides who consumes it.
|
|
28
|
+
*/
|
|
29
|
+
import { type RequestContext } from "./request-context.js";
|
|
30
|
+
/** The cookie's name for a router: `__Host-` on https. */
|
|
31
|
+
export declare function documentLocationStateCookieName(stateCookieName: string, secure: boolean): string;
|
|
32
|
+
/**
|
|
33
|
+
* Read the cookie a document redirect left for this request: seed
|
|
34
|
+
* `_locationState` with its slots and clear it. Only a GET document request
|
|
35
|
+
* of the target pathname that navigates consumes it (the request the browser
|
|
36
|
+
* makes for a 301/302/303, see isNavigationRequest); any other request, a
|
|
37
|
+
* form POST to that path or a prefetch of it included, leaves it to its
|
|
38
|
+
* expiry. A malformed value is cleared and ignored, and only `__rsc_ls_*`
|
|
39
|
+
* slots are taken from it (the value comes from the browser).
|
|
40
|
+
*/
|
|
41
|
+
export declare function consumeDocumentLocationState(reqCtx: Pick<RequestContext, "_locationState" | "setCookie">, request: Request, url: URL, stateCookieName: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Write the cookie on a document request's redirect that set location state,
|
|
44
|
+
* and mark the redirect private. Not for a partial or action request (their
|
|
45
|
+
* redirect is a Flight payload), an external or cross-origin target (the
|
|
46
|
+
* cookie would never reach it) or a response that is not a 3xx with a
|
|
47
|
+
* Location. Returns the response to send: a new one when its headers are
|
|
48
|
+
* immutable.
|
|
49
|
+
*/
|
|
50
|
+
export declare function carryLocationStateAcrossRedirect(response: Response, reqCtx: Pick<RequestContext, "_locationState">, request: Request, url: URL, stateCookieName: string): Response;
|
|
51
|
+
/**
|
|
52
|
+
* `Cache-Control: private, no-store` on a document that carries location
|
|
53
|
+
* state, after every middleware: a shared cache must never store or replay
|
|
54
|
+
* one visitor's state. Returns the response to send.
|
|
55
|
+
*/
|
|
56
|
+
export declare function markDocumentResponsePrivate(response: Response, reqCtx: Pick<RequestContext, "_documentLocationState">): Response;
|
|
@@ -547,12 +547,22 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
547
547
|
/**
|
|
548
548
|
* Attach location state entries to the current response.
|
|
549
549
|
*
|
|
550
|
-
* For
|
|
551
|
-
* metadata and merged into history.
|
|
552
|
-
*
|
|
553
|
-
*
|
|
550
|
+
* For a client navigation or an action, the state is included in the RSC
|
|
551
|
+
* payload metadata and merged into the entry's history.state on the
|
|
552
|
+
* client. For a document request (a page load, a no-JS form post), it rides
|
|
553
|
+
* the document's bootstrap payload and is merged into the entry when the
|
|
554
|
+
* client starts; readers get it once the page has hydrated. For a redirect,
|
|
555
|
+
* the state travels with the redirect: in its Flight payload on a
|
|
556
|
+
* navigation or action, in a one-shot cookie the target's document request
|
|
557
|
+
* reads on a document request. A document that carries state is sent
|
|
558
|
+
* `Cache-Control: private, no-store` and never stored by the document cache
|
|
559
|
+
* or as a PPR shell.
|
|
554
560
|
*
|
|
555
|
-
* Multiple calls accumulate entries.
|
|
561
|
+
* Multiple calls accumulate entries across definitions. For one definition
|
|
562
|
+
* the last write wins: two entries of the same definition share its slot
|
|
563
|
+
* in history.state, so a later call (or a later entry in one array)
|
|
564
|
+
* replaces an earlier one. To combine writes, make the state an array and
|
|
565
|
+
* write it once.
|
|
556
566
|
*
|
|
557
567
|
* @example
|
|
558
568
|
* ```typescript
|
|
@@ -562,6 +572,13 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
562
572
|
setLocationState(entries: LocationStateEntry | LocationStateEntry[]): void;
|
|
563
573
|
/** @internal Accumulated location state entries */
|
|
564
574
|
_locationState?: LocationStateEntry[];
|
|
575
|
+
/**
|
|
576
|
+
* @internal Set when a document's payload carries location state
|
|
577
|
+
* (rsc/rsc-rendering.ts, rsc/progressive-enhancement.ts), a shell HIT's
|
|
578
|
+
* included. The document is per visitor: the document cache refuses it,
|
|
579
|
+
* and it leaves `private, no-store` (server/document-location-state.ts).
|
|
580
|
+
*/
|
|
581
|
+
_documentLocationState?: boolean;
|
|
565
582
|
/**
|
|
566
583
|
* The matched route name, if the route has an explicit name.
|
|
567
584
|
* Undefined before route matching or for unnamed routes.
|
|
@@ -795,7 +812,7 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
795
812
|
* This is the type exported to library consumers. Internal code should
|
|
796
813
|
* use the full RequestContext interface directly.
|
|
797
814
|
*/
|
|
798
|
-
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_prerender" | "_onDemandProducer" | "_searchParamsFilter" | "_shellCaptureState" | "_shellImplicitCache" | "_shellLoaderSeed" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_prerenderWarm" | "_runAtRequestEntry" | "_shellFragmentPayload" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_payloadDeferred" | "_requestKind" | "_payloadVisitorLocation" | "_locationState" | "_routeName" | "_prevRouteKey" | "_visitorMoved" | "_inActionRevalidation" | "_actionRan" | "_reportedErrors" | "_throwers" | "_printedErrors" | "_renderErrors" | "_recoveredHandlerErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_handlerTiming" | "_tracing" | "_basename" | "_routerId" | "_versions" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
815
|
+
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_prerender" | "_onDemandProducer" | "_searchParamsFilter" | "_shellCaptureState" | "_shellImplicitCache" | "_shellLoaderSeed" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_prerenderWarm" | "_runAtRequestEntry" | "_shellFragmentPayload" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_payloadDeferred" | "_requestKind" | "_payloadVisitorLocation" | "_locationState" | "_documentLocationState" | "_routeName" | "_prevRouteKey" | "_visitorMoved" | "_inActionRevalidation" | "_actionRan" | "_reportedErrors" | "_throwers" | "_printedErrors" | "_renderErrors" | "_recoveredHandlerErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_handlerTiming" | "_tracing" | "_basename" | "_routerId" | "_versions" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
799
816
|
/**
|
|
800
817
|
* Marker for a waitUntil-scheduled fn whose task promise must NOT enter
|
|
801
818
|
* _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
|
|
@@ -185,6 +185,23 @@ export interface RenderRouteOptions {
|
|
|
185
185
|
* });
|
|
186
186
|
*/
|
|
187
187
|
locationState?: ReadonlyArray<readonly [LocationStateDefinition<any, any>, unknown]>;
|
|
188
|
+
/**
|
|
189
|
+
* Location state the document response carries, as `[def, value]` pairs:
|
|
190
|
+
* what a handler, middleware or no-JS form action set with
|
|
191
|
+
* `ctx.setLocationState()` (or a document redirect carried) for this page
|
|
192
|
+
* load. Merged into the entry at start-up as initBrowserApp merges the
|
|
193
|
+
* bootstrap payload's: after `locationState` and, with `hydrate: true`,
|
|
194
|
+
* after the `clearOnReload` pass, so a `clearOnReload` slot given here is
|
|
195
|
+
* applied. With `hydrate: true` a reader hydrates as `undefined` and gets
|
|
196
|
+
* the value once the root has hydrated.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* await renderRoute([{ path: "/", Component: FlashBanner }], {
|
|
200
|
+
* hydrate: true,
|
|
201
|
+
* documentLocationState: [[FlashMessage, { text: "Payment declined" }]],
|
|
202
|
+
* });
|
|
203
|
+
*/
|
|
204
|
+
documentLocationState?: ReadonlyArray<readonly [LocationStateDefinition<any, any>, unknown]>;
|
|
188
205
|
/**
|
|
189
206
|
* Handles to seed by REFERENCE, for components that read handle output via
|
|
190
207
|
* `useHandle(SomeHandle)` (e.g. a client `Breadcrumbs` trail). Each entry is
|
|
@@ -229,6 +229,15 @@ export interface ServeShellRequestResult {
|
|
|
229
229
|
* hydrates without it.
|
|
230
230
|
*/
|
|
231
231
|
readPayloadFormState(): Promise<unknown>;
|
|
232
|
+
/**
|
|
233
|
+
* The payload's location state as the browser reads it: the slots
|
|
234
|
+
* (`Def.__rsc_ls_key` to value) a document's start-up merges into its
|
|
235
|
+
* entry (or a navigation's commit, for a `partial` request). Undefined when
|
|
236
|
+
* the payload carries none (or no Flight was rendered). A redirect carries
|
|
237
|
+
* a document request's state in a `Set-Cookie` instead: pass that cookie
|
|
238
|
+
* on the request of its target to read what the target's payload carries.
|
|
239
|
+
*/
|
|
240
|
+
readLocationState(): Promise<Record<string, unknown> | undefined>;
|
|
232
241
|
/**
|
|
233
242
|
* For an `action` request, the call's answer as the browser reads it: its
|
|
234
243
|
* result and the `revalidationError` its loaders' reruns report.
|
|
@@ -274,9 +274,16 @@ export type HandlerContext<TParams = {}, TEnv = DefaultEnv, TSearch extends Sear
|
|
|
274
274
|
*/
|
|
275
275
|
setTheme?: (theme: Theme) => void;
|
|
276
276
|
/**
|
|
277
|
-
* Attach location state entries to this response
|
|
278
|
-
*
|
|
279
|
-
*
|
|
277
|
+
* Attach location state entries to this response, for the useLocationState()
|
|
278
|
+
* hook to read on the entry this response renders. A client navigation
|
|
279
|
+
* delivers it with its payload; a document load (a link from outside the
|
|
280
|
+
* app, a no-JS form post) with its bootstrap payload, once the page has
|
|
281
|
+
* hydrated; a redirect carries it to its target (in a one-shot cookie on a
|
|
282
|
+
* document request). A document carrying it is sent
|
|
283
|
+
* `Cache-Control: private, no-store`.
|
|
284
|
+
*
|
|
285
|
+
* Entries accumulate across definitions; for one definition the last write
|
|
286
|
+
* wins (an earlier entry of it is replaced, not merged).
|
|
280
287
|
*
|
|
281
288
|
* @example
|
|
282
289
|
* ```typescript
|
|
@@ -390,6 +397,14 @@ export type InternalHandlerContext<TParams = {}, TEnv = DefaultEnv, TSearch exte
|
|
|
390
397
|
* request is a fill. See router/segment-resolution/prefetch-deferral.ts.
|
|
391
398
|
*/
|
|
392
399
|
_prefetchDeferral?: import("../router/segment-resolution/prefetch-deferral.js").PrefetchDeferral;
|
|
400
|
+
/**
|
|
401
|
+
* @internal A revalidate() predicate that read the source page
|
|
402
|
+
* (`currentParams`, `currentUrl`, `fromRouteName`) kept a held segment, so
|
|
403
|
+
* this match's diff is right for that source only (#1331). Set by
|
|
404
|
+
* evaluateRevalidation (router/revalidation.ts); match-result.ts turns it
|
|
405
|
+
* into `sourceHeld`, which scopes a prefetch of the response to its source.
|
|
406
|
+
*/
|
|
407
|
+
_sourceHeld?: true;
|
|
393
408
|
/**
|
|
394
409
|
* @internal DSL loaders registered and not started, by `$$id`: a prefetch
|
|
395
410
|
* deferred them, or a pass that skips loaders (`skipLoaders`) did not run
|
|
@@ -274,6 +274,12 @@ export interface MatchResult {
|
|
|
274
274
|
* source, so the RSC handler scopes its prefetch entry to it (#1007).
|
|
275
275
|
*/
|
|
276
276
|
interceptTargeted?: true;
|
|
277
|
+
/**
|
|
278
|
+
* Set on a partial match when a revalidate() predicate read the source page
|
|
279
|
+
* and kept a held segment: the diff is that source's. The RSC handler
|
|
280
|
+
* scopes its prefetch entry to it, like `interceptTargeted` (#1331).
|
|
281
|
+
*/
|
|
282
|
+
sourceHeld?: true;
|
|
277
283
|
/**
|
|
278
284
|
* Redirect URL for trailing slash normalization.
|
|
279
285
|
* When set, the RSC handler should return a 308 redirect to this URL
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The discovery temp RSC server: a minimal Vite server whose module runner
|
|
3
3
|
* imports the user's router files. Shared by dev discovery
|
|
4
|
-
* (discovery/dev-server-phase.ts)
|
|
5
|
-
* (discovery/build-discovery-phase.ts)
|
|
4
|
+
* (discovery/dev-server-phase.ts), build discovery
|
|
5
|
+
* (discovery/build-discovery-phase.ts) and `rango generate --runtime`
|
|
6
|
+
* (build/runtime-discovery.ts).
|
|
6
7
|
*
|
|
7
8
|
* Sits in src/vite/, not src/vite/discovery/: the loader hook URL below
|
|
8
|
-
* resolves against this module's import.meta.url, and the published
|
|
9
|
-
* (dist/vite/index.js)
|
|
9
|
+
* resolves against this module's import.meta.url, and the published bundles
|
|
10
|
+
* (dist/vite/index.js, dist/bin/rango.js) ship the hook at the same relative
|
|
11
|
+
* path.
|
|
10
12
|
*/
|
|
11
13
|
import type { ViteDevServer } from "vite";
|
|
12
14
|
import type { DiscoveryState } from "./discovery/state.js";
|
|
@@ -36,4 +38,6 @@ export declare function createTempRscServer(state: DiscoveryState, options?: {
|
|
|
36
38
|
* shell capture actually runs.
|
|
37
39
|
*/
|
|
38
40
|
realSsrEntry?: boolean;
|
|
41
|
+
/** Caller-specific plugins, appended after the forwarded user plugins. */
|
|
42
|
+
plugins?: import("vite").Plugin[];
|
|
39
43
|
}): Promise<ViteDevServer>;
|
|
@@ -1,4 +1,34 @@
|
|
|
1
1
|
import type { Plugin, ResolvedConfig, UserConfig } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* Whether a user plugin must NOT be forwarded into the discovery temp server.
|
|
4
|
+
*
|
|
5
|
+
* Framework-owned plugins are matched precisely -- by exact name or a
|
|
6
|
+
* namespaced prefix -- rather than by a loose substring/word prefix, so an
|
|
7
|
+
* unrelated user resolver named e.g. `rsc-paths` or `cloudflare-kv-alias` is
|
|
8
|
+
* still forwarded (it would otherwise reproduce issue #500).
|
|
9
|
+
*
|
|
10
|
+
* - `vite:*` Vite core + official plugins (incl.
|
|
11
|
+
* @vitejs/plugin-react's `vite:react-*`). The temp
|
|
12
|
+
* server already provides its own core; forwarding
|
|
13
|
+
* these would duplicate or conflict with it.
|
|
14
|
+
* - `rsc` / `rsc:*` @vitejs/plugin-rsc. createTempRscServer instantiates
|
|
15
|
+
* its own rsc() plugin; forwarding would duplicate it.
|
|
16
|
+
* Matched exactly (`rsc`) or by the `rsc:` namespace --
|
|
17
|
+
* NOT every `rsc`-prefixed name.
|
|
18
|
+
* - `@rangojs/router*` Our own plugins. The discovery plugin spawns the
|
|
19
|
+
* temp server, so forwarding would recurse infinitely.
|
|
20
|
+
* - `@cloudflare/vite-plugin*` / @cloudflare/vite-plugin (emits the scoped
|
|
21
|
+
* `vite-plugin-cloudflare*` `@cloudflare/vite-plugin` and unscoped
|
|
22
|
+
* `vite-plugin-cloudflare` / `vite-plugin-cloudflare:*`).
|
|
23
|
+
* Forwarding re-inits workerd, defeating the Node temp
|
|
24
|
+
* server. Matched specifically so a scoped user resolver
|
|
25
|
+
* like `@cloudflare/kv-alias` is still forwarded.
|
|
26
|
+
*
|
|
27
|
+
* `rango generate --runtime` drops these before it resolves the user's config,
|
|
28
|
+
* so rango()'s configResolved (which writes the static gen files) and the
|
|
29
|
+
* Cloudflare plugin's config hooks never run there.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isFrameworkPlugin(name: string): boolean;
|
|
2
32
|
/**
|
|
3
33
|
* Pick the user's resolution plugins from the resolved plugin list, denylist
|
|
4
34
|
* framework-owned plugins, keep only those with resolution hooks, and strip
|
|
@@ -20,6 +50,8 @@ export interface ForwardedRunnerConfig {
|
|
|
20
50
|
/**
|
|
21
51
|
* Extract the data-only config slice to mirror into the discovery temp server.
|
|
22
52
|
* `alias` is included here so callers no longer need to thread it separately.
|
|
53
|
+
* Accepts the unresolved config too: `rango generate --runtime` passes the
|
|
54
|
+
* config file's own values, without what plugin `config` hooks add.
|
|
23
55
|
*
|
|
24
56
|
* `tsconfigPaths` is forwarded so Vite 8's native tsconfig `paths` resolution
|
|
25
57
|
* (a top-level `resolve` flag, off by default) reaches the temp server. The
|
|
@@ -34,4 +66,4 @@ export interface ForwardedRunnerConfig {
|
|
|
34
66
|
* replaced the deprecated `esbuild` transform option with `oxc`, so we read and
|
|
35
67
|
* forward `oxc` exclusively — no `esbuild` field is touched.
|
|
36
68
|
*/
|
|
37
|
-
export declare function pickForwardedRunnerConfig(config: ResolvedConfig): ForwardedRunnerConfig;
|
|
69
|
+
export declare function pickForwardedRunnerConfig(config: Pick<ResolvedConfig | UserConfig, "resolve" | "define" | "oxc">): ForwardedRunnerConfig;
|