@rangojs/router 0.18.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/dist/types/browser/event-controller.d.ts +3 -3
- package/dist/types/browser/history-state.d.ts +2 -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 +44 -13
- package/dist/types/cache/cache-policy.d.ts +1 -1
- package/dist/types/cache/cache-runtime.d.ts +7 -0
- package/dist/types/cache/cache-scope.d.ts +117 -35
- package/dist/types/cache/cache-tag.d.ts +24 -4
- package/dist/types/cache/cf/cf-cache-store.d.ts +55 -44
- package/dist/types/cache/cf/cf-shell-frame.d.ts +1 -1
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +0 -15
- package/dist/types/cache/document-cache.d.ts +10 -0
- package/dist/types/cache/handle-snapshot.d.ts +40 -8
- package/dist/types/cache/invalidation-order.d.ts +23 -0
- package/dist/types/cache/request-tag-mask.d.ts +54 -0
- package/dist/types/cache/shell-snapshot.d.ts +88 -141
- package/dist/types/cache/tag-invalidation.d.ts +38 -14
- package/dist/types/cache/types.d.ts +68 -61
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +23 -16
- 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/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/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/router-options.d.ts +4 -1
- package/dist/types/router/segment-resolution/loader-cache.d.ts +18 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -4
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +14 -40
- package/dist/types/router/segment-resolution/mask-nested.d.ts +11 -3
- 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 +14 -7
- package/dist/types/rsc/response-cache-serve.d.ts +15 -12
- package/dist/types/rsc/shell-build-manifest.d.ts +4 -3
- package/dist/types/rsc/shell-capture-constants.d.ts +77 -20
- package/dist/types/rsc/shell-capture.d.ts +78 -81
- package/dist/types/rsc/shell-serve.d.ts +19 -48
- package/dist/types/rsc/types.d.ts +2 -0
- package/dist/types/segment-system.d.ts +7 -0
- package/dist/types/server/context.d.ts +89 -61
- package/dist/types/server/cookie-store.d.ts +30 -18
- package/dist/types/server/handle-store.d.ts +52 -1
- package/dist/types/server/request-context.d.ts +66 -45
- package/dist/types/server/request-headers.d.ts +44 -0
- package/dist/types/server.d.ts +1 -0
- package/dist/types/testing/e2e/index.d.ts +1 -1
- 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-transition-when.d.ts +44 -69
- package/dist/types/testing/serve-shell-request.d.ts +7 -6
- package/dist/types/testing/shell-status.d.ts +34 -22
- package/dist/types/transition-when-ref.d.ts +79 -0
- package/dist/types/types/cache-types.d.ts +15 -3
- 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 +3 -4
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +45 -0
- package/dist/vite/index.js +960 -97
- package/package.json +1 -1
- package/skills/cache-guide/SKILL.md +76 -49
- package/skills/caching/SKILL.md +167 -69
- package/skills/client-urls/SKILL.md +1 -1
- package/skills/comparison/references/framework-comparison.md +8 -5
- package/skills/document-cache/SKILL.md +24 -0
- package/skills/hooks/SKILL.md +3 -1
- package/skills/hooks/navigation.md +23 -2
- package/skills/hooks/state.md +98 -6
- package/skills/intercept/SKILL.md +29 -12
- package/skills/loader/SKILL.md +52 -21
- package/skills/middleware/SKILL.md +18 -0
- package/skills/migrate-nextjs/SKILL.md +3 -3
- package/skills/observability/SKILL.md +6 -5
- package/skills/parallel/SKILL.md +1 -1
- package/skills/ppr/SKILL.md +129 -77
- package/skills/prerender/SKILL.md +3 -3
- package/skills/rango/SKILL.md +25 -6
- package/skills/route/SKILL.md +2 -0
- package/skills/testing/SKILL.md +27 -25
- package/skills/testing/cache-prerender.md +9 -9
- package/skills/testing/client-components.md +45 -3
- package/skills/testing/loader.md +3 -2
- 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 +14 -0
- package/skills/testing/server-actions.md +9 -3
- package/skills/theme/SKILL.md +8 -4
- package/skills/typesafety/env-and-bindings.md +8 -0
- package/skills/use-cache/SKILL.md +64 -19
- package/skills/view-transitions/SKILL.md +150 -29
- package/src/__augment-tests__/augmented.check.ts +23 -0
- package/src/browser/event-controller.ts +4 -4
- package/src/browser/history-state.ts +52 -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 +4 -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 +56 -16
- package/src/cache/cache-policy.ts +9 -4
- package/src/cache/cache-runtime.ts +197 -144
- package/src/cache/cache-scope.ts +304 -112
- package/src/cache/cache-tag.ts +105 -13
- package/src/cache/cf/cf-cache-store.ts +152 -76
- package/src/cache/cf/cf-shell-frame.ts +2 -2
- package/src/cache/cf/cf-tag-marker-memo.ts +11 -100
- package/src/cache/document-cache.ts +53 -7
- package/src/cache/handle-snapshot.ts +52 -9
- package/src/cache/invalidation-order.ts +84 -0
- package/src/cache/request-tag-mask.ts +147 -0
- package/src/cache/shell-snapshot.ts +130 -348
- package/src/cache/tag-invalidation.ts +57 -51
- package/src/cache/types.ts +71 -67
- package/src/cache/vercel/vercel-cache-store.ts +61 -58
- 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 +155 -146
- package/src/route-definition/dsl-helpers.ts +2 -0
- 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 +10 -7
- package/src/router/intercept-resolution.ts +11 -1
- package/src/router/loader-resolution.ts +28 -3
- package/src/router/logging.ts +5 -3
- package/src/router/match-api.ts +62 -34
- package/src/router/match-context.ts +5 -0
- package/src/router/match-handlers.ts +9 -29
- package/src/router/match-middleware/background-revalidation.ts +3 -5
- package/src/router/match-middleware/cache-lookup.ts +35 -19
- package/src/router/match-middleware/cache-store.ts +15 -9
- package/src/router/match-result.ts +1 -0
- package/src/router/middleware.ts +2 -5
- package/src/router/navigation-snapshot.ts +6 -5
- package/src/router/prerender-match.ts +4 -0
- package/src/router/request-classification.ts +7 -4
- package/src/router/router-options.ts +4 -1
- package/src/router/segment-resolution/fresh.ts +0 -4
- package/src/router/segment-resolution/loader-cache.ts +150 -25
- package/src/router/segment-resolution/loader-mask.ts +3 -4
- package/src/router/segment-resolution/loader-snapshot.ts +15 -78
- package/src/router/segment-resolution/mask-nested.ts +47 -22
- package/src/router/segment-resolution/revalidation.ts +0 -3
- 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 +30 -10
- package/src/rsc/handler.ts +12 -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 +7 -30
- package/src/rsc/response-cache-serve.ts +68 -80
- package/src/rsc/response-route-handler.ts +2 -2
- package/src/rsc/rsc-rendering.ts +206 -252
- package/src/rsc/server-action.ts +8 -20
- package/src/rsc/shell-build-manifest.ts +22 -20
- package/src/rsc/shell-capture-constants.ts +136 -20
- package/src/rsc/shell-capture.ts +352 -589
- package/src/rsc/shell-serve.ts +73 -109
- package/src/rsc/ssr-setup.ts +3 -2
- package/src/rsc/types.ts +2 -0
- package/src/segment-system.tsx +40 -7
- package/src/server/context.ts +189 -124
- package/src/server/cookie-store.ts +153 -127
- package/src/server/handle-store.ts +245 -27
- package/src/server/request-context.ts +123 -84
- package/src/server/request-headers.ts +134 -0
- package/src/server.ts +4 -0
- package/src/testing/dispatch.ts +4 -7
- package/src/testing/e2e/index.ts +1 -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 +5 -1
- package/src/testing/run-transition-when.ts +109 -172
- package/src/testing/serve-shell-request.ts +10 -7
- package/src/testing/shell-status.ts +60 -56
- package/src/transition-when-ref.ts +220 -0
- package/src/types/cache-types.ts +15 -3
- 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 +3 -4
- package/src/vite/discovery/discover-routers.ts +3 -0
- package/src/vite/discovery/shell-prerender-phase.ts +0 -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 +75 -5
- package/dist/types/rsc/transition-gate.d.ts +0 -23
- package/src/rsc/transition-gate.ts +0 -86
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { ServerRouteLocation } from "../types/segments.js";
|
|
1
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
3
|
import type { ReactNode } from "react";
|
|
3
4
|
import type { PartialCacheOptions, ErrorBoundaryHandler, Handler, LoaderDefinition, MiddlewareFn, NotFoundBoundaryHandler, ShouldRevalidateFn, TransitionConfig } from "../types";
|
|
4
|
-
import type { DefaultRouteName } from "../types/global-namespace.js";
|
|
5
5
|
import type { ContextVar } from "../context-var.js";
|
|
6
6
|
/**
|
|
7
7
|
* Performance metric entry for a single measured operation
|
|
@@ -132,20 +132,22 @@ export type InterceptSegmentsState = {
|
|
|
132
132
|
* Context passed to intercept selector functions (when())
|
|
133
133
|
* Contains navigation context to determine if interception should occur.
|
|
134
134
|
*
|
|
135
|
+
* `from` / `to` have the shape transition({ when }) sees, without `state`:
|
|
136
|
+
* history state never reaches the server.
|
|
137
|
+
*
|
|
135
138
|
* Note: when() is evaluated during route matching, BEFORE middleware runs.
|
|
136
139
|
* So ctx.get()/ctx.use() are not available, but env (platform bindings) is.
|
|
137
140
|
*
|
|
138
141
|
* @internal This type is an implementation detail and may change without notice.
|
|
139
142
|
*/
|
|
140
143
|
export type InterceptSelectorContext<TEnv = any> = {
|
|
141
|
-
from:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
/** Where the navigation comes from: the intercept source while one is open. */
|
|
145
|
+
from: ServerRouteLocation;
|
|
146
|
+
/** The navigation target. */
|
|
147
|
+
to: ServerRouteLocation;
|
|
144
148
|
request: Request;
|
|
145
149
|
env: TEnv;
|
|
146
150
|
segments: InterceptSegmentsState;
|
|
147
|
-
fromRouteName?: DefaultRouteName;
|
|
148
|
-
toRouteName?: DefaultRouteName;
|
|
149
151
|
};
|
|
150
152
|
/**
|
|
151
153
|
* Selector function for conditional interception
|
|
@@ -423,65 +425,82 @@ export declare function track(label: string, depth?: number): () => void;
|
|
|
423
425
|
*/
|
|
424
426
|
export declare function isInsideCacheScope(): boolean;
|
|
425
427
|
/**
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
* the
|
|
430
|
-
*
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
428
|
+
* What a refused identity read says (guardIdentityRead): its `verb`, and per
|
|
429
|
+
* refusing scope the text after "<surface> cannot be <verb> ...": why the
|
|
430
|
+
* value must not reach that scope, and what to do instead. `fix.warning` is
|
|
431
|
+
* the fix the capture's refusal warning gives (shell-capture.ts
|
|
432
|
+
* refuseOnCaptureGuard).
|
|
433
|
+
*/
|
|
434
|
+
export interface IdentityReadWording {
|
|
435
|
+
/** "called" for a function (cookies(), ctx.get()), "read" for a property (the theme getters). */
|
|
436
|
+
verb: LoaderIdentityReadVerb;
|
|
437
|
+
fix: {
|
|
438
|
+
useCache: string;
|
|
439
|
+
cacheScope: string;
|
|
440
|
+
capture: string;
|
|
441
|
+
warning: string;
|
|
442
|
+
};
|
|
443
|
+
/**
|
|
444
|
+
* False when the read is recorded later, by the returned view's read
|
|
445
|
+
* methods (cookies(), headers()): a view taken outside a loader and read
|
|
446
|
+
* inside one still counts, and a cookie write alone is not a read.
|
|
447
|
+
*/
|
|
448
|
+
record?: false;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* The one guard every request-identity read goes through: cookies(),
|
|
452
|
+
* headers(), the theme reads (cookie-store.ts readGuardedTheme), a
|
|
453
|
+
* non-cacheable ctx.get() (assertNonCacheableReadAllowed), and the raw reads
|
|
454
|
+
* `ctx.request.headers` and `getRequestContext().cookie()` / `.cookies()`
|
|
455
|
+
* (cookie-store.ts guardRequestHeaders, guardRawCookieRead; #976). Each surface keeps
|
|
456
|
+
* its own wording; the ladder and its exemptions are shared, so the surfaces
|
|
457
|
+
* refuse in exactly the same places:
|
|
449
458
|
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
* they
|
|
455
|
-
*
|
|
459
|
+
* 0. A cache's own key(), store keyGenerator, condition() and tags(), and
|
|
460
|
+
* onError, read freely and record nothing (runIdentityExempt,
|
|
461
|
+
* cache/cache-exec-scope.ts): the value picks or labels the entry, or is
|
|
462
|
+
* only observed; it is never rendered. A cached body, loader body or
|
|
463
|
+
* funnel they start is guarded again.
|
|
464
|
+
* 1. A PPR shell capture (`ctx` is the capture's derived context,
|
|
465
|
+
* `_shellCaptureRun`) trips first: the capture context is flagged (so a
|
|
466
|
+
* caught throw still refuses the capture) and the read throws. The shell is
|
|
467
|
+
* shared per host+URL, and every HIT replays what the capture read. There
|
|
468
|
+
* is no loader-body exemption here: a bake-lane loader and a loader a
|
|
469
|
+
* handler awaits both bake.
|
|
470
|
+
* 2. A "use cache" body throws: the key does not include the value, so the
|
|
471
|
+
* first caller's would be stored and served to later callers. That holds
|
|
472
|
+
* for a loader body entered inside the cached function too (`await
|
|
473
|
+
* ctx.use(Loader)` there): its value is part of what the function returns.
|
|
474
|
+
* Before, a non-cacheable ctx.get() there was exempt while cookies() threw,
|
|
475
|
+
* and the entry stored the first request's value.
|
|
476
|
+
* 3. A cache() boundary throws, except inside a loader body
|
|
477
|
+
* (isInsideCacheScope): a route cache() never stores loader values.
|
|
478
|
+
* 4. The read is allowed, and recorded on the current loader execution for a
|
|
479
|
+
* loader cache() fill without key() (#972, recordLoaderIdentityRead)
|
|
480
|
+
* unless `wording.record` defers it to the returned view.
|
|
456
481
|
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
|
|
482
|
+
* Outside these scopes every read is allowed, a live loader's included. The
|
|
483
|
+
* response directives (invalidateClientCache(), keepClientCache()) record
|
|
484
|
+
* nothing and are not captured reads: they take refuseInCacheScope alone.
|
|
485
|
+
*/
|
|
486
|
+
export declare function guardIdentityRead(ctx: unknown, surface: string, wording: IdentityReadWording): void;
|
|
487
|
+
/**
|
|
488
|
+
* Steps 2 and 3 of guardIdentityRead: throw when a "use cache" body or a
|
|
489
|
+
* cache() boundary would store what `surface` produces.
|
|
461
490
|
*/
|
|
462
|
-
export declare function
|
|
491
|
+
export declare function refuseInCacheScope(surface: string, { verb, fix }: IdentityReadWording): void;
|
|
463
492
|
/**
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
467
|
-
* the loader body (if any) that made the read, and the caller throws.
|
|
493
|
+
* The capture refusal for a request-scoped read (cookies(), headers(), a
|
|
494
|
+
* { cache: false } variable): the message after the surface, and the fix the
|
|
495
|
+
* refusal warning gives. `what` names the data that would leak.
|
|
468
496
|
*/
|
|
469
|
-
export declare function
|
|
497
|
+
export declare function requestReadCaptureFix(what: string): Pick<IdentityReadWording["fix"], "capture" | "warning">;
|
|
470
498
|
/**
|
|
471
499
|
* Read guard for a non-cacheable variable (`createVar({ cache: false })` or a
|
|
472
|
-
* `ctx.set(..., { cache: false })` write)
|
|
473
|
-
* so ordinary reads never reach the
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
* context; assertNotInsideShellCapture): the shell is shared per host+URL.
|
|
477
|
-
*
|
|
478
|
-
* Throws inside a "use cache" body: the key does not include the value, so the
|
|
479
|
-
* first caller's value would be stored and served to later callers (#925). A
|
|
480
|
-
* loader body entered INSIDE the cached function is exempt, the same baked-copy
|
|
481
|
-
* trade isInsideCacheScope() makes for cache(). A cached function called FROM a
|
|
482
|
-
* loader is not: the loader re-runs, the cached body does not. The body scope
|
|
483
|
-
* records the exec scope it was entered in, so the exemption holds only while
|
|
484
|
-
* that is still the innermost one.
|
|
500
|
+
* `ctx.set(..., { cache: false })` write), through guardIdentityRead.
|
|
501
|
+
* Callers check isNonCacheable() first so ordinary reads never reach the
|
|
502
|
+
* scope lookups. `requestCtx` is the ambient request context, whose capture
|
|
503
|
+
* flag the guard reads.
|
|
485
504
|
*/
|
|
486
505
|
export declare function assertNonCacheableReadAllowed(keyOrVar: string | ContextVar<unknown>, requestCtx?: unknown): void;
|
|
487
506
|
/** How the identity error words a read: a function call or a property read. */
|
|
@@ -608,10 +627,12 @@ export declare function assertCachedHeaderWriteAllowed(surface: string, surfaceP
|
|
|
608
627
|
export declare function runInsideLoaderScope<T>(fn: () => T): T;
|
|
609
628
|
/**
|
|
610
629
|
* Run `fn` inside a loader BODY scope. Marks loader-function execution for the
|
|
611
|
-
* cache
|
|
630
|
+
* cache() purity guard only (isInsideCacheScope), WITHOUT affecting
|
|
612
631
|
* isInsideLoaderScope()/rendered() gating. Applied to every loader body (DSL
|
|
613
632
|
* and handler-invoked via ctx.use) so request-scoped reads inside a loader
|
|
614
|
-
* never trip the cache
|
|
633
|
+
* never trip the cache() guard — a route cache() never stores loader values.
|
|
634
|
+
* A "use cache" body the loader was entered in still refuses them
|
|
635
|
+
* (guardIdentityRead).
|
|
615
636
|
*/
|
|
616
637
|
export declare function runInsideLoaderBodyScope<T>(fn: () => T, loaderId?: string, tags?: Set<string>): T;
|
|
617
638
|
/** The innermost loader body's execution tag set (runInsideLoaderBodyScope). */
|
|
@@ -619,12 +640,19 @@ export declare function getLoaderBodyTags(): Set<string> | undefined;
|
|
|
619
640
|
/**
|
|
620
641
|
* The $$id of the loader whose body is currently executing, or undefined
|
|
621
642
|
* outside any loader body. Used by the shell-capture identity guard
|
|
622
|
-
* (
|
|
643
|
+
* (guardIdentityRead) so its refusal warning can name the loader that read
|
|
623
644
|
* cookies()/headers() instead of blaming a lane it cannot see — the old
|
|
624
645
|
* hardcoded "bake-lane loader" text misled a live-lane debugging session
|
|
625
646
|
* (issue #672, secondary).
|
|
626
647
|
*/
|
|
627
648
|
export declare function getCurrentLoaderBodyId(): string | undefined;
|
|
649
|
+
/**
|
|
650
|
+
* The innermost loader body running here, or around it through the
|
|
651
|
+
* ctx.use(Loader) chain, whose id `match` accepts (HandleStore.push, the
|
|
652
|
+
* shell capture's push funnel). A body `stop` accepts, and `match` does not,
|
|
653
|
+
* ends the walk: nothing around it is returned.
|
|
654
|
+
*/
|
|
655
|
+
export declare function findEnclosingLoaderBody(match: (loaderId: string) => boolean, stop?: (loaderId: string) => boolean): string | undefined;
|
|
628
656
|
/**
|
|
629
657
|
* True while `loaderId`'s body, or a loader it awaits via ctx.use at any
|
|
630
658
|
* depth, is executing. The loader-level cache records these pushes
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* Writes append Set-Cookie to the response stub.
|
|
8
8
|
*/
|
|
9
9
|
import type { CookieOptions } from "../router/middleware-types.js";
|
|
10
|
+
import type { Theme } from "../theme/types.js";
|
|
11
|
+
import { type RequestContext } from "./request-context.js";
|
|
10
12
|
/**
|
|
11
13
|
* A single cookie entry returned by get() and getAll().
|
|
12
14
|
*/
|
|
@@ -63,27 +65,37 @@ export interface ReadonlyHeaders {
|
|
|
63
65
|
[Symbol.iterator](): HeadersIterator<[string, string]>;
|
|
64
66
|
}
|
|
65
67
|
type HeadersIterator<T> = IterableIterator<T>;
|
|
66
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Run the identity guard for a raw cookie read on `ctx`
|
|
70
|
+
* (request-context.ts `cookie()` / `cookies()`). Before #976 they were plain
|
|
71
|
+
* reads of the Cookie header that no shared scope refused. The guard reads
|
|
72
|
+
* the ambient context, as cookies() does, and falls back to `ctx`.
|
|
73
|
+
*/
|
|
74
|
+
export declare function guardRawCookieRead(ctx: RequestContext<any>, surface: "getRequestContext().cookie()" | "getRequestContext().cookies()"): void;
|
|
75
|
+
/**
|
|
76
|
+
* Guard `request.headers` like headers() (#976): the request every ctx
|
|
77
|
+
* exposes (request context, handler, middleware and loader `ctx.request`)
|
|
78
|
+
* gets an own getter that runs guardIdentityRead against the ambient request
|
|
79
|
+
* context, so a read inside a ppr capture, a cache() boundary, a "use cache"
|
|
80
|
+
* body or an unkeyed loader cache() fill refuses as cookies() does. A Request
|
|
81
|
+
* argument keys a "use cache" entry by its URL only (cache-runtime.ts), so a
|
|
82
|
+
* header read there baked the first caller's value into the shared entry.
|
|
83
|
+
* The router's own reads go through requestHeaders() (request-headers.ts).
|
|
84
|
+
* Idempotent; returns `request`.
|
|
85
|
+
*/
|
|
86
|
+
export declare function guardRequestHeaders(request: Request): Request;
|
|
87
|
+
/** The public reads of the visitor's theme cookie that readGuardedTheme guards. */
|
|
67
88
|
export type ThemeReadSurface = "ctx.theme" | "getRequestContext().theme";
|
|
68
89
|
/**
|
|
69
|
-
*
|
|
70
|
-
* `ctx.theme
|
|
71
|
-
* (request-context.ts). The
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* entry or a "use cache" entry stored the first visitor's theme and served it
|
|
77
|
-
* to every later visitor.
|
|
78
|
-
*
|
|
79
|
-
* A read the guards allow is recorded on the current loader execution, as a
|
|
80
|
-
* cookies() read method records it (#972, recordLoaderIdentityRead).
|
|
81
|
-
*
|
|
82
|
-
* `ctx` is the request context at read time, as cookies() reads it. The
|
|
83
|
-
* router's own payload read (payloadInitialTheme, rsc/full-payload.ts) goes
|
|
84
|
-
* through the unguarded `_readTheme()`.
|
|
90
|
+
* `ctx`'s theme through guardIdentityRead: the one body of every public theme
|
|
91
|
+
* read (the handler and middleware `ctx.theme`, handler-context.ts and
|
|
92
|
+
* middleware.ts, and `getRequestContext().theme`, request-context.ts). The
|
|
93
|
+
* guard reads the ambient context, as cookies() does, and falls back to
|
|
94
|
+
* `ctx`; the value is `ctx`'s unguarded `_readTheme()`, which the router's
|
|
95
|
+
* own payload read (payloadInitialTheme, rsc/full-payload.ts) calls directly.
|
|
96
|
+
* Undefined without a theme config.
|
|
85
97
|
*/
|
|
86
|
-
export declare function
|
|
98
|
+
export declare function readGuardedTheme(ctx: RequestContext<any> | undefined, surface: ThemeReadSurface): Theme | undefined;
|
|
87
99
|
/**
|
|
88
100
|
* Get the original request headers (read-only).
|
|
89
101
|
*
|
|
@@ -85,9 +85,60 @@ export interface HandleStore {
|
|
|
85
85
|
* body (loader-cache.ts replayLoaderHandles). If that loader then runs live
|
|
86
86
|
* in this request, its first push removes every value replayed for it and
|
|
87
87
|
* takes the first one's position (later live pushes follow it), so the
|
|
88
|
-
* handle output stays live without a duplicate.
|
|
88
|
+
* handle output stays live without a duplicate. A push counts as that
|
|
89
|
+
* loader's when it is made in its body, or in a body it entered that has
|
|
90
|
+
* no replayed values of its own (the capture credits a dependency's push
|
|
91
|
+
* under a live-lane loader to that loader); a hole's run that ends without
|
|
92
|
+
* one drops them (settleLoaderRun).
|
|
89
93
|
*/
|
|
90
94
|
pushReplayed(handleName: string, segmentId: string, data: unknown, loaderId: string): void;
|
|
95
|
+
/**
|
|
96
|
+
* push() a document HIT's copy of `loaderId`'s settled push, restored from
|
|
97
|
+
* the shell's doc record (handle-snapshot.ts restoreHandles). The record is
|
|
98
|
+
* authoritative for that loader's settled pushes: the prelude was rendered
|
|
99
|
+
* from it, and a run of the loader on the HIT reads the store, not the
|
|
100
|
+
* capture's values. So from then on this request drops every settled,
|
|
101
|
+
* thenable-free push the loader makes (live, or replayed from a cache
|
|
102
|
+
* entry, anywhere inside its body), and keeps the ones holding a thenable
|
|
103
|
+
* (holdsThenable: what the record could not keep, `runs`), placed among the
|
|
104
|
+
* restored copies in the loader's push order. Only bake-lane owners are
|
|
105
|
+
* restored this way (withCacheLookup): a live-lane loader is a hole.
|
|
106
|
+
*/
|
|
107
|
+
pushRestored(handleName: string, segmentId: string, data: unknown, loaderId: string): void;
|
|
108
|
+
/**
|
|
109
|
+
* The loaders the route runs on the live lane (liveLaneLoaderIds), from a
|
|
110
|
+
* PPR shell record's restore (handle-snapshot.ts restoreHandles): the
|
|
111
|
+
* holes. A push counts for a restored loader when that loader is the
|
|
112
|
+
* replayed one or the innermost enclosing loader body that restored
|
|
113
|
+
* copies; the walk out through enclosing bodies stops at a hole's body,
|
|
114
|
+
* and a replay of a hole's push counts for none. So a restored loader
|
|
115
|
+
* never takes a push made inside a hole it awaited, while a body inside the
|
|
116
|
+
* hole that restored copies of its own (a dependency the capture ran under
|
|
117
|
+
* a bake-lane loader) still takes its pushes.
|
|
118
|
+
*/
|
|
119
|
+
markLiveLane(loaderIds: ReadonlySet<string>): void;
|
|
120
|
+
/**
|
|
121
|
+
* `loaderId`'s run in this request settled (resolved or rejected), its
|
|
122
|
+
* pushes made (loader-resolution.ts createLoaderExecutor). When the loader
|
|
123
|
+
* is a hole (markLiveLane), values replayed for it that no push of the run
|
|
124
|
+
* replaced are dropped: the run's output decides, so a hole that throws or
|
|
125
|
+
* skips its push shows none rather than the capture's. Any other loader's
|
|
126
|
+
* replayed values stay: a bake-lane loader's record is authoritative for
|
|
127
|
+
* its settled pushes, as its pin is for its data. Restored copies are not
|
|
128
|
+
* replays and stand.
|
|
129
|
+
*/
|
|
130
|
+
settleLoaderRun(loaderId: string): void;
|
|
131
|
+
/**
|
|
132
|
+
* A hole's own cache() HIT (loader-cache.ts replayLoaderHandles, once it
|
|
133
|
+
* claims the hole): the values replayed for hole `loaderId` before (its
|
|
134
|
+
* shell copies, which restoreHandles leaves unclaimed, those of the
|
|
135
|
+
* dependencies credited to it included) give way to the pushes the entry
|
|
136
|
+
* recorded, none when it recorded none, so they match the entry's data.
|
|
137
|
+
* `deliver` makes the pushReplayed calls, which take the removed values'
|
|
138
|
+
* place in each array. Any other loader, or a hole with nothing replayed,
|
|
139
|
+
* delivers as a plain replay.
|
|
140
|
+
*/
|
|
141
|
+
redeliverReplays(loaderId: string, deliver: () => void): void;
|
|
91
142
|
/**
|
|
92
143
|
* Get all collected handle data after all handlers have settled.
|
|
93
144
|
* Waits for `settled` (handler lane), then returns the data at that point.
|
|
@@ -22,11 +22,12 @@ import { type MetricsStore } from "./context.js";
|
|
|
22
22
|
import type { SegmentCacheStore } from "../cache/types.js";
|
|
23
23
|
import type { Theme, ResolvedThemeConfig } from "../theme/types.js";
|
|
24
24
|
import type { ExecutionContext, RequestScope } from "../types/request-scope.js";
|
|
25
|
-
import type {
|
|
25
|
+
import type { TransitionWhenRecord } from "../router/transition-when.js";
|
|
26
26
|
import type { ResolvedTracing } from "../router/tracing.js";
|
|
27
27
|
import type { RenderMode, RenderPhase } from "../router/timeout.js";
|
|
28
28
|
import type { LocationStateEntry } from "../browser/react/location-state-shared.js";
|
|
29
29
|
import type { RoutineTrace } from "../rsc/routine-plan.js";
|
|
30
|
+
import { type ExecutionStart } from "../cache/invalidation-order.js";
|
|
30
31
|
export interface RenderForegroundCursor {
|
|
31
32
|
mode: RenderMode;
|
|
32
33
|
phase: RenderPhase;
|
|
@@ -86,10 +87,24 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
86
87
|
dynamic(): void;
|
|
87
88
|
/** @internal Request-local PPR opt-out marker set by ctx.dynamic(). */
|
|
88
89
|
_dynamic?: boolean;
|
|
89
|
-
/**
|
|
90
|
+
/**
|
|
91
|
+
* @internal Get a cookie value (effective: request + response mutations).
|
|
92
|
+
* Use cookies().get() instead. Guarded like cookies() (#976).
|
|
93
|
+
*/
|
|
90
94
|
cookie(name: string): string | undefined;
|
|
91
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* @internal Get all cookies (effective merged view). Use
|
|
97
|
+
* cookies().getAll() instead. Guarded like cookies() (#976).
|
|
98
|
+
*/
|
|
92
99
|
cookies(): Record<string, string>;
|
|
100
|
+
/**
|
|
101
|
+
* @internal `cookie()` without the identity guard: the read behind the
|
|
102
|
+
* cookies() store, which guards at its own call and records per read
|
|
103
|
+
* method. Non-enumerable, like `_readTheme`.
|
|
104
|
+
*/
|
|
105
|
+
_readCookie(name: string): string | undefined;
|
|
106
|
+
/** @internal `cookies()` without the identity guard (see `_readCookie`). */
|
|
107
|
+
_readCookies(): Record<string, string>;
|
|
93
108
|
/** @internal Set a cookie on the response. Use cookies().set() instead. */
|
|
94
109
|
setCookie(name: string, value: string, options?: CookieOptions): void;
|
|
95
110
|
/** @internal Delete a cookie. Use cookies().delete() instead. */
|
|
@@ -119,19 +134,18 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
119
134
|
/**
|
|
120
135
|
* @internal The context createRequestContext() returned. A context derived
|
|
121
136
|
* 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
|
-
*
|
|
124
|
-
*
|
|
137
|
+
* revalidation render) inherits it, so per-request invalidation state (the
|
|
138
|
+
* stores' masks) is keyed by the request, not by whichever derived object
|
|
139
|
+
* called or read (#973).
|
|
125
140
|
*/
|
|
126
141
|
_requestRoot?: RequestContext<any, any>;
|
|
127
142
|
/**
|
|
128
|
-
* @internal
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* invalidated is neither joined nor written (cache-runtime.ts, #973).
|
|
143
|
+
* @internal Where the request started in the isolate's invalidation order
|
|
144
|
+
* (cache/invalidation-order.ts), taken when createRequestContext() ran. The
|
|
145
|
+
* document cache gates its write on it (#977): a middleware ahead of the
|
|
146
|
+
* document cache can read tagged data the document bakes.
|
|
133
147
|
*/
|
|
134
|
-
|
|
148
|
+
_requestStart?: ExecutionStart;
|
|
135
149
|
/**
|
|
136
150
|
* @internal The handler has handed the response to the host (rsc/handler.ts
|
|
137
151
|
* `rango.response`): header and cookie writes after this are lost, as from
|
|
@@ -171,18 +185,13 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
171
185
|
*/
|
|
172
186
|
readonly _handleStore: HandleStore;
|
|
173
187
|
/**
|
|
174
|
-
* @internal transition({ when })
|
|
175
|
-
* keyed by segment id.
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
188
|
+
* @internal transition({ when }) client references of the matched entry
|
|
189
|
+
* chain, keyed by segment id. Recorded at match time from the static route
|
|
190
|
+
* definition (router/transition-when.ts) and attached to the payload's
|
|
191
|
+
* segments right before Flight (rsc/attach-transition-when.ts). The server
|
|
192
|
+
* never calls them, and no cache or snapshot stores them.
|
|
179
193
|
*/
|
|
180
|
-
|
|
181
|
-
id: string;
|
|
182
|
-
when: TransitionWhenFn;
|
|
183
|
-
}>;
|
|
184
|
-
/** @internal PPR transition decisions evaluated before cache lookup/handlers. */
|
|
185
|
-
_pprTransitionDecisions?: Map<string, boolean>;
|
|
194
|
+
_transitionWhenRefs?: ReadonlyMap<string, TransitionWhenRecord>;
|
|
186
195
|
/**
|
|
187
196
|
* @internal Post-match serve-source truth for the PPR replay reporter.
|
|
188
197
|
* Stamped from the match context as `intercept`, then overwritten as
|
|
@@ -206,8 +215,8 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
206
215
|
* capture task's derived request context (built by shell-capture.ts). This is
|
|
207
216
|
* the switch every capture-specific behavior reads: loader masking
|
|
208
217
|
* (loader-mask.ts isShellCaptureActive / fresh.ts emitStreaming) and the
|
|
209
|
-
*
|
|
210
|
-
*
|
|
218
|
+
* identity-read capture guard (server/context.ts guardIdentityRead). The
|
|
219
|
+
* foreground render never sets it, so the
|
|
211
220
|
* served response is byte-identical to axis 1. The capture descriptor itself
|
|
212
221
|
* (key/ttl/swr/tags/store) is NOT threaded through the request context — the
|
|
213
222
|
* integrated PPR serve path (rsc/shell-serve.ts + rsc-rendering.ts) builds it
|
|
@@ -232,6 +241,15 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
232
241
|
* `runs: 1`, so a HIT still runs their bodies for those pushes.
|
|
233
242
|
*/
|
|
234
243
|
_shellCaptureUnrecordedLoaderPush?: true;
|
|
244
|
+
/**
|
|
245
|
+
* @internal The lane of each loader the capture's matched route registers
|
|
246
|
+
* (loader-cache.ts routeLoaderLanes), set by createMatchContextForFull
|
|
247
|
+
* before any loader runs. The capture's push funnel credits a push made
|
|
248
|
+
* under a live-lane loader's body, at any depth, to that loader
|
|
249
|
+
* (shell-capture.ts deriveShellCaptureContext). Own property of the
|
|
250
|
+
* capture's derived context only.
|
|
251
|
+
*/
|
|
252
|
+
_shellCaptureLoaderLanes?: ReadonlyMap<string, "live" | "bake">;
|
|
235
253
|
/**
|
|
236
254
|
* @internal Record keys resolved for this request (CacheScope
|
|
237
255
|
* resolveKeyFrom): by the scope's `key()` (one result) or its store's
|
|
@@ -330,7 +348,9 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
330
348
|
* scope replaces any route-derived cache() scope for the tail's match
|
|
331
349
|
* (resolveShellImplicitCacheScope), and a lookup that does not hit throws
|
|
332
350
|
* ShellRecordUnavailableError instead of resolving segments
|
|
333
|
-
* (withCacheLookup): a HIT never runs a handler.
|
|
351
|
+
* (withCacheLookup): a HIT never runs a handler. The record's
|
|
352
|
+
* loader-owned handle pushes restore as authoritative
|
|
353
|
+
* (HandleStore.pushRestored): the prelude rendered them.
|
|
334
354
|
*/
|
|
335
355
|
docTail?: true;
|
|
336
356
|
/**
|
|
@@ -382,8 +402,9 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
382
402
|
_shellFragmentPayload?: boolean;
|
|
383
403
|
/**
|
|
384
404
|
* @internal Set by the capture guard (server/context.ts
|
|
385
|
-
*
|
|
386
|
-
* ("cookies()", "headers()",
|
|
405
|
+
* guardIdentityRead) when it throws DURING a capture render: the read
|
|
406
|
+
* ("cookies()", "headers()", `ctx.get() for a non-cacheable variable`,
|
|
407
|
+
* "ctx.theme") and the fix the
|
|
387
408
|
* refusal warning gives for it. Load-bearing for the
|
|
388
409
|
* bake lane: a guard throw inside an executing loader is swallowed by
|
|
389
410
|
* wrapLoaderPromise into per-loader error UI, which would otherwise bake
|
|
@@ -512,11 +533,24 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
512
533
|
/**
|
|
513
534
|
* @internal The theme cookie (or the default) read with no identity guard.
|
|
514
535
|
* The guarded reads (`theme` here, the handler and middleware `ctx.theme`)
|
|
515
|
-
* call it after
|
|
516
|
-
* through payloadInitialTheme (rsc/full-payload.ts)
|
|
536
|
+
* call it after guardIdentityRead (readGuardedTheme); the router's own payload read goes
|
|
537
|
+
* through payloadInitialTheme (rsc/full-payload.ts), except the unmatched
|
|
538
|
+
* route's 404 (rsc/handler.ts), which is never stored. Undefined without
|
|
517
539
|
* theme config.
|
|
518
540
|
*/
|
|
519
541
|
_readTheme(): Theme | undefined;
|
|
542
|
+
/**
|
|
543
|
+
* @internal Set by the document-cache middleware (cache/document-cache.ts)
|
|
544
|
+
* before it runs a render whose response it may store: the MISS and the
|
|
545
|
+
* stale refresh. payloadInitialTheme reads it (#978).
|
|
546
|
+
*/
|
|
547
|
+
_documentCacheRender?: boolean;
|
|
548
|
+
/**
|
|
549
|
+
* @internal Set by payloadInitialTheme when the document payload carries
|
|
550
|
+
* the visitor's theme and it differs from the no-cookie default. The
|
|
551
|
+
* document cache does not store that response (#978).
|
|
552
|
+
*/
|
|
553
|
+
_payloadVisitorTheme?: boolean;
|
|
520
554
|
/**
|
|
521
555
|
* Attach location state entries to the current response.
|
|
522
556
|
*
|
|
@@ -551,19 +585,6 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
551
585
|
_routeName?: string;
|
|
552
586
|
/** @internal Previous route key (from the navigation source), used for revalidation */
|
|
553
587
|
_prevRouteKey?: string;
|
|
554
|
-
/**
|
|
555
|
-
* @internal Navigation/action source data the transition({ when }) gate reads
|
|
556
|
-
* to build its ShouldRevalidateFn-shaped predicate context. currentUrl/Params
|
|
557
|
-
* come from the navigation snapshot (set at match time); action* are stashed
|
|
558
|
-
* at the action-bearing gate call sites. All undefined when there is no source
|
|
559
|
-
* (initial full load) or no action (plain navigation).
|
|
560
|
-
*/
|
|
561
|
-
_gateCurrentUrl?: URL;
|
|
562
|
-
_gateCurrentParams?: Record<string, string>;
|
|
563
|
-
_gateActionId?: string;
|
|
564
|
-
_gateActionUrl?: URL;
|
|
565
|
-
_gateActionResult?: unknown;
|
|
566
|
-
_gateFormData?: FormData;
|
|
567
588
|
/**
|
|
568
589
|
* @internal True while the post-action revalidation render is running (set by
|
|
569
590
|
* revalidateAfterAction). The "use cache" runtime reads this to prefer
|
|
@@ -727,7 +748,7 @@ export interface RouteRecordWindow {
|
|
|
727
748
|
* This is the type exported to library consumers. Internal code should
|
|
728
749
|
* use the full RequestContext interface directly.
|
|
729
750
|
*/
|
|
730
|
-
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "
|
|
751
|
+
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_searchParamsFilter" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureUnrecordedLoaderPush" | "_shellCaptureLoaderLanes" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_routeRecordWindow" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_locationState" | "_routeName" | "_prevRouteKey" | "_inActionRevalidation" | "_reportedErrors" | "_renderErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
731
752
|
/**
|
|
732
753
|
* Marker for a waitUntil-scheduled fn whose task promise must NOT enter
|
|
733
754
|
* _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
|
|
@@ -762,7 +783,7 @@ export declare function setRequestContextParams(params: Record<string, string>,
|
|
|
762
783
|
* route key available for revalidation and intercept evaluation.
|
|
763
784
|
* @internal
|
|
764
785
|
*/
|
|
765
|
-
export declare function setRequestContextPrevRouteKey(prevRouteKey: string | undefined
|
|
786
|
+
export declare function setRequestContextPrevRouteKey(prevRouteKey: string | undefined): void;
|
|
766
787
|
/**
|
|
767
788
|
* Get accumulated location state entries from the current request context.
|
|
768
789
|
* Returns undefined if no state has been set.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The guarded `ctx.request.headers` (#976) and the router's raw reads.
|
|
3
|
+
*
|
|
4
|
+
* The Request the router hands to user code (handler, middleware and loader
|
|
5
|
+
* `ctx.request`, `getRequestContext().request`) carries an own `headers`
|
|
6
|
+
* getter that shadows the prototype's and runs the identity guard
|
|
7
|
+
* (cookie-store.ts guardRequestHeaders). A Proxy around the Request is not an
|
|
8
|
+
* option: `fetch(request)`, `new Request(request)` and `request.clone()` read
|
|
9
|
+
* the platform's internal slots, which a Proxy does not have. The own getter
|
|
10
|
+
* keeps the object a real Request, and those operations never call it.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* A request's headers, past the guard. The rule: router code never reads a
|
|
14
|
+
* request's headers through the getter, only through this, so the guard sees
|
|
15
|
+
* user reads alone. Several router reads run inside the scopes the guard
|
|
16
|
+
* refuses (the state cookie rotation at a ppr capture, match's HMR marker,
|
|
17
|
+
* a store's cf-ray inside a "use cache" body, telemetry inside a loader
|
|
18
|
+
* fill); the rest follow the rule so a new call site cannot drift into one.
|
|
19
|
+
*/
|
|
20
|
+
export declare function requestHeaders(request: Request): Headers;
|
|
21
|
+
/**
|
|
22
|
+
* Shadow `request.headers` with an own, non-enumerable getter that calls
|
|
23
|
+
* `beforeRead` and returns the request's own Headers (stable per request, so
|
|
24
|
+
* a header set through it stays visible to every reader). Idempotent. Leaves
|
|
25
|
+
* the request as is when `headers` is a non-configurable own property (a
|
|
26
|
+
* runtime that defines it per instance). Three inherited members are
|
|
27
|
+
* shadowed with it:
|
|
28
|
+
*
|
|
29
|
+
* - `clone()` returns a clone shadowed the same way. A plain clone was a
|
|
30
|
+
* Request without the getter, so `ctx.request.clone().headers` read the
|
|
31
|
+
* visitor's headers past the guard. (`new Request(ctx.request)` still
|
|
32
|
+
* returns a plain Request: the constructor cannot be intercepted.)
|
|
33
|
+
* - `_request`, on a lazy srvx NodeRequest (what @vitejs/plugin-rsc's Node
|
|
34
|
+
* dev and preview servers and the vercel-output launcher hand the
|
|
35
|
+
* router), runs unguarded: it builds the platform Request on first use
|
|
36
|
+
* from `this.headers`, for clone() and the body readers. Through the
|
|
37
|
+
* getter, a clone() inside a cache() boundary threw as a user read. It
|
|
38
|
+
* stays lazy, so a request whose body srvx reads from its buffered
|
|
39
|
+
* `rawBody` never builds one.
|
|
40
|
+
* - Node's util.inspect hook runs unguarded: undici's inspect reads
|
|
41
|
+
* `this.headers`, so `console.log(ctx.request)` inside a "use cache" body
|
|
42
|
+
* threw. A log is not a read into a shared entry.
|
|
43
|
+
*/
|
|
44
|
+
export declare function shadowRequestHeaders(request: Request, beforeRead: () => void): Request;
|
package/dist/types/server.d.ts
CHANGED
|
@@ -13,4 +13,5 @@ export { registerRouteMap, setCachedManifest, clearCachedManifest, clearAllRoute
|
|
|
13
13
|
export { registerLoaderById, setLoaderImports, } from "./server/loader-registry.js";
|
|
14
14
|
export { createRequestContext, type CreateRequestContextOptions, } from "./server/request-context.js";
|
|
15
15
|
export { isClientComponent, assertClientComponent } from "./component-utils.js";
|
|
16
|
+
export { enableTransitionWhenValidation } from "./transition-when-ref.js";
|
|
16
17
|
export { clearClientUrlProjections, setClientUrlProjection, type ClientUrlProjection, } from "./client-urls/server-projection.js";
|
|
@@ -4,7 +4,7 @@ import { blockPrefetch, unblockPrefetch, createPageHelpers, createStopwatch, get
|
|
|
4
4
|
import { createParity, type ExpectParityOptions, type Parity, type ParityDescribeOptions, type ParityIntent } from "./parity.js";
|
|
5
5
|
import { createRangoMatchers, type RangoMatchers } from "./matchers.js";
|
|
6
6
|
export { assertCacheStatus, assertCacheDecision, parseCacheHeader, createCacheSink, filterCacheDecisions, type CacheSink, type ExpectedCacheStatus, type CacheStatusTarget, } from "../cache-status.js";
|
|
7
|
-
export { assertPprReplayStatus, assertShellStatus, parsePprReplayStatus, parseShellStatus, PPR_REPLAY_STATUS_HEADER, shellCacheKey, SHELL_STATUS_HEADER, type PprReplayBypassReason, type PprReplayStatus, type ShellStatus, type ShellStatusTarget, } from "../shell-status.js";
|
|
7
|
+
export { assertPprReplayStatus, assertShellStatus, parsePprReplayStatus, parseShellStatus, PPR_REPLAY_STATUS_HEADER, shellCacheKey, SHELL_STATUS_HEADER, type PprReplayBypassReason, type PprReplayStatus, type ShellCachePartition, type ShellStatus, type ShellStatusTarget, } from "../shell-status.js";
|
|
8
8
|
export { testId, waitForHydration, waitForNavigation, goBack, goForward, getHistoryState, waitForElement, isVisibleInViewport, isPrefetchRequest, blockPrefetch, unblockPrefetch, parseNumber, getNumericContent, createStopwatch, measureTime, createPageHelpers, createUseFixture, createParity, createRangoMatchers, };
|
|
9
9
|
export type { Fixture, FixtureOptions, PageHelpers, Stopwatch, Parity, ParityIntent, ParityDescribeOptions, ExpectParityOptions, RangoMatchers, };
|
|
10
10
|
export interface RangoE2E extends PageHelpers, Parity {
|