@rangojs/router 0.20.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 +39 -15
- package/dist/types/browser/event-controller.d.ts +49 -0
- package/dist/types/browser/history-state.d.ts +16 -4
- package/dist/types/browser/navigation-store.d.ts +9 -0
- package/dist/types/browser/navigation-transaction.d.ts +7 -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/rango-state.d.ts +3 -1
- package/dist/types/browser/react/NavigationProvider.d.ts +14 -1
- package/dist/types/browser/react/context.d.ts +25 -0
- package/dist/types/browser/react/location-state-shared.d.ts +84 -10
- package/dist/types/browser/react/location-state.d.ts +7 -2
- 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 +5 -6
- package/dist/types/cache/cf/cf-cache-store.d.ts +34 -7
- package/dist/types/cache/cf/cf-cache-types.d.ts +12 -4
- package/dist/types/cache/document-cache.d.ts +8 -5
- package/dist/types/cache/handle-snapshot.d.ts +59 -50
- package/dist/types/cache/index.d.ts +3 -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 +29 -4
- 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 +84 -24
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +35 -17
- package/dist/types/client-urls/navigation.d.ts +7 -1
- package/dist/types/client-urls/optimistic-location.d.ts +10 -4
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/handles/deferred-resolution.d.ts +18 -1
- 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/build-shell-capture.d.ts +8 -6
- 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 +15 -1
- package/dist/types/router/navigation-snapshot.d.ts +8 -1
- 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 +32 -1
- package/dist/types/router/router-options.d.ts +39 -5
- package/dist/types/router/segment-resolution/fresh.d.ts +7 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +23 -10
- 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/router-versions.d.ts +39 -0
- package/dist/types/rsc/handler-context.d.ts +5 -0
- package/dist/types/rsc/shell-build-manifest.d.ts +9 -6
- 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 +12 -6
- 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 +53 -0
- package/dist/types/server/context.d.ts +12 -4
- package/dist/types/server/handle-store.d.ts +89 -46
- package/dist/types/server/request-context.d.ts +84 -9
- 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/build-versions.d.ts +32 -0
- package/dist/types/testing/dom.entry.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +3 -1
- package/dist/types/testing/index.d.ts +6 -0
- package/dist/types/testing/internal/seed-vars.d.ts +7 -2
- package/dist/types/testing/internal/server-modules.d.ts +8 -0
- package/dist/types/testing/location-state-key.d.ts +5 -1
- package/dist/types/testing/render-route.d.ts +77 -6
- package/dist/types/testing/serve-shell-request.d.ts +55 -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/testing/vitest-stubs/version.d.ts +1 -0
- package/dist/types/thenable-status.d.ts +6 -0
- package/dist/types/types/handler-context.d.ts +15 -5
- 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/build-versions.d.ts +393 -0
- package/dist/types/vite/discovery/installed-packages.d.ts +26 -0
- package/dist/types/vite/discovery/router-versions-phase.d.ts +52 -0
- package/dist/types/vite/discovery/shell-prerender-phase.d.ts +7 -17
- package/dist/types/vite/discovery/state.d.ts +25 -0
- package/dist/types/vite/encryption-key.d.ts +18 -0
- package/dist/types/vite/inject-client-debug.d.ts +6 -25
- package/dist/types/vite/plugin-types.d.ts +27 -0
- package/dist/types/vite/plugins/{version-injector.d.ts → entry-bootstrap-injector.d.ts} +4 -6
- package/dist/types/vite/plugins/expose-ids/export-analysis.d.ts +1 -0
- package/dist/types/vite/plugins/expose-ids/router-transform.d.ts +14 -0
- package/dist/types/vite/plugins/stable-rsc-output.d.ts +51 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +9 -11
- package/dist/types/vite/plugins/virtual-entries.d.ts +18 -1
- package/dist/types/vite/router-discovery.d.ts +6 -0
- package/dist/types/vite/utils/bundle-analysis.d.ts +6 -2
- package/dist/types/vite/utils/client-chunks.d.ts +2 -0
- package/dist/types/vite/utils/compare-strings.d.ts +7 -0
- package/dist/types/vite/utils/package-resolution.d.ts +8 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +2 -0
- package/dist/vite/index.js +1707 -931
- package/package.json +12 -3
- package/skills/cache-guide/SKILL.md +102 -37
- package/skills/caching/SKILL.md +56 -9
- package/skills/catalog.json +1 -1
- package/skills/client-urls/SKILL.md +16 -0
- package/skills/cloudflare/SKILL.md +133 -1
- package/skills/comparison/references/framework-comparison.md +17 -13
- package/skills/deployment-caching/SKILL.md +33 -12
- package/skills/document-cache/SKILL.md +16 -14
- package/skills/hooks/SKILL.md +25 -0
- package/skills/hooks/handle-and-actions.md +5 -0
- package/skills/hooks/navigation.md +38 -0
- package/skills/hooks/state.md +213 -11
- package/skills/hooks/urls.md +40 -1
- package/skills/host-router/SKILL.md +31 -0
- package/skills/intercept/SKILL.md +6 -0
- package/skills/loader/SKILL.md +25 -5
- package/skills/middleware/SKILL.md +2 -0
- package/skills/migrate-nextjs/SKILL.md +82 -9
- package/skills/ppr/SKILL.md +150 -48
- package/skills/prerender/SKILL.md +651 -10
- package/skills/rango/SKILL.md +9 -7
- package/skills/response-routes/SKILL.md +5 -5
- package/skills/route/SKILL.md +29 -0
- package/skills/router-setup/SKILL.md +15 -1
- package/skills/testing/SKILL.md +32 -27
- package/skills/testing/cache-prerender.md +18 -17
- package/skills/testing/client-components.md +193 -8
- package/skills/testing/handles.md +2 -0
- package/skills/testing/loader.md +1 -1
- package/skills/testing/middleware.md +1 -1
- package/skills/testing/render-handler.md +18 -18
- package/skills/testing/serve-shell-request.md +167 -22
- package/skills/testing/server-actions.md +17 -17
- package/skills/testing/server-tree.md +1 -1
- package/skills/typesafety/generated-files-and-cli.md +1 -1
- package/skills/use-cache/SKILL.md +25 -10
- package/skills/vercel/SKILL.md +5 -3
- package/skills/view-transitions/SKILL.md +9 -4
- package/src/bin/rango.ts +1 -1
- package/src/browser/event-controller.ts +119 -2
- package/src/browser/history-state.ts +39 -17
- package/src/browser/link-interceptor.ts +2 -2
- package/src/browser/navigation-bridge.ts +104 -41
- package/src/browser/navigation-store.ts +26 -0
- package/src/browser/navigation-transaction.ts +24 -12
- package/src/browser/network-error-handler.ts +2 -0
- package/src/browser/partial-update.ts +58 -14
- package/src/browser/prefetch/default-strategy.ts +22 -42
- package/src/browser/rango-state.ts +3 -1
- package/src/browser/react/Link.tsx +37 -43
- package/src/browser/react/NavigationProvider.tsx +85 -1
- package/src/browser/react/context.ts +30 -0
- package/src/browser/react/location-state-shared.ts +200 -34
- package/src/browser/react/location-state.ts +28 -77
- package/src/browser/react/use-action.ts +4 -1
- package/src/browser/react/use-handle.ts +3 -0
- 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 +93 -31
- package/src/browser/segment-reconciler.ts +3 -3
- package/src/browser/server-action-bridge.ts +43 -7
- 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 +48 -36
- package/src/cache/cf/cf-cache-store.ts +91 -66
- package/src/cache/cf/cf-cache-types.ts +12 -4
- package/src/cache/document-cache.ts +35 -14
- package/src/cache/handle-snapshot.ts +118 -86
- package/src/cache/index.ts +5 -0
- package/src/cache/invalidation-order.ts +53 -0
- package/src/cache/memory-segment-store.ts +52 -1
- package/src/cache/shell-snapshot.ts +52 -5
- package/src/cache/store-scope.ts +36 -0
- package/src/cache/tag-invalidation.ts +7 -5
- package/src/cache/types.ts +90 -24
- package/src/cache/vercel/vercel-cache-store.ts +68 -26
- package/src/client-urls/client-root.tsx +1 -0
- package/src/client-urls/navigation.ts +10 -0
- package/src/client-urls/optimistic-location.ts +10 -4
- package/src/client.tsx +40 -3
- package/src/errors.ts +13 -6
- package/src/handles/deferred-resolution.ts +36 -0
- 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/build-shell-capture.ts +11 -9
- 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/manifest.ts +2 -0
- package/src/router/match-middleware/background-revalidation.ts +2 -0
- package/src/router/match-middleware/cache-lookup.ts +239 -54
- package/src/router/navigation-snapshot.ts +25 -6
- 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/request-classification.ts +15 -12
- package/src/router/route-trie-builder.ts +9 -0
- package/src/router/router-context.ts +1 -0
- package/src/router/router-interfaces.ts +35 -1
- package/src/router/router-options.ts +45 -5
- package/src/router/segment-resolution/fresh.ts +20 -19
- package/src/router/segment-resolution/loader-cache.ts +110 -77
- 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-versions.ts +60 -0
- package/src/router.ts +107 -1
- package/src/rsc/full-payload.ts +6 -2
- package/src/rsc/handler-context.ts +5 -0
- package/src/rsc/handler.ts +64 -7
- package/src/rsc/progressive-enhancement.ts +5 -1
- package/src/rsc/response-cache-serve.ts +10 -4
- package/src/rsc/rsc-rendering.ts +65 -12
- package/src/rsc/shell-build-manifest.ts +17 -12
- package/src/rsc/shell-capture-constants.ts +39 -7
- package/src/rsc/shell-capture.ts +144 -45
- package/src/rsc/shell-serve.ts +12 -6
- package/src/rsc/ssr-module-loader.ts +26 -0
- package/src/rsc/types.ts +12 -6
- 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 +130 -0
- package/src/server/context.ts +40 -17
- package/src/server/cookie-store.ts +5 -0
- package/src/server/handle-store.ts +357 -127
- package/src/server/request-context.ts +149 -12
- package/src/ssr/ssr-root.tsx +32 -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/build-versions.ts +64 -0
- package/src/testing/dispatch.ts +6 -0
- package/src/testing/dom.entry.ts +1 -0
- package/src/testing/flight-runtime.d.ts +27 -0
- package/src/testing/flight.entry.ts +4 -0
- package/src/testing/index.ts +22 -0
- package/src/testing/internal/context.ts +2 -1
- package/src/testing/internal/seed-vars.ts +14 -2
- package/src/testing/internal/server-modules.ts +32 -0
- package/src/testing/location-state-key.ts +18 -8
- package/src/testing/render-handler.ts +2 -1
- package/src/testing/render-route.tsx +293 -46
- package/src/testing/serve-shell-request.ts +262 -37
- package/src/testing/shell-status.ts +17 -6
- package/src/testing/vitest-stubs/plugin-rsc.ts +37 -11
- package/src/testing/vitest-stubs/version.ts +4 -1
- package/src/thenable-status.ts +10 -0
- package/src/types/handler-context.ts +15 -5
- 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/build-versions.ts +1281 -0
- package/src/vite/discovery/bundle-postprocess.ts +4 -0
- package/src/vite/discovery/discover-routers.ts +15 -0
- package/src/vite/discovery/installed-packages.ts +159 -0
- package/src/vite/discovery/prerender-collection.ts +38 -1
- package/src/vite/discovery/router-versions-phase.ts +336 -0
- package/src/vite/discovery/shell-prerender-phase.ts +33 -43
- package/src/vite/discovery/state.ts +36 -1
- package/src/vite/discovery/virtual-module-codegen.ts +7 -2
- package/src/vite/encryption-key.ts +101 -9
- package/src/vite/inject-client-debug.ts +42 -20
- package/src/vite/plugin-types.ts +28 -0
- package/src/vite/plugins/{version-injector.ts → entry-bootstrap-injector.ts} +7 -22
- package/src/vite/plugins/expose-ids/export-analysis.ts +1 -1
- package/src/vite/plugins/expose-ids/router-transform.ts +36 -15
- package/src/vite/plugins/expose-internal-ids.ts +12 -3
- package/src/vite/plugins/stable-rsc-output.ts +147 -0
- package/src/vite/plugins/version-plugin.ts +19 -24
- package/src/vite/plugins/version.d.ts +17 -2
- package/src/vite/plugins/virtual-entries.ts +39 -6
- package/src/vite/rango.ts +28 -3
- package/src/vite/router-discovery.ts +96 -13
- package/src/vite/utils/bundle-analysis.ts +39 -7
- package/src/vite/utils/client-chunks.ts +5 -1
- package/src/vite/utils/compare-strings.ts +9 -0
- package/src/vite/utils/package-resolution.ts +9 -0
- package/src/vite/utils/prerender-utils.ts +4 -1
- package/src/vite/utils/shared-utils.ts +1 -1
- package/dist/types/segment-content-promise.d.ts +0 -13
- package/src/segment-content-promise.ts +0 -67
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writable prerender store contract for on-demand (ISR-style) prerender refresh.
|
|
3
|
+
*
|
|
4
|
+
* The bundled build manifest (store.ts) is immutable and read-only. On-demand
|
|
5
|
+
* prerender adds a writable durable overlay in front of it: `router.prerender()`
|
|
6
|
+
* renders a route and writes a versioned envelope here; the serve path reads the
|
|
7
|
+
* overlay before the bundled manifest.
|
|
8
|
+
*
|
|
9
|
+
* This module is types + pure helpers only — no React/RSC/plugin-rsc imports —
|
|
10
|
+
* so it can be imported by the testing barrel and platform adapters alike.
|
|
11
|
+
*/
|
|
12
|
+
import type { PrerenderEntry } from "./store.js";
|
|
13
|
+
/**
|
|
14
|
+
* Structured durable-overlay key. Includes the router's cache version so a
|
|
15
|
+
* deploy that changed the router's server code never reads Flight payloads
|
|
16
|
+
* that reference its previous build, and so Cloudflare gradual deployments
|
|
17
|
+
* stay correct (old and new worker versions each read their own namespace).
|
|
18
|
+
*/
|
|
19
|
+
export interface PrerenderKey {
|
|
20
|
+
routerId: string;
|
|
21
|
+
/**
|
|
22
|
+
* The owning router's cache version (its data version, or
|
|
23
|
+
* `createRouter({ version })`). Opaque: never set or read by app code; a
|
|
24
|
+
* store keys off it as given.
|
|
25
|
+
*/
|
|
26
|
+
version: string;
|
|
27
|
+
routeName: string;
|
|
28
|
+
/** DJB2 8-hex hash of the canonical params (see param-hash.ts). */
|
|
29
|
+
paramHash: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @internal What the trigger stamps on a write. TTL is soft staleness metadata
|
|
33
|
+
* (`staleAt`), never a hard store expiry: hard expiry would delete the entry
|
|
34
|
+
* a stale-while-revalidate serve needs, and an expired overlay would fall back
|
|
35
|
+
* to older bundled-manifest content.
|
|
36
|
+
*/
|
|
37
|
+
export interface StoredEntryOptions {
|
|
38
|
+
/** Seconds until the entry is considered stale. Absent = never stale. */
|
|
39
|
+
ttl?: number;
|
|
40
|
+
tags: string[];
|
|
41
|
+
/** Canonical params, stored for verify-on-read. */
|
|
42
|
+
params: Record<string, string>;
|
|
43
|
+
}
|
|
44
|
+
/** What a page and a "removed" marker both carry: a store reads either alike. */
|
|
45
|
+
interface StoredEnvelope {
|
|
46
|
+
v: 1;
|
|
47
|
+
meta: {
|
|
48
|
+
/**
|
|
49
|
+
* When the render started, not when the entry was written: a `markStale()`
|
|
50
|
+
* at or after it (strictly after in an in-process store) covers the entry.
|
|
51
|
+
* A `remove()` marker renders nothing and carries its write time.
|
|
52
|
+
*/
|
|
53
|
+
storedAt: number;
|
|
54
|
+
/**
|
|
55
|
+
* Absent = never stale. Soft metadata only; controls `onRevalidate`
|
|
56
|
+
* scheduling, not serving. Counts the ttl from the write. A store may
|
|
57
|
+
* lower it (tag markers do).
|
|
58
|
+
*/
|
|
59
|
+
staleAt?: number;
|
|
60
|
+
/** The configured ttl in seconds, as a result reports it. Absent = none. */
|
|
61
|
+
ttl?: number;
|
|
62
|
+
tags: string[];
|
|
63
|
+
/** The key's `version` at write time; verified on read. */
|
|
64
|
+
version: string;
|
|
65
|
+
/** Verified against the request's params on read (DJB2 collision guard). */
|
|
66
|
+
params: Record<string, string>;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
type StoredPage = StoredEnvelope & {
|
|
70
|
+
entry: PrerenderEntry;
|
|
71
|
+
removed?: never;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* The "removed" marker (tombstone) stored in place of a page, by
|
|
75
|
+
* `prerender.remove()` or by a refresh whose render hit `notFound()` (or
|
|
76
|
+
* declined with `ctx.passthrough()`). A request that finds it is not served
|
|
77
|
+
* the build-time entry below the overlay. No `entry`: a router from before the
|
|
78
|
+
* marker rejects it as malformed (a miss) instead of serving an empty page.
|
|
79
|
+
* `meta` is stamped like a page's for a render outcome, so that marker goes
|
|
80
|
+
* stale and is rechecked; a `remove()` marker has no `staleAt` and no tags.
|
|
81
|
+
*/
|
|
82
|
+
type StoredTombstone = StoredEnvelope & {
|
|
83
|
+
removed: true;
|
|
84
|
+
entry?: never;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Versioned envelope the router composes on a refresh or a removal and
|
|
88
|
+
* verifies on every read: a page, or the marker that the page was removed. A
|
|
89
|
+
* store persists either as given and returns it as stored.
|
|
90
|
+
*/
|
|
91
|
+
export type PrerenderStoredEntry = StoredPage | StoredTombstone;
|
|
92
|
+
/**
|
|
93
|
+
* The writable durable overlay: plain get/set. Backed in production by a
|
|
94
|
+
* platform adapter (Cloudflare KV, …) and in dev/tests by an in-memory store.
|
|
95
|
+
* The router composes the envelope before `set()` and verifies whatever `get()`
|
|
96
|
+
* returns (shape, `version`, params collision guard), so a store holds no
|
|
97
|
+
* policy of its own.
|
|
98
|
+
*
|
|
99
|
+
* Key everything off the `key` argument (`serializePrerenderKey(key)` carries
|
|
100
|
+
* `key.version`). Never call `getCacheVersions()` here: the trigger's `set()`
|
|
101
|
+
* runs outside the producer's request context, where it returns the
|
|
102
|
+
* whole-build fallback instead of the owning router's version.
|
|
103
|
+
*/
|
|
104
|
+
export interface WritablePrerenderStore {
|
|
105
|
+
/**
|
|
106
|
+
* The envelope stored under `key`, or null. Never memoize a miss: a refresh
|
|
107
|
+
* can write the key after a request missed it. May lower `meta.staleAt` (a
|
|
108
|
+
* tag marked stale after the entry was written).
|
|
109
|
+
*/
|
|
110
|
+
get(key: PrerenderKey): Promise<PrerenderStoredEntry | null>;
|
|
111
|
+
/**
|
|
112
|
+
* Persist `stored` (a page, or the marker that the page was removed) under
|
|
113
|
+
* `key`, replacing any previous entry. No expiry.
|
|
114
|
+
*/
|
|
115
|
+
set(key: PrerenderKey, stored: PrerenderStoredEntry): Promise<void>;
|
|
116
|
+
delete?(key: PrerenderKey): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Mark the entries of router `routerId` (`PrerenderKey.routerId`) carrying
|
|
119
|
+
* any of `tags` stale (they keep serving). A mark covers an entry whose
|
|
120
|
+
* `meta.storedAt` it is at or after (strictly after for an in-process
|
|
121
|
+
* store), including one `set()` after the mark: a store that marks held
|
|
122
|
+
* entries in place has to remember its marks. Scope it to that router: routers
|
|
123
|
+
* behind a host router share one store, and a tag is only meaningful inside
|
|
124
|
+
* the router whose routes declared it. Optional: without it,
|
|
125
|
+
* `router.prerender().markStale()` is a no-op for this store.
|
|
126
|
+
*/
|
|
127
|
+
markStale?(routerId: string, tags: string[]): Promise<void>;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Serialize a {@link PrerenderKey} to the design's string form:
|
|
131
|
+
* `prerender:{routerId}:{version}:{routeName}:{paramHash}`
|
|
132
|
+
*/
|
|
133
|
+
export declare function serializePrerenderKey(key: PrerenderKey): string;
|
|
134
|
+
/**
|
|
135
|
+
* @internal Compose the versioned envelope the trigger hands to `store.set()`.
|
|
136
|
+
* `now` is `meta.storedAt`; `staleFrom` (default `now`) is where the ttl
|
|
137
|
+
* starts counting. Both are passed explicitly so tests stay deterministic.
|
|
138
|
+
*/
|
|
139
|
+
export declare function composeStoredEntry(key: PrerenderKey, entry: PrerenderEntry, options: StoredEntryOptions, now: number, staleFrom?: number): StoredPage;
|
|
140
|
+
/**
|
|
141
|
+
* @internal Compose the "removed" marker stored in place of a page. Its meta
|
|
142
|
+
* is a page's (composeStoredEntry), so `ttl` and `tags` mean the same: the
|
|
143
|
+
* marker of a render outcome is given the route's and is rechecked like a
|
|
144
|
+
* page; `prerender.remove()` gives neither, and its marker never goes stale.
|
|
145
|
+
*/
|
|
146
|
+
export declare function composeStoredTombstone(key: PrerenderKey, options: StoredEntryOptions, now: number, staleFrom?: number): StoredTombstone;
|
|
147
|
+
/**
|
|
148
|
+
* @internal Verify a store's answer is safe to serve for this key: the
|
|
149
|
+
* envelope shape and version tag, the key version, and the stored params
|
|
150
|
+
* against the request's (the 8-hex DJB2 collision guard, param-hash.ts: a
|
|
151
|
+
* runtime write keyed off webhook-supplied params must not serve one page's
|
|
152
|
+
* content under another's URL, nor remove another's page). False means treat
|
|
153
|
+
* it as a miss. Run by the router on every read, so a third-party store
|
|
154
|
+
* cannot skip it.
|
|
155
|
+
*/
|
|
156
|
+
export declare function isStoredEntryValidFor(stored: unknown, key: PrerenderKey, params: Record<string, string>): stored is PrerenderStoredEntry;
|
|
157
|
+
/** True once `now` has passed the entry's soft `staleAt`. Never-stale entries never go stale. */
|
|
158
|
+
export declare function isStoredEntryStale(stored: PrerenderStoredEntry, now: number): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* @internal Lower `meta.staleAt` to `at` when it is unset or later. Shared by
|
|
161
|
+
* the stores' tag marking so the rule cannot drift between them.
|
|
162
|
+
*/
|
|
163
|
+
export declare function lowerStoredEntryStaleAt(stored: PrerenderStoredEntry, at: number): void;
|
|
164
|
+
/**
|
|
165
|
+
* @internal `store.get(key)` verified for serving (isStoredEntryValidFor). A
|
|
166
|
+
* store error (e.g. a KV outage) reads as a miss: the serve path falls back to
|
|
167
|
+
* the bundled manifest or live handler, and the trigger's stale check renders.
|
|
168
|
+
*/
|
|
169
|
+
export declare function readVerifiedStoredEntry(store: WritablePrerenderStore, key: PrerenderKey, params: Record<string, string>): Promise<PrerenderStoredEntry | null>;
|
|
170
|
+
export {};
|
|
@@ -81,6 +81,26 @@ export interface PrerenderOptions {
|
|
|
81
81
|
* ```
|
|
82
82
|
*/
|
|
83
83
|
concurrency?: number;
|
|
84
|
+
/**
|
|
85
|
+
* Opt this route into on-demand (ISR-style) prerender refresh via
|
|
86
|
+
* `router.prerender()`. `true` uses the router-level `prerender` defaults; an
|
|
87
|
+
* object overrides them per route.
|
|
88
|
+
*
|
|
89
|
+
* Any truthy value opts in — a literal, a spread, or an imported const:
|
|
90
|
+
* producer retention in the production bundle is driven by the evaluated
|
|
91
|
+
* route manifest (the same source that sets the runtime od flag), not a
|
|
92
|
+
* textual scan of the call.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* export const ProductPage = Prerender(
|
|
97
|
+
* async () => [{ id: "featured" }],
|
|
98
|
+
* async (ctx) => <Product data={await ctx.env.PRODUCTS.get(ctx.params.id)} />,
|
|
99
|
+
* { onDemand: { ttl: 3600, tags: ({ params }) => [`product:${params.id}`] } },
|
|
100
|
+
* );
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
onDemand?: import("./prerender/on-demand.js").OnDemandOption;
|
|
84
104
|
}
|
|
85
105
|
/**
|
|
86
106
|
* Context passed to Prerender() handlers at build time.
|
|
@@ -98,6 +118,13 @@ export interface BuildContext<TParams> {
|
|
|
98
118
|
* changing build semantics.
|
|
99
119
|
*/
|
|
100
120
|
dev: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* True when this render is a requestless on-demand refresh driven by
|
|
123
|
+
* `router.prerender()` (rather than a build-time or dev prerender). The
|
|
124
|
+
* producer is still requestless — cookies/headers are unavailable — but
|
|
125
|
+
* `ctx.env` is the live trigger binding, not the shared build env.
|
|
126
|
+
*/
|
|
127
|
+
onDemand: boolean;
|
|
101
128
|
/**
|
|
102
129
|
* Build-time environment bindings (KV, D1, etc.) supplied by the Vite plugin.
|
|
103
130
|
* Only available when `buildEnv` is configured in rango() options.
|
package/dist/types/reverse.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type ParamsFor<TRoutes, TName extends keyof TRoutes> = ExtractParams<Rout
|
|
|
31
31
|
/**
|
|
32
32
|
* Check if an object type has any keys
|
|
33
33
|
*/
|
|
34
|
-
type IsEmptyObject<T> = keyof T extends never ? true : false;
|
|
34
|
+
export type IsEmptyObject<T> = keyof T extends never ? true : false;
|
|
35
35
|
/**
|
|
36
36
|
* Extract search schema from a route entry.
|
|
37
37
|
* Returns {} if no search schema is defined.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
1
|
+
import type { ComponentProps, ReactNode } from "react";
|
|
2
2
|
import { Component } from "react";
|
|
3
3
|
import type { ResolvedSegment } from "./types.js";
|
|
4
4
|
/**
|
|
@@ -70,6 +70,7 @@ export declare function RouteContentWrapper({ content, fallback, segmentId, }: {
|
|
|
70
70
|
fallback?: ReactNode;
|
|
71
71
|
segmentId?: string;
|
|
72
72
|
}): ReactNode;
|
|
73
|
+
export declare function AuditedRouteContent({ content, fallback, segmentId, }: ComponentProps<typeof RouteContentWrapper>): ReactNode;
|
|
73
74
|
/**
|
|
74
75
|
* LoaderBoundary - Client component that resolves loader promises and renders OutletProvider
|
|
75
76
|
*
|
|
@@ -102,3 +103,4 @@ export interface LoaderBoundaryProps {
|
|
|
102
103
|
children: ReactNode;
|
|
103
104
|
}
|
|
104
105
|
export declare function LoaderBoundary({ loaderDataPromise, loaderIds, loaderStreams, awaitedLoaderIds, fallback, outletKey, outletContent, segment, parallel, children, }: LoaderBoundaryProps): ReactNode;
|
|
106
|
+
export declare function AuditedLoaderBoundary({ fallback, children, ...resolver }: LoaderBoundaryProps): ReactNode;
|
|
@@ -78,6 +78,8 @@ export declare function findNearestNotFoundBoundary(entry: EntryData | null, def
|
|
|
78
78
|
* Sanitizes error details in production
|
|
79
79
|
*/
|
|
80
80
|
export declare function createErrorInfo(error: unknown, segmentId: string, segmentType: ErrorInfo["segmentType"]): ErrorInfo;
|
|
81
|
+
/** Invoke an errorBoundary() fallback that may be a handler or a plain node. */
|
|
82
|
+
export declare function renderErrorFallback(fallback: ReactNode | ErrorBoundaryHandler, errorInfo: ErrorInfo): ReactNode;
|
|
81
83
|
/**
|
|
82
84
|
* Create an error segment with the fallback component
|
|
83
85
|
* Renders the fallback with error info and reset function
|
|
@@ -37,7 +37,7 @@ export declare function createHandlerContext<TEnv>(params: Record<string, string
|
|
|
37
37
|
* search, reverse, and use(handle) work. Request-time properties
|
|
38
38
|
* (request, env, headers, cookies, get, set, res) throw with a clear error.
|
|
39
39
|
*/
|
|
40
|
-
export declare function createPrerenderContext<TEnv>(params: Record<string, string>, pathname: string, routeMap: Record<string, string>, routeName?: string, buildVars?: Record<string, any>, isPassthroughRoute?: boolean, buildEnv?: TEnv, devMode?: boolean): InternalHandlerContext<any, TEnv>;
|
|
40
|
+
export declare function createPrerenderContext<TEnv>(params: Record<string, string>, pathname: string, routeMap: Record<string, string>, routeName?: string, buildVars?: Record<string, any>, isPassthroughRoute?: boolean, buildEnv?: TEnv, devMode?: boolean, onDemand?: boolean): InternalHandlerContext<any, TEnv>;
|
|
41
41
|
/**
|
|
42
42
|
* Create a StaticContext for Static() handlers at build time.
|
|
43
43
|
*
|
|
@@ -92,8 +92,18 @@
|
|
|
92
92
|
* - Action context (if POST)
|
|
93
93
|
*/
|
|
94
94
|
import type { ResolvedSegment } from "../../types.js";
|
|
95
|
-
import type
|
|
95
|
+
import { type EntryData } from "../../server/context.js";
|
|
96
96
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
97
|
+
import type { PrerenderStore } from "../../prerender/store.js";
|
|
98
|
+
import type { PrerenderTargetObject, ResolvedPrerender } from "../../prerender/on-demand.js";
|
|
99
|
+
import { type RequestContext } from "../../server/request-context.js";
|
|
100
|
+
/**
|
|
101
|
+
* @internal Replace the prerender store this module serves from, and return
|
|
102
|
+
* the one it replaced. For serveShellRequest (testing/serve-shell-request.ts),
|
|
103
|
+
* which installs the production store over the artifacts it bakes for a call
|
|
104
|
+
* and puts the previous one back after it.
|
|
105
|
+
*/
|
|
106
|
+
export declare function setPrerenderStoreForTests(store: PrerenderStore | null | undefined): PrerenderStore | null | undefined;
|
|
97
107
|
/**
|
|
98
108
|
* Whether the prerender store holds a baked entry for this route + params.
|
|
99
109
|
* Consulted by the PPR replay gate (matchPartialWithPprReplay), which must
|
|
@@ -106,6 +116,10 @@ import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
|
106
116
|
* subsequent get() share one underlying load.
|
|
107
117
|
*/
|
|
108
118
|
export declare function prerenderEntryExists(routeKey: string | undefined, params: Record<string, string>, pathname: string, entries: EntryData[]): Promise<boolean>;
|
|
119
|
+
/** @internal Tests only (testing/serve-shell-request.ts resetShellTestState). */
|
|
120
|
+
export declare function resetOverlayRevalidationsForTests(): void;
|
|
121
|
+
/** @internal Exported for the eviction unit test. */
|
|
122
|
+
export declare function scheduleOverlayRevalidation<TEnv>(serializedKey: string, onRevalidate: NonNullable<ResolvedPrerender["config"]["onRevalidate"]>, target: PrerenderTargetObject, reqCtx: RequestContext<TEnv>, now?: number): void;
|
|
109
123
|
/**
|
|
110
124
|
* Async generator middleware type
|
|
111
125
|
*/
|
|
@@ -25,8 +25,15 @@ export interface ResolveNavigationDeps {
|
|
|
25
25
|
* never produce a partial match, so the replay path must decide
|
|
26
26
|
* `no-navigation-context` BEFORE spending shell-store reads — the two
|
|
27
27
|
* predicates drifting apart would misattribute the bypass again.
|
|
28
|
+
*
|
|
29
|
+
* `requestOrigin` is the origin pathname matching uses (`url.origin`), which
|
|
30
|
+
* may not be `request.url`'s. `X-RSC-Router-Client-Path` is returned as sent.
|
|
31
|
+
* A Referer counts only when it resolves against that origin and stays there.
|
|
32
|
+
* A cross-origin Referer is dropped: resolveNavigation matches only the
|
|
33
|
+
* pathname, so a foreign URL would be treated as a route on this app. A value
|
|
34
|
+
* that does not parse is no context either.
|
|
28
35
|
*/
|
|
29
|
-
export declare function getNavigationContextHeader(request: Request): string | null;
|
|
36
|
+
export declare function getNavigationContextHeader(request: Request, requestOrigin: string): string | null;
|
|
30
37
|
/**
|
|
31
38
|
* Whether withCacheLookup's prerender short-circuit will serve this partial
|
|
32
39
|
* from the build-time prerender store: a Prerender() match (`matched.pr`)
|
|
@@ -134,6 +134,8 @@ export interface RouteMatchResult<TEnv = any> {
|
|
|
134
134
|
pr?: true;
|
|
135
135
|
/** Passthrough: handler kept for live fallback on unknown params (from trie) */
|
|
136
136
|
pt?: true;
|
|
137
|
+
/** On-demand prerender eligible (router.prerender() refreshable) */
|
|
138
|
+
od?: true;
|
|
137
139
|
/** Response type for non-RSC routes (json, text, image, any) */
|
|
138
140
|
responseType?: string;
|
|
139
141
|
/** Negotiate variants: response-type routes sharing this path */
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolve the router-wide default Link prefetch strategy once, at router init.
|
|
3
|
-
* The resolved value ships to the client in payload metadata; the
|
|
4
|
-
*
|
|
5
|
-
* default-strategy.ts) and every `<Link>` without an explicit
|
|
6
|
-
* falls back to it.
|
|
3
|
+
* The resolved value ships to the client in payload metadata; the router
|
|
4
|
+
* store carries it (`NavigationStoreContext.defaultPrefetch`, see
|
|
5
|
+
* browser/prefetch/default-strategy.ts) and every `<Link>` without an explicit
|
|
6
|
+
* `prefetch` prop falls back to it.
|
|
7
7
|
*
|
|
8
8
|
* The type lives HERE (not in browser/react/Link.tsx) because both seats need
|
|
9
9
|
* it: this server-side resolver and the client Link/default-strategy modules.
|
|
@@ -5,10 +5,19 @@ import type { PartialPrerenderProps } from "../urls/pattern-types.js";
|
|
|
5
5
|
import type { HandlerContext, ResolvedSegment } from "../types";
|
|
6
6
|
import type { SerializedSegmentData } from "../cache/types.js";
|
|
7
7
|
import type { RouteMatchResult } from "./pattern-matching.js";
|
|
8
|
+
import type { RouterVersions } from "../router-versions.js";
|
|
9
|
+
import type { OnDemandRouteConfig } from "../prerender/on-demand.js";
|
|
8
10
|
export interface PrerenderMatchDeps<TEnv = any> {
|
|
9
11
|
/** Owning router id; scopes bake-time root-scope/search-schema lookups the
|
|
10
12
|
* same way reqCtx._routerId does at runtime (issue #762). */
|
|
11
13
|
routerId?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The owning router's cache versions. Set on the requestless on-demand
|
|
16
|
+
* producer's context as `_versions`, so cache stores built inside the render
|
|
17
|
+
* key under the router's pair like a live request does instead of the
|
|
18
|
+
* whole-build fallback (server/build-version-table.ts getCacheVersions).
|
|
19
|
+
*/
|
|
20
|
+
versions?: RouterVersions;
|
|
12
21
|
findMatch: (pathname: string) => RouteMatchResult<TEnv> | null | Promise<RouteMatchResult<TEnv> | null>;
|
|
13
22
|
buildRouterContext: () => RouterContext<TEnv>;
|
|
14
23
|
mergedRouteMap: Record<string, string>;
|
|
@@ -20,7 +29,15 @@ export interface PrerenderMatchDeps<TEnv = any> {
|
|
|
20
29
|
*/
|
|
21
30
|
export declare function matchForPrerender<TEnv = any>(pathname: string, params: Record<string, string>, deps: PrerenderMatchDeps<TEnv>, buildVars?: Record<string, any>, isPassthroughRoute?: boolean, buildEnv?: TEnv,
|
|
22
31
|
/** Dev-only: check getParams() for passthrough routes to skip unknown params. */
|
|
23
|
-
devMode?: boolean
|
|
32
|
+
devMode?: boolean,
|
|
33
|
+
/**
|
|
34
|
+
* Requestless on-demand refresh (router.prerender()). Arms the personalization
|
|
35
|
+
* guard: cookies()/headers()/response mutations throw a
|
|
36
|
+
* PrerenderPersonalizationError so the caller maps a personalized render to
|
|
37
|
+
* skipped-personalized instead of baking a shared payload. `buildEnv` here is
|
|
38
|
+
* the live trigger env, not the shared build env.
|
|
39
|
+
*/
|
|
40
|
+
onDemand?: boolean): Promise<{
|
|
24
41
|
segments: SerializedSegmentData[];
|
|
25
42
|
/** RSC-encoded handle map ("" when none) — see handle-snapshot.ts. Encoded in
|
|
26
43
|
* the producer (where the Flight codec resolves) so the node-side build/dev
|
|
@@ -33,6 +50,11 @@ devMode?: boolean): Promise<{
|
|
|
33
50
|
* the sinks store it as-is (no longer merge raw records). */
|
|
34
51
|
interceptHandles?: string;
|
|
35
52
|
passthrough?: true;
|
|
53
|
+
/** On-demand only: the render hit `notFound()` and nothing else failed. */
|
|
54
|
+
notFound?: true;
|
|
55
|
+
/** Route-level onDemand config (ttl/tags) read off the route entry; only set
|
|
56
|
+
* when `onDemand` and the route declared an onDemand object literal. */
|
|
57
|
+
onDemandConfig?: OnDemandRouteConfig;
|
|
36
58
|
/**
|
|
37
59
|
* The matched route entry's `ppr` path option, surfaced so the build
|
|
38
60
|
* collection can flag Prerender+ppr routes as build-time shell candidates
|
|
@@ -31,6 +31,12 @@ export interface TrieLeaf {
|
|
|
31
31
|
pr?: true;
|
|
32
32
|
/** Passthrough: handler kept in bundle for live fallback on unknown params */
|
|
33
33
|
pt?: true;
|
|
34
|
+
/**
|
|
35
|
+
* On-demand prerender eligible: the route opted into router.prerender()
|
|
36
|
+
* refresh. Distinct from `pr` — an od route may have no build-baked entry yet
|
|
37
|
+
* still needs a writable-overlay lookup at serve time.
|
|
38
|
+
*/
|
|
39
|
+
od?: true;
|
|
34
40
|
/** Response type for non-RSC routes (json, text, image, any) */
|
|
35
41
|
rt?: string;
|
|
36
42
|
/** Negotiate variants: response-type routes sharing this path */
|
|
@@ -73,5 +79,6 @@ export interface TrieNode {
|
|
|
73
79
|
* @param prerenderRouteNames - Optional set of prerendered route names (sets leaf.pr)
|
|
74
80
|
* @param passthroughRouteNames - Optional set of passthrough route names (sets leaf.pt)
|
|
75
81
|
* @param responseTypeRoutes - Optional map of route name to response type (sets leaf.rt)
|
|
82
|
+
* @param onDemandRouteNames - Optional set of on-demand-eligible route names (sets leaf.od)
|
|
76
83
|
*/
|
|
77
|
-
export declare function buildRouteTrie(routeManifest: Record<string, string>, routeToStaticPrefix: Record<string, string>, routeTrailingSlash?: Record<string, string>, prerenderRouteNames?: Set<string>, passthroughRouteNames?: Set<string>, responseTypeRoutes?: Record<string, string>): TrieNode;
|
|
84
|
+
export declare function buildRouteTrie(routeManifest: Record<string, string>, routeToStaticPrefix: Record<string, string>, routeTrailingSlash?: Record<string, string>, prerenderRouteNames?: Set<string>, passthroughRouteNames?: Set<string>, responseTypeRoutes?: Record<string, string>, onDemandRouteNames?: Set<string>): TrieNode;
|
|
@@ -45,6 +45,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
45
45
|
getContext: () => {
|
|
46
46
|
getOrCreateStore: (key: string) => any;
|
|
47
47
|
runWithStore: <T>(store: any, namespace: string, parent: any, fn: () => T) => T;
|
|
48
|
+
runIsolated: <T>(forRoute: string, fn: () => T) => T;
|
|
48
49
|
};
|
|
49
50
|
getMetricsStore: () => MetricsStore | undefined;
|
|
50
51
|
createCacheScope: (cacheConfig: any, parent: CacheScope | null) => CacheScope | null;
|
|
@@ -184,6 +184,28 @@ export interface Rango<TEnv = any, TRoutes extends Record<string, unknown> = Rec
|
|
|
184
184
|
* ```
|
|
185
185
|
*/
|
|
186
186
|
fetch(request: Request, input?: RouterRequestInput<TEnv>): Promise<Response>;
|
|
187
|
+
/**
|
|
188
|
+
* Bind `{ env, ctx }` and get the on-demand (ISR-style) prerender runner, to refresh from a running app —
|
|
189
|
+
* fetch handler, cron, queue, workflow, webhook, or server action.
|
|
190
|
+
*
|
|
191
|
+
* Requestless: the producer renders with route params and env only, never the
|
|
192
|
+
* caller's cookies/headers/session. Only routes that opted in via
|
|
193
|
+
* `Prerender(..., { onDemand })` are persistable; others return a skipped
|
|
194
|
+
* result. Configure the store via the `prerender` router option.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* const prerender = router.prerender({ env, ctx });
|
|
199
|
+
* await prerender("/products/42");
|
|
200
|
+
* await prerender(
|
|
201
|
+
* { route: "products.detail", params: { id: "42" } },
|
|
202
|
+
* { throwOnError: true },
|
|
203
|
+
* );
|
|
204
|
+
* await prerender.many(targets, { concurrency: 4 });
|
|
205
|
+
* await prerender.markStale(["product:42"]);
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
prerender: import("../prerender/on-demand.js").PrerenderFn<TEnv, TRoutes>;
|
|
187
209
|
}
|
|
188
210
|
/**
|
|
189
211
|
* Internal Rango router interface — the full framework-facing API.
|
|
@@ -254,6 +276,12 @@ export interface RangoInternal<TEnv = any, TRoutes extends Record<string, unknow
|
|
|
254
276
|
* Cache configuration
|
|
255
277
|
*/
|
|
256
278
|
readonly cache?: RangoOptions<TEnv>["cache"];
|
|
279
|
+
/**
|
|
280
|
+
* Prerender store configuration (the writable durable overlay for on-demand
|
|
281
|
+
* prerender). Stored separately from the `prerender` trigger method so the RSC
|
|
282
|
+
* handler can resolve it per request. @internal
|
|
283
|
+
*/
|
|
284
|
+
readonly _prerenderConfig?: RangoOptions<TEnv>["prerender"];
|
|
257
285
|
/**
|
|
258
286
|
* Not found component to render when no route matches
|
|
259
287
|
*/
|
|
@@ -357,7 +385,8 @@ export interface RangoInternal<TEnv = any, TRoutes extends Record<string, unknow
|
|
|
357
385
|
*/
|
|
358
386
|
readonly nonce?: NonceProvider<TEnv>;
|
|
359
387
|
/**
|
|
360
|
-
*
|
|
388
|
+
* The consumer-set version (createRouter({ version })), used for both of the
|
|
389
|
+
* router's versions. Undefined when the router uses its build versions.
|
|
361
390
|
*/
|
|
362
391
|
readonly version?: string;
|
|
363
392
|
/**
|
|
@@ -470,6 +499,8 @@ export interface RangoInternal<TEnv = any, TRoutes extends Record<string, unknow
|
|
|
470
499
|
* Handle an RSC request.
|
|
471
500
|
*/
|
|
472
501
|
fetch(request: Request, input?: RouterRequestInput<TEnv>): Promise<Response>;
|
|
502
|
+
/** On-demand prerender binder: router.prerender({ env, ctx }) returns the runner. */
|
|
503
|
+
prerender: import("../prerender/on-demand.js").PrerenderFn<TEnv, TRoutes>;
|
|
473
504
|
}
|
|
474
505
|
/**
|
|
475
506
|
* Assert a public Rango into the internal type.
|
|
@@ -314,6 +314,30 @@ export interface RangoOptions<TEnv = any> {
|
|
|
314
314
|
enabled?: boolean;
|
|
315
315
|
searchParams?: CacheSearchParams;
|
|
316
316
|
});
|
|
317
|
+
/**
|
|
318
|
+
* Writable prerender store for on-demand (ISR-style) prerender refresh.
|
|
319
|
+
*
|
|
320
|
+
* A durable overlay in front of the bundled build manifest. When provided,
|
|
321
|
+
* `router.prerender(target, { env, ctx })` renders a route requestlessly and
|
|
322
|
+
* writes a versioned payload here; the serve path reads the overlay before the
|
|
323
|
+
* bundled manifest. Same union shape as `cache`: a plain config object or a
|
|
324
|
+
* factory resolved per request/per call (never at `createRouter()` time), so
|
|
325
|
+
* multi-tenant apps never memoize one request's binding for another.
|
|
326
|
+
*
|
|
327
|
+
* @example Cloudflare KV overlay with SWR revalidation
|
|
328
|
+
* ```typescript
|
|
329
|
+
* import { createKVPrerenderStore } from "@rangojs/router/prerender/cloudflare";
|
|
330
|
+
*
|
|
331
|
+
* const router = createRouter<AppEnv>({
|
|
332
|
+
* prerender: (env) => ({
|
|
333
|
+
* store: createKVPrerenderStore(env.PRERENDER_KV),
|
|
334
|
+
* ttl: 3600,
|
|
335
|
+
* onRevalidate: (target, e) => e.PRERENDER_QUEUE.send({ target }),
|
|
336
|
+
* }),
|
|
337
|
+
* });
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
prerender?: import("../prerender/on-demand.js").PrerenderConfig<TEnv> | ((env: TEnv, ctx?: ExecutionContext) => import("../prerender/on-demand.js").PrerenderConfig<TEnv>);
|
|
317
341
|
/**
|
|
318
342
|
* Named cache profiles for "use cache" directive.
|
|
319
343
|
* Profile names map to TTL/SWR configuration.
|
|
@@ -466,13 +490,23 @@ export interface RangoOptions<TEnv = any> {
|
|
|
466
490
|
*/
|
|
467
491
|
nonce?: NonceProvider<TEnv>;
|
|
468
492
|
/**
|
|
469
|
-
*
|
|
470
|
-
*
|
|
493
|
+
* Version override. When set, this exact value is used for both of the
|
|
494
|
+
* router's versions: it keys the router's cached data (segments, `"use
|
|
495
|
+
* cache"` values, loader data) and its stored HTML (PPR shells,
|
|
496
|
+
* document-cache responses), is sent in payload metadata, and is what the
|
|
497
|
+
* browser's `_rsc_v` is compared with (a mismatch reloads the tab).
|
|
498
|
+
*
|
|
499
|
+
* Leave it unset for the default: rango computes two versions per router at
|
|
500
|
+
* build time, a data version from the router's server code and a document
|
|
501
|
+
* version that also covers the client assets. The same code builds to the
|
|
502
|
+
* same versions, so a deploy that does not change this router keeps its
|
|
503
|
+
* cache. In dev both are a stamp bumped on every RSC module edit.
|
|
471
504
|
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
505
|
+
* Set it to clear this router's cache on demand (change the value), or to
|
|
506
|
+
* tie the cache to your own release id (a per-deploy value clears the cache
|
|
507
|
+
* on every deploy).
|
|
474
508
|
*
|
|
475
|
-
* @default
|
|
509
|
+
* @default the router's build versions
|
|
476
510
|
*/
|
|
477
511
|
version?: string;
|
|
478
512
|
/**
|
|
@@ -37,6 +37,13 @@ export interface ResolveSegmentOptions {
|
|
|
37
37
|
* #918: resolved twice on a MISS, once and discarded on a HIT).
|
|
38
38
|
*/
|
|
39
39
|
chain?: readonly EntryData[];
|
|
40
|
+
/**
|
|
41
|
+
* The matched chain entry being resolved: where the sync path catches a
|
|
42
|
+
* handler error, so a streamed handler (or slot owned by a routeless layout)
|
|
43
|
+
* recovers into the same boundary. resolveSegment sets it for the entry it
|
|
44
|
+
* resolves; nested resolutions keep the outer value.
|
|
45
|
+
*/
|
|
46
|
+
boundaryEntry?: EntryData;
|
|
40
47
|
}
|
|
41
48
|
/**
|
|
42
49
|
* Resolve segments from EntryData.
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* 1. options.key(requestCtx) — full override, stored namespaced as
|
|
10
10
|
* loader:{loaderId}:key:{encodeURIComponent(result)} (#1009)
|
|
11
11
|
* 2. store.keyGenerator(requestCtx, defaultKey) — store-level modification
|
|
12
|
-
* 3. loader:{loaderId}:{host}{pathname}:{sortedParams} — default
|
|
12
|
+
* 3. loader:{loaderId}:{routerId}@{host}{pathname}:{sortedParams} — default
|
|
13
|
+
* (a loader's ctx is one router's: cache-key-utils.ts, the router rule)
|
|
13
14
|
*
|
|
14
15
|
* Values are serialized via RSC Flight (serializeResult/deserializeResult),
|
|
15
16
|
* supporting ReactNode, Promises, null, and all RSC-serializable types.
|
|
@@ -42,6 +43,8 @@
|
|
|
42
43
|
*/
|
|
43
44
|
import { type EntryData, type LoaderEntry } from "../../server/context.js";
|
|
44
45
|
import type { HandlerContext } from "../../types.js";
|
|
46
|
+
import { type OwnedPushDelivery } from "../../cache/handle-snapshot.js";
|
|
47
|
+
import { type RequestContext } from "../../server/request-context.js";
|
|
45
48
|
/**
|
|
46
49
|
* Whether a request over the matched chain `entries` resolves a loader bound
|
|
47
50
|
* with its own cache(): on a chain entry, or on its parallel slots, orphan
|
|
@@ -51,15 +54,6 @@ import type { HandlerContext } from "../../types.js";
|
|
|
51
54
|
* Memoized per entry.
|
|
52
55
|
*/
|
|
53
56
|
export declare function bindsLoaderCache(entries: readonly EntryData[]): boolean;
|
|
54
|
-
/**
|
|
55
|
-
* The ids of the loaders a request over the matched chain `entries` runs on
|
|
56
|
-
* the live lane (no `ssr: false`), on a chain entry, its orphan layouts or
|
|
57
|
-
* its parallel slots. A document HIT tail restores the record's pushes of
|
|
58
|
-
* every other owner as authoritative (withCacheLookup, HandleStore
|
|
59
|
-
* pushRestored); a live-lane loader is a hole, so its live run replaces its
|
|
60
|
-
* recorded pushes instead. Memoized per entry.
|
|
61
|
-
*/
|
|
62
|
-
export declare function liveLaneLoaderIds(entries: readonly EntryData[]): ReadonlySet<string>;
|
|
63
57
|
/**
|
|
64
58
|
* The lane of each loader the matched chain `entries` registers: "live" (no
|
|
65
59
|
* `ssr: false`) or "bake". A loader registered on both is "live". A PPR
|
|
@@ -67,6 +61,25 @@ export declare function liveLaneLoaderIds(entries: readonly EntryData[]): Readon
|
|
|
67
61
|
* one is live (shell-capture.ts deriveShellCaptureContext).
|
|
68
62
|
*/
|
|
69
63
|
export declare function routeLoaderLanes(entries: readonly EntryData[]): ReadonlyMap<string, "live" | "bake">;
|
|
64
|
+
/**
|
|
65
|
+
* What a record restored on a request over the matched chain `entries` is to
|
|
66
|
+
* each loader's handle pushes (HandleStore RecordAuthority), from the pins
|
|
67
|
+
* the request serves (servedPins). Call it when the record hits: the pins are
|
|
68
|
+
* read here, once, because a navigation replay arms its seed for the match
|
|
69
|
+
* only and the store asks while loader bodies run.
|
|
70
|
+
*
|
|
71
|
+
* Each side applies its own lane to the pin. The value is per registration
|
|
72
|
+
* (resolveLoaderData: an `ssr: false` registration is served its pin). The
|
|
73
|
+
* pushes are per loader: one the route also registers without `ssr: false`
|
|
74
|
+
* is a hole whatever its other registration's pin says, because the capture
|
|
75
|
+
* credited its pushes to the live registration's run (routeLoaderLanes).
|
|
76
|
+
*
|
|
77
|
+
* A dependency the route does not register has no pin of its own, and the
|
|
78
|
+
* record does not name the loader that ran it at capture: its copies stand
|
|
79
|
+
* only while every `ssr: false` loader is pinned (exact when the pins are
|
|
80
|
+
* all there or all gone).
|
|
81
|
+
*/
|
|
82
|
+
export declare function loaderPins(entries: readonly EntryData[], reqCtx: RequestContext<any> | undefined): OwnedPushDelivery;
|
|
70
83
|
/**
|
|
71
84
|
* Resolve loader data with optional caching.
|
|
72
85
|
*
|
|
@@ -51,6 +51,8 @@ export declare function resolveParallelSegmentsWithRevalidation<TEnv>(entry: Ent
|
|
|
51
51
|
* to it: loader sub-ids are filtered out and slots are re-grouped by parent).
|
|
52
52
|
*/
|
|
53
53
|
loaderOrder?: "after" | "before";
|
|
54
|
+
/** Matched chain entry being resolved; see ResolveSegmentOptions.boundaryEntry. */
|
|
55
|
+
boundaryEntry?: EntryData;
|
|
54
56
|
}): Promise<SegmentRevalidationResult>;
|
|
55
57
|
/**
|
|
56
58
|
* Resolve entry handler (layout, cache, or route) with revalidation.
|
|
@@ -74,7 +76,9 @@ chain?: readonly EntryData[]): Promise<SegmentRevalidationResult>;
|
|
|
74
76
|
*/
|
|
75
77
|
export declare function resolveOrphanLayoutWithRevalidation<TEnv>(orphan: EntryData, params: Record<string, string>, context: HandlerContext<any, TEnv>, clientSegmentIds: Set<string>, prevParams: Record<string, string>, request: Request, prevUrl: URL, nextUrl: URL, routeKey: string, belongsToRoute: boolean, deps: SegmentResolutionDeps<TEnv>, actionContext?: ActionContext, stale?: boolean,
|
|
76
78
|
/** Parent route entry — its loaders are inherited so parallel slots can access them. */
|
|
77
|
-
parentRouteEntry?: EntryData
|
|
79
|
+
parentRouteEntry?: EntryData,
|
|
80
|
+
/** Matched chain entry being resolved (see ResolveSegmentOptions.boundaryEntry); defaults to parentRouteEntry. */
|
|
81
|
+
boundaryEntry?: EntryData | undefined): Promise<SegmentRevalidationResult>;
|
|
78
82
|
/**
|
|
79
83
|
* Resolve all segments for a route with revalidation logic (for matchPartial).
|
|
80
84
|
*/
|