@timber-js/app 0.2.0-alpha.8 → 0.2.0-alpha.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/dist/_chunks/actions-Dg-ANYHb.js +421 -0
- package/dist/_chunks/actions-Dg-ANYHb.js.map +1 -0
- package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
- package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
- package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
- package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
- package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
- package/dist/_chunks/define-C77ScO0m.js +106 -0
- package/dist/_chunks/define-C77ScO0m.js.map +1 -0
- package/dist/_chunks/define-CZqDwhSu.js +199 -0
- package/dist/_chunks/define-CZqDwhSu.js.map +1 -0
- package/dist/_chunks/define-cookie-C2IkoFGN.js +94 -0
- package/dist/_chunks/define-cookie-C2IkoFGN.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
- package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
- package/dist/_chunks/format-CYBGxKtc.js +14 -0
- package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
- package/dist/_chunks/{interception-BOoWmLUA.js → interception-Dpn_UfAD.js} +171 -97
- package/dist/_chunks/interception-Dpn_UfAD.js.map +1 -0
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
- package/dist/_chunks/request-context-qMsWgy9C.js +478 -0
- package/dist/_chunks/request-context-qMsWgy9C.js.map +1 -0
- package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
- package/dist/_chunks/schema-bridge-C3xl_vfb.js.map +1 -0
- package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
- package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
- package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
- package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
- package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
- package/dist/_chunks/stale-reload-BX5gL1r-.js +64 -0
- package/dist/_chunks/stale-reload-BX5gL1r-.js.map +1 -0
- package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
- package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
- package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
- package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-Lo_s_pw2.js} +4 -4
- package/dist/_chunks/use-query-states-Lo_s_pw2.js.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +95 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +148 -12
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +135 -11
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +56 -13
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/cache/cache-api.d.ts +24 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +23 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +142 -80
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cli.d.ts +6 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +8 -3
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +27 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +30 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +23 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +19 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- package/dist/client/error-boundary.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +10 -4
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +54 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +3 -3
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +19 -4
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +7 -21
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +210 -1017
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +18 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +890 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link-pending-store.d.ts +63 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +90 -32
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +36 -0
- package/dist/client/nav-link-store.d.ts.map +1 -0
- package/dist/client/navigation-api-types.d.ts +90 -0
- package/dist/client/navigation-api-types.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts +115 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +13 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router.d.ts +70 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +63 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +5 -5
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-link-status.d.ts +5 -5
- package/dist/client/use-link-status.d.ts.map +1 -1
- package/dist/client/use-params.d.ts +6 -4
- package/dist/client/use-params.d.ts.map +1 -1
- package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/codec.d.ts +33 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +2 -0
- package/dist/config-types.d.ts +227 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts +35 -14
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -83
- package/dist/fonts/css.d.ts +1 -0
- package/dist/fonts/css.d.ts.map +1 -1
- package/dist/index.d.ts +45 -192
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12357 -11925
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +107 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +2 -2
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +3 -3
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +32 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-browser-logs.d.ts +84 -0
- package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
- package/dist/plugins/dev-error-overlay.d.ts +26 -1
- package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
- package/dist/plugins/dev-logs.d.ts +1 -1
- package/dist/plugins/dev-logs.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +19 -5
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +6 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +4 -4
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen.d.ts +2 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/index.d.ts +2 -0
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +3 -2
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +46 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/status-file-lint.d.ts +2 -1
- package/dist/routing/status-file-lint.d.ts.map +1 -1
- package/dist/routing/types.d.ts +16 -4
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +76 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +139 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -7
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +32 -441
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/registry.d.ts +2 -2
- package/dist/search-params/registry.d.ts.map +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +78 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +3 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +2 -0
- package/dist/server/access-gate.d.ts +4 -0
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +25 -6
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +3 -6
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +32 -4
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +2 -2
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/debug.d.ts +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-page-resolver.d.ts +52 -0
- package/dist/server/deny-page-resolver.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-holding-server.d.ts +52 -0
- package/dist/server/dev-holding-server.d.ts.map +1 -0
- package/dist/server/dev-warnings.d.ts +1 -21
- package/dist/server/dev-warnings.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -5
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +4 -3
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/flight-injection-state.d.ts +66 -0
- package/dist/server/flight-injection-state.d.ts.map +1 -0
- package/dist/server/flight-scripts.d.ts +42 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/flush.d.ts.map +1 -1
- package/dist/server/form-data.d.ts +29 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injectors.d.ts +51 -11
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -43
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +37 -2798
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +46 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +2883 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/logger.d.ts +25 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +19 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +113 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/page-deny-boundary.d.ts +31 -0
- package/dist/server/page-deny-boundary.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +42 -10
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +69 -18
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-timeout.d.ts +51 -0
- package/dist/server/render-timeout.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +112 -43
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +27 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +9 -2
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/api-handler.d.ts +2 -2
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +48 -5
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +8 -3
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +4 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +22 -0
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +39 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/status-code-resolver.d.ts +1 -1
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +36 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +4 -4
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +22 -19
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -4
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/headers.d.ts +2 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +1 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +3 -2
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/directive-parser.d.ts +5 -2
- package/dist/utils/directive-parser.d.ts.map +1 -1
- package/dist/utils/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/package.json +56 -22
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/adapters/cloudflare.ts +342 -28
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +52 -8
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +81 -18
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/sizeof.ts +31 -0
- package/src/cache/timber-cache.ts +24 -20
- package/src/cli.ts +16 -6
- package/src/client/browser-dev.ts +128 -1
- package/src/client/browser-entry/action-dispatch.ts +116 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +145 -0
- package/src/client/browser-entry/index.ts +138 -0
- package/src/client/browser-entry/post-hydration.ts +119 -0
- package/src/client/browser-entry/router-init.ts +193 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +27 -0
- package/src/client/error-boundary.tsx +48 -16
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +9 -7
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +19 -38
- package/src/client/internal.ts +57 -0
- package/src/client/link-pending-store.ts +111 -0
- package/src/client/link.tsx +329 -97
- package/src/client/nav-link-store.ts +47 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +332 -0
- package/src/client/navigation-context.ts +31 -6
- package/src/client/navigation-root.tsx +342 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +299 -72
- package/src/client/rsc-fetch.ts +97 -8
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +72 -3
- package/src/client/top-loader.tsx +16 -8
- package/src/client/use-link-status.ts +7 -7
- package/src/client/use-params.ts +7 -5
- package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
- package/src/client/use-query-states.ts +3 -3
- package/src/client/use-router.ts +1 -1
- package/src/codec.ts +49 -0
- package/src/config-types.ts +225 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +78 -25
- package/src/cookies/index.ts +8 -0
- package/src/fonts/css.ts +2 -1
- package/src/index.ts +295 -354
- package/src/plugin-context.ts +240 -0
- package/src/plugins/adapter-build.ts +9 -3
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +3 -3
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-browser-logs.ts +288 -0
- package/src/plugins/dev-error-overlay.ts +70 -1
- package/src/plugins/dev-logs.ts +1 -1
- package/src/plugins/dev-server.ts +70 -9
- package/src/plugins/entries.ts +71 -10
- package/src/plugins/fonts.ts +168 -61
- package/src/plugins/mdx.ts +1 -1
- package/src/plugins/routing.ts +57 -17
- package/src/plugins/server-action-exports.ts +1 -1
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +135 -35
- package/src/plugins/static-build.ts +17 -11
- package/src/routing/codegen.ts +165 -105
- package/src/routing/index.ts +2 -0
- package/src/routing/scanner.ts +93 -23
- package/src/routing/segment-classify.ts +89 -0
- package/src/routing/status-file-lint.ts +3 -2
- package/src/routing/types.ts +17 -4
- package/src/rsc-runtime/rsc.ts +2 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
- package/src/search-params/define.ts +482 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +85 -0
- package/src/segment-params/define.ts +279 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +70 -29
- package/src/server/action-client.ts +46 -11
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +21 -4
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +34 -6
- package/src/server/build-manifest.ts +10 -4
- package/src/server/compress.ts +25 -7
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-page-resolver.ts +154 -0
- package/src/server/deny-renderer.ts +24 -38
- package/src/server/dev-holding-server.ts +185 -0
- package/src/server/dev-warnings.ts +4 -49
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +31 -15
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/flush.ts +2 -1
- package/src/server/form-data.ts +76 -0
- package/src/server/html-injectors.ts +280 -120
- package/src/server/index.ts +25 -177
- package/src/server/internal.ts +169 -0
- package/src/server/logger.ts +44 -36
- package/src/server/middleware-runner.ts +31 -4
- package/src/server/node-stream-transforms.ts +509 -0
- package/src/server/page-deny-boundary.tsx +56 -0
- package/src/server/pipeline-interception.ts +17 -16
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline.ts +227 -62
- package/src/server/primitives.ts +111 -28
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +293 -132
- package/src/server/route-element-builder.ts +283 -191
- package/src/server/route-handler.ts +24 -4
- package/src/server/route-matcher.ts +24 -20
- package/src/server/rsc-entry/api-handler.ts +15 -16
- package/src/server/rsc-entry/error-renderer.ts +300 -89
- package/src/server/rsc-entry/helpers.ts +134 -5
- package/src/server/rsc-entry/index.ts +200 -112
- package/src/server/rsc-entry/rsc-payload.ts +65 -18
- package/src/server/rsc-entry/rsc-stream.ts +65 -13
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +168 -38
- package/src/server/safe-load.ts +60 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +126 -0
- package/src/server/slot-resolver.ts +244 -229
- package/src/server/ssr-entry.ts +211 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/status-code-resolver.ts +1 -1
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +20 -9
- package/src/server/tree-builder.ts +92 -58
- package/src/server/types.ts +3 -6
- package/src/server/version-skew.ts +104 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +5 -1
- package/src/shims/navigation-client.ts +1 -1
- package/src/shims/navigation.ts +7 -2
- package/src/utils/directive-parser.ts +5 -2
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/format-DviM89f0.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/cookies/index.js.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/server/response-cache.d.ts +0 -54
- package/dist/server/response-cache.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -103
- package/src/client/browser-entry.ts +0 -678
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/transition-root.tsx +0 -166
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/create.ts +0 -321
- package/src/server/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -410
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generate sitemap.xml from the route tree.
|
|
3
|
+
*
|
|
4
|
+
* When enabled via `sitemap: { enabled: true, baseUrl: '...' }` in timber.config.ts,
|
|
5
|
+
* this module walks the route tree and produces sitemap XML for all discoverable pages.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Collects all static page routes automatically
|
|
9
|
+
* - Calls `generateStaticParams()` on dynamic routes to enumerate URLs
|
|
10
|
+
* - Skips API routes (route.ts), layout-only segments, slots, intercepting routes
|
|
11
|
+
* - Skips auth-protected routes (access.ts in segment chain) by default
|
|
12
|
+
* - Automatic pagination: sitemap index when > 50,000 URLs
|
|
13
|
+
*
|
|
14
|
+
* See design/16-metadata.md §"Auto-generated Sitemap"
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { serializeSitemap, serializeSitemapIndex } from './pipeline-metadata.js';
|
|
18
|
+
import type { SegmentNode } from '../routing/types.js';
|
|
19
|
+
|
|
20
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
/** Configuration for sitemap generation from timber.config.ts. */
|
|
23
|
+
export interface SitemapConfig {
|
|
24
|
+
/** Must be explicitly true to enable auto-generation. */
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
/** Base URL for absolute URLs in the sitemap. Required. e.g., 'https://example.com' */
|
|
27
|
+
baseUrl: string;
|
|
28
|
+
/** Default changefreq for all entries. Optional. */
|
|
29
|
+
defaultChangeFrequency?: string;
|
|
30
|
+
/** Default priority for all entries (0.0–1.0). Optional. */
|
|
31
|
+
defaultPriority?: number;
|
|
32
|
+
/** Include routes protected by access.ts. Default: false. */
|
|
33
|
+
includeProtected?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** A single sitemap entry ready for serialization. */
|
|
37
|
+
export interface SitemapEntry {
|
|
38
|
+
url: string;
|
|
39
|
+
changeFrequency?: string;
|
|
40
|
+
priority?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A route discovered during tree walk that may need async resolution
|
|
45
|
+
* (dynamic routes with generateStaticParams).
|
|
46
|
+
*/
|
|
47
|
+
export interface SitemapRoute {
|
|
48
|
+
/** The URL path pattern (e.g., '/products/[id]'). */
|
|
49
|
+
urlPath: string;
|
|
50
|
+
/** Whether this route has dynamic segments that need generateStaticParams. */
|
|
51
|
+
isDynamic: boolean;
|
|
52
|
+
/** Loader for the page module (from route manifest). */
|
|
53
|
+
pageLoader?: { load: () => Promise<unknown>; filePath: string };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Function signature for loading a page module.
|
|
58
|
+
* Takes the manifest loader and returns the module exports.
|
|
59
|
+
*/
|
|
60
|
+
export type ModuleLoader = (loader: {
|
|
61
|
+
load: () => Promise<unknown>;
|
|
62
|
+
filePath: string;
|
|
63
|
+
}) => Promise<Record<string, unknown>>;
|
|
64
|
+
|
|
65
|
+
/** Result of sitemap generation. */
|
|
66
|
+
export type SitemapResult =
|
|
67
|
+
| { type: 'single'; xml: string }
|
|
68
|
+
| { type: 'index'; indexXml: string; pages: Map<number, string> };
|
|
69
|
+
|
|
70
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
/** Maximum URLs per sitemap file per the sitemap protocol. */
|
|
73
|
+
export const URLS_PER_SITEMAP = 50_000;
|
|
74
|
+
|
|
75
|
+
// ─── Tree Walking ────────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Walk the route tree and collect all routes eligible for the sitemap.
|
|
79
|
+
*
|
|
80
|
+
* Pure synchronous function — no module loading. Returns routes that may
|
|
81
|
+
* need async resolution (dynamic routes with generateStaticParams).
|
|
82
|
+
*
|
|
83
|
+
* @param root - The root segment node from the route tree
|
|
84
|
+
* @param config - Sitemap configuration
|
|
85
|
+
* @returns Array of sitemap routes to resolve
|
|
86
|
+
*/
|
|
87
|
+
export function collectSitemapRoutes(root: SegmentNode, config: SitemapConfig): SitemapRoute[] {
|
|
88
|
+
const routes: SitemapRoute[] = [];
|
|
89
|
+
walkNode(root, routes, config.includeProtected ?? false, false);
|
|
90
|
+
return routes;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Recursive tree walker. Collects page routes, skipping ineligible segments.
|
|
95
|
+
*
|
|
96
|
+
* @param node - Current segment node
|
|
97
|
+
* @param routes - Accumulator for discovered routes
|
|
98
|
+
* @param includeProtected - Whether to include routes with access.ts
|
|
99
|
+
* @param hasAccessInChain - Whether any ancestor has access.ts
|
|
100
|
+
*/
|
|
101
|
+
function walkNode(
|
|
102
|
+
node: SegmentNode,
|
|
103
|
+
routes: SitemapRoute[],
|
|
104
|
+
includeProtected: boolean,
|
|
105
|
+
hasAccessInChain: boolean
|
|
106
|
+
): void {
|
|
107
|
+
// Track whether this node or any ancestor has access.ts
|
|
108
|
+
const protectedChain = hasAccessInChain || !!node.access;
|
|
109
|
+
|
|
110
|
+
// Skip intercepting routes — they're conditional rewrites, not real pages
|
|
111
|
+
if (node.segmentType === 'intercepting') return;
|
|
112
|
+
|
|
113
|
+
// Skip private folders
|
|
114
|
+
if (node.segmentType === 'private') return;
|
|
115
|
+
|
|
116
|
+
// Skip slots — parallel routes don't contribute independent URLs
|
|
117
|
+
// (slots are handled via the parent's slots map, but we skip them here)
|
|
118
|
+
|
|
119
|
+
// Check if this node has a page (not a route.ts API endpoint)
|
|
120
|
+
if (node.page && !node.route) {
|
|
121
|
+
// Skip protected routes unless configured to include them
|
|
122
|
+
if (!protectedChain || includeProtected) {
|
|
123
|
+
const isDynamic = hasDynamicSegments(node.urlPath);
|
|
124
|
+
// At runtime (manifest), page has a `load` function. At scan time (RouteFile),
|
|
125
|
+
// it only has filePath + extension. We check for `load` at runtime.
|
|
126
|
+
const page = node.page as {
|
|
127
|
+
filePath: string;
|
|
128
|
+
extension: string;
|
|
129
|
+
load?: () => Promise<unknown>;
|
|
130
|
+
};
|
|
131
|
+
routes.push({
|
|
132
|
+
urlPath: node.urlPath,
|
|
133
|
+
isDynamic,
|
|
134
|
+
pageLoader: page.load ? { load: page.load, filePath: page.filePath } : undefined,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Recurse into children (not slots — slots don't contribute sitemap URLs)
|
|
140
|
+
for (const child of node.children) {
|
|
141
|
+
walkNode(child, routes, includeProtected, protectedChain);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Do NOT recurse into slots — they are parallel routes at the same URL
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Check if a URL path contains dynamic segments.
|
|
149
|
+
*
|
|
150
|
+
* Dynamic segments are enclosed in brackets: [param], [...param], [[...param]]
|
|
151
|
+
*/
|
|
152
|
+
export function hasDynamicSegments(urlPath: string): boolean {
|
|
153
|
+
return /\[/.test(urlPath);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ─── URL Resolution ──────────────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Resolve sitemap routes into concrete URLs.
|
|
160
|
+
*
|
|
161
|
+
* For static routes, the URL is derived directly from the path.
|
|
162
|
+
* For dynamic routes, calls `generateStaticParams()` from the page module.
|
|
163
|
+
*
|
|
164
|
+
* @param routes - Routes collected by collectSitemapRoutes
|
|
165
|
+
* @param config - Sitemap configuration
|
|
166
|
+
* @param loadModule - Async function to load a page module by file path
|
|
167
|
+
* @returns Array of sitemap entries with absolute URLs
|
|
168
|
+
*/
|
|
169
|
+
export async function resolveSitemapUrls(
|
|
170
|
+
routes: SitemapRoute[],
|
|
171
|
+
config: SitemapConfig,
|
|
172
|
+
loadModule?: ModuleLoader
|
|
173
|
+
): Promise<SitemapEntry[]> {
|
|
174
|
+
const baseUrl = config.baseUrl.replace(/\/+$/, ''); // strip trailing slash
|
|
175
|
+
const entries: SitemapEntry[] = [];
|
|
176
|
+
|
|
177
|
+
for (const route of routes) {
|
|
178
|
+
if (!route.isDynamic) {
|
|
179
|
+
// Static route — direct URL
|
|
180
|
+
const url = route.urlPath === '/' ? baseUrl + '/' : baseUrl + route.urlPath;
|
|
181
|
+
entries.push({
|
|
182
|
+
url,
|
|
183
|
+
changeFrequency: config.defaultChangeFrequency,
|
|
184
|
+
priority: config.defaultPriority,
|
|
185
|
+
});
|
|
186
|
+
} else if (loadModule && route.pageLoader) {
|
|
187
|
+
// Dynamic route — try to call generateStaticParams
|
|
188
|
+
try {
|
|
189
|
+
const mod = await loadModule(route.pageLoader);
|
|
190
|
+
const generateFn = mod.generateStaticParams;
|
|
191
|
+
if (typeof generateFn !== 'function') {
|
|
192
|
+
// No generateStaticParams export — skip this dynamic route
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const paramSets: Record<string, string>[] = await generateFn();
|
|
197
|
+
for (const params of paramSets) {
|
|
198
|
+
const resolvedPath = resolvePathWithParams(route.urlPath, params);
|
|
199
|
+
if (resolvedPath) {
|
|
200
|
+
entries.push({
|
|
201
|
+
url: baseUrl + resolvedPath,
|
|
202
|
+
changeFrequency: config.defaultChangeFrequency,
|
|
203
|
+
priority: config.defaultPriority,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
// Log and skip — don't fail the entire sitemap for one bad route
|
|
209
|
+
const filePath = route.pageLoader.filePath;
|
|
210
|
+
console.warn(
|
|
211
|
+
`[timber] sitemap: failed to call generateStaticParams for ${filePath}:`,
|
|
212
|
+
error instanceof Error ? error.message : error
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// If no loadModule provided and route is dynamic, skip it
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return entries;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Replace dynamic segments in a URL path with concrete param values.
|
|
224
|
+
*
|
|
225
|
+
* Handles:
|
|
226
|
+
* - `[param]` → single value
|
|
227
|
+
* - `[...param]` → slash-joined values
|
|
228
|
+
* - `[[...param]]` → slash-joined values (or empty string if not provided)
|
|
229
|
+
*
|
|
230
|
+
* @returns The resolved path, or null if params are missing
|
|
231
|
+
*/
|
|
232
|
+
export function resolvePathWithParams(
|
|
233
|
+
urlPath: string,
|
|
234
|
+
params: Record<string, string | string[]>
|
|
235
|
+
): string | null {
|
|
236
|
+
let resolved = urlPath;
|
|
237
|
+
|
|
238
|
+
// Optional catch-all: [[...param]]
|
|
239
|
+
resolved = resolved.replace(/\[\[\.\.\.([^\]]+)\]\]/g, (_, name) => {
|
|
240
|
+
const value = params[name];
|
|
241
|
+
if (value === undefined || value === '') return '';
|
|
242
|
+
if (Array.isArray(value)) return value.join('/');
|
|
243
|
+
return value;
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Catch-all: [...param]
|
|
247
|
+
resolved = resolved.replace(/\[\.\.\.([^\]]+)\]/g, (_, name) => {
|
|
248
|
+
const value = params[name];
|
|
249
|
+
if (value === undefined) return '';
|
|
250
|
+
if (Array.isArray(value)) return value.join('/');
|
|
251
|
+
return value;
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Single dynamic: [param] — return null if a required param is missing
|
|
255
|
+
let missingRequired = false;
|
|
256
|
+
resolved = resolved.replace(/\[([^\]]+)\]/g, (match, name) => {
|
|
257
|
+
const value = params[name];
|
|
258
|
+
if (value === undefined) {
|
|
259
|
+
missingRequired = true;
|
|
260
|
+
return match; // keep original to avoid malformed URL
|
|
261
|
+
}
|
|
262
|
+
if (Array.isArray(value)) return value[0] ?? '';
|
|
263
|
+
return value;
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
if (missingRequired) return null;
|
|
267
|
+
|
|
268
|
+
// Clean up double slashes from empty optional catch-alls
|
|
269
|
+
resolved = resolved.replace(/\/+/g, '/');
|
|
270
|
+
|
|
271
|
+
// Remove trailing slash (except for root)
|
|
272
|
+
if (resolved.length > 1 && resolved.endsWith('/')) {
|
|
273
|
+
resolved = resolved.slice(0, -1);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return resolved;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ─── Sitemap Generation ──────────────────────────────────────────────────────
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Generate the complete sitemap result from a route tree.
|
|
283
|
+
*
|
|
284
|
+
* Orchestrates tree walking, URL resolution, and XML serialization.
|
|
285
|
+
* Returns either a single sitemap or a paginated sitemap index.
|
|
286
|
+
*
|
|
287
|
+
* @param root - The root segment node from the route tree
|
|
288
|
+
* @param config - Sitemap configuration
|
|
289
|
+
* @param loadModule - Optional async function to load page modules (for generateStaticParams)
|
|
290
|
+
* @returns The sitemap result (single or index with pages)
|
|
291
|
+
*/
|
|
292
|
+
export async function generateSitemap(
|
|
293
|
+
root: SegmentNode,
|
|
294
|
+
config: SitemapConfig,
|
|
295
|
+
loadModule?: ModuleLoader
|
|
296
|
+
): Promise<SitemapResult> {
|
|
297
|
+
const routes = collectSitemapRoutes(root, config);
|
|
298
|
+
const entries = await resolveSitemapUrls(routes, config, loadModule);
|
|
299
|
+
|
|
300
|
+
if (entries.length <= URLS_PER_SITEMAP) {
|
|
301
|
+
// Single sitemap
|
|
302
|
+
return {
|
|
303
|
+
type: 'single',
|
|
304
|
+
xml: serializeSitemap(entries),
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Paginated — split into chunks
|
|
309
|
+
const baseUrl = config.baseUrl.replace(/\/+$/, '');
|
|
310
|
+
const pageCount = Math.ceil(entries.length / URLS_PER_SITEMAP);
|
|
311
|
+
const pages = new Map<number, string>();
|
|
312
|
+
const sitemapUrls: string[] = [];
|
|
313
|
+
|
|
314
|
+
for (let i = 0; i < pageCount; i++) {
|
|
315
|
+
const start = i * URLS_PER_SITEMAP;
|
|
316
|
+
const end = Math.min(start + URLS_PER_SITEMAP, entries.length);
|
|
317
|
+
const chunk = entries.slice(start, end);
|
|
318
|
+
pages.set(i, serializeSitemap(chunk));
|
|
319
|
+
sitemapUrls.push(`${baseUrl}/sitemap/${i}.xml`);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
type: 'index',
|
|
324
|
+
indexXml: serializeSitemapIndex(sitemapUrls),
|
|
325
|
+
pages,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Check if the route tree root has a user-authored sitemap metadata route.
|
|
331
|
+
*
|
|
332
|
+
* When a user-authored sitemap exists at the root, auto-generation is disabled
|
|
333
|
+
* to avoid conflicts — the user takes full control.
|
|
334
|
+
*/
|
|
335
|
+
export function hasUserSitemap(root: SegmentNode): boolean {
|
|
336
|
+
if (!root.metadataRoutes) return false;
|
|
337
|
+
return root.metadataRoutes.has('sitemap');
|
|
338
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-sitemap request handler for the pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Creates a handler function that intercepts `/sitemap.xml` and `/sitemap/N.xml`
|
|
5
|
+
* requests, generating sitemap XML from the route tree on-the-fly.
|
|
6
|
+
*
|
|
7
|
+
* This module bridges the pipeline (which doesn't know about route trees)
|
|
8
|
+
* with the sitemap generator (which doesn't know about HTTP).
|
|
9
|
+
*
|
|
10
|
+
* See design/16-metadata.md §"Auto-generated Sitemap"
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
generateSitemap,
|
|
15
|
+
hasUserSitemap,
|
|
16
|
+
type SitemapConfig,
|
|
17
|
+
type SitemapResult,
|
|
18
|
+
} from './sitemap-generator.js';
|
|
19
|
+
import { loadModule } from './safe-load.js';
|
|
20
|
+
import type { SegmentNode } from '../routing/types.js';
|
|
21
|
+
|
|
22
|
+
/** Regex to match /sitemap/N.xml where N is a non-negative integer. */
|
|
23
|
+
const SITEMAP_PAGE_PATTERN = /^\/sitemap\/(\d+)\.xml$/;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create the auto-sitemap request handler for the pipeline.
|
|
27
|
+
*
|
|
28
|
+
* Returns a function that handles `/sitemap.xml` and `/sitemap/N.xml`,
|
|
29
|
+
* or returns `null` to pass through to regular routing.
|
|
30
|
+
*
|
|
31
|
+
* Returns `undefined` if auto-sitemap is not enabled (no overhead in pipeline).
|
|
32
|
+
*/
|
|
33
|
+
export function createAutoSitemapHandler(
|
|
34
|
+
root: SegmentNode,
|
|
35
|
+
runtimeConfig: Record<string, unknown>
|
|
36
|
+
): ((pathname: string) => Promise<Response | null>) | undefined {
|
|
37
|
+
// Check if sitemap generation is enabled
|
|
38
|
+
const sitemapConfig = runtimeConfig.sitemap as
|
|
39
|
+
| {
|
|
40
|
+
enabled?: boolean;
|
|
41
|
+
baseUrl?: string;
|
|
42
|
+
defaultChangeFrequency?: string;
|
|
43
|
+
defaultPriority?: number;
|
|
44
|
+
includeProtected?: boolean;
|
|
45
|
+
}
|
|
46
|
+
| undefined;
|
|
47
|
+
|
|
48
|
+
if (!sitemapConfig?.enabled) return undefined;
|
|
49
|
+
|
|
50
|
+
if (!sitemapConfig.baseUrl) {
|
|
51
|
+
console.warn(
|
|
52
|
+
'[timber] sitemap.enabled is true but sitemap.baseUrl is missing. Sitemap generation disabled.'
|
|
53
|
+
);
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Don't generate if user has their own sitemap at the root
|
|
58
|
+
if (hasUserSitemap(root)) return undefined;
|
|
59
|
+
|
|
60
|
+
const config: SitemapConfig = {
|
|
61
|
+
enabled: true,
|
|
62
|
+
baseUrl: sitemapConfig.baseUrl,
|
|
63
|
+
defaultChangeFrequency: sitemapConfig.defaultChangeFrequency,
|
|
64
|
+
defaultPriority: sitemapConfig.defaultPriority,
|
|
65
|
+
includeProtected: sitemapConfig.includeProtected ?? false,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Module loader adapter — uses the safe-load helper which wraps
|
|
69
|
+
// the manifest's lazy import functions.
|
|
70
|
+
const moduleLoader = async (loader: { load: () => Promise<unknown>; filePath: string }) => {
|
|
71
|
+
return loadModule<Record<string, unknown>>(loader);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Cache the generated result to avoid regenerating on every request.
|
|
75
|
+
// In dev, this cache is busted by file changes (the handler is recreated
|
|
76
|
+
// when the route tree changes). In production, it's generated once.
|
|
77
|
+
let cachedResult: SitemapResult | null = null;
|
|
78
|
+
|
|
79
|
+
async function getOrGenerateSitemap(): Promise<SitemapResult> {
|
|
80
|
+
if (cachedResult) return cachedResult;
|
|
81
|
+
cachedResult = await generateSitemap(root, config, moduleLoader);
|
|
82
|
+
return cachedResult;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return async (pathname: string): Promise<Response | null> => {
|
|
86
|
+
// Handle /sitemap.xml
|
|
87
|
+
if (pathname === '/sitemap.xml') {
|
|
88
|
+
const result = await getOrGenerateSitemap();
|
|
89
|
+
const xml = result.type === 'single' ? result.xml : result.indexXml;
|
|
90
|
+
return new Response(xml, {
|
|
91
|
+
status: 200,
|
|
92
|
+
headers: { 'Content-Type': 'application/xml; charset=utf-8' },
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Handle /sitemap/N.xml (paginated sub-sitemaps)
|
|
97
|
+
const pageMatch = SITEMAP_PAGE_PATTERN.exec(pathname);
|
|
98
|
+
if (pageMatch) {
|
|
99
|
+
const result = await getOrGenerateSitemap();
|
|
100
|
+
if (result.type === 'single') {
|
|
101
|
+
// No pagination — only page 0 is valid for a single sitemap
|
|
102
|
+
const pageIndex = parseInt(pageMatch[1], 10);
|
|
103
|
+
if (pageIndex === 0) {
|
|
104
|
+
return new Response(result.xml, {
|
|
105
|
+
status: 200,
|
|
106
|
+
headers: { 'Content-Type': 'application/xml; charset=utf-8' },
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return new Response(null, { status: 404 });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const pageIndex = parseInt(pageMatch[1], 10);
|
|
113
|
+
const pageXml = result.pages.get(pageIndex);
|
|
114
|
+
if (!pageXml) {
|
|
115
|
+
return new Response(null, { status: 404 });
|
|
116
|
+
}
|
|
117
|
+
return new Response(pageXml, {
|
|
118
|
+
status: 200,
|
|
119
|
+
headers: { 'Content-Type': 'application/xml; charset=utf-8' },
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Not a sitemap URL — pass through
|
|
124
|
+
return null;
|
|
125
|
+
};
|
|
126
|
+
}
|