@timber-js/app 0.2.0-alpha.8 → 0.2.0-alpha.80
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/actions-Dg-ANYHb.js +421 -0
- package/dist/_chunks/actions-Dg-ANYHb.js.map +1 -0
- package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
- package/dist/_chunks/als-registry-HS0LGUl2.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-C77ScO0m.js +106 -0
- package/dist/_chunks/define-C77ScO0m.js.map +1 -0
- package/dist/_chunks/define-CZqDwhSu.js +199 -0
- package/dist/_chunks/define-CZqDwhSu.js.map +1 -0
- package/dist/_chunks/define-cookie-C2IkoFGN.js +94 -0
- package/dist/_chunks/define-cookie-C2IkoFGN.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
- package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
- package/dist/_chunks/format-CYBGxKtc.js +14 -0
- package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
- package/dist/_chunks/{interception-BOoWmLUA.js → interception-Dpn_UfAD.js} +171 -97
- package/dist/_chunks/interception-Dpn_UfAD.js.map +1 -0
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
- package/dist/_chunks/merge-search-params-Cm_KIWDX.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-qMsWgy9C.js +478 -0
- package/dist/_chunks/request-context-qMsWgy9C.js.map +1 -0
- package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
- package/dist/_chunks/schema-bridge-C3xl_vfb.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-fHFLF1PE.js +34 -0
- package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
- package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
- package/dist/_chunks/stale-reload-C2plcNtG.js +64 -0
- package/dist/_chunks/stale-reload-C2plcNtG.js.map +1 -0
- package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
- package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
- package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
- package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-Lo_s_pw2.js} +4 -4
- package/dist/_chunks/use-query-states-Lo_s_pw2.js.map +1 -0
- package/dist/_chunks/wrappers-_DTmImGt.js +63 -0
- package/dist/_chunks/wrappers-_DTmImGt.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-kv-cache.d.ts +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +95 -0
- package/dist/adapters/cloudflare-kv-cache.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/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +23 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +142 -80
- 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/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cli.d.ts +6 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +27 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +30 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +23 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +19 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- 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 +10 -4
- package/dist/client/error-boundary.js.map +1 -1
- 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 +7 -21
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +210 -1017
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +18 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +890 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link-pending-store.d.ts +63 -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-ref.d.ts +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-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 +5 -5
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-link-status.d.ts +5 -5
- package/dist/client/use-link-status.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-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/codec.d.ts +33 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +2 -0
- package/dist/config-types.d.ts +210 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts +35 -14
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -83
- package/dist/fonts/css.d.ts +1 -0
- package/dist/fonts/css.d.ts.map +1 -1
- package/dist/index.d.ts +45 -192
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12296 -11901
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +84 -0
- package/dist/plugin-context.d.ts.map +1 -0
- 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 +4 -4
- 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 -7
- 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 +2 -2
- package/dist/search-params/registry.d.ts.map +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 +6 -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-holding-server.d.ts +52 -0
- package/dist/server/dev-holding-server.d.ts.map +1 -0
- package/dist/server/dev-warnings.d.ts +1 -21
- 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 +6 -43
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +38 -2798
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +46 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +2883 -0
- package/dist/server/internal.js.map +1 -0
- 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 +42 -10
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +69 -18
- 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 +112 -43
- 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 +4 -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 +4 -4
- 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/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/headers.d.ts +2 -1
- package/dist/shims/headers.d.ts.map +1 -1
- 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 +3 -2
- 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 +53 -23
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/adapters/cloudflare.ts +342 -28
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +52 -8
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +81 -18
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/sizeof.ts +31 -0
- package/src/cache/timber-cache.ts +24 -20
- package/src/cli.ts +6 -1
- package/src/client/browser-dev.ts +128 -1
- package/src/client/browser-entry/action-dispatch.ts +116 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +145 -0
- package/src/client/browser-entry/index.ts +138 -0
- package/src/client/browser-entry/post-hydration.ts +119 -0
- package/src/client/browser-entry/router-init.ts +193 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +27 -0
- 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 +19 -38
- package/src/client/internal.ts +57 -0
- package/src/client/link-pending-store.ts +111 -0
- package/src/client/link.tsx +329 -97
- 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 +31 -6
- package/src/client/navigation-root.tsx +342 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +299 -72
- package/src/client/rsc-fetch.ts +97 -8
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +72 -3
- package/src/client/top-loader.tsx +16 -8
- package/src/client/use-link-status.ts +7 -7
- package/src/client/use-params.ts +7 -5
- package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
- package/src/client/use-query-states.ts +3 -3
- package/src/client/use-router.ts +1 -1
- package/src/codec.ts +49 -0
- package/src/config-types.ts +208 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +78 -25
- package/src/cookies/index.ts +8 -0
- package/src/fonts/css.ts +2 -1
- package/src/index.ts +258 -354
- package/src/plugin-context.ts +200 -0
- 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 +70 -9
- package/src/plugins/entries.ts +71 -10
- package/src/plugins/fonts.ts +168 -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 +135 -35
- package/src/plugins/static-build.ts +17 -11
- 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 +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +85 -0
- package/src/segment-params/define.ts +279 -0
- package/src/segment-params/index.ts +29 -0
- package/src/server/access-gate.tsx +70 -29
- package/src/server/action-client.ts +21 -2
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +21 -4
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +34 -6
- 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-holding-server.ts +185 -0
- package/src/server/dev-warnings.ts +4 -49
- 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 +280 -120
- package/src/server/index.ts +26 -177
- package/src/server/internal.ts +169 -0
- 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 +227 -62
- package/src/server/primitives.ts +111 -28
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +293 -132
- package/src/server/route-element-builder.ts +283 -191
- 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 +200 -112
- package/src/server/rsc-entry/rsc-payload.ts +65 -18
- package/src/server/rsc-entry/rsc-stream.ts +65 -13
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +168 -38
- 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 +244 -229
- 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 +20 -9
- 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/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/headers.ts +5 -1
- package/src/shims/navigation-client.ts +1 -1
- package/src/shims/navigation.ts +7 -2
- 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 +0 -330
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.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/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.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/client/use-navigation-pending.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 -54
- package/dist/server/response-cache.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -103
- package/src/client/browser-entry.ts +0 -678
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/transition-root.tsx +0 -166
- 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 -410
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin context — internal types and helpers for timber sub-plugins.
|
|
3
|
+
*
|
|
4
|
+
* These are NOT part of the user-facing API. They are consumed by
|
|
5
|
+
* sub-plugins (routing, entries, shims, etc.) via relative imports.
|
|
6
|
+
* The root entry point (index.ts) does not re-export them.
|
|
7
|
+
*
|
|
8
|
+
* Design doc: 18-build-system.md §"Shared Plugin Context"
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { existsSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
import type { RouteTree } from './routing/types';
|
|
15
|
+
import type { BuildManifest } from './server/build-manifest';
|
|
16
|
+
import type { StartupTimer } from './utils/startup-timer';
|
|
17
|
+
import { createStartupTimer } from './utils/startup-timer';
|
|
18
|
+
import type { TimberUserConfig, ClientJavascriptConfig } from './config-types.js';
|
|
19
|
+
import type { HoldingServer } from './server/dev-holding-server.js';
|
|
20
|
+
|
|
21
|
+
// Re-export for sub-plugin convenience — they import from plugin-context.ts
|
|
22
|
+
export type { TimberUserConfig, ClientJavascriptConfig } from './config-types.js';
|
|
23
|
+
|
|
24
|
+
// ── Client JavaScript config ─────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
/** Fully resolved client JavaScript configuration (no optionals). */
|
|
27
|
+
export interface ResolvedClientJavascript {
|
|
28
|
+
disabled: boolean;
|
|
29
|
+
enableHMRInDev: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Resolve `clientJavascript` into a fully resolved config.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveClientJavascript(config: TimberUserConfig): ResolvedClientJavascript {
|
|
36
|
+
if (config.clientJavascript !== undefined) {
|
|
37
|
+
if (typeof config.clientJavascript === 'boolean') {
|
|
38
|
+
return {
|
|
39
|
+
disabled: !config.clientJavascript,
|
|
40
|
+
enableHMRInDev: !config.clientJavascript,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
disabled: config.clientJavascript.disabled,
|
|
45
|
+
enableHMRInDev: config.clientJavascript.enableHMRInDev ?? config.clientJavascript.disabled,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return { disabled: false, enableHMRInDev: false };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ── Plugin Context ────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Shared context object passed to all sub-plugins via closure.
|
|
55
|
+
*
|
|
56
|
+
* Sub-plugins communicate through this context — not through Vite's
|
|
57
|
+
* plugin API or global state.
|
|
58
|
+
* See design/18-build-system.md §"Shared Plugin Context".
|
|
59
|
+
*/
|
|
60
|
+
export interface PluginContext {
|
|
61
|
+
config: TimberUserConfig;
|
|
62
|
+
/** Resolved client JavaScript configuration */
|
|
63
|
+
clientJavascript: ResolvedClientJavascript;
|
|
64
|
+
/** The scanned route tree (populated by timber-routing, consumed by timber-entries) */
|
|
65
|
+
routeTree: RouteTree | null;
|
|
66
|
+
/** Absolute path to the app/ directory */
|
|
67
|
+
appDir: string;
|
|
68
|
+
/** Absolute path to the project root */
|
|
69
|
+
root: string;
|
|
70
|
+
/** Whether the dev server is running (set by timber-root-sync in configResolved) */
|
|
71
|
+
dev: boolean;
|
|
72
|
+
/** CSS build manifest (populated by adapter after client build, null in dev) */
|
|
73
|
+
buildManifest: BuildManifest | null;
|
|
74
|
+
/** Per-build deployment ID for version skew detection (null in dev) */
|
|
75
|
+
deploymentId: string | null;
|
|
76
|
+
/** Startup timer for profiling cold start phases (active in dev, no-op in prod) */
|
|
77
|
+
timer: StartupTimer;
|
|
78
|
+
/** Holding server that binds the port during dev startup (closed in timber-dev-server) */
|
|
79
|
+
holdingServer?: HoldingServer | null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── App directory resolution ──────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the app directory. Checks (in order):
|
|
86
|
+
* 1. Explicit `configAppDir` from timber.config.ts
|
|
87
|
+
* 2. `<root>/app`
|
|
88
|
+
* 3. `<root>/src/app`
|
|
89
|
+
*
|
|
90
|
+
* Throws if none exist.
|
|
91
|
+
*/
|
|
92
|
+
export function resolveAppDir(root: string, configAppDir?: string): string {
|
|
93
|
+
if (configAppDir) {
|
|
94
|
+
const explicit = join(root, configAppDir);
|
|
95
|
+
if (!existsSync(explicit)) {
|
|
96
|
+
throw new Error(`[timber] Configured appDir "${configAppDir}" does not exist at ${explicit}`);
|
|
97
|
+
}
|
|
98
|
+
return explicit;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const rootApp = join(root, 'app');
|
|
102
|
+
if (existsSync(rootApp)) return rootApp;
|
|
103
|
+
|
|
104
|
+
const srcApp = join(root, 'src', 'app');
|
|
105
|
+
if (existsSync(srcApp)) return srcApp;
|
|
106
|
+
|
|
107
|
+
throw new Error(
|
|
108
|
+
`[timber] Could not find app directory. Expected "app/" or "src/app/" in ${root}. ` +
|
|
109
|
+
`You can set appDir in timber.config.ts to specify a custom location.`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ── Plugin context factory ────────────────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
export function createPluginContext(config?: TimberUserConfig, root?: string): PluginContext {
|
|
116
|
+
const projectRoot = root ?? process.cwd();
|
|
117
|
+
const resolvedConfig: TimberUserConfig = { ...config };
|
|
118
|
+
return {
|
|
119
|
+
config: resolvedConfig,
|
|
120
|
+
clientJavascript: resolveClientJavascript(resolvedConfig),
|
|
121
|
+
routeTree: null,
|
|
122
|
+
appDir: join(projectRoot, 'app'),
|
|
123
|
+
root: projectRoot,
|
|
124
|
+
dev: false,
|
|
125
|
+
buildManifest: null,
|
|
126
|
+
deploymentId: null,
|
|
127
|
+
timer: createStartupTimer(),
|
|
128
|
+
holdingServer: null,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ── Config file loading ───────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Load timber.config.ts (or .js, .mjs) from the project root.
|
|
136
|
+
* Returns the config object or null if no config file is found.
|
|
137
|
+
*
|
|
138
|
+
* Uses require() which works for ESM modules on Node 22.12+.
|
|
139
|
+
* This keeps timber() synchronous — no async config loading needed.
|
|
140
|
+
*/
|
|
141
|
+
export function loadTimberConfigFile(root: string): TimberUserConfig | null {
|
|
142
|
+
const configNames = ['timber.config.ts', 'timber.config.js', 'timber.config.mjs'];
|
|
143
|
+
const req = createRequire(join(root, 'package.json'));
|
|
144
|
+
|
|
145
|
+
for (const name of configNames) {
|
|
146
|
+
const configPath = join(root, name);
|
|
147
|
+
if (existsSync(configPath)) {
|
|
148
|
+
const mod = req(configPath);
|
|
149
|
+
return (mod.default ?? mod) as TimberUserConfig;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Detect config keys set in both inline (vite.config.ts) and file (timber.config.ts)
|
|
157
|
+
* and warn the user. The `output` key is excluded because it defaults to 'server'
|
|
158
|
+
* in createPluginContext and would always appear as an inline key.
|
|
159
|
+
*
|
|
160
|
+
* Returns the list of conflicting key names (for testing).
|
|
161
|
+
*/
|
|
162
|
+
export function warnConfigConflicts(
|
|
163
|
+
inline: TimberUserConfig,
|
|
164
|
+
fileConfig: TimberUserConfig
|
|
165
|
+
): string[] {
|
|
166
|
+
const conflicts: string[] = [];
|
|
167
|
+
for (const key of Object.keys(fileConfig) as (keyof TimberUserConfig)[]) {
|
|
168
|
+
if (key in inline && inline[key] !== undefined) {
|
|
169
|
+
conflicts.push(key);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (conflicts.length > 0) {
|
|
173
|
+
console.warn(
|
|
174
|
+
`[timber] Config conflict: ${conflicts.map((k) => `"${k}"`).join(', ')} set in both ` +
|
|
175
|
+
`vite.config.ts (inline) and timber.config.ts. ` +
|
|
176
|
+
`Move all config to timber.config.ts to avoid confusion. ` +
|
|
177
|
+
`The inline value from vite.config.ts will be used.`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
return conflicts;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Merge file-based config into ctx.config. Inline config (already in ctx.config)
|
|
185
|
+
* takes precedence — file config only fills in missing fields.
|
|
186
|
+
*/
|
|
187
|
+
export function mergeFileConfig(ctx: PluginContext, fileConfig: TimberUserConfig): void {
|
|
188
|
+
const inline = ctx.config;
|
|
189
|
+
warnConfigConflicts(inline, fileConfig);
|
|
190
|
+
|
|
191
|
+
ctx.config = {
|
|
192
|
+
...fileConfig,
|
|
193
|
+
...inline,
|
|
194
|
+
...(fileConfig.limits && inline.limits
|
|
195
|
+
? { limits: { ...fileConfig.limits, ...inline.limits } }
|
|
196
|
+
: {}),
|
|
197
|
+
...(fileConfig.dev && inline.dev ? { dev: { ...fileConfig.dev, ...inline.dev } } : {}),
|
|
198
|
+
...(fileConfig.mdx && inline.mdx ? { mdx: { ...fileConfig.mdx, ...inline.mdx } } : {}),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
@@ -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 '../plugin-context.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 '../plugin-context.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 '../plugin-context.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
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client chunk grouping strategy for @vitejs/plugin-rsc.
|
|
3
|
+
*
|
|
4
|
+
* Groups client reference modules by layout boundary to balance route-scoped
|
|
5
|
+
* code splitting with HTTP request count. A constant group name would collapse
|
|
6
|
+
* all routes into one chunk (every page downloads every client component).
|
|
7
|
+
* Per-serverChunk grouping creates many sub-500B files. Layout-boundary
|
|
8
|
+
* grouping is the middle ground.
|
|
9
|
+
*
|
|
10
|
+
* See design/27-chunking-strategy.md, TIM-440, TIM-499.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Derive a chunk group name for a client reference module.
|
|
15
|
+
*
|
|
16
|
+
* Groups by the first non-group route segment under appDir so that all
|
|
17
|
+
* client components belonging to the same layout boundary land in one
|
|
18
|
+
* chunk. For example:
|
|
19
|
+
* - `facade:app/dashboard/settings/page.tsx` → `"client-dashboard"`
|
|
20
|
+
* - `facade:app/(group-a)/group-page-a/page.tsx` → `"client-group-page-a"`
|
|
21
|
+
* - `facade:app/layout.tsx` (root layout) → `"client-shared"`
|
|
22
|
+
* - `shared:...` (shared across chunks) → `"client-shared"`
|
|
23
|
+
*
|
|
24
|
+
* This balances route-scoped code splitting with HTTP request count:
|
|
25
|
+
* fewer chunks than per-serverChunk, but still avoids downloading every
|
|
26
|
+
* client component on every page.
|
|
27
|
+
*/
|
|
28
|
+
export function clientChunkGroup(
|
|
29
|
+
meta: { id: string; normalizedId: string; serverChunk: string },
|
|
30
|
+
appDir: string
|
|
31
|
+
): string {
|
|
32
|
+
const { normalizedId, serverChunk } = meta;
|
|
33
|
+
|
|
34
|
+
// Shared chunks (not associated with a single route entry) get one group.
|
|
35
|
+
if (serverChunk.startsWith('shared:')) return 'client-shared';
|
|
36
|
+
|
|
37
|
+
// Derive the layout boundary from the file's location relative to the
|
|
38
|
+
// app directory. normalizedId is root-relative (e.g. "app/dashboard/shell.tsx"
|
|
39
|
+
// or "src/app/dashboard/shell.tsx"). We find the "app/" prefix and walk
|
|
40
|
+
// segments after it to find the first non-group directory.
|
|
41
|
+
const relPath = normalizedId.replace(/\\/g, '/');
|
|
42
|
+
|
|
43
|
+
// Find the app directory boundary in the path. The last segment of appDir
|
|
44
|
+
// is the app folder name (usually "app").
|
|
45
|
+
const appDirName = appDir.replace(/\\/g, '/').split('/').pop() || 'app';
|
|
46
|
+
const appIdx = relPath.indexOf(appDirName + '/');
|
|
47
|
+
if (appIdx === -1) return 'client-shared';
|
|
48
|
+
|
|
49
|
+
const withinApp = relPath.slice(appIdx + appDirName.length + 1);
|
|
50
|
+
const segments = withinApp.split('/');
|
|
51
|
+
|
|
52
|
+
// Find first directory segment that isn't a route group like (group-a)
|
|
53
|
+
for (const seg of segments) {
|
|
54
|
+
// Skip the filename itself
|
|
55
|
+
if (seg.includes('.')) break;
|
|
56
|
+
// Skip route groups — parenthesized segments like (group-a)
|
|
57
|
+
if (seg.startsWith('(') && seg.endsWith(')')) continue;
|
|
58
|
+
// Found a real route segment
|
|
59
|
+
return `client-${seg}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Root-level files (layout.tsx, page.tsx directly in app/) go into the
|
|
63
|
+
// shared group since the root layout is loaded on every page.
|
|
64
|
+
return 'client-shared';
|
|
65
|
+
}
|
package/src/plugins/content.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import type { Plugin } from 'vite';
|
|
12
12
|
import { existsSync } from 'node:fs';
|
|
13
13
|
import { join } from 'node:path';
|
|
14
|
-
import type { PluginContext } from '
|
|
14
|
+
import type { PluginContext } from '../plugin-context.js';
|
|
15
15
|
|
|
16
16
|
const CONFIG_FILE_NAMES = [
|
|
17
17
|
'content-collections.ts',
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* timber-dev-browser-logs — Forwards browser console output to the server terminal.
|
|
3
|
+
*
|
|
4
|
+
* Injects a small inline script in dev mode that intercepts browser
|
|
5
|
+
* `console.error`, `console.warn`, and `console.info`, then forwards
|
|
6
|
+
* messages to the server via Vite's HMR WebSocket.
|
|
7
|
+
*
|
|
8
|
+
* The server-side listener formats and prints the messages with color-coded
|
|
9
|
+
* prefixes: [browser:error], [browser:warn], [browser:info].
|
|
10
|
+
*
|
|
11
|
+
* Dev-only: this plugin only runs during `vite dev`.
|
|
12
|
+
* No runtime overhead in production.
|
|
13
|
+
*
|
|
14
|
+
* See TIM-513 for design context.
|
|
15
|
+
* See design/18-build-system.md §"Dev Server" for sub-plugin architecture.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { Plugin, ViteDevServer } from 'vite';
|
|
19
|
+
import type { PluginContext } from '../plugin-context.js';
|
|
20
|
+
|
|
21
|
+
// ─── Types ───────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
/** Log levels forwarded from the browser. */
|
|
24
|
+
export type BrowserLogLevel = 'error' | 'warn' | 'info';
|
|
25
|
+
|
|
26
|
+
/** Configuration value for devBrowserLogs in timber.config.ts. */
|
|
27
|
+
export type DevBrowserLogsConfig = BrowserLogLevel | 'none' | undefined;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Payload sent from browser to server via Vite's HMR WebSocket.
|
|
31
|
+
* Kept small — truncated before sending.
|
|
32
|
+
*/
|
|
33
|
+
export interface BrowserLogPayload {
|
|
34
|
+
level: BrowserLogLevel;
|
|
35
|
+
/** Serialized message string. */
|
|
36
|
+
message: string;
|
|
37
|
+
/** Error stack trace, if the first argument was an Error. */
|
|
38
|
+
stack: string | null;
|
|
39
|
+
/** Source URL and line number, if available. */
|
|
40
|
+
source: string | null;
|
|
41
|
+
/** Timestamp in ms (Date.now()) from the browser. */
|
|
42
|
+
timestamp: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ─── Constants ───────────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
/** Max message size in bytes before truncation. */
|
|
48
|
+
const MAX_MESSAGE_BYTES = 2048;
|
|
49
|
+
|
|
50
|
+
/** HMR event name for browser→server log forwarding. */
|
|
51
|
+
const HMR_EVENT = 'timber:browser-log';
|
|
52
|
+
|
|
53
|
+
/** ANSI color codes for terminal output. */
|
|
54
|
+
const COLORS = {
|
|
55
|
+
red: '\x1b[31m',
|
|
56
|
+
yellow: '\x1b[33m',
|
|
57
|
+
blue: '\x1b[34m',
|
|
58
|
+
dim: '\x1b[2m',
|
|
59
|
+
reset: '\x1b[0m',
|
|
60
|
+
} as const;
|
|
61
|
+
|
|
62
|
+
/** Level severity ordering for threshold comparison. */
|
|
63
|
+
const LEVEL_SEVERITY: Record<BrowserLogLevel | 'none', number> = {
|
|
64
|
+
none: 0,
|
|
65
|
+
info: 1,
|
|
66
|
+
warn: 2,
|
|
67
|
+
error: 3,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// ─── Formatting ──────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Format a browser log payload for server terminal output.
|
|
74
|
+
*
|
|
75
|
+
* Produces color-coded output like:
|
|
76
|
+
* [browser:error] Uncaught TypeError: x is not a function
|
|
77
|
+
* at App (app.tsx:10:5)
|
|
78
|
+
* [browser:warn] Deprecation warning (app/page.tsx:42:12)
|
|
79
|
+
*/
|
|
80
|
+
export function formatBrowserLog(payload: BrowserLogPayload): string {
|
|
81
|
+
const { level, message, stack, source } = payload;
|
|
82
|
+
|
|
83
|
+
// Color-coded prefix
|
|
84
|
+
const color = level === 'error' ? COLORS.red : level === 'warn' ? COLORS.yellow : COLORS.blue;
|
|
85
|
+
const prefix = `${color}[browser:${level}]${COLORS.reset}`;
|
|
86
|
+
|
|
87
|
+
// Source suffix
|
|
88
|
+
const sourceSuffix = source ? ` ${COLORS.dim}(${source})${COLORS.reset}` : '';
|
|
89
|
+
|
|
90
|
+
let output = `${prefix} ${message}${sourceSuffix}`;
|
|
91
|
+
|
|
92
|
+
// Append stack trace indented
|
|
93
|
+
if (stack) {
|
|
94
|
+
const indented = stack
|
|
95
|
+
.split('\n')
|
|
96
|
+
.map((line) => ` ${COLORS.dim}${line}${COLORS.reset}`)
|
|
97
|
+
.join('\n');
|
|
98
|
+
output += `\n${indented}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return output;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ─── Level Filtering ─────────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Check if a log at `level` should be forwarded given the configured threshold.
|
|
108
|
+
*
|
|
109
|
+
* The threshold acts as a minimum severity:
|
|
110
|
+
* - 'error' → only errors
|
|
111
|
+
* - 'warn' → errors + warnings
|
|
112
|
+
* - 'info' → errors + warnings + info
|
|
113
|
+
* - 'none' → nothing
|
|
114
|
+
*/
|
|
115
|
+
export function shouldForwardLevel(
|
|
116
|
+
level: BrowserLogLevel,
|
|
117
|
+
threshold: BrowserLogLevel | 'none'
|
|
118
|
+
): boolean {
|
|
119
|
+
if (threshold === 'none') return false;
|
|
120
|
+
return LEVEL_SEVERITY[level] >= LEVEL_SEVERITY[threshold];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ─── Truncation ──────────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Truncate a message to `maxBytes` to avoid flooding the terminal.
|
|
127
|
+
* Appends a suffix indicating how many bytes were dropped.
|
|
128
|
+
*/
|
|
129
|
+
export function truncateMessage(message: string, maxBytes: number): string {
|
|
130
|
+
if (message.length <= maxBytes) return message;
|
|
131
|
+
|
|
132
|
+
const truncated = message.slice(0, maxBytes);
|
|
133
|
+
const droppedBytes = message.length - maxBytes;
|
|
134
|
+
return `${truncated}… [truncated ${droppedBytes} bytes]`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ─── Client Injection Script ─────────────────────────────────────────────
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Generate the inline script injected into the browser in dev mode.
|
|
141
|
+
*
|
|
142
|
+
* This script:
|
|
143
|
+
* 1. Saves references to the original console methods
|
|
144
|
+
* 2. Wraps `console.error`, `console.warn`, `console.info`
|
|
145
|
+
* 3. Calls the original first (browser devtools still work)
|
|
146
|
+
* 4. Serializes and forwards via `import.meta.hot.send()`
|
|
147
|
+
* 5. Truncates messages to MAX_MESSAGE_BYTES
|
|
148
|
+
*
|
|
149
|
+
* The script is minimal and self-contained — no imports, no dependencies.
|
|
150
|
+
*/
|
|
151
|
+
export function generateClientScript(threshold: BrowserLogLevel | 'none'): string {
|
|
152
|
+
if (threshold === 'none') return '';
|
|
153
|
+
|
|
154
|
+
// Only intercept levels that meet the threshold
|
|
155
|
+
const levels: BrowserLogLevel[] = ['error', 'warn', 'info'].filter((l) =>
|
|
156
|
+
shouldForwardLevel(l as BrowserLogLevel, threshold)
|
|
157
|
+
) as BrowserLogLevel[];
|
|
158
|
+
|
|
159
|
+
if (levels.length === 0) return '';
|
|
160
|
+
|
|
161
|
+
return `
|
|
162
|
+
(function() {
|
|
163
|
+
if (!import.meta.hot) return;
|
|
164
|
+
var MAX_BYTES = ${MAX_MESSAGE_BYTES};
|
|
165
|
+
var levels = ${JSON.stringify(levels)};
|
|
166
|
+
var originals = {};
|
|
167
|
+
|
|
168
|
+
function serialize(arg) {
|
|
169
|
+
if (arg === null) return 'null';
|
|
170
|
+
if (arg === undefined) return 'undefined';
|
|
171
|
+
if (arg instanceof Error) return arg.stack || arg.message || String(arg);
|
|
172
|
+
if (typeof arg === 'object') {
|
|
173
|
+
try { return JSON.stringify(arg); } catch(e) { return String(arg); }
|
|
174
|
+
}
|
|
175
|
+
return String(arg);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function truncate(s) {
|
|
179
|
+
if (s.length <= MAX_BYTES) return s;
|
|
180
|
+
return s.slice(0, MAX_BYTES) + '... [truncated ' + (s.length - MAX_BYTES) + ' bytes]';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
levels.forEach(function(level) {
|
|
184
|
+
originals[level] = console[level];
|
|
185
|
+
console[level] = function() {
|
|
186
|
+
originals[level].apply(console, arguments);
|
|
187
|
+
try {
|
|
188
|
+
var args = Array.prototype.slice.call(arguments);
|
|
189
|
+
var firstArg = args[0];
|
|
190
|
+
var stack = null;
|
|
191
|
+
var source = null;
|
|
192
|
+
|
|
193
|
+
if (firstArg instanceof Error) {
|
|
194
|
+
stack = firstArg.stack || null;
|
|
195
|
+
source = null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
var message = args.map(serialize).join(' ');
|
|
199
|
+
message = truncate(message);
|
|
200
|
+
|
|
201
|
+
import.meta.hot.send('${HMR_EVENT}', {
|
|
202
|
+
level: level,
|
|
203
|
+
message: message,
|
|
204
|
+
stack: stack,
|
|
205
|
+
source: source,
|
|
206
|
+
timestamp: Date.now()
|
|
207
|
+
});
|
|
208
|
+
} catch(e) {
|
|
209
|
+
// Never let log forwarding break the page
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
})();
|
|
214
|
+
`.trim();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ─── Plugin ──────────────────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Create the timber-dev-browser-logs Vite plugin.
|
|
221
|
+
*
|
|
222
|
+
* - `configureServer`: Listens for HMR messages and prints them to the terminal
|
|
223
|
+
* - `transformIndexHtml`: Injects the client-side interception script
|
|
224
|
+
*
|
|
225
|
+
* Only active during `vite dev` (apply: 'serve').
|
|
226
|
+
*/
|
|
227
|
+
export function timberDevBrowserLogs(ctx: PluginContext): Plugin {
|
|
228
|
+
return {
|
|
229
|
+
name: 'timber-dev-browser-logs',
|
|
230
|
+
apply: 'serve',
|
|
231
|
+
|
|
232
|
+
configureServer(server: ViteDevServer) {
|
|
233
|
+
const threshold = ctx.config.devBrowserLogs ?? 'warn';
|
|
234
|
+
if (threshold === 'none') {
|
|
235
|
+
// Clear any stale script from a prior server instance (e.g. HMR reconfigure)
|
|
236
|
+
delete (globalThis as Record<string, unknown>).__timber_dev_browser_log_script;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Register the client injection script on globalThis so the RSC entry
|
|
241
|
+
// can include it in headHtml for all Timber route responses.
|
|
242
|
+
// transformIndexHtml only runs for Vite's index.html fallback, not
|
|
243
|
+
// for responses served by createTimberMiddleware (TIM-575).
|
|
244
|
+
const script = generateClientScript(threshold);
|
|
245
|
+
if (script) {
|
|
246
|
+
(globalThis as Record<string, unknown>).__timber_dev_browser_log_script =
|
|
247
|
+
`<script type="module">${script}</script>`;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Listen for browser log messages via HMR WebSocket
|
|
251
|
+
server.hot.on(HMR_EVENT, (payload: BrowserLogPayload) => {
|
|
252
|
+
try {
|
|
253
|
+
// Validate level
|
|
254
|
+
if (!shouldForwardLevel(payload.level, threshold)) return;
|
|
255
|
+
|
|
256
|
+
// Truncate server-side too (defense in depth)
|
|
257
|
+
payload.message = truncateMessage(payload.message, MAX_MESSAGE_BYTES);
|
|
258
|
+
|
|
259
|
+
const formatted = formatBrowserLog(payload);
|
|
260
|
+
|
|
261
|
+
// Use the correct console method for the log level
|
|
262
|
+
if (payload.level === 'error') {
|
|
263
|
+
process.stderr.write(formatted + '\n');
|
|
264
|
+
} else {
|
|
265
|
+
process.stdout.write(formatted + '\n');
|
|
266
|
+
}
|
|
267
|
+
} catch {
|
|
268
|
+
// Never let log forwarding crash the server
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
transformIndexHtml() {
|
|
274
|
+
const threshold = ctx.config.devBrowserLogs ?? 'warn';
|
|
275
|
+
const script = generateClientScript(threshold);
|
|
276
|
+
if (!script) return [];
|
|
277
|
+
|
|
278
|
+
return [
|
|
279
|
+
{
|
|
280
|
+
tag: 'script',
|
|
281
|
+
attrs: { type: 'module' },
|
|
282
|
+
children: script,
|
|
283
|
+
injectTo: 'head' as const,
|
|
284
|
+
},
|
|
285
|
+
];
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
}
|