@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as withBasePath } from "./base-path-DaQrzbez.js";
|
|
2
|
-
import { c as USER_PLATFORM_DIR, i as HEADERS_FILE, n as detectFsIdentity, r as fsKey, s as USER_MERGED_PLATFORM_FILES } from "./fs-identity-
|
|
2
|
+
import { c as USER_PLATFORM_DIR, i as HEADERS_FILE, n as detectFsIdentity, r as fsKey, s as USER_MERGED_PLATFORM_FILES } from "./fs-identity-BRKuL215.js";
|
|
3
3
|
import { basename, join, relative } from "node:path";
|
|
4
4
|
import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
5
5
|
//#region src/adapters/shared.ts
|
|
@@ -10,7 +10,7 @@ import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
|
10
10
|
* by callers that predate it (a hand-written adapter, a test harness). Falling
|
|
11
11
|
* back to `'/'` reproduces the pre-TIM-1274 output exactly, which is correct
|
|
12
12
|
* for the only deployments those callers can have: a build under a non-root
|
|
13
|
-
* base always goes through `plugins/
|
|
13
|
+
* base always goes through `plugins/post-build.ts`, which populates it.
|
|
14
14
|
*
|
|
15
15
|
* Typed structurally rather than as `TimberConfig` so this module keeps no
|
|
16
16
|
* import of `./types.js` at runtime.
|
|
@@ -29,7 +29,9 @@ var STATIC_CACHE = "public, max-age=3600, must-revalidate";
|
|
|
29
29
|
* Static Assets, Cloudflare Pages, and Netlify. It maps URL patterns to
|
|
30
30
|
* HTTP response headers.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
32
|
+
* The build's content-hashed directories (`immutableDirs`, recorded on
|
|
33
|
+
* `BuildArtifacts` by the phases that hashed them) get one wildcard rule
|
|
34
|
+
* each. When
|
|
33
35
|
* `unhashedPaths` is provided, per-file rules are appended for unhashed
|
|
34
36
|
* static assets (favicon.ico, robots.txt, etc.) so they get Cache-Control
|
|
35
37
|
* on platforms like Cloudflare Workers Static Assets where the server
|
|
@@ -48,11 +50,11 @@ var STATIC_CACHE = "public, max-age=3600, must-revalidate";
|
|
|
48
50
|
* Cloudflare Workers Static Assets without one.
|
|
49
51
|
*
|
|
50
52
|
* The prefix is applied at exactly one point, `rulePath()`, which every rule
|
|
51
|
-
* in this function goes through. Prefixing the
|
|
53
|
+
* in this function goes through. Prefixing the wildcards and
|
|
52
54
|
* hand-checking that the per-file rules agree is how the next rule gets
|
|
53
55
|
* missed.
|
|
54
56
|
*/
|
|
55
|
-
var
|
|
57
|
+
var MAX_RULES = 100;
|
|
56
58
|
/**
|
|
57
59
|
* Count the rules in a `_headers` file — a rule is a path line, which is any
|
|
58
60
|
* line that is neither blank, a comment, nor an indented header.
|
|
@@ -105,7 +107,7 @@ function patternsOverlap(a, b) {
|
|
|
105
107
|
if (pb !== null && (a.startsWith(pb) || pb === "")) return true;
|
|
106
108
|
return false;
|
|
107
109
|
}
|
|
108
|
-
function generateHeadersFile({ base, unhashedPaths, contentTypes, userRules }) {
|
|
110
|
+
function generateHeadersFile({ base, immutableDirs, unhashedPaths, contentTypes, userRules }) {
|
|
109
111
|
/** Route-space rule path → deployed-URL rule path. */
|
|
110
112
|
const rulePath = (path) => withBasePath(base, path);
|
|
111
113
|
const userRuleList = userRules ? parseHeaderRules(userRules) : [];
|
|
@@ -130,15 +132,12 @@ function generateHeadersFile({ base, unhashedPaths, contentTypes, userRules }) {
|
|
|
130
132
|
let content = `# Auto-generated by @timber-js/app — static asset cache headers.
|
|
131
133
|
# See design/25-production-deployments.md §"CDN / Edge Cache"
|
|
132
134
|
`;
|
|
133
|
-
for (const
|
|
134
|
-
|
|
135
|
-
"/_timber/fonts/*",
|
|
136
|
-
"/_rsc/*"
|
|
137
|
-
]) content += emit(rulePath(path), "Cache-Control", IMMUTABLE_CACHE);
|
|
135
|
+
for (const dir of immutableDirs) content += emit(rulePath(`/${dir}/*`), "Cache-Control", IMMUTABLE_CACHE);
|
|
136
|
+
const maxPerFileRules = MAX_RULES - immutableDirs.length;
|
|
138
137
|
const allCtEntries = contentTypes ? Object.entries(contentTypes).sort(([a], [b]) => a.localeCompare(b)) : [];
|
|
139
|
-
const ctEntries = allCtEntries.slice(0,
|
|
140
|
-
if (allCtEntries.length >
|
|
141
|
-
const remainingBudget =
|
|
138
|
+
const ctEntries = allCtEntries.slice(0, maxPerFileRules);
|
|
139
|
+
if (allCtEntries.length > maxPerFileRules) console.warn(`[timber] _headers: ${allCtEntries.length} content-type rules exceed Cloudflare's 100-rule limit. Only the first ${maxPerFileRules} extensionless API routes will get Content-Type headers.`);
|
|
140
|
+
const remainingBudget = maxPerFileRules - ctEntries.length;
|
|
142
141
|
if (unhashedPaths && unhashedPaths.length > 0) {
|
|
143
142
|
const capped = unhashedPaths.slice(0, Math.max(0, remainingBudget));
|
|
144
143
|
if (unhashedPaths.length > remainingBudget) console.warn(`[timber] _headers: ${unhashedPaths.length} unhashed static files + ${ctEntries.length} content-type rules found, but Cloudflare limits _headers to 100 rules. Only the first ${capped.length} unhashed files will get Cache-Control headers.`);
|
|
@@ -150,7 +149,7 @@ function generateHeadersFile({ base, unhashedPaths, contentTypes, userRules }) {
|
|
|
150
149
|
if (userRules && userRules.trim() !== "") {
|
|
151
150
|
content += `\n# User-authored rules from public/_headers\n\n${userRules.trim()}\n`;
|
|
152
151
|
const total = countHeaderRules(content);
|
|
153
|
-
if (total >
|
|
152
|
+
if (total > MAX_RULES) console.warn(`[timber] _headers: ${total} rules after merging public/_headers, over Cloudflare's ${MAX_RULES}-rule limit. Rules past the limit are dropped by the platform — remove some, or move static assets under a directory the wildcard rules already cover.`);
|
|
154
153
|
}
|
|
155
154
|
return content;
|
|
156
155
|
}
|
|
@@ -168,11 +167,11 @@ function generateHeadersFile({ base, unhashedPaths, contentTypes, userRules }) {
|
|
|
168
167
|
* Returns the resolved public directory path for further adapter-specific use.
|
|
169
168
|
*/
|
|
170
169
|
async function runSharedBuildSteps(opts) {
|
|
171
|
-
const { config,
|
|
170
|
+
const { config, artifacts, outDir, publicDirName } = opts;
|
|
172
171
|
await mkdir(outDir, { recursive: true });
|
|
173
|
-
const clientDir = join(buildDir, "client");
|
|
174
172
|
const publicDir = join(outDir, publicDirName);
|
|
175
173
|
await mkdir(publicDir, { recursive: true });
|
|
174
|
+
const clientDir = artifacts.client.path;
|
|
176
175
|
const referencedWasm = await findReferencedWasm(clientDir);
|
|
177
176
|
await cp(clientDir, publicDir, {
|
|
178
177
|
recursive: true,
|
|
@@ -181,18 +180,12 @@ async function runSharedBuildSteps(opts) {
|
|
|
181
180
|
if (config.clientJavascriptDisabled && src.endsWith(".js")) return false;
|
|
182
181
|
return true;
|
|
183
182
|
}
|
|
184
|
-
}).catch((e) => {
|
|
185
|
-
if (e.code !== "ENOENT") throw e;
|
|
186
183
|
});
|
|
187
|
-
await writeHeadersFile(publicDir, config,
|
|
188
|
-
await cp(
|
|
189
|
-
await cp(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
await cp(join(buildDir, "prebuilt"), join(outDir, "prebuilt"), { recursive: true }).catch((e) => {
|
|
193
|
-
if (e.code !== "ENOENT") throw e;
|
|
194
|
-
});
|
|
195
|
-
if (config.manifestInit) await writeFile(join(outDir, "_timber-manifest-init.js"), config.manifestInit);
|
|
184
|
+
await writeHeadersFile(publicDir, config, artifacts);
|
|
185
|
+
await cp(artifacts.rsc.path, join(outDir, "rsc"), { recursive: true });
|
|
186
|
+
await cp(artifacts.ssr.path, join(outDir, "ssr"), { recursive: true });
|
|
187
|
+
if (artifacts.prebuilt) await cp(artifacts.prebuilt.path, join(outDir, "prebuilt"), { recursive: true });
|
|
188
|
+
if (artifacts.manifestInit) await writeFile(join(outDir, "_timber-manifest-init.js"), artifacts.manifestInit);
|
|
196
189
|
return publicDir;
|
|
197
190
|
}
|
|
198
191
|
/**
|
|
@@ -200,9 +193,16 @@ async function runSharedBuildSteps(opts) {
|
|
|
200
193
|
* Cache-Control rules in the `_headers` file.
|
|
201
194
|
*
|
|
202
195
|
* Excludes:
|
|
203
|
-
* - Files under
|
|
196
|
+
* - Files under the build's `immutableDirs` (covered by wildcard rules)
|
|
197
|
+
* - Files under `rsc/` and `ssr/` (server bundles, never served)
|
|
204
198
|
* - Underscore-prefixed files (`_headers`, `_worker.js`, etc.)
|
|
205
199
|
*
|
|
200
|
+
* Ordered for the rule cap: well-known metadata files, then everything
|
|
201
|
+
* else, then files under an underscore-prefixed directory — the
|
|
202
|
+
* framework's own output (unhashed RSC payloads in a static build with
|
|
203
|
+
* client JavaScript disabled, which nothing fetches). Those can number one
|
|
204
|
+
* per route, and must not take the budget from the app's real files.
|
|
205
|
+
*
|
|
206
206
|
* @internal Exported for testing.
|
|
207
207
|
*/
|
|
208
208
|
var PRIORITY_FILES = /* @__PURE__ */ new Set([
|
|
@@ -213,7 +213,7 @@ var PRIORITY_FILES = /* @__PURE__ */ new Set([
|
|
|
213
213
|
"/manifest.webmanifest",
|
|
214
214
|
"/apple-touch-icon.png"
|
|
215
215
|
]);
|
|
216
|
-
async function findUnhashedStaticFiles(publicDir) {
|
|
216
|
+
async function findUnhashedStaticFiles(publicDir, immutableDirs) {
|
|
217
217
|
let files;
|
|
218
218
|
try {
|
|
219
219
|
files = await collectFiles(publicDir);
|
|
@@ -222,16 +222,22 @@ async function findUnhashedStaticFiles(publicDir) {
|
|
|
222
222
|
}
|
|
223
223
|
const priority = [];
|
|
224
224
|
const rest = [];
|
|
225
|
+
const framework = [];
|
|
225
226
|
for (const file of files) {
|
|
226
227
|
const rel = relative(publicDir, file).replace(/\\/g, "/");
|
|
227
|
-
if (
|
|
228
|
-
if (rel.startsWith("rsc/") || rel.startsWith("ssr/")
|
|
228
|
+
if (immutableDirs.some((dir) => rel.startsWith(`${dir}/`))) continue;
|
|
229
|
+
if (rel.startsWith("rsc/") || rel.startsWith("ssr/")) continue;
|
|
229
230
|
if (basename(rel).startsWith("_")) continue;
|
|
230
231
|
const urlPath = "/" + rel;
|
|
231
232
|
if (PRIORITY_FILES.has(urlPath)) priority.push(urlPath);
|
|
233
|
+
else if (rel.startsWith("_")) framework.push(urlPath);
|
|
232
234
|
else rest.push(urlPath);
|
|
233
235
|
}
|
|
234
|
-
return [
|
|
236
|
+
return [
|
|
237
|
+
...priority.sort(),
|
|
238
|
+
...rest.sort(),
|
|
239
|
+
...framework.sort()
|
|
240
|
+
];
|
|
235
241
|
}
|
|
236
242
|
/**
|
|
237
243
|
* Scan client JS files for references to .wasm filenames.
|
|
@@ -240,12 +246,7 @@ async function findUnhashedStaticFiles(publicDir) {
|
|
|
240
246
|
*/
|
|
241
247
|
async function findReferencedWasm(clientDir) {
|
|
242
248
|
const referenced = /* @__PURE__ */ new Set();
|
|
243
|
-
|
|
244
|
-
try {
|
|
245
|
-
files = await collectFiles(clientDir);
|
|
246
|
-
} catch {
|
|
247
|
-
return referenced;
|
|
248
|
-
}
|
|
249
|
+
const files = await collectFiles(clientDir);
|
|
249
250
|
const jsFiles = files.filter((f) => f.endsWith(".js"));
|
|
250
251
|
const wasmFiles = files.filter((f) => f.endsWith(".wasm")).map((f) => basename(f));
|
|
251
252
|
if (wasmFiles.length === 0) return referenced;
|
|
@@ -260,7 +261,7 @@ async function findReferencedWasm(clientDir) {
|
|
|
260
261
|
* assets and pre-rendered HTML/RSC/API files into `outDir/publicDirName`.
|
|
261
262
|
* Used by both Cloudflare and Nitro adapters in `output: 'static'` mode.
|
|
262
263
|
*/
|
|
263
|
-
async function buildStaticDirectoryOutput(config,
|
|
264
|
+
async function buildStaticDirectoryOutput(config, artifacts, outDir, publicDirName) {
|
|
264
265
|
await rm(outDir, {
|
|
265
266
|
recursive: true,
|
|
266
267
|
force: true
|
|
@@ -268,20 +269,15 @@ async function buildStaticDirectoryOutput(config, buildDir, outDir, publicDirNam
|
|
|
268
269
|
await mkdir(outDir, { recursive: true });
|
|
269
270
|
const publicDir = join(outDir, publicDirName);
|
|
270
271
|
await mkdir(publicDir, { recursive: true });
|
|
271
|
-
|
|
272
|
-
await cp(clientDir, publicDir, {
|
|
272
|
+
await cp(artifacts.client.path, publicDir, {
|
|
273
273
|
recursive: true,
|
|
274
274
|
filter: (src) => {
|
|
275
275
|
if (config.clientJavascriptDisabled && src.endsWith(".js")) return false;
|
|
276
276
|
return true;
|
|
277
277
|
}
|
|
278
|
-
}).catch((e) => {
|
|
279
|
-
if (e.code !== "ENOENT") throw e;
|
|
280
278
|
});
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
await cp(config.staticPagesDir, publicDir, { recursive: true });
|
|
284
|
-
}
|
|
279
|
+
await assertNoTreeCollision(artifacts.pages.path, publicDir);
|
|
280
|
+
await cp(artifacts.pages.path, publicDir, { recursive: true });
|
|
285
281
|
}
|
|
286
282
|
/**
|
|
287
283
|
* Write the `_headers` file, folding in the user's `public/_headers`.
|
|
@@ -308,12 +304,13 @@ async function buildStaticDirectoryOutput(config, buildDir, outDir, publicDirNam
|
|
|
308
304
|
*
|
|
309
305
|
* @internal Exported for testing.
|
|
310
306
|
*/
|
|
311
|
-
async function writeHeadersFile(dir, config,
|
|
307
|
+
async function writeHeadersFile(dir, config, artifacts) {
|
|
312
308
|
const userRules = await readUserPlatformFile(config.root, HEADERS_FILE);
|
|
313
309
|
await writeFile(join(dir, HEADERS_FILE), generateHeadersFile({
|
|
314
310
|
base: adapterBase(config),
|
|
315
|
-
|
|
316
|
-
|
|
311
|
+
immutableDirs: artifacts.immutableDirs,
|
|
312
|
+
unhashedPaths: await findUnhashedStaticFiles(dir, artifacts.immutableDirs),
|
|
313
|
+
contentTypes: artifacts.output === "static" ? artifacts.contentTypes : void 0,
|
|
317
314
|
userRules: userRules ?? void 0
|
|
318
315
|
}));
|
|
319
316
|
}
|
|
@@ -365,6 +362,6 @@ async function collectFiles(dir) {
|
|
|
365
362
|
return result;
|
|
366
363
|
}
|
|
367
364
|
//#endregion
|
|
368
|
-
export {
|
|
365
|
+
export { STATIC_CACHE as a, IMMUTABLE_CACHE as i, runSharedBuildSteps as n, adapterBase as o, writeHeadersFile as r, buildStaticDirectoryOutput as t };
|
|
369
366
|
|
|
370
|
-
//# sourceMappingURL=build-output-helper-
|
|
367
|
+
//# sourceMappingURL=build-output-helper-RV_BRcF1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-output-helper-RV_BRcF1.js","names":[],"sources":["../../src/adapters/shared.ts","../../src/adapters/build-output-helper.ts"],"sourcesContent":["// Shared adapter utilities — leaf module with zero deps on server/, client/,\n// or any Vite-dependent code.\n//\n// Adapters are loaded by Node at Vite startup time, before Vite's module\n// resolver is available. This module uses only Node built-ins and can be\n// imported by both adapters via a relative path.\n//\n// IMPORTANT: Do NOT add imports from ../server/, ../client/, ../plugins/,\n// or any module that transitively depends on Vite. A test in\n// tests/adapters/shared-no-forbidden-imports.test.ts enforces this.\n// ../shared/ is exempt: it is dependency-free by the same rule.\n\nimport { withBasePath } from '../shared/base-path.ts';\n\n/**\n * The deployment base an adapter should write platform rules against.\n *\n * `config.base` is optional on `TimberConfig` because adapters can be invoked\n * by callers that predate it (a hand-written adapter, a test harness). Falling\n * back to `'/'` reproduces the pre-TIM-1274 output exactly, which is correct\n * for the only deployments those callers can have: a build under a non-root\n * base always goes through `plugins/post-build.ts`, which populates it.\n *\n * Typed structurally rather than as `TimberConfig` so this module keeps no\n * import of `./types.js` at runtime.\n */\nexport function adapterBase(config: { base?: string }): string {\n return config.base ?? '/';\n}\n\n// ─── Static asset cache headers ──────────────────────────────────────────\n\n/** Cache-Control value for hashed (immutable) assets. */\nexport const IMMUTABLE_CACHE = 'public, max-age=31536000, immutable';\n\n/** Cache-Control value for unhashed static assets. */\nexport const STATIC_CACHE = 'public, max-age=3600, must-revalidate';\n\n/**\n * Generate a `_headers` file for static asset cache control.\n *\n * The `_headers` file is a platform convention supported by Cloudflare Workers\n * Static Assets, Cloudflare Pages, and Netlify. It maps URL patterns to\n * HTTP response headers.\n *\n * The build's content-hashed directories (`immutableDirs`, recorded on\n * `BuildArtifacts` by the phases that hashed them) get one wildcard rule\n * each. When\n * `unhashedPaths` is provided, per-file rules are appended for unhashed\n * static assets (favicon.ico, robots.txt, etc.) so they get Cache-Control\n * on platforms like Cloudflare Workers Static Assets where the server\n * handler never sees static file requests.\n *\n * A `/*` catch-all is NOT used — it would be additive on Cloudflare,\n * producing duplicate Cache-Control directives on hashed assets\n * (invalid per RFC 9111).\n *\n * **Every rule path is written in deployed-URL space** (TIM-1274). The\n * platform matches these patterns against the request path, which under a\n * non-root `base` sits below the prefix: with `base: '/repo/'` the assets are\n * at `/repo/assets/*`, so a rule saying `/assets/*` matches nothing. Silent\n * for the cache rules (slower, still correct) and not silent for the\n * Content-Type rules — an extensionless API route output is unreadable on\n * Cloudflare Workers Static Assets without one.\n *\n * The prefix is applied at exactly one point, `rulePath()`, which every rule\n * in this function goes through. Prefixing the wildcards and\n * hand-checking that the per-file rules agree is how the next rule gets\n * missed.\n */\n// Cloudflare Workers Static Assets caps _headers at 100 rules. The wildcard\n// rules for the immutable directories come out of the same budget.\nconst MAX_RULES = 100;\n\nexport interface HeadersFileOptions {\n /**\n * The deployment base, already normalized by `normalizeBasePath()` —\n * leading and trailing slash, `'/'` at the domain root.\n *\n * Required rather than defaulted: a caller that forgets it would emit\n * root-relative rules that match nothing, which is the bug this closes.\n */\n base: string;\n /**\n * Content-hashed directories, from `BuildArtifacts.immutableDirs`. Each\n * gets an immutable `Cache-Control` wildcard rule.\n */\n immutableDirs: readonly string[];\n /** Unhashed static files (route-space paths) needing per-file cache rules. */\n unhashedPaths?: string[];\n /** Route-space path → Content-Type, for extensionless API route outputs. */\n contentTypes?: Record<string, string>;\n /**\n * Verbatim contents of the user's `public/_headers`, appended after the\n * generated rules. See `mergeUserHeaders` for why it goes last.\n */\n userRules?: string;\n}\n\n/**\n * Count the rules in a `_headers` file — a rule is a path line, which is any\n * line that is neither blank, a comment, nor an indented header.\n *\n * @internal Exported for testing.\n */\nexport function countHeaderRules(content: string): number {\n return content\n .split('\\n')\n .filter((line) => line.trim() !== '' && !line.startsWith('#') && !/^\\s/.test(line)).length;\n}\n\n/** One `_headers` block: a path pattern and the headers it sets. */\nexport interface HeaderRule {\n pattern: string;\n headers: Array<{ name: string; value: string }>;\n}\n\n/**\n * Parse a `_headers` file. A non-indented, non-comment line opens a rule; the\n * indented `Name: value` lines beneath it belong to that rule.\n *\n * @internal Exported for testing.\n */\nexport function parseHeaderRules(content: string): HeaderRule[] {\n const rules: HeaderRule[] = [];\n for (const raw of content.split('\\n')) {\n const line = raw.replace(/\\r$/, '');\n if (line.trim() === '' || line.trimStart().startsWith('#')) continue;\n if (/^\\s/.test(line)) {\n const current = rules[rules.length - 1];\n if (!current) continue; // header with no rule above it — not ours to fix\n const colon = line.indexOf(':');\n if (colon === -1) continue;\n current.headers.push({\n name: line.slice(0, colon).trim(),\n value: line.slice(colon + 1).trim(),\n });\n } else {\n rules.push({ pattern: line.trim(), headers: [] });\n }\n }\n return rules;\n}\n\n/**\n * Whether a user pattern can match paths a generated pattern also matches.\n *\n * Deliberately narrow: equality, or a prefix-glob (`/x/*`, `/*`) whose literal\n * prefix contains the other's. Anything cleverer risks claiming an overlap\n * that is not there, and the only thing this drives is a warning — a false\n * positive is noise a developer cannot act on.\n */\nfunction patternsOverlap(a: string, b: string): boolean {\n if (a === b) return true;\n const prefixOf = (p: string) => (p.endsWith('*') ? p.slice(0, -1) : null);\n const [pa, pb] = [prefixOf(a), prefixOf(b)];\n if (pa !== null && (b.startsWith(pa) || pa === '')) return true;\n if (pb !== null && (a.startsWith(pb) || pb === '')) return true;\n return false;\n}\n\nexport function generateHeadersFile({\n base,\n immutableDirs,\n unhashedPaths,\n contentTypes,\n userRules,\n}: HeadersFileOptions): string {\n /** Route-space rule path → deployed-URL rule path. */\n const rulePath = (path: string) => withBasePath(base, path);\n\n // Cloudflare and Netlify apply *every* matching rule, so emitting a header\n // the user also sets on the same path yields two definitions of it — a\n // comma-joined `Cache-Control` that is invalid per RFC 9111, and neither\n // side's intent. This module already refuses to emit a `/*` catch-all for\n // that reason; appending the user's file verbatim reintroduced it through\n // the back door (TIM-1326).\n //\n // An explicit app rule beats a framework default, so where the user names\n // the same pattern and the same header, ours is dropped. Only exact pattern\n // matches are resolved this way: silently dropping asset immutability\n // because a `/*` rule *might* subsume it would be a worse surprise than the\n // duplicate, so overlapping-but-different patterns warn instead.\n const userRuleList = userRules ? parseHeaderRules(userRules) : [];\n const overriddenExactly = new Set(\n userRuleList.flatMap((rule) =>\n rule.headers.map((h) => `${rule.pattern}\\0${h.name.toLowerCase()}`)\n )\n );\n const overridden = (pattern: string, header: string) =>\n overriddenExactly.has(`${pattern}\\0${header.toLowerCase()}`);\n\n const warnedOverlaps = new Set<string>();\n const emit = (pattern: string, header: string, value: string): string => {\n if (overridden(pattern, header)) return '';\n for (const rule of userRuleList) {\n if (rule.pattern === pattern) continue;\n if (!patternsOverlap(rule.pattern, pattern)) continue;\n for (const h of rule.headers) {\n if (h.name.toLowerCase() !== header.toLowerCase()) continue;\n const key = `${rule.pattern}\\0${pattern}\\0${header.toLowerCase()}`;\n if (warnedOverlaps.has(key)) continue;\n warnedOverlaps.add(key);\n console.warn(\n `[timber] _headers: your rule \"${rule.pattern}\" sets ${header}, which ` +\n `timber also sets on \"${pattern}\". Cloudflare and Netlify apply both, ` +\n `so the response gets two ${header} values. Use the exact pattern ` +\n `\"${pattern}\" to replace timber's rule, or narrow yours so they do ` +\n `not overlap.`\n );\n }\n }\n return `\\n${pattern}\\n ${header}: ${value}\\n`;\n };\n\n let content = `# Auto-generated by @timber-js/app — static asset cache headers.\n# See design/25-production-deployments.md §\"CDN / Edge Cache\"\n`;\n for (const dir of immutableDirs) {\n content += emit(rulePath(`/${dir}/*`), 'Cache-Control', IMMUTABLE_CACHE);\n }\n const maxPerFileRules = MAX_RULES - immutableDirs.length;\n\n // Content-Type rules are higher priority than cache headers for\n // extensionless files — without them the file is unreadable.\n const allCtEntries = contentTypes\n ? Object.entries(contentTypes).sort(([a], [b]) => a.localeCompare(b))\n : [];\n const ctEntries = allCtEntries.slice(0, maxPerFileRules);\n if (allCtEntries.length > maxPerFileRules) {\n console.warn(\n `[timber] _headers: ${allCtEntries.length} content-type rules exceed ` +\n `Cloudflare's 100-rule limit. Only the first ${maxPerFileRules} ` +\n `extensionless API routes will get Content-Type headers.`\n );\n }\n const remainingBudget = maxPerFileRules - ctEntries.length;\n\n if (unhashedPaths && unhashedPaths.length > 0) {\n const capped = unhashedPaths.slice(0, Math.max(0, remainingBudget));\n if (unhashedPaths.length > remainingBudget) {\n console.warn(\n `[timber] _headers: ${unhashedPaths.length} unhashed static files + ` +\n `${ctEntries.length} content-type rules found, but Cloudflare limits ` +\n `_headers to 100 rules. Only the first ${capped.length} unhashed ` +\n `files will get Cache-Control headers.`\n );\n }\n // Section bodies are built before their comment header so a section the\n // user has overridden entirely does not leave a heading over nothing.\n const body = capped.map((p) => emit(rulePath(p), 'Cache-Control', STATIC_CACHE)).join('');\n if (body !== '') {\n content += `\\n# Unhashed static assets — short-lived cache with revalidation\\n${body}`;\n }\n }\n\n const ctBody = ctEntries\n .map(([urlPath, ct]) => emit(rulePath(urlPath), 'Content-Type', ct))\n .join('');\n if (ctBody !== '') {\n content += `\\n# Content-Type for extensionless API routes\\n${ctBody}`;\n }\n\n // User rules last, matching the `_redirects` merge. Their paths are left\n // verbatim: `_redirects` prefixes the rules it generates because it wrote\n // them in route space, but these are the user's own text, already authored\n // against the URLs the site is deployed at.\n if (userRules && userRules.trim() !== '') {\n content += `\\n# User-authored rules from public/_headers\\n\\n${userRules.trim()}\\n`;\n\n const total = countHeaderRules(content);\n if (total > MAX_RULES) {\n console.warn(\n `[timber] _headers: ${total} rules after merging public/_headers, over ` +\n `Cloudflare's ${MAX_RULES}-rule limit. Rules past the ` +\n `limit are dropped by the platform — remove some, or move static ` +\n `assets under a directory the wildcard rules already cover.`\n );\n }\n }\n\n return content;\n}\n","// Shared build-output helper for adapter buildOutput() methods.\n//\n// Steps 1–5 of every adapter's buildOutput are platform-agnostic:\n// 1. Copy client assets to the public/static directory\n// 2. Write _headers file for static asset cache control\n// 3. Copy RSC + SSR server bundles\n// 4. Write manifest-init module (if present)\n//\n// Only the final steps (entry codegen, platform config) vary per adapter.\n//\n// IMPORTANT: This module must remain a leaf — no imports from ../server/,\n// ../client/, or Vite-dependent code. See adapters/shared.ts header.\n\nimport { writeFile, mkdir, cp, rm, readdir, readFile } from 'node:fs/promises';\nimport { join, basename, relative } from 'node:path';\nimport { adapterBase, generateHeadersFile } from './shared.ts';\n// Isomorphic, zero-import module — safe to load from an adapter, which Node's\n// native ESM loader evaluates before Vite's resolver exists. Same precedent as\n// `adapters/shared.ts` importing `../shared/base-path.js`.\nimport {\n HEADERS_FILE,\n USER_MERGED_PLATFORM_FILES,\n USER_PLATFORM_DIR,\n} from '../shared/static-platform-files.ts';\nimport { detectFsIdentity, fsKey } from './fs-identity.ts';\nimport type {\n BuildArtifacts,\n ServerBuildArtifacts,\n StaticBuildArtifacts,\n TimberConfig,\n} from './types.ts';\n\n/** Options for the shared build output steps. */\nexport interface BuildOutputBaseOptions {\n /** Resolved timber config. */\n config: TimberConfig;\n /** What the build produced. */\n artifacts: ServerBuildArtifacts;\n /** Adapter-specific output directory (e.g. `.timber/dist/nitro`). */\n outDir: string;\n /**\n * Name of the public/static directory within outDir.\n * Nitro uses 'public', Cloudflare uses 'static'.\n */\n publicDirName: string;\n}\n\n/**\n * Run the platform-agnostic build output steps shared by all adapters:\n *\n * 1. Create the output directory\n * 2. Copy client assets to the public/static directory\n * 3. Write the `_headers` file for static asset cache control\n * 4. Copy RSC and SSR server bundles into the output directory\n * 5. Write the manifest-init module if present\n *\n * Returns the resolved public directory path for further adapter-specific use.\n */\nexport async function runSharedBuildSteps(opts: BuildOutputBaseOptions): Promise<string> {\n const { config, artifacts, outDir, publicDirName } = opts;\n\n // 1. Create the output directory.\n await mkdir(outDir, { recursive: true });\n\n // 2. Copy client assets to public/static directory.\n // When client JavaScript is disabled, skip .js files — only CSS,\n // fonts, images, and other static assets are needed.\n const publicDir = join(outDir, publicDirName);\n await mkdir(publicDir, { recursive: true });\n const clientDir = artifacts.client.path;\n // Find WASM files that are referenced by client JS (legitimate client WASM)\n // vs orphaned server-only WASM (e.g. @takumi-rs for OG image generation).\n // Only strip orphaned WASM to avoid breaking client-side WASM usage.\n const referencedWasm = await findReferencedWasm(clientDir);\n\n await cp(clientDir, publicDir, {\n recursive: true,\n filter: (src: string) => {\n if (src.endsWith('.wasm') && !referencedWasm.has(basename(src))) {\n return false;\n }\n if (config.clientJavascriptDisabled && src.endsWith('.js')) return false;\n return true;\n },\n });\n\n // 3. Write _headers file for static asset cache control.\n // Scan for unhashed files so they get per-file Cache-Control rules in the\n // _headers file. On platforms like Cloudflare Workers Static Assets, the\n // worker never sees static file requests — _headers is the only mechanism.\n await writeHeadersFile(publicDir, config, artifacts);\n\n // 4. Copy RSC + SSR server bundles into the output directory. The RSC\n // bundle imports the SSR one by a path the RSC plugin computed between the\n // two *build* directories, which the build names `rsc/` and `ssr/` as\n // siblings (index.ts); deploying them under the same names keeps it valid.\n await cp(artifacts.rsc.path, join(outDir, 'rsc'), { recursive: true });\n await cp(artifacts.ssr.path, join(outDir, 'ssr'), { recursive: true });\n\n // 4b. Copy prebuilt/ flight payloads (cache.component artifacts). These\n // are produced by the post-build capture pass (design/44) and read at\n // request time via the adapter's PrebuiltPayloadSource.\n if (artifacts.prebuilt) {\n await cp(artifacts.prebuilt.path, join(outDir, 'prebuilt'), { recursive: true });\n }\n\n // 5. Write manifest-init module if present.\n if (artifacts.manifestInit) {\n await writeFile(join(outDir, '_timber-manifest-init.js'), artifacts.manifestInit);\n }\n\n return publicDir;\n}\n\n/**\n * Find unhashed static files in the public directory that need per-file\n * Cache-Control rules in the `_headers` file.\n *\n * Excludes:\n * - Files under the build's `immutableDirs` (covered by wildcard rules)\n * - Files under `rsc/` and `ssr/` (server bundles, never served)\n * - Underscore-prefixed files (`_headers`, `_worker.js`, etc.)\n *\n * Ordered for the rule cap: well-known metadata files, then everything\n * else, then files under an underscore-prefixed directory — the\n * framework's own output (unhashed RSC payloads in a static build with\n * client JavaScript disabled, which nothing fetches). Those can number one\n * per route, and must not take the budget from the app's real files.\n *\n * @internal Exported for testing.\n */\n// Well-known metadata files that should be prioritized when capping\n// _headers rules, so they're never dropped in favor of less important files.\nconst PRIORITY_FILES = new Set([\n '/favicon.ico',\n '/robots.txt',\n '/sitemap.xml',\n '/manifest.json',\n '/manifest.webmanifest',\n '/apple-touch-icon.png',\n]);\n\nexport async function findUnhashedStaticFiles(\n publicDir: string,\n immutableDirs: readonly string[]\n): Promise<string[]> {\n let files: string[];\n try {\n files = await collectFiles(publicDir);\n } catch {\n return [];\n }\n\n const priority: string[] = [];\n const rest: string[] = [];\n const framework: string[] = [];\n for (const file of files) {\n const rel = relative(publicDir, file).replace(/\\\\/g, '/');\n if (immutableDirs.some((dir) => rel.startsWith(`${dir}/`))) continue;\n if (rel.startsWith('rsc/') || rel.startsWith('ssr/')) continue;\n if (basename(rel).startsWith('_')) continue;\n const urlPath = '/' + rel;\n if (PRIORITY_FILES.has(urlPath)) {\n priority.push(urlPath);\n } else if (rel.startsWith('_')) {\n framework.push(urlPath);\n } else {\n rest.push(urlPath);\n }\n }\n\n return [...priority.sort(), ...rest.sort(), ...framework.sort()];\n}\n\n/**\n * Scan client JS files for references to .wasm filenames.\n * Returns the set of WASM basenames that are actually imported/referenced\n * by client code and must be preserved in the static output.\n */\nasync function findReferencedWasm(clientDir: string): Promise<Set<string>> {\n const referenced = new Set<string>();\n const files = await collectFiles(clientDir);\n\n const jsFiles = files.filter((f) => f.endsWith('.js'));\n const wasmFiles = files.filter((f) => f.endsWith('.wasm')).map((f) => basename(f));\n if (wasmFiles.length === 0) return referenced;\n\n for (const jsFile of jsFiles) {\n const content = await readFile(jsFile, 'utf-8');\n for (const wasmName of wasmFiles) {\n if (content.includes(wasmName)) {\n referenced.add(wasmName);\n }\n }\n }\n\n return referenced;\n}\n\n/**\n * Build a static-only output directory (no server entry). Copies client\n * assets and pre-rendered HTML/RSC/API files into `outDir/publicDirName`.\n * Used by both Cloudflare and Nitro adapters in `output: 'static'` mode.\n */\nexport async function buildStaticDirectoryOutput(\n config: TimberConfig,\n artifacts: StaticBuildArtifacts,\n outDir: string,\n publicDirName: string\n): Promise<void> {\n // Clean stale artifacts from prior builds (e.g. server-mode builds that\n // left rsc/, ssr/, _worker.js in the outDir). Without this, a static\n // build after a server build inherits 140+ unused server chunks.\n await rm(outDir, { recursive: true, force: true }).catch(() => {});\n await mkdir(outDir, { recursive: true });\n\n const publicDir = join(outDir, publicDirName);\n await mkdir(publicDir, { recursive: true });\n\n // Copy client assets (JS, CSS, fonts, images).\n await cp(artifacts.client.path, publicDir, {\n recursive: true,\n filter: (src: string) => {\n if (config.clientJavascriptDisabled && src.endsWith('.js')) return false;\n return true;\n },\n });\n\n // Copy pre-rendered static pages (HTML + RSC flight + API routes).\n //\n // This is the one place the build merges two independently-produced trees\n // into a single directory, and `cp` resolves an overlap by overwriting with\n // no diagnostic — the deployment then contains one of the two artifacts and\n // nothing recorded which. Refuse instead (TIM-1266).\n await assertNoTreeCollision(artifacts.pages.path, publicDir);\n await cp(artifacts.pages.path, publicDir, { recursive: true });\n}\n\n/**\n * Write the `_headers` file, folding in the user's `public/_headers`.\n *\n * Every adapter used to `writeFile` a generated `_headers` over whatever\n * Vite had copied out of `public/`, so an app shipping its own CSP, CORS, or\n * cache rules deployed without them and without a word (TIM-1326). The\n * generated rules and the user's are not competitors — they address different\n * paths — so this merges rather than refusing, the way `_redirects` has since\n * TIM-1249.\n *\n * **Read from the project, not the output.** The generated file lands under\n * the same name in the output directory, and `runSharedBuildSteps` does not\n * clean `outDir`; a reader aimed there would fold the previous build's\n * generated rules back in and compound them on every rebuild — the defect\n * this pass fixed for `_redirects`.\n *\n * User rules go last. On Cloudflare and Netlify a `_headers` file applies\n * every matching rule, so appending means the user's rules take effect; where\n * a platform resolves a conflict in favour of the earlier rule instead, the\n * framework keeps the paths it owns and the user keeps the rest. Under either\n * reading this is no worse than the previous behaviour, which was to drop the\n * user's rules entirely.\n *\n * @internal Exported for testing.\n */\nexport async function writeHeadersFile(\n dir: string,\n config: TimberConfig,\n artifacts: BuildArtifacts\n): Promise<void> {\n const userRules = await readUserPlatformFile(config.root, HEADERS_FILE);\n await writeFile(\n join(dir, HEADERS_FILE),\n generateHeadersFile({\n base: adapterBase(config),\n immutableDirs: artifacts.immutableDirs,\n // Scanned from the directory being deployed, which holds everything\n // the platform will serve from it.\n unhashedPaths: await findUnhashedStaticFiles(dir, artifacts.immutableDirs),\n contentTypes: artifacts.output === 'static' ? artifacts.contentTypes : undefined,\n userRules: userRules ?? undefined,\n })\n );\n}\n\n/**\n * Read a user-authored platform file from the project's `public/` directory.\n * Returns null when the project has none, or when no root is configured —\n * a caller without a root cannot locate the project at all, and inventing\n * one from `process.cwd()` would read a different project's file.\n */\nasync function readUserPlatformFile(\n root: string | undefined,\n name: string\n): Promise<string | null> {\n if (!root) return null;\n try {\n return await readFile(join(root, USER_PLATFORM_DIR, name), 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Throw if copying `srcDir` over `destDir` would overwrite an existing file.\n *\n * Compared against the destination **as it stands**, not against the other\n * source tree: the first copy is filtered (client JS is dropped when client\n * JavaScript is disabled), so the files that are actually there are the only\n * ones a second copy can clobber.\n *\n * @internal Exported for testing.\n */\nexport async function assertNoTreeCollision(srcDir: string, destDir: string): Promise<void> {\n const [srcFiles, destFiles, identity] = await Promise.all([\n collectFiles(srcDir).catch(() => [] as string[]),\n collectFiles(destDir).catch(() => [] as string[]),\n // `cp` will resolve these paths the way the destination filesystem does,\n // so the comparison predicting it has to as well: on macOS a hand-written\n // `public/About/index.html` and a generated `about/index.html` are one\n // file, and an exact-string set waves the overwrite through (TIM-1266).\n detectFsIdentity(destDir),\n ]);\n\n const key = (p: string) => fsKey(p, identity);\n const existing = new Set(destFiles.map((f) => key(relative(destDir, f).replace(/\\\\/g, '/'))));\n const exempt = new Set(USER_MERGED_PLATFORM_FILES.map(key));\n const collisions = srcFiles\n .map((f) => relative(srcDir, f).replace(/\\\\/g, '/'))\n .filter((rel) => existing.has(key(rel)) && !exempt.has(key(rel)))\n .sort();\n\n if (collisions.length === 0) return;\n\n throw new Error(\n `[timber] Build output: ${collisions.length} file(s) in the pre-rendered site ` +\n `collide with files already in the output directory. Copying would silently ` +\n `overwrite them — a generated page and a file in public/ cannot share a path:\\n` +\n collisions.map((c) => ` - ${c}`).join('\\n')\n );\n}\n\nasync function collectFiles(dir: string): Promise<string[]> {\n const result: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n result.push(...(await collectFiles(fullPath)));\n } else {\n result.push(fullPath);\n }\n }\n return result;\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { l as waitUntilAls } from "./als-registry-DaxkVjt5.js";
|
|
2
|
+
import { E as addSpanEventSync, _ as swallow, p as logSwrRefetchFailed } from "./logger-DiDt5ppH.js";
|
|
3
3
|
import { t as fnv1aHash } from "./fast-hash-C-tVYrLb.js";
|
|
4
|
-
import { n as createSingleflight } from "./singleflight-
|
|
5
|
-
import { t as estimateByteSize } from "./sizeof-
|
|
6
|
-
import { t as warnLossyJsonValue } from "./json-lossy-check-
|
|
4
|
+
import { n as createSingleflight } from "./singleflight-BeVMMKi0.js";
|
|
5
|
+
import { t as estimateByteSize } from "./sizeof-UwzwB1uM.js";
|
|
6
|
+
import { t as warnLossyJsonValue } from "./json-lossy-check-ip0Qi0MT.js";
|
|
7
7
|
import { t as getCdnPurgeHandler } from "./purge-store-Byr8XOjU.js";
|
|
8
|
+
//#region src/server/waituntil-bridge.ts
|
|
9
|
+
/**
|
|
10
|
+
* Per-request waitUntil bridge — ALS bridge for platform adapters.
|
|
11
|
+
*
|
|
12
|
+
* The generated entry point (Nitro, Cloudflare) wraps the handler with
|
|
13
|
+
* `runWithWaitUntil`, binding the platform's lifecycle extension function
|
|
14
|
+
* (e.g., h3's `event.waitUntil()` or CF's `ctx.waitUntil()`) for the
|
|
15
|
+
* request duration. The `waitUntil()` primitive reads from this ALS to
|
|
16
|
+
* dispatch background work to the correct platform API.
|
|
17
|
+
*
|
|
18
|
+
* Design doc: design/11-platform.md §"waitUntil()"
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Get the current request's waitUntil function, if available.
|
|
22
|
+
*
|
|
23
|
+
* Returns undefined when no platform adapter has installed a waitUntil
|
|
24
|
+
* handler for the current request (e.g., on platforms that don't support
|
|
25
|
+
* lifecycle extension, or outside a request context).
|
|
26
|
+
*/
|
|
27
|
+
function getWaitUntil() {
|
|
28
|
+
return waitUntilAls.getStore();
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
8
31
|
//#region src/cache/stable-stringify.ts
|
|
9
32
|
/**
|
|
10
33
|
* Deterministic JSON serialization with sorted object keys.
|
|
@@ -479,10 +502,22 @@ var RedisCacheHandler = class {
|
|
|
479
502
|
var DATA_PREFIX = "d:";
|
|
480
503
|
var TAG_SET_PREFIX = "ts:";
|
|
481
504
|
var TAG_VERSION_PREFIX = "tv:";
|
|
505
|
+
function isNativeStore(store) {
|
|
506
|
+
return !!(store.setWithTags && store.invalidateTag);
|
|
507
|
+
}
|
|
508
|
+
function isEagerStore(store) {
|
|
509
|
+
return !!(store.sadd && store.smembers && store.srem && store.sdel);
|
|
510
|
+
}
|
|
482
511
|
function detectStrategy(store) {
|
|
483
|
-
if (store
|
|
484
|
-
|
|
485
|
-
|
|
512
|
+
if (isNativeStore(store)) return {
|
|
513
|
+
kind: "native",
|
|
514
|
+
store
|
|
515
|
+
};
|
|
516
|
+
if (isEagerStore(store)) return {
|
|
517
|
+
kind: "eager",
|
|
518
|
+
store
|
|
519
|
+
};
|
|
520
|
+
return { kind: "lazy" };
|
|
486
521
|
}
|
|
487
522
|
var TagAwareCacheHandler = class {
|
|
488
523
|
store;
|
|
@@ -512,7 +547,7 @@ var TagAwareCacheHandler = class {
|
|
|
512
547
|
async get(key) {
|
|
513
548
|
const raw = await this.store.get(this.dataKey(key));
|
|
514
549
|
if (raw === null) return null;
|
|
515
|
-
if (this.strategy
|
|
550
|
+
if (this.strategy.kind !== "lazy") {
|
|
516
551
|
const entry = JSON.parse(raw);
|
|
517
552
|
const stale = Date.now() > entry.expiresAt;
|
|
518
553
|
return {
|
|
@@ -536,25 +571,26 @@ var TagAwareCacheHandler = class {
|
|
|
536
571
|
}
|
|
537
572
|
async set(key, value, opts) {
|
|
538
573
|
const physicalTtl = Math.max(opts.ttl * 2 + 60, 120);
|
|
539
|
-
|
|
574
|
+
const strategy = this.strategy;
|
|
575
|
+
if (strategy.kind === "native") {
|
|
540
576
|
const entry = {
|
|
541
577
|
value,
|
|
542
578
|
expiresAt: Date.now() + opts.ttl * 1e3,
|
|
543
579
|
tags: opts.tags
|
|
544
580
|
};
|
|
545
581
|
const payload = JSON.stringify(entry);
|
|
546
|
-
if (opts.tags.length > 0) await
|
|
582
|
+
if (opts.tags.length > 0) await strategy.store.setWithTags(this.dataKey(key), payload, physicalTtl, this.prefixTags(opts.tags));
|
|
547
583
|
else await this.store.set(this.dataKey(key), payload, physicalTtl);
|
|
548
584
|
return;
|
|
549
585
|
}
|
|
550
|
-
if (
|
|
586
|
+
if (strategy.kind === "eager") {
|
|
551
587
|
const entry = {
|
|
552
588
|
value,
|
|
553
589
|
expiresAt: Date.now() + opts.ttl * 1e3,
|
|
554
590
|
tags: opts.tags
|
|
555
591
|
};
|
|
556
592
|
await this.store.set(this.dataKey(key), JSON.stringify(entry), physicalTtl);
|
|
557
|
-
if (opts.tags.length > 0) await Promise.all(opts.tags.map((tag) =>
|
|
593
|
+
if (opts.tags.length > 0) await Promise.all(opts.tags.map((tag) => strategy.store.sadd(this.tagSetKey(tag), [key], physicalTtl)));
|
|
558
594
|
return;
|
|
559
595
|
}
|
|
560
596
|
const tagVersions = opts.tags.length > 0 ? await this.getTagVersions(opts.tags) : {};
|
|
@@ -567,31 +603,27 @@ var TagAwareCacheHandler = class {
|
|
|
567
603
|
await this.store.set(this.dataKey(key), JSON.stringify(entry), physicalTtl);
|
|
568
604
|
}
|
|
569
605
|
async invalidate(opts) {
|
|
606
|
+
const strategy = this.strategy;
|
|
570
607
|
if (opts.key) {
|
|
571
|
-
|
|
572
|
-
|
|
608
|
+
const key = opts.key;
|
|
609
|
+
if (strategy.kind === "eager") {
|
|
610
|
+
const raw = await this.store.get(this.dataKey(key));
|
|
573
611
|
if (raw !== null) {
|
|
574
612
|
const entry = JSON.parse(raw);
|
|
575
|
-
if (entry.tags.length > 0) await Promise.all(entry.tags.map((tag) =>
|
|
613
|
+
if (entry.tags.length > 0) await Promise.all(entry.tags.map((tag) => strategy.store.srem(this.tagSetKey(tag), [key])));
|
|
576
614
|
}
|
|
577
615
|
}
|
|
578
|
-
await this.store.del(this.dataKey(
|
|
616
|
+
await this.store.del(this.dataKey(key));
|
|
579
617
|
}
|
|
580
618
|
if (opts.tag) {
|
|
581
619
|
const tag = opts.tag;
|
|
582
|
-
if (
|
|
583
|
-
else if (
|
|
584
|
-
const members = await
|
|
620
|
+
if (strategy.kind === "native") await strategy.store.invalidateTag(`${this.prefix}${tag}`);
|
|
621
|
+
else if (strategy.kind === "eager") {
|
|
622
|
+
const members = await strategy.store.smembers(this.tagSetKey(tag));
|
|
585
623
|
await Promise.all(members.map(async (k) => {
|
|
586
624
|
const raw = await this.store.get(this.dataKey(k));
|
|
587
|
-
if (raw
|
|
588
|
-
|
|
589
|
-
return;
|
|
590
|
-
}
|
|
591
|
-
if (JSON.parse(raw).tags.includes(tag)) {
|
|
592
|
-
await this.store.del(this.dataKey(k));
|
|
593
|
-
await this.store.srem(this.tagSetKey(tag), [k]);
|
|
594
|
-
} else await this.store.srem(this.tagSetKey(tag), [k]);
|
|
625
|
+
if (raw !== null && JSON.parse(raw).tags.includes(tag)) await this.store.del(this.dataKey(k));
|
|
626
|
+
await strategy.store.srem(this.tagSetKey(tag), [k]);
|
|
595
627
|
}));
|
|
596
628
|
} else await this.bumpTagVersion(opts.tag);
|
|
597
629
|
}
|
|
@@ -729,8 +761,8 @@ var DEPLOYMENT_ID_HEADER = "X-Timber-Deployment-Id";
|
|
|
729
761
|
/** Response header that signals the client to do a full page reload. */
|
|
730
762
|
var RELOAD_HEADER = "X-Timber-Reload";
|
|
731
763
|
/**
|
|
732
|
-
* The current build's deployment ID. Set at startup from the
|
|
733
|
-
*
|
|
764
|
+
* The current build's deployment ID. Set at startup from the runtime config
|
|
765
|
+
* (`virtual:timber-config`'s `deploymentId`). Null in dev mode.
|
|
734
766
|
*/
|
|
735
767
|
var currentDeploymentId = null;
|
|
736
768
|
/**
|
|
@@ -1145,6 +1177,6 @@ var cache = {
|
|
|
1145
1177
|
}
|
|
1146
1178
|
};
|
|
1147
1179
|
//#endregion
|
|
1148
|
-
export { setDefaultSingleflightTimeout as _, getManifestEntry as a, wasInvalidatedSince as b, lookupPrebuiltPayload as c, checkVersionSkew as d, MemoryCacheHandler as f, setCacheHandler as g, getCacheHandler as h, storeOverlayEntry as i, setPrebuiltPayloadSource as l, RedisCacheHandler as m, lookupOverlay as n, hasPrebuiltPayloadSource as o, TagAwareCacheHandler as p, overlayKey as r, isParamIndependent as s, cache as t, applyReloadHeaders as u, currentInvalidationEpoch as v, lastInvalidationEpochFor as y };
|
|
1180
|
+
export { setDefaultSingleflightTimeout as _, getManifestEntry as a, wasInvalidatedSince as b, lookupPrebuiltPayload as c, checkVersionSkew as d, MemoryCacheHandler as f, setCacheHandler as g, getCacheHandler as h, storeOverlayEntry as i, setPrebuiltPayloadSource as l, RedisCacheHandler as m, lookupOverlay as n, hasPrebuiltPayloadSource as o, TagAwareCacheHandler as p, overlayKey as r, isParamIndependent as s, cache as t, applyReloadHeaders as u, currentInvalidationEpoch as v, getWaitUntil as x, lastInvalidationEpochFor as y };
|
|
1149
1181
|
|
|
1150
|
-
//# sourceMappingURL=cache-api-
|
|
1182
|
+
//# sourceMappingURL=cache-api-CR23J_NC.js.map
|