@timber-js/app 0.2.0-alpha.134 → 0.2.0-alpha.136
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-B8Fhsosm.js → actions-CHFblsdT.js} +13 -9
- package/dist/_chunks/actions-CHFblsdT.js.map +1 -0
- package/dist/_chunks/{build-output-helper-K7oUCRqU.js → build-output-helper-CfBfOU9m.js} +1 -1
- package/dist/_chunks/{build-output-helper-K7oUCRqU.js.map → build-output-helper-CfBfOU9m.js.map} +1 -1
- package/dist/_chunks/{codec-registry-DqkeAydt.js → codec-registry-G9hD5LOq.js} +1 -1
- package/dist/_chunks/{codec-registry-DqkeAydt.js.map → codec-registry-G9hD5LOq.js.map} +1 -1
- package/dist/_chunks/{define-jeHDXZGq.js → define-DXWUJb-K.js} +3 -3
- package/dist/_chunks/{define-jeHDXZGq.js.map → define-DXWUJb-K.js.map} +1 -1
- package/dist/_chunks/{define-DMq-Yjp7.js → define-Dp-qu3ql.js} +3 -3
- package/dist/_chunks/{define-DMq-Yjp7.js.map → define-Dp-qu3ql.js.map} +1 -1
- package/dist/_chunks/fast-hash-DXZ7S2D5.js +36 -0
- package/dist/_chunks/fast-hash-DXZ7S2D5.js.map +1 -0
- package/dist/_chunks/{format-BjN9HLu9.js → format-CR6v1pWE.js} +1 -1
- package/dist/_chunks/{format-BjN9HLu9.js.map → format-CR6v1pWE.js.map} +1 -1
- package/dist/_chunks/{handler-store-bIAstrxQ.js → handler-store-aQMpqPe7.js} +1 -1
- package/dist/_chunks/{handler-store-bIAstrxQ.js.map → handler-store-aQMpqPe7.js.map} +1 -1
- package/dist/_chunks/{href-validation-BJmD5mZh.js → href-validation-2G-HZaQ8.js} +8 -8
- package/dist/_chunks/href-validation-2G-HZaQ8.js.map +1 -0
- package/dist/_chunks/{navigation-root-B5-RmsPi.js → navigation-root-BQqFQI-n.js} +3 -3
- package/dist/_chunks/{navigation-root-B5-RmsPi.js.map → navigation-root-BQqFQI-n.js.map} +1 -1
- package/dist/_chunks/{registry-BI9cgCt7.js → registry-Dp_hJL4s.js} +1 -1
- package/dist/_chunks/{registry-BI9cgCt7.js.map → registry-Dp_hJL4s.js.map} +1 -1
- package/dist/_chunks/{resolve-schema-DU2nbVOi.js → resolve-schema-D3CbcdCW.js} +2 -2
- package/dist/_chunks/{resolve-schema-DU2nbVOi.js.map → resolve-schema-D3CbcdCW.js.map} +1 -1
- package/dist/_chunks/{router-ref-B2-2kIIC.js → router-ref-B50j42zB.js} +2 -2
- package/dist/_chunks/{router-ref-B2-2kIIC.js.map → router-ref-B50j42zB.js.map} +1 -1
- package/dist/_chunks/{schema-bridge-o0SwFtXW.js → schema-bridge-Cuy8BaYu.js} +2 -2
- package/dist/_chunks/{schema-bridge-o0SwFtXW.js.map → schema-bridge-Cuy8BaYu.js.map} +1 -1
- package/dist/_chunks/{segment-context-Bg0pFbLT.js → segment-context-BnxoPSFQ.js} +1 -1
- package/dist/_chunks/{segment-context-Bg0pFbLT.js.map → segment-context-BnxoPSFQ.js.map} +1 -1
- package/dist/_chunks/{ssr-data-DVX8S7vj.js → ssr-data-DxXyoRrz.js} +1 -1
- package/dist/_chunks/{ssr-data-DVX8S7vj.js.map → ssr-data-DxXyoRrz.js.map} +1 -1
- package/dist/_chunks/{stale-reload-CCqb62Z3.js → stale-reload-DIIIVGh_.js} +1 -1
- package/dist/_chunks/{stale-reload-CCqb62Z3.js.map → stale-reload-DIIIVGh_.js.map} +1 -1
- package/dist/_chunks/{use-query-states-C9G6LP0F.js → use-query-states-D9SBlAfp.js} +2 -2
- package/dist/_chunks/{use-query-states-C9G6LP0F.js.map → use-query-states-D9SBlAfp.js.map} +1 -1
- package/dist/_chunks/{use-segment-params-CIeinIx2.js → use-segment-params-x2poKmk8.js} +2 -2
- package/dist/_chunks/use-segment-params-x2poKmk8.js.map +1 -0
- package/dist/_chunks/{validation-AfEFM5ze.js → validation-BoWM_qI1.js} +31 -2
- package/dist/_chunks/validation-BoWM_qI1.js.map +1 -0
- package/dist/_chunks/walkers-BbEu2_Pp.js.map +1 -1
- package/dist/adapters/cloudflare.js +1 -1
- package/dist/adapters/nitro.js +1 -1
- package/dist/cache/cache-api.d.ts +1 -1
- package/dist/cache/cache-api.d.ts.map +1 -1
- package/dist/cache/index.js +17 -39
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/client/error-boundary.js +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +10 -10
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.js +8 -8
- package/dist/client/internal.js.map +1 -1
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/use-pathname.d.ts.map +1 -1
- package/dist/client/use-search-params.d.ts.map +1 -1
- package/dist/codec.js +1 -1
- package/dist/cookies/index.js +3 -3
- package/dist/cookies/validation.d.ts +11 -23
- package/dist/cookies/validation.d.ts.map +1 -1
- package/dist/dev-tools/error-page.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +106 -3
- package/dist/index.js.map +1 -1
- package/dist/params/define-schema.d.ts.map +1 -1
- package/dist/params/index.js +2 -2
- package/dist/params/index.js.map +1 -1
- package/dist/plugins/cache.d.ts +31 -0
- package/dist/plugins/cache.d.ts.map +1 -0
- package/dist/routing/link-codegen.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts.map +1 -1
- package/dist/search-params/index.js +3 -3
- package/dist/segment-params/index.js +1 -1
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/body-limits.d.ts.map +1 -1
- package/dist/server/cookie-context.d.ts +2 -2
- package/dist/server/cookie-context.d.ts.map +1 -1
- package/dist/server/csrf.d.ts +3 -2
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts.map +1 -1
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.js +17 -8
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.js +50 -13
- package/dist/server/internal.js.map +1 -1
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/rsc-entry/api-handler.d.ts +11 -2
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
- package/dist/server/rsc-entry/ssr-renderer.d.ts +15 -0
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/sitemap-handler.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +22 -2
- package/dist/server/types.d.ts.map +1 -1
- package/dist/shared/href-validation.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/cache/cache-api.ts +3 -2
- package/src/cache/timber-cache.ts +27 -4
- package/src/cli.ts +0 -0
- package/src/client/index.ts +1 -0
- package/src/client/link.tsx +8 -5
- package/src/client/navigation-context.ts +2 -0
- package/src/client/use-pathname.ts +1 -0
- package/src/client/use-search-params.ts +1 -0
- package/src/client/use-segment-params.ts +1 -0
- package/src/config-validation.ts +1 -1
- package/src/cookies/validation.ts +58 -0
- package/src/dev-tools/error-page.ts +1 -0
- package/src/fonts/virtual-modules.ts +2 -0
- package/src/index.ts +5 -1
- package/src/params/define-schema.ts +1 -0
- package/src/plugins/cache.ts +180 -0
- package/src/routing/link-codegen.ts +5 -3
- package/src/schema-bridge.ts +3 -2
- package/src/server/action-client.ts +31 -13
- package/src/server/actions.ts +20 -3
- package/src/server/body-limits.ts +10 -2
- package/src/server/cookie-context.ts +7 -2
- package/src/server/cookie-parsing.ts +1 -1
- package/src/server/csrf.ts +39 -6
- package/src/server/html-injector-core.ts +6 -5
- package/src/server/html-injectors.ts +8 -5
- package/src/server/pipeline.ts +19 -10
- package/src/server/primitives.ts +11 -1
- package/src/server/route-element-builder.ts +2 -0
- package/src/server/rsc-entry/api-handler.ts +15 -9
- package/src/server/rsc-entry/error-renderer.ts +4 -3
- package/src/server/rsc-entry/index.ts +16 -36
- package/src/server/rsc-entry/render-route.ts +1 -1
- package/src/server/rsc-entry/revalidate-renderer.ts +344 -0
- package/src/server/rsc-entry/ssr-renderer.ts +76 -0
- package/src/server/sitemap-handler.ts +24 -2
- package/src/server/slot-resolver.ts +8 -2
- package/src/server/ssr-wrappers.tsx +2 -0
- package/src/server/tree-builder.ts +2 -0
- package/src/server/types.ts +24 -4
- package/src/shared/href-validation.ts +12 -8
- package/LICENSE +0 -8
- package/dist/_chunks/actions-B8Fhsosm.js.map +0 -1
- package/dist/_chunks/href-validation-BJmD5mZh.js.map +0 -1
- package/dist/_chunks/use-segment-params-CIeinIx2.js.map +0 -1
- package/dist/_chunks/validation-AfEFM5ze.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -3,8 +3,9 @@ import { a as isDynamicMetadataExtension, o as isMetadataRouteServePath } from "
|
|
|
3
3
|
import { h as swallow } from "./_chunks/logger-CMd9P1xQ.js";
|
|
4
4
|
import { c as loadTimberConfigFile, d as resolveBuildDir, f as resolveClientJavascript, l as mergeFileConfig, m as scanRoutes, o as DEFAULT_BUILD_DIR, p as createNoopTimer, s as createPluginContext, u as resolveAppDir } from "./_chunks/cli-schema-sync-q-Ce6-iG.js";
|
|
5
5
|
import { a as generateRouteMap, i as collectInterceptionRewrites, r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "./_chunks/walkers-BbEu2_Pp.js";
|
|
6
|
-
import { t as
|
|
7
|
-
import {
|
|
6
|
+
import { t as fnv1aHash } from "./_chunks/fast-hash-DXZ7S2D5.js";
|
|
7
|
+
import { t as formatSize } from "./_chunks/format-CR6v1pWE.js";
|
|
8
|
+
import { basename, dirname, extname, join, normalize, relative, resolve } from "node:path";
|
|
8
9
|
import { createRequire } from "node:module";
|
|
9
10
|
import react, { reactCompilerPreset } from "@vitejs/plugin-react";
|
|
10
11
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -1062,7 +1063,7 @@ function validateConfig(config) {
|
|
|
1062
1063
|
field: "renderTimeoutMs",
|
|
1063
1064
|
message: `renderTimeoutMs must be a non-negative number (got ${JSON.stringify(config.renderTimeoutMs)}).`,
|
|
1064
1065
|
value: config.renderTimeoutMs,
|
|
1065
|
-
suggestion: "Use renderTimeoutMs: 30000 (default)
|
|
1066
|
+
suggestion: "Use renderTimeoutMs: 30000 (default). Setting 0 uses a 120s safety ceiling."
|
|
1066
1067
|
});
|
|
1067
1068
|
}
|
|
1068
1069
|
if (config.serverTiming !== void 0) {
|
|
@@ -6502,6 +6503,107 @@ function timberServerBundle() {
|
|
|
6502
6503
|
];
|
|
6503
6504
|
}
|
|
6504
6505
|
//#endregion
|
|
6506
|
+
//#region src/plugins/cache.ts
|
|
6507
|
+
/**
|
|
6508
|
+
* timber-cache-transform — Vite plugin that injects stable callsite IDs
|
|
6509
|
+
* into `cache()` calls imported from `@timber-js/app/cache`.
|
|
6510
|
+
*
|
|
6511
|
+
* Without this plugin, cache keys use a process-local counter (fnIdCounter)
|
|
6512
|
+
* which is unstable across cold starts in serverless/multi-instance
|
|
6513
|
+
* deployments. With a shared CacheHandler (Redis/KV), colliding counters
|
|
6514
|
+
* cause cache key poisoning — serving one route's cached data to another.
|
|
6515
|
+
*
|
|
6516
|
+
* The plugin transforms:
|
|
6517
|
+
* cache(fn, opts) → cache(fn, opts, "stable-id")
|
|
6518
|
+
*
|
|
6519
|
+
* where stable-id = fnv1a(relativeModulePath + ":cache:" + callIndex).
|
|
6520
|
+
*
|
|
6521
|
+
* See TIM-997, design/06-caching.md §"Cache Key Security".
|
|
6522
|
+
*/
|
|
6523
|
+
var CACHE_MODULE_SOURCES = new Set(["@timber-js/app/cache", "timber/cache"]);
|
|
6524
|
+
/**
|
|
6525
|
+
* Find the local binding name(s) for `cache` imported from the cache module.
|
|
6526
|
+
*/
|
|
6527
|
+
function findCacheBindings(program) {
|
|
6528
|
+
const bindings = /* @__PURE__ */ new Set();
|
|
6529
|
+
for (const stmt of program.body) {
|
|
6530
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
6531
|
+
const decl = stmt;
|
|
6532
|
+
if (!CACHE_MODULE_SOURCES.has(decl.source.value)) continue;
|
|
6533
|
+
for (const spec of decl.specifiers) {
|
|
6534
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
6535
|
+
if ((spec.imported?.name ?? spec.local.name) === "cache") bindings.add(spec.local.name);
|
|
6536
|
+
}
|
|
6537
|
+
}
|
|
6538
|
+
return bindings;
|
|
6539
|
+
}
|
|
6540
|
+
/**
|
|
6541
|
+
* Recursively walk AST nodes to find cache() call expressions.
|
|
6542
|
+
*
|
|
6543
|
+
* cache() is typically called at module scope, but we also handle calls
|
|
6544
|
+
* inside functions/blocks for completeness.
|
|
6545
|
+
*/
|
|
6546
|
+
function findCacheCallSites(node, cacheBindings, results) {
|
|
6547
|
+
if (node.type === "CallExpression") {
|
|
6548
|
+
const call = node;
|
|
6549
|
+
if (call.callee.type === "Identifier" && cacheBindings.has(call.callee.name) && call.arguments.length === 2) results.push(call);
|
|
6550
|
+
}
|
|
6551
|
+
for (const key of Object.keys(node)) {
|
|
6552
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
6553
|
+
const val = node[key];
|
|
6554
|
+
if (val && typeof val === "object") {
|
|
6555
|
+
if (Array.isArray(val)) {
|
|
6556
|
+
for (const item of val) if (item && typeof item === "object" && typeof item.type === "string") findCacheCallSites(item, cacheBindings, results);
|
|
6557
|
+
} else if (typeof val.type === "string") findCacheCallSites(val, cacheBindings, results);
|
|
6558
|
+
}
|
|
6559
|
+
}
|
|
6560
|
+
}
|
|
6561
|
+
/**
|
|
6562
|
+
* Generate a stable callsite ID from a module path and call index.
|
|
6563
|
+
*
|
|
6564
|
+
* The ID is an FNV-1a hash of the relative module path + call index,
|
|
6565
|
+
* providing a deterministic identifier that is:
|
|
6566
|
+
* - Stable across cold starts of the same build
|
|
6567
|
+
* - Unique across different modules
|
|
6568
|
+
* - Unique across multiple cache() calls within the same module
|
|
6569
|
+
*/
|
|
6570
|
+
function generateStableId(relativeModulePath, callIndex) {
|
|
6571
|
+
return fnv1aHash(`${relativeModulePath}:cache:${callIndex}`);
|
|
6572
|
+
}
|
|
6573
|
+
function timberCacheTransform(ctx) {
|
|
6574
|
+
return {
|
|
6575
|
+
name: "timber-cache-transform",
|
|
6576
|
+
transform(code, id) {
|
|
6577
|
+
if (!code.includes("@timber-js/app/cache") && !code.includes("timber/cache")) return;
|
|
6578
|
+
if (id.includes("node_modules")) return;
|
|
6579
|
+
let program;
|
|
6580
|
+
try {
|
|
6581
|
+
program = parseAst(code, { lang: "tsx" });
|
|
6582
|
+
} catch {
|
|
6583
|
+
return;
|
|
6584
|
+
}
|
|
6585
|
+
const cacheBindings = findCacheBindings(program);
|
|
6586
|
+
if (cacheBindings.size === 0) return;
|
|
6587
|
+
const callSites = [];
|
|
6588
|
+
findCacheCallSites(program, cacheBindings, callSites);
|
|
6589
|
+
if (callSites.length === 0) return;
|
|
6590
|
+
callSites.sort((a, b) => a.start - b.start);
|
|
6591
|
+
const relPath = relative(ctx.root || process.cwd(), id);
|
|
6592
|
+
const s = new MagicString(code);
|
|
6593
|
+
for (let i = 0; i < callSites.length; i++) {
|
|
6594
|
+
const call = callSites[i];
|
|
6595
|
+
const stableId = generateStableId(relPath, i);
|
|
6596
|
+
const insertPos = call.end - 1;
|
|
6597
|
+
s.appendLeft(insertPos, `, "${stableId}"`);
|
|
6598
|
+
}
|
|
6599
|
+
return {
|
|
6600
|
+
code: s.toString(),
|
|
6601
|
+
map: s.generateMap({ hires: "boundary" })
|
|
6602
|
+
};
|
|
6603
|
+
}
|
|
6604
|
+
};
|
|
6605
|
+
}
|
|
6606
|
+
//#endregion
|
|
6505
6607
|
//#region src/plugins/cloudflare-wasm.ts
|
|
6506
6608
|
/**
|
|
6507
6609
|
* timber-cloudflare-wasm — Handle WASM modules for Cloudflare Workers builds.
|
|
@@ -7408,6 +7510,7 @@ function timber(config) {
|
|
|
7408
7510
|
timberStaticBuild(ctx),
|
|
7409
7511
|
timberFonts(ctx),
|
|
7410
7512
|
timberMdx(ctx),
|
|
7513
|
+
timberCacheTransform(ctx),
|
|
7411
7514
|
timberContent(ctx),
|
|
7412
7515
|
timberServerBundle(),
|
|
7413
7516
|
timberCloudflareWasm(ctx),
|