@timber-js/app 0.2.0-alpha.71 → 0.2.0-alpha.72
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/_chunks/actions-Dg-ANYHb.js +421 -0
- package/dist/_chunks/actions-Dg-ANYHb.js.map +1 -0
- package/dist/_chunks/{als-registry-BJARkOcu.js → als-registry-HS0LGUl2.js} +1 -1
- package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
- package/dist/_chunks/{define-Dz1bqwaS.js → define-C77ScO0m.js} +14 -14
- package/dist/_chunks/define-C77ScO0m.js.map +1 -0
- package/dist/_chunks/{define-CGuYoRHU.js → define-CZqDwhSu.js} +15 -15
- package/dist/_chunks/define-CZqDwhSu.js.map +1 -0
- package/dist/_chunks/{define-cookie-B5mewxwM.js → define-cookie-C2IkoFGN.js} +9 -8
- package/dist/_chunks/{define-cookie-B5mewxwM.js.map → define-cookie-C2IkoFGN.js.map} +1 -1
- package/dist/_chunks/{format-Rn922VH2.js → dev-warnings-DpGRGoDi.js} +4 -26
- package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
- package/dist/_chunks/format-CYBGxKtc.js +14 -0
- package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
- package/dist/_chunks/{interception-CEdHHviP.js → interception-Dpn_UfAD.js} +2 -2
- package/dist/_chunks/{interception-CEdHHviP.js.map → interception-Dpn_UfAD.js.map} +1 -1
- package/dist/_chunks/{segment-context-hzuJ048X.js → merge-search-params-Cm_KIWDX.js} +2 -33
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
- package/dist/_chunks/{request-context-CywiO4jV.js → request-context-qMsWgy9C.js} +72 -36
- package/dist/_chunks/request-context-qMsWgy9C.js.map +1 -0
- package/dist/_chunks/{schema-bridge-C4SwjCQD.js → schema-bridge-C3xl_vfb.js} +1 -1
- package/dist/_chunks/{schema-bridge-C4SwjCQD.js.map → schema-bridge-C3xl_vfb.js.map} +1 -1
- package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
- package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
- package/dist/_chunks/ssr-data-DzuI0bIV.js +88 -0
- package/dist/_chunks/ssr-data-DzuI0bIV.js.map +1 -0
- package/dist/_chunks/{stale-reload-BLUC_Pl_.js → stale-reload-C2plcNtG.js} +1 -1
- package/dist/_chunks/{stale-reload-BLUC_Pl_.js.map → stale-reload-C2plcNtG.js.map} +1 -1
- package/dist/_chunks/{handler-store-BVePM7hp.js → tracing-CCYbKn5n.js} +60 -60
- package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
- package/dist/_chunks/use-params-B1AuhI1p.js +307 -0
- package/dist/_chunks/use-params-B1AuhI1p.js.map +1 -0
- package/dist/_chunks/{use-query-states-DAhgj8Gx.js → use-query-states-Lo_s_pw2.js} +4 -4
- package/dist/_chunks/use-query-states-Lo_s_pw2.js.map +1 -0
- package/dist/_chunks/{wrappers-LZbghvn0.js → wrappers-_DTmImGt.js} +1 -1
- package/dist/_chunks/{wrappers-LZbghvn0.js.map → wrappers-_DTmImGt.js.map} +1 -1
- package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +95 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/cache/index.d.ts +18 -4
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +78 -12
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cli.d.ts +6 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +27 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +30 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +23 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +19 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- package/dist/client/error-boundary.js +131 -1
- package/dist/client/error-boundary.js.map +1 -0
- package/dist/client/index.d.ts +4 -19
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +14 -1191
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +18 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +890 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/top-loader.d.ts +2 -2
- package/dist/client/use-link-status.d.ts +1 -1
- package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-router.d.ts +1 -1
- package/dist/codec.d.ts +10 -0
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +1 -1
- package/dist/config-types.d.ts +210 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +0 -2
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +2 -3
- package/dist/index.d.ts +25 -288
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +261 -43
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +84 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +1 -1
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +1 -1
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-browser-logs.d.ts +1 -1
- package/dist/plugins/dev-browser-logs.d.ts.map +1 -1
- package/dist/plugins/dev-logs.d.ts +1 -1
- package/dist/plugins/dev-logs.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +1 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +1 -1
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +4 -4
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/index.js +1 -1
- package/dist/search-params/define.d.ts +6 -6
- package/dist/search-params/define.d.ts.map +1 -1
- package/dist/search-params/index.d.ts +1 -2
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +4 -4
- package/dist/search-params/registry.d.ts +1 -1
- package/dist/search-params/registry.d.ts.map +1 -1
- package/dist/segment-params/define.d.ts +6 -6
- package/dist/segment-params/define.d.ts.map +1 -1
- package/dist/segment-params/index.d.ts +0 -1
- package/dist/segment-params/index.d.ts.map +1 -1
- package/dist/segment-params/index.js +3 -3
- package/dist/server/als-registry.d.ts +1 -1
- package/dist/server/dev-holding-server.d.ts +52 -0
- package/dist/server/dev-holding-server.d.ts.map +1 -0
- package/dist/server/dev-warnings.d.ts +1 -7
- package/dist/server/dev-warnings.d.ts.map +1 -1
- package/dist/server/index.d.ts +6 -45
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +7 -3272
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +46 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +2865 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +41 -17
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +45 -15
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/tracing.d.ts +4 -4
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/shims/headers.d.ts +2 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +2 -1
- package/dist/shims/navigation.d.ts.map +1 -1
- package/package.json +19 -13
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/cache/handler-store.ts +2 -2
- package/src/cache/index.ts +74 -15
- package/src/cache/sizeof.ts +31 -0
- package/src/cli.ts +6 -1
- package/src/client/browser-dev.ts +128 -1
- package/src/client/browser-entry/action-dispatch.ts +116 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +145 -0
- package/src/client/browser-entry/index.ts +138 -0
- package/src/client/browser-entry/post-hydration.ts +119 -0
- package/src/client/browser-entry/router-init.ts +184 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +27 -0
- package/src/client/index.ts +10 -38
- package/src/client/internal.ts +57 -0
- package/src/client/navigation-context.ts +6 -2
- package/src/client/navigation-root.tsx +1 -1
- package/src/client/router-ref.ts +1 -1
- package/src/client/top-loader.tsx +2 -2
- package/src/client/use-link-status.ts +1 -1
- package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +5 -5
- package/src/client/use-query-states.ts +2 -2
- package/src/client/use-router.ts +1 -1
- package/src/codec.ts +15 -0
- package/src/config-types.ts +208 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +9 -7
- package/src/cookies/index.ts +6 -5
- package/src/index.ts +84 -416
- package/src/plugin-context.ts +200 -0
- package/src/plugins/adapter-build.ts +1 -1
- package/src/plugins/build-manifest.ts +1 -1
- package/src/plugins/build-report.ts +1 -1
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-browser-logs.ts +1 -1
- package/src/plugins/dev-logs.ts +1 -1
- package/src/plugins/dev-server.ts +16 -1
- package/src/plugins/entries.ts +2 -2
- package/src/plugins/fonts.ts +4 -3
- package/src/plugins/mdx.ts +1 -1
- package/src/plugins/routing.ts +1 -1
- package/src/plugins/shims.ts +53 -5
- package/src/plugins/static-build.ts +8 -6
- package/src/search-params/define.ts +22 -22
- package/src/search-params/index.ts +3 -3
- package/src/search-params/registry.ts +1 -1
- package/src/segment-params/define.ts +18 -18
- package/src/segment-params/index.ts +2 -1
- package/src/server/action-handler.ts +1 -1
- package/src/server/als-registry.ts +3 -3
- package/src/server/dev-holding-server.ts +185 -0
- package/src/server/dev-warnings.ts +2 -21
- package/src/server/html-injectors.ts +3 -3
- package/src/server/index.ts +25 -180
- package/src/server/internal.ts +169 -0
- package/src/server/pipeline.ts +12 -7
- package/src/server/primitives.ts +71 -30
- package/src/server/request-context.ts +77 -39
- package/src/server/route-element-builder.ts +1 -1
- package/src/server/rsc-entry/index.ts +2 -2
- package/src/server/rsc-entry/ssr-renderer.ts +1 -1
- package/src/server/slot-resolver.ts +1 -1
- package/src/server/tracing.ts +6 -6
- package/src/server/tree-builder.ts +1 -1
- package/src/shims/headers.ts +5 -1
- package/src/shims/navigation.ts +5 -1
- package/dist/_chunks/als-registry-BJARkOcu.js.map +0 -1
- package/dist/_chunks/define-CGuYoRHU.js.map +0 -1
- package/dist/_chunks/define-Dz1bqwaS.js.map +0 -1
- package/dist/_chunks/error-boundary-D9hzsveV.js +0 -216
- package/dist/_chunks/error-boundary-D9hzsveV.js.map +0 -1
- package/dist/_chunks/format-Rn922VH2.js.map +0 -1
- package/dist/_chunks/handler-store-BVePM7hp.js.map +0 -1
- package/dist/_chunks/request-context-CywiO4jV.js.map +0 -1
- package/dist/_chunks/segment-context-hzuJ048X.js.map +0 -1
- package/dist/_chunks/use-query-states-DAhgj8Gx.js.map +0 -1
- package/dist/client/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/src/client/browser-entry.ts +0 -846
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// #server-internal — Framework-internal server exports
|
|
2
|
+
//
|
|
3
|
+
// This module is a Node package import (#server-internal in package.json
|
|
4
|
+
// "imports" field). It is only resolvable from within @timber-js/app —
|
|
5
|
+
// external consumers cannot import it.
|
|
6
|
+
//
|
|
7
|
+
// These exports are consumed by entry modules (rsc-entry, ssr-entry),
|
|
8
|
+
// adapters, dev server plugins, and build plugins. They are NOT part of
|
|
9
|
+
// the user-facing API and should not appear in documentation or autocomplete
|
|
10
|
+
// for application developers.
|
|
11
|
+
//
|
|
12
|
+
// Design doc: design/triage/api-naming-spike.md §8.5
|
|
13
|
+
|
|
14
|
+
// ── Request Context internals ────────────────────────────────────────────
|
|
15
|
+
export {
|
|
16
|
+
setSegmentParams,
|
|
17
|
+
runWithRequestContext,
|
|
18
|
+
setMutableCookieContext,
|
|
19
|
+
markResponseFlushed,
|
|
20
|
+
getSetCookieHeaders,
|
|
21
|
+
} from './request-context.js';
|
|
22
|
+
|
|
23
|
+
// ── Signal classes (instanceof targets for pipeline catch logic) ──────────
|
|
24
|
+
export { DenySignal, RedirectSignal, RenderError } from './primitives.js';
|
|
25
|
+
export type { RenderErrorDigest } from './primitives.js';
|
|
26
|
+
|
|
27
|
+
// ── Pipeline ─────────────────────────────────────────────────────────────
|
|
28
|
+
export { createPipeline } from './pipeline.js';
|
|
29
|
+
export type {
|
|
30
|
+
PipelineConfig,
|
|
31
|
+
RouteMatch,
|
|
32
|
+
RouteMatcher,
|
|
33
|
+
RouteRenderer,
|
|
34
|
+
EarlyHintsEmitter,
|
|
35
|
+
} from './pipeline.js';
|
|
36
|
+
|
|
37
|
+
// ── Early Hints ──────────────────────────────────────────────────────────
|
|
38
|
+
export { collectEarlyHintHeaders, formatLinkHeader } from './early-hints.js';
|
|
39
|
+
export type { EarlyHint } from './early-hints.js';
|
|
40
|
+
|
|
41
|
+
// ── Early Hints 103 Sender — ALS bridge for platform adapters ────────────
|
|
42
|
+
export { runWithEarlyHintsSender, sendEarlyHints103 } from './early-hints-sender.js';
|
|
43
|
+
export type { EarlyHintsSenderFn } from './early-hints-sender.js';
|
|
44
|
+
|
|
45
|
+
// ── Canonicalization ─────────────────────────────────────────────────────
|
|
46
|
+
export { canonicalize } from './canonicalize.js';
|
|
47
|
+
export type { CanonicalizeResult } from './canonicalize.js';
|
|
48
|
+
|
|
49
|
+
// ── Proxy ────────────────────────────────────────────────────────────────
|
|
50
|
+
export { runProxy } from './proxy.js';
|
|
51
|
+
export type { ProxyFn, ProxyExport } from './proxy.js';
|
|
52
|
+
|
|
53
|
+
// ── Middleware ────────────────────────────────────────────────────────────
|
|
54
|
+
export { runMiddleware } from './middleware-runner.js';
|
|
55
|
+
export type { MiddlewareFn } from './middleware-runner.js';
|
|
56
|
+
|
|
57
|
+
// ── Tree Builder ─────────────────────────────────────────────────────────
|
|
58
|
+
export { buildElementTree } from './tree-builder.js';
|
|
59
|
+
export type {
|
|
60
|
+
TreeBuilderConfig,
|
|
61
|
+
TreeBuildResult,
|
|
62
|
+
LoadedModule,
|
|
63
|
+
ModuleLoader,
|
|
64
|
+
AccessGateProps,
|
|
65
|
+
SlotAccessGateProps,
|
|
66
|
+
ErrorBoundaryProps,
|
|
67
|
+
} from './tree-builder.js';
|
|
68
|
+
|
|
69
|
+
// ── Access Gates ─────────────────────────────────────────────────────────
|
|
70
|
+
export { AccessGate, SlotAccessGate } from './access-gate.js';
|
|
71
|
+
|
|
72
|
+
// ── Status-Code Resolver ─────────────────────────────────────────────────
|
|
73
|
+
export { resolveStatusFile, resolveSlotDenied } from './status-code-resolver.js';
|
|
74
|
+
export type {
|
|
75
|
+
StatusFileResolution,
|
|
76
|
+
StatusFileKind,
|
|
77
|
+
StatusFileFormat,
|
|
78
|
+
SlotDeniedResolution,
|
|
79
|
+
SlotDeniedKind,
|
|
80
|
+
} from './status-code-resolver.js';
|
|
81
|
+
|
|
82
|
+
// ── Flush Controller ─────────────────────────────────────────────────────
|
|
83
|
+
export { flushResponse } from './flush.js';
|
|
84
|
+
export type { FlushOptions, FlushResult, RenderFn, RenderResult } from './flush.js';
|
|
85
|
+
|
|
86
|
+
// ── CSRF Protection ──────────────────────────────────────────────────────
|
|
87
|
+
export { validateCsrf } from './csrf.js';
|
|
88
|
+
export type { CsrfConfig, CsrfResult } from './csrf.js';
|
|
89
|
+
|
|
90
|
+
// ── Body Limits ──────────────────────────────────────────────────────────
|
|
91
|
+
export { parseBodySize, enforceBodyLimits, DEFAULT_LIMITS } from './body-limits.js';
|
|
92
|
+
export type { BodyLimitsConfig, BodyLimitResult, BodyKind } from './body-limits.js';
|
|
93
|
+
|
|
94
|
+
// ── Metadata ─────────────────────────────────────────────────────────────
|
|
95
|
+
export {
|
|
96
|
+
resolveMetadata,
|
|
97
|
+
resolveTitle,
|
|
98
|
+
resolveMetadataUrls,
|
|
99
|
+
renderMetadataToElements,
|
|
100
|
+
} from './metadata.js';
|
|
101
|
+
export type { SegmentMetadataEntry, ResolveMetadataOptions, HeadElement } from './metadata.js';
|
|
102
|
+
|
|
103
|
+
// ── Metadata Routes ──────────────────────────────────────────────────────
|
|
104
|
+
export {
|
|
105
|
+
classifyMetadataRoute,
|
|
106
|
+
getMetadataRouteServePath,
|
|
107
|
+
getMetadataRouteAutoLink,
|
|
108
|
+
METADATA_ROUTE_CONVENTIONS,
|
|
109
|
+
} from './metadata-routes.js';
|
|
110
|
+
export type { MetadataRouteInfo, MetadataRouteType } from './metadata-routes.js';
|
|
111
|
+
|
|
112
|
+
// ── Server Actions (pipeline internals) ──────────────────────────────────
|
|
113
|
+
export { executeAction, buildNoJsResponse, isRscActionRequest } from './actions.js';
|
|
114
|
+
export type {
|
|
115
|
+
RevalidateRenderer,
|
|
116
|
+
RevalidationState,
|
|
117
|
+
ActionHandlerConfig,
|
|
118
|
+
ActionHandlerResult,
|
|
119
|
+
} from './actions.js';
|
|
120
|
+
|
|
121
|
+
// ── Tracing internals ────────────────────────────────────────────────────
|
|
122
|
+
export { runWithTraceId, replaceTraceId, generateTraceId } from './tracing.js';
|
|
123
|
+
export type { TraceStore } from './tracing.js';
|
|
124
|
+
|
|
125
|
+
// ── Logger ───────────────────────────────────────────────────────────────
|
|
126
|
+
export { setLogger, getLogger } from './logger.js';
|
|
127
|
+
export {
|
|
128
|
+
logRequestCompleted,
|
|
129
|
+
logRequestReceived,
|
|
130
|
+
logSlowRequest,
|
|
131
|
+
logMiddlewareShortCircuit,
|
|
132
|
+
logMiddlewareError,
|
|
133
|
+
logRenderError,
|
|
134
|
+
logProxyError,
|
|
135
|
+
logWaitUntilUnsupported,
|
|
136
|
+
logWaitUntilRejected,
|
|
137
|
+
logSwrRefetchFailed,
|
|
138
|
+
logCacheMiss,
|
|
139
|
+
} from './logger.js';
|
|
140
|
+
export type { TimberLogger } from './logger.js';
|
|
141
|
+
|
|
142
|
+
// ── Instrumentation ──────────────────────────────────────────────────────
|
|
143
|
+
export { loadInstrumentation, callOnRequestError, hasOnRequestError } from './instrumentation.js';
|
|
144
|
+
export type {
|
|
145
|
+
InstrumentationOnRequestError,
|
|
146
|
+
InstrumentationRequestInfo,
|
|
147
|
+
InstrumentationErrorContext,
|
|
148
|
+
} from './instrumentation.js';
|
|
149
|
+
|
|
150
|
+
// ── Dev Warnings ─────────────────────────────────────────────────────────
|
|
151
|
+
export {
|
|
152
|
+
warnSuspenseWrappingChildren,
|
|
153
|
+
warnDenyInSuspense,
|
|
154
|
+
warnRedirectInSuspense,
|
|
155
|
+
warnRedirectInAccess,
|
|
156
|
+
warnStaticRequestApi,
|
|
157
|
+
warnSlowSlotWithoutSuspense,
|
|
158
|
+
setViteServer,
|
|
159
|
+
WarningId,
|
|
160
|
+
} from './dev-warnings.js';
|
|
161
|
+
export type { DevWarningConfig } from './dev-warnings.js';
|
|
162
|
+
|
|
163
|
+
// ── Route Handler ────────────────────────────────────────────────────────
|
|
164
|
+
export { handleRouteRequest, resolveAllowedMethods } from './route-handler.js';
|
|
165
|
+
export type { RouteModule, RouteHandler, HttpMethod } from './route-handler.js';
|
|
166
|
+
|
|
167
|
+
// ── Render Timeout ───────────────────────────────────────────────────────
|
|
168
|
+
export { RenderTimeoutError } from './render-timeout.js';
|
|
169
|
+
export type { RenderTimeout } from './render-timeout.js';
|
package/src/server/pipeline.ts
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
replaceTraceId,
|
|
31
31
|
withSpan,
|
|
32
32
|
setSpanAttribute,
|
|
33
|
-
|
|
33
|
+
getTraceId,
|
|
34
34
|
} from './tracing.js';
|
|
35
35
|
import {
|
|
36
36
|
logRequestReceived,
|
|
@@ -245,7 +245,7 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
|
|
|
245
245
|
const traceIdValue = generateTraceId();
|
|
246
246
|
|
|
247
247
|
return runWithTraceId(traceIdValue, async () => {
|
|
248
|
-
// Establish request context ALS scope so
|
|
248
|
+
// Establish request context ALS scope so getHeaders() and getCookies() work
|
|
249
249
|
// throughout the entire request lifecycle (proxy, middleware, render).
|
|
250
250
|
return runWithRequestContext(req, async () => {
|
|
251
251
|
// In dev mode, wrap with timing collector for Server-Timing header.
|
|
@@ -533,7 +533,7 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
|
|
|
533
533
|
}
|
|
534
534
|
|
|
535
535
|
// Store coerced segment params in ALS so components can access them
|
|
536
|
-
// via
|
|
536
|
+
// via getSegmentParams() instead of receiving them as a prop.
|
|
537
537
|
// See design/07-routing.md §"params.ts — Convention File for Typed Params"
|
|
538
538
|
setSegmentParams(match.segmentParams);
|
|
539
539
|
|
|
@@ -578,16 +578,21 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
|
|
|
578
578
|
applyCookieJar(finalResponse.headers);
|
|
579
579
|
// Merge parent-set responseHeaders onto the short-circuit response.
|
|
580
580
|
// Child-set headers take precedence — only add headers not already present.
|
|
581
|
+
// Snapshot existing keys first so multi-value headers (Set-Cookie, Link)
|
|
582
|
+
// from the parent are all appended when the child didn't set that key.
|
|
583
|
+
const existingKeys = new Set(
|
|
584
|
+
[...finalResponse.headers.keys()].map((k) => k.toLowerCase())
|
|
585
|
+
);
|
|
581
586
|
for (const [key, value] of responseHeaders.entries()) {
|
|
582
|
-
if (!
|
|
583
|
-
finalResponse.headers.
|
|
587
|
+
if (!existingKeys.has(key.toLowerCase())) {
|
|
588
|
+
finalResponse.headers.append(key, value);
|
|
584
589
|
}
|
|
585
590
|
}
|
|
586
591
|
logMiddlewareShortCircuit({ method, path, status: finalResponse.status });
|
|
587
592
|
return finalResponse;
|
|
588
593
|
}
|
|
589
594
|
// Middleware chain completed without short-circuiting — apply any
|
|
590
|
-
// injected request headers so
|
|
595
|
+
// injected request headers so getHeaders() returns them downstream.
|
|
591
596
|
applyRequestHeaderOverlay(requestHeaderOverlay);
|
|
592
597
|
} catch (error) {
|
|
593
598
|
setMutableCookieContext(false);
|
|
@@ -669,7 +674,7 @@ async function fireOnRequestError(
|
|
|
669
674
|
await callOnRequestError(
|
|
670
675
|
error,
|
|
671
676
|
{ method: req.method, path: url.pathname, headers: headersObj },
|
|
672
|
-
{ phase, routePath: url.pathname, routeType: 'page', traceId:
|
|
677
|
+
{ phase, routePath: url.pathname, routeType: 'page', traceId: getTraceId() }
|
|
673
678
|
);
|
|
674
679
|
}
|
|
675
680
|
|
package/src/server/primitives.ts
CHANGED
|
@@ -145,37 +145,65 @@ export class DenySignal extends Error {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
/** Options for deny() when using the object form. */
|
|
149
|
+
export interface DenyOptions {
|
|
150
|
+
/** HTTP status code (4xx or 5xx). Default: 403. */
|
|
151
|
+
status?: number;
|
|
152
|
+
/** Human-readable message (logged server-side, not sent to client). */
|
|
153
|
+
message?: string;
|
|
154
|
+
/** JSON-serializable data passed as `dangerouslyPassData` prop to status-code files. */
|
|
155
|
+
data?: JsonSerializable;
|
|
156
|
+
}
|
|
157
|
+
|
|
148
158
|
/**
|
|
149
|
-
* Universal denial primitive. Throws a `DenySignal` that the framework catches.
|
|
159
|
+
* Universal denial/error primitive. Throws a `DenySignal` that the framework catches.
|
|
150
160
|
*
|
|
151
161
|
* - In segment context (outside Suspense): produces HTTP status code
|
|
152
162
|
* - In slot context: graceful degradation → denied.tsx → default.tsx → null
|
|
153
163
|
* - Inside Suspense (hold window): promoted to pre-flush behavior
|
|
154
164
|
* - Inside Suspense (after flush): error boundary + noindex meta
|
|
155
165
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
166
|
+
* Supports both positional and object signatures:
|
|
167
|
+
* ```ts
|
|
168
|
+
* deny() // 403 (default)
|
|
169
|
+
* deny(404) // 404
|
|
170
|
+
* deny(503, { retry: true }) // 503 with data
|
|
171
|
+
* deny({ status: 503, message: 'Maintenance' }) // object form
|
|
172
|
+
* ```
|
|
173
|
+
*
|
|
174
|
+
* Accepts any 4xx or 5xx status code. This replaces the need for
|
|
175
|
+
* `throw new RenderError(...)` in user code — RenderError is now an
|
|
176
|
+
* internal pipeline detail.
|
|
177
|
+
*
|
|
178
|
+
* @param statusOrOptions - Status code (number) or options object. Default: 403.
|
|
179
|
+
* @param data - Optional JSON-serializable data (positional form only).
|
|
158
180
|
*/
|
|
159
|
-
export function deny(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
181
|
+
export function deny(statusOrOptions?: number | DenyOptions, data?: JsonSerializable): never {
|
|
182
|
+
let status: number;
|
|
183
|
+
let resolvedData: JsonSerializable | undefined;
|
|
184
|
+
|
|
185
|
+
if (typeof statusOrOptions === 'object' && statusOrOptions !== null) {
|
|
186
|
+
status = statusOrOptions.status ?? 403;
|
|
187
|
+
resolvedData = statusOrOptions.data;
|
|
188
|
+
} else {
|
|
189
|
+
status = statusOrOptions ?? 403;
|
|
190
|
+
resolvedData = data;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (status < 400 || status > 599) {
|
|
194
|
+
throw new Error(`deny() requires a 4xx or 5xx status code, got ${status}.`);
|
|
165
195
|
}
|
|
166
|
-
warnIfNotSerializable(
|
|
167
|
-
throw new DenySignal(status,
|
|
196
|
+
warnIfNotSerializable(resolvedData, 'deny()');
|
|
197
|
+
throw new DenySignal(status, resolvedData);
|
|
168
198
|
}
|
|
169
199
|
|
|
170
200
|
/**
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* call `notFound()` from `next/navigation` get the same behavior as
|
|
175
|
-
* `deny(404)` in timber.
|
|
201
|
+
* @deprecated Use `deny(404)` instead.
|
|
202
|
+
* Kept for internal use by the Next.js shim layer.
|
|
203
|
+
* @internal
|
|
176
204
|
*/
|
|
177
205
|
export function notFound(): never {
|
|
178
|
-
|
|
206
|
+
deny(404);
|
|
179
207
|
}
|
|
180
208
|
|
|
181
209
|
/**
|
|
@@ -215,8 +243,17 @@ const ABSOLUTE_URL_RE = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/)/;
|
|
|
215
243
|
* Options for redirect() — alternative to passing a bare status code.
|
|
216
244
|
*/
|
|
217
245
|
export interface RedirectOptions {
|
|
218
|
-
/** HTTP redirect status code (3xx). Defaults to 302. */
|
|
246
|
+
/** HTTP redirect status code (3xx). Defaults to 302 (or 308 when `permanent: true`). */
|
|
219
247
|
status?: number;
|
|
248
|
+
/**
|
|
249
|
+
* When true, defaults the status to 308 (Permanent Redirect, preserves HTTP method).
|
|
250
|
+
* If `status` is also provided, `status` takes precedence.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* redirect('/new-path', { permanent: true }); // 308
|
|
254
|
+
* redirect('/new-path', { permanent: true, status: 301 }); // 301
|
|
255
|
+
*/
|
|
256
|
+
permanent?: boolean;
|
|
220
257
|
/**
|
|
221
258
|
* Preserve search params from the current request URL on the redirect target.
|
|
222
259
|
*
|
|
@@ -246,10 +283,18 @@ export interface RedirectOptions {
|
|
|
246
283
|
* redirect(`/docs/${version}/${slug}`, { preserveSearchParams: ['foo'] });
|
|
247
284
|
*/
|
|
248
285
|
export function redirect(path: string, statusOrOptions?: number | RedirectOptions): never {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
286
|
+
let status: number;
|
|
287
|
+
let preserveSearchParams: true | string[] | undefined;
|
|
288
|
+
|
|
289
|
+
if (typeof statusOrOptions === 'number') {
|
|
290
|
+
status = statusOrOptions;
|
|
291
|
+
} else if (statusOrOptions) {
|
|
292
|
+
// Explicit status wins. Otherwise permanent: true → 308, default → 302.
|
|
293
|
+
status = statusOrOptions.status ?? (statusOrOptions.permanent ? 308 : 302);
|
|
294
|
+
preserveSearchParams = statusOrOptions.preserveSearchParams;
|
|
295
|
+
} else {
|
|
296
|
+
status = 302;
|
|
297
|
+
}
|
|
253
298
|
|
|
254
299
|
if (status < 300 || status > 399) {
|
|
255
300
|
throw new Error(`redirect() requires a 3xx status code, got ${status}.`);
|
|
@@ -271,16 +316,12 @@ export function redirect(path: string, statusOrOptions?: number | RedirectOption
|
|
|
271
316
|
}
|
|
272
317
|
|
|
273
318
|
/**
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
* will replay POST requests to the new location. This matches Next.js behavior.
|
|
278
|
-
*
|
|
279
|
-
* @param path - Relative path (e.g. '/new-page', '/dashboard')
|
|
280
|
-
* @param options - Optional redirect options (e.g. preserveSearchParams).
|
|
319
|
+
* @deprecated Use `redirect(path, { permanent: true })` instead.
|
|
320
|
+
* Kept for internal use by the Next.js shim layer.
|
|
321
|
+
* @internal
|
|
281
322
|
*/
|
|
282
323
|
export function permanentRedirect(path: string, options?: Omit<RedirectOptions, 'status'>): never {
|
|
283
|
-
redirect(path, {
|
|
324
|
+
redirect(path, { permanent: true, ...options });
|
|
284
325
|
}
|
|
285
326
|
|
|
286
327
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Request Context — per-request ALS store for
|
|
2
|
+
* Request Context — per-request ALS store for getHeaders() and getCookies().
|
|
3
3
|
*
|
|
4
4
|
* Follows the same pattern as tracing.ts: a module-level AsyncLocalStorage
|
|
5
5
|
* instance, public accessor functions that throw outside request scope,
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import { requestContextAls, type RequestContextStore, type CookieEntry } from './als-registry.js';
|
|
14
14
|
import { isDebug } from './debug.js';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { _setGetSearchParamsFn } from '../search-params/define.js';
|
|
16
|
+
import { _setGetSegmentParamsFn } from '../segment-params/define.js';
|
|
17
17
|
|
|
18
18
|
// Re-export the ALS for framework-internal consumers that need direct access.
|
|
19
19
|
export { requestContextAls };
|
|
@@ -30,15 +30,34 @@ export { requestContextAls };
|
|
|
30
30
|
* Available in middleware, access checks, server components, and server actions.
|
|
31
31
|
* Throws if called outside a request context (security principle #2: no global fallback).
|
|
32
32
|
*/
|
|
33
|
-
export function
|
|
33
|
+
export function getHeaders(): Promise<ReadonlyHeaders> {
|
|
34
34
|
const store = requestContextAls.getStore();
|
|
35
35
|
if (!store) {
|
|
36
36
|
throw new Error(
|
|
37
|
-
'[timber]
|
|
37
|
+
'[timber] getHeaders() called outside of a request context. ' +
|
|
38
38
|
'It can only be used in middleware, access checks, server components, and server actions.'
|
|
39
39
|
);
|
|
40
40
|
}
|
|
41
|
-
return store.headers;
|
|
41
|
+
return Promise.resolve(store.headers);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns the value of a single request header, or undefined if absent.
|
|
46
|
+
*
|
|
47
|
+
* Thin wrapper over `(await getHeaders()).get(name)` for the common
|
|
48
|
+
* case where you need exactly one header.
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { getHeader } from '@timber-js/app/server'
|
|
52
|
+
*
|
|
53
|
+
* export default async function Page() {
|
|
54
|
+
* const auth = await getHeader('authorization');
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export async function getHeader(name: string): Promise<string | undefined> {
|
|
59
|
+
const headers = await getHeaders();
|
|
60
|
+
return headers.get(name) ?? undefined;
|
|
42
61
|
}
|
|
43
62
|
|
|
44
63
|
/**
|
|
@@ -56,11 +75,11 @@ export function headers(): ReadonlyHeaders {
|
|
|
56
75
|
*
|
|
57
76
|
* See design/29-cookies.md
|
|
58
77
|
*/
|
|
59
|
-
export function
|
|
78
|
+
export function getCookies(): Promise<RequestCookies> {
|
|
60
79
|
const store = requestContextAls.getStore();
|
|
61
80
|
if (!store) {
|
|
62
81
|
throw new Error(
|
|
63
|
-
'[timber]
|
|
82
|
+
'[timber] getCookies() called outside of a request context. ' +
|
|
64
83
|
'It can only be used in middleware, access checks, server components, and server actions.'
|
|
65
84
|
);
|
|
66
85
|
}
|
|
@@ -71,7 +90,7 @@ export function cookies(): RequestCookies {
|
|
|
71
90
|
}
|
|
72
91
|
|
|
73
92
|
const map = store.parsedCookies;
|
|
74
|
-
return {
|
|
93
|
+
return Promise.resolve({
|
|
75
94
|
get(name: string): string | undefined {
|
|
76
95
|
return map.get(name);
|
|
77
96
|
},
|
|
@@ -90,7 +109,7 @@ export function cookies(): RequestCookies {
|
|
|
90
109
|
if (store.flushed) {
|
|
91
110
|
if (isDebug()) {
|
|
92
111
|
console.warn(
|
|
93
|
-
`[timber] warn:
|
|
112
|
+
`[timber] warn: getCookies().set('${name}') called after response headers were committed.\n` +
|
|
94
113
|
` The cookie will NOT be sent. Move cookie mutations to middleware.ts, a server action,\n` +
|
|
95
114
|
` or a route.ts handler.`
|
|
96
115
|
);
|
|
@@ -107,7 +126,7 @@ export function cookies(): RequestCookies {
|
|
|
107
126
|
assertMutable(store, 'setFromHeaders');
|
|
108
127
|
if (store.flushed) {
|
|
109
128
|
console.warn(
|
|
110
|
-
`[timber] warn:
|
|
129
|
+
`[timber] warn: getCookies().setFromHeaders() called after response headers were committed.\n` +
|
|
111
130
|
` The cookies will NOT be sent. Move cookie mutations to middleware.ts, a server action,\n` +
|
|
112
131
|
` or a route.ts handler.`
|
|
113
132
|
);
|
|
@@ -131,7 +150,7 @@ export function cookies(): RequestCookies {
|
|
|
131
150
|
if (store.flushed) {
|
|
132
151
|
if (isDebug()) {
|
|
133
152
|
console.warn(
|
|
134
|
-
`[timber] warn:
|
|
153
|
+
`[timber] warn: getCookies().delete('${name}') called after response headers were committed.\n` +
|
|
135
154
|
` The cookie will NOT be deleted. Move cookie mutations to middleware.ts, a server action,\n` +
|
|
136
155
|
` or a route.ts handler.`
|
|
137
156
|
);
|
|
@@ -168,7 +187,26 @@ export function cookies(): RequestCookies {
|
|
|
168
187
|
.map(([name, value]) => `${name}=${value}`)
|
|
169
188
|
.join('; ');
|
|
170
189
|
},
|
|
171
|
-
};
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Returns the value of a single cookie, or undefined if absent.
|
|
195
|
+
*
|
|
196
|
+
* Thin wrapper over `(await getCookies()).get(name)` for the common
|
|
197
|
+
* case where you need exactly one cookie.
|
|
198
|
+
*
|
|
199
|
+
* ```ts
|
|
200
|
+
* import { getCookie } from '@timber-js/app/server'
|
|
201
|
+
*
|
|
202
|
+
* export default async function Page() {
|
|
203
|
+
* const session = await getCookie('session_id');
|
|
204
|
+
* }
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
export async function getCookie(name: string): Promise<string | undefined> {
|
|
208
|
+
const cookies = await getCookies();
|
|
209
|
+
return cookies.get(name);
|
|
172
210
|
}
|
|
173
211
|
|
|
174
212
|
/**
|
|
@@ -179,40 +217,40 @@ export function cookies(): RequestCookies {
|
|
|
179
217
|
*
|
|
180
218
|
* ```ts
|
|
181
219
|
* import { searchParams } from './params'
|
|
182
|
-
* const parsed = await searchParams.
|
|
220
|
+
* const parsed = await searchParams.get()
|
|
183
221
|
* ```
|
|
184
222
|
*
|
|
185
223
|
* Or explicitly:
|
|
186
224
|
*
|
|
187
225
|
* ```ts
|
|
188
|
-
* import {
|
|
226
|
+
* import { getSearchParams } from '@timber-js/app/server'
|
|
189
227
|
* import { searchParams } from './params'
|
|
190
|
-
* const parsed = searchParams.parse(await
|
|
228
|
+
* const parsed = searchParams.parse(await getSearchParams())
|
|
191
229
|
* ```
|
|
192
230
|
*
|
|
193
231
|
* Throws if called outside a request context.
|
|
194
232
|
*/
|
|
195
|
-
export function
|
|
233
|
+
export function getSearchParams(): Promise<URLSearchParams> {
|
|
196
234
|
const store = requestContextAls.getStore();
|
|
197
235
|
if (!store) {
|
|
198
236
|
throw new Error(
|
|
199
|
-
'[timber]
|
|
237
|
+
'[timber] getSearchParams() called outside of a request context. ' +
|
|
200
238
|
'It can only be used in middleware, access checks, server components, and server actions.'
|
|
201
239
|
);
|
|
202
240
|
}
|
|
203
241
|
return store.searchParamsPromise;
|
|
204
242
|
}
|
|
205
243
|
|
|
206
|
-
// Eagerly register
|
|
207
|
-
// searchParams.
|
|
244
|
+
// Eagerly register getSearchParams with the search-params module so
|
|
245
|
+
// searchParams.get() can call it synchronously without a dynamic import.
|
|
208
246
|
// Dynamic imports lose ALS context in React's RSC Flight renderer,
|
|
209
|
-
// breaking
|
|
210
|
-
|
|
247
|
+
// breaking getSearchParams() in parallel slot pages. See TIM-523.
|
|
248
|
+
_setGetSearchParamsFn(getSearchParams);
|
|
211
249
|
|
|
212
|
-
// Eagerly register
|
|
213
|
-
// segmentParams.
|
|
250
|
+
// Eagerly register getSegmentParams with the segment-params module so
|
|
251
|
+
// segmentParams.get() can call it synchronously without a dynamic import.
|
|
214
252
|
// Same pattern as search params — dynamic imports lose ALS context. See TIM-523.
|
|
215
|
-
|
|
253
|
+
_setGetSegmentParamsFn(getSegmentParams);
|
|
216
254
|
|
|
217
255
|
/**
|
|
218
256
|
* Returns a Promise resolving to the current request's coerced segment params.
|
|
@@ -225,27 +263,27 @@ _setRawSegmentParamsFn(rawSegmentParams);
|
|
|
225
263
|
* This is the primary way page and layout components access route params:
|
|
226
264
|
*
|
|
227
265
|
* ```ts
|
|
228
|
-
* import {
|
|
266
|
+
* import { getSegmentParams } from '@timber-js/app/server'
|
|
229
267
|
*
|
|
230
268
|
* export default async function Page() {
|
|
231
|
-
* const { slug } = await
|
|
269
|
+
* const { slug } = await getSegmentParams()
|
|
232
270
|
* // ...
|
|
233
271
|
* }
|
|
234
272
|
* ```
|
|
235
273
|
*
|
|
236
274
|
* Throws if called outside a request context.
|
|
237
275
|
*/
|
|
238
|
-
export function
|
|
276
|
+
export function getSegmentParams(): Promise<Record<string, string | string[]>> {
|
|
239
277
|
const store = requestContextAls.getStore();
|
|
240
278
|
if (!store) {
|
|
241
279
|
throw new Error(
|
|
242
|
-
'[timber]
|
|
280
|
+
'[timber] getSegmentParams() called outside of a request context. ' +
|
|
243
281
|
'It can only be used in middleware, access checks, server components, and server actions.'
|
|
244
282
|
);
|
|
245
283
|
}
|
|
246
284
|
if (!store.segmentParamsPromise) {
|
|
247
285
|
throw new Error(
|
|
248
|
-
'[timber]
|
|
286
|
+
'[timber] getSegmentParams() called before route matching completed. ' +
|
|
249
287
|
'Segment params are not available until after the route is matched.'
|
|
250
288
|
);
|
|
251
289
|
}
|
|
@@ -402,7 +440,7 @@ function parseSetCookie(
|
|
|
402
440
|
}
|
|
403
441
|
|
|
404
442
|
/**
|
|
405
|
-
* Cookie accessor returned by `
|
|
443
|
+
* Cookie accessor returned by `getCookies()`.
|
|
406
444
|
*
|
|
407
445
|
* Read methods are always available. Mutation methods throw in read-only
|
|
408
446
|
* contexts (access.ts, server components).
|
|
@@ -426,7 +464,7 @@ export interface RequestCookies {
|
|
|
426
464
|
* Useful when forwarding cookies from an internal `fetch()` or auth handler:
|
|
427
465
|
* ```ts
|
|
428
466
|
* const response = await auth.handler(req);
|
|
429
|
-
*
|
|
467
|
+
* getCookies().then(c => c.setFromHeaders(response.headers));
|
|
430
468
|
* ```
|
|
431
469
|
*/
|
|
432
470
|
setFromHeaders(headers: Headers): void;
|
|
@@ -442,7 +480,7 @@ export interface RequestCookies {
|
|
|
442
480
|
|
|
443
481
|
/**
|
|
444
482
|
* Run a callback within a request context. Used by the pipeline to establish
|
|
445
|
-
* per-request ALS scope so that `
|
|
483
|
+
* per-request ALS scope so that `getHeaders()` and `getCookies()` work.
|
|
446
484
|
*
|
|
447
485
|
* @param req - The incoming Request object.
|
|
448
486
|
* @param fn - The function to run within the request context.
|
|
@@ -492,7 +530,7 @@ export function markResponseFlushed(): void {
|
|
|
492
530
|
/**
|
|
493
531
|
* Build a Map of cookie name → value reflecting the current request's
|
|
494
532
|
* read-your-own-writes state. Includes incoming cookies plus any
|
|
495
|
-
* mutations from
|
|
533
|
+
* mutations from getCookies().set() / getCookies().delete() in the same request.
|
|
496
534
|
*
|
|
497
535
|
* Used by SSR renderers to populate NavContext.cookies so that
|
|
498
536
|
* useCookie()'s server snapshot matches the actual response state.
|
|
@@ -512,8 +550,8 @@ export function getCookiesForSsr(): Map<string, string> {
|
|
|
512
550
|
}
|
|
513
551
|
|
|
514
552
|
// The parsedCookies map already reflects read-your-own-writes:
|
|
515
|
-
// -
|
|
516
|
-
// -
|
|
553
|
+
// - getCookies().set() updates the map via map.set(name, value)
|
|
554
|
+
// - getCookies().delete() removes from the map via map.delete(name)
|
|
517
555
|
// Return a copy so callers can't mutate the internal map.
|
|
518
556
|
return new Map(store.parsedCookies);
|
|
519
557
|
}
|
|
@@ -535,7 +573,7 @@ export function getSetCookieHeaders(): string[] {
|
|
|
535
573
|
*
|
|
536
574
|
* Called by the pipeline after middleware.ts runs. Merges overlay headers
|
|
537
575
|
* on top of the original request headers so downstream code (access.ts,
|
|
538
|
-
* server components, server actions) sees them via `
|
|
576
|
+
* server components, server actions) sees them via `getHeaders()`.
|
|
539
577
|
*
|
|
540
578
|
* The original request headers are never mutated — a new frozen Headers
|
|
541
579
|
* object is created with the overlay applied on top.
|
|
@@ -582,7 +620,7 @@ function freezeHeaders(source: Headers): Headers {
|
|
|
582
620
|
if (typeof prop === 'string' && MUTATING_METHODS.has(prop)) {
|
|
583
621
|
return () => {
|
|
584
622
|
throw new Error(
|
|
585
|
-
`[timber]
|
|
623
|
+
`[timber] getHeaders() returns a read-only Headers object. ` +
|
|
586
624
|
`Calling .${prop}() is not allowed. ` +
|
|
587
625
|
`Use ctx.requestHeaders in middleware to inject headers for downstream components.`
|
|
588
626
|
);
|
|
@@ -604,7 +642,7 @@ function freezeHeaders(source: Headers): Headers {
|
|
|
604
642
|
function assertMutable(store: RequestContextStore, method: string): void {
|
|
605
643
|
if (!store.mutableContext) {
|
|
606
644
|
throw new Error(
|
|
607
|
-
`
|
|
645
|
+
`(timber] getCookies().${method}() cannot be called in this context.\n` +
|
|
608
646
|
` Set cookies in middleware.ts, server actions, or route.ts handlers.`
|
|
609
647
|
);
|
|
610
648
|
}
|