@rangojs/router 0.16.0 → 0.18.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 +255 -89
- package/dist/testing/vitest.js +252 -0
- package/dist/types/browser/cookie-name.d.ts +6 -0
- package/dist/types/browser/history-state.d.ts +16 -0
- package/dist/types/browser/navigation-transaction.d.ts +6 -0
- package/dist/types/browser/partial-update.d.ts +11 -0
- package/dist/types/browser/react/ScrollRestoration.d.ts +6 -6
- package/dist/types/browser/rsc-router.d.ts +1 -1
- package/dist/types/browser/scroll-restoration.d.ts +7 -0
- package/dist/types/cache/cache-exec-scope.d.ts +18 -1
- package/dist/types/cache/cache-key-utils.d.ts +17 -2
- package/dist/types/cache/cache-policy.d.ts +17 -0
- package/dist/types/cache/cache-scope.d.ts +132 -19
- package/dist/types/cache/cache-tag.d.ts +92 -7
- 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 +185 -44
- 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 +34 -0
- package/dist/types/cache/handle-capture.d.ts +41 -3
- package/dist/types/cache/handle-snapshot.d.ts +54 -13
- package/dist/types/cache/index.d.ts +1 -0
- package/dist/types/cache/isolate-tag-memo.d.ts +149 -0
- package/dist/types/cache/segment-codec.d.ts +10 -3
- package/dist/types/cache/shell-memo.d.ts +178 -0
- package/dist/types/cache/shell-snapshot.d.ts +110 -21
- package/dist/types/cache/tag-invalidation.d.ts +30 -3
- package/dist/types/cache/taint.d.ts +1 -1
- package/dist/types/cache/types.d.ts +220 -44
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +111 -13
- package/dist/types/client.d.ts +4 -4
- package/dist/types/client.rsc.d.ts +4 -5
- package/dist/types/components/DefaultDocument.d.ts +5 -2
- package/dist/types/context-var.d.ts +6 -5
- package/dist/types/escape-script.d.ts +1 -1
- package/dist/types/handles/MetaTags.d.ts +5 -4
- package/dist/types/handles/Scripts.d.ts +8 -7
- package/dist/types/handles/meta.d.ts +2 -2
- package/dist/types/handles/script.d.ts +17 -16
- package/dist/types/href-client.d.ts +1 -1
- package/dist/types/html.d.ts +12 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.rsc.d.ts +3 -2
- package/dist/types/loader-store.d.ts +7 -4
- package/dist/types/prerender/build-shell-capture.d.ts +11 -4
- package/dist/types/reverse.d.ts +36 -4
- package/dist/types/route-definition/dsl-helpers.d.ts +3 -3
- package/dist/types/route-definition/helpers-types.d.ts +33 -9
- package/dist/types/route-definition/resolve-handler-use.d.ts +23 -1
- package/dist/types/route-types.d.ts +1 -1
- package/dist/types/router/debug-manifest.d.ts +3 -2
- package/dist/types/router/error-handling.d.ts +20 -0
- package/dist/types/router/handler-context.d.ts +6 -0
- package/dist/types/router/instrument.d.ts +8 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +46 -5
- package/dist/types/router/middleware-types.d.ts +9 -3
- package/dist/types/router/router-context.d.ts +3 -1
- package/dist/types/router/router-interfaces.d.ts +24 -2
- package/dist/types/router/router-options.d.ts +8 -5
- package/dist/types/router/segment-resolution/fresh.d.ts +10 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +66 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +9 -19
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +23 -12
- package/dist/types/router/segment-resolution/mask-nested.d.ts +67 -26
- package/dist/types/router/segment-resolution/revalidation.d.ts +6 -2
- package/dist/types/router/segment-wrappers.d.ts +1 -1
- package/dist/types/rsc/full-payload.d.ts +14 -0
- package/dist/types/rsc/handler.d.ts +1 -1
- package/dist/types/rsc/response-route-handler.d.ts +1 -1
- package/dist/types/rsc/rsc-rendering.d.ts +1 -2
- package/dist/types/rsc/shell-build-manifest.d.ts +8 -0
- package/dist/types/rsc/shell-capture-constants.d.ts +61 -6
- package/dist/types/rsc/shell-capture.d.ts +151 -19
- package/dist/types/rsc/shell-serve.d.ts +140 -17
- package/dist/types/rsc/ssr-setup.d.ts +6 -6
- package/dist/types/rsc/types.d.ts +17 -0
- package/dist/types/server/context.d.ts +139 -15
- package/dist/types/server/cookie-store.d.ts +21 -0
- package/dist/types/server/handle-store.d.ts +26 -2
- package/dist/types/server/request-context.d.ts +182 -53
- package/dist/types/ssr/index.d.ts +24 -0
- package/dist/types/ssr/ssr-root.d.ts +9 -8
- package/dist/types/static-handler.d.ts +4 -1
- package/dist/types/testing/flight.entry.d.ts +7 -0
- package/dist/types/testing/generated-routes.d.ts +2 -2
- package/dist/types/testing/internal/context.d.ts +1 -1
- package/dist/types/testing/render-route.d.ts +32 -6
- package/dist/types/testing/run-loader.d.ts +18 -3
- package/dist/types/testing/serve-shell-request.d.ts +132 -0
- package/dist/types/testing/shell-status.d.ts +23 -10
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +28 -5
- package/dist/types/testing/vitest.d.ts +35 -1
- package/dist/types/theme/ThemeScript.d.ts +3 -3
- package/dist/types/types/cache-types.d.ts +14 -10
- package/dist/types/types/handler-context.d.ts +28 -1
- package/dist/types/types/loader-types.d.ts +8 -6
- package/dist/types/urls/pattern-types.d.ts +22 -18
- package/dist/types/urls/response-types.d.ts +3 -12
- package/dist/types/use-loader.d.ts +12 -3
- package/dist/types/vite/plugins/use-cache-transform.d.ts +33 -2
- package/dist/types/vite/rango.d.ts +1 -1
- package/dist/types/vite/router-discovery.d.ts +29 -2
- package/dist/vite/index.js +1420 -1348
- package/package.json +2 -2
- package/skills/api-client/SKILL.md +22 -10
- package/skills/breadcrumbs/SKILL.md +75 -22
- package/skills/bundle-analysis/SKILL.md +22 -22
- package/skills/cache-guide/SKILL.md +306 -124
- package/skills/caching/SKILL.md +530 -98
- package/skills/catalog.json +16 -16
- package/skills/client-urls/SKILL.md +65 -38
- package/skills/cloudflare/SKILL.md +87 -20
- package/skills/cloudflare/references/d1-and-local-dev.md +15 -2
- package/skills/cloudflare/references/streaming-and-deploy.md +10 -3
- package/skills/cloudflare/references/webhooks-and-crypto.md +9 -2
- package/skills/comparison/SKILL.md +5 -0
- package/skills/comparison/references/framework-comparison.md +75 -57
- package/skills/composability/SKILL.md +38 -29
- package/skills/css/SKILL.md +10 -13
- package/skills/debug-manifest/SKILL.md +74 -31
- package/skills/defer-hydration/SKILL.md +52 -31
- package/skills/deployment-caching/SKILL.md +11 -3
- package/skills/document-cache/SKILL.md +98 -28
- package/skills/fonts/SKILL.md +16 -8
- package/skills/handler-use/SKILL.md +55 -17
- package/skills/hooks/SKILL.md +28 -20
- package/skills/hooks/data.md +23 -3
- package/skills/hooks/handle-and-actions.md +34 -17
- package/skills/hooks/navigation.md +39 -10
- package/skills/hooks/outlets.md +13 -6
- package/skills/hooks/state.md +39 -15
- package/skills/hooks/urls.md +7 -5
- package/skills/host-router/SKILL.md +64 -12
- package/skills/i18n/SKILL.md +60 -34
- package/skills/intercept/SKILL.md +161 -26
- package/skills/layout/SKILL.md +106 -50
- package/skills/links/SKILL.md +51 -19
- package/skills/loader/SKILL.md +386 -128
- package/skills/middleware/SKILL.md +129 -26
- package/skills/migrate-nextjs/SKILL.md +156 -70
- package/skills/migrate-nextjs/backend-host-swap.md +5 -2
- package/skills/migrate-react-router/SKILL.md +51 -39
- package/skills/migrate-react-router/component-migration.md +28 -7
- package/skills/migrate-react-router/data-and-actions.md +21 -6
- package/skills/migrate-react-router/route-mapping.md +19 -10
- package/skills/mime-routes/SKILL.md +12 -7
- package/skills/observability/SKILL.md +92 -14
- package/skills/parallel/SKILL.md +88 -47
- package/skills/ppr/SKILL.md +866 -379
- package/skills/prerender/SKILL.md +210 -108
- package/skills/rango/SKILL.md +115 -65
- package/skills/react-compiler/SKILL.md +6 -5
- package/skills/response-routes/SKILL.md +133 -25
- package/skills/route/SKILL.md +170 -60
- package/skills/router-setup/SKILL.md +420 -240
- package/skills/scripts/SKILL.md +39 -21
- package/skills/server-actions/SKILL.md +231 -59
- package/skills/shell-manifest/SKILL.md +28 -14
- package/skills/streams-and-websockets/SKILL.md +32 -14
- package/skills/tailwind/SKILL.md +37 -33
- package/skills/testing/SKILL.md +73 -33
- package/skills/testing/cache-prerender.md +60 -33
- package/skills/testing/client-components.md +59 -6
- package/skills/testing/e2e-parity.md +12 -2
- package/skills/testing/flight.md +19 -11
- package/skills/testing/handles.md +8 -5
- package/skills/testing/loader.md +26 -6
- package/skills/testing/middleware.md +8 -3
- package/skills/testing/predicates.md +120 -0
- package/skills/testing/render-handler.md +70 -22
- package/skills/testing/response-routes.md +11 -4
- package/skills/testing/reverse-and-types.md +20 -14
- package/skills/testing/serve-shell-request.md +188 -0
- package/skills/testing/server-actions.md +12 -3
- package/skills/testing/server-tree.md +9 -0
- package/skills/testing/setup.md +9 -5
- package/skills/theme/SKILL.md +155 -30
- package/skills/typesafety/SKILL.md +20 -9
- package/skills/typesafety/env-and-bindings.md +137 -50
- package/skills/typesafety/generated-files-and-cli.md +26 -14
- package/skills/typesafety/params-and-search.md +44 -19
- package/skills/typesafety/route-types.md +50 -14
- package/skills/use-cache/SKILL.md +224 -83
- package/skills/vercel/SKILL.md +35 -13
- package/skills/view-transitions/SKILL.md +42 -21
- package/src/__augment-tests__/augmented.check.ts +26 -1
- package/src/browser/cookie-name.ts +23 -0
- package/src/browser/history-state.ts +23 -0
- package/src/browser/index.ts +2 -2
- package/src/browser/navigation-bridge.ts +3 -4
- package/src/browser/navigation-transaction.ts +22 -2
- package/src/browser/partial-update.ts +35 -25
- package/src/browser/react/ScrollRestoration.tsx +6 -6
- package/src/browser/rsc-router.tsx +6 -1
- package/src/browser/scroll-restoration.ts +53 -6
- package/src/cache/cache-exec-scope.ts +37 -4
- package/src/cache/cache-key-utils.ts +23 -8
- package/src/cache/cache-policy.ts +22 -0
- package/src/cache/cache-runtime.ts +264 -68
- package/src/cache/cache-scope.ts +419 -43
- package/src/cache/cache-tag.ts +375 -11
- 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 +990 -348
- 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 +143 -39
- package/src/cache/document-cache.ts +15 -0
- package/src/cache/handle-capture.ts +90 -10
- package/src/cache/handle-snapshot.ts +133 -28
- package/src/cache/index.ts +2 -0
- package/src/cache/isolate-tag-memo.ts +308 -0
- package/src/cache/segment-codec.ts +26 -7
- package/src/cache/shell-memo.ts +341 -0
- package/src/cache/shell-snapshot.ts +217 -27
- package/src/cache/tag-invalidation.ts +108 -22
- package/src/cache/taint.ts +1 -1
- package/src/cache/types.ts +225 -44
- package/src/cache/vercel/vercel-cache-store.ts +545 -61
- package/src/client.rsc.tsx +10 -9
- package/src/client.tsx +5 -4
- package/src/components/DefaultDocument.tsx +7 -2
- package/src/context-var.ts +6 -5
- package/src/escape-script.ts +1 -1
- package/src/handles/MetaTags.tsx +13 -11
- package/src/handles/Scripts.tsx +11 -10
- package/src/handles/meta.ts +2 -2
- package/src/handles/script.ts +17 -16
- package/src/href-client.ts +1 -1
- package/src/html.ts +12 -0
- package/src/index.rsc.ts +5 -0
- package/src/index.ts +1 -0
- package/src/loader-store.ts +7 -4
- package/src/prerender/build-shell-capture.ts +73 -22
- package/src/reverse.ts +44 -4
- package/src/route-definition/dsl-helpers.ts +121 -33
- package/src/route-definition/helpers-types.ts +33 -9
- package/src/route-definition/resolve-handler-use.ts +121 -6
- package/src/route-types.ts +0 -3
- package/src/router/debug-manifest.ts +10 -2
- package/src/router/error-handling.ts +51 -15
- package/src/router/handler-context.ts +71 -28
- package/src/router/instrument.ts +54 -2
- package/src/router/intercept-resolution.ts +141 -43
- package/src/router/loader-resolution.ts +115 -39
- package/src/router/match-api.ts +40 -26
- package/src/router/match-handlers.ts +5 -0
- package/src/router/match-middleware/background-revalidation.ts +161 -96
- package/src/router/match-middleware/cache-lookup.ts +110 -10
- package/src/router/match-middleware/cache-store.ts +48 -101
- package/src/router/middleware-types.ts +9 -6
- package/src/router/middleware.ts +75 -13
- package/src/router/prerender-match.ts +59 -19
- package/src/router/route-snapshot.ts +11 -1
- package/src/router/router-context.ts +2 -0
- package/src/router/router-interfaces.ts +25 -2
- package/src/router/router-options.ts +8 -5
- package/src/router/segment-resolution/fresh.ts +62 -21
- package/src/router/segment-resolution/helpers.ts +4 -2
- package/src/router/segment-resolution/loader-cache.ts +407 -76
- package/src/router/segment-resolution/loader-mask.ts +12 -22
- package/src/router/segment-resolution/loader-snapshot.ts +208 -56
- package/src/router/segment-resolution/mask-nested.ts +138 -44
- package/src/router/segment-resolution/revalidation.ts +61 -16
- package/src/router/segment-wrappers.ts +4 -0
- package/src/rsc/full-payload.ts +25 -1
- package/src/rsc/handler.ts +14 -2
- package/src/rsc/progressive-enhancement.ts +3 -2
- package/src/rsc/render-pipeline.ts +3 -0
- package/src/rsc/response-cache-serve.ts +9 -6
- package/src/rsc/response-route-handler.ts +11 -3
- package/src/rsc/rsc-rendering.ts +608 -225
- package/src/rsc/shell-build-manifest.ts +27 -9
- package/src/rsc/shell-capture-constants.ts +73 -6
- package/src/rsc/shell-capture.ts +1068 -296
- package/src/rsc/shell-serve.ts +316 -34
- package/src/rsc/ssr-setup.ts +14 -8
- package/src/rsc/types.ts +18 -0
- package/src/server/context.ts +300 -32
- package/src/server/cookie-store.ts +87 -61
- package/src/server/handle-store.ts +232 -7
- package/src/server/request-context.ts +297 -67
- package/src/ssr/index.tsx +136 -44
- package/src/ssr/ssr-root.tsx +9 -8
- package/src/static-handler.ts +4 -1
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/flight.entry.ts +14 -0
- package/src/testing/generated-routes.ts +2 -2
- package/src/testing/internal/context.ts +1 -1
- package/src/testing/internal/flight-client-globals.ts +7 -5
- package/src/testing/render-route.tsx +85 -24
- package/src/testing/run-loader.ts +68 -6
- package/src/testing/serve-shell-request.ts +378 -0
- package/src/testing/shell-status.ts +34 -12
- package/src/testing/vitest-stubs/plugin-rsc.ts +123 -20
- package/src/testing/vitest.ts +62 -1
- package/src/theme/ThemeProvider.tsx +7 -6
- package/src/theme/ThemeScript.tsx +3 -3
- package/src/types/cache-types.ts +14 -10
- package/src/types/handler-context.ts +28 -1
- package/src/types/loader-types.ts +8 -6
- package/src/urls/pattern-types.ts +22 -18
- package/src/urls/response-types.ts +3 -23
- package/src/use-loader.tsx +12 -3
- package/src/vite/discovery/shell-prerender-phase.ts +9 -0
- package/src/vite/plugins/use-cache-transform.ts +118 -74
- package/src/vite/rango.ts +7 -3
- package/src/vite/router-discovery.ts +14 -4
|
@@ -104,6 +104,40 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
104
104
|
_rotateStateCookie(): void;
|
|
105
105
|
/** @internal Set the keepClientCache() directive header on the response. */
|
|
106
106
|
_setKeepCacheDirective(): void;
|
|
107
|
+
/**
|
|
108
|
+
* @internal This request carries the fresh-reads cookie: it follows an
|
|
109
|
+
* updateTag()/revalidateTag() by the same user, so the stores read tag
|
|
110
|
+
* markers and shells from the store, not from an isolate memo.
|
|
111
|
+
*/
|
|
112
|
+
_freshReads?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* @internal Set the fresh-reads cookie on this response for `maxAgeMs`
|
|
115
|
+
* (rounded up to whole seconds; the longest stays). Called by
|
|
116
|
+
* updateTag()/revalidateTag().
|
|
117
|
+
*/
|
|
118
|
+
_setFreshReadsCookie(maxAgeMs: number): void;
|
|
119
|
+
/**
|
|
120
|
+
* @internal The context createRequestContext() returned. A context derived
|
|
121
|
+
* from it with Object.create (a PPR HIT tail, a shell capture, a background
|
|
122
|
+
* revalidation render) inherits it, so per-request invalidation state
|
|
123
|
+
* (tag-invalidation.ts, the stores' masks) is keyed by the request, not by
|
|
124
|
+
* whichever derived object called or read (#973).
|
|
125
|
+
*/
|
|
126
|
+
_requestRoot?: RequestContext<any, any>;
|
|
127
|
+
/**
|
|
128
|
+
* @internal The tags this request invalidated with
|
|
129
|
+
* updateTag()/revalidateTag(), each with its position in the invalidation
|
|
130
|
+
* order (tag-invalidation.ts currentCacheSeq). Kept on _requestRoot. A
|
|
131
|
+
* "use cache" execution that started before one of its own tags was
|
|
132
|
+
* invalidated is neither joined nor written (cache-runtime.ts, #973).
|
|
133
|
+
*/
|
|
134
|
+
_tagInvalidations?: Map<string, number>;
|
|
135
|
+
/**
|
|
136
|
+
* @internal The handler has handed the response to the host (rsc/handler.ts
|
|
137
|
+
* `rango.response`): header and cookie writes after this are lost, as from
|
|
138
|
+
* a streaming loader or render.
|
|
139
|
+
*/
|
|
140
|
+
_responseSent?: boolean;
|
|
107
141
|
/**
|
|
108
142
|
* Access loader data or push handle data.
|
|
109
143
|
*
|
|
@@ -129,8 +163,13 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
129
163
|
};
|
|
130
164
|
/** HTTP method (GET, POST, PUT, PATCH, DELETE, etc.) */
|
|
131
165
|
method: string;
|
|
132
|
-
/**
|
|
133
|
-
|
|
166
|
+
/**
|
|
167
|
+
* @internal Handle store for tracking handle data across segments.
|
|
168
|
+
* Readonly: a background render that needs its own store derives a context
|
|
169
|
+
* (rerenderAndCacheRoute, shell-capture.ts) instead of swapping this field,
|
|
170
|
+
* which the foreground still reads while it produces the page.
|
|
171
|
+
*/
|
|
172
|
+
readonly _handleStore: HandleStore;
|
|
134
173
|
/**
|
|
135
174
|
* @internal transition({ when }) predicates for segments matched this request,
|
|
136
175
|
* keyed by segment id. Collected during resolution (the function is stripped
|
|
@@ -178,15 +217,52 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
178
217
|
/**
|
|
179
218
|
* @internal Bake-lane loader containers collected DURING a shell capture:
|
|
180
219
|
* segment-key -> the loader's (pre-wrap) result promise. Populated by
|
|
181
|
-
* resolveLoaderData for loaders
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* shared shell). Own property of the capture's derived context only.
|
|
220
|
+
* resolveLoaderData for bake-lane loaders (lane rule: see its JSDoc in
|
|
221
|
+
* loader-cache.ts). Drained by captureAndStoreShell after the shell
|
|
222
|
+
* quiesces: settled containers are promise-elided, Flight-serialized, and
|
|
223
|
+
* pinned into the snapshot's loader family; a REJECTED container refuses
|
|
224
|
+
* the capture (error UI must never bake into the shared shell). Own
|
|
225
|
+
* property of the capture's derived context only.
|
|
188
226
|
*/
|
|
189
227
|
_shellCaptureLoaderRecords?: Map<string, Promise<unknown>>;
|
|
228
|
+
/**
|
|
229
|
+
* @internal Set on a capture's derived context when a loader pushed a
|
|
230
|
+
* value the record cannot keep (a deferred push, masked nested promises,
|
|
231
|
+
* or a push outside a loader body): the loader records then carry
|
|
232
|
+
* `runs: 1`, so a HIT still runs their bodies for those pushes.
|
|
233
|
+
*/
|
|
234
|
+
_shellCaptureUnrecordedLoaderPush?: true;
|
|
235
|
+
/**
|
|
236
|
+
* @internal Record keys resolved for this request (CacheScope
|
|
237
|
+
* resolveKeyFrom): by the scope's `key()` (one result) or its store's
|
|
238
|
+
* keyGenerator (one per default key). A shell capture's derived context
|
|
239
|
+
* reads it through the prototype chain, so the capture reuses the
|
|
240
|
+
* partition its request resolved instead of running `key()` again.
|
|
241
|
+
*/
|
|
242
|
+
_resolvedCacheKeys?: Map<unknown, Map<string, Promise<string>>>;
|
|
243
|
+
/**
|
|
244
|
+
* @internal The shell store key the PPR serve path resolved for this
|
|
245
|
+
* document request (rsc-rendering.ts shellServePlan), request partition
|
|
246
|
+
* included. Read by the testing helper serveShellRequest.
|
|
247
|
+
*/
|
|
248
|
+
_shellKey?: string;
|
|
249
|
+
/**
|
|
250
|
+
* @internal The request carried the forced-MISS reload marker
|
|
251
|
+
* (shell-serve.ts SHELL_MISS_PARAM). The handler strips the marker from the
|
|
252
|
+
* request on entry and sets this; the shell gate renders the request like a
|
|
253
|
+
* cache miss.
|
|
254
|
+
*/
|
|
255
|
+
_shellForcedMiss?: true;
|
|
256
|
+
/**
|
|
257
|
+
* @internal The freshness window of the route cache() records this
|
|
258
|
+
* request read or wrote (cache-scope.ts noteRouteRecordWindow), as ms
|
|
259
|
+
* timestamps: `freshUntil` is the record's `expiresAt`, `staleUntil` adds
|
|
260
|
+
* its scope's swr. The narrowest record wins. A shell capture caps its
|
|
261
|
+
* entry's ttl and ttl+swr to it (shell-capture.ts capShellWindow), so a
|
|
262
|
+
* shell is never fresher, or served longer, than the route cache() entry
|
|
263
|
+
* it replayed or wrote.
|
|
264
|
+
*/
|
|
265
|
+
_routeRecordWindow?: RouteRecordWindow;
|
|
190
266
|
/**
|
|
191
267
|
* @internal Loader-family snapshot seed for a shell HIT's tail render:
|
|
192
268
|
* segment-key -> the capture's elided container (already Flight-deserialized
|
|
@@ -194,21 +270,24 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
194
270
|
* overlays it onto the fresh run's container (recorded paths pinned,
|
|
195
271
|
* hole-marker paths keep the fresh nested promises) so the payload's baked
|
|
196
272
|
* bytes match the frozen prelude; a hole-free entry resolves pin-first
|
|
197
|
-
*
|
|
198
|
-
* context
|
|
273
|
+
* and does not run the loader. Two owners: serveShellHit sets it on the
|
|
274
|
+
* HIT tail's derived context, and matchPartialWithPprReplay sets it on the
|
|
275
|
+
* request context of a PPR partial replay once its doc record hits, and
|
|
276
|
+
* restores the previous value after the match.
|
|
199
277
|
*/
|
|
200
278
|
_shellLoaderSeed?: Map<string, import("../cache/shell-snapshot.js").ShellLoaderSeedEntry>;
|
|
201
279
|
/**
|
|
202
|
-
* @internal
|
|
203
|
-
*
|
|
280
|
+
* @internal The doc record marker: makes the next match treat the whole
|
|
281
|
+
* matched route as an implicit doc-level cache() boundary (see
|
|
204
282
|
* resolveShellImplicitCacheScope in cache/cache-scope.ts). Set ONLY on
|
|
205
283
|
* (a) the capture's derived context — with a record-only store so the
|
|
206
284
|
* capture's cacheRoute write lands in the snapshot, never the real store —
|
|
207
|
-
* (b) a HIT tail's seeded context, and (c) an eligible
|
|
208
|
-
* replay, where `store` is a request-local segment
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
285
|
+
* (b) a document HIT tail's seeded context (`docTail`), and (c) an eligible
|
|
286
|
+
* normal-route partial replay, where `store` is a request-local segment
|
|
287
|
+
* overlay.
|
|
288
|
+
* A document HIT tail replays the record even for a route with its own
|
|
289
|
+
* cache() config (the gate before the commit already evaluated that
|
|
290
|
+
* scope's opt-outs). Elsewhere the route's scope stays authoritative. On the
|
|
212
291
|
* navigation-replay serve path (`onExplicitHit` set) the marker COMPOSES with
|
|
213
292
|
* such a scope instead of being ignored: the seeded doc record supplies the match
|
|
214
293
|
* only when the explicit tier misses (withCacheLookup). cache(false) and a
|
|
@@ -225,12 +304,17 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
225
304
|
* segment record even when the triggering request is partial.
|
|
226
305
|
*/
|
|
227
306
|
keyPrefix?: "doc";
|
|
228
|
-
/**
|
|
229
|
-
|
|
307
|
+
/**
|
|
308
|
+
* @internal Called only after the implicit cache hit decodes
|
|
309
|
+
* successfully; the lookup awaits it before returning the hit, so work
|
|
310
|
+
* it starts lands before the route's loaders resolve.
|
|
311
|
+
*/
|
|
312
|
+
onHit?: () => void | Promise<void>;
|
|
230
313
|
/**
|
|
231
314
|
* @internal Called when the seeded document record fails server-side
|
|
232
315
|
* deserialization. Partial replay uses it to replace the enclosing shell
|
|
233
|
-
* snapshot after serving the fresh fallback.
|
|
316
|
+
* snapshot after serving the fresh fallback. A document HIT tail does not
|
|
317
|
+
* set it: withCacheLookup throws ShellRecordUnavailableError instead.
|
|
234
318
|
*/
|
|
235
319
|
onCorrupt?: () => void;
|
|
236
320
|
/**
|
|
@@ -241,6 +325,21 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
241
325
|
* require the exact consumable record instead of "any segment record".
|
|
242
326
|
*/
|
|
243
327
|
docKey?: string;
|
|
328
|
+
/**
|
|
329
|
+
* @internal Set on a document HIT tail (serveShellHit). The implicit doc
|
|
330
|
+
* scope replaces any route-derived cache() scope for the tail's match
|
|
331
|
+
* (resolveShellImplicitCacheScope), and a lookup that does not hit throws
|
|
332
|
+
* ShellRecordUnavailableError instead of resolving segments
|
|
333
|
+
* (withCacheLookup): a HIT never runs a handler.
|
|
334
|
+
*/
|
|
335
|
+
docTail?: true;
|
|
336
|
+
/**
|
|
337
|
+
* @internal The key a document HIT tail looks the doc record up by: the
|
|
338
|
+
* entry's own `docKey`. Recomputing it could name another key (a store
|
|
339
|
+
* keyGenerator folding request data, a build-time capture's synthetic
|
|
340
|
+
* host) and miss the record.
|
|
341
|
+
*/
|
|
342
|
+
fixedDocKey?: string;
|
|
244
343
|
/**
|
|
245
344
|
* @internal Set ONLY by matchPartialWithPprReplay on the navigation-replay
|
|
246
345
|
* serve path. Its presence arms the explicit-scope composition in
|
|
@@ -282,41 +381,19 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
282
381
|
*/
|
|
283
382
|
_shellFragmentPayload?: boolean;
|
|
284
383
|
/**
|
|
285
|
-
* @internal
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* pushes (liveness unknowable at the barrier); (c) a handler-invoked loader
|
|
290
|
-
* executing during the capture (loader-resolution.ts — its consumption-lane
|
|
291
|
-
* value would freeze on a handler-free HIT). captureAndStoreShell folds it
|
|
292
|
-
* into ShellCacheEntry.handlerLiveHoles at the putShell barrier. Own
|
|
293
|
-
* property of the capture's derived context only.
|
|
294
|
-
*/
|
|
295
|
-
_shellCaptureHandleLiveness?: {
|
|
296
|
-
holes: boolean;
|
|
297
|
-
pendingPushes: number;
|
|
298
|
-
handlerInvokedLoader: boolean;
|
|
299
|
-
};
|
|
300
|
-
/**
|
|
301
|
-
* @internal Handle values pushed from a DSL loader scope DURING a shell
|
|
302
|
-
* capture (identity set; populated by the capture push wrapper in
|
|
303
|
-
* shell-capture.ts). cacheRoute threads it into captureHandles so those
|
|
304
|
-
* values stay out of cache-write handle records — loaders re-run fresh on
|
|
305
|
-
* every HIT, so replaying their captured (masked) values would duplicate
|
|
306
|
-
* the fresh push and stall the Flight handle encode. Own property of the
|
|
307
|
-
* capture's derived context only; render-time handle consumers are
|
|
308
|
-
* unaffected (the exclusion applies only at the captureHandles call site).
|
|
309
|
-
*/
|
|
310
|
-
_shellCaptureLoaderHandleValues?: WeakSet<object>;
|
|
311
|
-
/**
|
|
312
|
-
* @internal Set (to the offending fn name) by the cookies()/headers()
|
|
313
|
-
* capture guard when it throws DURING a capture render. Load-bearing for the
|
|
384
|
+
* @internal Set by the capture guard (server/context.ts
|
|
385
|
+
* tripShellCaptureGuard) when it throws DURING a capture render: the read
|
|
386
|
+
* ("cookies()", "headers()", "ctx.get()", "ctx.theme") and the fix the
|
|
387
|
+
* refusal warning gives for it. Load-bearing for the
|
|
314
388
|
* bake lane: a guard throw inside an executing loader is swallowed by
|
|
315
389
|
* wrapLoaderPromise into per-loader error UI, which would otherwise bake
|
|
316
390
|
* silently into the shared shell — the capture checks this flag after the
|
|
317
391
|
* render and refuses instead. Deterministic, so the capture does not retry.
|
|
318
392
|
*/
|
|
319
|
-
_shellCaptureGuardTripped?:
|
|
393
|
+
_shellCaptureGuardTripped?: {
|
|
394
|
+
surface: string;
|
|
395
|
+
fix: string;
|
|
396
|
+
};
|
|
320
397
|
/**
|
|
321
398
|
* @internal The loader $$id whose BODY was executing when the capture guard
|
|
322
399
|
* tripped (read off the loader-body ALS scope at trip time), or undefined
|
|
@@ -343,6 +420,21 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
343
420
|
* content used and can therefore be invalidated by updateTag()/revalidateTag().
|
|
344
421
|
*/
|
|
345
422
|
_requestTags: Set<string>;
|
|
423
|
+
/**
|
|
424
|
+
* @internal This request can write a route cache() record: its match
|
|
425
|
+
* resolved a cache scope (match-api.ts). Arms the record tag owners
|
|
426
|
+
* (cache-tag.ts armRecordTagOwners); off, the segment scopes, loader links
|
|
427
|
+
* and owned tag sets are skipped entirely. A capture's or background
|
|
428
|
+
* re-render's derived context (Object.create) inherits it.
|
|
429
|
+
*/
|
|
430
|
+
_recordTagOwners?: true;
|
|
431
|
+
/**
|
|
432
|
+
* @internal This request resolves a loader bound with its own cache()
|
|
433
|
+
* (match-api.ts, or the binding's funnel). Arms the per-execution loader
|
|
434
|
+
* tag sets (cache-tag.ts armLoaderTagSets); off, a loader execution
|
|
435
|
+
* allocates no set and a read links nothing. Derived contexts inherit it.
|
|
436
|
+
*/
|
|
437
|
+
_recordLoaderTags?: true;
|
|
346
438
|
/** @internal Cache profiles for "use cache" profile resolution (per-router) */
|
|
347
439
|
_cacheProfiles?: Record<string, import("../cache/profile-registry.js").CacheProfile>;
|
|
348
440
|
/**
|
|
@@ -383,6 +475,11 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
383
475
|
* Returns the theme value from the cookie, or the default theme if not set.
|
|
384
476
|
* This is the user's preference ("light", "dark", or "system"), not the resolved value.
|
|
385
477
|
*
|
|
478
|
+
* The visitor's cookie, so it is guarded like `cookies()`: reading it
|
|
479
|
+
* refuses a ppr shell capture and throws inside a `cache()` boundary or a
|
|
480
|
+
* `"use cache"` function (#971). A non-enumerable getter: a spread or
|
|
481
|
+
* `Object.assign` copy of the context does not carry it.
|
|
482
|
+
*
|
|
386
483
|
* @example
|
|
387
484
|
* ```typescript
|
|
388
485
|
* route("settings", (ctx) => {
|
|
@@ -391,7 +488,7 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
391
488
|
* });
|
|
392
489
|
* ```
|
|
393
490
|
*/
|
|
394
|
-
theme?: Theme;
|
|
491
|
+
readonly theme?: Theme;
|
|
395
492
|
/**
|
|
396
493
|
* Set the theme (only available when theme is enabled in router config)
|
|
397
494
|
*
|
|
@@ -412,6 +509,14 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
412
509
|
setTheme?: (theme: Theme) => void;
|
|
413
510
|
/** @internal Theme configuration (null if theme not enabled) */
|
|
414
511
|
_themeConfig?: ResolvedThemeConfig | null;
|
|
512
|
+
/**
|
|
513
|
+
* @internal The theme cookie (or the default) read with no identity guard.
|
|
514
|
+
* The guarded reads (`theme` here, the handler and middleware `ctx.theme`)
|
|
515
|
+
* call it after assertThemeReadAllowed; the router's own payload read goes
|
|
516
|
+
* through payloadInitialTheme (rsc/full-payload.ts). Undefined without
|
|
517
|
+
* theme config.
|
|
518
|
+
*/
|
|
519
|
+
_readTheme(): Theme | undefined;
|
|
415
520
|
/**
|
|
416
521
|
* Attach location state entries to the current response.
|
|
417
522
|
*
|
|
@@ -535,6 +640,16 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
535
640
|
_renderBarrierGuardClosed?: boolean;
|
|
536
641
|
/** @internal Per-request error dedup set for onError reporting */
|
|
537
642
|
_reportedErrors: WeakSet<object>;
|
|
643
|
+
/**
|
|
644
|
+
* @internal Errors this response's Flight or Fizz render reported through
|
|
645
|
+
* onError: a component that threw does not fail the stream, which completes
|
|
646
|
+
* with an error row or an errored Suspense boundary. Whole-response captures
|
|
647
|
+
* (document-cache.ts, captureAndStoreShell) store nothing while it is
|
|
648
|
+
* non-empty (issue #915). An array so a render under a derived context (the
|
|
649
|
+
* shell HIT tail) pushes into the request's own list through the prototype;
|
|
650
|
+
* deriveShellCaptureContext gives the capture its own.
|
|
651
|
+
*/
|
|
652
|
+
_renderErrors?: unknown[];
|
|
538
653
|
/**
|
|
539
654
|
* @internal Report a non-fatal background error through the router's
|
|
540
655
|
* onError callback. Wired by the RSC handler / router during request
|
|
@@ -592,13 +707,27 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
592
707
|
*/
|
|
593
708
|
_cacheSignal?: import("../router/telemetry.js").CacheSegmentSignal[];
|
|
594
709
|
}
|
|
710
|
+
/**
|
|
711
|
+
* @internal The freshness window of a route cache() record, as ms
|
|
712
|
+
* timestamps: fresh until `freshUntil` (its `expiresAt`), stale until
|
|
713
|
+
* `staleUntil` (plus its scope's swr). `ttl`, `swr` and `written` describe
|
|
714
|
+
* the record that sets `staleUntil`: its cache() config, and whether this
|
|
715
|
+
* request wrote it (cacheRoute) rather than read it.
|
|
716
|
+
*/
|
|
717
|
+
export interface RouteRecordWindow {
|
|
718
|
+
freshUntil: number;
|
|
719
|
+
staleUntil: number;
|
|
720
|
+
ttl: number;
|
|
721
|
+
swr: number;
|
|
722
|
+
written: boolean;
|
|
723
|
+
}
|
|
595
724
|
/**
|
|
596
725
|
* Public view of RequestContext, without internal methods and fields.
|
|
597
726
|
*
|
|
598
727
|
* This is the type exported to library consumers. Internal code should
|
|
599
728
|
* use the full RequestContext interface directly.
|
|
600
729
|
*/
|
|
601
|
-
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhen" | "_pprTransitionDecisions" | "_pprReplayPostMatchReason" | "_cacheStore" | "_searchParamsFilter" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "
|
|
730
|
+
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhen" | "_pprTransitionDecisions" | "_pprReplayPostMatchReason" | "_cacheStore" | "_searchParamsFilter" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureUnrecordedLoaderPush" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_routeRecordWindow" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_locationState" | "_routeName" | "_prevRouteKey" | "_gateCurrentUrl" | "_gateCurrentParams" | "_gateActionId" | "_gateActionUrl" | "_gateActionResult" | "_gateFormData" | "_inActionRevalidation" | "_reportedErrors" | "_renderErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_tagInvalidations" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
602
731
|
/**
|
|
603
732
|
* Marker for a waitUntil-scheduled fn whose task promise must NOT enter
|
|
604
733
|
* _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
|
|
@@ -20,6 +20,7 @@ interface RenderToReadableStreamOptions {
|
|
|
20
20
|
nonce?: string;
|
|
21
21
|
formState?: unknown;
|
|
22
22
|
progressiveChunkSize?: number;
|
|
23
|
+
onError?: (error: unknown) => void;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
26
|
* ReadableStream with the allReady promise added by react-dom/server.edge.
|
|
@@ -99,6 +100,12 @@ export interface SSRRenderOptions {
|
|
|
99
100
|
* prerender pass (host-agnostic bare captures).
|
|
100
101
|
*/
|
|
101
102
|
origin?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Called for each error Fizz reports through its onError: a component that
|
|
105
|
+
* threw inside a Suspense boundary, which leaves the boundary errored in an
|
|
106
|
+
* otherwise completed document. React's default console.error is kept.
|
|
107
|
+
*/
|
|
108
|
+
onError?: (error: unknown) => void;
|
|
102
109
|
}
|
|
103
110
|
/**
|
|
104
111
|
* SSR dependencies from external packages
|
|
@@ -225,6 +232,21 @@ interface ShellCaptureOptions {
|
|
|
225
232
|
* capture, resume, and browser hydration.
|
|
226
233
|
*/
|
|
227
234
|
origin?: string;
|
|
235
|
+
/**
|
|
236
|
+
* Called for each component error the prerender reports (an errored
|
|
237
|
+
* boundary in the prelude), never for the capture's own abort. The caller
|
|
238
|
+
* refuses to store the shell (issue #915).
|
|
239
|
+
*/
|
|
240
|
+
onError?: (error: unknown) => void;
|
|
241
|
+
/**
|
|
242
|
+
* Called with React's errorInfo for each task still pending when the
|
|
243
|
+
* capture's own abort froze the prelude; its componentStack is computed
|
|
244
|
+
* when read. The dev no-shell warning prints the stacks: one of them is what
|
|
245
|
+
* suspended above <body> (issue #941).
|
|
246
|
+
*/
|
|
247
|
+
onAbortedTask?: (errorInfo: {
|
|
248
|
+
componentStack?: string;
|
|
249
|
+
} | undefined) => void;
|
|
228
250
|
}
|
|
229
251
|
/**
|
|
230
252
|
* Result of a successful shell capture. `prelude` is the raw prelude bytes;
|
|
@@ -253,6 +275,8 @@ interface ShellResumeOptions {
|
|
|
253
275
|
search?: string;
|
|
254
276
|
/** The HIT request's origin — same host as the capture's (key-scoped). */
|
|
255
277
|
origin?: string;
|
|
278
|
+
/** Called for each component error the resumed holes report. */
|
|
279
|
+
onError?: (error: unknown) => void;
|
|
256
280
|
}
|
|
257
281
|
/**
|
|
258
282
|
* Create an SSR handler that converts RSC streams to HTML.
|
|
@@ -54,14 +54,15 @@ export interface SsrRootOptions {
|
|
|
54
54
|
nonce?: string;
|
|
55
55
|
/**
|
|
56
56
|
* Fires once when the Flight payload root settles (resolve OR reject) — the
|
|
57
|
-
* signal that
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* a
|
|
64
|
-
*
|
|
57
|
+
* signal that fizz can start emitting the tree. A client component used as
|
|
58
|
+
* an element type resolves lazily, so its module load can still be in
|
|
59
|
+
* flight (captureShellHTML waits for those separately, issue #949). The
|
|
60
|
+
* capture pass gates its abort on this: a fully REPLAYED (prerendered)
|
|
61
|
+
* route's Flight stream goes byte-quiet in ~1-3ms, but fizz cannot render
|
|
62
|
+
* even <html> until the module loads finish (real module-runner I/O in dev;
|
|
63
|
+
* 100ms+ on a cold graph), so an abort gated on Flight quiet alone fires
|
|
64
|
+
* first and freezes a zero-byte prelude. Masked-loader holes do NOT block
|
|
65
|
+
* this signal — they postpone below the root.
|
|
65
66
|
*/
|
|
66
67
|
onPayloadSettled?: () => void;
|
|
67
68
|
/**
|
|
@@ -21,11 +21,14 @@
|
|
|
21
21
|
* ```ts
|
|
22
22
|
* export const DocsNav = Static((ctx) => <Nav docs={readDocsSync()} />);
|
|
23
23
|
* export const DocShell = Static((ctx) => <Shell />);
|
|
24
|
+
* // Prerender/Static must be exported consts; an inline call inside path()
|
|
25
|
+
* // gets no build-injected $$id and throws.
|
|
26
|
+
* export const DocPage = Prerender(getParams, DocPageHandler);
|
|
24
27
|
*
|
|
25
28
|
* urls(({ path, layout }) => [
|
|
26
29
|
* layout(DocsNav, () => [
|
|
27
30
|
* path("/getting-started", DocShell, { name: "doc.gs" }),
|
|
28
|
-
* path("/:slug",
|
|
31
|
+
* path("/:slug", DocPage),
|
|
29
32
|
* ]),
|
|
30
33
|
* ]);
|
|
31
34
|
* ```
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
* element tree, so you can assert typed prop fidelity across the client boundary
|
|
19
19
|
* (a `Date` comes back a `Date`) and detect inlined-vs-island. Serialize +
|
|
20
20
|
* deserialize only — no hydration/interaction (that is the e2e tier).
|
|
21
|
+
*
|
|
22
|
+
* `serveShellRequest` serves one request through the router's production
|
|
23
|
+
* handler, so a `ppr` route's MISS runs the real shell capture and a later
|
|
24
|
+
* request is a real HIT; only the HTML step is stubbed. `resetShellTestState`
|
|
25
|
+
* clears the per-isolate PPR state between tests.
|
|
21
26
|
*/
|
|
22
27
|
export { renderToFlightString, normalizeFlight, assertFlightRuntimeAvailable, } from "./flight.js";
|
|
23
28
|
export type { RenderToFlightStringOptions } from "./flight.js";
|
|
@@ -25,3 +30,5 @@ export { renderServerTree, findClientBoundaries, findElements, textContent, asse
|
|
|
25
30
|
export type { RenderServerTreeOptions, RenderServerTreeResult, ClientBoundary, BoundarySelector, FoundElement, ElementSelector, } from "./flight-tree.js";
|
|
26
31
|
export { renderHandler } from "./render-handler.js";
|
|
27
32
|
export type { TestableHandler, RenderHandlerOptions, RenderHandlerResult, StateCookieSeed, } from "./render-handler.js";
|
|
33
|
+
export { serveShellRequest, resetShellTestState, } from "./serve-shell-request.js";
|
|
34
|
+
export type { ServeShellRequestOptions, ServeShellRequestResult, } from "./serve-shell-request.js";
|
|
@@ -56,10 +56,10 @@ export declare function diffGeneratedRoutes(router: RouterWithRouteMap, generate
|
|
|
56
56
|
*
|
|
57
57
|
* @example
|
|
58
58
|
* ```ts
|
|
59
|
-
* import
|
|
59
|
+
* import { NamedRoutes } from "./router.named-routes.gen";
|
|
60
60
|
* import { router } from "./router";
|
|
61
61
|
*
|
|
62
|
-
* await assertGeneratedRoutesMatch(router,
|
|
62
|
+
* await assertGeneratedRoutesMatch(router, NamedRoutes);
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
65
65
|
export declare function assertGeneratedRoutesMatch(router: RouterWithRouteMap, generatedMap?: Record<string, unknown>): Promise<void>;
|
|
@@ -205,7 +205,7 @@ export declare function buildRunSnapshot<TEnv>(ctx: RequestContext<TEnv>, thrown
|
|
|
205
205
|
*
|
|
206
206
|
* @example
|
|
207
207
|
* ```ts
|
|
208
|
-
* const {
|
|
208
|
+
* const { cookies, headers, response, thrown } = await runInRequestContext(
|
|
209
209
|
* () => loginAction(input), // sets a session cookie, then `throw redirect("/app")`
|
|
210
210
|
* {
|
|
211
211
|
* env,
|
|
@@ -23,10 +23,13 @@
|
|
|
23
23
|
* SEEDED directly into client context (see the `loaders` / `locationState` /
|
|
24
24
|
* `handles` / `outletPending` options) — nothing is executed on the server.
|
|
25
25
|
* This exercises the context read path, not the run path.
|
|
26
|
-
* - navigate()
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
26
|
+
* - navigate() does NOT drive the navigation lifecycle: useNavigation().state,
|
|
27
|
+
* useLinkStatus().pending, and useAction().state stay "idle". Assert
|
|
28
|
+
* pending/loading/submitting transition states with renderServerTree / e2e
|
|
29
|
+
* instead (navigate() warns once if used). The one pending state it does
|
|
30
|
+
* model is the held-navigation useLoader().isLoading: a `transition` spec
|
|
31
|
+
* plus a pending Promise seeded via navigate(url, { loaders }) commits
|
|
32
|
+
* through production's commitInTransition (browser/partial-update.ts).
|
|
30
33
|
* What it DOES cover: client hooks that read NavigationProvider /
|
|
31
34
|
* OutletContext — useParams, useReverse, useHref, useMount, useNavigation,
|
|
32
35
|
* useRouter, usePathname, useSearchParams, Outlet/useOutlet nesting and seeded
|
|
@@ -42,7 +45,7 @@ import { type ComponentType } from "react";
|
|
|
42
45
|
import type { RenderResult } from "@testing-library/react";
|
|
43
46
|
import type { NavigationStore } from "../browser/types.js";
|
|
44
47
|
import type { EventController } from "../browser/event-controller.js";
|
|
45
|
-
import type { LoaderDefinition } from "../types.js";
|
|
48
|
+
import type { LoaderDefinition, TransitionConfig } from "../types.js";
|
|
46
49
|
import type { LocationStateDefinition } from "../browser/react/location-state-shared.js";
|
|
47
50
|
import type { Handle } from "../handle.js";
|
|
48
51
|
import type { ThemeConfig } from "../theme/types.js";
|
|
@@ -78,6 +81,14 @@ export interface RenderRouteSpec {
|
|
|
78
81
|
loaderIds?: string[];
|
|
79
82
|
/** Optional route name (informational; not used for matching). */
|
|
80
83
|
name?: string;
|
|
84
|
+
/**
|
|
85
|
+
* The `transition()` config this node declares (`{}` for a bare
|
|
86
|
+
* `transition()`), attached to its segment as the DSL does. Puts the chain in
|
|
87
|
+
* a transition scope: param-agnostic keys (segment-system.tsx) and a held
|
|
88
|
+
* navigate() commit, so a pending loader seed passed to
|
|
89
|
+
* `router.navigate(url, { loaders })` pins `useLoader().isLoading`.
|
|
90
|
+
*/
|
|
91
|
+
transition?: TransitionConfig;
|
|
81
92
|
}
|
|
82
93
|
/**
|
|
83
94
|
* Options for renderRoute.
|
|
@@ -247,8 +258,23 @@ export interface TestRouterHandle {
|
|
|
247
258
|
* updates params + location, and re-renders the segment tree. This is a
|
|
248
259
|
* client-only navigation: no server fetch occurs, so only the components in
|
|
249
260
|
* `routes` can be reached.
|
|
261
|
+
*
|
|
262
|
+
* `options.loaders` seeds loader data for THIS navigation, merged over the
|
|
263
|
+
* render-time seeds (the data a real navigation's response would carry). A
|
|
264
|
+
* pending Promise suspends the read like a streaming Flight chunk. When a
|
|
265
|
+
* spec in the chain has `transition`, the commit goes through production's
|
|
266
|
+
* commitInTransition: the reader stays on screen with
|
|
267
|
+
* `useLoader().isLoading === true` until the promise settles. Settle it
|
|
268
|
+
* inside RTL's `act()` to flush the commit. Without `transition` the commit
|
|
269
|
+
* is urgent and the read suspends to the nearest Suspense boundary.
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* await router.navigate("/products/2", { loaders: [[ProductLoader, next]] });
|
|
273
|
+
* // reader: isLoading true, old data
|
|
274
|
+
* await act(async () => resolve({ name: "Product 2" }));
|
|
275
|
+
* // reader: isLoading false, new data
|
|
250
276
|
*/
|
|
251
|
-
navigate(url: string): Promise<void>;
|
|
277
|
+
navigate(url: string, options?: Pick<RenderRouteOptions, "loaders">): Promise<void>;
|
|
252
278
|
/** The current committed pathname. */
|
|
253
279
|
pathname(): string;
|
|
254
280
|
/** The current committed params. */
|
|
@@ -38,6 +38,7 @@ import { type Handle } from "../handle.js";
|
|
|
38
38
|
import type { ThemeConfig } from "../theme/types.js";
|
|
39
39
|
import type { SegmentCacheStore } from "../cache/types.js";
|
|
40
40
|
import type { CacheProfile } from "../cache/profile-registry.js";
|
|
41
|
+
import type { PartialCacheOptions } from "../types/cache-types.js";
|
|
41
42
|
import { type VarsInit, type StateCookieSeed } from "./internal/context.js";
|
|
42
43
|
/**
|
|
43
44
|
* The loader context surfaced to a `runLoader` body. It mirrors the runtime
|
|
@@ -81,9 +82,11 @@ export interface RunLoaderOptions<TEnv = any> {
|
|
|
81
82
|
basename?: string;
|
|
82
83
|
/**
|
|
83
84
|
* Theme config in the same shape `createRouter({ theme })` takes (e.g. `true`
|
|
84
|
-
* or `{ themes: [...] }`). Seeds the request's theme config so
|
|
85
|
-
*
|
|
86
|
-
*
|
|
85
|
+
* or `{ themes: [...] }`). Seeds the request's theme config, so the loader
|
|
86
|
+
* body reads the visitor's theme (the Cookie on `request`, or the default)
|
|
87
|
+
* with `getRequestContext().theme`. That read is guarded like `cookies()`: it
|
|
88
|
+
* throws inside a `"use cache"` function (#971). The loader ctx has no
|
|
89
|
+
* `theme`/`setTheme` (those are handler/middleware-only).
|
|
87
90
|
*/
|
|
88
91
|
theme?: ThemeConfig | true;
|
|
89
92
|
/** Environment bindings surfaced as `ctx.env`. */
|
|
@@ -121,6 +124,18 @@ export interface RunLoaderOptions<TEnv = any> {
|
|
|
121
124
|
cacheStore?: SegmentCacheStore;
|
|
122
125
|
/** Cache profiles (the `createRouter({ cacheProfiles })` shape). */
|
|
123
126
|
cacheProfiles?: Record<string, CacheProfile>;
|
|
127
|
+
/**
|
|
128
|
+
* Run the loader through the `cache()` a route binds it with — the options
|
|
129
|
+
* `loader(Loader, () => [cache({...})])` takes — using the production
|
|
130
|
+
* read-through against `cache.store`, else `cacheStore`. A HIT returns the
|
|
131
|
+
* stored value without running the body and records the tags the body
|
|
132
|
+
* recorded when the entry was written, so `updateTag()` of any of them drops
|
|
133
|
+
* the entry. The write is a background task the call does not await (spy
|
|
134
|
+
* on the store's `setItem` to wait for it). A raw loader body is keyed by
|
|
135
|
+
* its function reference. `handlePushes` lists the body's pushes, so a HIT
|
|
136
|
+
* reports none: the replay into the page's handle store is not modeled.
|
|
137
|
+
*/
|
|
138
|
+
cache?: PartialCacheOptions;
|
|
124
139
|
/**
|
|
125
140
|
* Customize the rango state cookie a loader that calls
|
|
126
141
|
* `invalidateClientCache()` rotates (the name is always seeded — default
|