@timber-js/app 0.2.0-alpha.184 → 0.2.0-alpha.185
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/{cli-schema-sync-D3naS3eH.js → cli-schema-sync-BTWEKJXo.js} +1 -21
- package/dist/_chunks/cli-schema-sync-BTWEKJXo.js.map +1 -0
- package/dist/_chunks/logger-AWfuX-KJ.js.map +1 -1
- package/dist/_chunks/plugin-context---kTF5v8.js.map +1 -1
- package/dist/_chunks/segment-classify-Byy425ng.js.map +1 -1
- package/dist/_chunks/{walkers-BtTlKviE.js → walkers-_6zKFlch.js} +2 -2
- package/dist/_chunks/{walkers-BtTlKviE.js.map → walkers-_6zKFlch.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/internal.js +36 -28
- package/dist/client/internal.js.map +1 -1
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +11 -1
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/index.js +25 -15
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +2 -1
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +19 -6
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/index.js +2 -2
- package/dist/routing/manifest-codegen.d.ts.map +1 -1
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/types.d.ts +1 -3
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/server/deny-boundary.d.ts +4 -7
- package/dist/server/deny-boundary.d.ts.map +1 -1
- package/dist/server/internal.js +135 -161
- package/dist/server/internal.js.map +1 -1
- package/dist/server/prebuilt-builder.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +0 -12
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/sitemap-generator.d.ts.map +1 -1
- package/dist/server/static-generator.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +3 -10
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +8 -19
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +0 -1
- package/dist/shims/navigation.d.ts.map +1 -1
- package/docs/learn/11-error-handling.mdx +2 -3
- package/package.json +1 -1
- package/src/client/router.ts +24 -7
- package/src/client/rsc-fetch.ts +37 -46
- package/src/plugin-context.ts +2 -1
- package/src/plugins/routing.ts +1 -1
- package/src/plugins/static-build.ts +47 -19
- package/src/routing/manifest-codegen.ts +1 -6
- package/src/routing/scanner.ts +0 -24
- package/src/routing/types.ts +1 -3
- package/src/server/deny-boundary.ts +5 -31
- package/src/server/deny-renderer.ts +2 -2
- package/src/server/pipeline-outcome.ts +1 -1
- package/src/server/prebuilt-builder.ts +1 -7
- package/src/server/primitives.ts +0 -18
- package/src/server/rsc-entry/render-route.ts +3 -3
- package/src/server/sitemap-generator.ts +1 -7
- package/src/server/static-generator.ts +2 -18
- package/src/server/status-code-resolver.ts +4 -47
- package/src/shims/navigation-client.ts +8 -26
- package/src/shims/navigation.ts +0 -4
- package/dist/_chunks/cli-schema-sync-D3naS3eH.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prebuilt-builder.d.ts","sourceRoot":"","sources":["../../src/server/prebuilt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAwBH,OAAO,KAAK,EAAgB,YAAY,EAAuB,MAAM,oBAAoB,CAAC;AAO1F,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,EAAE,UAAU,CAAC;IAClB,gGAAgG;IAChG,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,mEAAmE;IACnE,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,qEAAqE;IACrE,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3C;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1D;;;;OAIG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,mDAAmD;IACnD,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;
|
|
1
|
+
{"version":3,"file":"prebuilt-builder.d.ts","sourceRoot":"","sources":["../../src/server/prebuilt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAwBH,OAAO,KAAK,EAAgB,YAAY,EAAuB,MAAM,oBAAoB,CAAC;AAO1F,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,EAAE,UAAU,CAAC;IAClB,gGAAgG;IAChG,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,mEAAmE;IACnE,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,qEAAqE;IACrE,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3C;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1D;;;;OAIG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,mDAAmD;IACnD,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AA+UD;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CA2TzB"}
|
|
@@ -54,12 +54,6 @@ export interface DenyOptions {
|
|
|
54
54
|
* @param data - Optional JSON-serializable data (positional form only).
|
|
55
55
|
*/
|
|
56
56
|
export declare function deny(statusOrOptions?: number | DenyOptions, data?: JsonSerializable): never;
|
|
57
|
-
/**
|
|
58
|
-
* @deprecated Use `deny(404)` instead.
|
|
59
|
-
* Kept for internal use by the Next.js shim layer.
|
|
60
|
-
* @internal
|
|
61
|
-
*/
|
|
62
|
-
export declare function notFound(): never;
|
|
63
57
|
export { RedirectType } from '../shared/redirect-type.js';
|
|
64
58
|
/**
|
|
65
59
|
* Render-phase signal thrown by `redirect()` and `redirectExternal()`.
|
|
@@ -121,12 +115,6 @@ export interface RedirectOptions {
|
|
|
121
115
|
* redirect(`/docs/${version}/${slug}`, { preserveSearchParams: ['foo'] });
|
|
122
116
|
*/
|
|
123
117
|
export declare function redirect(path: string, statusOrOptions?: number | RedirectOptions): never;
|
|
124
|
-
/**
|
|
125
|
-
* @deprecated Use `redirect(path, { permanent: true })` instead.
|
|
126
|
-
* Kept for internal use by the Next.js shim layer.
|
|
127
|
-
* @internal
|
|
128
|
-
*/
|
|
129
|
-
export declare function permanentRedirect(path: string, options?: Omit<RedirectOptions, 'status'>): never;
|
|
130
118
|
/**
|
|
131
119
|
* Redirect to an external URL. The origin must be in the provided allow-list.
|
|
132
120
|
*
|
|
@@ -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;AAYnD;;;;;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;IAE5C,YAAY,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,EAKlD;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAqBnC;CACF;AAED,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wFAAwF;IACxF,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,IAAI,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,KAAK,CAiB3F;
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/server/primitives.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sitemap-generator.d.ts","sourceRoot":"","sources":["../../src/server/sitemap-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,SAAS,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE;IAClC,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvC,oCAAoC;AACpC,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAIpE,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAIvC;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,GAAG,YAAY,EAAE,CAI7F;AAwDD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EAAE,EACtB,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,YAAY,GACxB,OAAO,CAAC,YAAY,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"sitemap-generator.d.ts","sourceRoot":"","sources":["../../src/server/sitemap-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,SAAS,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE;IAClC,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvC,oCAAoC;AACpC,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAIpE,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAIvC;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,GAAG,YAAY,EAAE,CAI7F;AAwDD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EAAE,EACtB,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,YAAY,GACxB,OAAO,CAAC,YAAY,EAAE,CAAC,CA+CzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GACxC,MAAM,GAAG,IAAI,CA2Cf;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,YAAY,GACxB,OAAO,CAAC,aAAa,CAAC,CA+BxB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,OAAO,CAGlE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-generator.d.ts","sourceRoot":"","sources":["../../src/server/static-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAgB,MAAM,oBAAoB,CAAC;AAO1F,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,kCAAkC;IAClC,IAAI,EAAE,UAAU,CAAC;IACjB,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;CAC9B;AAED,qDAAqD;AACrD,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,sDAAsD;AACtD,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,yEAAyE;IACzE,SAAS,EAAE,mBAAmB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,+BAA+B;IAC/B,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAID,UAAU,SAAS;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAC9B,SAAS,GAAE,MAAkC,GAC5C,OAAO,CAAC;IAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAAC,MAAM,EAAE,qBAAqB,EAAE,CAAA;CAAE,CAAC,CA2GjE;
|
|
1
|
+
{"version":3,"file":"static-generator.d.ts","sourceRoot":"","sources":["../../src/server/static-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAgB,MAAM,oBAAoB,CAAC;AAO1F,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,kCAAkC;IAClC,IAAI,EAAE,UAAU,CAAC;IACjB,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;CAC9B;AAED,qDAAqD;AACrD,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,sDAAsD;AACtD,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,yEAAyE;IACzE,SAAS,EAAE,mBAAmB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,+BAA+B;IAC/B,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAID,UAAU,SAAS;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAC9B,SAAS,GAAE,MAAkC,GAC5C,OAAO,CAAC;IAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAAC,MAAM,EAAE,qBAAqB,EAAE,CAAA;CAAE,CAAC,CA2GjE;AA6KD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,EAC5C,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,uBAAuB,CAAC,CAwNlC;AAED,4DAA4D;AAC5D,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAe5D"}
|
|
@@ -19,9 +19,8 @@
|
|
|
19
19
|
*
|
|
20
20
|
* **Component chain (4xx):**
|
|
21
21
|
* Pass 1 — status files (leaf → root): {status}.tsx → 4xx.tsx
|
|
22
|
-
* Pass 2 —
|
|
23
|
-
* Pass 3 —
|
|
24
|
-
* Pass 4 — framework default (returns null)
|
|
22
|
+
* Pass 2 — error.tsx (leaf → root)
|
|
23
|
+
* Pass 3 — framework default (returns null)
|
|
25
24
|
*
|
|
26
25
|
* **JSON chain (4xx and 5xx):**
|
|
27
26
|
* Pass 1 — json status files (leaf → root): {status}.json → {category}.json
|
|
@@ -33,7 +32,7 @@
|
|
|
33
32
|
*/
|
|
34
33
|
import type { SegmentNode } from '../routing/types.js';
|
|
35
34
|
/** How the status-code file was matched. */
|
|
36
|
-
export type StatusFileKind = 'exact' | 'category' | '
|
|
35
|
+
export type StatusFileKind = 'exact' | 'category' | 'error';
|
|
37
36
|
/** Response format family for status-code resolution. */
|
|
38
37
|
export type StatusFileFormat = 'component' | 'json';
|
|
39
38
|
/** Result of resolving a status-code file for a segment chain. */
|
|
@@ -58,12 +57,6 @@ export interface SlotDeniedResolution<TFile> {
|
|
|
58
57
|
/** How the file was matched. */
|
|
59
58
|
kind: SlotDeniedKind;
|
|
60
59
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Maps legacy file convention names to their corresponding HTTP status codes.
|
|
63
|
-
* Only used in the 4xx component fallback chain. Exported so the in-tree
|
|
64
|
-
* deny chain (deny-boundary.ts) uses the same mapping — see TIM-1081.
|
|
65
|
-
*/
|
|
66
|
-
export declare const LEGACY_FILE_TO_STATUS: Record<string, number>;
|
|
67
60
|
/**
|
|
68
61
|
* Resolve the status-code file to render for a given HTTP status code.
|
|
69
62
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status-code-resolver.d.ts","sourceRoot":"","sources":["../../src/server/status-code-resolver.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"status-code-resolver.d.ts","sourceRoot":"","sources":["../../src/server/status-code-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GACtB,OAAO,GACP,UAAU,GACV,OAAO,CAAC;AAEZ,yDAAyD;AACzD,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,MAAM,CAAC;AAEpD,kEAAkE;AAClE,MAAM,WAAW,oBAAoB,CAAC,KAAK;IACzC,8BAA8B;IAC9B,IAAI,EAAE,KAAK,CAAC;IACZ,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,0CAA0C;AAC1C,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElD,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB,CAAC,KAAK;IACzC,0DAA0D;IAC1D,IAAI,EAAE,KAAK,CAAC;IACZ,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,IAAI,EAAE,cAAc,CAAC;CACtB;AA4BD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EACrC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAC3C,MAAM,GAAE,gBAA8B,GACrC,oBAAoB,CAAC,KAAK,CAAC,GAAG,IAAI,CAKpC;AAoFD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EACrC,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,GAC3B,oBAAoB,CAAC,KAAK,CAAC,GAAG,IAAI,CAYpC"}
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* Shim: next/navigation (client environment only)
|
|
3
3
|
*
|
|
4
4
|
* Re-exports the client-side hooks from timber's client API, and implements
|
|
5
|
-
* client-render `redirect()`
|
|
6
|
-
*
|
|
5
|
+
* client-render `redirect()` without pulling server/primitives.ts into the
|
|
6
|
+
* browser bundle.
|
|
7
7
|
*
|
|
8
|
-
* Next.js supports calling redirect()
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
8
|
+
* Next.js supports calling redirect() during client component render.
|
|
9
|
+
* timber matches that by throwing a plain Error carrying the same JSON
|
|
10
|
+
* digest the server pipeline attaches to RedirectSignal. TimberErrorBoundary
|
|
11
|
+
* recognizes the digest and converts it to an SPA navigation (replace
|
|
12
|
+
* semantics), and browser-dev's isFrameworkSignalError() keeps it out of
|
|
13
|
+
* the dev overlay.
|
|
14
14
|
*
|
|
15
15
|
* The full shim (navigation.ts) is still used in the RSC and SSR environments
|
|
16
16
|
* where the real server primitives produce proper HTTP responses.
|
|
@@ -36,15 +36,4 @@ export { RedirectType } from '../shared/redirect-type.js';
|
|
|
36
36
|
* matching the server-side redirect().
|
|
37
37
|
*/
|
|
38
38
|
export declare function redirect(path: string, _type?: RedirectTypeValue): never;
|
|
39
|
-
/**
|
|
40
|
-
* Client-render permanent redirect. On the client there is no HTTP status —
|
|
41
|
-
* this behaves identically to redirect() apart from the digest's status.
|
|
42
|
-
*/
|
|
43
|
-
export declare function permanentRedirect(path: string, _type?: RedirectTypeValue): never;
|
|
44
|
-
/**
|
|
45
|
-
* Client-render notFound. Throws a deny-digest error (status 404) that the
|
|
46
|
-
* nearest matching TimberErrorBoundary renders as the 404 fallback. The
|
|
47
|
-
* message matches DenySignal's so digest-less fallback parsing still works.
|
|
48
|
-
*/
|
|
49
|
-
export declare function notFound(): never;
|
|
50
39
|
//# sourceMappingURL=navigation-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation-client.d.ts","sourceRoot":"","sources":["../../src/shims/navigation-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIpE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,IAAI,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,WAAW,EACX,SAAS,EACT,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAS1D;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAGvE
|
|
1
|
+
{"version":3,"file":"navigation-client.d.ts","sourceRoot":"","sources":["../../src/shims/navigation-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIpE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,IAAI,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,WAAW,EACX,SAAS,EACT,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAS1D;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAGvE"}
|
|
@@ -12,5 +12,4 @@ export { useSegmentParams, useSegmentParams as useParams } from '../client/use-s
|
|
|
12
12
|
export { useSearchParams } from '../client/use-search-params.js';
|
|
13
13
|
export { usePathname, useRouter, useSelectedLayoutSegment, useSelectedLayoutSegments, } from '@timber-js/app/client';
|
|
14
14
|
export { redirect, redirectExternal, RedirectType } from '@timber-js/app/server';
|
|
15
|
-
export { permanentRedirect, notFound } from '../server/primitives.js';
|
|
16
15
|
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/shims/navigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,IAAI,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,WAAW,EACX,SAAS,EACT,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/shims/navigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,IAAI,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,WAAW,EACX,SAAS,EACT,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -70,9 +70,8 @@ Priority order (innermost to outermost):
|
|
|
70
70
|
|
|
71
71
|
1. Specific status files (`403.tsx`, `503.tsx`)
|
|
72
72
|
2. Category catch-alls (`4xx.tsx`, `5xx.tsx`)
|
|
73
|
-
3.
|
|
74
|
-
4.
|
|
75
|
-
5. Parent segments → framework default
|
|
73
|
+
3. `error.tsx` — catches anything unmatched
|
|
74
|
+
4. Parent segments → framework default
|
|
76
75
|
|
|
77
76
|
## `error.tsx`
|
|
78
77
|
|
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.185",
|
|
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",
|
package/src/client/router.ts
CHANGED
|
@@ -494,6 +494,28 @@ export function createRouter(deps: RouterDeps): RouterInstance {
|
|
|
494
494
|
}
|
|
495
495
|
}
|
|
496
496
|
|
|
497
|
+
/**
|
|
498
|
+
* Perform a hard navigation to a URL. When the target is same-document
|
|
499
|
+
* (same pathname+search, different hash), `location.href = url` is a
|
|
500
|
+
* hash change — no reload. Use `location.reload()` instead (TIM-1235).
|
|
501
|
+
*
|
|
502
|
+
* `fromUrl` is the departing URL captured before any pushState or
|
|
503
|
+
* Navigation API commit — deps.getCurrentUrl() is unreliable here
|
|
504
|
+
* because the URL may have already been updated.
|
|
505
|
+
*/
|
|
506
|
+
function hardNavigate(url: string, fromUrl: string): void {
|
|
507
|
+
const current = new URL(fromUrl, window.location.origin);
|
|
508
|
+
const target = new URL(url, window.location.origin);
|
|
509
|
+
if (target.pathname === current.pathname && target.search === current.search) {
|
|
510
|
+
// Assign first to update the hash in the address bar, then reload
|
|
511
|
+
// to force a full page load. href alone is a no-op hash change.
|
|
512
|
+
window.location.href = url;
|
|
513
|
+
window.location.reload();
|
|
514
|
+
} else {
|
|
515
|
+
window.location.href = url;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
497
519
|
/** Run a callback after the next paint (after React commit). */
|
|
498
520
|
function afterPaint(callback: () => void): void {
|
|
499
521
|
if (deps.afterPaint) {
|
|
@@ -695,17 +717,12 @@ export function createRouter(deps: RouterDeps): RouterInstance {
|
|
|
695
717
|
}
|
|
696
718
|
if (error instanceof ServerErrorResponse) {
|
|
697
719
|
setHardNavigating(true);
|
|
698
|
-
|
|
699
|
-
// is hash-stripped. Preserves fragment on hard navigation.
|
|
700
|
-
window.location.href = url;
|
|
720
|
+
hardNavigate(url, departingUrl);
|
|
701
721
|
await new Promise(() => {});
|
|
702
722
|
}
|
|
703
723
|
if (error instanceof NonRscResponse) {
|
|
704
724
|
setHardNavigating(true);
|
|
705
|
-
|
|
706
|
-
// is hash-stripped. Preserves fragment on hard navigation (e.g.,
|
|
707
|
-
// /manual.pdf#page=5). Matches no-JS <a> behavior.
|
|
708
|
-
window.location.href = url;
|
|
725
|
+
hardNavigate(url, departingUrl);
|
|
709
726
|
await new Promise(() => {});
|
|
710
727
|
}
|
|
711
728
|
throw error;
|
package/src/client/rsc-fetch.ts
CHANGED
|
@@ -107,13 +107,24 @@ export function isStaticMode(): boolean {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
* RSC manifest
|
|
110
|
+
* RSC manifest entry: hashed URL with optional inlined route params.
|
|
111
|
+
* Params are embedded at build time (TIM-1255) so no sidecar fetch needed.
|
|
112
|
+
*/
|
|
113
|
+
interface RscManifestEntry {
|
|
114
|
+
url: string;
|
|
115
|
+
params?: Record<string, string | string[]>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type RscManifest = Record<string, RscManifestEntry>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* RSC manifest mapping unhashed → hashed URLs + params. Populated from
|
|
111
122
|
* `window.__TIMBER_RSC_MANIFEST__` (injected into HTML during
|
|
112
|
-
* static generation). See TIM-1254.
|
|
123
|
+
* static generation). See TIM-1254, TIM-1255.
|
|
113
124
|
*/
|
|
114
|
-
let rscManifest:
|
|
125
|
+
let rscManifest: RscManifest | null = null;
|
|
115
126
|
|
|
116
|
-
function getRscManifest():
|
|
127
|
+
function getRscManifest(): RscManifest | null {
|
|
117
128
|
if (rscManifest) return rscManifest;
|
|
118
129
|
if (typeof window !== 'undefined' && (window as any).__TIMBER_RSC_MANIFEST__) {
|
|
119
130
|
rscManifest = (window as any).__TIMBER_RSC_MANIFEST__;
|
|
@@ -122,7 +133,7 @@ function getRscManifest(): Record<string, string> | null {
|
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
/** @internal Exported for testing. */
|
|
125
|
-
export function setRscManifest(manifest:
|
|
136
|
+
export function setRscManifest(manifest: RscManifest | null): void {
|
|
126
137
|
rscManifest = manifest;
|
|
127
138
|
}
|
|
128
139
|
|
|
@@ -161,18 +172,11 @@ export function toUnhashedRscUrl(url: string): string {
|
|
|
161
172
|
return `/_rsc${rscPath}.rsc`;
|
|
162
173
|
}
|
|
163
174
|
|
|
164
|
-
/**
|
|
165
|
-
* Convert a route URL to the corresponding _rsc/*.params.json sidecar path.
|
|
166
|
-
* Used in static mode to fetch route params that are normally carried
|
|
167
|
-
* in the X-Timber-Params response header. See TIM-1246.
|
|
168
|
-
*
|
|
169
|
-
* Consults the RSC manifest for hashed filenames (TIM-1254).
|
|
170
|
-
*/
|
|
171
175
|
/**
|
|
172
176
|
* Look up a key in the RSC manifest, falling back to percent-decoded
|
|
173
|
-
* lookup for encoded browser URLs. Returns
|
|
177
|
+
* lookup for encoded browser URLs. Returns the entry or null.
|
|
174
178
|
*/
|
|
175
|
-
function
|
|
179
|
+
function manifestEntry(key: string): RscManifestEntry | null {
|
|
176
180
|
const manifest = getRscManifest();
|
|
177
181
|
if (!manifest) return null;
|
|
178
182
|
if (manifest[key]) return manifest[key];
|
|
@@ -185,9 +189,19 @@ function manifestLookup(key: string): string | null {
|
|
|
185
189
|
return null;
|
|
186
190
|
}
|
|
187
191
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Look up the hashed URL for an unhashed RSC path.
|
|
194
|
+
*/
|
|
195
|
+
function manifestLookup(key: string): string | null {
|
|
196
|
+
return manifestEntry(key)?.url ?? null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Look up inlined route params for a route from the manifest. TIM-1255.
|
|
201
|
+
*/
|
|
202
|
+
function manifestParams(url: string): Record<string, string | string[]> | null {
|
|
203
|
+
const key = toUnhashedRscUrl(url);
|
|
204
|
+
return manifestEntry(key)?.params ?? null;
|
|
191
205
|
}
|
|
192
206
|
|
|
193
207
|
// ─── Reload Signal ───────────────────────────────────────────────
|
|
@@ -446,21 +460,6 @@ export async function fetchRscPayload(
|
|
|
446
460
|
// Intercept the response to read segment metadata before createFromFetch
|
|
447
461
|
// consumes the body. Reading headers does NOT consume the body stream.
|
|
448
462
|
const fetchPromise = deps.fetch(rscUrl, { headers, redirect: 'manual', signal });
|
|
449
|
-
// In static mode, fetch the params sidecar in parallel. The .rsc
|
|
450
|
-
// file has no HTTP headers, so params come from a .params.json
|
|
451
|
-
// sidecar written at build time. See TIM-1246.
|
|
452
|
-
const staticParamsFetch = staticMode
|
|
453
|
-
? deps
|
|
454
|
-
.fetch(toStaticParamsUrl(url), { signal })
|
|
455
|
-
.then((r) => (r.ok ? (r.json() as Promise<Record<string, string | string[]>>) : null))
|
|
456
|
-
.catch((e) => {
|
|
457
|
-
if (e instanceof DOMException && e.name === 'AbortError') throw e;
|
|
458
|
-
return null;
|
|
459
|
-
})
|
|
460
|
-
: null;
|
|
461
|
-
// Observe the sidecar promise so its rejection doesn't become
|
|
462
|
-
// unhandled if wrappedPromise rejects first (TIM-1248).
|
|
463
|
-
staticParamsFetch?.catch(() => {});
|
|
464
463
|
let segmentInfo: SegmentInfo[] | null = null;
|
|
465
464
|
let params: Record<string, string | string[]> | null = null;
|
|
466
465
|
let skippedSegments: string[] | null = null;
|
|
@@ -538,10 +537,10 @@ export async function fetchRscPayload(
|
|
|
538
537
|
});
|
|
539
538
|
// Await headers so segmentInfo/params are populated.
|
|
540
539
|
await wrappedPromise;
|
|
541
|
-
// In static mode, params come from the
|
|
542
|
-
//
|
|
543
|
-
if (
|
|
544
|
-
params =
|
|
540
|
+
// In static mode, params come from the manifest (inlined at build
|
|
541
|
+
// time) since .rsc files have no HTTP headers. TIM-1255.
|
|
542
|
+
if (staticMode && !params) {
|
|
543
|
+
params = manifestParams(url);
|
|
545
544
|
}
|
|
546
545
|
// Start decoding but do NOT await — return the in-progress thenable.
|
|
547
546
|
// React can render a Flight thenable directly: it suspends on unresolved
|
|
@@ -601,17 +600,9 @@ export async function fetchRscPayload(
|
|
|
601
600
|
}
|
|
602
601
|
}
|
|
603
602
|
let fallbackParams = extractParams(response);
|
|
604
|
-
// In static mode, params come from the
|
|
603
|
+
// In static mode, params come from the manifest. TIM-1255.
|
|
605
604
|
if (staticMode && !fallbackParams) {
|
|
606
|
-
|
|
607
|
-
const paramsResponse = await deps.fetch(toStaticParamsUrl(url), { signal });
|
|
608
|
-
if (paramsResponse.ok) {
|
|
609
|
-
fallbackParams = (await paramsResponse.json()) as Record<string, string | string[]>;
|
|
610
|
-
}
|
|
611
|
-
} catch (e) {
|
|
612
|
-
if (e instanceof DOMException && e.name === 'AbortError') throw e;
|
|
613
|
-
// No params sidecar — non-dynamic route, params stay null
|
|
614
|
-
}
|
|
605
|
+
fallbackParams = manifestParams(url);
|
|
615
606
|
}
|
|
616
607
|
return {
|
|
617
608
|
payload: await response.text(),
|
package/src/plugin-context.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type { CaptureSummary } from './server/prebuilt-builder';
|
|
|
18
18
|
import type { StartupTimer } from './utils/startup-timer';
|
|
19
19
|
import { createStartupTimer } from './utils/startup-timer';
|
|
20
20
|
import type { TimberUserConfig, ClientJavascriptConfig } from './config-types.js';
|
|
21
|
+
import type { RscManifest } from './plugins/static-build.js';
|
|
21
22
|
import type { HoldingServer } from './dev-tools/holding-server.js';
|
|
22
23
|
import type { ProgramNode } from './plugins/callsite-ast.js';
|
|
23
24
|
|
|
@@ -171,7 +172,7 @@ export interface PluginContext {
|
|
|
171
172
|
* Populated during static generation, consumed by adapters to set
|
|
172
173
|
* immutable cache headers for `_rsc/` files. See TIM-1254.
|
|
173
174
|
*/
|
|
174
|
-
rscManifest?:
|
|
175
|
+
rscManifest?: RscManifest;
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
// ── AST parse memo ───────────────────────────────────────────────────────
|
package/src/plugins/routing.ts
CHANGED
|
@@ -69,7 +69,7 @@ const SEGMENT_PREFIX = '\0$segment:';
|
|
|
69
69
|
* File convention names we track for changes that require manifest regeneration.
|
|
70
70
|
*/
|
|
71
71
|
const ROUTE_FILE_PATTERNS =
|
|
72
|
-
/\/(page|layout|middleware|access|route|error|global-error|default|denied|params|schema|\d{3}|[45]xx|
|
|
72
|
+
/\/(page|layout|middleware|access|route|error|global-error|default|denied|params|schema|\d{3}|[45]xx|sitemap|robots|manifest|favicon|icon|opengraph-image|apple-icon)\./;
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
75
|
* Create the timber-routing Vite plugin.
|
|
@@ -28,6 +28,18 @@ import { htmlEscapeJsonString } from '../server/flight-scripts.js';
|
|
|
28
28
|
// Types
|
|
29
29
|
// ---------------------------------------------------------------------------
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* A single entry in the RSC manifest injected into static HTML.
|
|
33
|
+
* Maps an unhashed `/_rsc/*.rsc` path to its hashed URL, with
|
|
34
|
+
* optional route params inlined to avoid a sidecar fetch.
|
|
35
|
+
*/
|
|
36
|
+
export interface RscManifestEntry {
|
|
37
|
+
url: string;
|
|
38
|
+
params?: Record<string, string | string[]>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type RscManifest = Record<string, RscManifestEntry>;
|
|
42
|
+
|
|
31
43
|
export interface StaticValidationError {
|
|
32
44
|
type: 'dynamic-api';
|
|
33
45
|
file: string;
|
|
@@ -219,6 +231,10 @@ async function runStaticGeneration(ctx: PluginContext): Promise<StaticGeneration
|
|
|
219
231
|
const autoSitemapEnabled = Boolean(sitemapConfig?.enabled && sitemapConfig?.baseUrl);
|
|
220
232
|
|
|
221
233
|
const contentTypes: Record<string, string> = {};
|
|
234
|
+
// Collect route params from RSC entries so they can be inlined
|
|
235
|
+
// into the manifest instead of written as .params.json sidecars.
|
|
236
|
+
// Keyed by the unhashed /_rsc/*.rsc URL path. TIM-1255.
|
|
237
|
+
const routeParams: Record<string, Record<string, string | string[]>> = {};
|
|
222
238
|
|
|
223
239
|
const summary = await generate({
|
|
224
240
|
autoSitemapEnabled,
|
|
@@ -241,12 +257,15 @@ async function runStaticGeneration(ctx: PluginContext): Promise<StaticGeneration
|
|
|
241
257
|
await mkdir(dirname(fullPath), { recursive: true });
|
|
242
258
|
await writeFileAtomic(fullPath, entry.body);
|
|
243
259
|
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
// fetches this sidecar to populate useSegmentParams(). TIM-1246.
|
|
260
|
+
// Capture route params for RSC entries. These are inlined into
|
|
261
|
+
// the RSC manifest (TIM-1255) instead of written as sidecars.
|
|
247
262
|
if (entry.kind === 'rsc' && entry.headers['x-timber-params']) {
|
|
248
|
-
const
|
|
249
|
-
|
|
263
|
+
const rscUrlKey = entry.urlPath === '/' ? '/_rsc/index.rsc' : `/_rsc${entry.urlPath}.rsc`;
|
|
264
|
+
try {
|
|
265
|
+
routeParams[rscUrlKey] = JSON.parse(entry.headers['x-timber-params']);
|
|
266
|
+
} catch {
|
|
267
|
+
// Malformed params header — skip
|
|
268
|
+
}
|
|
250
269
|
}
|
|
251
270
|
|
|
252
271
|
// Track Content-Type for extensionless API routes so adapters
|
|
@@ -281,7 +300,7 @@ async function runStaticGeneration(ctx: PluginContext): Promise<StaticGeneration
|
|
|
281
300
|
// Skip when client JS is disabled — no SPA navigation, no RSC fetches,
|
|
282
301
|
// and injecting a <script> tag would violate the no-JS contract.
|
|
283
302
|
if (!ctx.clientJavascript.disabled) {
|
|
284
|
-
const rscManifest = await hashRscPayloads(staticDir);
|
|
303
|
+
const rscManifest = await hashRscPayloads(staticDir, routeParams);
|
|
285
304
|
if (Object.keys(rscManifest).length > 0) {
|
|
286
305
|
await injectRscManifestIntoHtml(staticDir, rscManifest);
|
|
287
306
|
ctx.rscManifest = rscManifest;
|
|
@@ -351,41 +370,50 @@ async function walkDir(dir: string): Promise<string[]> {
|
|
|
351
370
|
}
|
|
352
371
|
|
|
353
372
|
/**
|
|
354
|
-
* Hash all RSC flight payloads
|
|
355
|
-
*
|
|
373
|
+
* Hash all RSC flight payloads in `_rsc/`, rename them with content
|
|
374
|
+
* hashes, and build a manifest with optional inlined route params.
|
|
356
375
|
*
|
|
357
376
|
* Before: `_rsc/index.rsc`, `_rsc/about.rsc`
|
|
358
377
|
* After: `_rsc/index-B7YxEKdN.rsc`, `_rsc/about-C8ZzFLfO.rsc`
|
|
359
378
|
*
|
|
360
|
-
* The manifest maps the original `_rsc/` URL to
|
|
361
|
-
* `{"/_rsc/index.rsc":"/_rsc/index-B7YxEKdN.rsc", ...}`
|
|
379
|
+
* The manifest maps the original `_rsc/` URL to an entry object:
|
|
380
|
+
* `{"/_rsc/index.rsc":{"url":"/_rsc/index-B7YxEKdN.rsc"}, ...}`
|
|
381
|
+
*
|
|
382
|
+
* Route params (from `routeParams`) are inlined into the manifest
|
|
383
|
+
* entry, eliminating the need for .params.json sidecar files. TIM-1255.
|
|
362
384
|
*
|
|
363
385
|
* Injected into HTML as:
|
|
364
386
|
* `<script>window.__TIMBER_RSC_MANIFEST__={...}</script>`
|
|
365
387
|
*
|
|
366
388
|
* @internal Exported for testing.
|
|
367
389
|
*/
|
|
368
|
-
export async function hashRscPayloads(
|
|
390
|
+
export async function hashRscPayloads(
|
|
391
|
+
staticDir: string,
|
|
392
|
+
routeParams?: Record<string, Record<string, string | string[]>>
|
|
393
|
+
): Promise<RscManifest> {
|
|
369
394
|
const rscDir = join(staticDir, '_rsc');
|
|
370
395
|
const files = await walkDir(rscDir);
|
|
371
|
-
const manifest:
|
|
396
|
+
const manifest: RscManifest = {};
|
|
372
397
|
|
|
373
398
|
for (const filePath of files) {
|
|
374
|
-
if (!filePath.endsWith('.rsc')
|
|
399
|
+
if (!filePath.endsWith('.rsc')) continue;
|
|
375
400
|
|
|
376
401
|
const content = await readFile(filePath);
|
|
377
402
|
const hash = contentHash(content);
|
|
378
403
|
const rel = relative(staticDir, filePath).replace(/\\/g, '/');
|
|
379
404
|
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
const base = filePath.slice(0, -ext.length);
|
|
383
|
-
const hashedPath = `${base}-${hash}${ext}`;
|
|
405
|
+
const base = filePath.slice(0, -'.rsc'.length);
|
|
406
|
+
const hashedPath = `${base}-${hash}.rsc`;
|
|
384
407
|
|
|
385
408
|
await rename(filePath, hashedPath);
|
|
386
409
|
|
|
387
410
|
const hashedRel = relative(staticDir, hashedPath).replace(/\\/g, '/');
|
|
388
|
-
|
|
411
|
+
const key = `/${rel}`;
|
|
412
|
+
const entry: RscManifestEntry = { url: `/${hashedRel}` };
|
|
413
|
+
if (routeParams?.[key]) {
|
|
414
|
+
entry.params = routeParams[key];
|
|
415
|
+
}
|
|
416
|
+
manifest[key] = entry;
|
|
389
417
|
}
|
|
390
418
|
|
|
391
419
|
return manifest;
|
|
@@ -400,7 +428,7 @@ export async function hashRscPayloads(staticDir: string): Promise<Record<string,
|
|
|
400
428
|
*/
|
|
401
429
|
export async function injectRscManifestIntoHtml(
|
|
402
430
|
staticDir: string,
|
|
403
|
-
manifest:
|
|
431
|
+
manifest: RscManifest
|
|
404
432
|
): Promise<void> {
|
|
405
433
|
const allFiles = await walkDir(staticDir);
|
|
406
434
|
const htmlFiles = allFiles.filter((f) => f.endsWith('.html'));
|
|
@@ -31,12 +31,7 @@ const SINGLE_FILE_KEYS = [
|
|
|
31
31
|
|
|
32
32
|
// ── Record-shaped conventions ───────────────────────────────────────────
|
|
33
33
|
// Each entry maps to a node property that holds Record<string, RouteFile>.
|
|
34
|
-
const RECORD_FILE_KEYS = [
|
|
35
|
-
'statusFiles',
|
|
36
|
-
'jsonStatusFiles',
|
|
37
|
-
'legacyStatusFiles',
|
|
38
|
-
'metadataRoutes',
|
|
39
|
-
] as const;
|
|
34
|
+
const RECORD_FILE_KEYS = ['statusFiles', 'jsonStatusFiles', 'metadataRoutes'] as const;
|
|
40
35
|
|
|
41
36
|
const SCHEMA_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx'];
|
|
42
37
|
|
package/src/routing/scanner.ts
CHANGED
|
@@ -29,17 +29,6 @@ import { ENCODED_SEPARATOR_RE, NULL_BYTE_RE } from '../server/canonicalize.js';
|
|
|
29
29
|
*/
|
|
30
30
|
const PAGE_EXT_CONVENTIONS = new Set(['page', 'layout', 'error', 'default', 'denied']);
|
|
31
31
|
|
|
32
|
-
/**
|
|
33
|
-
* Legacy compat status-code files.
|
|
34
|
-
* Maps legacy file name → HTTP status code for the fallback chain.
|
|
35
|
-
* See design/10-error-handling.md §"Fallback Chain".
|
|
36
|
-
*/
|
|
37
|
-
const LEGACY_STATUS_FILES: Record<string, number> = {
|
|
38
|
-
'not-found': 404,
|
|
39
|
-
'forbidden': 403,
|
|
40
|
-
'unauthorized': 401,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
32
|
/**
|
|
44
33
|
* File convention names that are always .ts/.tsx (never .mdx etc.)
|
|
45
34
|
*/
|
|
@@ -219,19 +208,6 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
219
208
|
continue;
|
|
220
209
|
}
|
|
221
210
|
|
|
222
|
-
// Legacy compat files (not-found.tsx, forbidden.tsx, unauthorized.tsx)
|
|
223
|
-
if (name in LEGACY_STATUS_FILES && extSet.has(ext)) {
|
|
224
|
-
if (!node.legacyStatusFiles) {
|
|
225
|
-
node.legacyStatusFiles = {};
|
|
226
|
-
}
|
|
227
|
-
const existing = node.legacyStatusFiles[name];
|
|
228
|
-
if (existing) {
|
|
229
|
-
throwDuplicateConvention(name, existing.filePath, fullPath);
|
|
230
|
-
}
|
|
231
|
-
node.legacyStatusFiles[name] = { filePath: fullPath, extension: ext };
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
211
|
// Metadata route files (sitemap.ts, robots.ts, icon.tsx, opengraph-image.tsx, etc.)
|
|
236
212
|
// Both static (.xml, .txt, .png, .ico, etc.) and dynamic (.ts, .tsx) files are recognized.
|
|
237
213
|
// When both exist for the same base name, dynamic takes precedence.
|
package/src/routing/types.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* `SegmentNode` (Map-based) and `ManifestSegmentNode` (object-based).
|
|
15
15
|
*
|
|
16
16
|
* Keyed groups (`slots`, `statusFiles`, `jsonStatusFiles`,
|
|
17
|
-
* `
|
|
17
|
+
* `metadataRoutes`) are plain `Record<string, …>`
|
|
18
18
|
* objects rather than `Map`s so that the build-time tree can be
|
|
19
19
|
* serialized into the virtual route manifest with no shape transform.
|
|
20
20
|
*
|
|
@@ -110,8 +110,6 @@ export interface SegmentNode<TFile = RouteFile> {
|
|
|
110
110
|
jsonStatusFiles?: Record<string, TFile>;
|
|
111
111
|
/** denied.tsx — slot-only denial rendering */
|
|
112
112
|
denied?: TFile;
|
|
113
|
-
/** Legacy compat: not-found.tsx (maps to 404), forbidden.tsx (403), unauthorized.tsx (401) */
|
|
114
|
-
legacyStatusFiles?: Record<string, TFile>;
|
|
115
113
|
|
|
116
114
|
/** Metadata route files (sitemap.ts, robots.ts, icon.tsx, etc.) keyed by base name */
|
|
117
115
|
metadataRoutes?: Record<string, TFile>;
|