@timber-js/app 0.2.0-alpha.7 → 0.2.0-alpha.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-BJARkOcu.js} +1 -1
- package/dist/_chunks/als-registry-BJARkOcu.js.map +1 -0
- package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
- package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
- package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
- package/dist/_chunks/define-CGuYoRHU.js +199 -0
- package/dist/_chunks/define-CGuYoRHU.js.map +1 -0
- package/dist/_chunks/define-Dz1bqwaS.js +106 -0
- package/dist/_chunks/define-Dz1bqwaS.js.map +1 -0
- package/dist/_chunks/define-cookie-B5mewxwM.js +93 -0
- package/dist/_chunks/define-cookie-B5mewxwM.js.map +1 -0
- package/dist/_chunks/error-boundary-D9hzsveV.js +216 -0
- package/dist/_chunks/error-boundary-D9hzsveV.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → format-Rn922VH2.js} +3 -20
- package/dist/_chunks/format-Rn922VH2.js.map +1 -0
- package/dist/_chunks/{tracing-Cwn7697K.js → handler-store-BVePM7hp.js} +68 -3
- package/dist/_chunks/handler-store-BVePM7hp.js.map +1 -0
- package/dist/_chunks/{interception-BOoWmLUA.js → interception-CEdHHviP.js} +171 -97
- package/dist/_chunks/interception-CEdHHviP.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
- package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-CywiO4jV.js} +181 -69
- package/dist/_chunks/request-context-CywiO4jV.js.map +1 -0
- package/dist/_chunks/schema-bridge-C4SwjCQD.js +86 -0
- package/dist/_chunks/schema-bridge-C4SwjCQD.js.map +1 -0
- package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
- package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
- package/dist/_chunks/segment-context-hzuJ048X.js +72 -0
- package/dist/_chunks/segment-context-hzuJ048X.js.map +1 -0
- package/dist/_chunks/stale-reload-BLUC_Pl_.js +64 -0
- package/dist/_chunks/stale-reload-BLUC_Pl_.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DAhgj8Gx.js} +1 -1
- package/dist/_chunks/use-query-states-DAhgj8Gx.js.map +1 -0
- package/dist/_chunks/wrappers-LZbghvn0.js +63 -0
- package/dist/_chunks/wrappers-LZbghvn0.js.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +148 -12
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +135 -11
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +56 -13
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/cache/cache-api.d.ts +24 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/fast-hash.d.ts +22 -0
- package/dist/cache/fast-hash.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +7 -5
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +111 -73
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.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.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -125
- package/dist/client/error-reconstituter.d.ts +54 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +2 -2
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +19 -4
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +6 -5
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +537 -166
- package/dist/client/index.js.map +1 -1
- package/dist/client/link-pending-store.d.ts +78 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +90 -32
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +36 -0
- package/dist/client/nav-link-store.d.ts.map +1 -0
- package/dist/client/navigation-api-types.d.ts +90 -0
- package/dist/client/navigation-api-types.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts +115 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +13 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router.d.ts +70 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-context.d.ts +1 -1
- package/dist/client/segment-context.d.ts.map +1 -1
- package/dist/client/segment-merger.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +63 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +3 -3
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-params.d.ts +6 -4
- package/dist/client/use-params.d.ts.map +1 -1
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/codec.d.ts +23 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +2 -0
- package/dist/cookies/define-cookie.d.ts +35 -14
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +2 -0
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +3 -84
- package/dist/fonts/css.d.ts +1 -0
- package/dist/fonts/css.d.ts.map +1 -1
- package/dist/index.d.ts +154 -38
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12092 -11916
- package/dist/index.js.map +1 -1
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +2 -2
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +3 -3
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +32 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-browser-logs.d.ts +84 -0
- package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
- package/dist/plugins/dev-error-overlay.d.ts +26 -1
- package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
- package/dist/plugins/dev-logs.d.ts +1 -1
- package/dist/plugins/dev-logs.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +19 -5
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +6 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +1 -1
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen.d.ts +2 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/index.d.ts +2 -0
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +3 -2
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +46 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/status-file-lint.d.ts +2 -1
- package/dist/routing/status-file-lint.d.ts.map +1 -1
- package/dist/routing/types.d.ts +16 -4
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +76 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +139 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -6
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +4 -474
- package/dist/search-params/registry.d.ts +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +78 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +7 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +4 -0
- package/dist/server/access-gate.d.ts +4 -0
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +12 -1
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +3 -6
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +32 -4
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +2 -2
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/debug.d.ts +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-page-resolver.d.ts +52 -0
- package/dist/server/deny-page-resolver.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-warnings.d.ts +0 -14
- package/dist/server/dev-warnings.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -5
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +4 -3
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/flight-injection-state.d.ts +66 -0
- package/dist/server/flight-injection-state.d.ts.map +1 -0
- package/dist/server/flight-scripts.d.ts +42 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/flush.d.ts.map +1 -1
- package/dist/server/form-data.d.ts +29 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injectors.d.ts +51 -11
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2176 -1663
- package/dist/server/index.js.map +1 -1
- package/dist/server/logger.d.ts +25 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +19 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +113 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/page-deny-boundary.d.ts +31 -0
- package/dist/server/page-deny-boundary.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +32 -10
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +30 -3
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-timeout.d.ts +51 -0
- package/dist/server/render-timeout.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +76 -37
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +27 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +9 -2
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/api-handler.d.ts +2 -2
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +48 -5
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +8 -3
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +10 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +22 -0
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +39 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/status-code-resolver.d.ts +1 -1
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +36 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +10 -0
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +22 -19
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -4
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/server/waituntil-bridge.d.ts.map +1 -1
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/navigation-client.d.ts +1 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +1 -1
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/directive-parser.d.ts +5 -2
- package/dist/utils/directive-parser.d.ts.map +1 -1
- package/dist/utils/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/package.json +37 -17
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare.ts +342 -28
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +58 -9
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/fast-hash.ts +34 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +9 -5
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/timber-cache.ts +40 -29
- package/src/cli.ts +0 -0
- package/src/client/browser-entry.ts +314 -142
- package/src/client/error-boundary.tsx +48 -16
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +2 -2
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +13 -4
- package/src/client/link-pending-store.ts +136 -0
- package/src/client/link.tsx +346 -105
- package/src/client/nav-link-store.ts +47 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +332 -0
- package/src/client/navigation-context.ts +27 -6
- package/src/client/navigation-root.tsx +346 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router.ts +302 -77
- package/src/client/rsc-fetch.ts +93 -5
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-context.ts +6 -1
- package/src/client/segment-merger.ts +2 -8
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +73 -6
- package/src/client/top-loader.tsx +22 -13
- package/src/client/use-navigation-pending.ts +1 -1
- package/src/client/use-params.ts +7 -5
- package/src/client/use-query-states.ts +2 -2
- package/src/codec.ts +34 -0
- package/src/cookies/define-cookie.ts +72 -21
- package/src/cookies/index.ts +7 -0
- package/src/fonts/css.ts +2 -1
- package/src/index.ts +328 -92
- package/src/plugins/adapter-build.ts +8 -2
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +3 -3
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-browser-logs.ts +288 -0
- package/src/plugins/dev-error-overlay.ts +70 -1
- package/src/plugins/dev-logs.ts +1 -1
- package/src/plugins/dev-server.ts +55 -9
- package/src/plugins/entries.ts +70 -9
- package/src/plugins/fonts.ts +167 -61
- package/src/plugins/mdx.ts +1 -1
- package/src/plugins/routing.ts +57 -17
- package/src/plugins/server-action-exports.ts +1 -1
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +76 -33
- package/src/plugins/static-build.ts +10 -6
- package/src/routing/codegen.ts +165 -105
- package/src/routing/index.ts +2 -0
- package/src/routing/scanner.ts +93 -23
- package/src/routing/segment-classify.ts +89 -0
- package/src/routing/status-file-lint.ts +3 -2
- package/src/routing/types.ts +17 -4
- package/src/rsc-runtime/rsc.ts +2 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
- package/src/search-params/define.ts +482 -0
- package/src/search-params/index.ts +13 -19
- package/src/search-params/registry.ts +1 -1
- package/src/search-params/wrappers.ts +85 -0
- package/src/segment-params/define.ts +279 -0
- package/src/segment-params/index.ts +28 -0
- package/src/server/access-gate.tsx +70 -29
- package/src/server/action-client.ts +28 -3
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +20 -3
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +32 -4
- package/src/server/build-manifest.ts +10 -4
- package/src/server/compress.ts +25 -7
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-page-resolver.ts +154 -0
- package/src/server/deny-renderer.ts +24 -38
- package/src/server/dev-warnings.ts +2 -28
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +31 -15
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/flush.ts +2 -1
- package/src/server/form-data.ts +76 -0
- package/src/server/html-injectors.ts +277 -117
- package/src/server/index.ts +9 -5
- package/src/server/logger.ts +44 -36
- package/src/server/middleware-runner.ts +31 -4
- package/src/server/node-stream-transforms.ts +509 -0
- package/src/server/page-deny-boundary.tsx +56 -0
- package/src/server/pipeline-interception.ts +17 -16
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline.ts +195 -51
- package/src/server/primitives.ts +47 -5
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +240 -117
- package/src/server/route-element-builder.ts +284 -197
- package/src/server/route-handler.ts +24 -4
- package/src/server/route-matcher.ts +24 -20
- package/src/server/rsc-entry/api-handler.ts +15 -16
- package/src/server/rsc-entry/error-renderer.ts +300 -89
- package/src/server/rsc-entry/helpers.ts +134 -5
- package/src/server/rsc-entry/index.ts +202 -113
- package/src/server/rsc-entry/rsc-payload.ts +100 -21
- package/src/server/rsc-entry/rsc-stream.ts +74 -18
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +173 -40
- package/src/server/safe-load.ts +60 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +126 -0
- package/src/server/slot-resolver.ts +243 -228
- package/src/server/ssr-entry.ts +211 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/status-code-resolver.ts +1 -1
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +37 -3
- package/src/server/tree-builder.ts +92 -58
- package/src/server/types.ts +3 -6
- package/src/server/version-skew.ts +104 -0
- package/src/server/waituntil-bridge.ts +4 -1
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/navigation-client.ts +1 -1
- package/src/shims/navigation.ts +2 -1
- package/src/utils/directive-parser.ts +5 -2
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/format-DviM89f0.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js +0 -88
- package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
- package/dist/_chunks/tracing-Cwn7697K.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/error-boundary.js.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/cookies/index.js.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/search-params/index.js.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/server/response-cache.d.ts +0 -53
- package/dist/server/response-cache.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -99
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/transition-root.tsx +0 -160
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/create.ts +0 -321
- package/src/server/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -277
package/src/index.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { Plugin, PluginOption } from 'vite';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { pathToFileURL } from 'node:url';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
5
4
|
import { createRequire } from 'node:module';
|
|
6
|
-
import react from '@vitejs/plugin-react';
|
|
7
|
-
import { cacheTransformPlugin } from './plugins/cache-transform';
|
|
5
|
+
import react, { reactCompilerPreset } from '@vitejs/plugin-react';
|
|
8
6
|
import { timberContent } from './plugins/content';
|
|
9
7
|
import { timberDevServer } from './plugins/dev-server';
|
|
10
8
|
import { timberEntries } from './plugins/entries';
|
|
@@ -13,12 +11,13 @@ import { timberRouting } from './plugins/routing';
|
|
|
13
11
|
import { timberShims } from './plugins/shims';
|
|
14
12
|
import { timberFonts } from './plugins/fonts';
|
|
15
13
|
import { timberStaticBuild } from './plugins/static-build';
|
|
16
|
-
import { timberDynamicTransform } from './plugins/dynamic-transform';
|
|
17
14
|
import { timberServerActionExports } from './plugins/server-action-exports';
|
|
18
15
|
import { timberBuildManifest } from './plugins/build-manifest';
|
|
19
16
|
import { timberDevLogs } from './plugins/dev-logs';
|
|
17
|
+
import { timberDevBrowserLogs } from './plugins/dev-browser-logs';
|
|
20
18
|
import { timberReactProd } from './plugins/react-prod';
|
|
21
19
|
import { timberChunks } from './plugins/chunks';
|
|
20
|
+
import { clientChunkGroup } from './plugins/client-chunks';
|
|
22
21
|
import { timberServerBundle } from './plugins/server-bundle';
|
|
23
22
|
import { timberAdapterBuild } from './plugins/adapter-build';
|
|
24
23
|
import { timberBuildReport } from './plugins/build-report';
|
|
@@ -26,6 +25,7 @@ import type { RouteTree } from './routing/types';
|
|
|
26
25
|
import type { BuildManifest } from './server/build-manifest';
|
|
27
26
|
import type { StartupTimer } from './utils/startup-timer';
|
|
28
27
|
import { createStartupTimer, createNoopTimer } from './utils/startup-timer';
|
|
28
|
+
import { resolveEncryptionKeyExpression, shouldEnableEncryption } from './server/action-encryption';
|
|
29
29
|
|
|
30
30
|
/** Configuration for client-side JavaScript output. */
|
|
31
31
|
export interface ClientJavascriptConfig {
|
|
@@ -90,23 +90,54 @@ export interface TimberUserConfig {
|
|
|
90
90
|
* See design/17-logging.md §"slowRequestMs".
|
|
91
91
|
*/
|
|
92
92
|
slowRequestMs?: number;
|
|
93
|
+
/**
|
|
94
|
+
* Render timeout in milliseconds. If an SSR render or RSC stream read
|
|
95
|
+
* does not complete within this duration, the render is aborted and
|
|
96
|
+
* the connection is closed. Protects against hung fetches and Suspense
|
|
97
|
+
* components that never resolve.
|
|
98
|
+
*
|
|
99
|
+
* Set to 0 to disable (not recommended in production).
|
|
100
|
+
* Default: 30000 (30 seconds).
|
|
101
|
+
*
|
|
102
|
+
* See design/02-rendering-pipeline.md §"Streaming Constraints".
|
|
103
|
+
*/
|
|
104
|
+
renderTimeoutMs?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Forward browser console output to the server terminal in dev mode.
|
|
107
|
+
*
|
|
108
|
+
* Sets the minimum log level to forward:
|
|
109
|
+
* - `'error'` — only `console.error`
|
|
110
|
+
* - `'warn'` — `console.error` + `console.warn` (default)
|
|
111
|
+
* - `'info'` — `console.error` + `console.warn` + `console.info`
|
|
112
|
+
* - `'none'` — disabled
|
|
113
|
+
*
|
|
114
|
+
* Does not intercept `console.log` or `console.debug` (too noisy).
|
|
115
|
+
* No effect in production builds.
|
|
116
|
+
*
|
|
117
|
+
* See TIM-513.
|
|
118
|
+
*/
|
|
119
|
+
devBrowserLogs?: 'error' | 'warn' | 'info' | 'none';
|
|
93
120
|
/** Dev-mode options. These have no effect in production builds. */
|
|
94
121
|
dev?: {
|
|
95
122
|
/** Threshold in ms to highlight slow phases in dev logging output. Default: 200. */
|
|
96
123
|
slowPhaseMs?: number;
|
|
97
124
|
};
|
|
98
125
|
/**
|
|
99
|
-
*
|
|
126
|
+
* Control Server-Timing header output.
|
|
100
127
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
128
|
+
* - `'detailed'` — per-phase breakdown (proxy, middleware, render). Useful
|
|
129
|
+
* for APM / network monitoring. Exposes phase names to clients.
|
|
130
|
+
* - `'total'` — single `total;dur=N` entry. Safe to expose, gives
|
|
131
|
+
* browser DevTools useful timing without internal details.
|
|
132
|
+
* - `false` — no Server-Timing header at all.
|
|
133
|
+
*
|
|
134
|
+
* Default: `'detailed'` in dev, `'total'` in production.
|
|
135
|
+
*
|
|
136
|
+
* This is separate from `debug` / `TIMBER_DEBUG` — it's an intentional
|
|
137
|
+
* decision to expose timing data to clients, not a side effect of debug
|
|
138
|
+
* logging.
|
|
103
139
|
*/
|
|
104
|
-
|
|
105
|
-
/** Single signing secret. Shorthand for `secrets: [secret]`. */
|
|
106
|
-
secret?: string;
|
|
107
|
-
/** Array of signing secrets for key rotation. Index 0 signs; all verify. */
|
|
108
|
-
secrets?: string[];
|
|
109
|
-
};
|
|
140
|
+
serverTiming?: 'detailed' | 'total' | false;
|
|
110
141
|
/**
|
|
111
142
|
* Override the app directory location. By default, timber auto-detects
|
|
112
143
|
* `app/` at the project root, falling back to `src/app/`.
|
|
@@ -132,6 +163,72 @@ export interface TimberUserConfig {
|
|
|
132
163
|
*
|
|
133
164
|
* See LOCAL-336 for design decisions.
|
|
134
165
|
*/
|
|
166
|
+
/**
|
|
167
|
+
* Server action bound args encryption configuration.
|
|
168
|
+
*
|
|
169
|
+
* The RSC plugin encrypts closure variables captured by 'use server' functions
|
|
170
|
+
* using AES-256-GCM so they are opaque and tamper-proof in the Flight payload.
|
|
171
|
+
* Encryption is always enabled in production.
|
|
172
|
+
*
|
|
173
|
+
* The encryption key is auto-generated at build time and embedded in the server bundle,
|
|
174
|
+
* so all instances running the same build share the same key automatically.
|
|
175
|
+
* For rolling/blue-green deployments where multiple builds coexist, set
|
|
176
|
+
* `TIMBER_ACTIONS_ENCRYPTION_KEY` env var to share a key across builds.
|
|
177
|
+
*
|
|
178
|
+
* See design/08-forms-and-actions.md §"Security"
|
|
179
|
+
*/
|
|
180
|
+
actionEncryption?: {
|
|
181
|
+
/**
|
|
182
|
+
* Disable encryption in dev mode for easier debugging of bound args.
|
|
183
|
+
* Has no effect in production — encryption is always enabled.
|
|
184
|
+
* Default: false (encryption is on in dev too).
|
|
185
|
+
*/
|
|
186
|
+
disableInDev?: boolean;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Enable the React Compiler (babel-plugin-react-compiler) for automatic
|
|
190
|
+
* memoization of components and hooks at build time.
|
|
191
|
+
*
|
|
192
|
+
* - `true` — enable with default options
|
|
193
|
+
* - `{ compilationMode, target }` — enable with custom options
|
|
194
|
+
* - `compilationMode: 'annotation'` — only compile files with `'use memo'`
|
|
195
|
+
* - `target: '18'` — target React 18 (uses react-compiler-runtime package)
|
|
196
|
+
* - `false` or omitted — disabled (default)
|
|
197
|
+
*
|
|
198
|
+
* Uses `@vitejs/plugin-react`'s built-in `reactCompilerPreset`, which:
|
|
199
|
+
* - Applies Babel only for the compiler pass (OXC handles JSX)
|
|
200
|
+
* - Automatically scopes to client environment only
|
|
201
|
+
* - Uses `react/compiler-runtime` built into React 19
|
|
202
|
+
*
|
|
203
|
+
* Requires `babel-plugin-react-compiler` as a peer dependency.
|
|
204
|
+
*/
|
|
205
|
+
reactCompiler?: boolean | { compilationMode?: string; target?: string };
|
|
206
|
+
/**
|
|
207
|
+
* Auto-generate sitemap.xml from the route tree.
|
|
208
|
+
*
|
|
209
|
+
* When enabled, timber walks the file-system route tree and produces a sitemap
|
|
210
|
+
* for all discoverable pages. Dynamic routes with `generateStaticParams()` are
|
|
211
|
+
* enumerated. Routes protected by `access.ts` are excluded by default.
|
|
212
|
+
*
|
|
213
|
+
* If a user-authored `sitemap.ts` or `sitemap.xml` exists at the app root,
|
|
214
|
+
* auto-generation is disabled — the user takes full control.
|
|
215
|
+
*
|
|
216
|
+
* Supports automatic pagination (sitemap index) for sites with > 50,000 URLs.
|
|
217
|
+
*
|
|
218
|
+
* See design/16-metadata.md §"Auto-generated Sitemap"
|
|
219
|
+
*/
|
|
220
|
+
sitemap?: {
|
|
221
|
+
/** Must be explicitly `true` to enable auto-generation. Default: false. */
|
|
222
|
+
enabled?: boolean;
|
|
223
|
+
/** Base URL for absolute URLs in the sitemap. Required when enabled. e.g., 'https://example.com' */
|
|
224
|
+
baseUrl?: string;
|
|
225
|
+
/** Default `<changefreq>` for all entries. Optional. */
|
|
226
|
+
defaultChangeFrequency?: string;
|
|
227
|
+
/** Default `<priority>` for all entries (0.0–1.0). Optional. */
|
|
228
|
+
defaultPriority?: number;
|
|
229
|
+
/** Include routes protected by `access.ts`. Default: false. */
|
|
230
|
+
includeProtected?: boolean;
|
|
231
|
+
};
|
|
135
232
|
topLoader?: {
|
|
136
233
|
/** Whether the top-loader is enabled. Default: true. */
|
|
137
234
|
enabled?: boolean;
|
|
@@ -146,34 +243,6 @@ export interface TimberUserConfig {
|
|
|
146
243
|
/** CSS z-index. Default: 1600. */
|
|
147
244
|
zIndex?: number;
|
|
148
245
|
};
|
|
149
|
-
/**
|
|
150
|
-
* Response-level caching and deduplication.
|
|
151
|
-
*
|
|
152
|
-
* When enabled, concurrent requests to the same URL share a single render
|
|
153
|
-
* (singleflight), and recently rendered responses are reused from a short-TTL
|
|
154
|
-
* LRU cache without re-executing the RSC-to-SSR pipeline.
|
|
155
|
-
*
|
|
156
|
-
* Set to `false` to disable entirely. Default: enabled with sensible defaults.
|
|
157
|
-
*
|
|
158
|
-
* See design/31-benchmarking.md for performance context.
|
|
159
|
-
*/
|
|
160
|
-
responseCache?:
|
|
161
|
-
| false
|
|
162
|
-
| {
|
|
163
|
-
/** Maximum number of entries in the LRU cache. Default: 150. */
|
|
164
|
-
maxSize?: number;
|
|
165
|
-
/** TTL for cached entries in milliseconds. Default: 5000 (5s). */
|
|
166
|
-
ttlMs?: number;
|
|
167
|
-
/**
|
|
168
|
-
* When true (default), requests with Cookie or Authorization headers
|
|
169
|
-
* bypass the cache entirely. This prevents sharing user-specific
|
|
170
|
-
* responses across requests.
|
|
171
|
-
*
|
|
172
|
-
* Set to false to cache all responses regardless of auth state.
|
|
173
|
-
* Only do this if your pages are truly public and don't vary by user.
|
|
174
|
-
*/
|
|
175
|
-
publicOnly?: boolean;
|
|
176
|
-
};
|
|
177
246
|
}
|
|
178
247
|
|
|
179
248
|
/**
|
|
@@ -221,10 +290,10 @@ export interface PluginContext {
|
|
|
221
290
|
dev: boolean;
|
|
222
291
|
/** CSS build manifest (populated by adapter after client build, null in dev) */
|
|
223
292
|
buildManifest: BuildManifest | null;
|
|
293
|
+
/** Per-build deployment ID for version skew detection (null in dev) */
|
|
294
|
+
deploymentId: string | null;
|
|
224
295
|
/** Startup timer for profiling cold start phases (active in dev, no-op in prod) */
|
|
225
296
|
timer: StartupTimer;
|
|
226
|
-
/** URL path to font CSS file, set by timber-fonts when fonts are registered */
|
|
227
|
-
fontCssUrl?: string;
|
|
228
297
|
}
|
|
229
298
|
|
|
230
299
|
/**
|
|
@@ -258,7 +327,10 @@ export function resolveAppDir(root: string, configAppDir?: string): string {
|
|
|
258
327
|
|
|
259
328
|
function createPluginContext(config?: TimberUserConfig, root?: string): PluginContext {
|
|
260
329
|
const projectRoot = root ?? process.cwd();
|
|
261
|
-
|
|
330
|
+
// Don't apply defaults here — they would override file-based config
|
|
331
|
+
// during mergeFileConfig (inline spreads over file). Defaults are
|
|
332
|
+
// applied after merge in timber(). See TIM-451.
|
|
333
|
+
const resolvedConfig: TimberUserConfig = { ...config };
|
|
262
334
|
// Timer starts as active — swapped to noop in configResolved for production builds
|
|
263
335
|
return {
|
|
264
336
|
config: resolvedConfig,
|
|
@@ -268,6 +340,7 @@ function createPluginContext(config?: TimberUserConfig, root?: string): PluginCo
|
|
|
268
340
|
root: projectRoot,
|
|
269
341
|
dev: false,
|
|
270
342
|
buildManifest: null,
|
|
343
|
+
deploymentId: null,
|
|
271
344
|
timer: createStartupTimer(),
|
|
272
345
|
};
|
|
273
346
|
}
|
|
@@ -275,14 +348,18 @@ function createPluginContext(config?: TimberUserConfig, root?: string): PluginCo
|
|
|
275
348
|
/**
|
|
276
349
|
* Load timber.config.ts (or .js, .mjs) from the project root.
|
|
277
350
|
* Returns the config object or null if no config file is found.
|
|
351
|
+
*
|
|
352
|
+
* Uses require() which works for ESM modules on Node 22.12+.
|
|
353
|
+
* This keeps timber() synchronous — no async config loading needed.
|
|
278
354
|
*/
|
|
279
|
-
|
|
355
|
+
export function loadTimberConfigFile(root: string): TimberUserConfig | null {
|
|
280
356
|
const configNames = ['timber.config.ts', 'timber.config.js', 'timber.config.mjs'];
|
|
357
|
+
const req = createRequire(join(root, 'package.json'));
|
|
281
358
|
|
|
282
359
|
for (const name of configNames) {
|
|
283
360
|
const configPath = join(root, name);
|
|
284
361
|
if (existsSync(configPath)) {
|
|
285
|
-
const mod =
|
|
362
|
+
const mod = req(configPath);
|
|
286
363
|
return (mod.default ?? mod) as TimberUserConfig;
|
|
287
364
|
}
|
|
288
365
|
}
|
|
@@ -302,7 +379,6 @@ export function warnConfigConflicts(
|
|
|
302
379
|
): string[] {
|
|
303
380
|
const conflicts: string[] = [];
|
|
304
381
|
for (const key of Object.keys(fileConfig) as (keyof TimberUserConfig)[]) {
|
|
305
|
-
if (key === 'output') continue;
|
|
306
382
|
if (key in inline && inline[key] !== undefined) {
|
|
307
383
|
conflicts.push(key);
|
|
308
384
|
}
|
|
@@ -341,30 +417,181 @@ function mergeFileConfig(ctx: PluginContext, fileConfig: TimberUserConfig): void
|
|
|
341
417
|
};
|
|
342
418
|
}
|
|
343
419
|
|
|
344
|
-
|
|
345
|
-
|
|
420
|
+
/**
|
|
421
|
+
* Resolve the React Compiler plugin via @rolldown/plugin-babel.
|
|
422
|
+
*
|
|
423
|
+
* Uses the `reactCompilerPreset` from @vitejs/plugin-react, which:
|
|
424
|
+
* - Uses Babel ONLY for the compiler pass (OXC handles JSX)
|
|
425
|
+
* - Automatically scopes to client environment via applyToEnvironmentHook
|
|
426
|
+
* - Uses react/compiler-runtime built into React 19
|
|
427
|
+
*
|
|
428
|
+
* @rolldown/plugin-babel and babel-plugin-react-compiler are optional peer deps.
|
|
429
|
+
* If either is missing, require() fails with a clear error message.
|
|
430
|
+
*/
|
|
431
|
+
function resolveReactCompilerPlugin(
|
|
432
|
+
config: true | { compilationMode?: string; target?: string },
|
|
433
|
+
req: NodeRequire
|
|
434
|
+
): PluginOption {
|
|
435
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
436
|
+
let babel: any;
|
|
437
|
+
try {
|
|
438
|
+
babel = req('@rolldown/plugin-babel');
|
|
439
|
+
} catch {
|
|
440
|
+
throw new Error(
|
|
441
|
+
'[timber] reactCompiler requires @rolldown/plugin-babel. ' +
|
|
442
|
+
'Install it: pnpm add -D @rolldown/plugin-babel babel-plugin-react-compiler'
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
const options = typeof config === 'object' ? config : {};
|
|
446
|
+
const babelPlugin = babel.default ?? babel;
|
|
447
|
+
return babelPlugin({
|
|
448
|
+
presets: [reactCompilerPreset(options as Parameters<typeof reactCompilerPreset>[0])],
|
|
449
|
+
}) as PluginOption;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Build the options object for @vitejs/plugin-rsc.
|
|
454
|
+
*
|
|
455
|
+
* Uses a getter for `enableActionEncryption` so the RSC plugin reads
|
|
456
|
+
* the value lazily — after ctx.dev is set in configResolved. This lets
|
|
457
|
+
* `actionEncryption.disableInDev` work correctly even though the RSC
|
|
458
|
+
* plugin is created before Vite resolves the command.
|
|
459
|
+
*/
|
|
460
|
+
function createRscOptions(
|
|
461
|
+
ctx: PluginContext,
|
|
462
|
+
encryptionKeyExpr: string | undefined
|
|
463
|
+
): Record<string, unknown> {
|
|
464
|
+
const options: Record<string, unknown> = {
|
|
465
|
+
serverHandler: false,
|
|
466
|
+
customClientEntry: true,
|
|
467
|
+
entries: {
|
|
468
|
+
rsc: 'virtual:timber-rsc-entry',
|
|
469
|
+
ssr: 'virtual:timber-ssr-entry',
|
|
470
|
+
client: 'virtual:timber-browser-entry',
|
|
471
|
+
},
|
|
472
|
+
// Group client references by layout boundary to balance route-scoped code
|
|
473
|
+
// splitting with HTTP request count. A constant group name ('client-refs')
|
|
474
|
+
// would collapse all routes into one chunk — any page downloads every
|
|
475
|
+
// client component. Per-serverChunk grouping creates many sub-500B files.
|
|
476
|
+
// Layout-boundary grouping is the middle ground: components under the same
|
|
477
|
+
// layout segment share a chunk. See design/27-chunking-strategy.md, TIM-440, TIM-499.
|
|
478
|
+
clientChunks: (meta: { id: string; normalizedId: string; serverChunk: string }) =>
|
|
479
|
+
clientChunkGroup(meta, ctx.appDir),
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
// Bound args encryption — AES-256-GCM authenticated encryption for
|
|
483
|
+
// closure variables in 'use server' functions. Always on in production,
|
|
484
|
+
// configurable in dev. See design/08-forms-and-actions.md §"Bound Args Encryption".
|
|
485
|
+
//
|
|
486
|
+
// Uses a getter so the RSC plugin reads the value lazily in its transform
|
|
487
|
+
// hooks, after ctx.dev is set in configResolved. This lets disableInDev
|
|
488
|
+
// work correctly — ctx.dev is false at construction time but true during
|
|
489
|
+
// dev server transforms.
|
|
490
|
+
Object.defineProperty(options, 'enableActionEncryption', {
|
|
491
|
+
get() {
|
|
492
|
+
return shouldEnableEncryption(ctx.dev, ctx.config.actionEncryption);
|
|
493
|
+
},
|
|
494
|
+
enumerable: true,
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// When TIMBER_ACTIONS_ENCRYPTION_KEY is set, pass it as a runtime expression
|
|
498
|
+
// so the RSC plugin uses it instead of auto-generating a per-build key.
|
|
499
|
+
if (encryptionKeyExpr) {
|
|
500
|
+
options.defineEncryptionKey = encryptionKeyExpr;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return options;
|
|
346
504
|
}
|
|
347
505
|
|
|
506
|
+
// NOTE: 'use cache' directive transform removed — future feature pending design doc.
|
|
507
|
+
// The timber.cache() API (createCache) remains available for explicit caching.
|
|
508
|
+
// See design/06-caching.md.
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Create the timber Vite plugin array.
|
|
512
|
+
*
|
|
513
|
+
* Loads timber.config.ts and all dependencies synchronously before
|
|
514
|
+
* constructing the plugin array. This ensures ALL plugins — including
|
|
515
|
+
* the RSC plugin and React Compiler — see the fully merged config
|
|
516
|
+
* (inline + file-based). No async, no deferred config, no stale reads.
|
|
517
|
+
*
|
|
518
|
+
* Requires Node >= 22.12 for synchronous require() of ESM modules
|
|
519
|
+
* (@vitejs/plugin-rsc is ESM-only).
|
|
520
|
+
*
|
|
521
|
+
* Previous versions used async loading and deferred config merging,
|
|
522
|
+
* causing file-based config for reactCompiler, actionEncryption, and
|
|
523
|
+
* output mode to be silently ignored. See TIM-451.
|
|
524
|
+
*/
|
|
348
525
|
export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
349
526
|
const ctx = createPluginContext(config);
|
|
350
|
-
|
|
351
|
-
//
|
|
352
|
-
//
|
|
527
|
+
|
|
528
|
+
// Resolve dependencies from the consumer's project (process.cwd()),
|
|
529
|
+
// not from timber's own node_modules. This is critical for pnpm link:
|
|
530
|
+
// when linked, timber's node_modules has a separate vite instance, and
|
|
531
|
+
// the RSC plugin must use the same vite instance as the dev server.
|
|
532
|
+
const consumerRequire = createRequire(join(process.cwd(), 'package.json'));
|
|
533
|
+
|
|
534
|
+
// ── Step 1: Load @vitejs/plugin-rsc ─────────────────────────────────
|
|
535
|
+
// Synchronous require() works for ESM modules on Node 22.12+.
|
|
536
|
+
ctx.timer.start('rsc-plugin-import');
|
|
537
|
+
const rscMod = consumerRequire('@vitejs/plugin-rsc');
|
|
538
|
+
const vitePluginRsc = rscMod.default ?? rscMod;
|
|
539
|
+
ctx.timer.end('rsc-plugin-import');
|
|
540
|
+
|
|
541
|
+
// ── Step 2: Compute config-dependent options ────────────────────────
|
|
542
|
+
// encryptionKeyExpr is env-based and doesn't depend on file config.
|
|
543
|
+
const encryptionKeyExpr = resolveEncryptionKeyExpression();
|
|
544
|
+
|
|
545
|
+
// ── Step 3: Pre-load file config for plugin resolution ──────────────
|
|
546
|
+
// Load timber.config.ts eagerly from process.cwd() so we can resolve
|
|
547
|
+
// plugins (like React Compiler) and add them to the top-level array.
|
|
548
|
+
// Vite's config() hook return type is Omit<UserConfig, 'plugins'> —
|
|
549
|
+
// plugins returned from config() are silently ignored. See TIM-632.
|
|
550
|
+
//
|
|
551
|
+
// The config() hook still loads from the correct Vite root (which may
|
|
552
|
+
// differ from cwd in monorepo setups — see TIM-498), but only for
|
|
553
|
+
// non-plugin config merging.
|
|
554
|
+
const earlyFileConfig = loadTimberConfigFile(process.cwd());
|
|
555
|
+
|
|
556
|
+
// ── Step 4: Build rootSync plugin ───────────────────────────────────
|
|
557
|
+
// rootSync loads timber.config.ts from Vite's resolved root and merges
|
|
558
|
+
// it into ctx.config. Plugin resolution is handled eagerly above — the
|
|
559
|
+
// config() hook must NOT return a `plugins` field (Vite ignores it).
|
|
353
560
|
const rootSync: Plugin = {
|
|
354
561
|
name: 'timber-root-sync',
|
|
355
|
-
|
|
356
|
-
// Load timber.config.ts
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
|
|
562
|
+
config(userConfig, { command }) {
|
|
563
|
+
// ── Load timber.config.ts from the correct root ───────────────
|
|
564
|
+
// Vite's `config` hook fires before `configResolved`. The user's
|
|
565
|
+
// `root` option (if set) tells us where the project lives.
|
|
566
|
+
// `resolve()` mirrors Vite's own root resolution logic.
|
|
567
|
+
const viteRoot = resolve(userConfig.root ?? process.cwd());
|
|
360
568
|
ctx.timer.start('config-load');
|
|
361
|
-
const fileConfig =
|
|
569
|
+
const fileConfig = loadTimberConfigFile(viteRoot);
|
|
362
570
|
if (fileConfig) {
|
|
363
571
|
mergeFileConfig(ctx, fileConfig);
|
|
364
572
|
ctx.clientJavascript = resolveClientJavascript(ctx.config);
|
|
365
573
|
}
|
|
574
|
+
// Apply defaults AFTER merge so file-based config isn't overridden
|
|
575
|
+
// by defaults that were baked into the inline config object.
|
|
576
|
+
ctx.config.output ??= 'server';
|
|
366
577
|
ctx.timer.end('config-load');
|
|
367
578
|
|
|
579
|
+
// Warn if the Vite root differs from cwd and the re-loaded config
|
|
580
|
+
// has reactCompiler but the early cwd-based load missed it. In this
|
|
581
|
+
// edge case the user must move reactCompiler to inline config.
|
|
582
|
+
if (viteRoot !== process.cwd()) {
|
|
583
|
+
const hasCompilerInReloaded = !config?.reactCompiler && ctx.config.reactCompiler;
|
|
584
|
+
const hadCompilerInEarly = !config?.reactCompiler && earlyFileConfig?.reactCompiler;
|
|
585
|
+
if (hasCompilerInReloaded && !hadCompilerInEarly) {
|
|
586
|
+
console.warn(
|
|
587
|
+
'[timber] reactCompiler is set in timber.config.ts but could not be ' +
|
|
588
|
+
'registered because the config file is in a non-cwd root directory. ' +
|
|
589
|
+
'Move reactCompiler to the inline timber() config in vite.config.ts, or ' +
|
|
590
|
+
'run vite from the project root directory.'
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
368
595
|
// Force production JSX transform for builds.
|
|
369
596
|
//
|
|
370
597
|
// Vite determines dev vs prod JSX via `isProduction`, which checks
|
|
@@ -401,17 +628,28 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
401
628
|
}
|
|
402
629
|
},
|
|
403
630
|
};
|
|
631
|
+
|
|
632
|
+
// ── Step 5: Resolve optional plugins ────────────────────────────────
|
|
633
|
+
// React Compiler — resolved eagerly from either inline or file config.
|
|
634
|
+
// Vite's config() hook return type is Omit<UserConfig, 'plugins'>, so
|
|
635
|
+
// plugins MUST be in the top-level array — returning them from config()
|
|
636
|
+
// silently drops them. See TIM-632.
|
|
637
|
+
//
|
|
638
|
+
// Inline config takes precedence. File config (from the early cwd-based
|
|
639
|
+
// load) is used when inline config doesn't set reactCompiler.
|
|
640
|
+
const reactCompilerPlugins: PluginOption[] = [];
|
|
641
|
+
const effectiveReactCompiler = config?.reactCompiler ?? earlyFileConfig?.reactCompiler;
|
|
642
|
+
if (effectiveReactCompiler) {
|
|
643
|
+
reactCompilerPlugins.push(resolveReactCompilerPlugin(effectiveReactCompiler, consumerRequire));
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// ── Step 6: Assemble plugin array ─────────────────────────────────────
|
|
404
647
|
// @vitejs/plugin-rsc handles:
|
|
405
648
|
// - RSC/SSR/client environment setup
|
|
406
649
|
// - "use client" directive → client reference proxy transformation
|
|
407
650
|
// - "use server" directive → server reference transformation
|
|
408
651
|
// - Client reference tracking and module map generation
|
|
409
652
|
//
|
|
410
|
-
// Loaded via dynamic import() because @vitejs/plugin-rsc is ESM-only.
|
|
411
|
-
// Vite's config loader uses esbuild to transpile to CJS, which breaks
|
|
412
|
-
// static imports of ESM-only packages. The dynamic import() is preserved
|
|
413
|
-
// by esbuild and runs natively in ESM at runtime.
|
|
414
|
-
//
|
|
415
653
|
// serverHandler: false — timber has its own dev server (timber-dev-server)
|
|
416
654
|
// entries — tells the RSC plugin about timber's virtual entry modules so
|
|
417
655
|
// it correctly wires up the browser entry (needed for React Fast Refresh
|
|
@@ -424,30 +662,6 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
424
662
|
// We do NOT set customBuildApp — the RSC plugin's orchestration is correct
|
|
425
663
|
// and handles bundle ordering, asset manifest generation, and environment
|
|
426
664
|
// imports manifest. See @vitejs/plugin-rsc's buildApp implementation.
|
|
427
|
-
// Resolve @vitejs/plugin-rsc from the consumer's project (process.cwd()),
|
|
428
|
-
// not from timber's own node_modules. This is critical for pnpm link:
|
|
429
|
-
// when linked, timber's node_modules has a separate vite instance, and
|
|
430
|
-
// the RSC plugin must use the same vite instance as the dev server.
|
|
431
|
-
const consumerRequire = createRequire(join(process.cwd(), 'package.json'));
|
|
432
|
-
const rscPluginPath = consumerRequire.resolve('@vitejs/plugin-rsc');
|
|
433
|
-
ctx.timer.start('rsc-plugin-import');
|
|
434
|
-
const rscPluginsPromise = import(pathToFileURL(rscPluginPath).href).then(
|
|
435
|
-
({ default: vitePluginRsc }) => {
|
|
436
|
-
ctx.timer.end('rsc-plugin-import');
|
|
437
|
-
return vitePluginRsc({
|
|
438
|
-
serverHandler: false,
|
|
439
|
-
customClientEntry: true,
|
|
440
|
-
entries: {
|
|
441
|
-
rsc: 'virtual:timber-rsc-entry',
|
|
442
|
-
ssr: 'virtual:timber-ssr-entry',
|
|
443
|
-
client: 'virtual:timber-browser-entry',
|
|
444
|
-
},
|
|
445
|
-
// No custom clientChunks — Rolldown handles natural code splitting.
|
|
446
|
-
// See design/27-chunking-strategy.md and LOCAL-337.
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
);
|
|
450
|
-
|
|
451
665
|
return [
|
|
452
666
|
rootSync,
|
|
453
667
|
timberReactProd(),
|
|
@@ -456,15 +670,14 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
456
670
|
// following Vinext's convention — the RSC plugin's virtual browser entry
|
|
457
671
|
// coordinates with plugin-react via __vite_plugin_react_preamble_installed__.
|
|
458
672
|
react(),
|
|
673
|
+
...reactCompilerPlugins,
|
|
459
674
|
timberServerActionExports(),
|
|
460
|
-
|
|
675
|
+
vitePluginRsc(createRscOptions(ctx, encryptionKeyExpr)),
|
|
461
676
|
timberShims(ctx),
|
|
462
677
|
timberRouting(ctx),
|
|
463
678
|
timberEntries(ctx),
|
|
464
679
|
timberBuildManifest(ctx),
|
|
465
|
-
timberCache(ctx),
|
|
466
680
|
timberStaticBuild(ctx),
|
|
467
|
-
timberDynamicTransform(ctx),
|
|
468
681
|
timberFonts(ctx),
|
|
469
682
|
timberMdx(ctx),
|
|
470
683
|
timberContent(ctx),
|
|
@@ -473,6 +686,7 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
473
686
|
timberBuildReport(ctx), // Post-build: route table with bundle sizes
|
|
474
687
|
timberAdapterBuild(ctx), // Post-build: invoke adapter.buildOutput()
|
|
475
688
|
timberDevLogs(ctx), // Dev-only: forward server console.* to browser console
|
|
689
|
+
timberDevBrowserLogs(ctx), // Dev-only: forward browser console.* to server terminal
|
|
476
690
|
timberDevServer(ctx), // Must be last — configureServer post-hook runs after all watchers
|
|
477
691
|
];
|
|
478
692
|
}
|
|
@@ -481,7 +695,7 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
481
695
|
* Route map interface — augmented by the generated timber-routes.d.ts.
|
|
482
696
|
*
|
|
483
697
|
* Each key is a route path pattern. Values have:
|
|
484
|
-
*
|
|
698
|
+
* segmentParams: shape of URL segment params (e.g. { id: string })
|
|
485
699
|
* searchParams: parsed type from search-params.ts, or {} if none
|
|
486
700
|
*
|
|
487
701
|
* This interface is empty by default and populated via codegen.
|
|
@@ -490,4 +704,26 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
490
704
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
491
705
|
export interface Routes {}
|
|
492
706
|
|
|
707
|
+
/**
|
|
708
|
+
* Type-safe helper for timber.config.ts files.
|
|
709
|
+
*
|
|
710
|
+
* A pass-through identity function that provides autocomplete and
|
|
711
|
+
* type checking for timber configuration. No runtime validation —
|
|
712
|
+
* purely a DX convenience (same pattern as Vite's defineConfig).
|
|
713
|
+
*
|
|
714
|
+
* @example
|
|
715
|
+
* ```ts
|
|
716
|
+
* // timber.config.ts
|
|
717
|
+
* import { defineConfig } from '@timber-js/app';
|
|
718
|
+
*
|
|
719
|
+
* export default defineConfig({
|
|
720
|
+
* output: 'server',
|
|
721
|
+
* pageExtensions: ['tsx', 'ts', 'mdx'],
|
|
722
|
+
* });
|
|
723
|
+
* ```
|
|
724
|
+
*/
|
|
725
|
+
export function defineConfig(config: TimberUserConfig): TimberUserConfig {
|
|
726
|
+
return config;
|
|
727
|
+
}
|
|
728
|
+
|
|
493
729
|
export default timber;
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
import type { Plugin } from 'vite';
|
|
17
17
|
import { join } from 'node:path';
|
|
18
18
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
19
|
-
import type { PluginContext } from '
|
|
20
|
-
import type { TimberPlatformAdapter, TimberConfig } from '
|
|
19
|
+
import type { PluginContext } from '../index.js';
|
|
20
|
+
import type { TimberPlatformAdapter, TimberConfig } from '../adapters/types.js';
|
|
21
21
|
|
|
22
22
|
export function timberAdapterBuild(ctx: PluginContext): Plugin {
|
|
23
23
|
return {
|
|
@@ -50,6 +50,12 @@ export function timberAdapterBuild(ctx: PluginContext): Plugin {
|
|
|
50
50
|
: ctx.buildManifest;
|
|
51
51
|
const json = JSON.stringify(manifest);
|
|
52
52
|
manifestInit = `globalThis.__TIMBER_BUILD_MANIFEST__ = ${json};\n`;
|
|
53
|
+
|
|
54
|
+
// Embed the deployment ID for version skew detection (TIM-446).
|
|
55
|
+
// The server reads this at startup via setDeploymentId().
|
|
56
|
+
if (ctx.deploymentId) {
|
|
57
|
+
manifestInit += `globalThis.__TIMBER_DEPLOYMENT_ID__ = ${JSON.stringify(ctx.deploymentId)};\n`;
|
|
58
|
+
}
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
// Strip JS from the RSC plugin's assets manifest when client JS
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
* Design docs: 18-build-system.md §"Build Manifest", 02-rendering-pipeline.md §"Early Hints"
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { randomUUID } from 'node:crypto';
|
|
19
20
|
import type { Plugin, ResolvedConfig } from 'vite';
|
|
20
|
-
import type { PluginContext } from '
|
|
21
|
-
import type { BuildManifest } from '
|
|
21
|
+
import type { PluginContext } from '../index.js';
|
|
22
|
+
import type { BuildManifest } from '../server/build-manifest.js';
|
|
22
23
|
|
|
23
24
|
// Rollup types used by generateBundle hook — imported from vite which re-exports them.
|
|
24
25
|
// We define minimal interfaces here to avoid a direct 'rollup' dependency.
|
|
@@ -242,6 +243,16 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
242
243
|
configResolved(config: ResolvedConfig) {
|
|
243
244
|
resolvedBase = config.base;
|
|
244
245
|
isDev = config.command === 'serve';
|
|
246
|
+
|
|
247
|
+
// Generate a per-build deployment ID early so virtual:timber-config
|
|
248
|
+
// can serialize it during the load hook (which runs before generateBundle).
|
|
249
|
+
// A random UUID is used instead of a content hash — determinism provides
|
|
250
|
+
// no real benefit here since you almost never redeploy identical code,
|
|
251
|
+
// and a random ID avoids the timing problem where the content hash was
|
|
252
|
+
// only available after generateBundle (TIM-452).
|
|
253
|
+
if (!isDev && !ctx.deploymentId) {
|
|
254
|
+
ctx.deploymentId = randomUUID().replace(/-/g, '').slice(0, 16);
|
|
255
|
+
}
|
|
245
256
|
},
|
|
246
257
|
|
|
247
258
|
resolveId(id: string) {
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
|
|
16
16
|
import { gzipSync } from 'node:zlib';
|
|
17
17
|
import type { Plugin, Logger } from 'vite';
|
|
18
|
-
import type { PluginContext } from '
|
|
19
|
-
import type { SegmentNode, RouteTree } from '
|
|
20
|
-
import { formatSize } from '
|
|
18
|
+
import type { PluginContext } from '../index.js';
|
|
19
|
+
import type { SegmentNode, RouteTree } from '../routing/types.js';
|
|
20
|
+
import { formatSize } from '../utils/format.js';
|
|
21
21
|
|
|
22
22
|
// ─── Public types ─────────────────────────────────────────────────────────
|
|
23
23
|
|