@timber-js/app 0.2.0-alpha.36 → 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/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/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/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/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/index.ts +3 -0
- 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/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":"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":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQnD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAS,GAAG,MAAM,GAAG,IAAI,CA8DhF;AAsBD;;;GAGG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,CAAC;gBAEhC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB;IAOnD;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAqBnC;CACF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAC,MAAM,GAAE,MAAY,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,KAAK,CASzE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,IAAI,KAAK,CAEhC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAIX;;;GAGG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAM7C;AAKD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,KAAK,CAuBxF;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG,KAAK,CAEhG;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,MAAM,GAAE,MAAY,GAAG,KAAK,CAoB9F;AAID;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAChC,KAAK,SAAS,MAAM,GAAG,MAAM,EAC7B,KAAK,SAAS,gBAAgB,GAAG,gBAAgB;IAEjD,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,KAAK,CAAC;CACb;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,WAAW,CACtB,KAAK,SAAS,MAAM,GAAG,MAAM,EAC7B,KAAK,SAAS,gBAAgB,GAAG,gBAAgB,CACjD,SAAQ,KAAK;IACb,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAcpE;AAID,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7C;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAqBrF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAID;;;;;;;;;;GAUG;AACH,qBAAa,cAAe,SAAQ,KAAK;aAGrB,KAAK,EAAE,OAAO;gBAD9B,OAAO,EAAE,MAAM,EACC,KAAK,EAAE,OAAO;CAKjC"}
|
|
@@ -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"}
|
|
@@ -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
|
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). */
|
package/src/server/index.ts
CHANGED
|
@@ -13,6 +13,8 @@ export {
|
|
|
13
13
|
headers,
|
|
14
14
|
cookies,
|
|
15
15
|
rawSearchParams,
|
|
16
|
+
rawSegmentParams,
|
|
17
|
+
setSegmentParams,
|
|
16
18
|
runWithRequestContext,
|
|
17
19
|
setMutableCookieContext,
|
|
18
20
|
markResponseFlushed,
|
|
@@ -32,6 +34,7 @@ export {
|
|
|
32
34
|
waitUntil,
|
|
33
35
|
DenySignal,
|
|
34
36
|
RedirectSignal,
|
|
37
|
+
type RedirectOptions,
|
|
35
38
|
} from './primitives';
|
|
36
39
|
export type { RenderErrorDigest, WaitUntilAdapter } from './primitives';
|
|
37
40
|
export type { JsonSerializable } from './types';
|
package/src/server/pipeline.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
setMutableCookieContext,
|
|
22
22
|
getSetCookieHeaders,
|
|
23
23
|
markResponseFlushed,
|
|
24
|
+
setSegmentParams,
|
|
24
25
|
} from './request-context.js';
|
|
25
26
|
import {
|
|
26
27
|
generateTraceId,
|
|
@@ -484,6 +485,11 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
|
|
|
484
485
|
throw error;
|
|
485
486
|
}
|
|
486
487
|
|
|
488
|
+
// Store coerced segment params in ALS so components can access them
|
|
489
|
+
// via rawSegmentParams() instead of receiving them as a prop.
|
|
490
|
+
// See design/07-routing.md §"params.ts — Convention File for Typed Params"
|
|
491
|
+
setSegmentParams(match.params);
|
|
492
|
+
|
|
487
493
|
// Stage 3: Leaf middleware.ts (only the leaf route's middleware runs)
|
|
488
494
|
if (match.middleware) {
|
|
489
495
|
const ctx: MiddlewareContext = {
|
package/src/server/primitives.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
import type { JsonSerializable } from './types.js';
|
|
7
7
|
import { getWaitUntil as _getWaitUntil } from './waituntil-bridge.js';
|
|
8
8
|
import { isDebug } from './debug.js';
|
|
9
|
+
import { getRequestSearchString } from './request-context.js';
|
|
10
|
+
import { mergePreservedSearchParams } from '#/shared/merge-search-params.js';
|
|
9
11
|
|
|
10
12
|
// ─── Dev-mode validation ────────────────────────────────────────────────────
|
|
11
13
|
|
|
@@ -209,14 +211,46 @@ export class RedirectSignal extends Error {
|
|
|
209
211
|
/** Pattern matching absolute URLs: http(s):// or protocol-relative // */
|
|
210
212
|
const ABSOLUTE_URL_RE = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/)/;
|
|
211
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Options for redirect() — alternative to passing a bare status code.
|
|
216
|
+
*/
|
|
217
|
+
export interface RedirectOptions {
|
|
218
|
+
/** HTTP redirect status code (3xx). Defaults to 302. */
|
|
219
|
+
status?: number;
|
|
220
|
+
/**
|
|
221
|
+
* Preserve search params from the current request URL on the redirect target.
|
|
222
|
+
*
|
|
223
|
+
* - `true` — preserve ALL current search params (target params take precedence)
|
|
224
|
+
* - `string[]` — preserve only the named params (e.g. `['private', 'token']`)
|
|
225
|
+
*
|
|
226
|
+
* Target path's own query params always take precedence over preserved ones.
|
|
227
|
+
*/
|
|
228
|
+
preserveSearchParams?: true | string[];
|
|
229
|
+
}
|
|
230
|
+
|
|
212
231
|
/**
|
|
213
232
|
* Redirect to a relative path. Rejects absolute and protocol-relative URLs.
|
|
214
233
|
* Use `redirectExternal()` for external redirects with an allow-list.
|
|
215
234
|
*
|
|
216
235
|
* @param path - Relative path (e.g. '/login', 'settings', '/login?returnTo=/dash')
|
|
217
|
-
* @param
|
|
236
|
+
* @param statusOrOptions - HTTP status code (3xx, default 302) or options object.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* // Simple redirect
|
|
240
|
+
* redirect('/login');
|
|
241
|
+
*
|
|
242
|
+
* // With status code
|
|
243
|
+
* redirect('/login', 301);
|
|
244
|
+
*
|
|
245
|
+
* // With preserved search params
|
|
246
|
+
* redirect(`/docs/${version}/${slug}`, { preserveSearchParams: ['foo'] });
|
|
218
247
|
*/
|
|
219
|
-
export function redirect(path: string,
|
|
248
|
+
export function redirect(path: string, statusOrOptions?: number | RedirectOptions): never {
|
|
249
|
+
const status =
|
|
250
|
+
typeof statusOrOptions === 'number' ? statusOrOptions : (statusOrOptions?.status ?? 302);
|
|
251
|
+
const preserveSearchParams =
|
|
252
|
+
typeof statusOrOptions === 'object' ? statusOrOptions.preserveSearchParams : undefined;
|
|
253
|
+
|
|
220
254
|
if (status < 300 || status > 399) {
|
|
221
255
|
throw new Error(`redirect() requires a 3xx status code, got ${status}.`);
|
|
222
256
|
}
|
|
@@ -226,7 +260,14 @@ export function redirect(path: string, status: number = 302): never {
|
|
|
226
260
|
'Use redirectExternal(url, allowList) for external redirects.'
|
|
227
261
|
);
|
|
228
262
|
}
|
|
229
|
-
|
|
263
|
+
|
|
264
|
+
let resolvedPath = path;
|
|
265
|
+
if (preserveSearchParams) {
|
|
266
|
+
const currentSearch = getRequestSearchString();
|
|
267
|
+
resolvedPath = mergePreservedSearchParams(path, currentSearch, preserveSearchParams);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
throw new RedirectSignal(resolvedPath, status);
|
|
230
271
|
}
|
|
231
272
|
|
|
232
273
|
/**
|
|
@@ -236,9 +277,10 @@ export function redirect(path: string, status: number = 302): never {
|
|
|
236
277
|
* will replay POST requests to the new location. This matches Next.js behavior.
|
|
237
278
|
*
|
|
238
279
|
* @param path - Relative path (e.g. '/new-page', '/dashboard')
|
|
280
|
+
* @param options - Optional redirect options (e.g. preserveSearchParams).
|
|
239
281
|
*/
|
|
240
|
-
export function permanentRedirect(path: string): never {
|
|
241
|
-
redirect(path, 308);
|
|
282
|
+
export function permanentRedirect(path: string, options?: Omit<RedirectOptions, 'status'>): never {
|
|
283
|
+
redirect(path, { status: 308, ...options });
|
|
242
284
|
}
|
|
243
285
|
|
|
244
286
|
/**
|