@timber-js/app 0.2.0-alpha.35 → 0.2.0-alpha.37
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/LICENSE +8 -0
- package/dist/_chunks/als-registry-Ba7URUIn.js.map +1 -1
- package/dist/_chunks/{define-cookie-w5GWm_bL.js → define-cookie-BmKbSyp0.js} +4 -4
- package/dist/_chunks/{define-cookie-w5GWm_bL.js.map → define-cookie-BmKbSyp0.js.map} +1 -1
- package/dist/_chunks/{error-boundary-TYEQJZ1-.js → error-boundary-BAN3751q.js} +1 -1
- package/dist/_chunks/{error-boundary-TYEQJZ1-.js.map → error-boundary-BAN3751q.js.map} +1 -1
- package/dist/_chunks/{request-context-CZz_T0Bc.js → request-context-BxYIJM24.js} +59 -4
- package/dist/_chunks/request-context-BxYIJM24.js.map +1 -0
- package/dist/_chunks/segment-context-C6byCyZU.js +69 -0
- package/dist/_chunks/segment-context-C6byCyZU.js.map +1 -0
- package/dist/_chunks/{tracing-BPyIzIdu.js → tracing-CuXiCP5p.js} +1 -1
- package/dist/_chunks/{tracing-BPyIzIdu.js.map → tracing-CuXiCP5p.js.map} +1 -1
- package/dist/_chunks/{wrappers-C1SN725w.js → wrappers-C6J0nNji.js} +2 -2
- package/dist/_chunks/{wrappers-C1SN725w.js.map → wrappers-C6J0nNji.js.map} +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/client/error-boundary.js +1 -1
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +25 -8
- package/dist/client/index.js.map +1 -1
- package/dist/client/link.d.ts +15 -1
- package/dist/client/link.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -1
- package/dist/params/index.js +1 -1
- package/dist/search-params/index.js +1 -1
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +14 -0
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/flight-scripts.d.ts +39 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +3 -9
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +42 -26
- package/dist/server/index.js.map +1 -1
- package/dist/server/node-stream-transforms.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +30 -3
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +39 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/slot-resolver.d.ts +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +7 -4
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/package.json +6 -7
- package/src/cli.ts +0 -0
- package/src/client/browser-entry.ts +3 -12
- package/src/client/index.ts +1 -0
- package/src/client/link.tsx +57 -3
- package/src/server/access-gate.tsx +6 -5
- package/src/server/als-registry.ts +14 -0
- package/src/server/deny-renderer.ts +2 -1
- package/src/server/flight-scripts.ts +59 -0
- package/src/server/html-injectors.ts +8 -32
- package/src/server/index.ts +3 -0
- package/src/server/node-stream-transforms.ts +8 -24
- package/src/server/pipeline.ts +6 -0
- package/src/server/primitives.ts +47 -5
- package/src/server/request-context.ts +69 -1
- package/src/server/route-element-builder.ts +10 -16
- package/src/server/rsc-entry/error-renderer.ts +2 -1
- package/src/server/rsc-entry/ssr-renderer.ts +9 -1
- package/src/server/slot-resolver.ts +10 -19
- package/src/server/tree-builder.ts +13 -15
- package/src/shared/merge-search-params.ts +48 -0
- package/dist/_chunks/request-context-CZz_T0Bc.js.map +0 -1
- package/dist/_chunks/segment-context-Dpq2XOKg.js +0 -34
- package/dist/_chunks/segment-context-Dpq2XOKg.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-stream-transforms.d.ts","sourceRoot":"","sources":["../../src/server/node-stream-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"node-stream-transforms.d.ts","sourceRoot":"","sources":["../../src/server/node-stream-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAgBxC;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CA+ClE;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,SAAS,GAChD,SAAS,CAkIX;AAOD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAwBtE;AAoBD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,OAAO,EACvB,eAAe,EAAE,OAAO,GACvB,SAAS,GAAG,IAAI,CA8BlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/server/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/server/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAmC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,uDAAuD;IACvD,UAAU,CAAC,EAAE,YAAY,CAAC;CAC3B;AAED,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAAC;AAEnE,sEAAsE;AACtE,MAAM,MAAM,oBAAoB,GAAG,CACjC,QAAQ,EAAE,MAAM,KACb,OAAO,oBAAoB,EAAE,kBAAkB,GAAG,IAAI,CAAC;AAE5D,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,iEAAiE;IACjE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,6DAA6D;AAC7D,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,YAAY,CAAC,EAAE,mBAAmB,KAC/B,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC,+DAA+D;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAC9B,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,OAAO,KACrB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAI1B,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACtD,qEAAqE;IACrE,UAAU,EAAE,YAAY,CAAC;IACzB,iGAAiG;IACjG,kBAAkB,CAAC,EAAE,oBAAoB,CAAC;IAC1C,kEAAkE;IAClE,MAAM,EAAE,aAAa,CAAC;IACtB,kEAAkE;IAClE,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzF,kFAAkF;IAClF,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yGAAyG;IACzG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,2BAA2B,EAAE,mBAAmB,EAAE,CAAC;IACjF;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IAC5C;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,CACpB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,OAAO,KACrB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACnC;AAwCD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CA8Y1F"}
|
|
@@ -61,14 +61,40 @@ export declare class RedirectSignal extends Error {
|
|
|
61
61
|
readonly status: number;
|
|
62
62
|
constructor(location: string, status: number);
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Options for redirect() — alternative to passing a bare status code.
|
|
66
|
+
*/
|
|
67
|
+
export interface RedirectOptions {
|
|
68
|
+
/** HTTP redirect status code (3xx). Defaults to 302. */
|
|
69
|
+
status?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Preserve search params from the current request URL on the redirect target.
|
|
72
|
+
*
|
|
73
|
+
* - `true` — preserve ALL current search params (target params take precedence)
|
|
74
|
+
* - `string[]` — preserve only the named params (e.g. `['private', 'token']`)
|
|
75
|
+
*
|
|
76
|
+
* Target path's own query params always take precedence over preserved ones.
|
|
77
|
+
*/
|
|
78
|
+
preserveSearchParams?: true | string[];
|
|
79
|
+
}
|
|
64
80
|
/**
|
|
65
81
|
* Redirect to a relative path. Rejects absolute and protocol-relative URLs.
|
|
66
82
|
* Use `redirectExternal()` for external redirects with an allow-list.
|
|
67
83
|
*
|
|
68
84
|
* @param path - Relative path (e.g. '/login', 'settings', '/login?returnTo=/dash')
|
|
69
|
-
* @param
|
|
85
|
+
* @param statusOrOptions - HTTP status code (3xx, default 302) or options object.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Simple redirect
|
|
89
|
+
* redirect('/login');
|
|
90
|
+
*
|
|
91
|
+
* // With status code
|
|
92
|
+
* redirect('/login', 301);
|
|
93
|
+
*
|
|
94
|
+
* // With preserved search params
|
|
95
|
+
* redirect(`/docs/${version}/${slug}`, { preserveSearchParams: ['foo'] });
|
|
70
96
|
*/
|
|
71
|
-
export declare function redirect(path: string,
|
|
97
|
+
export declare function redirect(path: string, statusOrOptions?: number | RedirectOptions): never;
|
|
72
98
|
/**
|
|
73
99
|
* Permanent redirect to a relative path. Shorthand for `redirect(path, 308)`.
|
|
74
100
|
*
|
|
@@ -76,8 +102,9 @@ export declare function redirect(path: string, status?: number): never;
|
|
|
76
102
|
* will replay POST requests to the new location. This matches Next.js behavior.
|
|
77
103
|
*
|
|
78
104
|
* @param path - Relative path (e.g. '/new-page', '/dashboard')
|
|
105
|
+
* @param options - Optional redirect options (e.g. preserveSearchParams).
|
|
79
106
|
*/
|
|
80
|
-
export declare function permanentRedirect(path: string): never;
|
|
107
|
+
export declare function permanentRedirect(path: string, options?: Omit<RedirectOptions, 'status'>): never;
|
|
81
108
|
/**
|
|
82
109
|
* Redirect to an external URL. The hostname must be in the provided allow-list.
|
|
83
110
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/server/primitives.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/server/primitives.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,6 +56,45 @@ export declare function cookies(): RequestCookies;
|
|
|
56
56
|
* Throws if called outside a request context.
|
|
57
57
|
*/
|
|
58
58
|
export declare function rawSearchParams(): Promise<URLSearchParams>;
|
|
59
|
+
/**
|
|
60
|
+
* Returns a Promise resolving to the current request's coerced segment params.
|
|
61
|
+
*
|
|
62
|
+
* Segment params are set by the pipeline after route matching and param
|
|
63
|
+
* coercion (via params.ts codecs). When no params.ts exists, values are
|
|
64
|
+
* raw strings. When codecs are defined, values are already coerced
|
|
65
|
+
* (e.g., `id` is a `number` if `defineSegmentParams({ id: z.coerce.number() })`).
|
|
66
|
+
*
|
|
67
|
+
* This is the primary way page and layout components access route params:
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { rawSegmentParams } from '@timber-js/app/server'
|
|
71
|
+
*
|
|
72
|
+
* export default async function Page() {
|
|
73
|
+
* const { slug } = await rawSegmentParams()
|
|
74
|
+
* // ...
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* Throws if called outside a request context.
|
|
79
|
+
*/
|
|
80
|
+
export declare function rawSegmentParams(): Promise<Record<string, string | string[]>>;
|
|
81
|
+
/**
|
|
82
|
+
* Set the segment params promise on the current request context.
|
|
83
|
+
* Called by the pipeline after route matching and param coercion.
|
|
84
|
+
*
|
|
85
|
+
* @internal — framework use only
|
|
86
|
+
*/
|
|
87
|
+
export declare function setSegmentParams(params: Record<string, string | string[]>): void;
|
|
88
|
+
/**
|
|
89
|
+
* Returns the raw search string from the current request URL (e.g. "?foo=bar").
|
|
90
|
+
* Synchronous — safe for use in `redirect()` which throws synchronously.
|
|
91
|
+
*
|
|
92
|
+
* Returns empty string if called outside a request context (non-throwing for
|
|
93
|
+
* use in redirect's optional preserveSearchParams path).
|
|
94
|
+
*
|
|
95
|
+
* @internal — used by redirect() for preserveSearchParams support.
|
|
96
|
+
*/
|
|
97
|
+
export declare function getRequestSearchString(): string;
|
|
59
98
|
/**
|
|
60
99
|
* Read-only Headers interface. The standard Headers class is mutable;
|
|
61
100
|
* this type narrows it to read-only methods. The underlying object is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,iBAAiB,EAA8C,MAAM,mBAAmB,CAAC;AAIlG,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAQ7B;;;;;GAKG;AACH,wBAAgB,OAAO,IAAI,eAAe,CASzC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,IAAI,cAAc,CA0FxC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CAS1D;AAID;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,OAAO,EACP,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,MAAM,CAAC,QAAQ,CACnF,CAAC;AAEF,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AASD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACtC,gCAAgC;IAChC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,4DAA4D;IAC5D,MAAM,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAChE,2DAA2D;IAC3D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC;IAC7E,8DAA8D;IAC9D,KAAK,IAAI,IAAI,CAAC;IACd,mDAAmD;IACnD,QAAQ,IAAI,MAAM,CAAC;CACpB;AAID;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAK9D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAM7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAKzD;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAID,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAED,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,2CAA2C;IAC3C,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,wDAAwD;IACxD,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,qCAAqC;IACrC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,MAAM,EAAE,UAAU,GAAG,cAAc;aACnC,gBAAgB,EAAE,oBAAoB,EAAE;aACxC,QAAQ,EAAE,mBAAmB,EAAE;gBAF/B,MAAM,EAAE,UAAU,GAAG,cAAc,EACnC,gBAAgB,EAAE,oBAAoB,EAAE,EACxC,QAAQ,EAAE,mBAAmB,EAAE;CAIlD;
|
|
1
|
+
{"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAK9D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAM7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAKzD;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAID,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAED,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,2CAA2C;IAC3C,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,wDAAwD;IACxD,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,qCAAqC;IACrC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,MAAM,EAAE,UAAU,GAAG,cAAc;aACnC,gBAAgB,EAAE,oBAAoB,EAAE;aACxC,QAAQ,EAAE,mBAAmB,EAAE;gBAF/B,MAAM,EAAE,UAAU,GAAG,cAAc,EACnC,gBAAgB,EAAE,oBAAoB,EAAE,EACxC,QAAQ,EAAE,mBAAmB,EAAE;CAIlD;AA8DD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,YAAY,CAAC,EAAE,mBAAmB,EAClC,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GACnC,OAAO,CAAC,kBAAkB,CAAC,CA6R7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/error-renderer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"error-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/error-renderer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAGxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAM7D;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,gBAAgB,EAAE,WAAW,EAAE,EAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,eAAe,EAAE,qBAAqB,GACrC,OAAO,CAAC,QAAQ,CAAC,CA6FnB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,mBAAmB,EAChC,eAAe,EAAE,OAAO,EACxB,eAAe,EAAE,qBAAqB,GACrC,OAAO,CAAC,QAAQ,CAAC,CA6BnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/ssr-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"ssr-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/ssr-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAIxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAYrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,UAAU,gBAAgB;IACxB,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,KAAK,EAAE,UAAU,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,qBAAqB,CAAC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4LjF"}
|
|
@@ -29,6 +29,6 @@ type CreateElementFn = (...args: unknown[]) => React.ReactElement;
|
|
|
29
29
|
* 2. Layouts from each segment in the slot's matched chain
|
|
30
30
|
* 3. SlotAccessGate if the slot root has access.ts
|
|
31
31
|
*/
|
|
32
|
-
export declare function resolveSlotElement(slotNode: ManifestSegmentNode, match: RouteMatch,
|
|
32
|
+
export declare function resolveSlotElement(slotNode: ManifestSegmentNode, match: RouteMatch, h: CreateElementFn, interception?: InterceptionContext): Promise<React.ReactElement | null>;
|
|
33
33
|
export {};
|
|
34
34
|
//# sourceMappingURL=slot-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot-resolver.d.ts","sourceRoot":"","sources":["../../src/server/slot-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAErE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,KAAK,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"slot-resolver.d.ts","sourceRoot":"","sources":["../../src/server/slot-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAErE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,KAAK,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,YAAY,CAAC;AAkHlE;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,eAAe,EAClB,YAAY,CAAC,EAAE,mBAAmB,GACjC,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CA0EpC"}
|
|
@@ -32,8 +32,13 @@ export type SlotElements = Map<string, ReactElement>;
|
|
|
32
32
|
export interface TreeBuilderConfig {
|
|
33
33
|
/** The matched segment chain from root to leaf. */
|
|
34
34
|
segments: SegmentNode[];
|
|
35
|
-
/**
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Route params extracted by the matcher (catch-all segments produce string[]).
|
|
37
|
+
* @deprecated Params are now accessed via rawSegmentParams() from ALS.
|
|
38
|
+
* This field is kept for backward compatibility but is no longer used
|
|
39
|
+
* by the tree builder itself.
|
|
40
|
+
*/
|
|
41
|
+
params?: Record<string, string | string[]>;
|
|
37
42
|
/** Loads a route file's module. */
|
|
38
43
|
loadModule: ModuleLoader;
|
|
39
44
|
/** React.createElement or equivalent. */
|
|
@@ -61,7 +66,6 @@ export interface AccessGateProps {
|
|
|
61
66
|
accessFn: (ctx: {
|
|
62
67
|
params: Record<string, string | string[]>;
|
|
63
68
|
}) => unknown;
|
|
64
|
-
params: Record<string, string | string[]>;
|
|
65
69
|
/** Segment name for dev logging (e.g. "authenticated", "dashboard"). */
|
|
66
70
|
segmentName?: string;
|
|
67
71
|
/**
|
|
@@ -85,7 +89,6 @@ export interface SlotAccessGateProps {
|
|
|
85
89
|
accessFn: (ctx: {
|
|
86
90
|
params: Record<string, string | string[]>;
|
|
87
91
|
}) => unknown;
|
|
88
|
-
params: Record<string, string | string[]>;
|
|
89
92
|
/** The denied.tsx component (not a pre-built element). null if no denied.tsx exists. */
|
|
90
93
|
DeniedComponent: ((...args: unknown[]) => unknown) | null;
|
|
91
94
|
/** Slot directory name without @ prefix (e.g. "admin", "sidebar"). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-builder.d.ts","sourceRoot":"","sources":["../../src/server/tree-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIjE,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,SAAS,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAErF,gFAAgF;AAEhF,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC;AAE/B,oFAAoF;AACpF,MAAM,MAAM,aAAa,GAAG,CAC1B,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACrC,GAAG,QAAQ,EAAE,OAAO,EAAE,KACnB,YAAY,CAAC;AAElB;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAErD,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB
|
|
1
|
+
{"version":3,"file":"tree-builder.d.ts","sourceRoot":"","sources":["../../src/server/tree-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility for merging preserved search params into a target URL.
|
|
3
|
+
*
|
|
4
|
+
* Used by both <Link> (client) and redirect() (server). Extracted to a shared
|
|
5
|
+
* module to avoid importing client code ('use client') from server modules.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Merge preserved search params from the current URL into a target href.
|
|
9
|
+
*
|
|
10
|
+
* When `preserve` is `true`, all current search params are merged.
|
|
11
|
+
* When `preserve` is a `string[]`, only the named params are merged.
|
|
12
|
+
*
|
|
13
|
+
* The target href's own search params take precedence — preserved params
|
|
14
|
+
* are only added if the target doesn't already define them.
|
|
15
|
+
*
|
|
16
|
+
* @param targetHref - The resolved target href (may already contain query string)
|
|
17
|
+
* @param currentSearch - The current URL's search string (e.g. "?private=access&page=2")
|
|
18
|
+
* @param preserve - `true` to preserve all, or `string[]` to preserve specific params
|
|
19
|
+
* @returns The target href with preserved search params merged in
|
|
20
|
+
*/
|
|
21
|
+
export declare function mergePreservedSearchParams(targetHref: string, currentSearch: string, preserve: true | string[]): string;
|
|
22
|
+
//# sourceMappingURL=merge-search-params.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-search-params.d.ts","sourceRoot":"","sources":["../../src/shared/merge-search-params.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,IAAI,GAAG,MAAM,EAAE,GACxB,MAAM,CAsBR"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timber-js/app",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.37",
|
|
4
4
|
"description": "Vite-native React framework built for Servers and Serverless Platforms — correct HTTP semantics, real status codes, pages that work without JavaScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare-workers",
|
|
@@ -83,11 +83,6 @@
|
|
|
83
83
|
"publishConfig": {
|
|
84
84
|
"access": "public"
|
|
85
85
|
},
|
|
86
|
-
"scripts": {
|
|
87
|
-
"build": "vite build --config vite.lib.config.ts && tsc --emitDeclarationOnly --project tsconfig.json --outDir dist",
|
|
88
|
-
"typecheck": "tsgo --noEmit",
|
|
89
|
-
"prepublishOnly": "pnpm run build"
|
|
90
|
-
},
|
|
91
86
|
"dependencies": {
|
|
92
87
|
"@opentelemetry/api": "^1.9.1",
|
|
93
88
|
"@opentelemetry/context-async-hooks": "^2.6.1",
|
|
@@ -126,5 +121,9 @@
|
|
|
126
121
|
},
|
|
127
122
|
"engines": {
|
|
128
123
|
"node": ">=22.12.0"
|
|
124
|
+
},
|
|
125
|
+
"scripts": {
|
|
126
|
+
"build": "vite build --config vite.lib.config.ts && tsc --emitDeclarationOnly --project tsconfig.json --outDir dist",
|
|
127
|
+
"typecheck": "tsgo --noEmit"
|
|
129
128
|
}
|
|
130
|
-
}
|
|
129
|
+
}
|
package/src/cli.ts
CHANGED
|
File without changes
|
|
@@ -232,18 +232,9 @@ function bootstrap(runtimeConfig: typeof config): void {
|
|
|
232
232
|
// For subsequent navigations, it's fetched from the server.
|
|
233
233
|
type FlightSegment = [isBootstrap: 0] | [isData: 1, data: string];
|
|
234
234
|
|
|
235
|
-
//
|
|
236
|
-
//
|
|
237
|
-
//
|
|
238
|
-
// is injected by the flight injector AFTER Suspense resolution scripts.
|
|
239
|
-
// If the module import resolves before those scripts execute, __timber_f
|
|
240
|
-
// will be undefined.
|
|
241
|
-
//
|
|
242
|
-
// Fix: if __timber_f isn't available yet, pre-initialize it so the RSC
|
|
243
|
-
// bootstrap script's `(self.__timber_f=self.__timber_f||[]).push([0])` finds
|
|
244
|
-
// our array and pushes into it. This avoids a race condition that causes
|
|
245
|
-
// the browser entry to fall through to createRoot() (no hydration) on
|
|
246
|
-
// streaming pages.
|
|
235
|
+
// __timber_f is initialized in <head> via flightInitScript() (see
|
|
236
|
+
// flight-scripts.ts). It should always exist by the time this module
|
|
237
|
+
// runs. Defensive fallback kept for safety.
|
|
247
238
|
if (!(self as unknown as Record<string, unknown>).__timber_f) {
|
|
248
239
|
(self as unknown as Record<string, FlightSegment[]>).__timber_f = [];
|
|
249
240
|
}
|
package/src/client/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type { JsonSerializable, RenderErrorDigest } from './types';
|
|
|
5
5
|
|
|
6
6
|
// Navigation
|
|
7
7
|
export { Link, interpolateParams, resolveHref, validateLinkHref, buildLinkProps } from './link';
|
|
8
|
+
export { mergePreservedSearchParams } from '#/shared/merge-search-params.js';
|
|
8
9
|
export type { LinkProps, LinkPropsWithHref, LinkPropsWithParams } from './link';
|
|
9
10
|
export type { OnNavigateHandler, OnNavigateEvent } from './link';
|
|
10
11
|
export { createRouter } from './router';
|
package/src/client/link.tsx
CHANGED
|
@@ -22,6 +22,24 @@ import type { AnchorHTMLAttributes, ReactNode, MouseEvent as ReactMouseEvent } f
|
|
|
22
22
|
import type { SearchParamsDefinition } from '#/search-params/define.js';
|
|
23
23
|
import { LinkStatusProvider } from './link-status-provider.js';
|
|
24
24
|
import { getRouterOrNull } from './router-ref.js';
|
|
25
|
+
import { getSsrData } from './ssr-data.js';
|
|
26
|
+
import { mergePreservedSearchParams } from '#/shared/merge-search-params.js';
|
|
27
|
+
|
|
28
|
+
// ─── Current Search Params ────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Read the current URL's search string without requiring a React hook.
|
|
32
|
+
* On the client, reads window.location.search. During SSR, reads from
|
|
33
|
+
* the request context (getSsrData). Returns empty string if unavailable.
|
|
34
|
+
*/
|
|
35
|
+
function getCurrentSearch(): string {
|
|
36
|
+
if (typeof window !== 'undefined') return window.location.search;
|
|
37
|
+
const data = getSsrData();
|
|
38
|
+
if (!data) return '';
|
|
39
|
+
const sp = new URLSearchParams(data.searchParams);
|
|
40
|
+
const str = sp.toString();
|
|
41
|
+
return str ? `?${str}` : '';
|
|
42
|
+
}
|
|
25
43
|
|
|
26
44
|
// ─── Types ───────────────────────────────────────────────────────
|
|
27
45
|
|
|
@@ -42,6 +60,20 @@ interface LinkBaseProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'h
|
|
|
42
60
|
* Set to false for tabbed interfaces where content changes within a fixed layout.
|
|
43
61
|
*/
|
|
44
62
|
scroll?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Preserve search params from the current URL across navigation.
|
|
65
|
+
*
|
|
66
|
+
* - `true` — preserve ALL current search params (target params take precedence)
|
|
67
|
+
* - `string[]` — preserve only the named params (e.g. `['private', 'token']`)
|
|
68
|
+
*
|
|
69
|
+
* Useful for route-group gating where a search param (e.g. `?private=access`)
|
|
70
|
+
* must persist across internal navigations. The target href's own search params
|
|
71
|
+
* always take precedence over preserved ones.
|
|
72
|
+
*
|
|
73
|
+
* During SSR, reads search params from the request context. On the client,
|
|
74
|
+
* reads from the current URL and updates reactively when the URL changes.
|
|
75
|
+
*/
|
|
76
|
+
preserveSearchParams?: true | string[];
|
|
45
77
|
/**
|
|
46
78
|
* Called before client-side navigation commits. Call `e.preventDefault()`
|
|
47
79
|
* to cancel the default navigation — the caller is then responsible for
|
|
@@ -312,13 +344,25 @@ export function Link({
|
|
|
312
344
|
scroll,
|
|
313
345
|
segmentParams,
|
|
314
346
|
searchParams,
|
|
347
|
+
preserveSearchParams,
|
|
315
348
|
onNavigate,
|
|
316
349
|
onClick: userOnClick,
|
|
317
350
|
onMouseEnter: userOnMouseEnter,
|
|
318
351
|
children,
|
|
319
352
|
...rest
|
|
320
353
|
}: LinkProps) {
|
|
321
|
-
const { href:
|
|
354
|
+
const { href: baseHref } = buildLinkProps({ href, params: segmentParams, searchParams });
|
|
355
|
+
|
|
356
|
+
// Preserve search params from the current URL when requested.
|
|
357
|
+
// useSearchParams() works during both SSR (reads from request context)
|
|
358
|
+
// and on the client (reads from window.location, reactive to URL changes).
|
|
359
|
+
// We read current search params directly to avoid unconditional hook calls.
|
|
360
|
+
// On the client, window.location.search is always current; during SSR,
|
|
361
|
+
// getSsrData() provides the request's search params.
|
|
362
|
+
const resolvedHref = preserveSearchParams
|
|
363
|
+
? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
|
|
364
|
+
: baseHref;
|
|
365
|
+
|
|
322
366
|
const internal = isInternalHref(resolvedHref);
|
|
323
367
|
|
|
324
368
|
// ─── Click handler ───────────────────────────────────────────
|
|
@@ -351,7 +395,13 @@ export function Link({
|
|
|
351
395
|
|
|
352
396
|
event.preventDefault();
|
|
353
397
|
const shouldScroll = scroll !== false;
|
|
354
|
-
|
|
398
|
+
|
|
399
|
+
// Re-merge preserved search params at click time to pick up any
|
|
400
|
+
// URL changes since render (e.g. from other navigations or pushState).
|
|
401
|
+
const navHref = preserveSearchParams
|
|
402
|
+
? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
|
|
403
|
+
: resolvedHref;
|
|
404
|
+
void router.navigate(navHref, { scroll: shouldScroll });
|
|
355
405
|
}
|
|
356
406
|
: userOnClick; // External links — just pass through user's onClick
|
|
357
407
|
|
|
@@ -362,7 +412,11 @@ export function Link({
|
|
|
362
412
|
userOnMouseEnter?.(event);
|
|
363
413
|
const router = getRouterOrNull();
|
|
364
414
|
if (router) {
|
|
365
|
-
|
|
415
|
+
// Re-merge preserved search params at hover time for fresh prefetch URL
|
|
416
|
+
const prefetchHref = preserveSearchParams
|
|
417
|
+
? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
|
|
418
|
+
: resolvedHref;
|
|
419
|
+
router.prefetch(prefetchHref);
|
|
366
420
|
}
|
|
367
421
|
}
|
|
368
422
|
: userOnMouseEnter;
|
|
@@ -17,6 +17,7 @@ import { DenySignal, RedirectSignal } from './primitives.js';
|
|
|
17
17
|
import type { AccessGateProps, SlotAccessGateProps, ReactElement } from './tree-builder.js';
|
|
18
18
|
import { withSpan, setSpanAttribute } from './tracing.js';
|
|
19
19
|
import { isDebug } from './debug.js';
|
|
20
|
+
import { rawSegmentParams } from './request-context.js';
|
|
20
21
|
|
|
21
22
|
// ─── AccessGate ─────────────────────────────────────────────────────────────
|
|
22
23
|
|
|
@@ -35,7 +36,7 @@ import { isDebug } from './debug.js';
|
|
|
35
36
|
* gets the same data by calling the same cached functions (React.cache dedup).
|
|
36
37
|
*/
|
|
37
38
|
export function AccessGate(props: AccessGateProps): ReactElement | Promise<ReactElement> {
|
|
38
|
-
const { accessFn,
|
|
39
|
+
const { accessFn, segmentName, verdict, children } = props;
|
|
39
40
|
|
|
40
41
|
// Fast path: replay pre-computed verdict from the pre-render pass.
|
|
41
42
|
// This is synchronous — Suspense boundaries cannot interfere with the
|
|
@@ -52,7 +53,7 @@ export function AccessGate(props: AccessGateProps): ReactElement | Promise<React
|
|
|
52
53
|
|
|
53
54
|
// Fallback: call accessFn directly (used by tree-builder.ts which
|
|
54
55
|
// doesn't run a pre-render pass, and for backward compat).
|
|
55
|
-
return accessGateFallback(accessFn,
|
|
56
|
+
return accessGateFallback(accessFn, segmentName, children);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
/**
|
|
@@ -61,12 +62,12 @@ export function AccessGate(props: AccessGateProps): ReactElement | Promise<React
|
|
|
61
62
|
*/
|
|
62
63
|
async function accessGateFallback(
|
|
63
64
|
accessFn: AccessGateProps['accessFn'],
|
|
64
|
-
params: AccessGateProps['params'],
|
|
65
65
|
segmentName: AccessGateProps['segmentName'],
|
|
66
66
|
children: ReactElement
|
|
67
67
|
): Promise<ReactElement> {
|
|
68
68
|
await withSpan('timber.access', { 'timber.segment': segmentName ?? 'unknown' }, async () => {
|
|
69
69
|
try {
|
|
70
|
+
const params = await rawSegmentParams();
|
|
70
71
|
await accessFn({ params });
|
|
71
72
|
await setSpanAttribute('timber.result', 'pass');
|
|
72
73
|
} catch (error: unknown) {
|
|
@@ -103,10 +104,10 @@ async function accessGateFallback(
|
|
|
103
104
|
* slot doesn't make architectural sense.
|
|
104
105
|
*/
|
|
105
106
|
export async function SlotAccessGate(props: SlotAccessGateProps): Promise<ReactElement> {
|
|
106
|
-
const { accessFn,
|
|
107
|
-
props;
|
|
107
|
+
const { accessFn, DeniedComponent, slotName, createElement, defaultFallback, children } = props;
|
|
108
108
|
|
|
109
109
|
try {
|
|
110
|
+
const params = await rawSegmentParams();
|
|
110
111
|
await accessFn({ params });
|
|
111
112
|
} catch (error: unknown) {
|
|
112
113
|
// DenySignal → graceful degradation (denied.tsx → default.tsx → null)
|
|
@@ -44,6 +44,20 @@ export interface RequestContextStore {
|
|
|
44
44
|
* call `.parse(searchParams())`.
|
|
45
45
|
*/
|
|
46
46
|
searchParamsPromise: Promise<URLSearchParams>;
|
|
47
|
+
/**
|
|
48
|
+
* Raw search string from the request URL (e.g. "?foo=bar&baz=1").
|
|
49
|
+
* Available synchronously for use in `redirect()` with `preserveSearchParams`.
|
|
50
|
+
*/
|
|
51
|
+
searchString: string;
|
|
52
|
+
/**
|
|
53
|
+
* Promise resolving to the coerced segment params for the current request.
|
|
54
|
+
* Set by the pipeline after route matching and param coercion, before
|
|
55
|
+
* middleware and rendering. Pages and layouts read params via
|
|
56
|
+
* `rawSegmentParams()` instead of receiving them as a prop.
|
|
57
|
+
*
|
|
58
|
+
* See design/07-routing.md §"params.ts — Convention File for Typed Params"
|
|
59
|
+
*/
|
|
60
|
+
segmentParamsPromise?: Promise<Record<string, string | string[]>>;
|
|
47
61
|
/** Outgoing Set-Cookie entries (name → serialized value + options). Last write wins. */
|
|
48
62
|
cookieJar: Map<string, CookieEntry>;
|
|
49
63
|
/** Whether the response has flushed (headers committed). */
|
|
@@ -26,6 +26,7 @@ import { resolveManifestStatusFile } from './manifest-status-resolver.js';
|
|
|
26
26
|
import type { ManifestSegmentNode } from './route-matcher.js';
|
|
27
27
|
import type { RouteMatch } from './pipeline.js';
|
|
28
28
|
import type { NavContext } from './ssr-entry.js';
|
|
29
|
+
import { flightInitScript } from './flight-scripts.js';
|
|
29
30
|
import type { ClientBootstrapConfig } from './html-injectors.js';
|
|
30
31
|
import type { Metadata } from './types.js';
|
|
31
32
|
|
|
@@ -178,7 +179,7 @@ export async function renderDenyPage(
|
|
|
178
179
|
searchParams: Object.fromEntries(new URL(req.url).searchParams),
|
|
179
180
|
statusCode: deny.status,
|
|
180
181
|
responseHeaders,
|
|
181
|
-
headHtml,
|
|
182
|
+
headHtml: headHtml + flightInitScript(),
|
|
182
183
|
bootstrapScriptContent: clientBootstrap.bootstrapScriptContent,
|
|
183
184
|
rscStream: inlineStream,
|
|
184
185
|
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Flight data script generation.
|
|
3
|
+
*
|
|
4
|
+
* Both html-injectors.ts (Web Streams / dev) and node-stream-transforms.ts
|
|
5
|
+
* (Node streams / production) use this module to generate inline `<script>`
|
|
6
|
+
* tags for RSC Flight data injection.
|
|
7
|
+
*
|
|
8
|
+
* The init script goes in `<head>` as part of the HTML shell (guaranteed
|
|
9
|
+
* to execute before any streaming chunk scripts). Push scripts are emitted
|
|
10
|
+
* as RSC chunks arrive during streaming.
|
|
11
|
+
*
|
|
12
|
+
* See design/02-rendering-pipeline.md, LOCAL-415
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// ─── JSON Escaping ────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Escape a JSON string for safe embedding inside an HTML `<script>` tag.
|
|
19
|
+
*
|
|
20
|
+
* Prevents XSS via `</script>` injection and handles Unicode line/paragraph
|
|
21
|
+
* separators that are valid JSON but invalid in JS string literals (pre-ES2019).
|
|
22
|
+
*/
|
|
23
|
+
export function htmlEscapeJsonString(str: string): string {
|
|
24
|
+
return str
|
|
25
|
+
.replace(/</g, '\\u003c')
|
|
26
|
+
.replace(/>/g, '\\u003e')
|
|
27
|
+
.replace(/\u2028/g, '\\u2028')
|
|
28
|
+
.replace(/\u2029/g, '\\u2029');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ─── Script Generation ────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
/** The global variable name used for Flight data on the client. */
|
|
34
|
+
const FLIGHT_VAR = 'self.__timber_f';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Generate the init script that creates the Flight data array.
|
|
38
|
+
*
|
|
39
|
+
* This MUST be included in `<head>` (via headHtml) so it executes before
|
|
40
|
+
* any streaming chunk scripts arrive in `<body>`. The array is created
|
|
41
|
+
* unconditionally — no `||[]` guard needed in push scripts.
|
|
42
|
+
*
|
|
43
|
+
* Also emits the bootstrap signal [0] which tells the client that
|
|
44
|
+
* Flight data is active for this page.
|
|
45
|
+
*/
|
|
46
|
+
export function flightInitScript(): string {
|
|
47
|
+
return `<script>${FLIGHT_VAR}=[${htmlEscapeJsonString(JSON.stringify([0]))}]</script>`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Generate a push script for a Flight data chunk.
|
|
52
|
+
*
|
|
53
|
+
* The init script is guaranteed to have run (it's in `<head>`), so
|
|
54
|
+
* `self.__timber_f` always exists — no `||[]` guard needed.
|
|
55
|
+
*/
|
|
56
|
+
export function flightChunkScript(data: string): string {
|
|
57
|
+
const escaped = htmlEscapeJsonString(JSON.stringify([1, data]));
|
|
58
|
+
return `<script>${FLIGHT_VAR}.push(${escaped})</script>`;
|
|
59
|
+
}
|