@rangojs/router 0.21.0 → 0.22.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/rango.js +13 -1
- package/dist/types/browser/event-controller.d.ts +30 -13
- package/dist/types/browser/navigation-store.d.ts +9 -0
- package/dist/types/browser/partial-update.d.ts +2 -1
- package/dist/types/browser/prefetch/default-strategy.d.ts +16 -20
- package/dist/types/browser/react/NavigationProvider.d.ts +14 -1
- package/dist/types/browser/react/context.d.ts +14 -0
- package/dist/types/browser/rsc-router.d.ts +13 -2
- package/dist/types/browser/types.d.ts +10 -0
- package/dist/types/build/generate-manifest.d.ts +2 -0
- package/dist/types/cache/background-task.d.ts +22 -0
- package/dist/types/cache/cache-key-utils.d.ts +50 -5
- package/dist/types/cache/cache-policy.d.ts +17 -0
- package/dist/types/cache/cache-scope.d.ts +1 -1
- package/dist/types/cache/cf/cf-cache-store.d.ts +7 -1
- package/dist/types/cache/document-cache.d.ts +8 -5
- package/dist/types/cache/handle-snapshot.d.ts +23 -0
- package/dist/types/cache/index.d.ts +1 -1
- package/dist/types/cache/invalidation-order.d.ts +14 -0
- package/dist/types/cache/memory-segment-store.d.ts +33 -1
- package/dist/types/cache/shell-snapshot.d.ts +10 -1
- package/dist/types/cache/store-scope.d.ts +22 -0
- package/dist/types/cache/tag-invalidation.d.ts +7 -6
- package/dist/types/cache/types.d.ts +63 -14
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +7 -1
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/handles/deferred-resolution.d.ts +7 -0
- package/dist/types/internal-suspense-audit.d.ts +1 -0
- package/dist/types/loader-store.d.ts +4 -8
- package/dist/types/outlet-provider.d.ts +2 -1
- package/dist/types/prerender/cloudflare.d.ts +49 -0
- package/dist/types/prerender/create-prerender-trigger.d.ts +121 -0
- package/dist/types/prerender/index.d.ts +12 -0
- package/dist/types/prerender/memory-prerender-store.d.ts +29 -0
- package/dist/types/prerender/on-demand.d.ts +272 -0
- package/dist/types/prerender/producer-guard.d.ts +33 -0
- package/dist/types/prerender/shell-manifest-key.d.ts +1 -18
- package/dist/types/prerender/warm-request.d.ts +65 -0
- package/dist/types/prerender/warm.d.ts +65 -0
- package/dist/types/prerender/writable-store.d.ts +170 -0
- package/dist/types/prerender.d.ts +27 -0
- package/dist/types/reverse.d.ts +1 -1
- package/dist/types/route-content-wrapper.d.ts +3 -1
- package/dist/types/router/error-handling.d.ts +2 -0
- package/dist/types/router/handler-context.d.ts +1 -1
- package/dist/types/router/match-middleware/cache-lookup.d.ts +14 -0
- package/dist/types/router/pattern-matching.d.ts +2 -0
- package/dist/types/router/prefetch-default.d.ts +4 -4
- package/dist/types/router/prerender-match.d.ts +23 -1
- package/dist/types/router/route-trie-builder.d.ts +8 -1
- package/dist/types/router/router-context.d.ts +1 -0
- package/dist/types/router/router-interfaces.d.ts +30 -0
- package/dist/types/router/router-options.d.ts +24 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +7 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +2 -1
- package/dist/types/router/segment-resolution/revalidation.d.ts +5 -1
- package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +43 -0
- package/dist/types/router/trie-matching.d.ts +2 -0
- package/dist/types/rsc/shell-build-manifest.d.ts +6 -4
- package/dist/types/rsc/shell-capture-constants.d.ts +20 -5
- package/dist/types/rsc/shell-capture.d.ts +14 -1
- package/dist/types/rsc/shell-serve.d.ts +2 -2
- package/dist/types/rsc/ssr-module-loader.d.ts +15 -0
- package/dist/types/rsc/types.d.ts +8 -0
- package/dist/types/segment-boundary-content.d.ts +17 -0
- package/dist/types/segment-loader-promise.d.ts +2 -6
- package/dist/types/server/build-version-table.d.ts +9 -0
- package/dist/types/server/context.d.ts +12 -4
- package/dist/types/server/handle-store.d.ts +2 -0
- package/dist/types/server/request-context.d.ts +63 -2
- package/dist/types/suspense-audit-react.d.ts +26 -0
- package/dist/types/suspense-audit.d.ts +157 -0
- package/dist/types/testing/action-form.d.ts +34 -0
- package/dist/types/testing/flight.entry.d.ts +2 -0
- package/dist/types/testing/index.d.ts +4 -0
- package/dist/types/testing/internal/server-modules.d.ts +8 -0
- package/dist/types/testing/serve-shell-request.d.ts +34 -4
- package/dist/types/testing/shell-status.d.ts +14 -6
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +9 -6
- package/dist/types/thenable-status.d.ts +6 -0
- package/dist/types/types/handler-context.d.ts +7 -0
- package/dist/types/types/route-entry.d.ts +5 -0
- package/dist/types/urls/path-helper.d.ts +18 -0
- package/dist/types/vite/discovery/state.d.ts +11 -0
- package/dist/types/vite/inject-client-debug.d.ts +6 -25
- package/dist/types/vite/utils/bundle-analysis.d.ts +6 -2
- package/dist/vite/index.js +179 -496
- package/package.json +12 -2
- package/skills/cache-guide/SKILL.md +18 -17
- package/skills/caching/SKILL.md +40 -4
- package/skills/catalog.json +1 -1
- package/skills/cloudflare/SKILL.md +131 -0
- package/skills/comparison/references/framework-comparison.md +1 -1
- package/skills/deployment-caching/SKILL.md +33 -12
- package/skills/document-cache/SKILL.md +16 -14
- package/skills/hooks/SKILL.md +22 -0
- package/skills/hooks/handle-and-actions.md +3 -4
- package/skills/hooks/navigation.md +10 -0
- package/skills/hooks/state.md +5 -4
- package/skills/host-router/SKILL.md +18 -0
- package/skills/loader/SKILL.md +6 -4
- package/skills/middleware/SKILL.md +1 -1
- package/skills/migrate-nextjs/SKILL.md +82 -9
- package/skills/ppr/SKILL.md +31 -8
- package/skills/prerender/SKILL.md +645 -8
- package/skills/rango/SKILL.md +1 -0
- package/skills/response-routes/SKILL.md +5 -5
- package/skills/route/SKILL.md +29 -0
- package/skills/testing/SKILL.md +2 -1
- package/skills/testing/cache-prerender.md +18 -17
- package/skills/testing/serve-shell-request.md +104 -8
- package/skills/use-cache/SKILL.md +9 -5
- package/skills/vercel/SKILL.md +2 -0
- package/skills/view-transitions/SKILL.md +9 -4
- package/src/browser/event-controller.ts +69 -25
- package/src/browser/link-interceptor.ts +2 -2
- package/src/browser/navigation-bridge.ts +75 -35
- package/src/browser/navigation-store.ts +26 -0
- package/src/browser/navigation-transaction.ts +9 -2
- package/src/browser/network-error-handler.ts +2 -0
- package/src/browser/partial-update.ts +48 -12
- package/src/browser/prefetch/default-strategy.ts +22 -42
- package/src/browser/react/Link.tsx +37 -42
- package/src/browser/react/NavigationProvider.tsx +63 -3
- package/src/browser/react/context.ts +17 -0
- package/src/browser/react/location-state.ts +5 -19
- package/src/browser/react/use-action.ts +4 -1
- package/src/browser/react/use-handle.ts +4 -20
- package/src/browser/react/use-link-status.ts +4 -3
- package/src/browser/react/use-navigation.ts +4 -1
- package/src/browser/react/use-params.ts +4 -1
- package/src/browser/react/use-pathname.ts +4 -1
- package/src/browser/react/use-search-params.ts +5 -3
- package/src/browser/react/use-segments.ts +36 -54
- package/src/browser/rsc-router.tsx +79 -39
- package/src/browser/segment-reconciler.ts +3 -3
- package/src/browser/server-action-bridge.ts +26 -6
- package/src/browser/types.ts +11 -0
- package/src/build/generate-manifest.ts +17 -0
- package/src/build/merge-full-manifests.ts +5 -0
- package/src/build/route-trie.ts +1 -0
- package/src/cache/background-task.ts +61 -0
- package/src/cache/cache-key-utils.ts +91 -12
- package/src/cache/cache-policy.ts +11 -2
- package/src/cache/cache-runtime.ts +23 -23
- package/src/cache/cache-scope.ts +38 -36
- package/src/cache/cf/cf-cache-store.ts +16 -11
- package/src/cache/document-cache.ts +35 -14
- package/src/cache/handle-snapshot.ts +50 -0
- package/src/cache/index.ts +1 -0
- package/src/cache/invalidation-order.ts +53 -0
- package/src/cache/memory-segment-store.ts +52 -1
- package/src/cache/shell-snapshot.ts +17 -0
- package/src/cache/store-scope.ts +36 -0
- package/src/cache/tag-invalidation.ts +7 -5
- package/src/cache/types.ts +69 -14
- package/src/cache/vercel/vercel-cache-store.ts +20 -6
- package/src/client.tsx +40 -3
- package/src/errors.ts +13 -6
- package/src/handles/deferred-resolution.ts +7 -2
- package/src/internal-suspense-audit.ts +12 -0
- package/src/loader-store.ts +4 -9
- package/src/outlet-provider.tsx +25 -1
- package/src/prerender/cloudflare.ts +130 -0
- package/src/prerender/create-prerender-trigger.ts +780 -0
- package/src/prerender/index.ts +39 -0
- package/src/prerender/memory-prerender-store.ts +115 -0
- package/src/prerender/on-demand.ts +339 -0
- package/src/prerender/producer-guard.ts +66 -0
- package/src/prerender/shell-manifest-key.ts +12 -17
- package/src/prerender/warm-request.ts +154 -0
- package/src/prerender/warm.ts +193 -0
- package/src/prerender/writable-store.ts +278 -0
- package/src/prerender.ts +29 -0
- package/src/reverse.ts +1 -1
- package/src/route-content-wrapper.tsx +107 -13
- package/src/router/error-handling.ts +12 -12
- package/src/router/find-match.ts +1 -0
- package/src/router/handler-context.ts +2 -0
- package/src/router/intercept-resolution.ts +15 -8
- package/src/router/loader-resolution.ts +2 -10
- package/src/router/match-middleware/background-revalidation.ts +2 -0
- package/src/router/match-middleware/cache-lookup.ts +230 -38
- package/src/router/pattern-matching.ts +14 -0
- package/src/router/prefetch-default.ts +4 -4
- package/src/router/prerender-match.ts +460 -352
- package/src/router/route-trie-builder.ts +9 -0
- package/src/router/router-context.ts +1 -0
- package/src/router/router-interfaces.ts +33 -0
- package/src/router/router-options.ts +30 -0
- package/src/router/segment-resolution/fresh.ts +20 -19
- package/src/router/segment-resolution/loader-cache.ts +15 -17
- package/src/router/segment-resolution/revalidation.ts +34 -24
- package/src/router/segment-resolution/streamed-handler-boundary.ts +133 -0
- package/src/router/trie-matching.ts +3 -0
- package/src/router.ts +107 -1
- package/src/rsc/handler.ts +51 -4
- package/src/rsc/progressive-enhancement.ts +5 -1
- package/src/rsc/response-cache-serve.ts +10 -4
- package/src/rsc/rsc-rendering.ts +53 -11
- package/src/rsc/shell-build-manifest.ts +10 -8
- package/src/rsc/shell-capture-constants.ts +39 -7
- package/src/rsc/shell-capture.ts +108 -19
- package/src/rsc/shell-serve.ts +12 -6
- package/src/rsc/ssr-module-loader.ts +26 -0
- package/src/rsc/types.ts +8 -0
- package/src/segment-boundary-content.ts +25 -0
- package/src/segment-loader-promise.ts +28 -38
- package/src/segment-system.tsx +117 -57
- package/src/server/build-version-table.ts +15 -0
- package/src/server/context.ts +40 -17
- package/src/server/cookie-store.ts +5 -0
- package/src/server/handle-store.ts +13 -0
- package/src/server/request-context.ts +87 -1
- package/src/ssr/ssr-root.tsx +20 -13
- package/src/suspense-audit-react.tsx +98 -0
- package/src/suspense-audit.ts +1030 -0
- package/src/testing/action-form.ts +66 -0
- package/src/testing/flight-runtime.d.ts +27 -0
- package/src/testing/flight.entry.ts +3 -0
- package/src/testing/index.ts +19 -0
- package/src/testing/internal/server-modules.ts +32 -0
- package/src/testing/render-route.tsx +25 -12
- package/src/testing/serve-shell-request.ts +190 -34
- package/src/testing/shell-status.ts +17 -6
- package/src/testing/vitest-stubs/plugin-rsc.ts +37 -11
- package/src/thenable-status.ts +10 -0
- package/src/types/handler-context.ts +7 -0
- package/src/types/route-entry.ts +6 -0
- package/src/urls/path-helper.ts +69 -9
- package/src/use-loader.tsx +57 -30
- package/src/vite/discovery/bundle-postprocess.ts +4 -0
- package/src/vite/discovery/discover-routers.ts +15 -0
- package/src/vite/discovery/shell-prerender-phase.ts +5 -5
- package/src/vite/discovery/state.ts +17 -1
- package/src/vite/inject-client-debug.ts +42 -20
- package/src/vite/plugins/virtual-entries.ts +8 -1
- package/src/vite/router-discovery.ts +14 -0
- package/src/vite/utils/bundle-analysis.ts +39 -7
- package/dist/types/browser/react/subscribe-to-nothing.d.ts +0 -7
- package/dist/types/segment-content-promise.d.ts +0 -13
- package/src/browser/react/subscribe-to-nothing.ts +0 -7
- package/src/segment-content-promise.ts +0 -67
|
@@ -3,6 +3,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
import type { PartialCacheOptions, ErrorBoundaryHandler, Handler, LoaderDefinition, MiddlewareFn, NotFoundBoundaryHandler, ShouldRevalidateFn, TransitionConfig } from "../types";
|
|
5
5
|
import type { ContextVar } from "../context-var.js";
|
|
6
|
+
import { type WarmContext } from "../prerender/warm-request.js";
|
|
6
7
|
/**
|
|
7
8
|
* Performance metric entry for a single measured operation
|
|
8
9
|
*
|
|
@@ -219,8 +220,11 @@ export type EntryData = ({
|
|
|
219
220
|
getParams?: (ctx: any) => Promise<any[]> | any[];
|
|
220
221
|
options?: {
|
|
221
222
|
concurrency?: number;
|
|
223
|
+
onDemand?: import("../prerender/on-demand.js").OnDemandOption;
|
|
222
224
|
};
|
|
223
225
|
};
|
|
226
|
+
/** Set when the route opted into on-demand prerender (Prerender(..., { onDemand })) */
|
|
227
|
+
isOnDemand?: true;
|
|
224
228
|
/** Set when route is wrapped with Passthrough() — has a separate live handler */
|
|
225
229
|
isPassthrough?: true;
|
|
226
230
|
/** Live handler for runtime fallback (only set on Passthrough routes) */
|
|
@@ -341,6 +345,7 @@ export declare const getContext: () => {
|
|
|
341
345
|
getStore: () => HelperContext;
|
|
342
346
|
getParent: () => EntryData | null;
|
|
343
347
|
getOrCreateStore: (forRoute?: string) => HelperContext;
|
|
348
|
+
runIsolated: <T>(forRoute: string, callback: () => T) => T;
|
|
344
349
|
getNextIndex: (type: (string & {}) | "layout" | "parallel" | "middleware" | "revalidate") => string;
|
|
345
350
|
getShortCode: (type: "layout" | "parallel" | "route" | "loader" | "cache") => string;
|
|
346
351
|
run: <T>(namespace: string, parent: EntryData | null, callback: (...args: any[]) => T) => T;
|
|
@@ -483,12 +488,12 @@ export interface IdentityReadWording {
|
|
|
483
488
|
* response directives (invalidateClientCache(), keepClientCache()) record
|
|
484
489
|
* nothing and are not captured reads: they take refuseInCacheScope alone.
|
|
485
490
|
*/
|
|
486
|
-
export declare function guardIdentityRead(ctx:
|
|
491
|
+
export declare function guardIdentityRead(ctx: WarmContext | null | undefined, surface: string, wording: IdentityReadWording): void;
|
|
487
492
|
/**
|
|
488
493
|
* Steps 2 and 3 of guardIdentityRead: throw when a "use cache" body or a
|
|
489
494
|
* cache() boundary would store what `surface` produces.
|
|
490
495
|
*/
|
|
491
|
-
export declare function refuseInCacheScope(surface: string, { verb, fix }: IdentityReadWording): void;
|
|
496
|
+
export declare function refuseInCacheScope(surface: string, { verb, fix }: IdentityReadWording, ctx?: WarmContext | null): void;
|
|
492
497
|
/**
|
|
493
498
|
* The capture refusal for a request-scoped read (cookies(), headers(), a
|
|
494
499
|
* { cache: false } variable): the message after the surface, and the fix the
|
|
@@ -502,7 +507,7 @@ export declare function requestReadCaptureFix(what: string): Pick<IdentityReadWo
|
|
|
502
507
|
* scope lookups. `requestCtx` is the ambient request context, whose capture
|
|
503
508
|
* flag the guard reads.
|
|
504
509
|
*/
|
|
505
|
-
export declare function assertNonCacheableReadAllowed(keyOrVar: string | ContextVar<unknown>, requestCtx?:
|
|
510
|
+
export declare function assertNonCacheableReadAllowed(keyOrVar: string | ContextVar<unknown>, requestCtx?: WarmContext | null): void;
|
|
506
511
|
/** How the identity error words a read: a function call or a property read. */
|
|
507
512
|
export type LoaderIdentityReadVerb = "called" | "read";
|
|
508
513
|
/** A request-identity read a loader execution made (recordLoaderIdentityRead). */
|
|
@@ -598,7 +603,10 @@ export declare function latchCachedHeaderScope(kind: CachedHeaderScope["kind"],
|
|
|
598
603
|
export declare function isInsideAnyLoaderScope(): boolean;
|
|
599
604
|
/**
|
|
600
605
|
* The one ppr opt-in predicate: a page route entry that DECLARED `ppr`
|
|
601
|
-
* (`false
|
|
606
|
+
* (`false`, undefined, and on-demand routes mean plain axis 1). A writable
|
|
607
|
+
* prerender refresh cannot atomically replace the separate document shell, so
|
|
608
|
+
* combining those lanes would pair a fresh tail with a stale prelude. Shared by
|
|
609
|
+
* the serve path
|
|
602
610
|
* (rsc/shell-serve.ts resolvePprConfig) and the header-write latch below so
|
|
603
611
|
* the two layers can never drift on what counts as a ppr route.
|
|
604
612
|
*/
|
|
@@ -218,6 +218,8 @@ export interface HandleStore {
|
|
|
218
218
|
* value are omitted; undefined when none has one.
|
|
219
219
|
*/
|
|
220
220
|
getRecordOwners(segmentId: string): Record<string, (string | null)[]> | undefined;
|
|
221
|
+
/** The segment ids for which getRecordOwners returns an entry. */
|
|
222
|
+
getOwnedSegmentIds(): string[];
|
|
221
223
|
/**
|
|
222
224
|
* Replay cached handle data back into the store (for cache hits).
|
|
223
225
|
* Used to restore handle data when serving cached segments.
|
|
@@ -19,7 +19,7 @@ import type { Handle } from "../handle.js";
|
|
|
19
19
|
import { type ContextVar } from "../context-var.js";
|
|
20
20
|
import { type HandleStore, type HandleData } from "./handle-store.js";
|
|
21
21
|
import { type MetricsStore } from "./context.js";
|
|
22
|
-
import type { SegmentCacheStore } from "../cache/types.js";
|
|
22
|
+
import type { SegmentCacheStore, ShellSnapshotHandlesValue } from "../cache/types.js";
|
|
23
23
|
import type { RouterVersions } from "../router-versions.js";
|
|
24
24
|
import type { Theme, ResolvedThemeConfig } from "../theme/types.js";
|
|
25
25
|
import type { ExecutionContext, RequestScope } from "../types/request-scope.js";
|
|
@@ -204,6 +204,25 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
204
204
|
_pprReplayPostMatchReason?: "prerender-store" | "intercept";
|
|
205
205
|
/** @internal Cache store for segment caching (optional, used by CacheScope) */
|
|
206
206
|
_cacheStore?: SegmentCacheStore;
|
|
207
|
+
/**
|
|
208
|
+
* @internal Env-scoped writable prerender store (the durable overlay) plus the
|
|
209
|
+
* deployment identity for build-scoped keys, resolved per request from the
|
|
210
|
+
* `prerender` router option. Read by the serve-path overlay lookup before the
|
|
211
|
+
* bundled build manifest. Absent when no prerender store is configured.
|
|
212
|
+
*/
|
|
213
|
+
_prerender?: import("../prerender/on-demand.js").ResolvedPrerender<any>;
|
|
214
|
+
/**
|
|
215
|
+
* @internal Set only on the requestless on-demand producer's context. When
|
|
216
|
+
* present, the standalone request-scoped READS — `cookies()`, `headers()`,
|
|
217
|
+
* `invalidateClientCache()`, `keepClientCache()` — throw a
|
|
218
|
+
* PrerenderPersonalizationError so a personalized render is skipped rather than
|
|
219
|
+
* baked into a shared payload. Response MUTATIONS on the producer context
|
|
220
|
+
* (`ctx.setStatus`/`header`/`setCookie`) stay silent no-op stubs, matching
|
|
221
|
+
* build-time prerender (the design's "throw or skip" contract permits skip):
|
|
222
|
+
* they write to a discarded synthetic response, so there is nothing to leak.
|
|
223
|
+
* Never set on the live request path.
|
|
224
|
+
*/
|
|
225
|
+
_onDemandProducer?: true;
|
|
207
226
|
/**
|
|
208
227
|
* @internal Compiled `cache.searchParams` filter for default cache-key
|
|
209
228
|
* generation (undefined = "all", the byte-stable unfiltered format). Set
|
|
@@ -272,6 +291,20 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
272
291
|
* cache miss.
|
|
273
292
|
*/
|
|
274
293
|
_shellForcedMiss?: true;
|
|
294
|
+
/**
|
|
295
|
+
* @internal This request is a router.prerender() warm
|
|
296
|
+
* (prerender/warm-request.ts). In `replace` mode every runtime cache read
|
|
297
|
+
* misses (isWarmReplace); the layers report into the record. A capture's
|
|
298
|
+
* derived context inherits it through the prototype.
|
|
299
|
+
*/
|
|
300
|
+
_prerenderWarm?: import("../prerender/warm-request.js").PrerenderWarmRecord;
|
|
301
|
+
/**
|
|
302
|
+
* @internal Runs a callback in the async context this request entered the
|
|
303
|
+
* handler with (captureRequestEntryContext). router.prerender() dispatches
|
|
304
|
+
* a warm through it when called from inside a request. Absent where the
|
|
305
|
+
* runtime has no AsyncLocalStorage.snapshot.
|
|
306
|
+
*/
|
|
307
|
+
_runAtRequestEntry?: <T>(fn: () => T) => T;
|
|
275
308
|
/**
|
|
276
309
|
* @internal The freshness window of the route cache() records this
|
|
277
310
|
* request read or wrote (cache-scope.ts noteRouteRecordWindow), as ms
|
|
@@ -361,6 +394,8 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
361
394
|
* host) and miss the record.
|
|
362
395
|
*/
|
|
363
396
|
fixedDocKey?: string;
|
|
397
|
+
/** @internal The snapshot's `handles` record (ShellSnapshotHandlesValue). */
|
|
398
|
+
prerenderHandles?: ShellSnapshotHandlesValue;
|
|
364
399
|
/**
|
|
365
400
|
* @internal Set ONLY by matchPartialWithPprReplay on the navigation-replay
|
|
366
401
|
* serve path. Its presence arms the explicit-scope composition in
|
|
@@ -672,6 +707,17 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
672
707
|
* deriveShellCaptureContext gives the capture its own.
|
|
673
708
|
*/
|
|
674
709
|
_renderErrors?: unknown[];
|
|
710
|
+
/**
|
|
711
|
+
* @internal Rejections of streamed (loading()) handlers that were recovered
|
|
712
|
+
* into a declared errorBoundary()/notFoundBoundary() fallback, by segment id.
|
|
713
|
+
* The recovered promise resolves, so Flight reports nothing; cacheRoute
|
|
714
|
+
* (cache-scope.ts) refuses a write only when one of ITS segments is listed,
|
|
715
|
+
* the granularity a Flight error row has. The same errors are also pushed to
|
|
716
|
+
* `_renderErrors` for the document cache and PPR shell capture. A render
|
|
717
|
+
* under a derived context (shell capture, SWR re-render) owns its own map.
|
|
718
|
+
* Allocated on the first recovery.
|
|
719
|
+
*/
|
|
720
|
+
_recoveredHandlerErrors?: Map<string, unknown>;
|
|
675
721
|
/**
|
|
676
722
|
* @internal Report a non-fatal background error through the router's
|
|
677
723
|
* onError callback. Wired by the RSC handler / router during request
|
|
@@ -757,7 +803,7 @@ export interface RouteRecordWindow {
|
|
|
757
803
|
* This is the type exported to library consumers. Internal code should
|
|
758
804
|
* use the full RequestContext interface directly.
|
|
759
805
|
*/
|
|
760
|
-
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_searchParamsFilter" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureUnrecordedLoaderPush" | "_shellCaptureLoaderLanes" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_routeRecordWindow" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_locationState" | "_routeName" | "_prevRouteKey" | "_inActionRevalidation" | "_reportedErrors" | "_renderErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_versions" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
806
|
+
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" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureUnrecordedLoaderPush" | "_shellCaptureLoaderLanes" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_prerenderWarm" | "_runAtRequestEntry" | "_routeRecordWindow" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_locationState" | "_routeName" | "_prevRouteKey" | "_inActionRevalidation" | "_reportedErrors" | "_renderErrors" | "_recoveredHandlerErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_versions" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
761
807
|
/**
|
|
762
808
|
* Marker for a waitUntil-scheduled fn whose task promise must NOT enter
|
|
763
809
|
* _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
|
|
@@ -766,6 +812,15 @@ export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, str
|
|
|
766
812
|
* @internal
|
|
767
813
|
*/
|
|
768
814
|
export declare const UNTRACKED_BACKGROUND_TASK: unique symbol;
|
|
815
|
+
/**
|
|
816
|
+
* Capture the current async context (RequestContext._runAtRequestEntry), taken
|
|
817
|
+
* on handler entry before any router scope, so a nested dispatch (a
|
|
818
|
+
* router.prerender() warm called from a handler, loader or action) does not
|
|
819
|
+
* inherit the caller's route-definition, loader and cache-scope state. Per
|
|
820
|
+
* request: workerd refuses a snapshot outside the request that created it.
|
|
821
|
+
* See docs/design/prerender-every-route.md.
|
|
822
|
+
*/
|
|
823
|
+
export declare function captureRequestEntryContext(): (<T>(fn: () => T) => T) | undefined;
|
|
769
824
|
/**
|
|
770
825
|
* Run a function within a request context
|
|
771
826
|
* Used by the RSC handler to provide context to server actions
|
|
@@ -813,6 +868,12 @@ export interface CreateRequestContextOptions<TEnv> {
|
|
|
813
868
|
initialResponse?: Response;
|
|
814
869
|
/** Optional cache store for segment caching (used by CacheScope) */
|
|
815
870
|
cacheStore?: SegmentCacheStore;
|
|
871
|
+
/**
|
|
872
|
+
* Optional env-scoped writable prerender store + deployment identity (the
|
|
873
|
+
* durable overlay), resolved per request by the RSC handler from the
|
|
874
|
+
* `prerender` router option.
|
|
875
|
+
*/
|
|
876
|
+
prerender?: import("../prerender/on-demand.js").ResolvedPrerender<any>;
|
|
816
877
|
/**
|
|
817
878
|
* Compiled `cache.searchParams` filter from the resolved handler cache
|
|
818
879
|
* config (handler.ts). Stored as _searchParamsFilter.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type BoundaryAudit } from "./suspense-audit.js";
|
|
3
|
+
/**
|
|
4
|
+
* One boundary: what each render hands it, what each commit carries, and its
|
|
5
|
+
* mount. Called above the Suspense, which commits while the content waits.
|
|
6
|
+
* `streams` and `nodes` are what else its content waits for (I3 only).
|
|
7
|
+
*/
|
|
8
|
+
export declare function useBoundaryAudit(boundary: string, segmentId: string, value: unknown, streams?: Record<string, unknown>, nodes?: unknown): BoundaryAudit;
|
|
9
|
+
/** The boundary's content is on screen. */
|
|
10
|
+
export declare function useRevealAudit(rec: BoundaryAudit): void;
|
|
11
|
+
/**
|
|
12
|
+
* One `useLoader` read of a per-loader stream (I1, I2 at the read site). A
|
|
13
|
+
* read that suspends while mounting keeps no record: only a reader on screen
|
|
14
|
+
* is audited.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useReadAudit(loaderId: string, stream: unknown): void;
|
|
17
|
+
/** Wraps a boundary's fallback: mounted means the fallback is on screen. */
|
|
18
|
+
export declare function AuditedFallback({ audit, children, }: {
|
|
19
|
+
audit: BoundaryAudit;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
}): ReactNode;
|
|
22
|
+
/** Wraps a segment's outlet children: the segment's mount (I4). */
|
|
23
|
+
export declare function AuditedOutlet({ segmentId, children, }: {
|
|
24
|
+
segmentId: string;
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
}): ReactNode;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export type SuspenseAuditKind = "swap" | "untracked" | "idle-fallback" | "resuspended" | "remount" | "drift" | "uncaused" | "mutated";
|
|
2
|
+
/** What may hand React a tree (I6). */
|
|
3
|
+
export type TreeUpdateCause = "navigation" | "popstate" | "stale-revalidation" | "action" | "error" | "hmr";
|
|
4
|
+
export interface SuspenseAuditEvent {
|
|
5
|
+
/** I1 swap, I2 untracked, I3 idle-fallback and resuspended, I4 remount, I5 drift, I6 uncaused, I7 mutated. */
|
|
6
|
+
kind: SuspenseAuditKind;
|
|
7
|
+
/** `content:<segment id>`, `loaders:<outlet key>`, `outlet:<segment id>`, `read:<loader id>`, `segment:<segment id>`. */
|
|
8
|
+
boundary: string;
|
|
9
|
+
detail: string;
|
|
10
|
+
url: string;
|
|
11
|
+
at: number;
|
|
12
|
+
}
|
|
13
|
+
export interface SuspenseAuditReport {
|
|
14
|
+
swaps: number;
|
|
15
|
+
untracked: number;
|
|
16
|
+
idleFallbacks: number;
|
|
17
|
+
resuspended: number;
|
|
18
|
+
remounts: number;
|
|
19
|
+
drifts: number;
|
|
20
|
+
uncaused: number;
|
|
21
|
+
mutations: number;
|
|
22
|
+
/**
|
|
23
|
+
* Not a violation: fallbacks the router cannot attribute. Nothing it handed
|
|
24
|
+
* the boundary was a promise React read, so the content's own suspension
|
|
25
|
+
* put the fallback up: an app's use(), a React.lazy, a client reference.
|
|
26
|
+
*/
|
|
27
|
+
unattributedFallbacks: number;
|
|
28
|
+
/** Not a violation: tree updates React was handed, by cause ("none" without one). */
|
|
29
|
+
treeUpdates: Record<string, number>;
|
|
30
|
+
/**
|
|
31
|
+
* Not a violation: the distinct thenables each boundary or read was handed.
|
|
32
|
+
* One per value it waited for; two for one navigation is a gate replaced
|
|
33
|
+
* by the real promise.
|
|
34
|
+
*/
|
|
35
|
+
readonly handed: Record<string, number>;
|
|
36
|
+
/**
|
|
37
|
+
* Not a violation: fallbacks shown over content on screen while what the
|
|
38
|
+
* boundary waits for was pending. An urgent commit does that by design.
|
|
39
|
+
*/
|
|
40
|
+
shownWhilePending: number;
|
|
41
|
+
/** Mounts per boundary since the document loaded. */
|
|
42
|
+
readonly mounts: Record<string, number>;
|
|
43
|
+
/** The last events, oldest first. */
|
|
44
|
+
events: SuspenseAuditEvent[];
|
|
45
|
+
reset(): void;
|
|
46
|
+
}
|
|
47
|
+
/** One boundary, or one `useLoader` read. Lives as long as its fiber. */
|
|
48
|
+
export interface BoundaryAudit {
|
|
49
|
+
boundary: string;
|
|
50
|
+
/** Segment id, for the place in the tree. */
|
|
51
|
+
segmentId: string;
|
|
52
|
+
/** The React key the segment was mounted under (I4 identity). */
|
|
53
|
+
key: string;
|
|
54
|
+
/** 0 until the boundary is on screen. */
|
|
55
|
+
mountId: number;
|
|
56
|
+
/** Last value a render ran with, and the URL it ran under. */
|
|
57
|
+
seen: unknown;
|
|
58
|
+
hasSeen: boolean;
|
|
59
|
+
seenUrl: string;
|
|
60
|
+
/** Last value a commit carried. */
|
|
61
|
+
committed: unknown;
|
|
62
|
+
hasCommitted: boolean;
|
|
63
|
+
/** What else the boundary's content waits for: per-loader streams, nodes. */
|
|
64
|
+
streams: Record<string, unknown> | undefined;
|
|
65
|
+
nodes: unknown;
|
|
66
|
+
/** The content has been on screen. */
|
|
67
|
+
revealed: boolean;
|
|
68
|
+
/** The fallback's effect was cleaned up in this task (auditFallback). */
|
|
69
|
+
fallbackGone: boolean;
|
|
70
|
+
}
|
|
71
|
+
export declare function createBoundaryAudit(boundary: string, segmentId: string): BoundaryAudit;
|
|
72
|
+
/**
|
|
73
|
+
* Render phase: the value this render hands the boundary.
|
|
74
|
+
*
|
|
75
|
+
* I1: a boundary on screen was handed a thenable that is still pending, and
|
|
76
|
+
* is handed another one that is not already settled, for the same URL. React
|
|
77
|
+
* starts waiting again. A settled replacement is read at once, and another
|
|
78
|
+
* URL is another navigation: both are exempt.
|
|
79
|
+
* I2: a boundary whose content has been on screen is handed a native promise
|
|
80
|
+
* React has not read, and React finds it settled when it reads it. A render
|
|
81
|
+
* that cannot wait suspends on it and commits the fallback over the content,
|
|
82
|
+
* which React keeps up for 300 ms. Judged from the status React leaves on
|
|
83
|
+
* the promise when it reads it in the same task.
|
|
84
|
+
*/
|
|
85
|
+
export declare function auditHandover(rec: BoundaryAudit, value: unknown): void;
|
|
86
|
+
/** Commit phase: what the boundary on screen now reads. */
|
|
87
|
+
export declare function auditCommit(rec: BoundaryAudit, value: unknown, streams?: Record<string, unknown>, nodes?: unknown): void;
|
|
88
|
+
export declare function auditReveal(rec: BoundaryAudit): void;
|
|
89
|
+
/** One `useLoader` read on screen: it has a mount and reveals with it. */
|
|
90
|
+
export declare function auditRead(rec: BoundaryAudit, stream: unknown): void;
|
|
91
|
+
/**
|
|
92
|
+
* How the audit learns that a payload is still streaming: the event
|
|
93
|
+
* controller, set at boot (browser/rsc-router.tsx). Not read from
|
|
94
|
+
* NavigationStoreContext in AuditedFallback: see the header.
|
|
95
|
+
*/
|
|
96
|
+
export declare function setSuspenseAuditStreamProbe(probe: () => boolean): void;
|
|
97
|
+
/**
|
|
98
|
+
* I3: the boundary's fallback is on screen with nothing to wait for: nothing
|
|
99
|
+
* the router handed the boundary is pending, no payload is streaming and no
|
|
100
|
+
* client reference is loading. `idle-fallback` on a boundary new to the page,
|
|
101
|
+
* `resuspended` when the fallback replaced content that had been on screen.
|
|
102
|
+
*
|
|
103
|
+
* Reported only when the router owns the fallback: React suspended on a
|
|
104
|
+
* promise the router handed unread that was already settled (`needless`).
|
|
105
|
+
* Any other fallback is the content's own (an app's use(), a React.lazy, a
|
|
106
|
+
* client reference) and is counted as `unattributedFallbacks`, not reported,
|
|
107
|
+
* also when the boundary holds a promise React has read.
|
|
108
|
+
*
|
|
109
|
+
* A fallback over content on screen while something is pending is counted
|
|
110
|
+
* (`shownWhilePending`) and not reported: an urgent commit does that by
|
|
111
|
+
* design (transition({ when }) gated off, #995), and so does dev while a
|
|
112
|
+
* client reference loads.
|
|
113
|
+
*/
|
|
114
|
+
export declare function auditFallback(rec: BoundaryAudit): () => void;
|
|
115
|
+
/** One renderSegments call, collected while it builds. */
|
|
116
|
+
export interface TreeAudit {
|
|
117
|
+
/** Segment ids, leaf first while building, root first once finished. */
|
|
118
|
+
order: string[];
|
|
119
|
+
keys: Map<string, string>;
|
|
120
|
+
types: Map<string, string>;
|
|
121
|
+
chains: Map<string, string[]>;
|
|
122
|
+
/** Segments this tree remounts by the documented rules. */
|
|
123
|
+
replaced: Set<string>;
|
|
124
|
+
/** The segment objects the tree is built from (I7), until it is held. */
|
|
125
|
+
segments: object[];
|
|
126
|
+
}
|
|
127
|
+
export declare function startTreeAudit(): TreeAudit | undefined;
|
|
128
|
+
/** The element renderSegments built for one segment, leaf first. */
|
|
129
|
+
export declare function auditSegmentElement(tree: TreeAudit | undefined, id: string, type: string, key: string, element: unknown, outletTransition: boolean, slots: readonly string[], segments: readonly object[]): void;
|
|
130
|
+
/**
|
|
131
|
+
* A finished tree. The first is the document's, which React holds from
|
|
132
|
+
* hydration; any later one is held when an emit hands its root to React
|
|
133
|
+
* (auditTreeUpdate).
|
|
134
|
+
*/
|
|
135
|
+
export declare function finishTreeAudit(tree: TreeAudit | undefined, root: unknown): void;
|
|
136
|
+
/**
|
|
137
|
+
* I4: a boundary that stays on the page under the same React key is
|
|
138
|
+
* unmounted and mounted again. A different key is the documented remount.
|
|
139
|
+
*/
|
|
140
|
+
export declare function auditMount(rec: BoundaryAudit): void;
|
|
141
|
+
export declare function auditUnmount(rec: BoundaryAudit): void;
|
|
142
|
+
/**
|
|
143
|
+
* I6: the cause of the tree update the caller emits next, in the same task.
|
|
144
|
+
* It does not outlive the task: an emit after an await names its cause again,
|
|
145
|
+
* or a cause left behind would cover an emitter that names none.
|
|
146
|
+
*/
|
|
147
|
+
export declare function auditTreeCause(cause: TreeUpdateCause): void;
|
|
148
|
+
/**
|
|
149
|
+
* I6: a tree update reached React (the store.onUpdate subscriber in
|
|
150
|
+
* browser/react/NavigationProvider.tsx), with the root it hands React. Only a
|
|
151
|
+
* navigation, a back/forward, its stale revalidation, an action, an error and
|
|
152
|
+
* HMR hand React a tree; anything else updates in place through a store its
|
|
153
|
+
* readers subscribe to, or through a pending promise read with use().
|
|
154
|
+
*/
|
|
155
|
+
export declare function auditTreeUpdate(root?: unknown): void;
|
|
156
|
+
/** Forget every tree and mount seen so far. For tests of the audit itself. */
|
|
157
|
+
export declare function forgetSuspenseAudit(): void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createActionForm: the FormData a browser posts when a form is submitted
|
|
3
|
+
* before hydration (no JavaScript), for a server action.
|
|
4
|
+
*
|
|
5
|
+
* React's server render writes hidden fields on the form so the POST names its
|
|
6
|
+
* action and carries the bound state; decodeAction / decodeFormState read them
|
|
7
|
+
* back. A test cannot render those fields (react-dom/server does not load under
|
|
8
|
+
* the react-server condition), so this builds the same wire format and
|
|
9
|
+
* registers the action where the plugin-rsc stub's decodeAction resolves it,
|
|
10
|
+
* tagged as a server reference like a built "use server" export so the bound
|
|
11
|
+
* action keeps its `$$id` (onError's actionId, the action phase label).
|
|
12
|
+
* Post the result with `serveShellRequest(router, url, { form })`.
|
|
13
|
+
*/
|
|
14
|
+
/** Options for {@link createActionForm}. */
|
|
15
|
+
export interface CreateActionFormOptions {
|
|
16
|
+
/**
|
|
17
|
+
* The action's reference id, `<module id>#<export name>`, as the build gives
|
|
18
|
+
* a "use server" export. Any unique string of that shape in a test.
|
|
19
|
+
*/
|
|
20
|
+
id: string;
|
|
21
|
+
/**
|
|
22
|
+
* A `useActionState` form (default): the action runs as `(prevState, formData)`
|
|
23
|
+
* and the POST carries the state key. false: a plain `<form action={fn}>`
|
|
24
|
+
* ($ACTION_ID_), the action runs as `(formData)`.
|
|
25
|
+
*/
|
|
26
|
+
useActionState?: boolean;
|
|
27
|
+
/** The form's own fields, as the person filled them. */
|
|
28
|
+
fields?: Record<string, string>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build a no-JS form POST body for `action` and register it so a handler
|
|
32
|
+
* decodes it back to `action`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createActionForm(action: (...args: any[]) => unknown, options: CreateActionFormOptions): FormData;
|
|
@@ -30,5 +30,7 @@ export { renderServerTree, findClientBoundaries, findElements, textContent, asse
|
|
|
30
30
|
export type { RenderServerTreeOptions, RenderServerTreeResult, ClientBoundary, BoundarySelector, FoundElement, ElementSelector, } from "./flight-tree.js";
|
|
31
31
|
export { renderHandler } from "./render-handler.js";
|
|
32
32
|
export type { TestableHandler, RenderHandlerOptions, RenderHandlerResult, StateCookieSeed, } from "./render-handler.js";
|
|
33
|
+
export { createActionForm } from "./action-form.js";
|
|
34
|
+
export type { CreateActionFormOptions } from "./action-form.js";
|
|
33
35
|
export { serveShellRequest, resetShellTestState, } from "./serve-shell-request.js";
|
|
34
36
|
export type { ServeShellRequestOptions, ServeShellRequestResult, ShellRequestHandles, } from "./serve-shell-request.js";
|
|
@@ -43,6 +43,10 @@ export { runClientRevalidate } from "./run-client-revalidate.js";
|
|
|
43
43
|
export type { RunClientRevalidateOptions } from "./run-client-revalidate.js";
|
|
44
44
|
export { dispatch } from "./dispatch.js";
|
|
45
45
|
export type { DispatchOptions } from "./dispatch.js";
|
|
46
|
+
export { createMemoryPrerenderStore } from "../prerender/memory-prerender-store.js";
|
|
47
|
+
export type { MemoryPrerenderStore, MemoryPrerenderStoreOptions, } from "../prerender/memory-prerender-store.js";
|
|
48
|
+
export type { WritablePrerenderStore, PrerenderStoredEntry, PrerenderKey, } from "../prerender/writable-store.js";
|
|
49
|
+
export type { PrerenderConfig, PrerenderResult, PrerenderWarmCaches, } from "../prerender/on-demand.js";
|
|
46
50
|
export { assertCacheStatus, assertCacheDecision, parseCacheHeader, createCacheSink, filterCacheDecisions, } from "./cache-status.js";
|
|
47
51
|
export type { ExpectedCacheStatus, CacheStatusTarget, CacheSink, } from "./cache-status.js";
|
|
48
52
|
export type { TelemetryEvent, TelemetrySink, CacheDecisionEvent, CacheSegmentSignal, CacheSegmentStatus, } from "../router/telemetry.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register `exports` as the server module `id`, merging into an earlier call.
|
|
3
|
+
* The module object is kept and mutated: the stub's require is memoized per
|
|
4
|
+
* id, so a later export must appear on the object it first returned.
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerServerModule(id: string, exports: Record<string, unknown>): void;
|
|
7
|
+
/** The module a decoded server reference resolves to. */
|
|
8
|
+
export declare function loadServerModule(id: string): Record<string, unknown>;
|
|
@@ -27,6 +27,14 @@
|
|
|
27
27
|
* capture refuses for a root postpone (a live loader read with no boundary
|
|
28
28
|
* above it) or an SSR render error is captured here.
|
|
29
29
|
*
|
|
30
|
+
* A `Prerender` route serves its handler layer from the artifact
|
|
31
|
+
* `router.matchForPrerender` bakes for the URL (on its first request, kept
|
|
32
|
+
* until resetShellTestState), through the production prerender store. Its
|
|
33
|
+
* first `ppr` request is a MISS with a runtime capture, as a URL without a
|
|
34
|
+
* build-time shell is in production; build-time shells are e2e-only. An
|
|
35
|
+
* on-demand route (`Prerender(..., { onDemand })`) bakes nothing here: it
|
|
36
|
+
* serves from its prerender store, as a refresh-only page does in production.
|
|
37
|
+
*
|
|
30
38
|
* Must run under the `react-server` condition (the rsc Vitest project), with
|
|
31
39
|
* `rangoTestAliases()` resolving `@vitejs/plugin-rsc/rsc/server` to the stub
|
|
32
40
|
* that carries the Flight runtime.
|
|
@@ -60,6 +68,14 @@ export interface ServeShellRequestOptions<TEnv = any> {
|
|
|
60
68
|
from?: string;
|
|
61
69
|
segments?: readonly string[];
|
|
62
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* POST this form as a submit before hydration: the no-JS request the
|
|
73
|
+
* progressive-enhancement path runs the action for and re-renders the page
|
|
74
|
+
* after. Build it with `createActionForm`. The response is the document
|
|
75
|
+
* (`flight` is its payload, `formState` what the SSR render received).
|
|
76
|
+
* Not with `partial`.
|
|
77
|
+
*/
|
|
78
|
+
form?: FormData;
|
|
63
79
|
}
|
|
64
80
|
/** A response's handle data, as the browser consumes it. */
|
|
65
81
|
export interface ShellRequestHandles {
|
|
@@ -117,17 +133,31 @@ export interface ServeShellRequestResult {
|
|
|
117
133
|
* values resolved. Undefined when no Flight was rendered.
|
|
118
134
|
*/
|
|
119
135
|
readHandles(): Promise<ShellRequestHandles | undefined>;
|
|
136
|
+
/**
|
|
137
|
+
* The form state the SSR render received (the `formState` render option),
|
|
138
|
+
* or undefined when it received none.
|
|
139
|
+
*/
|
|
140
|
+
formState: unknown;
|
|
141
|
+
/**
|
|
142
|
+
* The payload's `formState` as the browser reads it, the value the entry
|
|
143
|
+
* hands `hydrateRoot`. Undefined when the payload carries none (or no
|
|
144
|
+
* Flight was rendered). Rejects when the action's state is not
|
|
145
|
+
* Flight-serializable: the document still renders, and the entry
|
|
146
|
+
* hydrates without it.
|
|
147
|
+
*/
|
|
148
|
+
readPayloadFormState(): Promise<unknown>;
|
|
120
149
|
}
|
|
121
150
|
/**
|
|
122
151
|
* Reset the per-isolate PPR state requests leave behind, so the next test
|
|
123
152
|
* starts as a fresh worker would: the capture's stampede guard, its backoff
|
|
124
153
|
* (a refused capture backs its URL off for later tests too), the shell path's
|
|
125
154
|
* once-per-key warnings, the build-shell manifest memo, the "use cache"
|
|
126
|
-
* in-flight leaders and warnings,
|
|
155
|
+
* in-flight leaders and warnings, CFCacheStore's isolate memos (shells,
|
|
127
156
|
* tag markers, tag hints) and warnings, which every CFCacheStore in the
|
|
128
|
-
* process shares by namespace and URL
|
|
129
|
-
*
|
|
130
|
-
* handle it is given: a new
|
|
157
|
+
* process shares by namespace and URL, and the Prerender artifacts baked so
|
|
158
|
+
* far. Call it in `beforeEach`, never while a request is in flight.
|
|
159
|
+
* VercelCacheStore's memos live on the `cache` handle it is given: a new
|
|
160
|
+
* handle starts empty.
|
|
131
161
|
*/
|
|
132
162
|
export declare function resetShellTestState(): Promise<void>;
|
|
133
163
|
/**
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* 2. **Smallest status signals:** `x-rango-shell` (`HIT` | `MISS`) on document
|
|
16
16
|
* GETs, and `x-rango-ppr-replay` on partial requests to ppr routes. A replay
|
|
17
17
|
* HIT is reported only when matching consumes the captured segment record.
|
|
18
|
-
* Secondary unit signal: `store.getShell(shellCacheKey(url))` after a real
|
|
18
|
+
* Secondary unit signal: `store.getShell(shellCacheKey(router, url))` after a real
|
|
19
19
|
* capture flush (background `putShell`). There is no Flight flag for shell HIT.
|
|
20
20
|
*
|
|
21
21
|
* 3. **A real MISS → capture → HIT in unit tests:** `serveShellRequest`
|
|
@@ -68,10 +68,16 @@ export interface ShellCachePartition {
|
|
|
68
68
|
generated?: readonly string[];
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
|
-
* Shell store key for a document URL: the production
|
|
72
|
-
* pathname + sorted search + `:shell`)
|
|
73
|
-
*
|
|
74
|
-
*
|
|
71
|
+
* Shell store key of `router` for a document URL: the production
|
|
72
|
+
* `buildShellKey` (router id + host + pathname + sorted search + `:shell`)
|
|
73
|
+
* and `partitionShellKey`, both from the React-free leaf
|
|
74
|
+
* `rsc/shell-capture-constants.ts`, so the testing barrel never imports the
|
|
75
|
+
* shell-serve module (it pulls React).
|
|
76
|
+
*
|
|
77
|
+
* `router` is the router that serves the URL, or anything carrying its `id`
|
|
78
|
+
* (`{ id }` where the router cannot be imported, as in a Playwright test). A
|
|
79
|
+
* shell belongs to one router: two routers serving one host and path keep
|
|
80
|
+
* two entries.
|
|
75
81
|
*
|
|
76
82
|
* Accepts a `URL` or an absolute/relative request URL string (relative strings
|
|
77
83
|
* resolve against `http://localhost`). Pass the router's `cache.searchParams`
|
|
@@ -86,7 +92,9 @@ export interface ShellCachePartition {
|
|
|
86
92
|
* - store `keyGenerator` results, with or without `key()` results, as
|
|
87
93
|
* `{ keys, generated }` (see {@link ShellCachePartition}).
|
|
88
94
|
*/
|
|
89
|
-
export declare function shellCacheKey(
|
|
95
|
+
export declare function shellCacheKey(router: {
|
|
96
|
+
readonly id: string;
|
|
97
|
+
}, url: URL | string, searchParams?: CacheSearchParams, partition?: string | readonly string[] | ShellCachePartition): string;
|
|
90
98
|
/**
|
|
91
99
|
* Read `x-rango-shell` from a response. Returns `null` when the header is
|
|
92
100
|
* absent (axis-1 / non-ppr / ineligible request).
|
|
@@ -16,8 +16,11 @@
|
|
|
16
16
|
*
|
|
17
17
|
* Without the condition React's server build refuses to load, so the codec
|
|
18
18
|
* functions throw and a "use cache" call runs uncached. Any other load failure
|
|
19
|
-
* (a moved vendored path, a missing peer) throws.
|
|
20
|
-
*
|
|
19
|
+
* (a moved vendored path, a missing peer) throws. decodeAction and
|
|
20
|
+
* decodeFormState decode a no-JS form POST under the condition, resolving its
|
|
21
|
+
* action from the modules createActionForm() registered, as do
|
|
22
|
+
* `loadServerAction` and `decodeReply` for a plain form action. Without the
|
|
23
|
+
* condition they stay inert.
|
|
21
24
|
*/
|
|
22
25
|
export declare const renderToReadableStream: (value: unknown, options?: object) => ReadableStream<Uint8Array>;
|
|
23
26
|
export declare const createTemporaryReferenceSet: () => unknown;
|
|
@@ -26,7 +29,7 @@ export declare const createFromReadableStream: (stream: ReadableStream<Uint8Arra
|
|
|
26
29
|
}) => Promise<unknown>;
|
|
27
30
|
export declare const encodeReply: (value: unknown, options?: object) => Promise<string | FormData>;
|
|
28
31
|
export declare const createClientTemporaryReferenceSet: () => unknown;
|
|
29
|
-
export declare const loadServerAction: () => undefined;
|
|
30
|
-
export declare const decodeReply: () => undefined;
|
|
31
|
-
export declare const decodeAction: () => undefined;
|
|
32
|
-
export declare const decodeFormState: () => undefined;
|
|
32
|
+
export declare const loadServerAction: (id: string) => Promise<unknown> | undefined;
|
|
33
|
+
export declare const decodeReply: (body: string | FormData, options?: object) => Promise<unknown> | undefined;
|
|
34
|
+
export declare const decodeAction: (body: FormData) => Promise<unknown> | null | undefined;
|
|
35
|
+
export declare const decodeFormState: (actionResult: unknown, body: FormData) => Promise<unknown> | undefined;
|
|
@@ -7,3 +7,9 @@
|
|
|
7
7
|
* isLoading registration (loader-store.ts), which must agree on "settled".
|
|
8
8
|
*/
|
|
9
9
|
export declare function unwrapsSynchronously(stream: Promise<unknown>): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* A resolved thenable for a use() whose result is ignored: React reads the
|
|
12
|
+
* "fulfilled" stamp and returns at once. `_debugInfo` keeps React DevTools from
|
|
13
|
+
* listing a 0 ms promise on every reader that calls it.
|
|
14
|
+
*/
|
|
15
|
+
export declare const SETTLED_THENABLE: Promise<undefined>;
|
|
@@ -329,6 +329,13 @@ export type InternalHandlerContext<TParams = {}, TEnv = DefaultEnv, TSearch exte
|
|
|
329
329
|
_responseType?: string;
|
|
330
330
|
/** Route name for cache key scoping (prevents cross-route collisions). */
|
|
331
331
|
_routeName?: string;
|
|
332
|
+
/**
|
|
333
|
+
* @internal The on-demand overlay holds a "removed" marker for this request
|
|
334
|
+
* (tryPrerenderLookup, cache-lookup.ts); gateOnDemandProducer reads it. On
|
|
335
|
+
* this context, not the request's: withCacheLookup documents that the
|
|
336
|
+
* request ALS can be lost mid-pipeline on workerd.
|
|
337
|
+
*/
|
|
338
|
+
_prerenderRemoved?: true;
|
|
332
339
|
/**
|
|
333
340
|
* @internal Loader-cache override table: loaderId -> memoized data promise.
|
|
334
341
|
* A single stable ctx.use interceptor consults this instead of chaining one
|
|
@@ -72,6 +72,11 @@ export interface RouteEntry<TEnv = any> {
|
|
|
72
72
|
* Used by the non-trie match path to set the `pt` flag.
|
|
73
73
|
*/
|
|
74
74
|
passthroughRouteKeys?: Set<string>;
|
|
75
|
+
/**
|
|
76
|
+
* Route keys in this entry that opted into on-demand prerender.
|
|
77
|
+
* Used by the non-trie match path to set the `od` flag.
|
|
78
|
+
*/
|
|
79
|
+
onDemandRouteKeys?: Set<string>;
|
|
75
80
|
/**
|
|
76
81
|
* Whether this entry is lazily evaluated.
|
|
77
82
|
* When true, routes are populated on first matching request.
|