@rangojs/router 0.17.0 → 0.19.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/README.md +3 -2
- package/dist/types/browser/cookie-name.d.ts +6 -0
- package/dist/types/browser/event-controller.d.ts +3 -3
- package/dist/types/browser/history-state.d.ts +18 -0
- package/dist/types/browser/navigation-transaction.d.ts +20 -2
- package/dist/types/browser/partial-update.d.ts +16 -1
- package/dist/types/browser/prefetch/cache.d.ts +6 -6
- package/dist/types/browser/react/Link.d.ts +19 -9
- package/dist/types/browser/react/context.d.ts +2 -2
- package/dist/types/browser/react/location-state-shared.d.ts +95 -56
- package/dist/types/browser/react/location-state.d.ts +1 -1
- package/dist/types/browser/transition-when.d.ts +80 -0
- package/dist/types/browser/types.d.ts +104 -9
- package/dist/types/build/generate-manifest.d.ts +8 -0
- package/dist/types/cache/background-task.d.ts +24 -2
- package/dist/types/cache/cache-exec-scope.d.ts +31 -0
- package/dist/types/cache/cache-key-utils.d.ts +48 -2
- package/dist/types/cache/cache-policy.d.ts +18 -1
- package/dist/types/cache/cache-runtime.d.ts +7 -0
- package/dist/types/cache/cache-scope.d.ts +192 -26
- package/dist/types/cache/cache-tag.d.ts +116 -11
- package/dist/types/cache/cf/cf-base64.d.ts +6 -0
- package/dist/types/cache/cf/cf-cache-constants.d.ts +11 -0
- package/dist/types/cache/cf/cf-cache-store.d.ts +224 -72
- package/dist/types/cache/cf/cf-cache-types.d.ts +31 -4
- package/dist/types/cache/cf/cf-shell-frame.d.ts +95 -0
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +19 -0
- package/dist/types/cache/document-cache.d.ts +10 -0
- package/dist/types/cache/handle-snapshot.d.ts +41 -8
- package/dist/types/cache/index.d.ts +1 -0
- package/dist/types/cache/invalidation-order.d.ts +23 -0
- package/dist/types/cache/isolate-tag-memo.d.ts +149 -0
- package/dist/types/cache/request-tag-mask.d.ts +54 -0
- package/dist/types/cache/shell-memo.d.ts +178 -0
- package/dist/types/cache/shell-snapshot.d.ts +141 -105
- package/dist/types/cache/tag-invalidation.d.ts +54 -3
- package/dist/types/cache/types.d.ts +267 -96
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +123 -18
- package/dist/types/client-urls/navigation.d.ts +28 -2
- package/dist/types/client-urls/server-projection.d.ts +5 -2
- package/dist/types/client-urls/types.d.ts +5 -5
- package/dist/types/client.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.rsc.d.ts +1 -1
- package/dist/types/prerender/build-shell-capture.d.ts +11 -4
- package/dist/types/route-definition/helpers-types.d.ts +11 -11
- package/dist/types/route-name.d.ts +7 -0
- package/dist/types/router/error-handling.d.ts +1 -1
- package/dist/types/router/instrument.d.ts +8 -0
- package/dist/types/router/intercept-resolution.d.ts +2 -0
- package/dist/types/router/match-context.d.ts +5 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +0 -4
- package/dist/types/router/middleware-types.d.ts +6 -1
- package/dist/types/router/router-options.d.ts +4 -1
- package/dist/types/router/segment-resolution/loader-cache.d.ts +58 -12
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -4
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +33 -48
- package/dist/types/router/segment-resolution/mask-nested.d.ts +73 -24
- package/dist/types/router/segment-resolution/view-transition-default.d.ts +7 -5
- package/dist/types/router/transition-when.d.ts +24 -10
- package/dist/types/rsc/attach-transition-when.d.ts +18 -0
- package/dist/types/rsc/full-payload.d.ts +21 -0
- package/dist/types/rsc/handler.d.ts +1 -1
- package/dist/types/rsc/response-cache-serve.d.ts +15 -12
- package/dist/types/rsc/shell-build-manifest.d.ts +12 -3
- package/dist/types/rsc/shell-capture-constants.d.ts +116 -12
- package/dist/types/rsc/shell-capture.d.ts +202 -74
- package/dist/types/rsc/shell-serve.d.ts +144 -50
- package/dist/types/rsc/types.d.ts +9 -0
- package/dist/types/segment-system.d.ts +7 -0
- package/dist/types/server/context.d.ts +155 -33
- package/dist/types/server/cookie-store.d.ts +33 -0
- package/dist/types/server/handle-store.d.ts +52 -1
- package/dist/types/server/request-context.d.ts +210 -63
- package/dist/types/server/request-headers.d.ts +44 -0
- package/dist/types/server.d.ts +1 -0
- package/dist/types/ssr/index.d.ts +9 -0
- package/dist/types/ssr/ssr-root.d.ts +9 -8
- package/dist/types/testing/e2e/index.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +7 -0
- package/dist/types/testing/index.d.ts +3 -2
- package/dist/types/testing/internal/action-id.d.ts +7 -0
- package/dist/types/testing/location-state-key.d.ts +24 -0
- package/dist/types/testing/render-route.d.ts +17 -1
- package/dist/types/testing/run-loader.d.ts +18 -3
- package/dist/types/testing/run-transition-when.d.ts +44 -69
- package/dist/types/testing/serve-shell-request.d.ts +133 -0
- package/dist/types/testing/shell-status.d.ts +44 -19
- package/dist/types/transition-when-ref.d.ts +79 -0
- package/dist/types/types/cache-types.d.ts +15 -3
- package/dist/types/types/handler-context.d.ts +14 -1
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/segments.d.ts +86 -71
- package/dist/types/urls/path-helper-types.d.ts +3 -4
- package/dist/types/urls/pattern-types.d.ts +21 -18
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +45 -0
- package/dist/types/vite/router-discovery.d.ts +29 -2
- package/dist/vite/index.js +1005 -105
- package/package.json +1 -1
- package/skills/breadcrumbs/SKILL.md +17 -7
- package/skills/cache-guide/SKILL.md +175 -76
- package/skills/caching/SKILL.md +361 -33
- package/skills/catalog.json +1 -1
- package/skills/client-urls/SKILL.md +12 -7
- package/skills/cloudflare/SKILL.md +15 -0
- package/skills/comparison/references/framework-comparison.md +52 -37
- package/skills/defer-hydration/SKILL.md +50 -30
- package/skills/deployment-caching/SKILL.md +5 -2
- package/skills/document-cache/SKILL.md +32 -2
- package/skills/handler-use/SKILL.md +2 -0
- package/skills/hooks/SKILL.md +3 -1
- package/skills/hooks/handle-and-actions.md +3 -1
- package/skills/hooks/navigation.md +23 -2
- package/skills/hooks/state.md +101 -7
- package/skills/intercept/SKILL.md +29 -12
- package/skills/loader/SKILL.md +197 -44
- package/skills/middleware/SKILL.md +34 -9
- package/skills/migrate-nextjs/SKILL.md +68 -37
- package/skills/migrate-react-router/SKILL.md +2 -1
- package/skills/migrate-react-router/component-migration.md +3 -1
- package/skills/migrate-react-router/data-and-actions.md +3 -1
- package/skills/migrate-react-router/route-mapping.md +7 -4
- package/skills/observability/SKILL.md +65 -0
- package/skills/parallel/SKILL.md +13 -8
- package/skills/ppr/SKILL.md +715 -371
- package/skills/prerender/SKILL.md +30 -17
- package/skills/rango/SKILL.md +72 -34
- package/skills/route/SKILL.md +14 -7
- package/skills/router-setup/SKILL.md +4 -2
- package/skills/scripts/SKILL.md +8 -1
- package/skills/server-actions/SKILL.md +11 -0
- package/skills/shell-manifest/SKILL.md +21 -12
- package/skills/testing/SKILL.md +49 -43
- package/skills/testing/cache-prerender.md +15 -14
- package/skills/testing/client-components.md +45 -3
- package/skills/testing/loader.md +19 -1
- package/skills/testing/middleware.md +1 -0
- package/skills/testing/predicates.md +49 -49
- package/skills/testing/render-handler.md +1 -0
- package/skills/testing/serve-shell-request.md +202 -0
- package/skills/testing/server-actions.md +9 -3
- package/skills/theme/SKILL.md +56 -4
- package/skills/typesafety/env-and-bindings.md +18 -2
- package/skills/use-cache/SKILL.md +91 -23
- package/skills/vercel/SKILL.md +14 -2
- package/skills/view-transitions/SKILL.md +150 -29
- package/src/__augment-tests__/augmented.check.ts +23 -0
- package/src/browser/cookie-name.ts +23 -0
- package/src/browser/event-controller.ts +4 -4
- package/src/browser/history-state.ts +75 -1
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +77 -18
- package/src/browser/navigation-client.ts +4 -3
- package/src/browser/navigation-store.ts +43 -1
- package/src/browser/navigation-transaction.ts +31 -11
- package/src/browser/partial-update.ts +146 -35
- package/src/browser/prefetch/cache.ts +6 -6
- package/src/browser/prefetch/fetch.ts +2 -2
- package/src/browser/react/Link.tsx +38 -33
- package/src/browser/react/NavigationProvider.tsx +2 -2
- package/src/browser/react/context.ts +2 -2
- package/src/browser/react/location-state-shared.ts +241 -49
- package/src/browser/react/location-state.ts +5 -2
- package/src/browser/rsc-router.tsx +9 -0
- package/src/browser/server-action-bridge.ts +84 -15
- package/src/browser/transition-when.ts +205 -0
- package/src/browser/types.ts +124 -10
- package/src/build/generate-manifest.ts +77 -1
- package/src/cache/background-task.ts +55 -2
- package/src/cache/cache-exec-scope.ts +48 -1
- package/src/cache/cache-key-utils.ts +62 -2
- package/src/cache/cache-policy.ts +31 -4
- package/src/cache/cache-runtime.ts +209 -129
- package/src/cache/cache-scope.ts +573 -69
- package/src/cache/cache-tag.ts +475 -19
- package/src/cache/cf/cf-base64.ts +36 -4
- package/src/cache/cf/cf-cache-constants.ts +12 -0
- package/src/cache/cf/cf-cache-store.ts +1094 -376
- package/src/cache/cf/cf-cache-types.ts +32 -4
- package/src/cache/cf/cf-shell-frame.ts +258 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +55 -40
- package/src/cache/document-cache.ts +53 -7
- package/src/cache/handle-snapshot.ts +53 -9
- package/src/cache/index.ts +2 -0
- package/src/cache/invalidation-order.ts +84 -0
- package/src/cache/isolate-tag-memo.ts +308 -0
- package/src/cache/request-tag-mask.ts +147 -0
- package/src/cache/shell-memo.ts +341 -0
- package/src/cache/shell-snapshot.ts +249 -277
- package/src/cache/tag-invalidation.ts +109 -18
- package/src/cache/types.ts +274 -102
- package/src/cache/vercel/vercel-cache-store.ts +561 -74
- package/src/client-urls/client-root.tsx +8 -4
- package/src/client-urls/client-urls.ts +8 -6
- package/src/client-urls/navigation.ts +55 -4
- package/src/client-urls/server-projection.ts +31 -10
- package/src/client-urls/types.ts +12 -5
- package/src/client.tsx +2 -0
- package/src/host/cookie-handler.ts +2 -1
- package/src/index.rsc.ts +3 -0
- package/src/index.ts +3 -0
- package/src/loader-redirect.tsx +7 -3
- package/src/prerender/build-shell-capture.ts +173 -110
- package/src/route-definition/dsl-helpers.ts +6 -3
- package/src/route-definition/helpers-types.ts +11 -11
- package/src/route-name.ts +12 -0
- package/src/router/content-negotiation.ts +4 -1
- package/src/router/error-handling.ts +5 -2
- package/src/router/handler-context.ts +42 -5
- package/src/router/instrument.ts +54 -2
- package/src/router/intercept-resolution.ts +30 -8
- package/src/router/loader-resolution.ts +89 -33
- package/src/router/logging.ts +5 -3
- package/src/router/match-api.ts +89 -42
- package/src/router/match-context.ts +5 -0
- package/src/router/match-handlers.ts +14 -29
- package/src/router/match-middleware/background-revalidation.ts +3 -5
- package/src/router/match-middleware/cache-lookup.ts +52 -19
- package/src/router/match-middleware/cache-store.ts +36 -10
- package/src/router/match-result.ts +1 -0
- package/src/router/middleware-types.ts +6 -1
- package/src/router/middleware.ts +20 -4
- package/src/router/navigation-snapshot.ts +6 -5
- package/src/router/prerender-match.ts +10 -0
- package/src/router/request-classification.ts +7 -4
- package/src/router/router-options.ts +4 -1
- package/src/router/segment-resolution/fresh.ts +18 -13
- package/src/router/segment-resolution/helpers.ts +4 -2
- package/src/router/segment-resolution/loader-cache.ts +366 -70
- package/src/router/segment-resolution/loader-mask.ts +3 -4
- package/src/router/segment-resolution/loader-snapshot.ts +215 -126
- package/src/router/segment-resolution/mask-nested.ts +161 -42
- package/src/router/segment-resolution/revalidation.ts +27 -13
- package/src/router/segment-resolution/view-transition-default.ts +6 -21
- package/src/router/telemetry.ts +6 -3
- package/src/router/transition-when.ts +34 -52
- package/src/router.ts +2 -1
- package/src/rsc/attach-transition-when.ts +47 -0
- package/src/rsc/full-payload.ts +47 -3
- package/src/rsc/handler.ts +24 -10
- package/src/rsc/loader-fetch.ts +2 -1
- package/src/rsc/manifest-init.ts +4 -0
- package/src/rsc/origin-guard.ts +8 -5
- package/src/rsc/progressive-enhancement.ts +10 -32
- package/src/rsc/response-cache-serve.ts +69 -78
- package/src/rsc/response-route-handler.ts +2 -2
- package/src/rsc/rsc-rendering.ts +712 -338
- package/src/rsc/server-action.ts +8 -20
- package/src/rsc/shell-build-manifest.ts +49 -29
- package/src/rsc/shell-capture-constants.ts +182 -12
- package/src/rsc/shell-capture.ts +1126 -612
- package/src/rsc/shell-serve.ts +331 -85
- package/src/rsc/ssr-setup.ts +3 -2
- package/src/rsc/types.ts +9 -0
- package/src/segment-system.tsx +40 -7
- package/src/server/context.ts +328 -72
- package/src/server/cookie-store.ts +184 -133
- package/src/server/handle-store.ts +245 -27
- package/src/server/request-context.ts +364 -100
- package/src/server/request-headers.ts +134 -0
- package/src/server.ts +4 -0
- package/src/ssr/index.tsx +96 -37
- package/src/ssr/ssr-root.tsx +9 -8
- package/src/testing/dispatch.ts +4 -7
- package/src/testing/e2e/index.ts +1 -0
- package/src/testing/flight.entry.ts +14 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/internal/action-id.ts +25 -0
- package/src/testing/internal/context.ts +1 -1
- package/src/testing/location-state-key.ts +45 -0
- package/src/testing/render-handler.ts +1 -1
- package/src/testing/render-route.tsx +109 -16
- package/src/testing/run-client-revalidate.ts +3 -19
- package/src/testing/run-loader.ts +67 -5
- package/src/testing/run-transition-when.ts +109 -172
- package/src/testing/serve-shell-request.ts +381 -0
- package/src/testing/shell-status.ts +73 -47
- package/src/theme/ThemeProvider.tsx +7 -6
- package/src/transition-when-ref.ts +220 -0
- package/src/types/cache-types.ts +15 -3
- package/src/types/handler-context.ts +14 -1
- package/src/types/index.ts +3 -0
- package/src/types/segments.ts +94 -91
- package/src/urls/path-helper-types.ts +3 -4
- package/src/urls/pattern-types.ts +21 -18
- package/src/vite/discovery/discover-routers.ts +3 -0
- package/src/vite/discovery/shell-prerender-phase.ts +9 -2
- package/src/vite/discovery/virtual-module-codegen.ts +16 -6
- package/src/vite/plugins/transition-when-hoist.ts +1064 -0
- package/src/vite/rango.ts +2 -0
- package/src/vite/router-discovery.ts +89 -9
- package/dist/types/rsc/transition-gate.d.ts +0 -23
- package/src/rsc/transition-gate.ts +0 -86
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
* `@vercel/functions`). It is the production store analogue to CFCacheStore, but
|
|
6
6
|
* far smaller: Vercel's Runtime Cache already IS a distributed, tag-aware cache
|
|
7
7
|
* (regional storage, global tag-expire within ~300ms), so none of CFCacheStore's
|
|
8
|
-
* L1/L2 tiering
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* L1/L2 tiering or per-tier timeout budgets are needed here - the platform does
|
|
9
|
+
* that work. Tag markers (`tm`, see isTagsInvalidatedSince) gate shell reads
|
|
10
|
+
* and writes and every cache write that started before an invalidation
|
|
11
|
+
* (#977); only PPR shell reads memoize them. What this
|
|
12
|
+
* store adds on top of the raw primitive is the parts Vercel does NOT give us:
|
|
11
13
|
*
|
|
12
14
|
* 1. Stale-while-revalidate. `getCache` has no stale-but-serve: a TTL'd entry
|
|
13
15
|
* simply becomes a miss. We store our own {staleAt, expiresAt} envelope and
|
|
@@ -30,8 +32,9 @@
|
|
|
30
32
|
* `getCache(...)` result, which satisfies the shape structurally. That keeps the
|
|
31
33
|
* router free of a hard Vercel dependency.
|
|
32
34
|
*/
|
|
33
|
-
import type { SegmentCacheStore, CachedEntryData, CacheDefaults, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry, CacheReadError } from "../types.js";
|
|
34
|
-
import type
|
|
35
|
+
import type { SegmentCacheStore, CachedEntryData, CacheDefaults, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry, ShellDocumentRead, ShellDocumentReadOptions, CacheReadError } from "../types.js";
|
|
36
|
+
import { type RequestContext } from "../../server/request-context.js";
|
|
37
|
+
import { type StoreMemoOptions } from "../shell-memo.js";
|
|
35
38
|
/**
|
|
36
39
|
* Minimal structural shape of the Vercel Runtime Cache returned by `getCache()`
|
|
37
40
|
* from `@vercel/functions`. Declared locally so @rangojs/router carries no hard
|
|
@@ -69,7 +72,7 @@ export declare const VERCEL_MAX_TAGS_PER_ITEM: number;
|
|
|
69
72
|
/** Max tag length in UTF-8 bytes accepted by Vercel; longer tags are skipped. */
|
|
70
73
|
export declare const VERCEL_MAX_TAG_BYTES: number;
|
|
71
74
|
/** Read-path outcome for the debug sink. */
|
|
72
|
-
export type VercelCacheReadOutcome = "miss" | "fresh" | "stale-revalidate" | "expired" | "corrupt" | "error";
|
|
75
|
+
export type VercelCacheReadOutcome = "miss" | "memo-hit" | "fresh" | "stale-revalidate" | "expired" | "corrupt" | "error";
|
|
73
76
|
/** Diagnostic event emitted on every read when `debug` is set. */
|
|
74
77
|
export interface VercelCacheReadDebugEvent {
|
|
75
78
|
op: "get" | "getItem" | "getResponse" | "getShell";
|
|
@@ -100,10 +103,13 @@ export interface VercelCacheStoreOptions<TEnv = unknown> {
|
|
|
100
103
|
*/
|
|
101
104
|
cache: VercelRuntimeCache;
|
|
102
105
|
/**
|
|
103
|
-
* `waitUntil` from `@vercel/functions`.
|
|
104
|
-
*
|
|
105
|
-
* backgrounds the actual writes
|
|
106
|
-
* (
|
|
106
|
+
* `waitUntil` from `@vercel/functions`. Keeps two background reads/writes
|
|
107
|
+
* alive past the response: the stale-read lock write (herd dampening; the
|
|
108
|
+
* router already backgrounds the actual writes) and the PPR shell reads'
|
|
109
|
+
* tag-marker memo refreshes (`memo.markerMaxStaleMs`). When omitted, both
|
|
110
|
+
* run detached (fire-and-forget), and the platform may end a refresh when
|
|
111
|
+
* the response ends; the next read past the stale window then reads the
|
|
112
|
+
* marker itself.
|
|
107
113
|
*/
|
|
108
114
|
waitUntil?: (promise: Promise<unknown>) => void;
|
|
109
115
|
/**
|
|
@@ -136,6 +142,26 @@ export interface VercelCacheStoreOptions<TEnv = unknown> {
|
|
|
136
142
|
* receives the structured VercelCacheReadDebugEvent.
|
|
137
143
|
*/
|
|
138
144
|
debug?: VercelCacheDebug;
|
|
145
|
+
/**
|
|
146
|
+
* Per-process memos ({@link StoreMemoOptions}), kept per `cache` handle:
|
|
147
|
+
* create the `getCache()` handle once per process, not per request, or the
|
|
148
|
+
* memos never hit. `shellMs` (default 2000) and `shellMaxBytes` (default
|
|
149
|
+
* 16 MiB) size the PPR shell memo; `markerFreshMs` (default 300) and
|
|
150
|
+
* `markerMaxStaleMs` (default 2000) the memo of the tag markers
|
|
151
|
+
* `invalidateTags()` writes, which PPR shell reads use
|
|
152
|
+
* (stale-while-revalidate). The process that invalidates writes the new
|
|
153
|
+
* marker into its memo; another process in the region rejects a memoized
|
|
154
|
+
* shell once its marker memo sees it (up to `markerMaxStaleMs`). The
|
|
155
|
+
* markers are a regional `cache.set` (only `expireTag` is global), so
|
|
156
|
+
* another region serves a shell it memoized before the invalidation until
|
|
157
|
+
* its window passes, where without the memo `expireTag` removes it within
|
|
158
|
+
* about 300 ms; a platform `expireTag` issued outside rango is likewise
|
|
159
|
+
* seen once the window passes. The response of a request that ran
|
|
160
|
+
* `updateTag()` / `revalidateTag()` sets the fresh-reads cookie, and the
|
|
161
|
+
* same user's requests carrying it skip both memos. `{ shellMs: 0 }` turns
|
|
162
|
+
* the shell memo off, `{ markerFreshMs: 0 }` the marker memo.
|
|
163
|
+
*/
|
|
164
|
+
memo?: StoreMemoOptions;
|
|
139
165
|
}
|
|
140
166
|
/**
|
|
141
167
|
* Vercel Runtime Cache-backed segment cache store.
|
|
@@ -170,12 +196,18 @@ export interface VercelCacheStoreOptions<TEnv = unknown> {
|
|
|
170
196
|
* import { getCache, waitUntil } from "@vercel/functions";
|
|
171
197
|
* import { VercelCacheStore } from "@rangojs/router/cache";
|
|
172
198
|
*
|
|
199
|
+
* // One handle per process: getCache() resolves the platform cache on every
|
|
200
|
+
* // call, and the PPR shell and tag-marker memos are kept per handle.
|
|
201
|
+
* // `process.env` (not `import.meta.env`, which needs a VITE_ prefix and
|
|
202
|
+
* // would be undefined here) so cross-deploy busting via `version` works.
|
|
203
|
+
* const runtimeCache = getCache({
|
|
204
|
+
* namespace: process.env.VERCEL_DEPLOYMENT_ID,
|
|
205
|
+
* });
|
|
206
|
+
*
|
|
173
207
|
* export const router = createRouter({
|
|
174
208
|
* cache: () => ({
|
|
175
209
|
* store: new VercelCacheStore({
|
|
176
|
-
*
|
|
177
|
-
* // would be undefined here) so cross-deploy busting via `version` works.
|
|
178
|
-
* cache: getCache({ namespace: process.env.VERCEL_DEPLOYMENT_ID }),
|
|
210
|
+
* cache: runtimeCache,
|
|
179
211
|
* waitUntil,
|
|
180
212
|
* defaults: { ttl: 60, swr: 300 },
|
|
181
213
|
* }),
|
|
@@ -191,6 +223,16 @@ export declare class VercelCacheStore<TEnv = unknown> implements SegmentCacheSto
|
|
|
191
223
|
private readonly waitUntil?;
|
|
192
224
|
private readonly version?;
|
|
193
225
|
private readonly maxItemBytes;
|
|
226
|
+
private readonly memo;
|
|
227
|
+
private readonly handleMemos;
|
|
228
|
+
/** @internal SegmentCacheStore.freshReadsWindowMs */
|
|
229
|
+
readonly freshReadsWindowMs: number;
|
|
230
|
+
/**
|
|
231
|
+
* @internal SegmentCacheStore.maxShellEntryBytes: the item cap, less the
|
|
232
|
+
* base64 expansion of the prelude the shell envelope stores (the capture
|
|
233
|
+
* measures raw prelude bytes).
|
|
234
|
+
*/
|
|
235
|
+
readonly maxShellEntryBytes: number;
|
|
194
236
|
private readonly name?;
|
|
195
237
|
private readonly debug?;
|
|
196
238
|
constructor(options: VercelCacheStoreOptions<TEnv>);
|
|
@@ -210,15 +252,78 @@ export declare class VercelCacheStore<TEnv = unknown> implements SegmentCacheSto
|
|
|
210
252
|
entry: ShellCacheEntry;
|
|
211
253
|
shouldRevalidate?: boolean;
|
|
212
254
|
} | null>;
|
|
255
|
+
/**
|
|
256
|
+
* @internal The document serve path's read (SegmentCacheStore
|
|
257
|
+
* .readShellDocument): the same read as getShell, with the prelude decoded
|
|
258
|
+
* here, once per memoized shell rather than once per HIT, and the read's
|
|
259
|
+
* `debugPerformance` stats. The runtime cache returns a parsed value, so
|
|
260
|
+
* there is no prelude-first read and the tag-marker read follows the entry
|
|
261
|
+
* read (`markerSerial`).
|
|
262
|
+
*/
|
|
263
|
+
readShellDocument(key: string, options?: ShellDocumentReadOptions): Promise<ShellDocumentRead | null>;
|
|
264
|
+
/** @internal SegmentCacheStore.dropShellMemo */
|
|
265
|
+
dropShellMemo(key: string): void;
|
|
266
|
+
/**
|
|
267
|
+
* getShell's read, shared with readShellDocument: the shell memo first
|
|
268
|
+
* (shell-memo.ts), then the runtime cache. A memoized shell still runs the
|
|
269
|
+
* tag-marker check; `memoized` is the memo slot's value when the read came
|
|
270
|
+
* from, or went into, the memo (readShellDocument keeps the decoded prelude
|
|
271
|
+
* there).
|
|
272
|
+
*/
|
|
273
|
+
private readShell;
|
|
274
|
+
/**
|
|
275
|
+
* The shell's tag-marker check, timed into `stats`. Markers a prefetch
|
|
276
|
+
* already started (hinted tags) are awaited, not re-read; the check itself
|
|
277
|
+
* always uses the entry's own tags.
|
|
278
|
+
*/
|
|
279
|
+
private shellTagsInvalidated;
|
|
280
|
+
/**
|
|
281
|
+
* Start the tm-marker reads of the tags this shell key carried last time
|
|
282
|
+
* (and the route's static tags) alongside the entry read.
|
|
283
|
+
*/
|
|
284
|
+
private prefetchShellMarkers;
|
|
285
|
+
/**
|
|
286
|
+
* A tag's latest invalidatedAt (or null). With `isolateMemo` (PPR shell
|
|
287
|
+
* reads only) through the per-process marker memo (isolate-tag-memo.ts):
|
|
288
|
+
* fresh values are used as is, stale ones are used and refreshed in the
|
|
289
|
+
* background, older ones block on the runtime-cache read. A request
|
|
290
|
+
* carrying the fresh-reads cookie skips the memo. A failed read rejects and
|
|
291
|
+
* is never memoized. The shell write gate, build shells and the data
|
|
292
|
+
* write gates (isTagsInvalidatedSince) read the runtime cache each time
|
|
293
|
+
* they ask; gates of a request asking while a read is in flight share it
|
|
294
|
+
* (gateMarkerRead), and nothing is kept once it settles.
|
|
295
|
+
*/
|
|
296
|
+
private readTagMarker;
|
|
213
297
|
putShell(key: string, entry: ShellCacheEntry, ttlSeconds?: number, swrSeconds?: number, tags?: string[]): Promise<"stored" | "invalidated" | void>;
|
|
214
298
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
299
|
+
* SegmentCacheStore.isTagsInvalidatedSince. expireTag() keeps no queryable
|
|
300
|
+
* history, so invalidateTags() writes "tm" markers for runtime capture
|
|
301
|
+
* races, immutable build shells and data writes that started before an
|
|
302
|
+
* invalidation (#977, tag-invalidation.ts predatesInvalidation). Marker >=
|
|
303
|
+
* generation start wins. Read errors fail open like the CF marker check,
|
|
304
|
+
* except for the write gate (`failClosed`), which counts them as an
|
|
305
|
+
* invalidation. Each tag's marker is read through gateMarkerRead
|
|
306
|
+
* (request-tag-mask.ts): gates asking while a read is in flight share it.
|
|
219
307
|
*/
|
|
220
|
-
isTagsInvalidatedSince(tags: string[], sinceMs: number
|
|
308
|
+
isTagsInvalidatedSince(tags: string[], sinceMs: number, options?: {
|
|
309
|
+
failClosed?: boolean;
|
|
310
|
+
}): Promise<boolean>;
|
|
311
|
+
private tagsInvalidatedSince;
|
|
221
312
|
invalidateTags(tags: string[]): Promise<void>;
|
|
313
|
+
/**
|
|
314
|
+
* The request-local half of invalidateTags(), run before its first await
|
|
315
|
+
* (#973): the request masks the tags (request-tag-mask.ts). The platform's
|
|
316
|
+
* expireTag() and the tm marker writes are what other requests see, and
|
|
317
|
+
* revalidateTag() does not wait for them.
|
|
318
|
+
*/
|
|
319
|
+
private maskTagsForRequest;
|
|
320
|
+
/**
|
|
321
|
+
* Whether this request masked one of `tags` through this store at or after
|
|
322
|
+
* `taggedAt`. An entry without a stamp counts as older than any mask.
|
|
323
|
+
*/
|
|
324
|
+
private maskedForRequest;
|
|
325
|
+
/** A data read's mask check: reports the miss and returns true when masked. */
|
|
326
|
+
private maskedMiss;
|
|
222
327
|
private toStoreKey;
|
|
223
328
|
private write;
|
|
224
329
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ClientUrlPatterns } from "./types.js";
|
|
2
|
+
import type { TransitionWhenFn } from "../types/segments.js";
|
|
2
3
|
export interface ClientUrlNavigationIntent {
|
|
3
4
|
readonly routeId: string;
|
|
4
5
|
/** Destination params from the local trie match (definition-local). */
|
|
@@ -6,14 +7,39 @@ export interface ClientUrlNavigationIntent {
|
|
|
6
7
|
/** Absolute destination pathname (mount included) and search ("?..." or ""). */
|
|
7
8
|
readonly pathname: string;
|
|
8
9
|
readonly search: string;
|
|
10
|
+
/**
|
|
11
|
+
* transition({ when }) gated this navigation off at the swap: the
|
|
12
|
+
* destination presents urgently instead of in a transition lane.
|
|
13
|
+
*/
|
|
14
|
+
readonly transitionGatedOff?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** What the bridge needs to decide transition({ when }) at the swap. */
|
|
17
|
+
export interface ClientUrlDestination {
|
|
18
|
+
/** Definition-local params of the destination match. */
|
|
19
|
+
readonly params: Readonly<Record<string, string>>;
|
|
20
|
+
/** Canonical route name (include prefix applied); undefined when unnamed. */
|
|
21
|
+
readonly routeName: string | undefined;
|
|
22
|
+
/** The destination route's own `when`, from its "use client" definition. */
|
|
23
|
+
readonly when: TransitionWhenFn | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Param names the ORIGIN route matched inside the group: the committed
|
|
26
|
+
* params minus these are the mount's (include prefix) params.
|
|
27
|
+
*/
|
|
28
|
+
readonly originLocalParamNames: readonly string[];
|
|
9
29
|
}
|
|
10
30
|
export declare function setActiveInterceptTargets(targets: readonly string[] | undefined): void;
|
|
11
31
|
export interface ClientUrlNavigationPresentation {
|
|
12
32
|
readonly routeId: string;
|
|
33
|
+
/**
|
|
34
|
+
* The transition({ when }) decision made at the optimistic swap (true =
|
|
35
|
+
* gated off), or undefined when nothing was swapped (a same-route
|
|
36
|
+
* navigation decides at the canonical commit).
|
|
37
|
+
*/
|
|
38
|
+
readonly transitionGatedOff: boolean | undefined;
|
|
13
39
|
clear(): void;
|
|
14
40
|
}
|
|
15
|
-
export declare function registerClientUrlGroup(definition: ClientUrlPatterns, mount: string, namePrefix: string, setIntent: (intent: ClientUrlNavigationIntent | null) => void): () => void;
|
|
16
|
-
export declare function beginClientUrlNavigation(targetUrl: URL, signal: AbortSignal): ClientUrlNavigationPresentation | null;
|
|
41
|
+
export declare function registerClientUrlGroup(definition: ClientUrlPatterns, mount: string, namePrefix: string, setIntent: (intent: ClientUrlNavigationIntent | null) => void, routeId?: string): () => void;
|
|
42
|
+
export declare function beginClientUrlNavigation(targetUrl: URL, signal: AbortSignal, decideTransition?: (destination: ClientUrlDestination) => boolean): ClientUrlNavigationPresentation | null;
|
|
17
43
|
/**
|
|
18
44
|
* Run the held clientUrls route's per-loader revalidate() predicates and
|
|
19
45
|
* encode their decisions for the request header. Predicates are CLIENT code
|
|
@@ -32,9 +32,12 @@ export interface ClientUrlProjectionRoute {
|
|
|
32
32
|
* document renders await them before first flush. Absent (= none) in
|
|
33
33
|
* projections serialized before the option existed. */
|
|
34
34
|
readonly awaitedLoaderIndices?: readonly number[];
|
|
35
|
-
/** Data-only transition config (
|
|
36
|
-
*
|
|
35
|
+
/** Data-only transition config (never `when`); absent in projections
|
|
36
|
+
* serialized before transition support. */
|
|
37
37
|
readonly transition?: Readonly<ClientTransitionConfig>;
|
|
38
|
+
/** The route's transition() declares a browser-run `when`. Materialization
|
|
39
|
+
* attaches a clientUrls when reference (definition + route id). */
|
|
40
|
+
readonly transitionWhen?: true;
|
|
38
41
|
}
|
|
39
42
|
export interface ClientUrlProjectionIntercept {
|
|
40
43
|
readonly slotName: `@${string}`;
|
|
@@ -88,12 +88,12 @@ export interface ClientUrlLoaderRecord {
|
|
|
88
88
|
readonly ssr?: false;
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
|
-
* The
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
91
|
+
* The TransitionConfig subset a clientUrls() route may declare: ViewTransition
|
|
92
|
+
* classes/name, the boundary opt-out, and the browser-run `when` gate. The
|
|
93
|
+
* projection carries only a "has when" marker; the browser calls the function
|
|
94
|
+
* this module declares (transition-when-ref.ts resolveTransitionWhen).
|
|
95
95
|
*/
|
|
96
|
-
export type ClientTransitionConfig = Pick<TransitionConfig, "enter" | "exit" | "update" | "share" | "default" | "name" | "viewTransition">;
|
|
96
|
+
export type ClientTransitionConfig = Pick<TransitionConfig, "enter" | "exit" | "update" | "share" | "default" | "name" | "viewTransition" | "when">;
|
|
97
97
|
export interface ClientUrlRouteRecord {
|
|
98
98
|
readonly id: string;
|
|
99
99
|
readonly pattern: string;
|
package/dist/types/client.d.ts
CHANGED
|
@@ -167,7 +167,7 @@ export { useSearchParams } from "./browser/react/use-search-params.js";
|
|
|
167
167
|
export type { SearchParamsInit, SetSearchParams, SetSearchParamsOptions, } from "./browser/react/use-search-params.js";
|
|
168
168
|
export { useParams } from "./browser/react/use-params.js";
|
|
169
169
|
export { useNonce } from "./browser/react/nonce-context.js";
|
|
170
|
-
export type { RouterInstance, RouterNavigateOptions, ReadonlyURLSearchParams, ActionState, ActionLifecycleState, } from "./browser/types.js";
|
|
170
|
+
export type { RouterInstance, RouterNavigateOptions, HistoryState, PlainHistoryState, ReadonlyURLSearchParams, ActionState, ActionLifecycleState, } from "./browser/types.js";
|
|
171
171
|
export { useAction, type ServerActionFunction, } from "./browser/react/use-action.js";
|
|
172
172
|
export { useSegments, type SegmentsState, } from "./browser/react/use-segments.js";
|
|
173
173
|
export { NavigationProvider, type NavigationProviderProps, } from "./browser/react/NavigationProvider.js";
|
package/dist/types/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type { SearchSchema, SearchSchemaValue, ResolveSearchSchema, RouteSearchP
|
|
|
16
16
|
export { TRACKING_SEARCH_PARAMS, type CacheSearchParams, } from "./cache/search-params-filter.js";
|
|
17
17
|
export { createLoader } from "./loader.js";
|
|
18
18
|
export type { RouteHelpers, RouteHandlers } from "./route-definition.js";
|
|
19
|
-
export type { TransitionConfig, TransitionWhenFn, TransitionWhenContext, ViewTransitionClass, } from "./types.js";
|
|
19
|
+
export type { TransitionConfig, TransitionWhenFn, TransitionWhenContext, TransitionWhenKind, RouteLocation, ServerRouteLocation, ViewTransitionClass, } from "./types.js";
|
|
20
20
|
export type { RouteUseItem, LayoutUseItem, AllUseItems, UseItems, HandlerUseItem, } from "./route-types.js";
|
|
21
21
|
export type { ResponseHandler, ResponseHandlerContext, JsonResponseHandler, TextResponseHandler, JsonValue, ResponsePathFn, JsonResponsePathFn, TextResponsePathFn, RouteResponse, ProblemDetails, PartialPrerenderProps, } from "./urls.js";
|
|
22
22
|
export type { MiddlewareContext, CookieOptions } from "./router/middleware.js";
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* in RSC context, while the regular index.ts is used in client components.
|
|
10
10
|
*/
|
|
11
11
|
export { RouteNotFoundError, DataNotFoundError, notFound, MiddlewareError, HandlerError, BuildError, DslContextError, InvalidHandlerError, RouterError, Skip, isSkip, } from "./index.js";
|
|
12
|
-
export type { DocumentProps, DefaultEnv, RouteDefinition, RouteConfig, RouteDefinitionOptions, TrailingSlashMode, Handler, HandlerContext, ExtractParams, GenericParams, Middleware, RevalidateParams, Revalidate, ActionRef, IsActionFn, RouteKeys, LoaderDefinition, LoaderFn, LoaderContext, LoaderOptions, FetchableLoaderOptions, LoadOptions, ErrorInfo, ErrorBoundaryFallbackProps, ErrorBoundaryHandler, ClientErrorBoundaryFallbackProps, NotFoundInfo, NotFoundBoundaryFallbackProps, NotFoundBoundaryHandler, ErrorPhase, OnErrorContext, OnErrorCallback, TransitionConfig, TransitionWhenFn, TransitionWhenContext, ViewTransitionClass, } from "./types.js";
|
|
12
|
+
export type { DocumentProps, DefaultEnv, RouteDefinition, RouteConfig, RouteDefinitionOptions, TrailingSlashMode, Handler, HandlerContext, ExtractParams, GenericParams, Middleware, RevalidateParams, Revalidate, ActionRef, IsActionFn, RouteKeys, LoaderDefinition, LoaderFn, LoaderContext, LoaderOptions, FetchableLoaderOptions, LoadOptions, ErrorInfo, ErrorBoundaryFallbackProps, ErrorBoundaryHandler, ClientErrorBoundaryFallbackProps, NotFoundInfo, NotFoundBoundaryFallbackProps, NotFoundBoundaryHandler, ErrorPhase, OnErrorContext, OnErrorCallback, TransitionConfig, TransitionWhenFn, TransitionWhenContext, TransitionWhenKind, RouteLocation, ServerRouteLocation, ViewTransitionClass, } from "./types.js";
|
|
13
13
|
export type { RangoOptions, SSRStreamMode, SSROptions, ResolveStreamingContext, } from "./router.js";
|
|
14
14
|
export type { OriginCheckConfig, OriginCheckContext, OriginCheckPhase, } from "./rsc/origin-guard.js";
|
|
15
15
|
export type { ShellCaptureDebug, ShellCaptureDebugEvent, } from "./rsc/shell-capture.js";
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Runs in the RSC realm of the build's temp server, AFTER all bundles are
|
|
5
5
|
* written (the prelude embeds built client asset URLs — bootstrap module,
|
|
6
6
|
* chunk preloads — that only exist post-client-build). The capture core is
|
|
7
|
-
* producer A's, verbatim: deriveShellCaptureContext (
|
|
8
|
-
*
|
|
9
|
-
* quiesce, tags union, putShell barrier). Build capture first replays global
|
|
7
|
+
* producer A's, verbatim: deriveShellCaptureContext (push funnel, snapshot
|
|
8
|
+
* recording, implicit doc-cache scope) + settleCaptureRecord (the record-first
|
|
9
|
+
* step) + captureAndStoreShell (gates, quiesce, tags union, putShell barrier). Build capture first replays global
|
|
10
10
|
* and route middleware with a synthetic build request context
|
|
11
11
|
* (`ctx.build === true`, inert `ctx.waitUntil()`); middleware can seed vars or
|
|
12
12
|
* call `ctx.dynamic()` to skip this URL. The sink is an entry collector instead
|
|
@@ -95,10 +95,17 @@ export interface BuildShellCaptureResult {
|
|
|
95
95
|
tags?: string[];
|
|
96
96
|
/** On route-mismatch: what this router's match actually landed on. */
|
|
97
97
|
matchedRouteName?: string;
|
|
98
|
+
/**
|
|
99
|
+
* On no-shell: the attempt ran out of ppr.captureTimeout. It is not
|
|
100
|
+
* retried: its match may still be running, and the retry would start the
|
|
101
|
+
* same work beside it (runtime twin: shell-capture.ts runShellCapture).
|
|
102
|
+
*/
|
|
103
|
+
timedOut?: true;
|
|
98
104
|
}
|
|
99
105
|
/**
|
|
100
106
|
* Capture the PPR shell for one prerendered URL at build time. Retries once
|
|
101
107
|
* in place on `no-shell` (the first attempt warms the temp server's SSR/Flight
|
|
102
|
-
* transform graph, mirroring producer A's cold-start retry — same delay)
|
|
108
|
+
* transform graph, mirroring producer A's cold-start retry — same delay),
|
|
109
|
+
* unless the attempt ran out of ppr.captureTimeout (`timedOut`).
|
|
103
110
|
*/
|
|
104
111
|
export declare function captureShellForBuild(opts: BuildShellCaptureOptions): Promise<BuildShellCaptureResult>;
|
|
@@ -110,7 +110,7 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
110
110
|
*
|
|
111
111
|
* // Conditional activation via the config object's `when` selector
|
|
112
112
|
* intercept("@modal", "card", <CardModal />, {
|
|
113
|
-
* when: ({ from }) => from.pathname.startsWith("/board"),
|
|
113
|
+
* when: ({ from }) => from.url.pathname.startsWith("/board"),
|
|
114
114
|
* })
|
|
115
115
|
*
|
|
116
116
|
* // Config + other use-items: config is arg 4, use is arg 5
|
|
@@ -118,7 +118,7 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
118
118
|
* "@modal",
|
|
119
119
|
* "card",
|
|
120
120
|
* <CardModal />,
|
|
121
|
-
* { when: ({ from }) => from.pathname.startsWith("/board") },
|
|
121
|
+
* { when: ({ from }) => from.url.pathname.startsWith("/board") },
|
|
122
122
|
* () => [loader(CardDetailLoader)],
|
|
123
123
|
* )
|
|
124
124
|
* ```
|
|
@@ -387,12 +387,12 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
387
387
|
* transition({}) is startTransition + ViewTransition under the default and
|
|
388
388
|
* startTransition only when the router sets viewTransition: false.
|
|
389
389
|
*
|
|
390
|
-
* Conditional hold: pass `when
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
390
|
+
* Conditional hold: pass `when` to gate the navigation in the browser,
|
|
391
|
+
* inline (the build hoists the literal into a client module) or as a
|
|
392
|
+
* "use client" export. It runs once per
|
|
393
|
+
* navigation with { kind, from, to, isAction, action }, never on the server;
|
|
394
|
+
* false makes the commit urgent (no hold, no view transition). This is
|
|
395
|
+
* distinct from intercept()'s match-time `when` selector.
|
|
396
396
|
*
|
|
397
397
|
* ```typescript
|
|
398
398
|
* // Attach to a single route
|
|
@@ -411,15 +411,15 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
411
411
|
* transition({ viewTransition: false }),
|
|
412
412
|
* ])
|
|
413
413
|
*
|
|
414
|
-
* // Hold only when
|
|
414
|
+
* // Hold only when arriving from the list (a browser predicate):
|
|
415
415
|
* path("/product/:id", ProductPage, { name: "product" }, () => [
|
|
416
|
-
* transition({ when: (
|
|
416
|
+
* transition({ when: ({ from }) => from.routeName === "products.list" }),
|
|
417
417
|
* ])
|
|
418
418
|
* ```
|
|
419
419
|
* @param config - ViewTransition configuration (enter, exit, update, share,
|
|
420
420
|
* default, name), `viewTransition: "auto" | false` to toggle the router
|
|
421
421
|
* boundary (createRouter({ viewTransition }) sets the app-wide default), and
|
|
422
|
-
* `when
|
|
422
|
+
* `when` to gate the transition per navigation (a browser predicate)
|
|
423
423
|
* @param children - Optional callback returning child routes to wrap
|
|
424
424
|
*/
|
|
425
425
|
transition: {
|
|
@@ -17,6 +17,13 @@ export declare const INTERNAL_INCLUDE_SCOPE_PREFIX = "$prefix_";
|
|
|
17
17
|
* be preserved.
|
|
18
18
|
*/
|
|
19
19
|
export declare function isAutoGeneratedRouteName(name: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The route name user code may see: a user-defined name, or undefined for an
|
|
22
|
+
* internal one (unnamed path(), hidden include scope). Internal names are
|
|
23
|
+
* route keys, not API, and must not leak into transition({ when }) or
|
|
24
|
+
* intercept({ when }) locations.
|
|
25
|
+
*/
|
|
26
|
+
export declare function publicRouteName(routeKey: string | undefined): string | undefined;
|
|
20
27
|
/**
|
|
21
28
|
* Validate that a user-provided route name does not collide with
|
|
22
29
|
* reserved internal prefixes. Checks every dot-separated segment,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Also includes the shared invokeOnError utility for error callback invocation.
|
|
6
6
|
*/
|
|
7
7
|
import { type ReactNode } from "react";
|
|
8
|
-
import type { EntryData } from "../server/context";
|
|
8
|
+
import type { EntryData } from "../server/context.js";
|
|
9
9
|
import type { ResolvedSegment, ErrorInfo, ErrorBoundaryHandler, NotFoundInfo, NotFoundBoundaryHandler, ErrorPhase, OnErrorCallback } from "../types";
|
|
10
10
|
/**
|
|
11
11
|
* Context required to invoke the onError callback.
|
|
@@ -163,6 +163,14 @@ export declare function observePhase<T>(spec: PhaseSpec, fn: (span: TraceSpan) =
|
|
|
163
163
|
* nothing to record here and short-circuits.
|
|
164
164
|
*/
|
|
165
165
|
export declare function observeHandler<C, R>(id: string, handler: (ctx: C) => R, ctx: C): R;
|
|
166
|
+
/**
|
|
167
|
+
* observeHandler, inside segment `segmentId`'s tag scope, so the tags the
|
|
168
|
+
* handler records reach the route's cache() record (#957, cache-tag.ts
|
|
169
|
+
* runInSegmentTagScope). `spanId` is observeHandler's `id`. A request that
|
|
170
|
+
* cannot write a record takes observeHandler's path as is, with the same one
|
|
171
|
+
* request-context read: no scope, no closure.
|
|
172
|
+
*/
|
|
173
|
+
export declare function observeSegmentHandler<C, R>(segmentId: string, spanId: string, handler: (ctx: C) => R, ctx: C): R;
|
|
166
174
|
/**
|
|
167
175
|
* Emit one discrete telemetry event (the event-shaped counterpart to
|
|
168
176
|
* observePhase). Resolves the sink from the active router context and stamps the
|
|
@@ -11,6 +11,8 @@ import type { SegmentResolutionDeps } from "./types.js";
|
|
|
11
11
|
* Check if an intercept's when conditions are satisfied.
|
|
12
12
|
* All when() functions must return true for the intercept to activate.
|
|
13
13
|
* If no when() conditions are defined, the intercept always activates.
|
|
14
|
+
* A selector that throws yields the conservative default, no intercept (the
|
|
15
|
+
* full page renders), and is logged; it never fails the request.
|
|
14
16
|
*
|
|
15
17
|
* During action revalidation, when() is NOT evaluated.
|
|
16
18
|
*/
|
|
@@ -151,6 +151,11 @@ export interface MatchContext<TEnv = any> {
|
|
|
151
151
|
interceptSelectorContext: InterceptSelectorContext;
|
|
152
152
|
isSameRouteNavigation: boolean;
|
|
153
153
|
interceptResult: InterceptResult | null;
|
|
154
|
+
/**
|
|
155
|
+
* An intercept targets this route, matched or not (a same-route navigation
|
|
156
|
+
* skips it), so the response depends on the source. Partial matches only.
|
|
157
|
+
*/
|
|
158
|
+
interceptTargeted?: boolean;
|
|
154
159
|
cacheScope: CacheScope | null;
|
|
155
160
|
isIntercept: boolean;
|
|
156
161
|
actionContext?: ActionContext;
|
|
@@ -126,10 +126,6 @@ import { type RequestContext } from "../../server/request-context.js";
|
|
|
126
126
|
* cache-scope.ts), so a swap sent live pushes into this render.
|
|
127
127
|
* setupLoaderAccess binds the store at setup, so it runs inside the
|
|
128
128
|
* derived context too.
|
|
129
|
-
* - _transitionWhen: fresh resolution appends transition({ when })
|
|
130
|
-
* predicates; the foreground's gateTransitions reads the array after the
|
|
131
|
-
* match, and a stale HIT (which replays the stored transition) must not
|
|
132
|
-
* evaluate this render's predicates.
|
|
133
129
|
* - _metricsStore: undefined, and the DSL store below has `metrics` unset
|
|
134
130
|
* (track() reads that one), so nothing lands on the foreground's perf
|
|
135
131
|
* timeline. ctx.Store.run closes over ctx.Store, so the derived store
|
|
@@ -48,7 +48,12 @@ export interface MiddlewareContext<TEnv = any, TParams = Record<string, string |
|
|
|
48
48
|
header(name: string, value: string): void;
|
|
49
49
|
routeName?: DefaultRouteName;
|
|
50
50
|
debugPerformance(): void;
|
|
51
|
-
|
|
51
|
+
/**
|
|
52
|
+
* The visitor's theme (cookie or default); undefined without theme config.
|
|
53
|
+
* Guarded like `cookies()`: a read inside a `"use cache"` function throws
|
|
54
|
+
* (#971).
|
|
55
|
+
*/
|
|
56
|
+
readonly theme?: Theme;
|
|
52
57
|
setTheme?: (theme: Theme) => void;
|
|
53
58
|
setLocationState(entries: LocationStateEntry | LocationStateEntry[]): void;
|
|
54
59
|
/** Global route names only; see {@link GlobalReverseFunction}. */
|
|
@@ -481,7 +481,10 @@ export interface RangoOptions<TEnv = any> {
|
|
|
481
481
|
*
|
|
482
482
|
* Controls how long prefetch responses are kept in the client-side
|
|
483
483
|
* in-memory cache and sets `Cache-Control: private, max-age=<ttl>`
|
|
484
|
-
* on
|
|
484
|
+
* on prefetch responses, so the browser's HTTP cache may reuse them
|
|
485
|
+
* (`private`: shared caches such as a CDN do not store them). A route an
|
|
486
|
+
* intercept targets gets no prefetch `Cache-Control`: whether its
|
|
487
|
+
* response is the modal or the full page depends on the source page.
|
|
485
488
|
*
|
|
486
489
|
* The cache is automatically invalidated on server actions regardless
|
|
487
490
|
* of TTL, so this is primarily a staleness safety net.
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* getItem()/setItem() methods on SegmentCacheStore.
|
|
7
7
|
*
|
|
8
8
|
* Cache key resolution (3-tier, matching CacheScope.resolveKey):
|
|
9
|
-
* 1. options.key(requestCtx) — full override
|
|
9
|
+
* 1. options.key(requestCtx) — full override, stored namespaced as
|
|
10
|
+
* loader:{loaderId}:key:{encodeURIComponent(result)} (#1009)
|
|
10
11
|
* 2. store.keyGenerator(requestCtx, defaultKey) — store-level modification
|
|
11
12
|
* 3. loader:{loaderId}:{host}{pathname}:{sortedParams} — default
|
|
12
13
|
*
|
|
@@ -17,15 +18,55 @@
|
|
|
17
18
|
* On stale hit (SWR): returns stale data, schedules background revalidation.
|
|
18
19
|
* On miss: executes loader, schedules non-blocking cache write.
|
|
19
20
|
*
|
|
21
|
+
* Identity (#972): without a key() or a store keyGenerator the entry is
|
|
22
|
+
* shared across users, so a fill whose execution recorded a request-identity
|
|
23
|
+
* read fails and is not stored, whoever started that execution
|
|
24
|
+
* (server/context.ts recordLoaderIdentityRead).
|
|
25
|
+
*
|
|
20
26
|
* Handle pushes (`ctx.use(Handle)(...)` in the loader body) are a side effect
|
|
21
27
|
* the HIT must reproduce: the MISS records the pushes of the body and of the
|
|
22
28
|
* loaders it awaits via ctx.use into the entry's `handles` blob (the
|
|
23
29
|
* "use cache" capture/encode), and every HIT — stale included — replays
|
|
24
30
|
* them, each loader's pushes at most once per request (a dependency another
|
|
25
31
|
* reader already ran keeps its live pushes). See replayLoaderHandles.
|
|
32
|
+
*
|
|
33
|
+
* Tags too (#964): the entry stores its cache() tags plus every tag its
|
|
34
|
+
* execution recorded, those of the loader values it read included
|
|
35
|
+
* (cache-tag.ts "Recorded-tag sets"), so updateTag() of any of them drops it.
|
|
36
|
+
* Every HIT records the stored tags through the loader's tag owner
|
|
37
|
+
* (recordLoaderTags), so a route cache() record, PPR shell or document built
|
|
38
|
+
* over the HIT carries them, and a loader that reads this one takes them on.
|
|
39
|
+
* Once the binding started, a loader body's ctx.use of it gets the same
|
|
40
|
+
* dataPromise as a handler read (createLoaderExecutor's useLoader); a stale
|
|
41
|
+
* refresh does not (setupLoaderAccess _runLoaderIsolated).
|
|
26
42
|
*/
|
|
27
|
-
import { type LoaderEntry } from "../../server/context.js";
|
|
43
|
+
import { type EntryData, type LoaderEntry } from "../../server/context.js";
|
|
28
44
|
import type { HandlerContext } from "../../types.js";
|
|
45
|
+
/**
|
|
46
|
+
* Whether a request over the matched chain `entries` resolves a loader bound
|
|
47
|
+
* with its own cache(): on a chain entry, or on its parallel slots, orphan
|
|
48
|
+
* layouts or intercepts. The match arms the per-execution loader tag sets on
|
|
49
|
+
* it (cache-tag.ts armLoaderTagSets), before any loader starts, so a
|
|
50
|
+
* dependency the handler or another binding starts first still records.
|
|
51
|
+
* Memoized per entry.
|
|
52
|
+
*/
|
|
53
|
+
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
|
+
/**
|
|
64
|
+
* The lane of each loader the matched chain `entries` registers: "live" (no
|
|
65
|
+
* `ssr: false`) or "bake". A loader registered on both is "live". A PPR
|
|
66
|
+
* capture credits a push to the first registered loader around it when that
|
|
67
|
+
* one is live (shell-capture.ts deriveShellCaptureContext).
|
|
68
|
+
*/
|
|
69
|
+
export declare function routeLoaderLanes(entries: readonly EntryData[]): ReadonlyMap<string, "live" | "bake">;
|
|
29
70
|
/**
|
|
30
71
|
* Resolve loader data with optional caching.
|
|
31
72
|
*
|
|
@@ -46,18 +87,23 @@ import type { HandlerContext } from "../../types.js";
|
|
|
46
87
|
* never run under a shell capture), so the lane is decided here, per LOADER,
|
|
47
88
|
* never by the entry's loading():
|
|
48
89
|
*
|
|
49
|
-
* - BAKE lane: `loader(Def, { ssr: false })` (
|
|
50
|
-
* `bakeSegmentKey`
|
|
90
|
+
* - BAKE lane: `loader(Def, { ssr: false })` (LoaderEntry `bake`: the
|
|
91
|
+
* caller passes a `bakeSegmentKey` for it on document and navigation
|
|
92
|
+
* evaluations alike; a capture, a document evaluation, also has
|
|
93
|
+
* awaitBeforeFlush). The loader EXECUTES at capture (the
|
|
51
94
|
* flag's "data in the HTML before first flush" maps to the frozen prelude)
|
|
52
95
|
* and its settled non-promise data bakes into the shell. Promises nested in
|
|
53
|
-
* plain objects
|
|
54
|
-
* the consumer's own Suspense — per-request material must be
|
|
55
|
-
* (the #692 cross-session scar). The masked container
|
|
56
|
-
* `_shellCaptureLoaderRecords`: it holds the capture gate
|
|
57
|
-
* `ppr.captureTimeout`) and pins into the snapshot's loader
|
|
58
|
-
* HIT the recorded container is overlaid onto the fresh
|
|
59
|
-
* payload matches the frozen prelude
|
|
60
|
-
*
|
|
96
|
+
* plain objects, arrays and JSX props are masked (mask-nested.ts) and stay
|
|
97
|
+
* live holes at the consumer's own Suspense — per-request material must be
|
|
98
|
+
* promise-shaped (the #692 cross-session scar). The masked container
|
|
99
|
+
* registers on `_shellCaptureLoaderRecords`: it holds the capture gate
|
|
100
|
+
* (bounded by `ppr.captureTimeout`) and pins into the snapshot's loader
|
|
101
|
+
* family, and on a HIT the recorded container is overlaid onto the fresh
|
|
102
|
+
* run (below) so the payload matches the frozen prelude outside the holes.
|
|
103
|
+
* A server-component element holding a promise is a hole as a whole, so its
|
|
104
|
+
* other props come from the fresh run (loader-snapshot.ts
|
|
105
|
+
* elideLoaderContainer). cookies()/headers() in its body (nested promise
|
|
106
|
+
* bodies included) trip the capture guard.
|
|
61
107
|
* - LIVE lane: every other loader, whatever its entry's loading(). Never
|
|
62
108
|
* executes at capture: the slot gets a never-resolving promise
|
|
63
109
|
* (loader-mask.ts) and postpones at the reader's boundary — loading() or an
|
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
* fresh into it.
|
|
9
9
|
*
|
|
10
10
|
* Capture mode is signalled by `requestCtx._shellCaptureRun`, set to true ONLY on
|
|
11
|
-
* the derived request context of the background capture task (shell-capture.ts)
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* for the mask so every loader execution site gates the same way (loader-cache.ts
|
|
11
|
+
* the derived request context of the background capture task (shell-capture.ts);
|
|
12
|
+
* the foreground render never sets it. This module is the single home for the
|
|
13
|
+
* mask so every loader execution site gates the same way (loader-cache.ts
|
|
15
14
|
* `resolveLoaderData`, fresh.ts `resolveLoaders`).
|
|
16
15
|
*/
|
|
17
16
|
import { type RequestContext } from "../../server/request-context.js";
|