@timber-js/app 0.2.0-alpha.160 → 0.2.0-alpha.161
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{actions-C9yAuoX3.js → actions-cjklt63G.js} +7 -4
- package/dist/_chunks/{actions-C9yAuoX3.js.map → actions-cjklt63G.js.map} +1 -1
- package/dist/_chunks/{cache-api-swbefQ6F.js → cache-api-CzYUlgXA.js} +2 -2
- package/dist/_chunks/{cache-api-swbefQ6F.js.map → cache-api-CzYUlgXA.js.map} +1 -1
- package/dist/_chunks/{cli-schema-sync-BhYDz_-x.js → cli-schema-sync-NfLbLnDw.js} +2 -2
- package/dist/_chunks/{cli-schema-sync-BhYDz_-x.js.map → cli-schema-sync-NfLbLnDw.js.map} +1 -1
- package/dist/_chunks/{logger-CPoQkGK6.js → logger-B_O6-mdJ.js} +7 -45
- package/dist/_chunks/logger-B_O6-mdJ.js.map +1 -0
- package/dist/_chunks/{walkers-c8aReVgo.js → walkers-9mz9T7mb.js} +2 -2
- package/dist/_chunks/{walkers-c8aReVgo.js.map → walkers-9mz9T7mb.js.map} +1 -1
- package/dist/adapters/cloudflare.d.ts +13 -13
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +44 -46
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +1 -8
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/types.d.ts +0 -6
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/child-segment-context.d.ts +22 -0
- package/dist/client/child-segment-context.d.ts.map +1 -0
- package/dist/client/child-segment-outlet.d.ts +18 -0
- package/dist/client/child-segment-outlet.d.ts.map +1 -0
- package/dist/client/child-segment-provider.d.ts +21 -0
- package/dist/client/child-segment-provider.d.ts.map +1 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +5 -1
- package/dist/cookies/index.js.map +1 -1
- package/dist/index.js +256 -9
- package/dist/index.js.map +1 -1
- package/dist/plugins/cache.d.ts.map +1 -1
- package/dist/plugins/callsite-ast.d.ts +27 -5
- package/dist/plugins/callsite-ast.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/routing/index.js +2 -2
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +1 -0
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/internal.js +85 -10
- package/dist/server/internal.js.map +1 -1
- package/dist/server/prebuilt-builder.d.ts.map +1 -1
- package/dist/server/prebuilt-runtime.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +5 -12
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +7 -0
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +2 -2
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/adapters/cloudflare.ts +41 -63
- package/src/adapters/nitro.ts +0 -11
- package/src/adapters/types.ts +0 -7
- package/src/client/child-segment-context.ts +40 -0
- package/src/client/child-segment-outlet.tsx +25 -0
- package/src/client/child-segment-provider.tsx +27 -0
- package/src/client/use-cookie.ts +11 -1
- package/src/plugins/cache.ts +44 -1
- package/src/plugins/callsite-ast.ts +310 -5
- package/src/plugins/fonts.ts +8 -0
- package/src/plugins/prebuilt-capture.ts +7 -0
- package/src/plugins/shims.ts +24 -0
- package/src/server/actions.ts +10 -1
- package/src/server/als-registry.ts +1 -0
- package/src/server/index.ts +1 -1
- package/src/server/prebuilt-builder.ts +120 -42
- package/src/server/prebuilt-runtime.ts +24 -1
- package/src/server/primitives.ts +5 -20
- package/src/server/route-element-builder.ts +31 -6
- package/src/server/rsc-entry/index.ts +40 -40
- package/src/server/rsc-entry/render-route.ts +6 -2
- package/src/server/rsc-entry/rsc-payload.ts +2 -2
- package/src/server/server-only-guard-noop.js +3 -0
- package/dist/_chunks/logger-CPoQkGK6.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;
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prebuilt-runtime.d.ts","sourceRoot":"","sources":["../../src/server/prebuilt-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;
|
|
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"}
|
|
@@ -168,25 +168,18 @@ export declare class RenderError<TCode extends string = string, TData extends Js
|
|
|
168
168
|
status?: number;
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
|
-
/** Minimal interface for adapters that support background work. */
|
|
172
|
-
export interface WaitUntilAdapter {
|
|
173
|
-
waitUntil?(promise: Promise<unknown>): void;
|
|
174
|
-
}
|
|
175
171
|
/**
|
|
176
172
|
* Register a promise to be kept alive after the response is sent.
|
|
177
173
|
* Maps to `ctx.waitUntil()` on Cloudflare Workers and similar platforms.
|
|
178
174
|
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* If neither is available, a warning is logged once and the promise is
|
|
184
|
-
* left to resolve (or reject) without being tracked.
|
|
175
|
+
* The platform adapter installs a per-request waitUntil function via ALS
|
|
176
|
+
* (see waituntil-bridge.ts). If no ALS handler is available, a warning
|
|
177
|
+
* is logged once and the promise is left to resolve (or reject) without
|
|
178
|
+
* being tracked.
|
|
185
179
|
*
|
|
186
180
|
* @param promise - The background work to keep alive.
|
|
187
|
-
* @param adapter - Optional legacy adapter (prefer ALS bridge in production).
|
|
188
181
|
*/
|
|
189
|
-
export declare function waitUntil(promise: Promise<unknown
|
|
182
|
+
export declare function waitUntil(promise: Promise<unknown>): void;
|
|
190
183
|
/**
|
|
191
184
|
* Reset the waitUntil warning state. Exported for testing only.
|
|
192
185
|
* @internal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/server/primitives.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/server/primitives.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,6 +44,13 @@ export declare function isClientReference(component: unknown): boolean;
|
|
|
44
44
|
export declare class ParamCoercionError extends Error {
|
|
45
45
|
constructor(message: string);
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Thrown when a matched route has no page component in its leaf segment.
|
|
49
|
+
* The pipeline catches this and renders the custom 404 page.
|
|
50
|
+
*/
|
|
51
|
+
export declare class NoPageComponentError extends Error {
|
|
52
|
+
constructor(message: string);
|
|
53
|
+
}
|
|
47
54
|
/** Layout entry with component and segment. */
|
|
48
55
|
export interface LayoutComponentEntry {
|
|
49
56
|
component: (...args: unknown[]) => unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AA4B9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,YAAY,CAW/E;AAwCD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAM7D;AAID;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAID,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,wDAAwD;IACxD,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,qCAAqC;IACrC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AA8DD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,YAAY,CAAC,EAAE,mBAAmB,EAClC,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EACpC,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,kBAAkB,CAAC,CAigB7B"}
|
|
@@ -24,11 +24,11 @@ export { runWithWorkersCachePurge } from '../workers-cache-bridge.js';
|
|
|
24
24
|
* See design/44-render-at-build-time.md §Build Phase.
|
|
25
25
|
*/
|
|
26
26
|
export declare function __timber_capturePrebuilt(options: import('../prebuilt-builder.js').CaptureOptions): Promise<import('../prebuilt-builder.js').CaptureSummary>;
|
|
27
|
-
declare const _handler: (req: Request) => Promise<Response>;
|
|
28
27
|
/**
|
|
29
28
|
* The pipeline configuration object. Exported so the dev server can set
|
|
30
29
|
* `devPipelineErrorHandler` after import without a module-level singleton.
|
|
31
30
|
*/
|
|
32
31
|
export declare const pipelineConfig: PipelineConfig;
|
|
33
|
-
|
|
32
|
+
declare const _default: (req: Request) => Promise<Response>;
|
|
33
|
+
export default _default;
|
|
34
34
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -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;
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-route.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/render-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAW1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"render-route.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/render-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAW1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAMtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAa/D;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,qBAAqB,CAAC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,mBAAmB,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAClE;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,IAAI,EAAE,eAAe,EACrB,YAAY,CAAC,EAAE,mBAAmB,GACjC,OAAO,CAAC,QAAQ,CAAC,CA+MnB"}
|
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.161",
|
|
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",
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
"#routing": {
|
|
46
46
|
"types": "./dist/routing/index.d.ts",
|
|
47
47
|
"default": "./dist/routing/index.js"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"#server-only-guard": "./src/server/server-only-guard-noop.js"
|
|
49
50
|
},
|
|
50
51
|
"exports": {
|
|
51
52
|
".": {
|
|
@@ -228,11 +228,7 @@ export function cloudflare(options: CloudflareAdapterOptions = {}): TimberPlatfo
|
|
|
228
228
|
async buildOutput(config: TimberConfig, buildDir: string) {
|
|
229
229
|
const outDir = join(buildDir, 'cloudflare');
|
|
230
230
|
|
|
231
|
-
// Clean stale prebuilt artifacts
|
|
232
|
-
// The shared step uses cp (merge, not replace), so old .flight files
|
|
233
|
-
// from removed/renamed components would persist and get picked up by
|
|
234
|
-
// find_additional_modules. Also clean static/prebuilt/ from pre-TIM-1162
|
|
235
|
-
// builds where prebuilt was copied into static assets.
|
|
231
|
+
// Clean stale prebuilt artifacts from prior builds.
|
|
236
232
|
await rm(join(outDir, 'prebuilt'), { recursive: true, force: true }).catch(() => {});
|
|
237
233
|
await rm(join(outDir, 'static', 'prebuilt'), { recursive: true, force: true }).catch(
|
|
238
234
|
() => {}
|
|
@@ -273,17 +269,16 @@ export function cloudflare(options: CloudflareAdapterOptions = {}): TimberPlatfo
|
|
|
273
269
|
hasWorkerHandlers = true;
|
|
274
270
|
}
|
|
275
271
|
|
|
276
|
-
//
|
|
277
|
-
//
|
|
278
|
-
//
|
|
279
|
-
// manifest.json publicly fetchable, bypassing middleware and access
|
|
280
|
-
// gates. Now payloads are imported as native wrangler Data/Text modules
|
|
281
|
-
// from outDir/prebuilt/ (outside static/), keeping them server-side only.
|
|
272
|
+
// Inline prebuilt flight payloads into the worker JS module (TIM-1162).
|
|
273
|
+
// Data is read from buildDir/prebuilt/ and embedded as literals —
|
|
274
|
+
// no external Text/Data module imports needed.
|
|
282
275
|
const prebuiltData = await readPrebuiltData(buildDir);
|
|
283
276
|
await writeFile(
|
|
284
277
|
join(outDir, '_timber-prebuilt-source.js'),
|
|
285
278
|
generatePrebuiltSourceModule(prebuiltData)
|
|
286
279
|
);
|
|
280
|
+
// Remove the copied prebuilt/ dir — data is inlined, files aren't needed.
|
|
281
|
+
await rm(join(outDir, 'prebuilt'), { recursive: true, force: true }).catch(() => {});
|
|
287
282
|
|
|
288
283
|
// Write the runtime init module — sets process.env.TIMBER_RUNTIME
|
|
289
284
|
// BEFORE the RSC entry evaluates (ESM import order). Without this,
|
|
@@ -446,26 +441,29 @@ ${handlersSpread} async fetch(request, env, ctx) {
|
|
|
446
441
|
`;
|
|
447
442
|
}
|
|
448
443
|
|
|
449
|
-
/** Build-time prebuilt
|
|
444
|
+
/** Build-time prebuilt data read from `.timber/dist/prebuilt/`. */
|
|
450
445
|
export interface PrebuiltModuleData {
|
|
451
|
-
/**
|
|
452
|
-
|
|
446
|
+
/** Raw manifest.json content. */
|
|
447
|
+
manifestJson: string;
|
|
448
|
+
/** Payload file paths and their raw bytes. */
|
|
449
|
+
payloads: Array<{ file: string; bytes: Buffer }>;
|
|
453
450
|
}
|
|
454
451
|
|
|
455
452
|
/**
|
|
456
|
-
* Discover prebuilt flight payload files from the build directory.
|
|
453
|
+
* Discover and read prebuilt flight payload files from the build directory.
|
|
457
454
|
* Returns null when no prebuilt artifacts exist (no cache.component usage).
|
|
458
455
|
*
|
|
459
456
|
* @internal Exported for testing.
|
|
460
457
|
*/
|
|
461
458
|
export async function readPrebuiltData(buildDir: string): Promise<PrebuiltModuleData | null> {
|
|
462
459
|
const prebuiltDir = join(buildDir, 'prebuilt');
|
|
460
|
+
let manifestJson: string;
|
|
463
461
|
try {
|
|
464
|
-
await readFile(join(prebuiltDir, 'manifest.json'));
|
|
462
|
+
manifestJson = await readFile(join(prebuiltDir, 'manifest.json'), 'utf-8');
|
|
465
463
|
} catch {
|
|
466
464
|
return null;
|
|
467
465
|
}
|
|
468
|
-
const
|
|
466
|
+
const payloads: PrebuiltModuleData['payloads'] = [];
|
|
469
467
|
try {
|
|
470
468
|
const componentDirs = await readdir(prebuiltDir, { withFileTypes: true });
|
|
471
469
|
for (const dir of componentDirs) {
|
|
@@ -473,28 +471,25 @@ export async function readPrebuiltData(buildDir: string): Promise<PrebuiltModule
|
|
|
473
471
|
const files = await readdir(join(prebuiltDir, dir.name));
|
|
474
472
|
for (const file of files) {
|
|
475
473
|
if (file.endsWith('.flight')) {
|
|
476
|
-
|
|
474
|
+
const filePath = `${dir.name}/${file}`;
|
|
475
|
+
const bytes = await readFile(join(prebuiltDir, filePath));
|
|
476
|
+
payloads.push({ file: filePath, bytes });
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
480
|
} catch {
|
|
481
481
|
// No subdirectories — manifest exists but no payloads
|
|
482
482
|
}
|
|
483
|
-
return {
|
|
483
|
+
return { manifestJson, payloads };
|
|
484
484
|
}
|
|
485
485
|
|
|
486
486
|
/**
|
|
487
487
|
* Generate the prebuilt payload source module for Cloudflare Workers.
|
|
488
488
|
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
* `find_additional_modules: true` with Data/Text rules.
|
|
494
|
-
*
|
|
495
|
-
* This is a separate ESM module so it evaluates before the RSC handler —
|
|
496
|
-
* static imports are hoisted, guaranteeing `globalThis.__TIMBER_PREBUILT_SOURCE__`
|
|
497
|
-
* is set before `createRequestHandler()` reads it.
|
|
489
|
+
* Inlines manifest JSON and flight payload bytes directly into the module
|
|
490
|
+
* so they're part of the worker's JS bundle — no external Text/Data module
|
|
491
|
+
* imports needed. This avoids depending on wrangler's find_additional_modules
|
|
492
|
+
* to discover non-JS files, which doesn't reliably resolve Text/Data imports.
|
|
498
493
|
*
|
|
499
494
|
* @internal Exported for testing.
|
|
500
495
|
*/
|
|
@@ -509,24 +504,23 @@ globalThis.__TIMBER_PREBUILT_SOURCE__ = {
|
|
|
509
504
|
`;
|
|
510
505
|
}
|
|
511
506
|
|
|
512
|
-
const imports: string[] = [];
|
|
513
507
|
const entries: string[] = [];
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
for (let i = 0; i < data.payloadFiles.length; i++) {
|
|
518
|
-
const file = data.payloadFiles[i];
|
|
519
|
-
imports.push(`import _p${i} from './prebuilt/${file}'`);
|
|
520
|
-
entries.push(` ${JSON.stringify(file)}: new Uint8Array(_p${i})`);
|
|
508
|
+
for (const { file, bytes } of data.payloads) {
|
|
509
|
+
const b64 = bytes.toString('base64');
|
|
510
|
+
entries.push(` ${JSON.stringify(file)}: ${JSON.stringify(b64)}`);
|
|
521
511
|
}
|
|
522
512
|
|
|
523
513
|
return `// Generated by @timber-js/app/adapters/cloudflare
|
|
524
|
-
// Prebuilt payload source —
|
|
525
|
-
//
|
|
526
|
-
|
|
527
|
-
${imports.join('\n')}
|
|
514
|
+
// Prebuilt payload source — inlines cache.component flight payloads
|
|
515
|
+
// directly into the worker bundle (TIM-1162).
|
|
516
|
+
const _manifest = ${data.manifestJson.trim()}
|
|
528
517
|
|
|
529
|
-
|
|
518
|
+
function _decode(b64) {
|
|
519
|
+
const bin = atob(b64)
|
|
520
|
+
const buf = new Uint8Array(bin.length)
|
|
521
|
+
for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i)
|
|
522
|
+
return buf
|
|
523
|
+
}
|
|
530
524
|
|
|
531
525
|
const _payloads = {
|
|
532
526
|
${entries.join(',\n')}
|
|
@@ -534,7 +528,10 @@ ${entries.join(',\n')}
|
|
|
534
528
|
|
|
535
529
|
globalThis.__TIMBER_PREBUILT_SOURCE__ = {
|
|
536
530
|
async loadManifest() { return _manifest },
|
|
537
|
-
async readPayload(file) {
|
|
531
|
+
async readPayload(file) {
|
|
532
|
+
const b64 = _payloads[file]
|
|
533
|
+
return b64 ? _decode(b64) : null
|
|
534
|
+
},
|
|
538
535
|
}
|
|
539
536
|
`;
|
|
540
537
|
}
|
|
@@ -694,11 +691,6 @@ export function generateWranglerConfig(
|
|
|
694
691
|
|
|
695
692
|
const flags = options.compatibilityFlags ?? ['nodejs_compat'];
|
|
696
693
|
|
|
697
|
-
const PREBUILT_MODULE_RULES = [
|
|
698
|
-
{ type: 'Text' as const, globs: ['prebuilt/**/*.json'] },
|
|
699
|
-
{ type: 'Data' as const, globs: ['prebuilt/**/*.flight'] },
|
|
700
|
-
];
|
|
701
|
-
|
|
702
694
|
const base: Record<string, unknown> = {
|
|
703
695
|
name: 'timber-app',
|
|
704
696
|
main: '_worker.js',
|
|
@@ -708,7 +700,7 @@ export function generateWranglerConfig(
|
|
|
708
700
|
// esbuild pass to avoid issues with top-level await and module format.
|
|
709
701
|
no_bundle: true,
|
|
710
702
|
find_additional_modules: true,
|
|
711
|
-
rules: [{ type: 'ESModule', globs: ['**/*.js'] }
|
|
703
|
+
rules: [{ type: 'ESModule', globs: ['**/*.js'] }],
|
|
712
704
|
assets: {
|
|
713
705
|
directory: './static',
|
|
714
706
|
binding: 'ASSETS',
|
|
@@ -733,21 +725,7 @@ export function generateWranglerConfig(
|
|
|
733
725
|
// durable_objects.bindings. Deep merge preserves generated keys while
|
|
734
726
|
// letting wrangler override on actual key-level conflicts.
|
|
735
727
|
if (options.wrangler) {
|
|
736
|
-
|
|
737
|
-
// Ensure required prebuilt module rules survive a user `rules` override.
|
|
738
|
-
// Without this, `wrangler: { rules: [...] }` replaces the entire array
|
|
739
|
-
// and drops the Text/Data rules that _timber-prebuilt-source.js needs.
|
|
740
|
-
if (options.wrangler.rules) {
|
|
741
|
-
const userRules = result.rules as Array<Record<string, unknown>>;
|
|
742
|
-
for (const required of PREBUILT_MODULE_RULES) {
|
|
743
|
-
const exists = userRules.some(
|
|
744
|
-
(r) =>
|
|
745
|
-
r.type === required.type && JSON.stringify(r.globs) === JSON.stringify(required.globs)
|
|
746
|
-
);
|
|
747
|
-
if (!exists) userRules.push(required);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
return result;
|
|
728
|
+
return shallowDeepMerge(merged, options.wrangler);
|
|
751
729
|
}
|
|
752
730
|
|
|
753
731
|
return merged;
|
package/src/adapters/nitro.ts
CHANGED
|
@@ -180,8 +180,6 @@ export function nitro(options: NitroAdapterOptions = {}): TimberPlatformAdapter
|
|
|
180
180
|
const preset = options.preset ?? 'node-server';
|
|
181
181
|
const compress = options.compress ?? true;
|
|
182
182
|
const presetConfig = PRESET_CONFIGS[preset];
|
|
183
|
-
const pendingPromises: Promise<unknown>[] = [];
|
|
184
|
-
|
|
185
183
|
return {
|
|
186
184
|
name: `nitro-${preset}`,
|
|
187
185
|
|
|
@@ -238,15 +236,6 @@ export function nitro(options: NitroAdapterOptions = {}): TimberPlatformAdapter
|
|
|
238
236
|
await spawnNitroPreview(command, [scriptPath], join(buildDir, 'nitro'));
|
|
239
237
|
}
|
|
240
238
|
: undefined,
|
|
241
|
-
|
|
242
|
-
waitUntil: presetConfig.supportsWaitUntil
|
|
243
|
-
? (promise: Promise<unknown>) => {
|
|
244
|
-
const tracked = promise.catch((err) => {
|
|
245
|
-
console.error('[timber] waitUntil promise rejected:', err);
|
|
246
|
-
});
|
|
247
|
-
pendingPromises.push(tracked);
|
|
248
|
-
}
|
|
249
|
-
: undefined,
|
|
250
239
|
};
|
|
251
240
|
}
|
|
252
241
|
|
package/src/adapters/types.ts
CHANGED
|
@@ -42,13 +42,6 @@ export interface TimberPlatformAdapter {
|
|
|
42
42
|
*/
|
|
43
43
|
preview?(config: TimberConfig, buildDir: string): Promise<void>;
|
|
44
44
|
|
|
45
|
-
/**
|
|
46
|
-
* Register a promise to be kept alive after the response is sent.
|
|
47
|
-
* Maps to platform-specific lifecycle extension (e.g. ctx.waitUntil()
|
|
48
|
-
* on Cloudflare Workers). Undefined if the platform doesn't support it.
|
|
49
|
-
*/
|
|
50
|
-
waitUntil?(promise: Promise<unknown>): void;
|
|
51
|
-
|
|
52
45
|
/**
|
|
53
46
|
* Send 103 Early Hints to the client before the final response.
|
|
54
47
|
*
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChildSegmentContext — delivers child segment content to ChildSegmentOutlet.
|
|
3
|
+
*
|
|
4
|
+
* Each layout receives a stable <ChildSegmentOutlet /> client reference as
|
|
5
|
+
* its `children` prop instead of varying server content. The actual child
|
|
6
|
+
* content (page or inner layout) is provided via this context from a
|
|
7
|
+
* ChildSegmentProvider placed ABOVE the layout in the element tree.
|
|
8
|
+
*
|
|
9
|
+
* This structural separation is what makes layout cache.component hits
|
|
10
|
+
* possible: the cached layout payload contains a deterministic client
|
|
11
|
+
* reference as children, not the varying inner content that changes per
|
|
12
|
+
* route. Same pattern as Next.js LayoutRouter.
|
|
13
|
+
*
|
|
14
|
+
* SINGLETON GUARANTEE: Uses globalThis + Symbol.for — same pattern as
|
|
15
|
+
* SegmentUpdateContext. The RSC client bundler can duplicate this module
|
|
16
|
+
* across chunks; globalThis guarantees a single context instance.
|
|
17
|
+
*
|
|
18
|
+
* See design/45-cache-lifetimes.md §Layout Propagation.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
'use client';
|
|
22
|
+
|
|
23
|
+
import React, { type ReactNode } from 'react';
|
|
24
|
+
|
|
25
|
+
const CTX_KEY = Symbol.for('__timber_child_segment_ctx');
|
|
26
|
+
|
|
27
|
+
function getOrCreateContext(): React.Context<ReactNode> {
|
|
28
|
+
const existing = (globalThis as Record<symbol, unknown>)[CTX_KEY] as
|
|
29
|
+
| React.Context<ReactNode>
|
|
30
|
+
| undefined;
|
|
31
|
+
if (existing !== undefined) return existing;
|
|
32
|
+
if (typeof React.createContext === 'function') {
|
|
33
|
+
const ctx = React.createContext<ReactNode>(null);
|
|
34
|
+
(globalThis as Record<symbol, unknown>)[CTX_KEY] = ctx;
|
|
35
|
+
return ctx;
|
|
36
|
+
}
|
|
37
|
+
return undefined as unknown as React.Context<ReactNode>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const ChildSegmentContext = getOrCreateContext();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChildSegmentOutlet — renders child segment content from context.
|
|
3
|
+
*
|
|
4
|
+
* Passed as `children` to every layout component, replacing the previous
|
|
5
|
+
* pattern of passing rendered server content directly. The layout receives
|
|
6
|
+
* a stable client reference (this component), and the actual child content
|
|
7
|
+
* is delivered via ChildSegmentContext from a provider above the layout.
|
|
8
|
+
*
|
|
9
|
+
* This makes layout cache.component hits possible: the cached layout
|
|
10
|
+
* payload contains this deterministic client reference, not varying
|
|
11
|
+
* server content. On cache hit, the revived payload contains the layout
|
|
12
|
+
* shell + this outlet; the provider above supplies the current request's
|
|
13
|
+
* child content.
|
|
14
|
+
*
|
|
15
|
+
* See design/45-cache-lifetimes.md §Layout Propagation.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
'use client';
|
|
19
|
+
|
|
20
|
+
import { useContext } from 'react';
|
|
21
|
+
import { ChildSegmentContext } from './child-segment-context.js';
|
|
22
|
+
|
|
23
|
+
export function ChildSegmentOutlet() {
|
|
24
|
+
return useContext(ChildSegmentContext);
|
|
25
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChildSegmentProvider — wraps a layout to provide child segment content.
|
|
3
|
+
*
|
|
4
|
+
* Placed above the layout in the element tree so that ChildSegmentOutlet
|
|
5
|
+
* (inside the layout's `children`) can read the actual child content.
|
|
6
|
+
*
|
|
7
|
+
* Tree structure:
|
|
8
|
+
* ChildSegmentProvider(childContent=innerElement)
|
|
9
|
+
* └── Layout(children=<ChildSegmentOutlet />)
|
|
10
|
+
* └── ChildSegmentOutlet → reads context → innerElement
|
|
11
|
+
*
|
|
12
|
+
* See design/45-cache-lifetimes.md §Layout Propagation.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use client';
|
|
16
|
+
|
|
17
|
+
import { createElement, type ReactNode } from 'react';
|
|
18
|
+
import { ChildSegmentContext } from './child-segment-context.js';
|
|
19
|
+
|
|
20
|
+
interface ChildSegmentProviderProps {
|
|
21
|
+
childContent: ReactNode;
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function ChildSegmentProvider({ childContent, children }: ChildSegmentProviderProps) {
|
|
26
|
+
return createElement(ChildSegmentContext.Provider, { value: childContent }, children);
|
|
27
|
+
}
|
package/src/client/use-cookie.ts
CHANGED
|
@@ -117,7 +117,17 @@ export function useCookie(
|
|
|
117
117
|
};
|
|
118
118
|
|
|
119
119
|
const getSnapshot = (): string | undefined => getCookieValue(name);
|
|
120
|
-
const getServerSnapshot = (): string | undefined =>
|
|
120
|
+
const getServerSnapshot = (): string | undefined => {
|
|
121
|
+
// During SSR, read the ALS-backed request cookies.
|
|
122
|
+
const ssrData = getSsrData();
|
|
123
|
+
if (ssrData) return ssrData.cookies.get(name);
|
|
124
|
+
// During client hydration there is no SSR data (it lives in the server's
|
|
125
|
+
// module graph), but React still calls getServerSnapshot. document.cookie
|
|
126
|
+
// holds the same cookies the server rendered with, so reading it here
|
|
127
|
+
// keeps the hydration render consistent with the server HTML.
|
|
128
|
+
// See design/29-cookies.md §"SSR Hydration".
|
|
129
|
+
return getCookieValue(name);
|
|
130
|
+
};
|
|
121
131
|
|
|
122
132
|
const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
123
133
|
|
package/src/plugins/cache.ts
CHANGED
|
@@ -60,6 +60,7 @@ import type { Plugin } from 'vite';
|
|
|
60
60
|
import type { PluginContext } from '../plugin-context.js';
|
|
61
61
|
import {
|
|
62
62
|
CACHE_MODULE_SOURCES,
|
|
63
|
+
collectShadowRanges,
|
|
63
64
|
findCallSites,
|
|
64
65
|
findImportBindings,
|
|
65
66
|
generateStableCallsiteId,
|
|
@@ -71,6 +72,7 @@ import type {
|
|
|
71
72
|
MemberExpressionNode,
|
|
72
73
|
PositionedNode,
|
|
73
74
|
ProgramNode,
|
|
75
|
+
ShadowRange,
|
|
74
76
|
} from './callsite-ast.js';
|
|
75
77
|
|
|
76
78
|
/**
|
|
@@ -96,6 +98,25 @@ function isCacheCallee(callee: PositionedNode, bindings: ImportBindings): boolea
|
|
|
96
98
|
return false;
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Extract the local binding name that a cache callee resolves to — the
|
|
103
|
+
* identifier for named imports, or the namespace object for `ns.cache()`.
|
|
104
|
+
*/
|
|
105
|
+
function calleeBindingName(callee: PositionedNode, bindings: ImportBindings): string | null {
|
|
106
|
+
if (callee.type === 'Identifier') {
|
|
107
|
+
const name = (callee as IdentifierNode).name;
|
|
108
|
+
return bindings.named.has(name) ? name : null;
|
|
109
|
+
}
|
|
110
|
+
if (callee.type === 'MemberExpression') {
|
|
111
|
+
const member = callee as unknown as MemberExpressionNode;
|
|
112
|
+
if (member.object.type === 'Identifier') {
|
|
113
|
+
const name = (member.object as IdentifierNode).name;
|
|
114
|
+
return bindings.namespaces.has(name) ? name : null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
99
120
|
/**
|
|
100
121
|
* Generate a stable callsite ID for a cache() call. See callsite-ast.ts for
|
|
101
122
|
* the derivation properties.
|
|
@@ -134,6 +155,25 @@ export function timberCacheTransform(ctx: PluginContext): Plugin {
|
|
|
134
155
|
const cacheBindings = findImportBindings(program, CACHE_MODULE_SOURCES, 'cache');
|
|
135
156
|
if (cacheBindings.named.size === 0 && cacheBindings.namespaces.size === 0) return;
|
|
136
157
|
|
|
158
|
+
// Collect byte ranges where tracked binding names are shadowed by
|
|
159
|
+
// function/arrow parameters or catch bindings (TIM-1141). Calls inside
|
|
160
|
+
// these ranges are NOT rewritten — they fall back to the runtime fnId.
|
|
161
|
+
const trackedNames = new Set([...cacheBindings.named, ...cacheBindings.namespaces]);
|
|
162
|
+
const shadowRanges: ShadowRange[] = [];
|
|
163
|
+
collectShadowRanges(program, trackedNames, shadowRanges);
|
|
164
|
+
|
|
165
|
+
// Check whether the specific binding name a callee resolves to is
|
|
166
|
+
// shadowed at the call position. Only that name is blocked — other
|
|
167
|
+
// tracked imports from the same module remain valid (codex review
|
|
168
|
+
// on PR #876).
|
|
169
|
+
const isCalleeShadowed = (call: CallExpressionNode): boolean => {
|
|
170
|
+
const name = calleeBindingName(call.callee, cacheBindings);
|
|
171
|
+
if (!name) return false;
|
|
172
|
+
return shadowRanges.some(
|
|
173
|
+
(r) => call.start >= r.start && call.start < r.end && r.names.has(name)
|
|
174
|
+
);
|
|
175
|
+
};
|
|
176
|
+
|
|
137
177
|
// Collect call sites per top-level statement so each call carries its
|
|
138
178
|
// enclosing statement's source text into the ID hash.
|
|
139
179
|
const callSites: Array<{ call: CallExpressionNode; stmt: PositionedNode }> = [];
|
|
@@ -141,7 +181,10 @@ export function timberCacheTransform(ctx: PluginContext): Plugin {
|
|
|
141
181
|
const calls: CallExpressionNode[] = [];
|
|
142
182
|
findCallSites(
|
|
143
183
|
stmt,
|
|
144
|
-
(call) =>
|
|
184
|
+
(call) =>
|
|
185
|
+
call.arguments.length === 2 &&
|
|
186
|
+
isCacheCallee(call.callee, cacheBindings) &&
|
|
187
|
+
!isCalleeShadowed(call),
|
|
145
188
|
calls
|
|
146
189
|
);
|
|
147
190
|
for (const call of calls) callSites.push({ call, stmt });
|