@timber-js/app 0.2.0-alpha.208 → 0.2.0-alpha.209
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/{primitives-DLAnvsrk.js → actions-BerlqoXA.js} +640 -410
- package/dist/_chunks/actions-BerlqoXA.js.map +1 -0
- package/dist/_chunks/{als-registry-C6kcfprT.js → als-registry-DaxkVjt5.js} +6 -2
- package/dist/_chunks/als-registry-DaxkVjt5.js.map +1 -0
- package/dist/_chunks/{build-manifest-DTmSGLRz.js → build-manifest-DWppEdLB.js} +2 -51
- package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
- package/dist/_chunks/{build-output-helper-9dqCv1pZ.js → build-output-helper-RV_BRcF1.js} +50 -53
- package/dist/_chunks/build-output-helper-RV_BRcF1.js.map +1 -0
- package/dist/_chunks/{cache-api-CUD9Ezaq.js → cache-api-CR23J_NC.js} +64 -32
- package/dist/_chunks/cache-api-CR23J_NC.js.map +1 -0
- package/dist/_chunks/{chains-B4bgOl2g.js → chains-CpFg56UB.js} +2 -2
- package/dist/_chunks/{chains-B4bgOl2g.js.map → chains-CpFg56UB.js.map} +1 -1
- package/dist/_chunks/{cli-check-G8o30ldg.js → cli-check-C6Ev6wBO.js} +11 -52
- package/dist/_chunks/cli-check-C6Ev6wBO.js.map +1 -0
- package/dist/_chunks/cli-context-By7k2xVo.js +70 -0
- package/dist/_chunks/cli-context-By7k2xVo.js.map +1 -0
- package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js → cli-schema-sync-CbT2AUUI.js} +3 -3
- package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js.map → cli-schema-sync-CbT2AUUI.js.map} +1 -1
- package/dist/_chunks/{cloudflare-BFb__LYG.js → cloudflare-Byxl8FWP.js} +96 -53
- package/dist/_chunks/{cloudflare-BFb__LYG.js.map → cloudflare-Byxl8FWP.js.map} +1 -1
- package/dist/_chunks/{convention-lint-5KzoMg_A.js → convention-lint-jKTwKwPe.js} +21 -6
- package/dist/_chunks/convention-lint-jKTwKwPe.js.map +1 -0
- package/dist/_chunks/{dev-server-BzBxgYAV.js → dev-server-C4WZdB7L.js} +15 -167
- package/dist/_chunks/dev-server-C4WZdB7L.js.map +1 -0
- package/dist/_chunks/{error-boundary-BrHmG-2X.js → error-boundary-tA7kVfs4.js} +84 -104
- package/dist/_chunks/error-boundary-tA7kVfs4.js.map +1 -0
- package/dist/_chunks/{fs-identity-D7vb6GdI.js → fs-identity-BRKuL215.js} +3 -4
- package/dist/_chunks/fs-identity-BRKuL215.js.map +1 -0
- package/dist/_chunks/{graph-cache-CP4GEmf9.js → graph-cache-CYiUS2aS.js} +4 -5
- package/dist/_chunks/graph-cache-CYiUS2aS.js.map +1 -0
- package/dist/_chunks/{json-lossy-check-ClNvBM_3.js → json-lossy-check-ip0Qi0MT.js} +6 -3
- package/dist/_chunks/json-lossy-check-ip0Qi0MT.js.map +1 -0
- package/dist/_chunks/{live-graph-Bm5WTvcr.js → live-graph-Dv-JJCZw.js} +3 -3
- package/dist/_chunks/{live-graph-Bm5WTvcr.js.map → live-graph-Dv-JJCZw.js.map} +1 -1
- package/dist/_chunks/{logger-k2DQ4EUf.js → logger-DiDt5ppH.js} +192 -51
- package/dist/_chunks/logger-DiDt5ppH.js.map +1 -0
- package/dist/_chunks/{navigation-root-mHSK9psY.js → navigation-root-BQfo1-kG.js} +2 -2
- package/dist/_chunks/{navigation-root-mHSK9psY.js.map → navigation-root-BQfo1-kG.js.map} +1 -1
- package/dist/_chunks/{plugin-context-8idfR3UZ.js → plugin-context-BPBPc3lL.js} +28 -4
- package/dist/_chunks/plugin-context-BPBPc3lL.js.map +1 -0
- package/dist/_chunks/{poison-scan-DG5eI2_z.js → poison-scan-CpeT6_OJ.js} +2 -2
- package/dist/_chunks/{poison-scan-DG5eI2_z.js.map → poison-scan-CpeT6_OJ.js.map} +1 -1
- package/dist/_chunks/render-timeout-DOf_BBcO.js +46 -0
- package/dist/_chunks/render-timeout-DOf_BBcO.js.map +1 -0
- package/dist/_chunks/{rsc-payload-path-B_LBodc2.js → rsc-payload-path-dffcs4jp.js} +9 -3
- package/dist/_chunks/{rsc-payload-path-B_LBodc2.js.map → rsc-payload-path-dffcs4jp.js.map} +1 -1
- package/dist/_chunks/{scanner-BQ5sPIJ7.js → scanner-Bw0oq1HB.js} +2 -2
- package/dist/_chunks/{scanner-BQ5sPIJ7.js.map → scanner-Bw0oq1HB.js.map} +1 -1
- package/dist/_chunks/{navigation-context-D0TU0Jog.js → segment-context-xtPUGfdq.js} +36 -34
- package/dist/_chunks/segment-context-xtPUGfdq.js.map +1 -0
- package/dist/_chunks/{singleflight-2lUWfcAk.js → singleflight-BeVMMKi0.js} +4 -3
- package/dist/_chunks/{singleflight-2lUWfcAk.js.map → singleflight-BeVMMKi0.js.map} +1 -1
- package/dist/_chunks/{sizeof-lXffQ1Vr.js → sizeof-UwzwB1uM.js} +3 -2
- package/dist/_chunks/sizeof-UwzwB1uM.js.map +1 -0
- package/dist/_chunks/ssr-data-nA3I70_n.js +49 -0
- package/dist/_chunks/ssr-data-nA3I70_n.js.map +1 -0
- package/dist/_chunks/{state-FippDgxN.js → state-BhNGPsdi.js} +6 -8
- package/dist/_chunks/state-BhNGPsdi.js.map +1 -0
- package/dist/_chunks/{status-page-marker-CNbpUOPB.js → status-page-marker-gaihi0KZ.js} +53 -20
- package/dist/_chunks/status-page-marker-gaihi0KZ.js.map +1 -0
- package/dist/_chunks/{walkers-CN2N_bA-.js → walkers-BXExhzzk.js} +2 -2
- package/dist/_chunks/{walkers-CN2N_bA-.js.map → walkers-BXExhzzk.js.map} +1 -1
- package/dist/_chunks/write-file-atomic-D1qWqHb4.js +32 -0
- package/dist/_chunks/write-file-atomic-D1qWqHb4.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +7 -7
- package/dist/adapters/build-output-helper.d.ts.map +1 -1
- package/dist/adapters/canonicalize-module.d.ts +8 -0
- package/dist/adapters/canonicalize-module.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +1 -1
- package/dist/adapters/cloudflare-kv-cache.js +2 -2
- package/dist/adapters/cloudflare.d.ts +30 -8
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +2 -2
- package/dist/adapters/compress-module.d.ts +8 -0
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/fs-identity.d.ts +2 -3
- package/dist/adapters/fs-identity.d.ts.map +1 -1
- package/dist/adapters/nitro-presets.d.ts +0 -6
- package/dist/adapters/nitro-presets.d.ts.map +1 -1
- package/dist/adapters/nitro-preview.d.ts +43 -11
- package/dist/adapters/nitro-preview.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +1 -13
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +291 -176
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +7 -2
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/types.d.ts +105 -21
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js +0 -0
- package/dist/analyze/crawl-entry.js +3 -3
- package/dist/analyze/graph-cache.d.ts.map +1 -1
- package/dist/analyze/graph-command.js +4 -4
- package/dist/cache/index.js +2 -2
- package/dist/cache/json-lossy-check.d.ts.map +1 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts.map +1 -1
- package/dist/cache/stores/memory.js +1 -1
- package/dist/cache/tag-aware-handler.d.ts.map +1 -1
- package/dist/cdn/workers-cache-purge.js +1 -1
- package/dist/cli-check.d.ts +7 -37
- package/dist/cli-check.d.ts.map +1 -1
- package/dist/cli-context.d.ts +54 -0
- package/dist/cli-context.d.ts.map +1 -0
- package/dist/cli.d.ts +9 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +20 -24
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
- package/dist/client/browser-entry/hydrate.d.ts +19 -29
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
- package/dist/client/browser-entry/index.d.ts +7 -7
- package/dist/client/browser-entry/post-hydration.d.ts +6 -9
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
- package/dist/client/browser-entry/router-init.d.ts +6 -11
- package/dist/client/browser-entry/router-init.d.ts.map +1 -1
- package/dist/client/error-boundary.d.ts +4 -3
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -1
- package/dist/client/error-reconstituter.d.ts +3 -9
- package/dist/client/error-reconstituter.d.ts.map +1 -1
- package/dist/client/history.d.ts +12 -11
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +0 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +5 -6
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +3 -3
- package/dist/client/internal.d.ts.map +1 -1
- package/dist/client/internal.js +68 -104
- package/dist/client/internal.js.map +1 -1
- package/dist/client/navigation-commit.d.ts +16 -7
- package/dist/client/navigation-commit.d.ts.map +1 -1
- package/dist/client/navigation-context.d.ts +3 -5
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/react-root.d.ts +3 -2
- package/dist/client/react-root.d.ts.map +1 -1
- package/dist/client/router-pipeline.d.ts +1 -6
- package/dist/client/router-pipeline.d.ts.map +1 -1
- package/dist/client/router-types.d.ts +45 -39
- package/dist/client/router-types.d.ts.map +1 -1
- package/dist/client/router-url.d.ts +24 -0
- package/dist/client/router-url.d.ts.map +1 -0
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +8 -4
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/ssr-data.d.ts +18 -64
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/state.d.ts +2 -5
- package/dist/client/state.d.ts.map +1 -1
- package/dist/client/use-pathname.d.ts +1 -1
- package/dist/config-types.d.ts +2 -1
- package/dist/config-types.d.ts.map +1 -1
- package/dist/config-validation.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -1
- package/dist/dev-tools/dev-page-shell.d.ts +17 -0
- package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
- package/dist/dev-tools/index.d.ts +1 -1
- package/dist/dev-tools/index.d.ts.map +1 -1
- package/dist/dev-tools/instrumentation.d.ts +17 -2
- package/dist/dev-tools/instrumentation.d.ts.map +1 -1
- package/dist/dev-tools/overlay.d.ts +6 -27
- package/dist/dev-tools/overlay.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +531 -373
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +26 -40
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +15 -2
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +19 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/post-build.d.ts +110 -0
- package/dist/plugins/post-build.d.ts.map +1 -0
- package/dist/plugins/prebuilt-capture.d.ts +11 -4
- package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
- package/dist/plugins/prebuilt.d.ts +17 -1
- package/dist/plugins/prebuilt.d.ts.map +1 -1
- package/dist/plugins/prerender-sugar.d.ts.map +1 -1
- package/dist/plugins/rsc-assets-manifest.d.ts +33 -0
- package/dist/plugins/rsc-assets-manifest.d.ts.map +1 -0
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +32 -9
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-write.d.ts +0 -9
- package/dist/routing/codegen-write.d.ts.map +1 -1
- package/dist/routing/index.js +2 -2
- package/dist/routing/segment-codegen.d.ts.map +1 -1
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts +5 -4
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +46 -7
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +58 -5
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/children-interception.d.ts.map +1 -1
- package/dist/server/cookie-context.d.ts +2 -23
- package/dist/server/cookie-context.d.ts.map +1 -1
- package/dist/server/csp-nonce.d.ts +0 -9
- package/dist/server/csp-nonce.d.ts.map +1 -1
- package/dist/server/csrf.d.ts +27 -4
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/debug.d.ts +0 -1
- package/dist/server/debug.d.ts.map +1 -1
- package/dist/server/default-logger.d.ts +2 -1
- package/dist/server/default-logger.d.ts.map +1 -1
- package/dist/server/deny-boundary.d.ts +12 -6
- package/dist/server/deny-boundary.d.ts.map +1 -1
- package/dist/server/deny-renderer.d.ts +2 -2
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -3
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +9 -2
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/head-response.d.ts +4 -4
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/instrumentation.d.ts +10 -3
- package/dist/server/instrumentation.d.ts.map +1 -1
- package/dist/server/internal.d.ts +1 -4
- package/dist/server/internal.d.ts.map +1 -1
- package/dist/server/internal.js +961 -581
- package/dist/server/internal.js.map +1 -1
- package/dist/server/json-status-response.d.ts +34 -0
- package/dist/server/json-status-response.d.ts.map +1 -0
- package/dist/server/logger.d.ts +26 -0
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/param-coercion.d.ts +11 -6
- package/dist/server/param-coercion.d.ts.map +1 -1
- package/dist/server/pipeline-helpers.d.ts +95 -7
- package/dist/server/pipeline-helpers.d.ts.map +1 -1
- package/dist/server/pipeline-interception.d.ts +11 -0
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts +11 -1
- package/dist/server/pipeline-outcome.d.ts.map +1 -1
- package/dist/server/pipeline-phases.d.ts +2 -2
- package/dist/server/pipeline-phases.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +23 -35
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/prebuilt/capture-render.d.ts +25 -0
- package/dist/server/prebuilt/capture-render.d.ts.map +1 -0
- package/dist/server/prebuilt/capture-routes.d.ts +37 -0
- package/dist/server/prebuilt/capture-routes.d.ts.map +1 -0
- package/dist/server/prebuilt/capture-state.d.ts +79 -35
- package/dist/server/prebuilt/capture-state.d.ts.map +1 -1
- package/dist/server/prebuilt/lifetime.d.ts +38 -0
- package/dist/server/prebuilt/lifetime.d.ts.map +1 -0
- package/dist/server/prebuilt/slots.d.ts +7 -0
- package/dist/server/prebuilt/slots.d.ts.map +1 -1
- package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -1
- package/dist/server/prebuilt-builder.d.ts.map +1 -1
- package/dist/server/prebuilt-runtime.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +6 -81
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/react-cache-bridge.d.ts +59 -0
- package/dist/server/react-cache-bridge.d.ts.map +1 -0
- package/dist/server/react-cache-scope.d.ts +49 -0
- package/dist/server/react-cache-scope.d.ts.map +1 -0
- package/dist/server/render-timeout.d.ts +15 -0
- package/dist/server/render-timeout.d.ts.map +1 -1
- package/dist/server/render-utils.d.ts +9 -0
- package/dist/server/render-utils.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +26 -5
- package/dist/server/request-context.d.ts.map +1 -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 +7 -0
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts +22 -22
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
- package/dist/server/rsc-entry/api-handler.d.ts +7 -0
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/deny-fallback.d.ts +32 -6
- package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +11 -18
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +0 -1
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +5 -15
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +5 -6
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-signals.d.ts +65 -0
- package/dist/server/rsc-entry/render-signals.d.ts.map +1 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts +6 -16
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +7 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +8 -53
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +2 -2
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +9 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
- package/dist/server/signal-identity.d.ts +43 -0
- package/dist/server/signal-identity.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +4 -3
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/slot-subtree-contain.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +91 -53
- package/dist/server/ssr-bridge-types.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +8 -5
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +26 -40
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +1 -1
- package/dist/server/static-generator.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +12 -0
- package/dist/server/stream-utils.d.ts.map +1 -1
- package/dist/server/tracing.d.ts +12 -16
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -1
- package/dist/server/version-skew.d.ts +3 -3
- package/dist/shared/csrf-reject.d.ts +16 -0
- package/dist/shared/csrf-reject.d.ts.map +1 -0
- package/dist/shared/error-digest.d.ts +28 -0
- package/dist/shared/error-digest.d.ts.map +1 -0
- package/dist/shared/payload-root.d.ts +11 -10
- package/dist/shared/payload-root.d.ts.map +1 -1
- package/dist/shared/rsc-payload-path.d.ts +6 -0
- package/dist/shared/rsc-payload-path.d.ts.map +1 -1
- package/dist/utils/write-file-atomic.d.ts +17 -0
- package/dist/utils/write-file-atomic.d.ts.map +1 -0
- package/docs/api/30-api-server.mdx +17 -14
- package/docs/api/32-api-cache.mdx +51 -23
- package/docs/api/34-api-config.mdx +34 -6
- package/docs/api/36-cli.mdx +11 -1
- package/docs/learn/03-fetching-data.mdx +17 -1
- package/docs/learn/04-access-control.mdx +1 -1
- package/docs/learn/10-caching.mdx +29 -11
- package/docs/learn/11-middleware.mdx +8 -2
- package/docs/learn/12-error-handling.mdx +6 -1
- package/package.json +5 -1
- package/src/adapters/build-output-helper.ts +55 -53
- package/src/adapters/canonicalize-module.ts +29 -0
- package/src/adapters/cloudflare.ts +105 -63
- package/src/adapters/compress-module.ts +16 -5
- package/src/adapters/fs-identity.ts +2 -3
- package/src/adapters/nitro-presets.ts +0 -15
- package/src/adapters/nitro-preview.ts +272 -136
- package/src/adapters/nitro.ts +119 -82
- package/src/adapters/shared.ts +23 -14
- package/src/adapters/types.ts +110 -21
- package/src/analyze/graph-cache.ts +3 -4
- package/src/cache/json-lossy-check.ts +3 -9
- package/src/cache/singleflight.ts +5 -2
- package/src/cache/sizeof.ts +3 -1
- package/src/cache/tag-aware-handler.ts +43 -26
- package/src/cli-check.ts +8 -98
- package/src/cli-context.ts +119 -0
- package/src/cli.ts +19 -28
- package/src/client/browser-dev.ts +1 -1
- package/src/client/browser-entry/action-dispatch.ts +26 -4
- package/src/client/browser-entry/hydrate.ts +53 -58
- package/src/client/browser-entry/index.ts +16 -27
- package/src/client/browser-entry/post-hydration.ts +6 -40
- package/src/client/browser-entry/router-init.ts +66 -84
- package/src/client/error-boundary.tsx +9 -41
- package/src/client/error-reconstituter.tsx +10 -5
- package/src/client/history.ts +18 -21
- package/src/client/index.ts +0 -1
- package/src/client/internal.ts +2 -7
- package/src/client/navigation-commit.ts +35 -18
- package/src/client/navigation-context.ts +3 -39
- package/src/client/react-root.ts +3 -2
- package/src/client/router-pipeline.ts +65 -128
- package/src/client/router-types.ts +46 -44
- package/src/client/router-url.ts +32 -0
- package/src/client/router.ts +43 -22
- package/src/client/rsc-fetch.ts +117 -155
- package/src/client/ssr-data.ts +19 -80
- package/src/client/state.ts +2 -9
- package/src/client/use-pathname.ts +1 -1
- package/src/config-types.ts +2 -1
- package/src/config-validation.ts +2 -1
- package/src/dev-tools/dev-page-shell.ts +18 -0
- package/src/dev-tools/index.ts +0 -2
- package/src/dev-tools/instrumentation.ts +50 -2
- package/src/dev-tools/overlay.ts +8 -238
- package/src/index.ts +24 -14
- package/src/plugin-context.ts +39 -40
- package/src/plugins/build-manifest.ts +4 -11
- package/src/plugins/build-report.ts +70 -70
- package/src/plugins/dev-server.ts +24 -44
- package/src/plugins/entries.ts +2 -1
- package/src/plugins/fonts.ts +35 -7
- package/src/plugins/post-build.ts +327 -0
- package/src/plugins/prebuilt-capture.ts +28 -32
- package/src/plugins/prebuilt.ts +54 -39
- package/src/plugins/prerender-sugar.ts +0 -4
- package/src/plugins/{adapter-build.ts → rsc-assets-manifest.ts} +20 -109
- package/src/plugins/shims.ts +1 -0
- package/src/plugins/static-build.ts +42 -74
- package/src/routing/codegen-write.ts +25 -3
- package/src/routing/segment-codegen.ts +3 -2
- package/src/rsc-runtime/vendor-types.d.ts +8 -0
- package/src/server/access-gate.tsx +2 -1
- package/src/server/action-client.ts +1 -1
- package/src/server/action-handler.ts +253 -110
- package/src/server/actions.ts +73 -25
- package/src/server/als-registry.ts +73 -5
- package/src/server/chain-url-parts.ts +1 -1
- package/src/server/children-interception.ts +2 -1
- package/src/server/cookie-context.ts +18 -48
- package/src/server/csp-nonce.ts +0 -12
- package/src/server/csrf.ts +140 -8
- package/src/server/debug.ts +0 -1
- package/src/server/default-logger.ts +2 -1
- package/src/server/deny-boundary.ts +25 -13
- package/src/server/deny-renderer.ts +30 -97
- package/src/server/error-boundary-wrapper.ts +7 -3
- package/src/server/fallback-error.ts +26 -11
- package/src/server/flight-scripts.ts +1 -1
- package/src/server/head-response.ts +4 -4
- package/src/server/html-injector-core.ts +2 -2
- package/src/server/html-injectors.ts +2 -4
- package/src/server/index.ts +0 -4
- package/src/server/instrumentation.ts +10 -3
- package/src/server/internal.ts +1 -6
- package/src/server/json-status-response.ts +105 -0
- package/src/server/logger.ts +39 -3
- package/src/server/param-coercion.ts +15 -12
- package/src/server/pipeline-helpers.ts +257 -12
- package/src/server/pipeline-interception.ts +133 -0
- package/src/server/pipeline-outcome.ts +103 -31
- package/src/server/pipeline-phases.ts +127 -237
- package/src/server/pipeline.ts +204 -207
- package/src/server/prebuilt/capture-render.ts +118 -0
- package/src/server/prebuilt/capture-routes.ts +104 -0
- package/src/server/prebuilt/capture-state.ts +155 -48
- package/src/server/prebuilt/lifetime.ts +151 -0
- package/src/server/prebuilt/slots.ts +14 -2
- package/src/server/prebuilt/synthetic-store.ts +3 -0
- package/src/server/prebuilt-builder.ts +30 -320
- package/src/server/prebuilt-runtime.ts +125 -129
- package/src/server/primitives.ts +8 -168
- package/src/server/react-cache-bridge.ts +124 -0
- package/src/server/react-cache-scope.ts +104 -0
- package/src/server/render-timeout.ts +20 -0
- package/src/server/render-utils.ts +11 -1
- package/src/server/request-context.ts +36 -9
- package/src/server/route-element-builder.ts +11 -6
- package/src/server/route-handler.ts +36 -23
- package/src/server/route-matcher.ts +15 -1
- package/src/server/rsc-entry/action-middleware-runner.ts +79 -123
- package/src/server/rsc-entry/api-handler.ts +27 -103
- package/src/server/rsc-entry/deny-fallback.ts +93 -26
- package/src/server/rsc-entry/error-renderer.ts +39 -91
- package/src/server/rsc-entry/helpers.ts +2 -4
- package/src/server/rsc-entry/index.ts +64 -58
- package/src/server/rsc-entry/render-route.ts +15 -80
- package/src/server/rsc-entry/render-signals.ts +108 -0
- package/src/server/rsc-entry/revalidate-renderer.ts +56 -57
- package/src/server/rsc-entry/rsc-payload.ts +28 -61
- package/src/server/rsc-entry/rsc-stream.ts +113 -213
- package/src/server/rsc-entry/ssr-bridge.ts +2 -2
- package/src/server/rsc-entry/ssr-renderer.ts +182 -263
- package/src/server/rsc-entry/wrap-action-dispatch.ts +12 -14
- package/src/server/signal-identity.ts +112 -0
- package/src/server/slot-resolver.ts +18 -18
- package/src/server/slot-subtree-contain.ts +2 -1
- package/src/server/ssr-bridge-types.ts +92 -56
- package/src/server/ssr-entry.ts +87 -111
- package/src/server/ssr-render.ts +55 -64
- package/src/server/ssr-wrappers.tsx +2 -2
- package/src/server/static-generator.ts +7 -42
- package/src/server/static-not-found.ts +3 -3
- package/src/server/stream-utils.ts +51 -0
- package/src/server/tracing.ts +58 -75
- package/src/server/types.ts +1 -1
- package/src/server/version-skew.ts +5 -5
- package/src/shared/csrf-reject.ts +15 -0
- package/src/shared/error-digest.ts +46 -0
- package/src/shared/payload-root.ts +11 -10
- package/src/shared/rsc-payload-path.ts +8 -1
- package/src/utils/write-file-atomic.ts +32 -0
- package/dist/_chunks/actions-jNrXdzgs.js +0 -346
- package/dist/_chunks/actions-jNrXdzgs.js.map +0 -1
- package/dist/_chunks/als-registry-C6kcfprT.js.map +0 -1
- package/dist/_chunks/build-manifest-DTmSGLRz.js.map +0 -1
- package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +0 -1
- package/dist/_chunks/cache-api-CUD9Ezaq.js.map +0 -1
- package/dist/_chunks/cli-check-G8o30ldg.js.map +0 -1
- package/dist/_chunks/convention-lint-5KzoMg_A.js.map +0 -1
- package/dist/_chunks/dev-server-BzBxgYAV.js.map +0 -1
- package/dist/_chunks/error-boundary-BrHmG-2X.js.map +0 -1
- package/dist/_chunks/fs-identity-D7vb6GdI.js.map +0 -1
- package/dist/_chunks/graph-cache-CP4GEmf9.js.map +0 -1
- package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +0 -1
- package/dist/_chunks/logger-k2DQ4EUf.js.map +0 -1
- package/dist/_chunks/navigation-context-D0TU0Jog.js.map +0 -1
- package/dist/_chunks/plugin-context-8idfR3UZ.js.map +0 -1
- package/dist/_chunks/primitives-DLAnvsrk.js.map +0 -1
- package/dist/_chunks/segment-context-D9_89u34.js +0 -34
- package/dist/_chunks/segment-context-D9_89u34.js.map +0 -1
- package/dist/_chunks/sizeof-lXffQ1Vr.js.map +0 -1
- package/dist/_chunks/ssr-data-D6T6Y3ef.js +0 -60
- package/dist/_chunks/ssr-data-D6T6Y3ef.js.map +0 -1
- package/dist/_chunks/state-FippDgxN.js.map +0 -1
- package/dist/_chunks/status-page-marker-CNbpUOPB.js.map +0 -1
- package/dist/client/types.d.ts +0 -14
- package/dist/client/types.d.ts.map +0 -1
- package/dist/plugins/adapter-build.d.ts +0 -38
- package/dist/plugins/adapter-build.d.ts.map +0 -1
- package/dist/server/asset-headers.d.ts +0 -32
- package/dist/server/asset-headers.d.ts.map +0 -1
- package/dist/server/dev-source-map.d.ts +0 -22
- package/dist/server/dev-source-map.d.ts.map +0 -1
- package/src/client/types.ts +0 -21
- package/src/server/asset-headers.ts +0 -59
- package/src/server/dev-source-map.ts +0 -31
package/dist/index.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { a as formatMissingPeers, i as formatConfigErrors, n as timberDevServer, o as validateConfig, r as checkPeerDependencies } from "./_chunks/dev-server-
|
|
1
|
+
import { a as formatMissingPeers, i as formatConfigErrors, n as timberDevServer, o as validateConfig, r as checkPeerDependencies } from "./_chunks/dev-server-C4WZdB7L.js";
|
|
2
|
+
import { i as resolveRenderTimeoutMs } from "./_chunks/render-timeout-DOf_BBcO.js";
|
|
3
|
+
import { t as writeFileAtomic } from "./_chunks/write-file-atomic-D1qWqHb4.js";
|
|
2
4
|
import { a as isDynamicMetadataExtension } from "./_chunks/metadata-routes-DSDjM_hJ.js";
|
|
3
|
-
import { n as scanRoutes, r as collectInterceptionRewrites } from "./_chunks/scanner-
|
|
4
|
-
import {
|
|
5
|
-
import { c as writeRouteCodegen, i as getPrerenderExport, l as buildDirToRouteMap, n as formatConventionWarnings, r as lintConventions, s as flushCodegenWrites, t as checkAppDirExists } from "./_chunks/convention-lint-
|
|
6
|
-
import { c as
|
|
7
|
-
import { r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "./_chunks/walkers-CN2N_bA-.js";
|
|
8
|
-
import { i as poisonPillSource, r as markerFor, t as EXPLICIT_MARKERS } from "./_chunks/poison-rules-DoEhbqaY.js";
|
|
5
|
+
import { n as scanRoutes, r as collectInterceptionRewrites } from "./_chunks/scanner-Bw0oq1HB.js";
|
|
6
|
+
import { _ as swallow } from "./_chunks/logger-DiDt5ppH.js";
|
|
7
|
+
import { c as writeRouteCodegen, i as getPrerenderExport, l as buildDirToRouteMap, n as formatConventionWarnings, r as lintConventions, s as flushCodegenWrites, t as checkAppDirExists } from "./_chunks/convention-lint-jKTwKwPe.js";
|
|
8
|
+
import { a as loadTimberConfigFile, c as resolveAppDir, d as createNoopTimer, l as resolveBuildDir, n as contextAdapter, o as mergeFileConfig, r as createPluginContext, t as adapterConfig, u as resolveClientJavascript } from "./_chunks/plugin-context-BPBPc3lL.js";
|
|
9
9
|
import { i as withBasePath, n as normalizeBasePath, t as isRelativeBase } from "./_chunks/base-path-DaQrzbez.js";
|
|
10
|
-
import { t as
|
|
11
|
-
import { t as
|
|
12
|
-
import {
|
|
10
|
+
import { r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "./_chunks/walkers-BXExhzzk.js";
|
|
11
|
+
import { i as poisonPillSource, r as markerFor, t as EXPLICIT_MARKERS } from "./_chunks/poison-rules-DoEhbqaY.js";
|
|
12
|
+
import { n as rscPayloadPath, t as RSC_PAYLOAD_DIR } from "./_chunks/rsc-payload-path-dffcs4jp.js";
|
|
13
|
+
import { a as REDIRECTS_FILE, n as detectFsIdentity, o as RESERVED_OUTPUT_PATHS, r as fsKey, t as EXACT_FS_IDENTITY } from "./_chunks/fs-identity-BRKuL215.js";
|
|
14
|
+
import { t as EMPTY_BUILD_MANIFEST } from "./_chunks/build-manifest-DWppEdLB.js";
|
|
13
15
|
import { t as fnv1aHash } from "./_chunks/fast-hash-C-tVYrLb.js";
|
|
14
16
|
import { t as formatSize } from "./_chunks/format-BKclgVbk.js";
|
|
15
17
|
import { createLogger, parseAst } from "vite";
|
|
@@ -202,7 +204,7 @@ function generateConfigModule(ctx) {
|
|
|
202
204
|
topLoader: ctx.config.topLoader,
|
|
203
205
|
debug: ctx.config.debug ?? false,
|
|
204
206
|
serverTiming: ctx.config.serverTiming,
|
|
205
|
-
renderTimeoutMs: ctx.config.renderTimeoutMs
|
|
207
|
+
renderTimeoutMs: resolveRenderTimeoutMs(ctx.config.renderTimeoutMs),
|
|
206
208
|
sitemap: ctx.config.sitemap,
|
|
207
209
|
forms: serializeFormsConfig(ctx.config.forms),
|
|
208
210
|
deploymentId: ctx.deploymentId ?? null,
|
|
@@ -962,7 +964,8 @@ var SUBPATH_SRC_MAP = {
|
|
|
962
964
|
"adapters/cloudflare": "adapters/cloudflare.ts",
|
|
963
965
|
"adapters/cloudflare/cache": "adapters/cloudflare-kv-cache.ts",
|
|
964
966
|
"adapters/cloudflare/dev": "adapters/cloudflare-dev.ts",
|
|
965
|
-
"adapters/nitro": "adapters/nitro.ts"
|
|
967
|
+
"adapters/nitro": "adapters/nitro.ts",
|
|
968
|
+
"adapters/types": "adapters/types.ts"
|
|
966
969
|
};
|
|
967
970
|
/**
|
|
968
971
|
* Runtime value exports of @timber-js/app/server, stubbed in the client
|
|
@@ -4543,8 +4546,14 @@ function writeFontManifest(pipeline, buildManifest, base = "/") {
|
|
|
4543
4546
|
*/
|
|
4544
4547
|
function timberFonts(ctx) {
|
|
4545
4548
|
const pipeline = new FontPipeline({ hashOnRegister: !ctx.dev });
|
|
4549
|
+
/** Whether the client environment emitted a binary this build. */
|
|
4550
|
+
let emittedToClient = false;
|
|
4546
4551
|
return {
|
|
4547
4552
|
name: "timber-fonts",
|
|
4553
|
+
api: {
|
|
4554
|
+
contributeManifest: (manifest) => writeFontManifest(pipeline, manifest, ctx.base),
|
|
4555
|
+
immutableDirs: () => emittedToClient ? [FONT_OUTPUT_DIR] : []
|
|
4556
|
+
},
|
|
4548
4557
|
/**
|
|
4549
4558
|
* Push Vite's resolved `base` into the pipeline so every font URL it
|
|
4550
4559
|
* emits (@font-face src, manifest hrefs, dev middleware matching)
|
|
@@ -4724,213 +4733,24 @@ function timberFonts(ctx) {
|
|
|
4724
4733
|
}
|
|
4725
4734
|
},
|
|
4726
4735
|
/**
|
|
4727
|
-
* Emit font binaries
|
|
4736
|
+
* Emit font binaries.
|
|
4728
4737
|
*
|
|
4729
4738
|
* All font binaries (Google and local) use content-hashed filenames
|
|
4730
4739
|
* for immutable caching. Font CSS is handled by Vite's CSS pipeline
|
|
4731
|
-
* via virtual modules — we only emit binaries here.
|
|
4740
|
+
* via virtual modules — we only emit binaries here. Manifest entries are
|
|
4741
|
+
* written by the post-build phase through `api.contributeManifest`.
|
|
4732
4742
|
*/
|
|
4733
4743
|
generateBundle() {
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4744
|
+
let emitted = 0;
|
|
4745
|
+
emitFontAssets(pipeline, (asset) => {
|
|
4746
|
+
emitted++;
|
|
4747
|
+
return this.emitFile(asset);
|
|
4748
|
+
}, (msg) => this.warn(msg));
|
|
4749
|
+
if (this.environment?.name === "client") emittedToClient = emitted > 0;
|
|
4737
4750
|
}
|
|
4738
4751
|
};
|
|
4739
4752
|
}
|
|
4740
4753
|
//#endregion
|
|
4741
|
-
//#region src/plugins/adapter-build.ts
|
|
4742
|
-
function timberAdapterBuild(ctx) {
|
|
4743
|
-
return {
|
|
4744
|
-
name: "timber-adapter-build",
|
|
4745
|
-
buildApp: {
|
|
4746
|
-
order: "post",
|
|
4747
|
-
async handler() {
|
|
4748
|
-
if (ctx.dev) return;
|
|
4749
|
-
const adapter = ctx.config.adapter;
|
|
4750
|
-
if (!adapter || typeof adapter.buildOutput !== "function") return;
|
|
4751
|
-
const buildDir = ctx.buildDir;
|
|
4752
|
-
if (ctx.buildManifest) await mergeRscAssetsManifest(buildDir, ctx.root, ctx.buildManifest, ctx.routeClientRefKeys);
|
|
4753
|
-
let manifestInit;
|
|
4754
|
-
if (ctx.buildManifest) {
|
|
4755
|
-
const manifest = ctx.clientJavascript.disabled ? {
|
|
4756
|
-
...ctx.buildManifest,
|
|
4757
|
-
js: {},
|
|
4758
|
-
modulepreload: {}
|
|
4759
|
-
} : ctx.buildManifest;
|
|
4760
|
-
manifestInit = `globalThis.__TIMBER_BUILD_MANIFEST__ = ${JSON.stringify(manifest)};\n`;
|
|
4761
|
-
if (ctx.deploymentId) manifestInit += `globalThis.__TIMBER_DEPLOYMENT_ID__ = ${JSON.stringify(ctx.deploymentId)};\n`;
|
|
4762
|
-
}
|
|
4763
|
-
if (ctx.clientJavascript.disabled) await stripJsFromRscAssetsManifests(buildDir);
|
|
4764
|
-
const adapterConfig = {
|
|
4765
|
-
root: ctx.root,
|
|
4766
|
-
base: normalizeBasePath(ctx.base),
|
|
4767
|
-
output: ctx.config.output ?? "server",
|
|
4768
|
-
clientJavascriptDisabled: ctx.clientJavascript.disabled,
|
|
4769
|
-
manifestInit,
|
|
4770
|
-
staticPagesDir: (ctx.config.output ?? "server") === "static" ? join(buildDir, "static-pages") : void 0,
|
|
4771
|
-
staticContentTypes: ctx.staticContentTypes
|
|
4772
|
-
};
|
|
4773
|
-
await adapter.buildOutput(adapterConfig, buildDir);
|
|
4774
|
-
}
|
|
4775
|
-
}
|
|
4776
|
-
};
|
|
4777
|
-
}
|
|
4778
|
-
/**
|
|
4779
|
-
* Parse the RSC assets manifest at `manifestPath`. Tries JSON.parse first
|
|
4780
|
-
* (fast path for plain-string manifests); falls back to a dynamic import()
|
|
4781
|
-
* for manifests that contain runtime expressions from renderBuiltUrl.
|
|
4782
|
-
* Returns null if both paths fail.
|
|
4783
|
-
*/
|
|
4784
|
-
async function parseRscManifest(manifestPath, content) {
|
|
4785
|
-
const jsonStr = content.replace(/^export default\s*/, "").replace(/;?\s*$/, "");
|
|
4786
|
-
try {
|
|
4787
|
-
return JSON.parse(jsonStr);
|
|
4788
|
-
} catch {}
|
|
4789
|
-
try {
|
|
4790
|
-
return (await import(`${pathToFileURL(manifestPath).href}?t=${Date.now()}`)).default ?? null;
|
|
4791
|
-
} catch (err) {
|
|
4792
|
-
swallow(err, `failed to evaluate RSC assets manifest: ${manifestPath}`, { level: "warn" });
|
|
4793
|
-
return null;
|
|
4794
|
-
}
|
|
4795
|
-
}
|
|
4796
|
-
/**
|
|
4797
|
-
* Replace all `"js": [...]` array contents with `"js": []` using balanced
|
|
4798
|
-
* bracket matching. Handles nested brackets from runtime expressions like
|
|
4799
|
-
* `__rbu("path/to/[slug]/file.js")`.
|
|
4800
|
-
*/
|
|
4801
|
-
function clearJsArrays(src) {
|
|
4802
|
-
const pattern = /"js"\s*:\s*\[/g;
|
|
4803
|
-
let result = "";
|
|
4804
|
-
let lastEnd = 0;
|
|
4805
|
-
let match;
|
|
4806
|
-
while ((match = pattern.exec(src)) !== null) {
|
|
4807
|
-
const arrayStart = match.index + match[0].length;
|
|
4808
|
-
let depth = 1;
|
|
4809
|
-
let i = arrayStart;
|
|
4810
|
-
while (i < src.length && depth > 0) {
|
|
4811
|
-
if (src[i] === "[") depth++;
|
|
4812
|
-
else if (src[i] === "]") depth--;
|
|
4813
|
-
i++;
|
|
4814
|
-
}
|
|
4815
|
-
result += src.slice(lastEnd, match.index) + "\"js\": []";
|
|
4816
|
-
lastEnd = i;
|
|
4817
|
-
}
|
|
4818
|
-
result += src.slice(lastEnd);
|
|
4819
|
-
return result;
|
|
4820
|
-
}
|
|
4821
|
-
/**
|
|
4822
|
-
* Replace `"bootstrapScriptContent": <value>` with an empty string. The
|
|
4823
|
-
* value may be a JS expression (e.g., concatenation with runtime helpers),
|
|
4824
|
-
* not a simple string literal. Scans forward from the colon, tracking
|
|
4825
|
-
* balanced parens and brackets, and stops at the next unbalanced `,` or `}`.
|
|
4826
|
-
*/
|
|
4827
|
-
function clearBootstrapScriptContent(src) {
|
|
4828
|
-
const idx = src.indexOf("\"bootstrapScriptContent\"");
|
|
4829
|
-
if (idx === -1) return src;
|
|
4830
|
-
const colonIdx = src.indexOf(":", idx + 24);
|
|
4831
|
-
if (colonIdx === -1) return src;
|
|
4832
|
-
let valStart = colonIdx + 1;
|
|
4833
|
-
while (valStart < src.length && /\s/.test(src[valStart])) valStart++;
|
|
4834
|
-
let i = valStart;
|
|
4835
|
-
let depth = 0;
|
|
4836
|
-
let inString = false;
|
|
4837
|
-
let stringChar = "";
|
|
4838
|
-
while (i < src.length) {
|
|
4839
|
-
const ch = src[i];
|
|
4840
|
-
if (inString) {
|
|
4841
|
-
if (ch === "\\") {
|
|
4842
|
-
i += 2;
|
|
4843
|
-
continue;
|
|
4844
|
-
}
|
|
4845
|
-
if (ch === stringChar) inString = false;
|
|
4846
|
-
} else if (ch === "\"" || ch === "'") {
|
|
4847
|
-
inString = true;
|
|
4848
|
-
stringChar = ch;
|
|
4849
|
-
} else if (ch === "(" || ch === "[") depth++;
|
|
4850
|
-
else if (ch === ")" || ch === "]") depth--;
|
|
4851
|
-
else if (depth === 0 && (ch === "," || ch === "}" || ch === "\n")) break;
|
|
4852
|
-
i++;
|
|
4853
|
-
}
|
|
4854
|
-
return src.slice(0, idx) + "\"bootstrapScriptContent\": \"\"" + src.slice(i);
|
|
4855
|
-
}
|
|
4856
|
-
/**
|
|
4857
|
-
* Strip JS references from the RSC plugin's assets manifest files.
|
|
4858
|
-
*
|
|
4859
|
-
* The RSC plugin writes `__vite_rsc_assets_manifest.js` to rsc/ and ssr/
|
|
4860
|
-
* as standalone files (not Rollup chunks), so generateBundle can't
|
|
4861
|
-
* intercept them. This rewrites the files on disk after all builds
|
|
4862
|
-
* complete but before the adapter copies them to the output directory.
|
|
4863
|
-
*/
|
|
4864
|
-
/**
|
|
4865
|
-
* Read the RSC plugin's assets manifest and merge per-route CSS and
|
|
4866
|
-
* per-route JS modulepreloads into the build manifest.
|
|
4867
|
-
*
|
|
4868
|
-
* CSS: `serverResources` maps server component paths to CSS URLs.
|
|
4869
|
-
* JS: `clientReferenceDeps` maps reference hashes to JS dep URLs.
|
|
4870
|
-
* Combined with `routeClientRefKeys` (from the RSC generateBundle
|
|
4871
|
-
* module graph walk) to produce per-route modulepreload entries.
|
|
4872
|
-
*/
|
|
4873
|
-
async function mergeRscAssetsManifest(buildDir, root, buildManifest, routeClientRefKeys) {
|
|
4874
|
-
const manifestPath = join(buildDir, "rsc", "__vite_rsc_assets_manifest.js");
|
|
4875
|
-
let content;
|
|
4876
|
-
try {
|
|
4877
|
-
content = await readFile(manifestPath, "utf-8");
|
|
4878
|
-
} catch {
|
|
4879
|
-
return;
|
|
4880
|
-
}
|
|
4881
|
-
const manifest = await parseRscManifest(manifestPath, content);
|
|
4882
|
-
if (!manifest) return;
|
|
4883
|
-
const serverResources = manifest.serverResources;
|
|
4884
|
-
if (serverResources) {
|
|
4885
|
-
for (const [relativePath, deps] of Object.entries(serverResources)) if (deps.css && deps.css.length > 0) {
|
|
4886
|
-
const absolutePath = join(root, relativePath);
|
|
4887
|
-
buildManifest.css[absolutePath] = deps.css;
|
|
4888
|
-
}
|
|
4889
|
-
}
|
|
4890
|
-
if (routeClientRefKeys && routeClientRefKeys.size > 0) {
|
|
4891
|
-
const clientReferenceDeps = manifest.clientReferenceDeps;
|
|
4892
|
-
if (clientReferenceDeps) for (const [filePath, refKeys] of routeClientRefKeys) {
|
|
4893
|
-
const jsUrls = /* @__PURE__ */ new Set();
|
|
4894
|
-
for (const key of refKeys) {
|
|
4895
|
-
const deps = clientReferenceDeps[key];
|
|
4896
|
-
if (deps?.js) for (const url of deps.js) jsUrls.add(url);
|
|
4897
|
-
}
|
|
4898
|
-
if (jsUrls.size > 0) buildManifest.modulepreload[filePath] = Array.from(jsUrls);
|
|
4899
|
-
}
|
|
4900
|
-
}
|
|
4901
|
-
}
|
|
4902
|
-
async function stripJsFromRscAssetsManifests(buildDir) {
|
|
4903
|
-
const manifestName = "__vite_rsc_assets_manifest.js";
|
|
4904
|
-
const paths = [join(buildDir, "rsc", manifestName), join(buildDir, "ssr", manifestName)];
|
|
4905
|
-
for (const path of paths) {
|
|
4906
|
-
let content;
|
|
4907
|
-
try {
|
|
4908
|
-
content = await readFile(path, "utf-8");
|
|
4909
|
-
} catch {
|
|
4910
|
-
continue;
|
|
4911
|
-
}
|
|
4912
|
-
const jsonStr = content.replace(/^export default\s*/, "").replace(/;?\s*$/, "");
|
|
4913
|
-
let isStrictJson = true;
|
|
4914
|
-
let manifest = null;
|
|
4915
|
-
try {
|
|
4916
|
-
manifest = JSON.parse(jsonStr);
|
|
4917
|
-
} catch {
|
|
4918
|
-
isStrictJson = false;
|
|
4919
|
-
}
|
|
4920
|
-
if (!isStrictJson) {
|
|
4921
|
-
let rewritten = content;
|
|
4922
|
-
rewritten = clearJsArrays(rewritten);
|
|
4923
|
-
rewritten = clearBootstrapScriptContent(rewritten);
|
|
4924
|
-
await writeFile(path, rewritten);
|
|
4925
|
-
continue;
|
|
4926
|
-
}
|
|
4927
|
-
const deps = manifest?.clientReferenceDeps;
|
|
4928
|
-
if (deps) for (const entry of Object.values(deps)) entry.js = [];
|
|
4929
|
-
if (manifest) manifest.bootstrapScriptContent = "";
|
|
4930
|
-
await writeFile(path, `export default ${JSON.stringify(manifest, null, 2)};\n`);
|
|
4931
|
-
}
|
|
4932
|
-
}
|
|
4933
|
-
//#endregion
|
|
4934
4754
|
//#region src/server/flight-scripts.ts
|
|
4935
4755
|
/**
|
|
4936
4756
|
* Escape a JSON string for safe embedding inside an HTML `<script>` tag.
|
|
@@ -5012,12 +4832,6 @@ function generateRedirectsFile(redirects, base) {
|
|
|
5012
4832
|
const target = (to) => to.startsWith("/") && !to.startsWith("//") ? withBasePath(base, to) : to;
|
|
5013
4833
|
return redirects.map((r) => `${withBasePath(base, r.from)} ${target(r.to)} ${r.status}`).join("\n") + "\n";
|
|
5014
4834
|
}
|
|
5015
|
-
/** Write a file atomically: temp sibling + rename. */
|
|
5016
|
-
async function writeFileAtomic$1(path, data) {
|
|
5017
|
-
const tmp = `${path}.tmp`;
|
|
5018
|
-
await writeFile(tmp, data);
|
|
5019
|
-
await rename(tmp, path);
|
|
5020
|
-
}
|
|
5021
4835
|
/**
|
|
5022
4836
|
* Determine the output file path for a static page entry.
|
|
5023
4837
|
*
|
|
@@ -5056,7 +4870,7 @@ function staticOutputPath(entry) {
|
|
|
5056
4870
|
* API route, `about/index.html` from a page). The filesystem does refuse that
|
|
5057
4871
|
* one — `EISDIR` on the rename, `ENOTDIR` on the mkdir, depending on which
|
|
5058
4872
|
* lands second — but an errno names a path, and in the rename case the path
|
|
5059
|
-
* it names is
|
|
4873
|
+
* it names is the write's temp file. Reported here instead, so the message says which
|
|
5060
4874
|
* two routes.
|
|
5061
4875
|
*
|
|
5062
4876
|
* Collisions are **collected, not thrown**. `onEntry` runs inside the
|
|
@@ -5145,7 +4959,7 @@ var StaticSiteWriter = class {
|
|
|
5145
4959
|
if (rel.split(/[\\/]/)[0] === ".." || isAbsolute(rel) || resolve(this.staticDir, rel) !== fullPath) throw new Error(`[timber] Static generation: output path "${relPath}" escapes the static output directory — check generateStaticSegmentParams for path traversal characters in ${entry.urlPath}`);
|
|
5146
4960
|
if (!this.paths.claim(rel.replace(/\\/g, "/"), entry)) return;
|
|
5147
4961
|
await mkdir(dirname(fullPath), { recursive: true });
|
|
5148
|
-
await writeFileAtomic
|
|
4962
|
+
await writeFileAtomic(fullPath, entry.body);
|
|
5149
4963
|
if (entry.kind === "api" && !extname(relPath) && entry.contentType) this.contentTypes[entry.urlPath] = entry.contentType;
|
|
5150
4964
|
}
|
|
5151
4965
|
/** Throw if any two entries could not both be written. */
|
|
@@ -5173,7 +4987,7 @@ var StaticSiteWriter = class {
|
|
|
5173
4987
|
* @internal Exported for testing.
|
|
5174
4988
|
*/
|
|
5175
4989
|
async function cleanConditionalArtifacts(staticDir) {
|
|
5176
|
-
await rm(join(staticDir,
|
|
4990
|
+
await rm(join(staticDir, RSC_PAYLOAD_DIR), {
|
|
5177
4991
|
recursive: true,
|
|
5178
4992
|
force: true
|
|
5179
4993
|
}).catch(() => {});
|
|
@@ -5219,19 +5033,21 @@ async function withSchedulerPortsReleased(fn) {
|
|
|
5219
5033
|
}
|
|
5220
5034
|
}
|
|
5221
5035
|
/**
|
|
5222
|
-
* Load the built RSC entry and run the static generation pass
|
|
5036
|
+
* Load the built RSC entry and run the static generation pass — the static
|
|
5037
|
+
* generation step of the post-build phase (plugins/post-build.ts).
|
|
5223
5038
|
*
|
|
5224
|
-
*
|
|
5039
|
+
* The build manifest it renders with is already final: the phase merged the
|
|
5040
|
+
* RSC assets manifest into it and published it before this step. Unlike
|
|
5041
|
+
* prebuilt capture, this needs the FULL pipeline handler, so
|
|
5225
5042
|
* __TIMBER_CAPTURE_MODE__ must be false.
|
|
5043
|
+
*
|
|
5044
|
+
* Returns the site only once it is complete, so an adapter is never handed a
|
|
5045
|
+
* directory a failed pass left half-written — a failure throws instead.
|
|
5226
5046
|
*/
|
|
5227
|
-
async function runStaticGeneration(ctx) {
|
|
5228
|
-
const entryPath = join(
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
if (ctx.buildManifest) g.__TIMBER_BUILD_MANIFEST__ ??= ctx.buildManifest;
|
|
5232
|
-
if (ctx.deploymentId) g.__TIMBER_DEPLOYMENT_ID__ ??= ctx.deploymentId;
|
|
5233
|
-
g.__TIMBER_CAPTURE_MODE__ = false;
|
|
5234
|
-
if (ctx.buildManifest) await mergeRscAssetsManifest(ctx.buildDir, ctx.root, ctx.buildManifest, ctx.routeClientRefKeys);
|
|
5047
|
+
async function runStaticGeneration(ctx, rscDir) {
|
|
5048
|
+
const entryPath = join(rscDir, "index.js");
|
|
5049
|
+
warnUnusableBase(ctx);
|
|
5050
|
+
globalThis.__TIMBER_CAPTURE_MODE__ = false;
|
|
5235
5051
|
console.log("[timber] Static generation: building site…");
|
|
5236
5052
|
const staticDir = join(ctx.buildDir, "static-pages");
|
|
5237
5053
|
await cleanConditionalArtifacts(staticDir);
|
|
@@ -5265,12 +5081,12 @@ async function runStaticGeneration(ctx) {
|
|
|
5265
5081
|
throw new Error(`[timber] Static generation failed:\n${details}`);
|
|
5266
5082
|
}
|
|
5267
5083
|
writer.assertNoCollisions();
|
|
5268
|
-
|
|
5084
|
+
const immutableDirs = [];
|
|
5269
5085
|
if (!ctx.clientJavascript.disabled) {
|
|
5270
5086
|
const rscManifest = await hashRscPayloads(staticDir);
|
|
5271
5087
|
if (Object.keys(rscManifest).length > 0) {
|
|
5088
|
+
immutableDirs.push(RSC_PAYLOAD_DIR);
|
|
5272
5089
|
await injectRscManifestIntoHtml(staticDir, rscManifest);
|
|
5273
|
-
ctx.rscManifest = rscManifest;
|
|
5274
5090
|
console.log(`[timber] Static generation: hashed ${Object.keys(rscManifest).length} RSC flight payloads`);
|
|
5275
5091
|
}
|
|
5276
5092
|
}
|
|
@@ -5279,14 +5095,18 @@ async function runStaticGeneration(ctx) {
|
|
|
5279
5095
|
const redirectsPath = join(staticDir, REDIRECTS_FILE);
|
|
5280
5096
|
const userRedirects = await readUserRedirects(ctx.root);
|
|
5281
5097
|
if (userRedirects !== null) {
|
|
5282
|
-
await writeFileAtomic
|
|
5098
|
+
await writeFileAtomic(redirectsPath, generated + "\n" + userRedirects);
|
|
5283
5099
|
console.log(`[timber] Static generation: wrote _redirects with ${summary.redirects.length} generated rule(s), merged with user-authored _redirects`);
|
|
5284
5100
|
} else {
|
|
5285
|
-
await writeFileAtomic
|
|
5101
|
+
await writeFileAtomic(redirectsPath, generated);
|
|
5286
5102
|
console.log(`[timber] Static generation: wrote _redirects with ${summary.redirects.length} rule(s)`);
|
|
5287
5103
|
}
|
|
5288
5104
|
}
|
|
5289
|
-
return
|
|
5105
|
+
return {
|
|
5106
|
+
pages: { path: staticDir },
|
|
5107
|
+
contentTypes: writer.contentTypes,
|
|
5108
|
+
immutableDirs
|
|
5109
|
+
};
|
|
5290
5110
|
}
|
|
5291
5111
|
/**
|
|
5292
5112
|
* Warn when Vite's `base` is document-relative (`'./'`) in static mode.
|
|
@@ -5359,7 +5179,7 @@ async function walkDir(dir) {
|
|
|
5359
5179
|
* @internal Exported for testing.
|
|
5360
5180
|
*/
|
|
5361
5181
|
async function hashRscPayloads(staticDir) {
|
|
5362
|
-
const files = await walkDir(join(staticDir,
|
|
5182
|
+
const files = await walkDir(join(staticDir, RSC_PAYLOAD_DIR));
|
|
5363
5183
|
const manifest = {};
|
|
5364
5184
|
for (const filePath of files) {
|
|
5365
5185
|
if (!filePath.endsWith(".rsc")) continue;
|
|
@@ -5407,11 +5227,9 @@ async function readUserRedirects(root) {
|
|
|
5407
5227
|
/**
|
|
5408
5228
|
* Create the timber-static-build Vite plugin.
|
|
5409
5229
|
*
|
|
5410
|
-
* Only active when output: 'static' is configured.
|
|
5411
|
-
*
|
|
5412
|
-
*
|
|
5413
|
-
* - transform: Validates source files for static mode violations
|
|
5414
|
-
* - buildApp (post): Renders all routes to static HTML after the build
|
|
5230
|
+
* Only active when output: 'static' is configured. Validates source files
|
|
5231
|
+
* for static mode violations; rendering the site is `runStaticGeneration`,
|
|
5232
|
+
* which the post-build phase calls.
|
|
5415
5233
|
*/
|
|
5416
5234
|
function timberStaticBuild(ctx) {
|
|
5417
5235
|
return {
|
|
@@ -5433,22 +5251,6 @@ function timberStaticBuild(ctx) {
|
|
|
5433
5251
|
this.error(messages.join("\n\n"));
|
|
5434
5252
|
}
|
|
5435
5253
|
return null;
|
|
5436
|
-
},
|
|
5437
|
-
/**
|
|
5438
|
-
* After all environments are built, render every route to static HTML.
|
|
5439
|
-
*
|
|
5440
|
-
* Runs with order: 'post' so the RSC plugin's buildApp completes first,
|
|
5441
|
-
* producing the built entry we import. Must run BEFORE the adapter
|
|
5442
|
-
* build copies output to its platform-specific directory.
|
|
5443
|
-
*/
|
|
5444
|
-
buildApp: {
|
|
5445
|
-
order: "post",
|
|
5446
|
-
async handler() {
|
|
5447
|
-
if (ctx.dev) return;
|
|
5448
|
-
if (!(ctx.config.output === "static")) return;
|
|
5449
|
-
warnUnusableBase(ctx);
|
|
5450
|
-
await runStaticGeneration(ctx);
|
|
5451
|
-
}
|
|
5452
5254
|
}
|
|
5453
5255
|
};
|
|
5454
5256
|
}
|
|
@@ -5658,8 +5460,6 @@ function timberBuildManifest(ctx) {
|
|
|
5658
5460
|
if (ctx.requestDepMap === void 0) throw new Error("[timber] Build manifest: the request-dependency map was never computed. The RSC environment's buildEnd hook did not run before the client build, so no segment or slot could be skipped on client navigation. This is a plugin pipeline bug — timber-request-dep must run in the rsc environment.");
|
|
5659
5461
|
ctx.buildManifest.requestDep = ctx.requestDepMap;
|
|
5660
5462
|
if (ctx.clientJavascript.disabled) {
|
|
5661
|
-
ctx.buildManifest.js = {};
|
|
5662
|
-
ctx.buildManifest.modulepreload = {};
|
|
5663
5463
|
for (const [fileName, item] of Object.entries(bundle)) if (item.type === "chunk") delete bundle[fileName];
|
|
5664
5464
|
}
|
|
5665
5465
|
}
|
|
@@ -7841,8 +7641,8 @@ function mayPrerender(call) {
|
|
|
7841
7641
|
/**
|
|
7842
7642
|
* Post-build prebuilt capture — Node-side orchestration (TIM-1119).
|
|
7843
7643
|
*
|
|
7844
|
-
* Runs
|
|
7845
|
-
* build sequence. Imports the BUILT `rsc/index.js` (the bundle carries
|
|
7644
|
+
* Runs as the capture step of the post-build phase (plugins/post-build.ts),
|
|
7645
|
+
* after Vite's 5-step build sequence and the manifest finalization step. Imports the BUILT `rsc/index.js` (the bundle carries
|
|
7846
7646
|
* the react-server condition resolved at build time, so a plain dynamic
|
|
7847
7647
|
* import works) and calls its `__timber_capturePrebuilt` export — the
|
|
7848
7648
|
* capture itself must run inside the bundle's module graph, where the
|
|
@@ -7871,12 +7671,6 @@ function mayPrerender(call) {
|
|
|
7871
7671
|
*/
|
|
7872
7672
|
var COMPONENT_ID_RE = /^[a-z0-9]+_[0-9a-f]{16}$/;
|
|
7873
7673
|
var CACHE_KEY_RE = /^[0-9a-f]{16}$/;
|
|
7874
|
-
/** Write a file atomically: temp sibling + rename. */
|
|
7875
|
-
async function writeFileAtomic(path, data) {
|
|
7876
|
-
const tmp = `${path}.tmp`;
|
|
7877
|
-
await writeFile(tmp, data);
|
|
7878
|
-
await rename(tmp, path);
|
|
7879
|
-
}
|
|
7880
7674
|
/**
|
|
7881
7675
|
* Create the writer for `.timber/dist/prebuilt/`. Storage layout per
|
|
7882
7676
|
* design/44 §Storage: one directory per component ID, one `.flight` file
|
|
@@ -7918,7 +7712,7 @@ function createPrebuiltArtifactWriter(prebuiltDir) {
|
|
|
7918
7712
|
* make adapters ship payloads from an OLD build — reviving them serves
|
|
7919
7713
|
* outdated content with that build's chunk references instead of the
|
|
7920
7714
|
* intended miss → live render. Runs unconditionally at the start of the
|
|
7921
|
-
*
|
|
7715
|
+
* capture step, BEFORE the capture decision: a build whose app no
|
|
7922
7716
|
* longer declares any prebuilt components must also shed the artifacts
|
|
7923
7717
|
* (codex P2 on PR #836).
|
|
7924
7718
|
*/
|
|
@@ -7935,19 +7729,16 @@ async function cleanPrebuiltDir(buildDir) {
|
|
|
7935
7729
|
* component). Per-entry data errors skip-and-report per design/44
|
|
7936
7730
|
* §Build-Phase Error Handling.
|
|
7937
7731
|
*/
|
|
7938
|
-
async function runPrebuiltCapture(ctx) {
|
|
7732
|
+
async function runPrebuiltCapture(ctx, rscDir) {
|
|
7939
7733
|
const routeComponents = ctx.routePrebuiltComponents;
|
|
7940
|
-
if (!routeComponents || routeComponents.size === 0) return {
|
|
7734
|
+
if (!routeComponents || routeComponents.size === 0) return { summary: {
|
|
7941
7735
|
captured: 0,
|
|
7942
7736
|
skipped: [],
|
|
7943
7737
|
hardErrors: [],
|
|
7944
7738
|
nestingWarnings: 0
|
|
7945
|
-
};
|
|
7946
|
-
const entryPath = join(
|
|
7947
|
-
if (!existsSync(entryPath)) throw new Error(`[timber] prebuilt capture: built RSC entry not found at ${entryPath} — the app declares cache.component({ prerender: true }) call sites but the RSC build output is missing`);
|
|
7739
|
+
} };
|
|
7740
|
+
const entryPath = join(rscDir, "index.js");
|
|
7948
7741
|
const g = globalThis;
|
|
7949
|
-
if (ctx.buildManifest) g.__TIMBER_BUILD_MANIFEST__ ??= ctx.buildManifest;
|
|
7950
|
-
if (ctx.deploymentId) g.__TIMBER_DEPLOYMENT_ID__ ??= ctx.deploymentId;
|
|
7951
7742
|
console.log("[timber] cache.component: capturing prebuilt flight payloads…");
|
|
7952
7743
|
g.__TIMBER_CAPTURE_MODE__ = true;
|
|
7953
7744
|
let mod;
|
|
@@ -7961,7 +7752,8 @@ async function runPrebuiltCapture(ctx) {
|
|
|
7961
7752
|
}
|
|
7962
7753
|
const capture = mod.__timber_capturePrebuilt;
|
|
7963
7754
|
if (typeof capture !== "function") throw new Error("[timber] prebuilt capture: built RSC entry does not export __timber_capturePrebuilt — the build output predates this framework version; rebuild from a clean .timber/dist");
|
|
7964
|
-
const
|
|
7755
|
+
const prebuiltDir = join(ctx.buildDir, "prebuilt");
|
|
7756
|
+
const writer = createPrebuiltArtifactWriter(prebuiltDir);
|
|
7965
7757
|
const summary = await capture({
|
|
7966
7758
|
fileComponentMap: Object.fromEntries(routeComponents),
|
|
7967
7759
|
callSiteProps: ctx.prebuiltCallSiteProps ? Object.fromEntries(ctx.prebuiltCallSiteProps) : void 0,
|
|
@@ -7972,10 +7764,13 @@ async function runPrebuiltCapture(ctx) {
|
|
|
7972
7764
|
const details = summary.hardErrors.map((issue) => ` - ${issue.message}`).join("\n");
|
|
7973
7765
|
throw new Error(`[timber] prebuilt capture failed: ${summary.hardErrors.length} component(s) read per-request context at build time:\n${details}`);
|
|
7974
7766
|
}
|
|
7975
|
-
await writer.finalize();
|
|
7767
|
+
const written = await writer.finalize();
|
|
7976
7768
|
const total = summary.captured + summary.skipped.length;
|
|
7977
7769
|
console.log(`[timber] Prebuilt ${summary.captured}/${total} entries.` + (summary.skipped.length > 0 ? ` ${summary.skipped.length} skipped due to errors.` : ""));
|
|
7978
|
-
return
|
|
7770
|
+
return written > 0 ? {
|
|
7771
|
+
summary,
|
|
7772
|
+
artifact: { path: prebuiltDir }
|
|
7773
|
+
} : { summary };
|
|
7979
7774
|
}
|
|
7980
7775
|
//#endregion
|
|
7981
7776
|
//#region src/plugins/prebuilt.ts
|
|
@@ -8149,8 +7944,7 @@ function collectPageAndLayoutFiles(root) {
|
|
|
8149
7944
|
return files;
|
|
8150
7945
|
}
|
|
8151
7946
|
var DEFAULT_SENTINEL = "\0default";
|
|
8152
|
-
async function collectCrossModuleProps(ctx, moduleId, getInfo, resolve) {
|
|
8153
|
-
const bindingNames = ctx.prebuiltBindingNames;
|
|
7947
|
+
async function collectCrossModuleProps(ctx, bindingNames, moduleId, getInfo, resolve) {
|
|
8154
7948
|
const info = getInfo(moduleId);
|
|
8155
7949
|
if (!info) return;
|
|
8156
7950
|
const declaringImports = info.importedIds.filter((id) => bindingNames.has(id) && id !== moduleId);
|
|
@@ -8218,10 +8012,34 @@ async function collectCrossModuleProps(ctx, moduleId, getInfo, resolve) {
|
|
|
8218
8012
|
}
|
|
8219
8013
|
}
|
|
8220
8014
|
function timberPrebuilt(ctx) {
|
|
8015
|
+
/**
|
|
8016
|
+
* Module ID → prerender-capable component IDs declared in it. Recorded by
|
|
8017
|
+
* the RSC transform, read by the RSC `generateBundle` module-graph walk
|
|
8018
|
+
* that computes `ctx.routePrebuiltComponents`. Build only.
|
|
8019
|
+
*/
|
|
8020
|
+
const moduleComponents = /* @__PURE__ */ new Map();
|
|
8021
|
+
/**
|
|
8022
|
+
* Module ID → variable name → component ID, for the prebuilt components
|
|
8023
|
+
* that module declares. Read at `generateBundle` time to trace imports in
|
|
8024
|
+
* other modules back to component IDs (cross-module call-site props).
|
|
8025
|
+
*/
|
|
8026
|
+
const bindingNames = /* @__PURE__ */ new Map();
|
|
8221
8027
|
return {
|
|
8222
8028
|
name: "timber-prebuilt",
|
|
8029
|
+
api: { async capture(rscDir) {
|
|
8030
|
+
await cleanPrebuiltDir(ctx.buildDir);
|
|
8031
|
+
if (!ctx.routePrebuiltComponents || ctx.routePrebuiltComponents.size === 0) return null;
|
|
8032
|
+
if (ctx.config.output === "static") {
|
|
8033
|
+
console.log(`[timber] cache.component: skipped prerender capture (output: 'static' renders all components at build time)`);
|
|
8034
|
+
return null;
|
|
8035
|
+
}
|
|
8036
|
+
return runPrebuiltCapture(ctx, rscDir);
|
|
8037
|
+
} },
|
|
8223
8038
|
transform(code, id) {
|
|
8224
|
-
if (!ctx.dev && this?.environment?.name === "rsc")
|
|
8039
|
+
if (!ctx.dev && this?.environment?.name === "rsc") {
|
|
8040
|
+
moduleComponents.delete(id);
|
|
8041
|
+
bindingNames.delete(id);
|
|
8042
|
+
}
|
|
8225
8043
|
if (!code.includes("@timber-js/app/cache") && !code.includes("timber/cache")) return;
|
|
8226
8044
|
if (id.includes("node_modules")) return;
|
|
8227
8045
|
if (this?.environment?.name === "client") return;
|
|
@@ -8253,8 +8071,7 @@ function timberPrebuilt(ctx) {
|
|
|
8253
8071
|
s.appendLeft(call.arguments[0].start, `${JSON.stringify(firstArg)}, `);
|
|
8254
8072
|
}
|
|
8255
8073
|
if (!ctx.dev && componentIds.length > 0 && this?.environment?.name === "rsc") {
|
|
8256
|
-
|
|
8257
|
-
ctx.prebuiltModuleComponents.set(id, componentIds);
|
|
8074
|
+
moduleComponents.set(id, componentIds);
|
|
8258
8075
|
const bindingMap = /* @__PURE__ */ new Map();
|
|
8259
8076
|
let componentIdIdx = 0;
|
|
8260
8077
|
for (const { call, stmt, displayName } of callSites) if (!ctx.dev && mayPrerender(call)) {
|
|
@@ -8274,10 +8091,7 @@ function timberPrebuilt(ctx) {
|
|
|
8274
8091
|
}
|
|
8275
8092
|
}
|
|
8276
8093
|
}
|
|
8277
|
-
if (bindingMap.size > 0)
|
|
8278
|
-
ctx.prebuiltBindingNames ??= /* @__PURE__ */ new Map();
|
|
8279
|
-
ctx.prebuiltBindingNames.set(id, bindingMap);
|
|
8280
|
-
}
|
|
8094
|
+
if (bindingMap.size > 0) bindingNames.set(id, bindingMap);
|
|
8281
8095
|
const declaredBindings = new Set([...bindingMap.keys()].filter((k) => k !== DEFAULT_SENTINEL));
|
|
8282
8096
|
if (declaredBindings.size > 0) {
|
|
8283
8097
|
const usages = collectJsxUsages(program, declaredBindings);
|
|
@@ -8308,8 +8122,8 @@ function timberPrebuilt(ctx) {
|
|
|
8308
8122
|
if (ctx.dev) return;
|
|
8309
8123
|
if (this?.environment?.name !== "rsc") return;
|
|
8310
8124
|
ctx.routePrebuiltComponents = void 0;
|
|
8311
|
-
|
|
8312
|
-
if (
|
|
8125
|
+
ctx.prebuiltLazyChunks = void 0;
|
|
8126
|
+
if (moduleComponents.size === 0 || !ctx.routeTree) return;
|
|
8313
8127
|
const self = this;
|
|
8314
8128
|
const getInfo = (id) => self.getModuleInfo?.(id) ?? null;
|
|
8315
8129
|
const resolveFn = async (source, importer) => {
|
|
@@ -8337,7 +8151,7 @@ function timberPrebuilt(ctx) {
|
|
|
8337
8151
|
}
|
|
8338
8152
|
if (lazyChunks.size > 0) ctx.prebuiltLazyChunks = lazyChunks;
|
|
8339
8153
|
}
|
|
8340
|
-
if (
|
|
8154
|
+
if (bindingNames.size > 0) {
|
|
8341
8155
|
const scannedModules = /* @__PURE__ */ new Set();
|
|
8342
8156
|
for (const filePath of routeComponents.keys()) {
|
|
8343
8157
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -8348,7 +8162,7 @@ function timberPrebuilt(ctx) {
|
|
|
8348
8162
|
visited.add(modId);
|
|
8349
8163
|
if (!scannedModules.has(modId)) {
|
|
8350
8164
|
scannedModules.add(modId);
|
|
8351
|
-
await collectCrossModuleProps(ctx, modId, getInfo, resolveFn);
|
|
8165
|
+
await collectCrossModuleProps(ctx, bindingNames, modId, getInfo, resolveFn);
|
|
8352
8166
|
}
|
|
8353
8167
|
const modInfo = getInfo(modId);
|
|
8354
8168
|
if (!modInfo) continue;
|
|
@@ -8358,26 +8172,6 @@ function timberPrebuilt(ctx) {
|
|
|
8358
8172
|
}
|
|
8359
8173
|
}
|
|
8360
8174
|
} else console.warn(`[timber] cache.component: ${moduleComponents.size} module(s) declare prebuilt components, but none are reachable from any page or layout — no payloads will be prerendered`);
|
|
8361
|
-
},
|
|
8362
|
-
/**
|
|
8363
|
-
* Post-build capture (design/44 §Build Phase). `order: 'post'` runs
|
|
8364
|
-
* after the RSC plugin's buildApp — all five build steps are complete —
|
|
8365
|
-
* and BEFORE timber-adapter-build's post hook (plugin array order), so
|
|
8366
|
-
* `prebuilt/` exists when the adapter assembles its output (TIM-1122).
|
|
8367
|
-
*/
|
|
8368
|
-
buildApp: {
|
|
8369
|
-
order: "post",
|
|
8370
|
-
async handler() {
|
|
8371
|
-
if (ctx.dev) return;
|
|
8372
|
-
ctx.captureSummary = void 0;
|
|
8373
|
-
await cleanPrebuiltDir(ctx.buildDir);
|
|
8374
|
-
if (!ctx.routePrebuiltComponents || ctx.routePrebuiltComponents.size === 0) return;
|
|
8375
|
-
if (ctx.config.output === "static") {
|
|
8376
|
-
console.log(`[timber] cache.component: skipped prerender capture (output: 'static' renders all components at build time)`);
|
|
8377
|
-
return;
|
|
8378
|
-
}
|
|
8379
|
-
ctx.captureSummary = await runPrebuiltCapture(ctx);
|
|
8380
|
-
}
|
|
8381
8175
|
}
|
|
8382
8176
|
};
|
|
8383
8177
|
}
|
|
@@ -8530,8 +8324,6 @@ function timberPrerenderSugar(ctx) {
|
|
|
8530
8324
|
if (defaultExport.kind === "expression" && defaultExport.node.declaration) {
|
|
8531
8325
|
if (code.slice(defaultExport.node.declaration.start, defaultExport.node.declaration.end).includes(".component(")) return;
|
|
8532
8326
|
}
|
|
8533
|
-
ctx.prerenderSugarPages ??= /* @__PURE__ */ new Set();
|
|
8534
|
-
ctx.prerenderSugarPages.add(id);
|
|
8535
8327
|
const s = new MagicString(code);
|
|
8536
8328
|
const optionsSource = buildOptionsSource(value);
|
|
8537
8329
|
const importAlias = "__timber_prerender_cache__";
|
|
@@ -8668,6 +8460,378 @@ function timberCloudflareWasm(ctx) {
|
|
|
8668
8460
|
}];
|
|
8669
8461
|
}
|
|
8670
8462
|
//#endregion
|
|
8463
|
+
//#region src/plugins/rsc-assets-manifest.ts
|
|
8464
|
+
/**
|
|
8465
|
+
* The RSC plugin's assets manifest (`__vite_rsc_assets_manifest.js`) — read
|
|
8466
|
+
* into the build manifest, and stripped of JavaScript when client JS is off.
|
|
8467
|
+
*
|
|
8468
|
+
* The RSC plugin writes the file to rsc/ and ssr/ as a standalone file, not
|
|
8469
|
+
* a Rollup chunk, so no `generateBundle` can intercept it; both operations
|
|
8470
|
+
* work on the written files. Both run once, from the post-build phase's
|
|
8471
|
+
* manifest finalization step (plugins/post-build.ts), before anything
|
|
8472
|
+
* imports the built bundle.
|
|
8473
|
+
*
|
|
8474
|
+
* Design doc: 18-build-system.md §"Post-Build Phase"
|
|
8475
|
+
*/
|
|
8476
|
+
/**
|
|
8477
|
+
* Parse the RSC assets manifest at `manifestPath`. Tries JSON.parse first
|
|
8478
|
+
* (fast path for plain-string manifests); falls back to a dynamic import()
|
|
8479
|
+
* for manifests that contain runtime expressions from renderBuiltUrl.
|
|
8480
|
+
* Returns null if both paths fail.
|
|
8481
|
+
*/
|
|
8482
|
+
async function parseRscManifest(manifestPath, content) {
|
|
8483
|
+
const jsonStr = content.replace(/^export default\s*/, "").replace(/;?\s*$/, "");
|
|
8484
|
+
try {
|
|
8485
|
+
return JSON.parse(jsonStr);
|
|
8486
|
+
} catch {}
|
|
8487
|
+
try {
|
|
8488
|
+
return (await import(`${pathToFileURL(manifestPath).href}?t=${Date.now()}`)).default ?? null;
|
|
8489
|
+
} catch (err) {
|
|
8490
|
+
swallow(err, `failed to evaluate RSC assets manifest: ${manifestPath}`, { level: "warn" });
|
|
8491
|
+
return null;
|
|
8492
|
+
}
|
|
8493
|
+
}
|
|
8494
|
+
/**
|
|
8495
|
+
* Replace all `"js": [...]` array contents with `"js": []` using balanced
|
|
8496
|
+
* bracket matching. Handles nested brackets from runtime expressions like
|
|
8497
|
+
* `__rbu("path/to/[slug]/file.js")`.
|
|
8498
|
+
*/
|
|
8499
|
+
function clearJsArrays(src) {
|
|
8500
|
+
const pattern = /"js"\s*:\s*\[/g;
|
|
8501
|
+
let result = "";
|
|
8502
|
+
let lastEnd = 0;
|
|
8503
|
+
let match;
|
|
8504
|
+
while ((match = pattern.exec(src)) !== null) {
|
|
8505
|
+
const arrayStart = match.index + match[0].length;
|
|
8506
|
+
let depth = 1;
|
|
8507
|
+
let i = arrayStart;
|
|
8508
|
+
while (i < src.length && depth > 0) {
|
|
8509
|
+
if (src[i] === "[") depth++;
|
|
8510
|
+
else if (src[i] === "]") depth--;
|
|
8511
|
+
i++;
|
|
8512
|
+
}
|
|
8513
|
+
result += src.slice(lastEnd, match.index) + "\"js\": []";
|
|
8514
|
+
lastEnd = i;
|
|
8515
|
+
}
|
|
8516
|
+
result += src.slice(lastEnd);
|
|
8517
|
+
return result;
|
|
8518
|
+
}
|
|
8519
|
+
/**
|
|
8520
|
+
* Replace `"bootstrapScriptContent": <value>` with an empty string. The
|
|
8521
|
+
* value may be a JS expression (e.g., concatenation with runtime helpers),
|
|
8522
|
+
* not a simple string literal. Scans forward from the colon, tracking
|
|
8523
|
+
* balanced parens and brackets, and stops at the next unbalanced `,` or `}`.
|
|
8524
|
+
*/
|
|
8525
|
+
function clearBootstrapScriptContent(src) {
|
|
8526
|
+
const idx = src.indexOf("\"bootstrapScriptContent\"");
|
|
8527
|
+
if (idx === -1) return src;
|
|
8528
|
+
const colonIdx = src.indexOf(":", idx + 24);
|
|
8529
|
+
if (colonIdx === -1) return src;
|
|
8530
|
+
let valStart = colonIdx + 1;
|
|
8531
|
+
while (valStart < src.length && /\s/.test(src[valStart])) valStart++;
|
|
8532
|
+
let i = valStart;
|
|
8533
|
+
let depth = 0;
|
|
8534
|
+
let inString = false;
|
|
8535
|
+
let stringChar = "";
|
|
8536
|
+
while (i < src.length) {
|
|
8537
|
+
const ch = src[i];
|
|
8538
|
+
if (inString) {
|
|
8539
|
+
if (ch === "\\") {
|
|
8540
|
+
i += 2;
|
|
8541
|
+
continue;
|
|
8542
|
+
}
|
|
8543
|
+
if (ch === stringChar) inString = false;
|
|
8544
|
+
} else if (ch === "\"" || ch === "'") {
|
|
8545
|
+
inString = true;
|
|
8546
|
+
stringChar = ch;
|
|
8547
|
+
} else if (ch === "(" || ch === "[") depth++;
|
|
8548
|
+
else if (ch === ")" || ch === "]") depth--;
|
|
8549
|
+
else if (depth === 0 && (ch === "," || ch === "}" || ch === "\n")) break;
|
|
8550
|
+
i++;
|
|
8551
|
+
}
|
|
8552
|
+
return src.slice(0, idx) + "\"bootstrapScriptContent\": \"\"" + src.slice(i);
|
|
8553
|
+
}
|
|
8554
|
+
/**
|
|
8555
|
+
* Read the RSC plugin's assets manifest and merge per-route CSS and
|
|
8556
|
+
* per-route JS modulepreloads into the build manifest.
|
|
8557
|
+
*
|
|
8558
|
+
* CSS: `serverResources` maps server component paths to CSS URLs.
|
|
8559
|
+
* JS: `clientReferenceDeps` maps reference hashes to JS dep URLs.
|
|
8560
|
+
* Combined with `routeClientRefKeys` (from the RSC generateBundle
|
|
8561
|
+
* module graph walk) to produce per-route modulepreload entries.
|
|
8562
|
+
*/
|
|
8563
|
+
async function mergeRscAssetsManifest(rscDir, root, buildManifest, routeClientRefKeys) {
|
|
8564
|
+
const manifestPath = join(rscDir, "__vite_rsc_assets_manifest.js");
|
|
8565
|
+
let content;
|
|
8566
|
+
try {
|
|
8567
|
+
content = await readFile(manifestPath, "utf-8");
|
|
8568
|
+
} catch {
|
|
8569
|
+
return;
|
|
8570
|
+
}
|
|
8571
|
+
const manifest = await parseRscManifest(manifestPath, content);
|
|
8572
|
+
if (!manifest) return;
|
|
8573
|
+
const serverResources = manifest.serverResources;
|
|
8574
|
+
if (serverResources) {
|
|
8575
|
+
for (const [relativePath, deps] of Object.entries(serverResources)) if (deps.css && deps.css.length > 0) {
|
|
8576
|
+
const absolutePath = join(root, relativePath);
|
|
8577
|
+
buildManifest.css[absolutePath] = deps.css;
|
|
8578
|
+
}
|
|
8579
|
+
}
|
|
8580
|
+
if (routeClientRefKeys && routeClientRefKeys.size > 0) {
|
|
8581
|
+
const clientReferenceDeps = manifest.clientReferenceDeps;
|
|
8582
|
+
if (clientReferenceDeps) for (const [filePath, refKeys] of routeClientRefKeys) {
|
|
8583
|
+
const jsUrls = /* @__PURE__ */ new Set();
|
|
8584
|
+
for (const key of refKeys) {
|
|
8585
|
+
const deps = clientReferenceDeps[key];
|
|
8586
|
+
if (deps?.js) for (const url of deps.js) jsUrls.add(url);
|
|
8587
|
+
}
|
|
8588
|
+
if (jsUrls.size > 0) buildManifest.modulepreload[filePath] = Array.from(jsUrls);
|
|
8589
|
+
}
|
|
8590
|
+
}
|
|
8591
|
+
}
|
|
8592
|
+
/**
|
|
8593
|
+
* Strip JS references from the RSC plugin's assets manifest files.
|
|
8594
|
+
*
|
|
8595
|
+
* The RSC plugin writes `__vite_rsc_assets_manifest.js` to rsc/ and ssr/
|
|
8596
|
+
* as standalone files (not Rollup chunks), so generateBundle can't
|
|
8597
|
+
* intercept them. This rewrites the files on disk after all builds
|
|
8598
|
+
* complete but before the adapter copies them to the output directory.
|
|
8599
|
+
*/
|
|
8600
|
+
async function stripJsFromRscAssetsManifests(serverDirs) {
|
|
8601
|
+
const paths = serverDirs.map((dir) => join(dir, "__vite_rsc_assets_manifest.js"));
|
|
8602
|
+
for (const path of paths) {
|
|
8603
|
+
let content;
|
|
8604
|
+
try {
|
|
8605
|
+
content = await readFile(path, "utf-8");
|
|
8606
|
+
} catch {
|
|
8607
|
+
continue;
|
|
8608
|
+
}
|
|
8609
|
+
const jsonStr = content.replace(/^export default\s*/, "").replace(/;?\s*$/, "");
|
|
8610
|
+
let isStrictJson = true;
|
|
8611
|
+
let manifest = null;
|
|
8612
|
+
try {
|
|
8613
|
+
manifest = JSON.parse(jsonStr);
|
|
8614
|
+
} catch {
|
|
8615
|
+
isStrictJson = false;
|
|
8616
|
+
}
|
|
8617
|
+
if (!isStrictJson) {
|
|
8618
|
+
let rewritten = content;
|
|
8619
|
+
rewritten = clearJsArrays(rewritten);
|
|
8620
|
+
rewritten = clearBootstrapScriptContent(rewritten);
|
|
8621
|
+
await writeFile(path, rewritten);
|
|
8622
|
+
continue;
|
|
8623
|
+
}
|
|
8624
|
+
const deps = manifest?.clientReferenceDeps;
|
|
8625
|
+
if (deps) for (const entry of Object.values(deps)) entry.js = [];
|
|
8626
|
+
if (manifest) manifest.bootstrapScriptContent = "";
|
|
8627
|
+
await writeFile(path, `export default ${JSON.stringify(manifest, null, 2)};\n`);
|
|
8628
|
+
}
|
|
8629
|
+
}
|
|
8630
|
+
//#endregion
|
|
8631
|
+
//#region src/plugins/post-build.ts
|
|
8632
|
+
/** The Vite environments whose output adapters consume. */
|
|
8633
|
+
var ARTIFACT_ENVIRONMENTS = [
|
|
8634
|
+
"client",
|
|
8635
|
+
"rsc",
|
|
8636
|
+
"ssr"
|
|
8637
|
+
];
|
|
8638
|
+
function isArtifactEnvironment(name) {
|
|
8639
|
+
return ARTIFACT_ENVIRONMENTS.includes(name);
|
|
8640
|
+
}
|
|
8641
|
+
function timberPostBuild(ctx, steps) {
|
|
8642
|
+
const environments = {};
|
|
8643
|
+
/** What the client environment's bundle wrote, from its `writeBundle`. */
|
|
8644
|
+
let clientOutput = {
|
|
8645
|
+
assetsDir: "",
|
|
8646
|
+
emitted: /* @__PURE__ */ new Set()
|
|
8647
|
+
};
|
|
8648
|
+
return {
|
|
8649
|
+
name: "timber-post-build",
|
|
8650
|
+
writeBundle(options, bundle) {
|
|
8651
|
+
if (ctx.dev) return;
|
|
8652
|
+
const env = this.environment;
|
|
8653
|
+
if (!isArtifactEnvironment(env.name)) return;
|
|
8654
|
+
environments[env.name] = { path: resolve(env.config.root, env.config.build.outDir) };
|
|
8655
|
+
if (env.name === "client") clientOutput = {
|
|
8656
|
+
assetsDir: hashedAssetsDir(env.config.build.assetsDir, options),
|
|
8657
|
+
emitted: new Set(Object.keys(bundle))
|
|
8658
|
+
};
|
|
8659
|
+
},
|
|
8660
|
+
buildApp: {
|
|
8661
|
+
order: "post",
|
|
8662
|
+
async handler() {
|
|
8663
|
+
if (ctx.dev) return;
|
|
8664
|
+
await runPostBuild(ctx, steps, environments, clientOutput);
|
|
8665
|
+
}
|
|
8666
|
+
}
|
|
8667
|
+
};
|
|
8668
|
+
}
|
|
8669
|
+
/**
|
|
8670
|
+
* The client bundle's assets directory, in the artifacts' form (no leading
|
|
8671
|
+
* or trailing slash) — or `''` when its files are not all content-hashed.
|
|
8672
|
+
*
|
|
8673
|
+
* `assetsDir` names where Vite writes; it is the naming patterns that decide
|
|
8674
|
+
* whether a file name carries a hash. Vite's defaults do
|
|
8675
|
+
* (`<assetsDir>/[name]-[hash].js`), but an app can set
|
|
8676
|
+
* `assetFileNames: 'static/[name][extname]'`, and marking that directory
|
|
8677
|
+
* immutable would pin a changed image under an unchanged URL for a year. A
|
|
8678
|
+
* pattern given as a function cannot be inspected, so it counts as unhashed:
|
|
8679
|
+
* those files fall back to the revalidating per-file rule.
|
|
8680
|
+
*
|
|
8681
|
+
* @internal Exported for testing.
|
|
8682
|
+
*/
|
|
8683
|
+
function hashedAssetsDir(assetsDir, output) {
|
|
8684
|
+
const dir = assetsDir.replace(/^\/+|\/+$/g, "");
|
|
8685
|
+
return [
|
|
8686
|
+
output.entryFileNames,
|
|
8687
|
+
output.chunkFileNames,
|
|
8688
|
+
output.assetFileNames
|
|
8689
|
+
].every((p) => typeof p === "string" && p.includes("[hash")) ? dir : "";
|
|
8690
|
+
}
|
|
8691
|
+
/**
|
|
8692
|
+
* Keep only the directories whose every file the client bundle emitted.
|
|
8693
|
+
*
|
|
8694
|
+
* A producer knows it hashes what *it* writes, not what else lands beside it:
|
|
8695
|
+
* Vite copies `public/` into the client output verbatim, so `public/assets/logo.png`
|
|
8696
|
+
* sits in `assets/` under a stable name, and `public/_rsc/…` would sit among
|
|
8697
|
+
* the hashed payloads. A directory holding any file the bundle did not emit
|
|
8698
|
+
* is not content-hashed as a whole, and marking it immutable would pin that
|
|
8699
|
+
* file for a year — so it is dropped, and its files take the per-file rule.
|
|
8700
|
+
*
|
|
8701
|
+
* @internal Exported for testing.
|
|
8702
|
+
*/
|
|
8703
|
+
async function onlyEmittedDirs(clientDir, dirs, emitted) {
|
|
8704
|
+
const kept = [];
|
|
8705
|
+
for (const dir of dirs) {
|
|
8706
|
+
const root = join(clientDir, dir);
|
|
8707
|
+
if (!(await readdir(root, {
|
|
8708
|
+
recursive: true,
|
|
8709
|
+
withFileTypes: true
|
|
8710
|
+
}).catch(() => [])).some((entry) => entry.isFile() && !emitted.has(relative(clientDir, join(entry.parentPath, entry.name)).replace(/\\/g, "/")))) kept.push(dir);
|
|
8711
|
+
}
|
|
8712
|
+
return kept;
|
|
8713
|
+
}
|
|
8714
|
+
async function runPostBuild(ctx, steps, environments, clientOutput) {
|
|
8715
|
+
const output = ctx.config.output ?? "server";
|
|
8716
|
+
const rsc = requireEnvironment(environments, "rsc");
|
|
8717
|
+
const ssr = requireEnvironment(environments, "ssr");
|
|
8718
|
+
const manifest = await finalizeBuildManifest(ctx, steps.fonts, rsc, ssr);
|
|
8719
|
+
if (manifest) Reflect.set(globalThis, "__TIMBER_BUILD_MANIFEST__", manifest);
|
|
8720
|
+
const prebuilt = await steps.prebuilt.capture(rsc.path);
|
|
8721
|
+
const site = output === "static" ? await runStaticGeneration(ctx, rsc.path) : void 0;
|
|
8722
|
+
steps.report.print(prebuilt);
|
|
8723
|
+
const adapter = contextAdapter(ctx);
|
|
8724
|
+
if (!adapter || typeof adapter.buildOutput !== "function") return;
|
|
8725
|
+
await adapter.buildOutput(adapterConfig(ctx), assembleBuildArtifacts({
|
|
8726
|
+
output,
|
|
8727
|
+
outputDir: ctx.buildDir,
|
|
8728
|
+
environments,
|
|
8729
|
+
immutableDirs: await onlyEmittedDirs(requireEnvironment(environments, "client").path, [
|
|
8730
|
+
...clientOutput.assetsDir ? [clientOutput.assetsDir] : [],
|
|
8731
|
+
...steps.fonts.immutableDirs(),
|
|
8732
|
+
...site?.immutableDirs ?? []
|
|
8733
|
+
], clientOutput.emitted),
|
|
8734
|
+
prebuilt: prebuilt?.artifact,
|
|
8735
|
+
site,
|
|
8736
|
+
manifestInit: manifest ? serializeManifestInit(manifest) : void 0
|
|
8737
|
+
}));
|
|
8738
|
+
}
|
|
8739
|
+
function requireEnvironment(environments, name) {
|
|
8740
|
+
const artifact = environments[name];
|
|
8741
|
+
if (!artifact) throw new Error(`[timber] Build output: the ${name} environment wrote no bundle`);
|
|
8742
|
+
return artifact;
|
|
8743
|
+
}
|
|
8744
|
+
/**
|
|
8745
|
+
* Step 1: bring the build manifest to its final shape, once.
|
|
8746
|
+
*
|
|
8747
|
+
* `timber-build-manifest` creates it from the client bundle; this adds what
|
|
8748
|
+
* only exists once every environment is built — the font entries and the
|
|
8749
|
+
* per-route CSS and modulepreloads in the RSC plugin's assets manifest —
|
|
8750
|
+
* and then, when client JavaScript is disabled, removes every JavaScript
|
|
8751
|
+
* reference, from the manifest and from the assets manifests on disk. The
|
|
8752
|
+
* manifest's `js` / `modulepreload` are cleared after the merge has written
|
|
8753
|
+
* into them, so nothing the merge adds survives.
|
|
8754
|
+
*
|
|
8755
|
+
* Returns null only when no client bundle produced a manifest.
|
|
8756
|
+
*
|
|
8757
|
+
* @internal Exported for testing.
|
|
8758
|
+
*/
|
|
8759
|
+
async function finalizeBuildManifest(ctx, fonts, rsc, ssr) {
|
|
8760
|
+
const manifest = ctx.buildManifest;
|
|
8761
|
+
if (manifest) {
|
|
8762
|
+
fonts.contributeManifest(manifest);
|
|
8763
|
+
await mergeRscAssetsManifest(rsc.path, ctx.root, manifest, ctx.routeClientRefKeys);
|
|
8764
|
+
}
|
|
8765
|
+
if (ctx.clientJavascript.disabled) {
|
|
8766
|
+
if (manifest) {
|
|
8767
|
+
manifest.js = {};
|
|
8768
|
+
manifest.modulepreload = {};
|
|
8769
|
+
}
|
|
8770
|
+
await stripJsFromRscAssetsManifests([rsc.path, ssr.path]);
|
|
8771
|
+
}
|
|
8772
|
+
return manifest;
|
|
8773
|
+
}
|
|
8774
|
+
/**
|
|
8775
|
+
* The build manifest as a JS module that sets the global. Adapters write
|
|
8776
|
+
* it as `_timber-manifest-init.js` (or prepend it to the entry) and
|
|
8777
|
+
* evaluate it before the RSC handler, so `virtual:timber-build-manifest`
|
|
8778
|
+
* finds it.
|
|
8779
|
+
*/
|
|
8780
|
+
function serializeManifestInit(manifest) {
|
|
8781
|
+
return `globalThis.__TIMBER_BUILD_MANIFEST__ = ${JSON.stringify(manifest)};\n`;
|
|
8782
|
+
}
|
|
8783
|
+
/**
|
|
8784
|
+
* Dedupe the producers' directories and drop any that sits inside another.
|
|
8785
|
+
*
|
|
8786
|
+
* Two producers can name overlapping directories — a custom `assetsDir` of
|
|
8787
|
+
* `_timber` beside the fonts' `_timber/fonts`. Cloudflare and Netlify apply
|
|
8788
|
+
* every matching `_headers` rule, so emitting both would send two
|
|
8789
|
+
* `Cache-Control` values for one file; the outer directory already covers
|
|
8790
|
+
* the inner one.
|
|
8791
|
+
*/
|
|
8792
|
+
function canonicalImmutableDirs(dirs) {
|
|
8793
|
+
const unique = [...new Set(dirs)];
|
|
8794
|
+
return unique.filter((dir) => !unique.some((other) => other !== dir && dir.startsWith(`${other}/`)));
|
|
8795
|
+
}
|
|
8796
|
+
/**
|
|
8797
|
+
* Assemble the adapter's view of the build from what each step returned.
|
|
8798
|
+
*
|
|
8799
|
+
* Not a validator: every field is copied from the phase that produced it.
|
|
8800
|
+
* The throws are the states the union cannot represent — a Vite environment
|
|
8801
|
+
* that wrote no bundle, a static build with no site. Each means an earlier
|
|
8802
|
+
* phase failed without failing the build, and a deploy missing its SSR
|
|
8803
|
+
* bundle fails on the first request rather than here.
|
|
8804
|
+
*
|
|
8805
|
+
* @internal Exported for testing.
|
|
8806
|
+
*/
|
|
8807
|
+
function assembleBuildArtifacts(input) {
|
|
8808
|
+
const { output, outputDir, environments } = input;
|
|
8809
|
+
const client = requireEnvironment(environments, "client");
|
|
8810
|
+
const immutableDirs = canonicalImmutableDirs(input.immutableDirs);
|
|
8811
|
+
if (output === "static") {
|
|
8812
|
+
if (!input.site) throw new Error("[timber] Build output: output is 'static' but static generation recorded no site");
|
|
8813
|
+
const { pages, contentTypes } = input.site;
|
|
8814
|
+
return {
|
|
8815
|
+
output,
|
|
8816
|
+
outputDir,
|
|
8817
|
+
client,
|
|
8818
|
+
immutableDirs,
|
|
8819
|
+
pages,
|
|
8820
|
+
contentTypes
|
|
8821
|
+
};
|
|
8822
|
+
}
|
|
8823
|
+
return {
|
|
8824
|
+
output,
|
|
8825
|
+
outputDir,
|
|
8826
|
+
client,
|
|
8827
|
+
immutableDirs,
|
|
8828
|
+
rsc: requireEnvironment(environments, "rsc"),
|
|
8829
|
+
ssr: requireEnvironment(environments, "ssr"),
|
|
8830
|
+
prebuilt: input.prebuilt,
|
|
8831
|
+
manifestInit: input.manifestInit
|
|
8832
|
+
};
|
|
8833
|
+
}
|
|
8834
|
+
//#endregion
|
|
8671
8835
|
//#region src/plugins/build-report.ts
|
|
8672
8836
|
/**
|
|
8673
8837
|
* timber-build-report — Post-build route summary table.
|
|
@@ -8771,13 +8935,10 @@ function pad(str, width, align = "right") {
|
|
|
8771
8935
|
function stripAnsi(str) {
|
|
8772
8936
|
return str.replace(/\u001b\[\d+m/g, "");
|
|
8773
8937
|
}
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
} catch {
|
|
8779
|
-
return null;
|
|
8780
|
-
}
|
|
8938
|
+
/** Read the manifest of the prebuilt artifact this build recorded, if any. */
|
|
8939
|
+
function loadPrebuiltManifest(prebuiltDir) {
|
|
8940
|
+
if (!prebuiltDir) return null;
|
|
8941
|
+
return JSON.parse(readFileSync(join(prebuiltDir, "manifest.json"), "utf-8"));
|
|
8781
8942
|
}
|
|
8782
8943
|
function buildPrebuiltReportData(manifest, summary) {
|
|
8783
8944
|
const hasCaptures = summary && (summary.captured > 0 || summary.skipped.length > 0);
|
|
@@ -8981,11 +9142,47 @@ function timberBuildReport(ctx) {
|
|
|
8981
9142
|
let logger = null;
|
|
8982
9143
|
let chunkSizes = null;
|
|
8983
9144
|
let clientBundle = null;
|
|
8984
|
-
let reported = false;
|
|
8985
|
-
let deferReport = false;
|
|
8986
9145
|
const buildStart = performance.now();
|
|
9146
|
+
function printRouteTable() {
|
|
9147
|
+
if (!ctx.routeTree || !chunkSizes || !clientBundle || !logger) return;
|
|
9148
|
+
const outputMode = ctx.config.output ?? "server";
|
|
9149
|
+
const { entries, sharedGzip } = ctx.clientJavascript.disabled ? {
|
|
9150
|
+
entries: collectRoutes(ctx.routeTree).map((info) => ({
|
|
9151
|
+
path: info.path,
|
|
9152
|
+
type: classifyRoute(info.segments, outputMode),
|
|
9153
|
+
size: 0,
|
|
9154
|
+
firstLoadSize: 0
|
|
9155
|
+
})),
|
|
9156
|
+
sharedGzip: 0
|
|
9157
|
+
} : buildEntries(ctx.routeTree, chunkSizes, clientBundle, outputMode, ctx.appDir, ctx.root);
|
|
9158
|
+
const elapsed = ((performance.now() - buildStart) / 1e3).toFixed(2);
|
|
9159
|
+
const lines = buildRouteReport(entries, sharedGzip);
|
|
9160
|
+
logger.info("");
|
|
9161
|
+
for (const line of lines) logger.info(line);
|
|
9162
|
+
const warnings = buildWarnings(entries, ctx.config.budget);
|
|
9163
|
+
if (warnings.length > 0) {
|
|
9164
|
+
logger.info("");
|
|
9165
|
+
for (const w of warnings) logger.warn(w);
|
|
9166
|
+
}
|
|
9167
|
+
logger.info("");
|
|
9168
|
+
logger.info(`✓ built ${entries.length} routes for all three environments (rsc, ssr, client) in ${elapsed}s`);
|
|
9169
|
+
logger.info("");
|
|
9170
|
+
}
|
|
9171
|
+
function printPrebuiltReport(prebuilt) {
|
|
9172
|
+
if (!logger || !prebuilt) return;
|
|
9173
|
+
const prebuiltData = buildPrebuiltReportData(loadPrebuiltManifest(prebuilt.artifact?.path), prebuilt.summary);
|
|
9174
|
+
if (!prebuiltData) return;
|
|
9175
|
+
logger.info("");
|
|
9176
|
+
for (const line of buildPrebuiltReport(prebuiltData)) logger.info(line);
|
|
9177
|
+
logger.info("");
|
|
9178
|
+
}
|
|
8987
9179
|
return {
|
|
8988
9180
|
name: "timber-build-report",
|
|
9181
|
+
api: { print(prebuilt) {
|
|
9182
|
+
if (ctx.dev) return;
|
|
9183
|
+
printRouteTable();
|
|
9184
|
+
printPrebuiltReport(prebuilt);
|
|
9185
|
+
} },
|
|
8989
9186
|
config(_cfg, { command }) {
|
|
8990
9187
|
if (command !== "build") return;
|
|
8991
9188
|
return { environments: {
|
|
@@ -9002,50 +9199,6 @@ function timberBuildReport(ctx) {
|
|
|
9002
9199
|
if (this.environment?.name && this.environment.name !== "client") return;
|
|
9003
9200
|
chunkSizes = collectChunkSizes(bundle);
|
|
9004
9201
|
clientBundle = { ...bundle };
|
|
9005
|
-
deferReport = true;
|
|
9006
|
-
},
|
|
9007
|
-
closeBundle() {
|
|
9008
|
-
if (ctx.dev || reported) return;
|
|
9009
|
-
if (deferReport) {
|
|
9010
|
-
deferReport = false;
|
|
9011
|
-
return;
|
|
9012
|
-
}
|
|
9013
|
-
if (!ctx.routeTree || !chunkSizes || !clientBundle || !logger) return;
|
|
9014
|
-
reported = true;
|
|
9015
|
-
const outputMode = ctx.config.output ?? "server";
|
|
9016
|
-
const { entries, sharedGzip } = ctx.clientJavascript.disabled ? {
|
|
9017
|
-
entries: collectRoutes(ctx.routeTree).map((info) => ({
|
|
9018
|
-
path: info.path,
|
|
9019
|
-
type: classifyRoute(info.segments, outputMode),
|
|
9020
|
-
size: 0,
|
|
9021
|
-
firstLoadSize: 0
|
|
9022
|
-
})),
|
|
9023
|
-
sharedGzip: 0
|
|
9024
|
-
} : buildEntries(ctx.routeTree, chunkSizes, clientBundle, outputMode, ctx.appDir, ctx.root);
|
|
9025
|
-
const elapsed = ((performance.now() - buildStart) / 1e3).toFixed(2);
|
|
9026
|
-
const lines = buildRouteReport(entries, sharedGzip);
|
|
9027
|
-
logger.info("");
|
|
9028
|
-
for (const line of lines) logger.info(line);
|
|
9029
|
-
const warnings = buildWarnings(entries, ctx.config.budget);
|
|
9030
|
-
if (warnings.length > 0) {
|
|
9031
|
-
logger.info("");
|
|
9032
|
-
for (const w of warnings) logger.warn(w);
|
|
9033
|
-
}
|
|
9034
|
-
logger.info("");
|
|
9035
|
-
logger.info(`✓ built ${entries.length} routes for all three environments (rsc, ssr, client) in ${elapsed}s`);
|
|
9036
|
-
logger.info("");
|
|
9037
|
-
},
|
|
9038
|
-
buildApp: {
|
|
9039
|
-
order: "post",
|
|
9040
|
-
async handler() {
|
|
9041
|
-
if (ctx.dev || !logger) return;
|
|
9042
|
-
const prebuiltData = buildPrebuiltReportData(loadPrebuiltManifest(ctx.buildDir), ctx.captureSummary);
|
|
9043
|
-
if (!prebuiltData) return;
|
|
9044
|
-
logger.info("");
|
|
9045
|
-
const prebuiltLines = buildPrebuiltReport(prebuiltData);
|
|
9046
|
-
for (const line of prebuiltLines) logger.info(line);
|
|
9047
|
-
logger.info("");
|
|
9048
|
-
}
|
|
9049
9202
|
}
|
|
9050
9203
|
};
|
|
9051
9204
|
}
|
|
@@ -9387,10 +9540,8 @@ function timber(config) {
|
|
|
9387
9540
|
}
|
|
9388
9541
|
ctx.config.output ??= "server";
|
|
9389
9542
|
ctx.timer.end("config-load");
|
|
9390
|
-
const viteOutDir = userConfig.build?.outDir;
|
|
9391
|
-
const timberBuildDir = ctx.config.buildDir;
|
|
9392
9543
|
const resolvedRoot = resolve(userConfig.root ?? process.cwd());
|
|
9393
|
-
|
|
9544
|
+
const buildDir = resolveBuildDir(resolvedRoot, ctx.config.buildDir, userConfig.build?.outDir);
|
|
9394
9545
|
if (viteRoot !== process.cwd()) {
|
|
9395
9546
|
const hasCompilerInReloaded = !config?.reactCompiler && ctx.config.reactCompiler;
|
|
9396
9547
|
const hadCompilerInEarly = !config?.reactCompiler && earlyFileConfig?.reactCompiler;
|
|
@@ -9421,7 +9572,7 @@ function timber(config) {
|
|
|
9421
9572
|
resolvedDevPort = start.port;
|
|
9422
9573
|
resolvedDevPortExplicit = start.explicit;
|
|
9423
9574
|
}
|
|
9424
|
-
const buildOutDir = relative(resolvedRoot,
|
|
9575
|
+
const buildOutDir = relative(resolvedRoot, buildDir);
|
|
9425
9576
|
const envOutDirs = {};
|
|
9426
9577
|
for (const envName of [
|
|
9427
9578
|
"rsc",
|
|
@@ -9485,6 +9636,9 @@ function timber(config) {
|
|
|
9485
9636
|
};
|
|
9486
9637
|
const effectiveReactCompiler = config?.reactCompiler ?? earlyFileConfig?.reactCompiler ?? true;
|
|
9487
9638
|
// @vitejs/plugin-rsc handles:
|
|
9639
|
+
const fonts = timberFonts(ctx);
|
|
9640
|
+
const prebuilt = timberPrebuilt(ctx);
|
|
9641
|
+
const buildReport = timberBuildReport(ctx);
|
|
9488
9642
|
return [
|
|
9489
9643
|
rootSync,
|
|
9490
9644
|
timberReactResolve(),
|
|
@@ -9495,19 +9649,23 @@ function timber(config) {
|
|
|
9495
9649
|
timberRouting(ctx),
|
|
9496
9650
|
timberEntries(ctx),
|
|
9497
9651
|
timberBuildManifest(ctx),
|
|
9498
|
-
|
|
9652
|
+
fonts,
|
|
9499
9653
|
timberMdx(ctx),
|
|
9500
9654
|
timberRequestDep(ctx),
|
|
9501
9655
|
timberCacheTransform(ctx),
|
|
9502
9656
|
timberPrerenderSugar(ctx),
|
|
9503
|
-
|
|
9657
|
+
prebuilt,
|
|
9504
9658
|
timberStaticBuild(ctx),
|
|
9505
9659
|
timberContent(ctx),
|
|
9506
9660
|
timberServerBundle(),
|
|
9507
9661
|
timberCloudflareWasm(ctx),
|
|
9508
9662
|
timberChunks(ctx),
|
|
9509
|
-
|
|
9510
|
-
|
|
9663
|
+
buildReport,
|
|
9664
|
+
timberPostBuild(ctx, {
|
|
9665
|
+
fonts: fonts.api,
|
|
9666
|
+
prebuilt: prebuilt.api,
|
|
9667
|
+
report: buildReport.api
|
|
9668
|
+
}),
|
|
9511
9669
|
timberDevLogs(ctx),
|
|
9512
9670
|
timberDevServer(ctx)
|
|
9513
9671
|
];
|