@timber-js/app 0.2.0-alpha.14 → 0.2.0-alpha.141
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/actions-DzFMnUAR.js +1147 -0
- package/dist/_chunks/actions-DzFMnUAR.js.map +1 -0
- package/dist/_chunks/build-output-helper-B20ZuTSA.js +102 -0
- package/dist/_chunks/build-output-helper-B20ZuTSA.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-D2IpXicg.js +785 -0
- package/dist/_chunks/cli-schema-sync-D2IpXicg.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-DH-M8Poy.js +2 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
- package/dist/_chunks/define-C3RvHQPK.js +195 -0
- package/dist/_chunks/define-C3RvHQPK.js.map +1 -0
- package/dist/_chunks/define-DMVhsipD.js +112 -0
- package/dist/_chunks/define-DMVhsipD.js.map +1 -0
- package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
- package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
- package/dist/_chunks/format-CfwjgPz9.js +14 -0
- package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
- package/dist/_chunks/handler-store-DjISKYEB.js +54 -0
- package/dist/_chunks/handler-store-DjISKYEB.js.map +1 -0
- package/dist/_chunks/href-validation-EZktELp8.js +124 -0
- package/dist/_chunks/href-validation-EZktELp8.js.map +1 -0
- package/dist/_chunks/logger-Dt-jQaBO.js +291 -0
- package/dist/_chunks/logger-Dt-jQaBO.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-BjepjefT.js} +32 -19
- package/dist/_chunks/metadata-routes-BjepjefT.js.map +1 -0
- package/dist/_chunks/navigation-root-DLc4s4ZC.js +103 -0
- package/dist/_chunks/navigation-root-DLc4s4ZC.js.map +1 -0
- package/dist/_chunks/registry-DbJPKoBp.js +20 -0
- package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
- package/dist/_chunks/resolve-schema-Dj8tQloi.js +77 -0
- package/dist/_chunks/resolve-schema-Dj8tQloi.js.map +1 -0
- package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
- package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
- package/dist/_chunks/schema-bridge-DK_89h8O.js +86 -0
- package/dist/_chunks/schema-bridge-DK_89h8O.js.map +1 -0
- package/dist/_chunks/segment-classify-CDDRVKs7.js +137 -0
- package/dist/_chunks/segment-classify-CDDRVKs7.js.map +1 -0
- package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
- package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
- package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
- package/dist/_chunks/tracing-M_zKubhk.js +358 -0
- package/dist/_chunks/tracing-M_zKubhk.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-CbeQmext.js} +7 -20
- package/dist/_chunks/use-query-states-CbeQmext.js.map +1 -0
- package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
- package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
- package/dist/_chunks/validation-taUkvA4Q.js +113 -0
- package/dist/_chunks/validation-taUkvA4Q.js.map +1 -0
- package/dist/_chunks/walkers-7FBPM-hX.js +724 -0
- package/dist/_chunks/walkers-7FBPM-hX.js.map +1 -0
- package/dist/_chunks/{format-RyoGQL74.js → warnings-CNPXaypM.js} +6 -45
- package/dist/_chunks/warnings-CNPXaypM.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +28 -0
- package/dist/adapters/build-output-helper.d.ts.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 +142 -38
- 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 +154 -48
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +16 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- 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 +165 -117
- 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-schema-sync.d.ts +39 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +48 -6
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +34 -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 +26 -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 +29 -6
- 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 +16 -27
- 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 +10 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +183 -1134
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +19 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +925 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link-pending-store.d.ts +65 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +69 -60
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +27 -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 +14 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +46 -9
- 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 +79 -10
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +46 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +3 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +49 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/segment-update-context.d.ts +21 -0
- package/dist/client/segment-update-context.d.ts.map +1 -0
- package/dist/client/shallow-url.d.ts +10 -0
- package/dist/client/shallow-url.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/state.d.ts +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-cookie.d.ts +12 -0
- package/dist/client/use-cookie.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-pathname.d.ts.map +1 -1
- package/dist/client/use-pending-navigation.d.ts +23 -0
- 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/client/use-router.d.ts.map +1 -1
- package/dist/client/use-search-params.d.ts +7 -5
- package/dist/client/use-search-params.d.ts.map +1 -1
- package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
- package/dist/client/use-segment-params.d.ts.map +1 -0
- package/dist/codec.d.ts +69 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +75 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +294 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/config-validation.d.ts +51 -0
- package/dist/config-validation.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 +58 -25
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +2 -1
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +251 -36
- package/dist/cookies/index.js.map +1 -1
- package/dist/cookies/json-cookie.d.ts +64 -0
- package/dist/cookies/json-cookie.d.ts.map +1 -0
- package/dist/cookies/validation.d.ts +34 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/dev-tools/404-page.d.ts +46 -0
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/dev-tools/browser-logs.d.ts +84 -0
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/dev-tools/error-page.d.ts +58 -0
- package/dist/dev-tools/error-page.d.ts.map +1 -0
- package/dist/dev-tools/holding-server.d.ts +54 -0
- package/dist/dev-tools/holding-server.d.ts.map +1 -0
- package/dist/dev-tools/index.d.ts +31 -0
- package/dist/dev-tools/index.d.ts.map +1 -0
- package/dist/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
- package/dist/dev-tools/instrumentation.d.ts.map +1 -0
- package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
- package/dist/dev-tools/logger.d.ts.map +1 -0
- package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +2 -2
- package/dist/dev-tools/logs.d.ts.map +1 -0
- package/dist/dev-tools/overlay.d.ts +91 -0
- package/dist/dev-tools/overlay.d.ts.map +1 -0
- package/dist/dev-tools/stack-classifier.d.ts +34 -0
- package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
- package/dist/dev-tools/terminal.d.ts +28 -0
- package/dist/dev-tools/terminal.d.ts.map +1 -0
- package/dist/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +2 -22
- package/dist/dev-tools/warnings.d.ts.map +1 -0
- package/dist/fonts/ast.d.ts +98 -6
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +48 -0
- package/dist/fonts/bundle.d.ts.map +1 -0
- package/dist/fonts/dev-middleware.d.ts +22 -0
- package/dist/fonts/dev-middleware.d.ts.map +1 -0
- package/dist/fonts/local.d.ts +1 -1
- package/dist/fonts/pipeline.d.ts +172 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +78 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +47 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +94 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +46 -180
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5315 -12687
- package/dist/index.js.map +1 -1
- package/dist/params/codec-registry.d.ts +26 -0
- package/dist/params/codec-registry.d.ts.map +1 -0
- package/dist/params/define-schema.d.ts +81 -0
- package/dist/params/define-schema.d.ts.map +1 -0
- package/dist/params/index.d.ts +5 -0
- package/dist/params/index.d.ts.map +1 -0
- package/dist/params/index.js +34 -0
- package/dist/params/index.js.map +1 -0
- package/dist/params/resolve-schema.d.ts +34 -0
- package/dist/params/resolve-schema.d.ts.map +1 -0
- package/dist/plugin-context.d.ts +114 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +20 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +7 -3
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +9 -7
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/cache.d.ts +31 -0
- package/dist/plugins/cache.d.ts.map +1 -0
- package/dist/plugins/client-chunks.d.ts +39 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/cloudflare-wasm.d.ts +18 -0
- package/dist/plugins/cloudflare-wasm.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-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 +17 -73
- 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 +5 -26
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +67 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +60 -0
- package/dist/routing/codegen-types.d.ts.map +1 -0
- package/dist/routing/codegen.d.ts +7 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts +41 -0
- package/dist/routing/convention-lint.d.ts.map +1 -0
- package/dist/routing/index.d.ts +7 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -2
- package/dist/routing/link-codegen.d.ts +90 -0
- package/dist/routing/link-codegen.d.ts.map +1 -0
- package/dist/routing/scanner.d.ts +1 -10
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/schema-validation.d.ts +35 -0
- package/dist/routing/schema-validation.d.ts.map +1 -0
- package/dist/routing/segment-classify.d.ts +75 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/segment-codegen.d.ts +38 -0
- package/dist/routing/segment-codegen.d.ts.map +1 -0
- package/dist/routing/types.d.ts +77 -25
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +51 -0
- package/dist/routing/walkers.d.ts.map +1 -0
- 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 +157 -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 +34 -441
- package/dist/search-params/index.js.map +1 -1
- 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 +89 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +3 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +2 -0
- package/dist/server/access-gate.d.ts +8 -3
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +41 -6
- 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 +35 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +6 -14
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +70 -11
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +1 -15
- package/dist/server/asset-headers.d.ts.map +1 -1
- package/dist/server/body-limits.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +8 -2
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/coalesce-tick.d.ts +40 -0
- package/dist/server/coalesce-tick.d.ts.map +1 -0
- package/dist/server/cookie-context.d.ts +170 -0
- package/dist/server/cookie-context.d.ts.map +1 -0
- package/dist/server/cookie-parsing.d.ts +51 -0
- package/dist/server/cookie-parsing.d.ts.map +1 -0
- package/dist/server/csrf.d.ts +3 -2
- package/dist/server/csrf.d.ts.map +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-boundary.d.ts +90 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts +1 -1
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-source-map.d.ts +22 -0
- package/dist/server/dev-source-map.d.ts.map +1 -0
- package/dist/server/early-hints-sender.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -11
- 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 +12 -7
- 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-injector-core.d.ts +213 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +81 -41
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +10 -46
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +170 -2911
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +48 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +3126 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/logger.d.ts +39 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/metadata-routes.d.ts +23 -7
- package/dist/server/metadata-routes.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +36 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +112 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/param-coercion.d.ts +54 -0
- package/dist/server/param-coercion.d.ts.map +1 -0
- package/dist/server/pipeline-helpers.d.ts +95 -0
- package/dist/server/pipeline-helpers.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-outcome.d.ts +49 -0
- package/dist/server/pipeline-outcome.d.ts.map +1 -0
- package/dist/server/pipeline-phases.d.ts +56 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +111 -19
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/port-resolution.d.ts +117 -0
- package/dist/server/port-resolution.d.ts.map +1 -0
- package/dist/server/primitives.d.ts +74 -20
- 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 +62 -107
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +28 -2
- 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 +25 -36
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts +12 -3
- 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 +50 -6
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +19 -8
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +50 -0
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
- package/dist/server/rsc-entry/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 +17 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +34 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sensitive-fields.d.ts +74 -0
- package/dist/server/sensitive-fields.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-bridge-types.d.ts +121 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -0
- package/dist/server/ssr-entry.d.ts +2 -43
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +64 -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/state-tree-diff.d.ts +12 -5
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +16 -11
- 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 +5 -5
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +62 -30
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/tree-match.d.ts +49 -0
- package/dist/server/tree-match.d.ts.map +1 -0
- package/dist/server/types.d.ts +71 -6
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/utils/escape-html.d.ts +14 -0
- package/dist/server/utils/escape-html.d.ts.map +1 -0
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/shared/href-validation.d.ts +38 -0
- package/dist/shared/href-validation.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/image.d.ts +1 -1
- package/dist/shims/navigation-client.d.ts +3 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +11 -5
- package/dist/shims/navigation.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 +63 -22
- package/src/adapters/build-output-helper.ts +139 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/adapters/cloudflare.ts +350 -76
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +147 -60
- package/src/adapters/shared.ts +40 -0
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +39 -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 +33 -0
- package/src/cache/timber-cache.ts +52 -24
- package/src/cli-schema-sync.ts +295 -0
- package/src/cli.ts +76 -8
- package/src/client/browser-dev.ts +153 -1
- package/src/client/browser-entry/action-dispatch.ts +125 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +153 -0
- package/src/client/browser-entry/index.ts +151 -0
- package/src/client/browser-entry/post-hydration.ts +113 -0
- package/src/client/browser-entry/router-init.ts +219 -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 +99 -22
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +67 -45
- package/src/client/internal.ts +58 -0
- package/src/client/link-pending-store.ts +116 -0
- package/src/client/link.tsx +343 -150
- package/src/client/nav-link-store.ts +37 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +338 -0
- package/src/client/navigation-context.ts +35 -7
- package/src/client/navigation-root.tsx +347 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +418 -128
- package/src/client/rsc-fetch.ts +208 -10
- package/src/client/segment-cache.ts +6 -3
- package/src/client/segment-outlet.tsx +77 -0
- package/src/client/segment-update-context.ts +42 -0
- package/src/client/shallow-url.ts +22 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +72 -3
- package/src/client/state.ts +2 -2
- package/src/client/top-loader.tsx +11 -9
- package/src/client/use-cookie.ts +31 -2
- package/src/client/use-link-status.ts +7 -7
- package/src/client/use-pathname.ts +1 -0
- package/src/client/use-pending-navigation.ts +40 -0
- package/src/client/use-query-states.ts +9 -3
- package/src/client/use-router.ts +4 -1
- package/src/client/use-search-params.ts +26 -44
- package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
- package/src/codec.ts +147 -0
- package/src/config-types.ts +292 -0
- package/src/config-validation.ts +303 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +233 -53
- package/src/cookies/index.ts +12 -1
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +192 -0
- package/src/dev-tools/404-page.ts +387 -0
- package/src/dev-tools/browser-logs.ts +291 -0
- package/src/dev-tools/error-page.ts +507 -0
- package/src/dev-tools/holding-server.ts +187 -0
- package/src/dev-tools/index.ts +90 -0
- package/src/dev-tools/instrumentation.ts +176 -0
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +9 -5
- package/src/dev-tools/overlay.ts +469 -0
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/dev-tools/terminal.ts +183 -0
- package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +5 -50
- package/src/fonts/ast.ts +525 -16
- package/src/fonts/bundle.ts +131 -0
- package/src/fonts/dev-middleware.ts +74 -0
- package/src/fonts/local.ts +3 -3
- package/src/fonts/pipeline.ts +337 -0
- package/src/fonts/transform.ts +317 -0
- package/src/fonts/types.ts +52 -1
- package/src/fonts/virtual-modules.ts +235 -0
- package/src/index.ts +415 -345
- package/src/params/codec-registry.ts +34 -0
- package/src/params/define-schema.ts +115 -0
- package/src/params/index.ts +17 -0
- package/src/params/resolve-schema.ts +116 -0
- package/src/plugin-context.ts +247 -0
- package/src/plugins/adapter-build.ts +98 -4
- package/src/plugins/build-manifest.ts +168 -23
- package/src/plugins/build-report.ts +16 -25
- package/src/plugins/cache.ts +180 -0
- package/src/plugins/client-chunks.ts +113 -0
- package/src/plugins/cloudflare-wasm.ts +103 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +179 -37
- package/src/plugins/entries.ts +110 -8
- package/src/plugins/fonts.ts +167 -655
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/routing.ts +386 -47
- package/src/plugins/server-bundle.ts +59 -3
- package/src/plugins/shims.ts +136 -35
- package/src/plugins/static-build.ts +15 -89
- package/src/routing/codegen-shared.ts +115 -0
- package/src/routing/codegen-types.ts +61 -0
- package/src/routing/codegen.ts +321 -177
- package/src/routing/convention-lint.ts +357 -0
- package/src/routing/index.ts +10 -1
- package/src/routing/interception.ts +1 -1
- package/src/routing/link-codegen.ts +310 -0
- package/src/routing/scanner.ts +165 -110
- package/src/routing/schema-validation.ts +149 -0
- package/src/routing/segment-classify.ts +188 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/types.ts +78 -25
- package/src/routing/walkers.ts +90 -0
- 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} +60 -22
- package/src/search-params/define.ts +538 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +92 -0
- package/src/segment-params/define.ts +309 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +76 -34
- package/src/server/action-client.ts +119 -28
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +112 -14
- package/src/server/actions.ts +34 -26
- package/src/server/als-registry.ts +108 -20
- package/src/server/asset-headers.ts +8 -34
- package/src/server/body-limits.ts +10 -2
- package/src/server/build-manifest.ts +17 -4
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +25 -7
- package/src/server/cookie-context.ts +473 -0
- package/src/server/cookie-parsing.ts +135 -0
- package/src/server/csrf.ts +39 -6
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-boundary.ts +218 -0
- package/src/server/deny-renderer.ts +32 -52
- package/src/server/dev-source-map.ts +31 -0
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/early-hints.ts +35 -27
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +74 -102
- 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 +101 -5
- package/src/server/html-injector-core.ts +418 -0
- package/src/server/html-injectors.ts +238 -223
- package/src/server/index.ts +29 -183
- package/src/server/internal.ts +182 -0
- package/src/server/logger.ts +67 -36
- package/src/server/metadata-routes.ts +44 -19
- package/src/server/middleware-runner.ts +75 -4
- package/src/server/node-stream-transforms.ts +361 -0
- package/src/server/param-coercion.ts +206 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +32 -18
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline-outcome.ts +197 -0
- package/src/server/pipeline-phases.ts +527 -0
- package/src/server/pipeline.ts +201 -382
- package/src/server/port-resolution.ts +215 -0
- package/src/server/primitives.ts +130 -46
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +168 -337
- package/src/server/route-element-builder.ts +437 -208
- package/src/server/route-handler.ts +31 -4
- package/src/server/route-matcher.ts +128 -277
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +69 -32
- package/src/server/rsc-entry/error-renderer.ts +316 -89
- package/src/server/rsc-entry/helpers.ts +155 -26
- package/src/server/rsc-entry/index.ts +283 -329
- package/src/server/rsc-entry/render-route.ts +313 -0
- package/src/server/rsc-entry/revalidate-renderer.ts +344 -0
- package/src/server/rsc-entry/rsc-payload.ts +65 -22
- package/src/server/rsc-entry/rsc-stream.ts +85 -13
- package/src/server/rsc-entry/ssr-bridge.ts +18 -5
- package/src/server/rsc-entry/ssr-renderer.ts +271 -41
- package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +148 -0
- package/src/server/slot-resolver.ts +234 -246
- package/src/server/ssr-bridge-types.ts +124 -0
- package/src/server/ssr-entry.ts +217 -78
- package/src/server/ssr-render.ts +344 -71
- package/src/server/ssr-wrappers.tsx +141 -0
- package/src/server/state-tree-diff.ts +30 -23
- package/src/server/status-code-resolver.ts +112 -128
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +21 -10
- package/src/server/tree-builder.ts +204 -90
- package/src/server/tree-match.ts +210 -0
- package/src/server/types.ts +78 -9
- package/src/server/utils/escape-html.ts +20 -0
- package/src/server/version-skew.ts +104 -0
- package/src/shared/href-validation.ts +127 -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 +4 -3
- package/src/shims/navigation.ts +14 -7
- package/src/utils/state-machine.ts +111 -0
- package/LICENSE +0 -8
- package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-B3Gypr3D.js +0 -108
- package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
- package/dist/_chunks/format-RyoGQL74.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js +0 -676
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
- package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
- package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.js +0 -187
- 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/segment-merger.d.ts +0 -119
- package/dist/client/segment-merger.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts +0 -26
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/client/use-params.d.ts.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/dev-error-overlay.d.ts +0 -60
- package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
- package/dist/plugins/dev-logs.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/plugins/server-action-exports.d.ts +0 -26
- package/dist/plugins/server-action-exports.d.ts.map +0 -1
- package/dist/routing/status-file-lint.d.ts +0 -33
- package/dist/routing/status-file-lint.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/server/dev-fetch-instrumentation.d.ts +0 -22
- package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
- package/dist/server/dev-logger.d.ts.map +0 -1
- package/dist/server/dev-span-processor.d.ts.map +0 -1
- package/dist/server/dev-warnings.d.ts.map +0 -1
- package/dist/server/manifest-status-resolver.d.ts +0 -58
- package/dist/server/manifest-status-resolver.d.ts.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/utils/directive-parser.d.ts +0 -70
- package/dist/utils/directive-parser.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/segment-merger.ts +0 -339
- package/src/client/transition-root.tsx +0 -166
- package/src/client/use-navigation-pending.ts +0 -38
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dev-error-overlay.ts +0 -230
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/plugins/server-action-exports.ts +0 -220
- package/src/routing/status-file-lint.ts +0 -112
- 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/dev-fetch-instrumentation.ts +0 -96
- package/src/server/dev-span-processor.ts +0 -78
- package/src/server/manifest-status-resolver.ts +0 -215
- package/src/server/prerender.ts +0 -139
- package/src/utils/directive-parser.ts +0 -529
- /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
|
@@ -16,9 +16,13 @@
|
|
|
16
16
|
* Design docs: 18-build-system.md §"Build Manifest", 02-rendering-pipeline.md §"Early Hints"
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { randomUUID, createHash } from 'node:crypto';
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
19
21
|
import type { Plugin, ResolvedConfig } from 'vite';
|
|
20
|
-
import type { PluginContext } from '
|
|
21
|
-
import type { BuildManifest } from '
|
|
22
|
+
import type { PluginContext } from '../plugin-context.js';
|
|
23
|
+
import type { BuildManifest } from '../server/build-manifest.js';
|
|
24
|
+
import type { SegmentNode, RouteFile } from '../routing/types.js';
|
|
25
|
+
import { isDynamicMetadataExtension } from '../server/metadata-routes.js';
|
|
22
26
|
|
|
23
27
|
// Rollup types used by generateBundle hook — imported from vite which re-exports them.
|
|
24
28
|
// We define minimal interfaces here to avoid a direct 'rollup' dependency.
|
|
@@ -30,6 +34,7 @@ interface OutputChunk {
|
|
|
30
34
|
name: string;
|
|
31
35
|
code: string;
|
|
32
36
|
viteMetadata?: { importedCss?: Set<string> };
|
|
37
|
+
modules?: Record<string, { code: string | null; renderedLength: number }>;
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
interface OutputAsset {
|
|
@@ -83,7 +88,7 @@ export function parseViteManifest(
|
|
|
83
88
|
modulepreload[inputPath] = collectTransitiveDeps(inputPath, viteManifest, base);
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
return { css, js, modulepreload, fonts: {} };
|
|
91
|
+
return { css, js, modulepreload, fonts: {}, metadataRouteHashes: {} };
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
/**
|
|
@@ -180,23 +185,7 @@ export function buildManifestFromBundle(
|
|
|
180
185
|
}
|
|
181
186
|
}
|
|
182
187
|
|
|
183
|
-
|
|
184
|
-
// Route files (app/layout.tsx, app/page.tsx) are server components —
|
|
185
|
-
// they don't appear in the client bundle, so per-route CSS keying
|
|
186
|
-
// via facadeModuleId doesn't work. The RSC plugin handles per-route
|
|
187
|
-
// CSS injection via data-rsc-css-href. For Link headers (103 Early
|
|
188
|
-
// Hints), we emit all CSS files — they're just prefetch hints.
|
|
189
|
-
const allCss: string[] = [];
|
|
190
|
-
for (const item of Object.values(bundle) as (OutputChunk | OutputAsset)[]) {
|
|
191
|
-
if (item.type === 'asset' && item.fileName.endsWith('.css')) {
|
|
192
|
-
allCss.push(base + item.fileName);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
if (allCss.length > 0) {
|
|
196
|
-
css['_global'] = allCss;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return { css, js, modulepreload, fonts: {} };
|
|
188
|
+
return { css, js, modulepreload, fonts: {}, metadataRouteHashes: {} };
|
|
200
189
|
}
|
|
201
190
|
|
|
202
191
|
/**
|
|
@@ -227,10 +216,123 @@ function collectTransitiveBundleDeps(
|
|
|
227
216
|
return result;
|
|
228
217
|
}
|
|
229
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Walk the route tree and compute short content hashes for metadata route files
|
|
221
|
+
* (opengraph-image, icon, apple-icon) used for cache-busting
|
|
222
|
+
* the auto-linked URLs in <head>.
|
|
223
|
+
*/
|
|
224
|
+
function computeMetadataRouteHashes(node: SegmentNode<RouteFile>): Record<string, string> {
|
|
225
|
+
const hashes: Record<string, string> = {};
|
|
226
|
+
|
|
227
|
+
if (node.metadataRoutes) {
|
|
228
|
+
for (const [baseName, file] of Object.entries(node.metadataRoutes)) {
|
|
229
|
+
if (!isDynamicMetadataExtension(baseName, file.extension)) {
|
|
230
|
+
// For static files, hash the file content
|
|
231
|
+
try {
|
|
232
|
+
const content = readFileSync(file.filePath);
|
|
233
|
+
const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);
|
|
234
|
+
hashes[file.filePath] = hash;
|
|
235
|
+
} catch {
|
|
236
|
+
// File unreadable — skip hash, DEV_NONCE fallback applies
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
// For dynamic files (.ts/.tsx), hash the source file as a reasonable
|
|
240
|
+
// approximation — the output depends on runtime data too, but the
|
|
241
|
+
// source change is the best build-time signal we have.
|
|
242
|
+
try {
|
|
243
|
+
const content = readFileSync(file.filePath);
|
|
244
|
+
const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);
|
|
245
|
+
hashes[file.filePath] = hash;
|
|
246
|
+
} catch {
|
|
247
|
+
// File unreadable — skip
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
for (const child of node.children) {
|
|
254
|
+
Object.assign(hashes, computeMetadataRouteHashes(child));
|
|
255
|
+
}
|
|
256
|
+
for (const slot of Object.values(node.slots)) {
|
|
257
|
+
Object.assign(hashes, computeMetadataRouteHashes(slot));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return hashes;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Regex to extract client reference hash keys from registerClientReference calls.
|
|
264
|
+
// Matches: registerClientReference(..., "abc123def456", "ExportName")
|
|
265
|
+
const CLIENT_REF_KEY_RE = /registerClientReference\([^,]+,\s*"([0-9a-f]{12})"/g;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Collect all route file paths (layout, page) from the route tree.
|
|
269
|
+
*/
|
|
270
|
+
function collectRouteFilePaths(node: SegmentNode<RouteFile>): string[] {
|
|
271
|
+
const paths: string[] = [];
|
|
272
|
+
if (node.layout) paths.push(node.layout.filePath);
|
|
273
|
+
if (node.page) paths.push(node.page.filePath);
|
|
274
|
+
for (const child of node.children) paths.push(...collectRouteFilePaths(child));
|
|
275
|
+
for (const slot of Object.values(node.slots)) paths.push(...collectRouteFilePaths(slot));
|
|
276
|
+
return paths;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Scan RSC bundle chunks to find which modules contain registerClientReference
|
|
281
|
+
* calls, and extract the reference hash keys from each.
|
|
282
|
+
*/
|
|
283
|
+
function buildClientRefIndex(bundle: OutputBundle): Map<string, string[]> {
|
|
284
|
+
const index = new Map<string, string[]>();
|
|
285
|
+
for (const item of Object.values(bundle)) {
|
|
286
|
+
if (item.type !== 'chunk' || !item.modules) continue;
|
|
287
|
+
for (const [moduleId, mod] of Object.entries(item.modules)) {
|
|
288
|
+
if (!mod.code) continue;
|
|
289
|
+
const keys: string[] = [];
|
|
290
|
+
for (const match of mod.code.matchAll(CLIENT_REF_KEY_RE)) {
|
|
291
|
+
keys.push(match[1]);
|
|
292
|
+
}
|
|
293
|
+
if (keys.length > 0) {
|
|
294
|
+
index.set(moduleId, keys);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return index;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** Rollup getModuleInfo shape (subset). */
|
|
302
|
+
interface ModuleInfo {
|
|
303
|
+
importedIds: string[];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Walk a module's transitive imports to collect all client reference
|
|
308
|
+
* keys reachable from it.
|
|
309
|
+
*/
|
|
310
|
+
function walkModuleImports(
|
|
311
|
+
moduleId: string,
|
|
312
|
+
clientRefIndex: Map<string, string[]>,
|
|
313
|
+
visited: Set<string>,
|
|
314
|
+
result: Set<string>,
|
|
315
|
+
getModuleInfo: (id: string) => ModuleInfo | null
|
|
316
|
+
): void {
|
|
317
|
+
if (visited.has(moduleId)) return;
|
|
318
|
+
visited.add(moduleId);
|
|
319
|
+
|
|
320
|
+
const refKeys = clientRefIndex.get(moduleId);
|
|
321
|
+
if (refKeys) {
|
|
322
|
+
for (const key of refKeys) result.add(key);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const info = getModuleInfo(moduleId);
|
|
326
|
+
if (!info) return;
|
|
327
|
+
for (const importedId of info.importedIds) {
|
|
328
|
+
walkModuleImports(importedId, clientRefIndex, visited, result, getModuleInfo);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
230
332
|
/**
|
|
231
333
|
* Create the timber-build-manifest Vite plugin.
|
|
232
334
|
*
|
|
233
|
-
* Hooks: configResolved, resolveId, load, generateBundle (client
|
|
335
|
+
* Hooks: configResolved, resolveId, load, generateBundle (client and RSC envs)
|
|
234
336
|
*/
|
|
235
337
|
export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
236
338
|
let resolvedBase = '/';
|
|
@@ -242,6 +344,16 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
242
344
|
configResolved(config: ResolvedConfig) {
|
|
243
345
|
resolvedBase = config.base;
|
|
244
346
|
isDev = config.command === 'serve';
|
|
347
|
+
|
|
348
|
+
// Generate a per-build deployment ID early so virtual:timber-config
|
|
349
|
+
// can serialize it during the load hook (which runs before generateBundle).
|
|
350
|
+
// A random UUID is used instead of a content hash — determinism provides
|
|
351
|
+
// no real benefit here since you almost never redeploy identical code,
|
|
352
|
+
// and a random ID avoids the timing problem where the content hash was
|
|
353
|
+
// only available after generateBundle (TIM-452).
|
|
354
|
+
if (!isDev && !ctx.deploymentId) {
|
|
355
|
+
ctx.deploymentId = randomUUID().replace(/-/g, '').slice(0, 16);
|
|
356
|
+
}
|
|
245
357
|
},
|
|
246
358
|
|
|
247
359
|
resolveId(id: string) {
|
|
@@ -267,7 +379,7 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
267
379
|
'// Auto-generated build manifest — do not edit.',
|
|
268
380
|
'// Dev mode: empty manifest (Vite HMR handles CSS/JS).',
|
|
269
381
|
'',
|
|
270
|
-
'const manifest = { css: {}, js: {}, modulepreload: {}, fonts: {} };',
|
|
382
|
+
'const manifest = { css: {}, js: {}, modulepreload: {}, fonts: {}, metadataRouteHashes: {} };',
|
|
271
383
|
'',
|
|
272
384
|
'export default manifest;',
|
|
273
385
|
].join('\n');
|
|
@@ -281,7 +393,7 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
281
393
|
'// Auto-generated build manifest — do not edit.',
|
|
282
394
|
'// Production: reads manifest from globalThis (set by _timber-manifest-init.js).',
|
|
283
395
|
'',
|
|
284
|
-
'const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? { css: {}, js: {}, modulepreload: {}, fonts: {} };',
|
|
396
|
+
'const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? { css: {}, js: {}, modulepreload: {}, fonts: {}, metadataRouteHashes: {} };',
|
|
285
397
|
'',
|
|
286
398
|
'export default manifest;',
|
|
287
399
|
].join('\n');
|
|
@@ -295,9 +407,42 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
295
407
|
|
|
296
408
|
const envName = (this as { environment?: { name: string } }).environment?.name;
|
|
297
409
|
|
|
410
|
+
// RSC environment: walk the module graph to find which client
|
|
411
|
+
// references each route file transitively imports. Store the
|
|
412
|
+
// mapping in ctx so the adapter-build post hook can cross-reference
|
|
413
|
+
// with clientReferenceDeps to populate per-route modulepreloads.
|
|
414
|
+
if (envName === 'rsc' && ctx.routeTree) {
|
|
415
|
+
const clientRefIndex = buildClientRefIndex(bundle);
|
|
416
|
+
if (clientRefIndex.size > 0) {
|
|
417
|
+
const routeFiles = collectRouteFilePaths(ctx.routeTree.root);
|
|
418
|
+
const routeClientRefKeys = new Map<string, Set<string>>();
|
|
419
|
+
|
|
420
|
+
const getInfo = (id: string) =>
|
|
421
|
+
(this as { getModuleInfo?: (id: string) => ModuleInfo | null }).getModuleInfo?.(id) ??
|
|
422
|
+
null;
|
|
423
|
+
|
|
424
|
+
for (const filePath of routeFiles) {
|
|
425
|
+
const refKeys = new Set<string>();
|
|
426
|
+
walkModuleImports(filePath, clientRefIndex, new Set(), refKeys, getInfo);
|
|
427
|
+
if (refKeys.size > 0) {
|
|
428
|
+
routeClientRefKeys.set(filePath, refKeys);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (routeClientRefKeys.size > 0) {
|
|
433
|
+
ctx.routeClientRefKeys = routeClientRefKeys;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
298
438
|
if (envName === 'client') {
|
|
299
439
|
ctx.buildManifest = buildManifestFromBundle(bundle, resolvedBase, ctx.root);
|
|
300
440
|
|
|
441
|
+
// Compute cache-busting hashes for metadata route files
|
|
442
|
+
if (ctx.routeTree) {
|
|
443
|
+
ctx.buildManifest.metadataRouteHashes = computeMetadataRouteHashes(ctx.routeTree.root);
|
|
444
|
+
}
|
|
445
|
+
|
|
301
446
|
// When client JavaScript is disabled, strip JS chunks from the bundle
|
|
302
447
|
// so Rollup never writes them to disk. CSS assets are preserved —
|
|
303
448
|
// they're still needed for server-rendered HTML.
|
|
@@ -15,9 +15,10 @@
|
|
|
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 {
|
|
18
|
+
import type { PluginContext } from '../plugin-context.js';
|
|
19
|
+
import type { SegmentNode, RouteTree } from '../routing/types.js';
|
|
20
|
+
import { collectLeafRoutes } from '../routing/walkers.js';
|
|
21
|
+
import { formatSize } from '../utils/format.js';
|
|
21
22
|
|
|
22
23
|
// ─── Public types ─────────────────────────────────────────────────────────
|
|
23
24
|
|
|
@@ -83,33 +84,23 @@ interface RouteInfo {
|
|
|
83
84
|
/**
|
|
84
85
|
* Walk the route tree and collect all leaf routes (pages + API endpoints).
|
|
85
86
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
87
|
+
* Wraps the shared `collectLeafRoutes` walker (TIM-848). Parallel slots
|
|
88
|
+
* (`@artists`, `@shows`, etc.) are intentionally skipped — they render
|
|
89
|
+
* alongside the parent page at the same URL and are not separately
|
|
90
|
+
* URL-addressable. Their JS is captured in shared/layout chunks.
|
|
89
91
|
*
|
|
90
92
|
* After collection, entries are deduplicated by URL path so that overlapping
|
|
91
93
|
* route groups (e.g. `(browse)` and `(marketing)` both producing `/`) only
|
|
92
|
-
* appear once. The entry with the
|
|
94
|
+
* appear once. The entry with the longest segment chain (most specific
|
|
95
|
+
* match) wins.
|
|
93
96
|
*/
|
|
94
97
|
export function collectRoutes(tree: RouteTree): RouteInfo[] {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (node.page) {
|
|
102
|
-
routes.push({ path, segments: currentChain, entryFilePath: node.page.filePath });
|
|
103
|
-
}
|
|
104
|
-
if (node.route) {
|
|
105
|
-
routes.push({ path, segments: currentChain, entryFilePath: node.route.filePath });
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Recurse into child segments only — skip parallel slots (node.slots)
|
|
109
|
-
for (const child of node.children) walk(child, currentChain);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
walk(tree.root, []);
|
|
98
|
+
const leaves = collectLeafRoutes(tree.root);
|
|
99
|
+
const routes: RouteInfo[] = leaves.map((leaf) => ({
|
|
100
|
+
path: leaf.urlPath,
|
|
101
|
+
segments: leaf.segments,
|
|
102
|
+
entryFilePath: leaf.page?.filePath ?? leaf.route?.filePath ?? null,
|
|
103
|
+
}));
|
|
113
104
|
|
|
114
105
|
// Deduplicate entries with the same URL path (e.g. from overlapping route groups).
|
|
115
106
|
// Keep the entry with the longest segment chain (most specific match).
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* timber-cache-transform — Vite plugin that injects stable callsite IDs
|
|
3
|
+
* into `cache()` calls imported from `@timber-js/app/cache`.
|
|
4
|
+
*
|
|
5
|
+
* Without this plugin, cache keys use a process-local counter (fnIdCounter)
|
|
6
|
+
* which is unstable across cold starts in serverless/multi-instance
|
|
7
|
+
* deployments. With a shared CacheHandler (Redis/KV), colliding counters
|
|
8
|
+
* cause cache key poisoning — serving one route's cached data to another.
|
|
9
|
+
*
|
|
10
|
+
* The plugin transforms:
|
|
11
|
+
* cache(fn, opts) → cache(fn, opts, "stable-id")
|
|
12
|
+
*
|
|
13
|
+
* where stable-id = fnv1a(relativeModulePath + ":cache:" + callIndex).
|
|
14
|
+
*
|
|
15
|
+
* See TIM-997, design/06-caching.md §"Cache Key Security".
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { relative } from 'node:path';
|
|
19
|
+
import MagicString from 'magic-string';
|
|
20
|
+
import { parseAst } from 'vite';
|
|
21
|
+
import type { Plugin } from 'vite';
|
|
22
|
+
import type { PluginContext } from '../plugin-context.js';
|
|
23
|
+
import { fnv1aHash } from '../cache/fast-hash.js';
|
|
24
|
+
|
|
25
|
+
const CACHE_MODULE_SOURCES = new Set(['@timber-js/app/cache', 'timber/cache']);
|
|
26
|
+
|
|
27
|
+
interface PositionedNode {
|
|
28
|
+
type: string;
|
|
29
|
+
start: number;
|
|
30
|
+
end: number;
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface IdentifierNode extends PositionedNode {
|
|
35
|
+
type: 'Identifier';
|
|
36
|
+
name: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface ImportDeclarationNode extends PositionedNode {
|
|
40
|
+
type: 'ImportDeclaration';
|
|
41
|
+
source: { value: string };
|
|
42
|
+
specifiers: Array<
|
|
43
|
+
PositionedNode & {
|
|
44
|
+
type: string;
|
|
45
|
+
local: IdentifierNode;
|
|
46
|
+
imported?: IdentifierNode;
|
|
47
|
+
}
|
|
48
|
+
>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface CallExpressionNode extends PositionedNode {
|
|
52
|
+
type: 'CallExpression';
|
|
53
|
+
callee: PositionedNode;
|
|
54
|
+
arguments: PositionedNode[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface ProgramNode extends PositionedNode {
|
|
58
|
+
type: 'Program';
|
|
59
|
+
body: PositionedNode[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Find the local binding name(s) for `cache` imported from the cache module.
|
|
64
|
+
*/
|
|
65
|
+
function findCacheBindings(program: ProgramNode): Set<string> {
|
|
66
|
+
const bindings = new Set<string>();
|
|
67
|
+
for (const stmt of program.body) {
|
|
68
|
+
if (stmt.type !== 'ImportDeclaration') continue;
|
|
69
|
+
const decl = stmt as unknown as ImportDeclarationNode;
|
|
70
|
+
if (!CACHE_MODULE_SOURCES.has(decl.source.value)) continue;
|
|
71
|
+
for (const spec of decl.specifiers) {
|
|
72
|
+
if (spec.type !== 'ImportSpecifier') continue;
|
|
73
|
+
const importedName = spec.imported?.name ?? spec.local.name;
|
|
74
|
+
if (importedName === 'cache') {
|
|
75
|
+
bindings.add(spec.local.name);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return bindings;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Recursively walk AST nodes to find cache() call expressions.
|
|
84
|
+
*
|
|
85
|
+
* cache() is typically called at module scope, but we also handle calls
|
|
86
|
+
* inside functions/blocks for completeness.
|
|
87
|
+
*/
|
|
88
|
+
function findCacheCallSites(
|
|
89
|
+
node: PositionedNode,
|
|
90
|
+
cacheBindings: Set<string>,
|
|
91
|
+
results: CallExpressionNode[]
|
|
92
|
+
): void {
|
|
93
|
+
if (node.type === 'CallExpression') {
|
|
94
|
+
const call = node as unknown as CallExpressionNode;
|
|
95
|
+
if (
|
|
96
|
+
call.callee.type === 'Identifier' &&
|
|
97
|
+
cacheBindings.has((call.callee as IdentifierNode).name) &&
|
|
98
|
+
call.arguments.length === 2
|
|
99
|
+
) {
|
|
100
|
+
results.push(call);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const key of Object.keys(node)) {
|
|
104
|
+
if (key === 'type' || key === 'start' || key === 'end') continue;
|
|
105
|
+
const val = node[key];
|
|
106
|
+
if (val && typeof val === 'object') {
|
|
107
|
+
if (Array.isArray(val)) {
|
|
108
|
+
for (const item of val) {
|
|
109
|
+
if (item && typeof item === 'object' && typeof item.type === 'string') {
|
|
110
|
+
findCacheCallSites(item as PositionedNode, cacheBindings, results);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} else if (typeof (val as PositionedNode).type === 'string') {
|
|
114
|
+
findCacheCallSites(val as PositionedNode, cacheBindings, results);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Generate a stable callsite ID from a module path and call index.
|
|
122
|
+
*
|
|
123
|
+
* The ID is an FNV-1a hash of the relative module path + call index,
|
|
124
|
+
* providing a deterministic identifier that is:
|
|
125
|
+
* - Stable across cold starts of the same build
|
|
126
|
+
* - Unique across different modules
|
|
127
|
+
* - Unique across multiple cache() calls within the same module
|
|
128
|
+
*/
|
|
129
|
+
function generateStableId(relativeModulePath: string, callIndex: number): string {
|
|
130
|
+
return fnv1aHash(`${relativeModulePath}:cache:${callIndex}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function timberCacheTransform(ctx: PluginContext): Plugin {
|
|
134
|
+
return {
|
|
135
|
+
name: 'timber-cache-transform',
|
|
136
|
+
|
|
137
|
+
transform(code, id) {
|
|
138
|
+
if (!code.includes('@timber-js/app/cache') && !code.includes('timber/cache')) return;
|
|
139
|
+
// Skip node_modules (don't transform third-party code)
|
|
140
|
+
if (id.includes('node_modules')) return;
|
|
141
|
+
|
|
142
|
+
let program: ProgramNode;
|
|
143
|
+
try {
|
|
144
|
+
program = parseAst(code, { lang: 'tsx' }) as unknown as ProgramNode;
|
|
145
|
+
} catch {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const cacheBindings = findCacheBindings(program);
|
|
150
|
+
if (cacheBindings.size === 0) return;
|
|
151
|
+
|
|
152
|
+
const callSites: CallExpressionNode[] = [];
|
|
153
|
+
findCacheCallSites(program, cacheBindings, callSites);
|
|
154
|
+
if (callSites.length === 0) return;
|
|
155
|
+
|
|
156
|
+
// Sort by position in file for deterministic call indices
|
|
157
|
+
callSites.sort((a, b) => a.start - b.start);
|
|
158
|
+
|
|
159
|
+
const root = ctx.root || process.cwd();
|
|
160
|
+
const relPath = relative(root, id);
|
|
161
|
+
const s = new MagicString(code);
|
|
162
|
+
|
|
163
|
+
for (let i = 0; i < callSites.length; i++) {
|
|
164
|
+
const call = callSites[i];
|
|
165
|
+
const stableId = generateStableId(relPath, i);
|
|
166
|
+
// Insert the stable ID as the 3rd argument just before the closing ')'
|
|
167
|
+
const insertPos = call.end - 1;
|
|
168
|
+
s.appendLeft(insertPos, `, "${stableId}"`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
code: s.toString(),
|
|
173
|
+
map: s.generateMap({ hires: 'boundary' }),
|
|
174
|
+
};
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Exported for testing
|
|
180
|
+
export { generateStableId };
|
|
@@ -0,0 +1,113 @@
|
|
|
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
|
+
import { relative } from 'node:path';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check whether a root-relative path lives under the app directory,
|
|
17
|
+
* and if so return the first non-group route segment.
|
|
18
|
+
*
|
|
19
|
+
* `appPrefix` is the root-relative app directory with a trailing slash
|
|
20
|
+
* (e.g. "app/" or "src/app/"), computed once from the resolved appDir
|
|
21
|
+
* and root. Matching uses `startsWith` — no ambiguity.
|
|
22
|
+
*
|
|
23
|
+
* Returns:
|
|
24
|
+
* { inApp: false } — path is not under app/
|
|
25
|
+
* { inApp: true, segment: null } — root of app/ (e.g. app/layout.tsx)
|
|
26
|
+
* { inApp: true, segment: "dashboard" } — nested route boundary
|
|
27
|
+
*/
|
|
28
|
+
function findAppBoundary(
|
|
29
|
+
path: string,
|
|
30
|
+
appPrefix: string
|
|
31
|
+
): { inApp: false } | { inApp: true; segment: string | null } {
|
|
32
|
+
const relPath = path.replace(/\\/g, '/');
|
|
33
|
+
if (!relPath.startsWith(appPrefix)) return { inApp: false };
|
|
34
|
+
|
|
35
|
+
const withinApp = relPath.slice(appPrefix.length);
|
|
36
|
+
const segments = withinApp.split('/');
|
|
37
|
+
|
|
38
|
+
for (const seg of segments) {
|
|
39
|
+
if (seg.includes('.')) break;
|
|
40
|
+
if (seg.startsWith('(') && seg.endsWith(')')) continue;
|
|
41
|
+
return { inApp: true, segment: seg };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return { inApp: true, segment: null };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Derive a chunk group name for a client reference module.
|
|
49
|
+
*
|
|
50
|
+
* Groups by the first non-group route segment under appDir so that all
|
|
51
|
+
* client components belonging to the same layout boundary land in one
|
|
52
|
+
* chunk. For example:
|
|
53
|
+
* - `facade:app/dashboard/settings/page.tsx` → `"client-dashboard"`
|
|
54
|
+
* - `facade:app/(group-a)/group-page-a/page.tsx` → `"client-group-page-a"`
|
|
55
|
+
* - `facade:app/layout.tsx` (root layout) → `"client-shared"`
|
|
56
|
+
* - `shared:...` (shared across chunks) → `"client-shared"`
|
|
57
|
+
*
|
|
58
|
+
* When a 'use client' module lives outside the app directory (e.g. in
|
|
59
|
+
* src/posts/ or src/components/), the function falls back to deriving
|
|
60
|
+
* the layout boundary from the serverChunk's facade path. This prevents
|
|
61
|
+
* lazily-loaded client dependencies (e.g. via import.meta.glob) from
|
|
62
|
+
* being hoisted into the shared chunk when they're only used by a
|
|
63
|
+
* specific route.
|
|
64
|
+
*
|
|
65
|
+
* This balances route-scoped code splitting with HTTP request count:
|
|
66
|
+
* fewer chunks than per-serverChunk, but still avoids downloading every
|
|
67
|
+
* client component on every page.
|
|
68
|
+
*/
|
|
69
|
+
export function clientChunkGroup(
|
|
70
|
+
meta: { id: string; normalizedId: string; serverChunk: string },
|
|
71
|
+
appDir: string,
|
|
72
|
+
root: string
|
|
73
|
+
): string {
|
|
74
|
+
const { normalizedId, serverChunk } = meta;
|
|
75
|
+
|
|
76
|
+
// Shared chunks (not associated with a single route entry) get one group.
|
|
77
|
+
if (serverChunk.startsWith('shared:')) return 'client-shared';
|
|
78
|
+
|
|
79
|
+
// Compute the root-relative app directory prefix once. Both normalizedId
|
|
80
|
+
// and serverChunk paths from the RSC plugin are root-relative (via
|
|
81
|
+
// path.relative(root, absoluteId)), so this prefix matches exactly —
|
|
82
|
+
// no ambiguity with content directories that happen to share a name.
|
|
83
|
+
const appPrefix = relative(root, appDir).replace(/\\/g, '/') + '/';
|
|
84
|
+
|
|
85
|
+
// Try the client module's own path first.
|
|
86
|
+
const result = findAppBoundary(normalizedId, appPrefix);
|
|
87
|
+
if (result.inApp && result.segment) return `client-${result.segment}`;
|
|
88
|
+
if (result.inApp) return 'client-shared';
|
|
89
|
+
|
|
90
|
+
// The client module lives outside the app directory (e.g. src/posts/,
|
|
91
|
+
// src/components/). Fall back to the serverChunk's facade path — the
|
|
92
|
+
// RSC entry point that imported this module — to derive the route's
|
|
93
|
+
// layout boundary. This keeps dependencies of lazily-loaded 'use client'
|
|
94
|
+
// components (e.g. from import.meta.glob) in per-route async chunks
|
|
95
|
+
// instead of hoisting them into client-shared.
|
|
96
|
+
if (serverChunk.startsWith('facade:')) {
|
|
97
|
+
const facadePath = serverChunk.slice('facade:'.length).replace(/\\/g, '/');
|
|
98
|
+
const facadeResult = findAppBoundary(facadePath, appPrefix);
|
|
99
|
+
if (facadeResult.inApp && facadeResult.segment) return `client-${facadeResult.segment}`;
|
|
100
|
+
if (facadeResult.inApp) return 'client-shared';
|
|
101
|
+
|
|
102
|
+
// Both module and facade are outside app/. Derive a chunk name from
|
|
103
|
+
// the full facade path to keep these isolated from client-shared.
|
|
104
|
+
// Uses the full path (minus extension) to avoid collisions between
|
|
105
|
+
// facades with the same basename (e.g. foo/index.mdx vs bar/index.mdx).
|
|
106
|
+
const facadeName = facadePath.replace(/\.[^.]+$/, '').replace(/\//g, '-');
|
|
107
|
+
if (facadeName) return `client-${facadeName}`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Root-level files (layout.tsx, page.tsx directly in app/) go into the
|
|
111
|
+
// shared group since the root layout is loaded on every page.
|
|
112
|
+
return 'client-shared';
|
|
113
|
+
}
|