@timber-js/app 0.2.0-alpha.163 → 0.2.0-alpha.165

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.
Files changed (102) hide show
  1. package/dist/_chunks/{actions-cjklt63G.js → actions-CSDD6x7U.js} +2 -2
  2. package/dist/_chunks/{actions-cjklt63G.js.map → actions-CSDD6x7U.js.map} +1 -1
  3. package/dist/_chunks/{cache-api-CzYUlgXA.js → cache-api-eb1gydM7.js} +41 -13
  4. package/dist/_chunks/cache-api-eb1gydM7.js.map +1 -0
  5. package/dist/_chunks/{cli-schema-sync-NfLbLnDw.js → cli-schema-sync-mGfRbjh2.js} +2 -2
  6. package/dist/_chunks/{cli-schema-sync-NfLbLnDw.js.map → cli-schema-sync-mGfRbjh2.js.map} +1 -1
  7. package/dist/_chunks/{plugin-context-DeAxFRMq.js → plugin-context-BnaiU_cF.js} +37 -2
  8. package/dist/_chunks/plugin-context-BnaiU_cF.js.map +1 -0
  9. package/dist/_chunks/{walkers-9mz9T7mb.js → walkers-BL3MCMgO.js} +2 -2
  10. package/dist/_chunks/{walkers-9mz9T7mb.js.map → walkers-BL3MCMgO.js.map} +1 -1
  11. package/dist/adapters/cloudflare-kv-cache.d.ts +1 -0
  12. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -1
  13. package/dist/adapters/cloudflare-kv-cache.js.map +1 -1
  14. package/dist/adapters/nitro.d.ts +40 -0
  15. package/dist/adapters/nitro.d.ts.map +1 -1
  16. package/dist/adapters/nitro.js +133 -73
  17. package/dist/adapters/nitro.js.map +1 -1
  18. package/dist/cache/index.d.ts +3 -0
  19. package/dist/cache/index.d.ts.map +1 -1
  20. package/dist/cache/index.js +1 -1
  21. package/dist/cache/redis-handler.d.ts +1 -0
  22. package/dist/cache/redis-handler.d.ts.map +1 -1
  23. package/dist/cache/tag-aware-handler.d.ts +1 -0
  24. package/dist/cache/tag-aware-handler.d.ts.map +1 -1
  25. package/dist/cache/timber-cache.d.ts.map +1 -1
  26. package/dist/cli.js +2 -2
  27. package/dist/client/slot-context.d.ts +29 -0
  28. package/dist/client/slot-context.d.ts.map +1 -0
  29. package/dist/client/slot-outlet.d.ts +16 -0
  30. package/dist/client/slot-outlet.d.ts.map +1 -0
  31. package/dist/client/slot-provider.d.ts +20 -0
  32. package/dist/client/slot-provider.d.ts.map +1 -0
  33. package/dist/config-types.d.ts +2 -1
  34. package/dist/config-types.d.ts.map +1 -1
  35. package/dist/dev-tools/logs.d.ts.map +1 -1
  36. package/dist/index.js +293 -124
  37. package/dist/index.js.map +1 -1
  38. package/dist/plugin-context.d.ts +27 -0
  39. package/dist/plugin-context.d.ts.map +1 -1
  40. package/dist/plugins/cache.d.ts.map +1 -1
  41. package/dist/plugins/client-chunks.d.ts.map +1 -1
  42. package/dist/plugins/dev-server.d.ts.map +1 -1
  43. package/dist/plugins/prebuilt-options-analysis.d.ts +40 -0
  44. package/dist/plugins/prebuilt-options-analysis.d.ts.map +1 -0
  45. package/dist/plugins/prebuilt.d.ts.map +1 -1
  46. package/dist/plugins/prerender-sugar.d.ts.map +1 -1
  47. package/dist/routing/index.js +2 -2
  48. package/dist/server/html-injector-core.d.ts +30 -9
  49. package/dist/server/html-injector-core.d.ts.map +1 -1
  50. package/dist/server/html-injectors.d.ts.map +1 -1
  51. package/dist/server/index.js +1 -1
  52. package/dist/server/internal.js +346 -51
  53. package/dist/server/internal.js.map +1 -1
  54. package/dist/server/node-stream-transforms.d.ts.map +1 -1
  55. package/dist/server/pipeline-phases.d.ts.map +1 -1
  56. package/dist/server/prebuilt/cache-key.d.ts +4 -0
  57. package/dist/server/prebuilt/cache-key.d.ts.map +1 -1
  58. package/dist/server/prebuilt/key-discipline.d.ts +23 -0
  59. package/dist/server/prebuilt/key-discipline.d.ts.map +1 -0
  60. package/dist/server/prebuilt/slots.d.ts +74 -0
  61. package/dist/server/prebuilt/slots.d.ts.map +1 -0
  62. package/dist/server/prebuilt-builder.d.ts.map +1 -1
  63. package/dist/server/prebuilt-runtime.d.ts +12 -2
  64. package/dist/server/prebuilt-runtime.d.ts.map +1 -1
  65. package/dist/server/rsc-entry/deny-fallback.d.ts +29 -0
  66. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -0
  67. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  68. package/docs/api/34-api-config.mdx +165 -3
  69. package/docs/learn/00-introduction.mdx +78 -44
  70. package/docs/learn/13-configuration.mdx +27 -8
  71. package/package.json +3 -2
  72. package/src/adapters/cloudflare-kv-cache.ts +5 -1
  73. package/src/adapters/nitro.ts +188 -68
  74. package/src/cache/index.ts +25 -2
  75. package/src/cache/redis-handler.ts +27 -7
  76. package/src/cache/tag-aware-handler.ts +5 -1
  77. package/src/cache/timber-cache.ts +21 -10
  78. package/src/client/slot-context.ts +48 -0
  79. package/src/client/slot-outlet.tsx +22 -0
  80. package/src/client/slot-provider.tsx +25 -0
  81. package/src/config-types.ts +2 -1
  82. package/src/dev-tools/logs.ts +7 -0
  83. package/src/plugin-context.ts +54 -0
  84. package/src/plugins/cache.ts +1 -2
  85. package/src/plugins/client-chunks.ts +42 -1
  86. package/src/plugins/dev-server.ts +12 -69
  87. package/src/plugins/prebuilt-options-analysis.ts +175 -0
  88. package/src/plugins/prebuilt.ts +82 -127
  89. package/src/plugins/prerender-sugar.ts +1 -2
  90. package/src/server/html-injector-core.ts +85 -27
  91. package/src/server/html-injectors.ts +5 -1
  92. package/src/server/node-stream-transforms.ts +6 -1
  93. package/src/server/pipeline-phases.ts +4 -1
  94. package/src/server/prebuilt/cache-key.ts +74 -0
  95. package/src/server/prebuilt/key-discipline.ts +53 -0
  96. package/src/server/prebuilt/slots.ts +167 -0
  97. package/src/server/prebuilt-builder.ts +57 -23
  98. package/src/server/prebuilt-runtime.ts +144 -60
  99. package/src/server/rsc-entry/deny-fallback.ts +92 -0
  100. package/src/server/rsc-entry/index.ts +16 -70
  101. package/dist/_chunks/cache-api-CzYUlgXA.js.map +0 -1
  102. package/dist/_chunks/plugin-context-DeAxFRMq.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;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGpE,OAAO,EAGL,YAAY,EAOb,MAAM,yBAAyB,CAAC;AAOjC,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACvC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,4BAAiC,GAAG,SAAS,CA2BjG;AAID;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,IAAI,SAAS,CAoBzD;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC;AAIxB;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CA2BlE;AAID;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,SAAS,EACjD,OAAO,CAAC,EAAE,yBAAyB,GAClC,SAAS,CAiEX;AAID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,QAAQ,EAChB,UAAU,EAAE,SAAS,CAAC,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC,EAChD,MAAM,CAAC,EAAE,WAAW,GACnB,WAAW,CAgCb"}
1
+ {"version":3,"file":"node-stream-transforms.d.ts","sourceRoot":"","sources":["../../src/server/node-stream-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGpE,OAAO,EAGL,YAAY,EAOb,MAAM,yBAAyB,CAAC;AAOjC,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACvC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,4BAAiC,GAAG,SAAS,CA2BjG;AAID;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,IAAI,SAAS,CAyBzD;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC;AAIxB;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CA2BlE;AAID;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,SAAS,EACjD,OAAO,CAAC,EAAE,yBAAyB,GAClC,SAAS,CAiEX;AAID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,QAAQ,EAChB,UAAU,EAAE,SAAS,CAAC,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC,EAChD,MAAM,CAAC,EAAE,WAAW,GACnB,WAAW,CAgCb"}
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline-phases.d.ts","sourceRoot":"","sources":["../../src/server/pipeline-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEpG,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKrF,UAAU,aAAa;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAwBD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CAmBvB;AAID;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,YAAY,CAAC,CA6DvB;AAID;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE,aAAa,GACjD,OAAO,CAAC,YAAY,CAAC,CAkBvB;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAAC,QAAQ,CAAC,CAgTnB"}
1
+ {"version":3,"file":"pipeline-phases.d.ts","sourceRoot":"","sources":["../../src/server/pipeline-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEpG,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKrF,UAAU,aAAa;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAwBD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CAmBvB;AAID;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,YAAY,CAAC,CA6DvB;AAID;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE,aAAa,GACjD,OAAO,CAAC,YAAY,CAAC,CAkBvB;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAAC,QAAQ,CAAC,CAmTnB"}
@@ -47,6 +47,10 @@
47
47
  * bigints, …) live in exactly one place.
48
48
  */
49
49
  export declare function tryCanonicalize(value: unknown): string | null;
50
+ export declare function splitSlotProps(props: Record<string, unknown>, slots: readonly string[]): {
51
+ dataProps: Record<string, unknown>;
52
+ slotValues: Record<string, unknown>;
53
+ } | null;
50
54
  /**
51
55
  * Compute the cache-entry hash for a component render:
52
56
  * `sha256({props, params}).slice(0, 16)` over canonical JSON.
@@ -1 +1 @@
1
- {"version":3,"file":"cache-key.d.ts","sourceRoot":"","sources":["../../../src/server/prebuilt/cache-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAwGH;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAM7D;AAsBD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GACxC,MAAM,GAAG,IAAI,CAkCf"}
1
+ {"version":3,"file":"cache-key.d.ts","sourceRoot":"","sources":["../../../src/server/prebuilt/cache-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAwGH;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAM7D;AAsDD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB;IAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,IAAI,CAqCpF;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GACxC,MAAM,GAAG,IAAI,CAkCf"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Key-discipline diagnostic for cache.component (design/45 §Enforcement).
3
+ *
4
+ * Runtime-tier cached components MAY read request context, but the cache
5
+ * key is computed from props and segment params only — request-derived
6
+ * values in cached output are the data-leak danger zone (design/06
7
+ * security note). During a capture render the ALS store is wrapped in a
8
+ * transparent observing proxy; any request-context read produces a
9
+ * once-per-component warning.
10
+ */
11
+ import type { RequestContextStore } from '../als-registry.js';
12
+ /** Components already warned — exported so tests can reset between cases. */
13
+ export declare const keyDisciplineWarned: Set<string>;
14
+ /**
15
+ * Wrap a store with a proxy that records per-request field access.
16
+ * The proxy forwards all reads/writes transparently — it only observes.
17
+ */
18
+ export declare function createKeyDisciplineProxy(store: RequestContextStore): {
19
+ proxy: RequestContextStore;
20
+ accessedApis: Set<string>;
21
+ };
22
+ export declare function emitKeyDisciplineWarning(id: string, apis: Set<string>): void;
23
+ //# sourceMappingURL=key-discipline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-discipline.d.ts","sourceRoot":"","sources":["../../../src/server/prebuilt/key-discipline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,6EAA6E;AAC7E,eAAO,MAAM,mBAAmB,aAAoB,CAAC;AAQrD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,mBAAmB,GAAG;IACpE,KAAK,EAAE,mBAAmB,CAAC;IAC3B,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC3B,CAUA;AAED,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAW5E"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Slot-component helpers for cache.component (TIM-1173).
3
+ *
4
+ * A `slots: ['children', ...]` declaration caches the component's output
5
+ * as a shell with a stable <SlotOutlet slot={name} /> client-reference
6
+ * hole per declared slot prop; live slot content composes in per instance
7
+ * at request time via SlotsProvider/SlotContext. This generalizes the
8
+ * TIM-1181 layout mechanism (ChildSegmentOutlet) to explicitly declared,
9
+ * named slots on any cached component.
10
+ *
11
+ * Both the production wrapper (cache path) and the dev wrapper (no cache,
12
+ * same tree shape for dev/prod parity) build their render from these
13
+ * helpers. See design/45-cache-lifetimes.md §Slot Components.
14
+ */
15
+ import type { PrebuiltComponentOptions } from '../prebuilt-runtime.js';
16
+ /**
17
+ * Is this value the framework-injected `<ChildSegmentOutlet />` element?
18
+ * Total: the `in` probe and `.type` read run against a user-controlled
19
+ * value, and a Proxy trap can throw — that must classify as "not the
20
+ * outlet" (the canonicalizer then rejects the value as unkeyable → live
21
+ * render), not abort the request (codex P2 on PR #890).
22
+ */
23
+ export declare function isChildSegmentOutletElement(value: unknown): boolean;
24
+ /**
25
+ * Outcome of validating a `slots` declaration at registration time.
26
+ *
27
+ * - `none` — not declared (or an empty array): plain non-slot component.
28
+ * - `disabled` — declared but unusable (malformed shape, or missing the
29
+ * required runtime lifetime): warned once here (module load); the
30
+ * component falls back WHOLESALE to non-slot semantics — the caller
31
+ * strips `slots` from the options and every other option (including
32
+ * `prerender`) keeps its normal meaning. Safe by construction:
33
+ * element-valued props are unkeyable on the non-slot path, so renders
34
+ * with slot content go live. Slower, never wrong.
35
+ * - `active` — usable slot names.
36
+ */
37
+ export type SlotResolution = {
38
+ kind: 'none' | 'disabled';
39
+ } | {
40
+ kind: 'active';
41
+ slots: string[];
42
+ };
43
+ /**
44
+ * Validate the `slots` option. Both the production and dev wrappers gate
45
+ * on this — slot substitution is active in dev exactly when it would be
46
+ * active in production, so the tree shape a component sees never
47
+ * diverges between the two.
48
+ */
49
+ export declare function resolveSlotNames(id: string, options: PrebuiltComponentOptions): SlotResolution;
50
+ export interface SlotRender {
51
+ /** Props the shell renders with: data props + a SlotOutlet per slot. */
52
+ shellProps: Record<string, unknown>;
53
+ /** Non-slot props — the only props that participate in the cache key. */
54
+ dataProps: Record<string, unknown>;
55
+ /** Live slot content, keyed by slot name, for the SlotsProvider. */
56
+ slotValues: Record<string, unknown>;
57
+ }
58
+ /**
59
+ * Split the live props into the cacheable shell render (data props plus a
60
+ * deterministic SlotOutlet placeholder per declared slot — identical
61
+ * whether or not the caller passed the slot) and the per-instance live
62
+ * slot values.
63
+ *
64
+ * Null when the props object itself is unkeyable at the top level
65
+ * (accessors, hidden properties, exotic prototype — see splitSlotProps):
66
+ * the caller must render live with the original props.
67
+ */
68
+ export declare function prepareSlotRender(props: Record<string, unknown>, slots: readonly string[]): SlotRender | null;
69
+ /**
70
+ * Wrap a rendered shell (revived payload or live element) in a
71
+ * per-instance SlotsProvider feeding the live values to its outlets.
72
+ */
73
+ export declare function wrapInSlotsProvider(shell: unknown, slotValues: Record<string, unknown>): React.ReactElement;
74
+ //# sourceMappingURL=slots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../../src/server/prebuilt/slots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEvE;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWnE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAqBjG;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,GAAG,cAAc,CA0B9F;AAED,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,UAAU,GAAG,IAAI,CAiBnB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,KAAK,CAAC,YAAY,CAMpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"prebuilt-builder.d.ts","sourceRoot":"","sources":["../../src/server/prebuilt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAuBH,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;AAyUD;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CAqSzB"}
1
+ {"version":3,"file":"prebuilt-builder.d.ts","sourceRoot":"","sources":["../../src/server/prebuilt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAuBH,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;AAqVD;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CA2TzB"}
@@ -53,6 +53,17 @@ export interface PrebuiltComponentOptions {
53
53
  tags?: string[] | ((props: Record<string, unknown>) => string[]);
54
54
  /** Serve stale while a background re-render refreshes (design/45 §SWR). */
55
55
  staleWhileRevalidate?: boolean;
56
+ /**
57
+ * Slot props (TIM-1173): prop names whose values are live React
58
+ * elements composed into the cached shell at request time instead of
59
+ * participating in the cache. Each declared slot renders as a stable
60
+ * SlotOutlet client reference at capture time; the live value flows in
61
+ * through SlotContext per instance. Slot props are excluded from the
62
+ * cache key — only the remaining data props (+ segment params) hash.
63
+ * Runtime tier only: `prerender` is ignored (with a warning) because
64
+ * the build cannot enumerate children variants.
65
+ */
66
+ slots?: string[];
56
67
  /**
57
68
  * On a cache miss, render the component live (default: true). When false,
58
69
  * a miss throws instead — for sites that must never render unknown params
@@ -78,7 +89,6 @@ interface RscFunctions {
78
89
  * startup from the RSC entry module.
79
90
  */
80
91
  export declare function setRscFunctions(fns: RscFunctions): void;
81
- export declare const keyDisciplineWarned: Set<string>;
82
92
  /**
83
93
  * Production wrapper injected by the timber-prebuilt transform. Registers
84
94
  * the component under its stable ID and returns a wrapper component that
@@ -96,6 +106,6 @@ export declare function getPrebuiltRegistry(): ReadonlyMap<string, PrebuiltRegis
96
106
  * component on first render so the production behavior difference is visible.
97
107
  * See design/44 §Dev Mode.
98
108
  */
99
- export declare function __prebuiltDev<C extends ServerComponent>(name: string, component: C, _options?: PrebuiltComponentOptions): C;
109
+ export declare function __prebuiltDev<C extends ServerComponent>(name: string, component: C, options?: PrebuiltComponentOptions): C;
100
110
  export {};
101
111
  //# sourceMappingURL=prebuilt-runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prebuilt-runtime.d.ts","sourceRoot":"","sources":["../../src/server/prebuilt-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAmCH;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGlE;AAID;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACvC,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;IACjE,2EAA2E;IAC3E,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;OAIG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED,2DAA2D;AAE3D,KAAK,eAAe,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC;AAY/C,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,wBAAwB,CAAC;CACnC;AA8ED,UAAU,YAAY;IACpB,wBAAwB,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnF,sBAAsB,EAAE,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAA;KAAE,KAC/C,cAAc,CAAC,UAAU,CAAC,CAAC;CACjC;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAEvD;AAmCD,eAAO,MAAM,mBAAmB,aAAoB,CAAC;AA2YrD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,eAAe,EAClD,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,CAAC,EACZ,OAAO,GAAE,wBAA6B,GACrC,CAAC,CAyCH;AAED,qDAAqD;AACrD,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAEpF;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,IAAI,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAE/E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,eAAe,EACrD,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,CAAC,EACZ,QAAQ,CAAC,EAAE,wBAAwB,GAClC,CAAC,CAYH"}
1
+ {"version":3,"file":"prebuilt-runtime.d.ts","sourceRoot":"","sources":["../../src/server/prebuilt-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AA6CH;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGlE;AAID;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACvC,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;IACjE,2EAA2E;IAC3E,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED,2DAA2D;AAE3D,KAAK,eAAe,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC;AAY/C,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,wBAAwB,CAAC;CACnC;AAqID,UAAU,YAAY;IACpB,wBAAwB,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnF,sBAAsB,EAAE,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAA;KAAE,KAC/C,cAAc,CAAC,UAAU,CAAC,CAAC;CACjC;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAEvD;AAoYD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,eAAe,EAClD,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,CAAC,EACZ,OAAO,GAAE,wBAA6B,GACrC,CAAC,CAoEH;AAED,qDAAqD;AACrD,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAEpF;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,IAAI,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAE/E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,eAAe,EACrD,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,CAAC,EACZ,OAAO,GAAE,wBAA6B,GACrC,CAAC,CAmCH"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Deny fallback renderer — renders the deny page (403.tsx, 404.tsx, etc.)
3
+ * for DenySignals that escape from middleware or the render phase.
4
+ *
5
+ * Extracted from index.ts (TIM-968) as a pure move. The factory captures
6
+ * the root segment and client bootstrap config once at handler creation;
7
+ * the returned function is wired into `PipelineConfig.renderDenyFallback`
8
+ * and reused by the action-dispatch wrapper.
9
+ *
10
+ * Design docs: 04-authorization.md, 10-error-handling.md
11
+ */
12
+ import type { ClientBootstrapConfig } from '../html-injectors.js';
13
+ import type { PipelineConfig } from '../pipeline.js';
14
+ import type { ManifestSegmentNode } from '../route-matcher.js';
15
+ /**
16
+ * Create the pipeline's deny fallback renderer.
17
+ *
18
+ * When the pipeline already matched a route (the common case — matching
19
+ * runs before middleware and rendering), resolve the status file against
20
+ * the matched chain so colocated files like a nested `403.tsx` or an API
21
+ * route's `401.json` are picked up. Fall back to the root chain when no
22
+ * match is available (e.g. proxy-stage deny before route matching).
23
+ * See TIM-822, design/04-authorization.md, design/10-error-handling.md.
24
+ */
25
+ export declare function createDenyFallbackRenderer(options: {
26
+ rootSegment: ManifestSegmentNode;
27
+ clientBootstrap: ClientBootstrapConfig;
28
+ }): NonNullable<PipelineConfig['renderDenyFallback']>;
29
+ //# sourceMappingURL=deny-fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deny-fallback.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/deny-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAK/D;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE;IAClD,WAAW,EAAE,mBAAmB,CAAC;IACjC,eAAe,EAAE,qBAAqB,CAAC;CACxC,GAAG,WAAW,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC,CAwDpD"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/index.ts"],"names":[],"mappings":"AAuBA,OAAO,uCAAuC,CAAC;AAuB/C,OAAO,KAAK,EAAuB,cAAc,EAAc,MAAM,gBAAgB,CAAC;AAuCtF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAE5E;AAoZD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAInE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAK1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,OAAO,wBAAwB,EAAE,cAAc,GACvD,OAAO,CAAC,OAAO,wBAAwB,EAAE,cAAc,CAAC,CAE1D;AAyCD;;;GAGG;AACH,eAAO,MAAM,cAAc,gBAAmB,CAAC;8BAb1B,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC;AAelD,wBAAyB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/index.ts"],"names":[],"mappings":"AA+BA,OAAO,uCAAuC,CAAC;AAqB/C,OAAO,KAAK,EAAuB,cAAc,EAAc,MAAM,gBAAgB,CAAC;AAmCtF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAE5E;AA4VD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAInE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAK1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,OAAO,wBAAwB,EAAE,cAAc,GACvD,OAAO,CAAC,OAAO,wBAAwB,EAAE,cAAc,CAAC,CAE1D;AAyCD;;;GAGG;AACH,eAAO,MAAM,cAAc,gBAAmB,CAAC;8BAb1B,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC;AAelD,wBAAyB"}
@@ -13,10 +13,12 @@ Project-wide configuration. Export a default object from `timber.config.ts` at t
13
13
  ```ts
14
14
  interface TimberUserConfig {
15
15
  output?: 'server' | 'static';
16
+ debug?: boolean;
16
17
  buildDir?: string;
17
18
  clientJavascript?: boolean | ClientJavascriptConfig;
18
19
  adapter?: TimberPlatformAdapter;
19
20
  cacheHandler?: CacheHandler;
21
+ cdnPurge?: CdnPurgeHandler;
20
22
  serverTiming?: 'detailed' | 'total' | false;
21
23
  allowedOrigins?: string[];
22
24
  csrf?: boolean;
@@ -29,18 +31,44 @@ interface TimberUserConfig {
29
31
  runMiddleware?: boolean;
30
32
  };
31
33
  forms?: {
32
- stripSensitiveFields?: boolean | string[];
34
+ stripSensitiveFields?: boolean | readonly string[];
33
35
  };
34
36
  pageExtensions?: string[];
37
+ slowRequestMs?: number;
38
+ renderTimeoutMs?: number;
39
+ devBrowserLogs?: 'error' | 'warn' | 'info' | 'none';
35
40
  dev?: {
36
41
  slowPhaseMs?: number;
37
42
  };
43
+ budget?: {
44
+ firstLoadJs?: number;
45
+ };
46
+ appDir?: string;
38
47
  mdx?: {
39
48
  remarkPlugins?: any[];
40
49
  rehypePlugins?: any[];
41
50
  recmaPlugins?: any[];
42
51
  remarkRehypeOptions?: any;
43
52
  };
53
+ actionEncryption?: {
54
+ disableInDev?: boolean;
55
+ };
56
+ reactCompiler?: boolean | { compilationMode?: string; target?: string };
57
+ sitemap?: {
58
+ enabled?: boolean;
59
+ baseUrl?: string;
60
+ defaultChangeFrequency?: string;
61
+ defaultPriority?: number;
62
+ includeProtected?: boolean;
63
+ };
64
+ topLoader?: {
65
+ enabled?: boolean;
66
+ color?: string;
67
+ height?: number;
68
+ shadow?: boolean;
69
+ delay?: number;
70
+ zIndex?: number;
71
+ };
44
72
  }
45
73
  ```
46
74
 
@@ -156,12 +184,71 @@ Code-only conventions (`middleware.*`, `access.*`, `route.*`, `params.*`) always
156
184
 
157
185
  Two files claiming the same convention in one directory (e.g. `page.tsx` + `page.jsx`) are a build error — filesystem order is platform-dependent, so timber refuses to pick one silently.
158
186
 
187
+ ### `debug`
188
+
189
+ - **Type:** `boolean`
190
+ - **Default:** `false`
191
+
192
+ Enable timber debug logging in production builds. When `true`, timber's own diagnostics (dev warnings, verbose logging) are active even in production mode. React stays in production mode — only timber's logs are affected. Can also be enabled at runtime via the `TIMBER_DEBUG` environment variable.
193
+
194
+ ### `cdnPurge`
195
+
196
+ - **Type:** `CdnPurgeHandler`
197
+ - **Default:** none
198
+
199
+ CDN purge handler called on `revalidateTag` / `cache.invalidate` to purge CDN-cached responses.
200
+
201
+ ### `slowRequestMs`
202
+
203
+ - **Type:** `number`
204
+ - **Default:** `3000`
205
+
206
+ Slow request threshold in milliseconds. Requests exceeding this emit a warning via the logger. Set to `0` to disable.
207
+
208
+ ### `renderTimeoutMs`
209
+
210
+ - **Type:** `number`
211
+ - **Default:** `30000`
212
+
213
+ Render timeout in milliseconds. If an SSR render or RSC stream read does not complete within this duration, the render is aborted and the connection is closed. Protects against hung fetches and Suspense components that never resolve. Setting `0` uses a 120-second safety ceiling rather than disabling the timeout entirely.
214
+
215
+ ### `devBrowserLogs`
216
+
217
+ - **Type:** `'error' | 'warn' | 'info' | 'none'`
218
+ - **Default:** `'warn'`
219
+
220
+ Forward browser console output to the server terminal in dev mode. Sets the minimum log level to forward. Does not intercept `console.log` or `console.debug` (too noisy). No effect in production builds.
221
+
159
222
  ### `dev.slowPhaseMs`
160
223
 
161
224
  - **Type:** `number`
162
- - **Default:** framework default
225
+ - **Default:** `200`
226
+
227
+ Threshold in milliseconds to highlight slow phases in dev logging output.
228
+
229
+ ### `budget`
230
+
231
+ Build-time performance budgets. When exceeded, the build report emits a warning (does not fail the build).
232
+
233
+ ```ts
234
+ budget: {
235
+ firstLoadJs: 100_000, // bytes (gzipped)
236
+ }
237
+ ```
238
+
239
+ #### `budget.firstLoadJs`
240
+
241
+ - **Type:** `number`
242
+ - **Default:** none
163
243
 
164
- Threshold in milliseconds for slow-phase warnings in dev mode.
244
+ Warn when any route's first-load JS (gzip) exceeds this many bytes.
245
+
246
+ ### `appDir`
247
+
248
+ - **Type:** `string`
249
+ - **Default:** auto-detected (`app/` or `src/app/`)
250
+
251
+ Override the app directory location. Set to a relative path from the project root (e.g. `'src/app'`) to use a custom location.
165
252
 
166
253
  ### `mdx`
167
254
 
@@ -174,6 +261,81 @@ mdx: {
174
261
  }
175
262
  ```
176
263
 
264
+ ### `actionEncryption`
265
+
266
+ Server action bound args encryption configuration. The RSC plugin encrypts closure variables captured by `'use server'` functions using AES-256-GCM so they are opaque and tamper-proof in the Flight payload. Encryption is always enabled in production.
267
+
268
+ The encryption key is auto-generated at build time and embedded in the server bundle. For rolling/blue-green deployments where multiple builds coexist, set `TIMBER_ACTIONS_ENCRYPTION_KEY` env var to share a key across builds.
269
+
270
+ #### `actionEncryption.disableInDev`
271
+
272
+ - **Type:** `boolean`
273
+ - **Default:** `false`
274
+
275
+ Disable encryption in dev mode for easier debugging of bound args. Has no effect in production — encryption is always enabled.
276
+
277
+ ### `reactCompiler`
278
+
279
+ - **Type:** `boolean | { compilationMode?: string; target?: string }`
280
+ - **Default:** `false`
281
+
282
+ Enable the React Compiler (`babel-plugin-react-compiler`) for automatic memoization of components and hooks at build time.
283
+
284
+ ```ts
285
+ reactCompiler: true // enable with defaults
286
+ reactCompiler: { compilationMode: 'annotation' } // only compile 'use memo' files
287
+ reactCompiler: { target: '18' } // target React 18
288
+ ```
289
+
290
+ Requires `babel-plugin-react-compiler` as a peer dependency.
291
+
292
+ ### `sitemap`
293
+
294
+ Auto-generate `sitemap.xml` from the route tree. When enabled, timber walks the file-system route tree and produces a sitemap for all discoverable pages. Dynamic routes with `generateStaticSegmentParams()` are enumerated. Routes protected by `access.ts` are excluded by default. Supports automatic pagination (sitemap index) for sites with > 50,000 URLs.
295
+
296
+ If a user-authored `sitemap.ts` or `sitemap.xml` exists at the app root, auto-generation is disabled.
297
+
298
+ ```ts
299
+ sitemap: {
300
+ enabled: true,
301
+ baseUrl: 'https://example.com',
302
+ defaultChangeFrequency: 'weekly',
303
+ defaultPriority: 0.5,
304
+ }
305
+ ```
306
+
307
+ | Sub-option | Type | Default | Description |
308
+ | ------------------------- | --------- | ------- | ------------------------------------------------ |
309
+ | `enabled` | `boolean` | `false` | Must be `true` to enable auto-generation |
310
+ | `baseUrl` | `string` | — | Base URL for absolute URLs. Required when enabled |
311
+ | `defaultChangeFrequency` | `string` | — | Default `<changefreq>` for all entries |
312
+ | `defaultPriority` | `number` | — | Default `<priority>` (0.0–1.0) |
313
+ | `includeProtected` | `boolean` | `false` | Include routes protected by `access.ts` |
314
+
315
+ ### `topLoader`
316
+
317
+ Navigation progress bar shown at the top of the page during client-side navigations.
318
+
319
+ ```ts
320
+ topLoader: {
321
+ enabled: true,
322
+ color: '#2299DD',
323
+ height: 3,
324
+ shadow: true,
325
+ delay: 0,
326
+ zIndex: 1600,
327
+ }
328
+ ```
329
+
330
+ | Sub-option | Type | Default | Description |
331
+ | ---------- | --------- | ----------- | -------------------------------------------------- |
332
+ | `enabled` | `boolean` | `true` | Whether the top-loader is enabled |
333
+ | `color` | `string` | `'#2299DD'` | Bar color |
334
+ | `height` | `number` | `3` | Bar height in pixels |
335
+ | `shadow` | `boolean` | `true` | Show subtle glow/shadow effect |
336
+ | `delay` | `number` | `0` | Delay in ms before showing (avoids flash on fast navs) |
337
+ | `zIndex` | `number` | `1600` | CSS z-index |
338
+
177
339
  ## `TimberPlatformAdapter`
178
340
 
179
341
  The adapter interface for community adapters:
@@ -9,68 +9,102 @@ notAI: true
9
9
 
10
10
  ## Basics
11
11
 
12
- Timber is a react-based web framework built on vite and server components. It is inspired by next.js, tanstack start, and remix however it brings an independent approach built on a more modern foundation.
12
+ Timber is a react-based web framework built on Vite and Server Components. It is inspired by next.js, tanstack start, and remix however it brings an independent approach built on a modern and flexible foundation.
13
13
 
14
- It is built on web standards and attempts to use as little framework magic as possible. We feel it unlocks both the most flexible UX and DX possible. Rather than using heuristics to adjust how the framework operates, it gives you the knobs to fine-tune your website to your liking.
14
+ It is designed to align with web standards and attempts to use as little framework magic as possible. We feel it unlocks both the most flexible UX and DX possible. Rather than using heuristics to adjust how the framework operates, it gives you the knobs to fine-tune your website to your liking.
15
15
 
16
- That means it is entirely possible to write an inefficient website with timber, however, you will also _understand_ exactly what is happening and have clear eyes on how to fix it.
16
+ ---
17
+
18
+ Here are some of the ideas that drive Timber.
19
+
20
+ ### Architectural Optionality
21
+
22
+ Timber is a framework that aims to bring architectural optionality. All websites run in three environments:
23
+
24
+ * The Server
25
+ * The Server and the Client (often called SSR or pre-rendering)
26
+ * The Client
27
+
28
+ The server brings forth access control, privacy, and performance and sets up the initial response to the user.
29
+
30
+ The client unlocks interactivity, dynamic rendering, and cross-route state.
31
+
32
+ SSR and pre-rendering bridge the two.
33
+
34
+ Server Components unlock each environment to its fullest capacity, while allowing you to step through them via one unified component tree. And timber embraces them fully.
35
+
36
+ ### Upside-Down Astro
37
+
38
+ Astro is a framework built for content and it's philsophy is: static first, islands of interactivity and dynamic content.
39
+
40
+ Timber is the inverse of this approach: dynamic first, with islands of static content. In our experience, most webpages require some form of dynamic rendering. Expensive stuff, cached stuff, is usually on the leafier side – a component tree here and there. Only caching subsets of your tree gives you powerful performance without sacrificing the full server functionality (access control, middleware, logging, and more).
41
+
42
+ We also find this to be a simpler mental model. Requests flow through the server – subsets of the page are cached. Interactivity and state exists throughout the tree and across routes.
43
+
44
+ ### Serialized Building Blocks: Cookies, Search Params, Segment Params
45
+
46
+ Timber takes all of the building blocks of the web that are effectively: serialize data to a string and back and it gives you the guard rails to properly type and validate them. Things like cookies, search params, and segment params.
47
+
48
+ Everything is driven by standard schemas (zod, valibot, nuqs, custom, etc.) and you create factory functions to access that data on the server and the client.
49
+
50
+ ```tsx
51
+ import { defineSearchParams } from '@timber-js/app/search-params';
52
+ import { z } from 'zod/v4';
53
+
54
+ export const searchParams = defineSearchParams({
55
+ month: z.string().optional(),
56
+ day: z.string().optional(),
57
+ slug: z.string().optional(),
58
+ });
59
+
60
+ // later on
61
+ const sp = searchParams.get();
62
+
63
+ // or on the client
64
+
65
+ const [sp, setSearchParams] = searchParams.useQueryState();
66
+ ```
17
67
 
18
- We believe that the best UX is often invisible, but the best DX is _transparent_. You shouldn't ever be confused about where something is running and why.
68
+ ### Typed Routes
19
69
 
20
- Timber is not a framework that comes with the simplest mental model – rather it embraces the _inherent complexity_ of the web and gives you the tools to define your boundaries as you see fit. Server and client, static and dynamic, build-time and run-time. So on and so forth. There is no one true _best_ place to put these boundaries, so it is incumbent on the developer to _choose_ where to place them.
70
+ All routing in timber is fully typed and integrated. So you can write a `<Link>` as:
21
71
 
22
- Timber is a tool for frontend professionals. Though a beginner could pick it up and learn both the framework and the platform (the web) incrementally, it is best utilized by people who have a deep understanding of both the web and building websites.
72
+ ```tsx
73
+ <Link href="/blog/[slug]" segmentParams={{ slug: 'a-post' }} searchParams={{ foo: 'bar' }}>Page</Link>
74
+ ```
23
75
 
24
- Think of it as a flexible toolbelt of tools: the mental model to understand each of these tools and how to use them is high, but once you do, the framework clicks into place. A simpler mental model may come with it an easier skill curve, but at the sacrifice of both user experience and developer experience.
76
+ Or just normal `<a>` tags work too.
25
77
 
26
- Timber is understandable, but you'll have to be patient in understanding it. We feel it's worth the investment.
78
+ ### Middleware and Access Control
27
79
 
28
- ## Philosophy
80
+ Timber's routing and layouting system is almost 1:1 inspired by next.js. This file based routing structure lends itself to a compositional architecture, where you can build up layers of functionality as you go deeper into the route tree.
29
81
 
30
- All web frameworks are created out of some basic philosophies of how its creators feel websites should be built. Timber is no exception.
82
+ The filesystem maps directly to the route tree. On top of that, because our architecture is dynamic first, we can give you: proper middleware and `access.ts` access control.
31
83
 
32
- Here's ours:
84
+ When you hit a route, every segment's `middleware.ts` and `access.ts` is executed in series. Though some would call this slow, with a proper data architecture, we find that this is rarely the bottleneck to building a fast and performant website.
33
85
 
34
- A good web architecture _embraces_ the complexity of building websites. Since building a website is inherently complex, a framework that embraces that complexity will inevitably feel overwhelming at first. But I'd implore you to imagine it as a toolbelt that gives you access to each tool in the toolkit. As you understand the tools, the toolbelt falls into place.
86
+ And the DX clarity and functionality gains are immense. Give it a try, you'll be surprised how nice it feels.
35
87
 
36
- So while a beginner could pick up this framework, and it could incrementally teach them each component of building a powerful website, this framework is _not_ designed to be the simplest mental model. This is a framework for the frontend professional. Or a team building a complex and powerful web experience.
88
+ ### Forms
37
89
 
38
- ------
90
+ Forms have long been the biggest pain point of building React apps. They are chonky, buggy, and painful to write. Timber flips forms on their head and make the whole process feel a lot more like _react_.
39
91
 
40
- This all sounds like a lot. I'm not here to say it isn't. But if you're building a serious website, if you work on a team of experienced engineers, an architecture that sits across these complexities and doesn't abstract them gives you the power to define your boundaries: server and client, static and dynamic, client js and not.
92
+ Here are our rules for forms:
41
93
 
42
- To learn the inherent complexity of these ideas, you internalize an architecture that can scale up and down. One that gives you access to both UX and DX that is unparalleled and not limited. Timber does not dumb down our abstractions to make it easier to _understand_, because that comes at the cost of optionality.
94
+ 1. Forms must work consistently with or without javascript
95
+ 2. Inputs must _own their own state_ or be uncontrolled – no more hoisting your logic and context above the form. This makes sure forms are composable.
96
+ 3. You should be able to have global validation and input-level validation
97
+ 4. Validation should be possible to run on either the server, or the client
98
+ 5. Forms should maintain their data if submission fails (whether you are on the JS or non-JS track)
43
99
 
44
- Other frameworks that have pursued this have either abstracted away too much, leaned on too much magic, or ignored web standards. Timber is _not_ smarter than you. It doesn't try to be. You can write an inefficient website in Timber, and it won't stop you. But it also won't project onto you _how_ to build a website. It just gives you the foundation to control it yourself.
100
+ Now you might say, wow, these are a lot of rules – even though they all sound good. But to handle all of these features, you'd need way more code.
45
101
 
46
- Again, if you're new to building websites, this is a tall task.
102
+ Turns out – the opposite. It's way less code. It's more functional, more flexible, and you write less code to handle it all. Does the science back it up? Let's see:
47
103
 
48
- But the good news is, you don't have to understand this all immediately. You can layer on your understanding one by one. And I promise, in the long-term it will click. But you may have to touch it yourself one by one.
104
+ ### Developer Clarity
49
105
 
50
- {/* Here are our basic philosophies:
106
+ We believe the good UX is invisible, but good DX is _transparent_. You should always be able to see what's going on. No caching is implicit.
51
107
 
52
- - All websites sit somewhere across three environments. Embracing these three as first-party targets is a bid for developer autonomy, not confusion.
53
- - Server
54
- - Client
55
- - Isomorphic (Universal SSR)
56
- - Serverless is a flawed paradigm for rendering
57
- - Though it can be useful at times, owning your _own_ server (and CPU cycles) will always be more performant and cost effective at anything beyond a basic scale
58
- - An inefficiency in serverless means an unbounded/infinite bill, on a server it only means degraded performance
59
- - A server means your database can live _next_ to your rendering layer, which will always outperform _holistic_ edge rendering in generic real-world scenarios
60
- - Your framework should never be smarter than you
61
- - Good UX is invisible, good DX is transparent
62
- - It's better to be understandable than magic, which means performance is fine tunable – rather than automatic
63
- - The web constantly serializes and deserializes strings, the framework should provide typing and parsing to those edges
64
- - Search Params
65
- - Cookies
66
- - Segment URL Params
67
- - and more...
68
- - A good web-framework scales horizontally across your surface API (routes)
69
- - Adding more routes or components shouldn't affect performance on others
70
- - A good web framework has finely-tuned control over static (build-time) and dynamic (run-time) rendering
71
- - A good web framework has the ability to scale up and down functionally and with developer clarity, which means deploying a website that:
72
- - Can ship zero client javascript
73
- - Can ship static content
74
- - And can scale up to a completely dynamic website */}
108
+ -----
75
109
 
76
- More here soon...
110
+ These are the core tenants of Timber. It's the framework I wish existed. Thanks for taking the time to look into it.