@timber-js/app 0.2.0-alpha.18 → 0.2.0-alpha.181
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/agent-skill.md +344 -0
- package/dist/_chunks/actions-O_LsyCE4.js +317 -0
- package/dist/_chunks/actions-O_LsyCE4.js.map +1 -0
- package/dist/_chunks/build-output-helper-DF5uScqS.js +158 -0
- package/dist/_chunks/build-output-helper-DF5uScqS.js.map +1 -0
- package/dist/_chunks/cache-api-B-lhk9p4.js +1202 -0
- package/dist/_chunks/cache-api-B-lhk9p4.js.map +1 -0
- package/dist/_chunks/canonicalize-DQHyFClh.js +248 -0
- package/dist/_chunks/canonicalize-DQHyFClh.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-D3naS3eH.js +688 -0
- package/dist/_chunks/cli-schema-sync-D3naS3eH.js.map +1 -0
- package/dist/_chunks/cloudflare-AHoWYTYr.js +1188 -0
- package/dist/_chunks/cloudflare-AHoWYTYr.js.map +1 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
- package/dist/_chunks/define-COtkxMRT.js +191 -0
- package/dist/_chunks/define-COtkxMRT.js.map +1 -0
- package/dist/_chunks/define-c4au4I9R.js +82 -0
- package/dist/_chunks/define-c4au4I9R.js.map +1 -0
- package/dist/_chunks/dist-BA3u1z3W.js +423 -0
- package/dist/_chunks/dist-BA3u1z3W.js.map +1 -0
- package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
- package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
- package/dist/_chunks/format-CfwjgPz9.js +14 -0
- package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
- package/dist/_chunks/href-validation-CMc5JRls.js +141 -0
- package/dist/_chunks/href-validation-CMc5JRls.js.map +1 -0
- package/dist/_chunks/json-lossy-check-ClNvBM_3.js +63 -0
- package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +1 -0
- package/dist/_chunks/logger-AWfuX-KJ.js +1468 -0
- package/dist/_chunks/logger-AWfuX-KJ.js.map +1 -0
- package/dist/_chunks/navigation-root-bUDZLw74.js +124 -0
- package/dist/_chunks/navigation-root-bUDZLw74.js.map +1 -0
- package/dist/_chunks/plugin-context---kTF5v8.js +315 -0
- package/dist/_chunks/plugin-context---kTF5v8.js.map +1 -0
- package/dist/_chunks/registry-DbJPKoBp.js +20 -0
- package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
- package/dist/_chunks/resolve-schema-Dz3fcFUo.js +50 -0
- package/dist/_chunks/resolve-schema-Dz3fcFUo.js.map +1 -0
- package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
- package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
- package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +119 -0
- package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +1 -0
- package/dist/_chunks/segment-classify-Byy425ng.js +176 -0
- package/dist/_chunks/segment-classify-Byy425ng.js.map +1 -0
- package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
- package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
- package/dist/_chunks/sizeof-lXffQ1Vr.js +35 -0
- package/dist/_chunks/sizeof-lXffQ1Vr.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
- package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DFvWd-EA.js} +71 -26
- package/dist/_chunks/use-query-states-DFvWd-EA.js.map +1 -0
- package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
- package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
- package/dist/_chunks/walkers-BtTlKviE.js +1002 -0
- package/dist/_chunks/walkers-BtTlKviE.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +29 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts +65 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +124 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +189 -21
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +2 -188
- package/dist/adapters/compress-module.d.ts +5 -4
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +41 -3
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +224 -172
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +6 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/adapters/types.d.ts +2 -6
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cache/cache-api.d.ts +48 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +33 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +31 -8
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +3 -326
- package/dist/cache/invalidation-epoch.d.ts +43 -0
- package/dist/cache/invalidation-epoch.d.ts.map +1 -0
- package/dist/cache/json-lossy-check.d.ts +11 -0
- package/dist/cache/json-lossy-check.d.ts.map +1 -0
- package/dist/cache/redis-handler.d.ts +140 -8
- package/dist/cache/redis-handler.d.ts.map +1 -1
- package/dist/cache/singleflight.d.ts +19 -2
- 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/stable-stringify.d.ts +9 -0
- package/dist/cache/stable-stringify.d.ts.map +1 -1
- package/dist/cache/store.d.ts +53 -0
- package/dist/cache/store.d.ts.map +1 -0
- package/dist/cache/stores/cloudflare-kv.d.ts +38 -0
- package/dist/cache/stores/cloudflare-kv.d.ts.map +1 -0
- package/dist/cache/stores/cloudflare-kv.js +29 -0
- package/dist/cache/stores/cloudflare-kv.js.map +1 -0
- package/dist/cache/stores/memory.d.ts +42 -0
- package/dist/cache/stores/memory.d.ts.map +1 -0
- package/dist/cache/stores/memory.js +90 -0
- package/dist/cache/stores/memory.js.map +1 -0
- package/dist/cache/stores/redis.d.ts +69 -0
- package/dist/cache/stores/redis.d.ts.map +1 -0
- package/dist/cache/stores/redis.js +35 -0
- package/dist/cache/stores/redis.js.map +1 -0
- package/dist/cache/stores/vercel.d.ts +36 -0
- package/dist/cache/stores/vercel.d.ts.map +1 -0
- package/dist/cache/stores/vercel.js +33 -0
- package/dist/cache/stores/vercel.js.map +1 -0
- package/dist/cache/tag-aware-handler.d.ts +52 -0
- package/dist/cache/tag-aware-handler.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +20 -10
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cdn/cloudflare-purge.d.ts +23 -0
- package/dist/cdn/cloudflare-purge.d.ts.map +1 -0
- package/dist/cdn/fastly-purge.d.ts +25 -0
- package/dist/cdn/fastly-purge.d.ts.map +1 -0
- package/dist/cdn/headers.d.ts +97 -0
- package/dist/cdn/headers.d.ts.map +1 -0
- package/dist/cdn/index.d.ts +5 -0
- package/dist/cdn/index.d.ts.map +1 -0
- package/dist/cdn/purge-store.d.ts +23 -0
- package/dist/cdn/purge-store.d.ts.map +1 -0
- package/dist/cdn/workers-cache-purge.d.ts +16 -0
- package/dist/cdn/workers-cache-purge.d.ts.map +1 -0
- package/dist/cli-schema-sync.d.ts +59 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +35 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +113 -34
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +37 -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 +29 -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 +27 -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 +28 -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 +47 -10
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +61 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +16 -27
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +21 -6
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +10 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +185 -1134
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +19 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +938 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link.d.ts +69 -60
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-api.d.ts +121 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +3 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/navigation-root.d.ts +119 -0
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts +1 -1
- 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 +99 -14
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +62 -15
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +30 -7
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +57 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/segment-update-context.d.ts +21 -0
- package/dist/client/segment-update-context.d.ts.map +1 -0
- package/dist/client/shallow-url.d.ts +10 -0
- package/dist/client/shallow-url.d.ts.map +1 -0
- package/dist/client/slot-context.d.ts +31 -0
- package/dist/client/slot-context.d.ts.map +1 -0
- package/dist/client/slot-outlet.d.ts +16 -0
- package/dist/client/slot-outlet.d.ts.map +1 -0
- package/dist/client/slot-provider.d.ts +25 -0
- package/dist/client/slot-provider.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/state.d.ts +1 -1
- package/dist/client/top-loader.d.ts +5 -5
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-cookie.d.ts +12 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/use-link-status.d.ts +5 -5
- package/dist/client/use-link-status.d.ts.map +1 -1
- package/dist/client/use-pathname.d.ts.map +1 -1
- package/dist/client/use-pending-navigation.d.ts +23 -0
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/client/use-router.d.ts.map +1 -1
- package/dist/client/use-search-params.d.ts +12 -5
- package/dist/client/use-search-params.d.ts.map +1 -1
- package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
- package/dist/client/use-segment-params.d.ts.map +1 -0
- package/dist/codec.d.ts +69 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +76 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +284 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/config-validation.d.ts +51 -0
- package/dist/config-validation.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts +58 -25
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +2 -1
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +257 -36
- package/dist/cookies/index.js.map +1 -1
- package/dist/cookies/json-cookie.d.ts +64 -0
- package/dist/cookies/json-cookie.d.ts.map +1 -0
- package/dist/cookies/validation.d.ts +34 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/dev-tools/404-page.d.ts +50 -0
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/dev-tools/browser-logs.d.ts +40 -0
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/dev-tools/dev-page-shell.d.ts +78 -0
- package/dist/dev-tools/dev-page-shell.d.ts.map +1 -0
- package/dist/dev-tools/error-page.d.ts +32 -0
- package/dist/dev-tools/error-page.d.ts.map +1 -0
- package/dist/dev-tools/holding-server.d.ts +54 -0
- package/dist/dev-tools/holding-server.d.ts.map +1 -0
- package/dist/dev-tools/hydration-overlay.d.ts +11 -0
- package/dist/dev-tools/hydration-overlay.d.ts.map +1 -0
- package/dist/dev-tools/index.d.ts +31 -0
- package/dist/dev-tools/index.d.ts.map +1 -0
- package/dist/dev-tools/instrumentation.d.ts +59 -0
- package/dist/dev-tools/instrumentation.d.ts.map +1 -0
- package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
- package/dist/dev-tools/logger.d.ts.map +1 -0
- package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +17 -3
- package/dist/dev-tools/logs.d.ts.map +1 -0
- package/dist/dev-tools/overlay.d.ts +91 -0
- package/dist/dev-tools/overlay.d.ts.map +1 -0
- package/dist/dev-tools/stack-classifier.d.ts +34 -0
- package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
- package/dist/dev-tools/terminal.d.ts +28 -0
- package/dist/dev-tools/terminal.d.ts.map +1 -0
- package/dist/fonts/ast-walk.d.ts +68 -0
- package/dist/fonts/ast-walk.d.ts.map +1 -0
- package/dist/fonts/ast.d.ts +110 -6
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +50 -0
- package/dist/fonts/bundle.d.ts.map +1 -0
- package/dist/fonts/dev-middleware.d.ts +22 -0
- package/dist/fonts/dev-middleware.d.ts.map +1 -0
- package/dist/fonts/fallbacks.d.ts +0 -7
- package/dist/fonts/fallbacks.d.ts.map +1 -1
- package/dist/fonts/google.d.ts +4 -2
- package/dist/fonts/google.d.ts.map +1 -1
- package/dist/fonts/local.d.ts +4 -4
- package/dist/fonts/local.d.ts.map +1 -1
- package/dist/fonts/paths.d.ts +43 -0
- package/dist/fonts/paths.d.ts.map +1 -0
- package/dist/fonts/pipeline.d.ts +177 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +82 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +47 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +77 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +46 -180
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9243 -14093
- package/dist/index.js.map +1 -1
- package/dist/params/codec-registry.d.ts +26 -0
- package/dist/params/codec-registry.d.ts.map +1 -0
- package/dist/params/define-schema.d.ts +81 -0
- package/dist/params/define-schema.d.ts.map +1 -0
- package/dist/params/index.d.ts +5 -0
- package/dist/params/index.d.ts.map +1 -0
- package/dist/params/index.js +34 -0
- package/dist/params/index.js.map +1 -0
- package/dist/params/resolve-schema.d.ts +34 -0
- package/dist/params/resolve-schema.d.ts.map +1 -0
- package/dist/plugin-context.d.ts +217 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +21 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +7 -3
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +43 -7
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/cache.d.ts +64 -0
- package/dist/plugins/cache.d.ts.map +1 -0
- package/dist/plugins/callsite-ast.d.ts +117 -0
- package/dist/plugins/callsite-ast.d.ts.map +1 -0
- package/dist/plugins/callsite-jsx.d.ts +35 -0
- package/dist/plugins/callsite-jsx.d.ts.map +1 -0
- package/dist/plugins/chunks.d.ts +11 -4
- package/dist/plugins/chunks.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +40 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/cloudflare-wasm.d.ts +21 -0
- package/dist/plugins/cloudflare-wasm.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +17 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +28 -4
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +16 -73
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/prebuilt-capture.d.ts +60 -0
- package/dist/plugins/prebuilt-capture.d.ts.map +1 -0
- package/dist/plugins/prebuilt-options-analysis.d.ts +40 -0
- package/dist/plugins/prebuilt-options-analysis.d.ts.map +1 -0
- package/dist/plugins/prebuilt.d.ts +82 -0
- package/dist/plugins/prebuilt.d.ts.map +1 -0
- package/dist/plugins/prerender-sugar.d.ts +42 -0
- package/dist/plugins/prerender-sugar.d.ts.map +1 -0
- package/dist/plugins/request-dep.d.ts +21 -0
- package/dist/plugins/request-dep.d.ts.map +1 -0
- 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 +29 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +5 -26
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +67 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +64 -0
- package/dist/routing/codegen-types.d.ts.map +1 -0
- package/dist/routing/codegen.d.ts +7 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts +41 -0
- package/dist/routing/convention-lint.d.ts.map +1 -0
- package/dist/routing/export-detect.d.ts +56 -0
- package/dist/routing/export-detect.d.ts.map +1 -0
- package/dist/routing/file-cache.d.ts +8 -0
- package/dist/routing/file-cache.d.ts.map +1 -0
- package/dist/routing/index.d.ts +7 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -2
- package/dist/routing/interception.d.ts +0 -5
- package/dist/routing/interception.d.ts.map +1 -1
- package/dist/routing/link-codegen.d.ts +90 -0
- package/dist/routing/link-codegen.d.ts.map +1 -0
- package/dist/routing/manifest-codegen.d.ts +32 -0
- package/dist/routing/manifest-codegen.d.ts.map +1 -0
- package/dist/routing/scanner.d.ts +1 -10
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/schema-validation.d.ts +35 -0
- package/dist/routing/schema-validation.d.ts.map +1 -0
- package/dist/routing/segment-classify.d.ts +81 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/segment-codegen.d.ts +38 -0
- package/dist/routing/segment-codegen.d.ts.map +1 -0
- package/dist/routing/types.d.ts +81 -25
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +51 -0
- package/dist/routing/walkers.d.ts.map +1 -0
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +91 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +188 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -7
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +34 -441
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/registry.d.ts +2 -2
- package/dist/search-params/registry.d.ts.map +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +89 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +3 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +2 -0
- package/dist/server/access-gate.d.ts +8 -3
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +42 -7
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts +35 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +6 -30
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +93 -11
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +8 -18
- package/dist/server/asset-headers.d.ts.map +1 -1
- package/dist/server/body-limits.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +12 -29
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/canonicalize.d.ts +10 -0
- package/dist/server/canonicalize.d.ts.map +1 -1
- package/dist/server/coalesce-tick.d.ts +40 -0
- package/dist/server/coalesce-tick.d.ts.map +1 -0
- package/dist/server/cookie-context.d.ts +170 -0
- package/dist/server/cookie-context.d.ts.map +1 -0
- package/dist/server/cookie-parsing.d.ts +65 -0
- package/dist/server/cookie-parsing.d.ts.map +1 -0
- package/dist/server/csrf.d.ts +3 -2
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-boundary.d.ts +117 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts +2 -2
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-source-map.d.ts +22 -0
- package/dist/server/dev-source-map.d.ts.map +1 -0
- package/dist/server/early-hints-sender.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -11
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +12 -7
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/flight-injection-state.d.ts +66 -0
- package/dist/server/flight-injection-state.d.ts.map +1 -0
- package/dist/server/flight-scripts.d.ts +42 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/form-data.d.ts +41 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts +242 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +82 -41
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +11 -47
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +182 -2906
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +49 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +3892 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/logger.d.ts +39 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/metadata-routes.d.ts +60 -11
- package/dist/server/metadata-routes.d.ts.map +1 -1
- package/dist/server/metadata.d.ts +8 -0
- package/dist/server/metadata.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 +119 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/param-coercion.d.ts +54 -0
- package/dist/server/param-coercion.d.ts.map +1 -0
- package/dist/server/pipeline-helpers.d.ts +95 -0
- package/dist/server/pipeline-helpers.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts +49 -0
- package/dist/server/pipeline-outcome.d.ts.map +1 -0
- package/dist/server/pipeline-phases.d.ts +59 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +140 -19
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/port-resolution.d.ts +117 -0
- package/dist/server/port-resolution.d.ts.map +1 -0
- package/dist/server/prebuilt/cache-key.d.ts +62 -0
- package/dist/server/prebuilt/cache-key.d.ts.map +1 -0
- package/dist/server/prebuilt/capture-state.d.ts +57 -0
- package/dist/server/prebuilt/capture-state.d.ts.map +1 -0
- package/dist/server/prebuilt/key-discipline.d.ts +23 -0
- package/dist/server/prebuilt/key-discipline.d.ts.map +1 -0
- package/dist/server/prebuilt/manifest-tag-index.d.ts +27 -0
- package/dist/server/prebuilt/manifest-tag-index.d.ts.map +1 -0
- package/dist/server/prebuilt/overlay.d.ts +100 -0
- package/dist/server/prebuilt/overlay.d.ts.map +1 -0
- package/dist/server/prebuilt/payload-source.d.ts +78 -0
- package/dist/server/prebuilt/payload-source.d.ts.map +1 -0
- package/dist/server/prebuilt/slots.d.ts +99 -0
- package/dist/server/prebuilt/slots.d.ts.map +1 -0
- package/dist/server/prebuilt/synthetic-store.d.ts +66 -0
- package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -0
- package/dist/server/prebuilt-builder.d.ts +120 -0
- package/dist/server/prebuilt-builder.d.ts.map +1 -0
- package/dist/server/prebuilt-runtime.d.ts +111 -0
- package/dist/server/prebuilt-runtime.d.ts.map +1 -0
- package/dist/server/primitives.d.ts +88 -43
- 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/render-utils.d.ts +25 -0
- package/dist/server/render-utils.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +62 -107
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-dep.d.ts +15 -0
- package/dist/server/request-dep.d.ts.map +1 -0
- package/dist/server/route-element-builder.d.ts +53 -25
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +25 -36
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts +12 -3
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/deny-fallback.d.ts +29 -0
- package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -0
- 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 +69 -37
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +28 -6
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +51 -0
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
- package/dist/server/rsc-entry/rsc-payload.d.ts +6 -6
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +25 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +36 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +89 -0
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sensitive-fields.d.ts +74 -0
- package/dist/server/sensitive-fields.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +66 -5
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +121 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -0
- package/dist/server/ssr-entry.d.ts +2 -43
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +64 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/state-tree-diff.d.ts +72 -9
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +22 -11
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +47 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +44 -9
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +69 -30
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/tree-match.d.ts +49 -0
- package/dist/server/tree-match.d.ts.map +1 -0
- package/dist/server/types.d.ts +71 -6
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/utils/escape-html.d.ts +14 -0
- package/dist/server/utils/escape-html.d.ts.map +1 -0
- package/dist/server/utils/mdx-file.d.ts +15 -0
- package/dist/server/utils/mdx-file.d.ts.map +1 -0
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/server/workers-cache-bridge.d.ts +26 -0
- package/dist/server/workers-cache-bridge.d.ts.map +1 -0
- package/dist/shared/href-validation.d.ts +49 -0
- package/dist/shared/href-validation.d.ts.map +1 -0
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shared/redirect-type.d.ts +17 -0
- package/dist/shared/redirect-type.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 +53 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/image.d.ts +120 -120
- package/dist/shims/image.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +35 -11
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +11 -5
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/docs/api/30-api-server.mdx +233 -0
- package/docs/api/31-api-client.mdx +161 -0
- package/docs/api/32-api-cache.mdx +311 -0
- package/docs/api/33-api-search-params.mdx +154 -0
- package/docs/api/34-api-config.mdx +325 -0
- package/docs/api/35-api-typescript.mdx +170 -0
- package/docs/api/36-cli.mdx +143 -0
- package/docs/learn/00-introduction.mdx +109 -0
- package/docs/learn/01-quick-start.mdx +94 -0
- package/docs/learn/02-pages-and-layouts.mdx +147 -0
- package/docs/learn/03-fetching-data.mdx +211 -0
- package/docs/learn/03b-access-control.mdx +130 -0
- package/docs/learn/04-loading-states.mdx +67 -0
- package/docs/learn/04b-the-flush-point.mdx +115 -0
- package/docs/learn/05-typed-params.mdx +275 -0
- package/docs/learn/06-forms-and-actions.mdx +146 -0
- package/docs/learn/07-typed-routes.mdx +127 -0
- package/docs/learn/08-streaming.mdx +146 -0
- package/docs/learn/09-caching.mdx +252 -0
- package/docs/learn/10-middleware.mdx +157 -0
- package/docs/learn/11-error-handling.mdx +156 -0
- package/docs/learn/12-client-navigation.mdx +176 -0
- package/docs/learn/13-configuration.mdx +162 -0
- package/docs/learn/14-deploying.mdx +264 -0
- package/docs/more/01-advanced-routing.mdx +173 -0
- package/docs/more/02-advanced-forms.mdx +137 -0
- package/docs/more/03-coming-from-nextjs.mdx +186 -0
- package/docs/more/04-metadata-and-fonts.mdx +193 -0
- package/docs/more/04b-mdx.mdx +209 -0
- package/docs/more/05-content-collections.mdx +90 -0
- package/docs/more/06-instrumentation.mdx +214 -0
- package/docs/more/07-security.mdx +129 -0
- package/docs/more/08-developer-experience.mdx +134 -0
- package/docs/more/40-why-timber.mdx +50 -0
- package/docs/more/41-timber-vs-nextjs.mdx +81 -0
- package/docs/more/42-timber-vs-others.mdx +68 -0
- package/docs/more/50-ai-agent-instructions.mdx +169 -0
- package/llms.txt +55 -0
- package/package.json +105 -26
- package/src/adapters/build-output-helper.ts +199 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +204 -0
- package/src/adapters/cloudflare.ts +620 -129
- package/src/adapters/compress-module.ts +27 -92
- package/src/adapters/nitro.ts +266 -122
- package/src/adapters/raw-imports.d.ts +5 -0
- package/src/adapters/shared.ts +68 -0
- package/src/adapters/types.ts +2 -7
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +107 -0
- package/src/cache/handler-store.ts +76 -0
- package/src/cache/index.ts +114 -21
- package/src/cache/invalidation-epoch.ts +93 -0
- package/src/cache/json-lossy-check.ts +75 -0
- package/src/cache/redis-handler.ts +197 -19
- package/src/cache/singleflight.ts +64 -6
- package/src/cache/sizeof.ts +33 -0
- package/src/cache/stable-stringify.ts +65 -2
- package/src/cache/store.ts +71 -0
- package/src/cache/stores/cloudflare-kv.ts +52 -0
- package/src/cache/stores/memory.ts +125 -0
- package/src/cache/stores/redis.ts +97 -0
- package/src/cache/stores/vercel.ts +59 -0
- package/src/cache/tag-aware-handler.ts +237 -0
- package/src/cache/timber-cache.ts +161 -36
- package/src/cdn/cloudflare-purge.ts +50 -0
- package/src/cdn/fastly-purge.ts +63 -0
- package/src/cdn/headers.ts +153 -0
- package/src/cdn/index.ts +17 -0
- package/src/cdn/purge-store.ts +34 -0
- package/src/cdn/workers-cache-purge.ts +30 -0
- package/src/cli-schema-sync.ts +401 -0
- package/src/cli.ts +167 -34
- package/src/client/browser-dev.ts +156 -1
- package/src/client/browser-entry/action-dispatch.ts +124 -0
- package/src/client/browser-entry/hmr.ts +70 -0
- package/src/client/browser-entry/hydrate.ts +187 -0
- package/src/client/browser-entry/index.ts +113 -0
- package/src/client/browser-entry/post-hydration.ts +110 -0
- package/src/client/browser-entry/router-init.ts +286 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +50 -0
- package/src/client/error-boundary.tsx +127 -22
- package/src/client/error-reconstituter.tsx +79 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +21 -6
- package/src/client/index.ts +67 -45
- package/src/client/internal.ts +58 -0
- package/src/client/link.tsx +349 -150
- package/src/client/navigation-api.ts +345 -0
- package/src/client/navigation-context.ts +15 -7
- package/src/client/navigation-root.tsx +355 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +589 -215
- package/src/client/rsc-fetch.ts +251 -34
- package/src/client/segment-cache.ts +105 -17
- package/src/client/segment-outlet.tsx +141 -0
- package/src/client/segment-update-context.ts +42 -0
- package/src/client/shallow-url.ts +22 -0
- package/src/client/slot-context.ts +50 -0
- package/src/client/slot-outlet.tsx +22 -0
- package/src/client/slot-provider.tsx +32 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/state.ts +2 -2
- package/src/client/top-loader.tsx +11 -9
- package/src/client/use-cookie.ts +60 -15
- package/src/client/use-link-status.ts +7 -7
- package/src/client/use-pathname.ts +1 -0
- package/src/client/use-pending-navigation.ts +40 -0
- package/src/client/use-query-states.ts +108 -10
- package/src/client/use-router.ts +4 -1
- package/src/client/use-search-params.ts +31 -44
- package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
- package/src/codec.ts +149 -0
- package/src/config-types.ts +282 -0
- package/src/config-validation.ts +330 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +217 -53
- package/src/cookies/index.ts +12 -1
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +192 -0
- package/src/dev-tools/404-page.ts +286 -0
- package/src/dev-tools/browser-logs.ts +55 -0
- package/src/dev-tools/dev-page-shell.ts +260 -0
- package/src/dev-tools/error-page.ts +331 -0
- package/src/dev-tools/holding-server.ts +187 -0
- package/src/dev-tools/hydration-overlay.ts +158 -0
- package/src/dev-tools/index.ts +83 -0
- package/src/dev-tools/instrumentation.ts +213 -0
- package/src/{server/dev-logger.ts → dev-tools/logger.ts} +33 -51
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +122 -26
- package/src/dev-tools/overlay.ts +469 -0
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/dev-tools/terminal.ts +182 -0
- package/src/fonts/ast-walk.ts +235 -0
- package/src/fonts/ast.ts +477 -126
- package/src/fonts/bundle.ts +138 -0
- package/src/fonts/dev-middleware.ts +85 -0
- package/src/fonts/fallbacks.ts +0 -23
- package/src/fonts/google.ts +100 -18
- package/src/fonts/local.ts +9 -8
- package/src/fonts/paths.ts +58 -0
- package/src/fonts/pipeline.ts +348 -0
- package/src/fonts/transform.ts +311 -0
- package/src/fonts/types.ts +52 -1
- package/src/fonts/virtual-modules.ts +179 -0
- package/src/index.ts +446 -352
- package/src/params/codec-registry.ts +34 -0
- package/src/params/define-schema.ts +115 -0
- package/src/params/index.ts +17 -0
- package/src/params/resolve-schema.ts +84 -0
- package/src/plugin-context.ts +432 -0
- package/src/plugins/adapter-build.ts +220 -7
- package/src/plugins/build-manifest.ts +177 -23
- package/src/plugins/build-report.ts +253 -35
- package/src/plugins/cache.ts +243 -0
- package/src/plugins/callsite-ast.ts +472 -0
- package/src/plugins/callsite-jsx.ts +243 -0
- package/src/plugins/chunks.ts +74 -5
- package/src/plugins/client-chunks.ts +185 -0
- package/src/plugins/cloudflare-wasm.ts +141 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +284 -94
- package/src/plugins/entries.ts +134 -16
- package/src/plugins/fonts.ts +225 -660
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/prebuilt-capture.ts +217 -0
- package/src/plugins/prebuilt-options-analysis.ts +175 -0
- package/src/plugins/prebuilt.ts +655 -0
- package/src/plugins/prerender-sugar.ts +328 -0
- package/src/plugins/request-dep.ts +458 -0
- package/src/plugins/routing.ts +237 -241
- package/src/plugins/server-bundle.ts +89 -12
- package/src/plugins/shims.ts +241 -64
- package/src/plugins/static-build.ts +15 -90
- package/src/routing/codegen-shared.ts +115 -0
- package/src/routing/codegen-types.ts +65 -0
- package/src/routing/codegen.ts +372 -178
- package/src/routing/convention-lint.ts +394 -0
- package/src/routing/export-detect.ts +304 -0
- package/src/routing/file-cache.ts +23 -0
- package/src/routing/index.ts +10 -1
- package/src/routing/interception.ts +3 -22
- package/src/routing/link-codegen.ts +313 -0
- package/src/routing/manifest-codegen.ts +287 -0
- package/src/routing/scanner.ts +338 -189
- package/src/routing/schema-validation.ts +155 -0
- package/src/routing/segment-classify.ts +223 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/types.ts +82 -25
- package/src/routing/walkers.ts +90 -0
- package/src/rsc-runtime/rsc.ts +9 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/schema-bridge.ts +253 -0
- package/src/search-params/define.ts +576 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +101 -0
- package/src/segment-params/define.ts +249 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +111 -34
- package/src/server/action-client.ts +120 -29
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +123 -33
- package/src/server/actions.ts +48 -54
- package/src/server/als-registry.ts +137 -20
- package/src/server/asset-headers.ts +15 -37
- package/src/server/body-limits.ts +10 -2
- package/src/server/build-manifest.ts +19 -56
- package/src/server/canonicalize.ts +6 -3
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +34 -7
- package/src/server/cookie-context.ts +484 -0
- package/src/server/cookie-parsing.ts +163 -0
- package/src/server/csrf.ts +39 -6
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-boundary.ts +314 -0
- package/src/server/deny-renderer.ts +85 -77
- package/src/server/dev-source-map.ts +31 -0
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/early-hints.ts +37 -27
- package/src/server/error-boundary-wrapper.ts +61 -22
- package/src/server/fallback-error.ts +79 -102
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/form-data.ts +124 -12
- package/src/server/html-injector-core.ts +495 -0
- package/src/server/html-injectors.ts +271 -254
- package/src/server/index.ts +31 -185
- package/src/server/internal.ts +181 -0
- package/src/server/logger.ts +72 -36
- package/src/server/metadata-routes.ts +205 -24
- package/src/server/metadata.ts +21 -0
- package/src/server/middleware-runner.ts +31 -4
- package/src/server/node-stream-transforms.ts +336 -0
- package/src/server/param-coercion.ts +207 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +45 -18
- package/src/server/pipeline-metadata.ts +14 -0
- package/src/server/pipeline-outcome.ts +197 -0
- package/src/server/pipeline-phases.ts +545 -0
- package/src/server/pipeline.ts +274 -382
- package/src/server/port-resolution.ts +215 -0
- package/src/server/prebuilt/cache-key.ts +298 -0
- package/src/server/prebuilt/capture-state.ts +89 -0
- package/src/server/prebuilt/key-discipline.ts +53 -0
- package/src/server/prebuilt/manifest-tag-index.ts +46 -0
- package/src/server/prebuilt/overlay.ts +256 -0
- package/src/server/prebuilt/payload-source.ts +201 -0
- package/src/server/prebuilt/slots.ts +190 -0
- package/src/server/prebuilt/synthetic-store.ts +121 -0
- package/src/server/prebuilt-builder.ts +809 -0
- package/src/server/prebuilt-runtime.ts +815 -0
- package/src/server/primitives.ts +160 -83
- package/src/server/render-timeout.ts +108 -0
- package/src/server/render-utils.ts +31 -0
- package/src/server/request-context.ts +170 -337
- package/src/server/request-dep.ts +37 -0
- package/src/server/route-element-builder.ts +699 -295
- package/src/server/route-handler.ts +31 -4
- package/src/server/route-matcher.ts +158 -277
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +69 -32
- package/src/server/rsc-entry/deny-fallback.ts +92 -0
- package/src/server/rsc-entry/error-renderer.ts +306 -89
- package/src/server/rsc-entry/helpers.ts +210 -85
- package/src/server/rsc-entry/index.ts +332 -332
- package/src/server/rsc-entry/render-route.ts +300 -0
- package/src/server/rsc-entry/revalidate-renderer.ts +349 -0
- package/src/server/rsc-entry/rsc-payload.ts +102 -42
- package/src/server/rsc-entry/rsc-stream.ts +93 -13
- package/src/server/rsc-entry/ssr-bridge.ts +18 -5
- package/src/server/rsc-entry/ssr-renderer.ts +275 -43
- package/src/server/rsc-entry/wrap-action-dispatch.ts +186 -0
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -0
- package/src/server/server-only-guard-noop.js +3 -0
- package/src/server/sitemap-generator.ts +345 -0
- package/src/server/sitemap-handler.ts +157 -0
- package/src/server/slot-resolver.ts +574 -250
- package/src/server/ssr-bridge-types.ts +124 -0
- package/src/server/ssr-entry.ts +206 -86
- package/src/server/ssr-render.ts +345 -86
- package/src/server/ssr-wrappers.tsx +141 -0
- package/src/server/state-tree-diff.ts +177 -30
- package/src/server/status-code-resolver.ts +115 -130
- package/src/server/stream-utils.ts +288 -0
- package/src/server/tracing.ts +126 -14
- package/src/server/tree-builder.ts +214 -90
- package/src/server/tree-match.ts +262 -0
- package/src/server/types.ts +78 -9
- package/src/server/utils/escape-html.ts +20 -0
- package/src/server/utils/mdx-file.ts +22 -0
- package/src/server/version-skew.ts +104 -0
- package/src/server/workers-cache-bridge.ts +33 -0
- package/src/shared/href-validation.ts +159 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shared/redirect-type.ts +17 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +122 -1
- package/src/shims/navigation-client.ts +51 -29
- package/src/shims/navigation.ts +14 -7
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-B3Gypr3D.js +0 -108
- package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
- package/dist/_chunks/format-RyoGQL74.js +0 -164
- package/dist/_chunks/format-RyoGQL74.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js +0 -676
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/metadata-routes-Cjmvi3rQ.js +0 -153
- package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
- package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
- package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.js +0 -187
- package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/adapters/cloudflare.js.map +0 -1
- package/dist/cache/index.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/head.d.ts +0 -16
- package/dist/client/head.d.ts.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/segment-merger.d.ts +0 -119
- package/dist/client/segment-merger.d.ts.map +0 -1
- package/dist/client/stale-reload.d.ts +0 -44
- package/dist/client/stale-reload.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts +0 -74
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts +0 -26
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/client/use-params.d.ts.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dev-error-overlay.d.ts +0 -60
- package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
- package/dist/plugins/dev-logs.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/plugins/server-action-exports.d.ts +0 -26
- package/dist/plugins/server-action-exports.d.ts.map +0 -1
- package/dist/routing/status-file-lint.d.ts +0 -33
- package/dist/routing/status-file-lint.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/server/client-module-map.d.ts +0 -47
- package/dist/server/client-module-map.d.ts.map +0 -1
- package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
- package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
- package/dist/server/dev-logger.d.ts.map +0 -1
- package/dist/server/dev-span-processor.d.ts +0 -29
- package/dist/server/dev-span-processor.d.ts.map +0 -1
- package/dist/server/dev-warnings.d.ts +0 -129
- package/dist/server/dev-warnings.d.ts.map +0 -1
- package/dist/server/flush.d.ts +0 -74
- package/dist/server/flush.d.ts.map +0 -1
- package/dist/server/manifest-status-resolver.d.ts +0 -58
- package/dist/server/manifest-status-resolver.d.ts.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/utils/directive-parser.d.ts +0 -70
- package/dist/utils/directive-parser.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -103
- package/src/client/browser-entry.ts +0 -678
- package/src/client/head.ts +0 -61
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/segment-merger.ts +0 -339
- package/src/client/stale-reload.ts +0 -87
- package/src/client/transition-root.tsx +0 -166
- package/src/client/use-navigation-pending.ts +0 -38
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dev-error-overlay.ts +0 -230
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/plugins/server-action-exports.ts +0 -220
- package/src/routing/status-file-lint.ts +0 -112
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/codecs.ts +0 -153
- package/src/search-params/create.ts +0 -321
- package/src/server/client-module-map.ts +0 -58
- package/src/server/dev-fetch-instrumentation.ts +0 -96
- package/src/server/dev-span-processor.ts +0 -78
- package/src/server/dev-warnings.ts +0 -283
- package/src/server/flush.ts +0 -182
- package/src/server/manifest-status-resolver.ts +0 -215
- package/src/server/prerender.ts +0 -139
- package/src/utils/directive-parser.ts +0 -529
|
@@ -0,0 +1,1002 @@
|
|
|
1
|
+
import { n as classifyUrlSegment } from "./segment-classify-Byy425ng.js";
|
|
2
|
+
import { n as findSchemaFile, r as parseExistingSchemaKeys } from "./cli-schema-sync-D3naS3eH.js";
|
|
3
|
+
import { parseAst } from "vite";
|
|
4
|
+
import { join, posix, relative } from "node:path";
|
|
5
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
6
|
+
//#region src/routing/codegen-shared.ts
|
|
7
|
+
/**
|
|
8
|
+
* Shared codegen helpers — import-path computation, codec chain type
|
|
9
|
+
* builder, and searchParams type formatter.
|
|
10
|
+
*
|
|
11
|
+
* Extracted from `codegen.ts` so `link-codegen.ts` can use the same
|
|
12
|
+
* helpers without a cyclic import.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Compute a relative import specifier for a codec/page file, stripping
|
|
16
|
+
* the .ts/.tsx extension and resolving against the codegen output dir.
|
|
17
|
+
*/
|
|
18
|
+
function codecImportPath(codecFilePath, importBase) {
|
|
19
|
+
const absPath = codecFilePath.replace(/\.(ts|tsx)$/, "");
|
|
20
|
+
if (importBase) return "./" + relative(importBase, absPath).replace(/\\/g, "/");
|
|
21
|
+
return "./" + posix.basename(absPath);
|
|
22
|
+
}
|
|
23
|
+
/** Name of the shared helper type emitted at the top of the .d.ts. */
|
|
24
|
+
var RESOLVE_SEGMENT_FIELD_TYPE_NAME = "_TimberResolveSegmentField";
|
|
25
|
+
/**
|
|
26
|
+
* Helper type emitted once at the top of the generated `.d.ts` and
|
|
27
|
+
* referenced by every codec-chain conditional. Without this shared
|
|
28
|
+
* helper, the inline expansion would duplicate the fallback branch on
|
|
29
|
+
* every step and grow O(2^N) in chain depth (a single deep nested route
|
|
30
|
+
* could blow up the file size and TS performance). With the helper,
|
|
31
|
+
* each step reuses the named type and growth is O(N).
|
|
32
|
+
*
|
|
33
|
+
* The helper is a 2-arg conditional: given a typeof import expression
|
|
34
|
+
* (`Def`), a key (`K`), and a fallback (`F`), it returns `T[K]` if
|
|
35
|
+
* `Def extends ParamsDefinition<T>` and `K extends keyof T`, otherwise
|
|
36
|
+
* `F`. The codec chain composes calls to this helper.
|
|
37
|
+
*/
|
|
38
|
+
function emitResolveSegmentFieldHelper() {
|
|
39
|
+
return [
|
|
40
|
+
`type ${RESOLVE_SEGMENT_FIELD_TYPE_NAME}<Def, K extends string, F> =`,
|
|
41
|
+
` Def extends import('@timber-js/app/segment-params').ParamsDefinition<infer T>`,
|
|
42
|
+
` ? K extends keyof T ? T[K] : F`,
|
|
43
|
+
` : F;`
|
|
44
|
+
].join("\n");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build a TypeScript type expression that resolves a single param's
|
|
48
|
+
* codec by walking a chain of params.ts files in priority order.
|
|
49
|
+
*
|
|
50
|
+
* Each entry in the chain emits one application of the shared
|
|
51
|
+
* `_TimberResolveSegmentField` helper type. Composing N applications
|
|
52
|
+
* grows linearly with chain depth (O(N) characters), unlike an inline
|
|
53
|
+
* conditional that would duplicate the fallback in each branch and
|
|
54
|
+
* grow O(2^N).
|
|
55
|
+
*
|
|
56
|
+
* The closest match (position 0 in the chain) is checked first; if its
|
|
57
|
+
* `segmentParams` definition declares the key, its inferred type wins.
|
|
58
|
+
* Otherwise we fall through to the next entry, and finally to the
|
|
59
|
+
* provided fallback. See TIM-834.
|
|
60
|
+
*/
|
|
61
|
+
function buildCodecChainType(p, importBase, fallback) {
|
|
62
|
+
const files = p.codecFilePaths;
|
|
63
|
+
if (!files || files.length === 0) return fallback;
|
|
64
|
+
const key = JSON.stringify(p.name);
|
|
65
|
+
let inner = fallback;
|
|
66
|
+
for (let i = files.length - 1; i >= 0; i--) inner = `${RESOLVE_SEGMENT_FIELD_TYPE_NAME}<(typeof import('${codecImportPath(files[i], importBase)}'))['segmentParams'], ${key}, ${inner}>`;
|
|
67
|
+
return inner;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Build a TypeScript type expression for a single param using the global
|
|
71
|
+
* schema's InferCodecType. Falls back to the param's base type when
|
|
72
|
+
* schema doesn't declare this param (schemas are opt-in per key).
|
|
73
|
+
*
|
|
74
|
+
* Uses `infer` to extract the codec value rather than direct indexing
|
|
75
|
+
* because TypeScript doesn't narrow index validity inside a conditional
|
|
76
|
+
* type's true branch — `typeof schema.segmentParams[K]` produces TS2538
|
|
77
|
+
* even when the condition proves K is a valid key. In .d.ts files that
|
|
78
|
+
* error is suppressed and the type silently becomes `any`.
|
|
79
|
+
*/
|
|
80
|
+
function buildSchemaParamType(p, fallback) {
|
|
81
|
+
return `typeof schema['segmentParams'] extends Record<${JSON.stringify(p.bracketName)}, infer V> ? InferCodecType<V> : ${fallback ?? p.type}`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Format the searchParams type for a route entry.
|
|
85
|
+
*
|
|
86
|
+
* When a page.tsx (or params.ts) exports searchParams, we reference its
|
|
87
|
+
* inferred type via an import type. The import path is relative to
|
|
88
|
+
* `importBase` (the directory where the .d.ts will be written). When
|
|
89
|
+
* importBase is undefined, falls back to a bare relative path.
|
|
90
|
+
*/
|
|
91
|
+
function formatSearchParamsType(route, importBase) {
|
|
92
|
+
if (route.hasSearchParams && route.searchParamsPagePath) return `(typeof import('${codecImportPath(route.searchParamsPagePath, importBase)}'))['searchParams'] extends import('@timber-js/app/search-params').SearchParamsDefinition<infer T> ? T : never`;
|
|
93
|
+
return "{}";
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/routing/file-cache.ts
|
|
97
|
+
var cache = /* @__PURE__ */ new Map();
|
|
98
|
+
/**
|
|
99
|
+
* Read a file's text content, returning a cached copy when the file
|
|
100
|
+
* hasn't been modified since the last read (checked via mtime + size).
|
|
101
|
+
*
|
|
102
|
+
* Falls back to a fresh read on any stat/read error.
|
|
103
|
+
*/
|
|
104
|
+
function readFileCached(filePath) {
|
|
105
|
+
try {
|
|
106
|
+
const stat = statSync(filePath);
|
|
107
|
+
const entry = cache.get(filePath);
|
|
108
|
+
if (entry && entry.mtimeMs === stat.mtimeMs && entry.size === stat.size) return entry.content;
|
|
109
|
+
const content = readFileSync(filePath, "utf-8");
|
|
110
|
+
cache.set(filePath, {
|
|
111
|
+
mtimeMs: stat.mtimeMs,
|
|
112
|
+
size: stat.size,
|
|
113
|
+
content
|
|
114
|
+
});
|
|
115
|
+
return content;
|
|
116
|
+
} catch {
|
|
117
|
+
cache.delete(filePath);
|
|
118
|
+
return readFileSync(filePath, "utf-8");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/routing/export-detect.ts
|
|
123
|
+
/**
|
|
124
|
+
* AST-based export detection for route files.
|
|
125
|
+
*
|
|
126
|
+
* Uses Vite's `parseAst` (backed by oxc) to precisely detect named and
|
|
127
|
+
* default exports, replacing the regex-based approach that was fragile
|
|
128
|
+
* with TypeScript syntax (type exports, `as` aliases, comments, etc.).
|
|
129
|
+
*/
|
|
130
|
+
function tryParse(source) {
|
|
131
|
+
try {
|
|
132
|
+
return parseAst(source, { lang: "tsx" });
|
|
133
|
+
} catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Collect all named export identifiers from a parsed program.
|
|
139
|
+
* Handles: `export function X`, `export const X`, `export { X }`,
|
|
140
|
+
* `export { X } from '...'`, `export { Y as X }`.
|
|
141
|
+
*/
|
|
142
|
+
function collectNamedExports(program) {
|
|
143
|
+
const names = /* @__PURE__ */ new Set();
|
|
144
|
+
for (const stmt of program.body) {
|
|
145
|
+
if (stmt.type !== "ExportNamedDeclaration") continue;
|
|
146
|
+
if (stmt.exportKind === "type") continue;
|
|
147
|
+
if (stmt.declaration) {
|
|
148
|
+
if (stmt.declaration.id?.name) names.add(stmt.declaration.id.name);
|
|
149
|
+
if (stmt.declaration.declarations) {
|
|
150
|
+
for (const decl of stmt.declaration.declarations) if (decl.id?.name) names.add(decl.id.name);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (stmt.specifiers) for (const spec of stmt.specifiers) {
|
|
154
|
+
if (spec.exportKind === "type") continue;
|
|
155
|
+
if (spec.exported?.name && spec.exported.name !== "default") names.add(spec.exported.name);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return names;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check whether a program has a default export.
|
|
162
|
+
* Handles: `export default ...`, `export { X as default }`,
|
|
163
|
+
* `export { default } from '...'`.
|
|
164
|
+
*/
|
|
165
|
+
function hasDefaultExport(program) {
|
|
166
|
+
for (const stmt of program.body) {
|
|
167
|
+
if (stmt.type === "ExportDefaultDeclaration") return true;
|
|
168
|
+
if (stmt.type === "ExportNamedDeclaration" && stmt.specifiers) {
|
|
169
|
+
for (const spec of stmt.specifiers) if (spec.exported?.name === "default") return true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Check whether a program has any bare `export * from '...'` declarations.
|
|
176
|
+
* Excludes `export * as X from '...'` (namespace re-exports) since those
|
|
177
|
+
* create a namespace object, not individual top-level exports.
|
|
178
|
+
*/
|
|
179
|
+
function hasStarExport(program) {
|
|
180
|
+
return program.body.some((stmt) => stmt.type === "ExportAllDeclaration" && !stmt.exported && stmt.exportKind !== "type");
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Check if a file exports a specific named export.
|
|
184
|
+
* Returns false if the file doesn't exist or can't be parsed.
|
|
185
|
+
*/
|
|
186
|
+
function fileHasExport(filePath, exportName) {
|
|
187
|
+
if (!existsSync(filePath)) return false;
|
|
188
|
+
try {
|
|
189
|
+
const program = tryParse(readFileCached(filePath));
|
|
190
|
+
if (!program) return false;
|
|
191
|
+
return collectNamedExports(program).has(exportName);
|
|
192
|
+
} catch {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Check if a file has any of the given named exports.
|
|
198
|
+
* Returns the set of matching export names.
|
|
199
|
+
*/
|
|
200
|
+
function fileHasAnyExport(filePath, exportNames) {
|
|
201
|
+
const matches = /* @__PURE__ */ new Set();
|
|
202
|
+
try {
|
|
203
|
+
const program = tryParse(readFileCached(filePath));
|
|
204
|
+
if (!program) return matches;
|
|
205
|
+
const exports = collectNamedExports(program);
|
|
206
|
+
for (const name of exportNames) if (exports.has(name)) matches.add(name);
|
|
207
|
+
} catch {}
|
|
208
|
+
return matches;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Check if a file has a default export.
|
|
212
|
+
* Returns false if the file doesn't exist or can't be parsed.
|
|
213
|
+
*/
|
|
214
|
+
function fileHasDefaultExport(filePath) {
|
|
215
|
+
if (!existsSync(filePath)) return false;
|
|
216
|
+
try {
|
|
217
|
+
const program = tryParse(readFileCached(filePath));
|
|
218
|
+
if (!program) return false;
|
|
219
|
+
return hasDefaultExport(program);
|
|
220
|
+
} catch {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Check if a file has any `export * from '...'` declarations.
|
|
226
|
+
* Returns false if the file doesn't exist or can't be parsed.
|
|
227
|
+
*/
|
|
228
|
+
function fileHasStarExport(filePath) {
|
|
229
|
+
if (!existsSync(filePath)) return false;
|
|
230
|
+
try {
|
|
231
|
+
const program = tryParse(readFileCached(filePath));
|
|
232
|
+
if (!program) return false;
|
|
233
|
+
return hasStarExport(program);
|
|
234
|
+
} catch {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function extractLiteralValue(node) {
|
|
239
|
+
if (!node) return void 0;
|
|
240
|
+
const n = node;
|
|
241
|
+
if (n.type === "Literal") return n.value;
|
|
242
|
+
if (n.type === "UnaryExpression" && n.operator === "-" && n.argument?.type === "Literal") return -n.argument.value;
|
|
243
|
+
if (n.type === "ArrayExpression") {
|
|
244
|
+
const elements = n.elements;
|
|
245
|
+
if (!elements) return void 0;
|
|
246
|
+
const result = [];
|
|
247
|
+
for (const el of elements) {
|
|
248
|
+
const v = extractLiteralValue(el);
|
|
249
|
+
if (v === void 0) return void 0;
|
|
250
|
+
result.push(v);
|
|
251
|
+
}
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function extractObjectLiteral(node) {
|
|
256
|
+
if (node.type !== "ObjectExpression") return void 0;
|
|
257
|
+
const props = node.properties;
|
|
258
|
+
if (!props) return void 0;
|
|
259
|
+
const result = {};
|
|
260
|
+
for (const prop of props) {
|
|
261
|
+
const p = prop;
|
|
262
|
+
if (p.type === "SpreadElement") return void 0;
|
|
263
|
+
if (p.type !== "Property" || p.computed) return void 0;
|
|
264
|
+
const key = p.key?.type === "Identifier" ? p.key.name : p.key?.type === "Literal" ? String(p.key.value) : void 0;
|
|
265
|
+
if (!key) return void 0;
|
|
266
|
+
const value = extractLiteralValue(p.value);
|
|
267
|
+
if (value === void 0) return void 0;
|
|
268
|
+
result[key] = value;
|
|
269
|
+
}
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Extract the value of `export const prerender` from a file.
|
|
274
|
+
* Returns undefined if the file doesn't export `prerender` or can't be parsed.
|
|
275
|
+
*
|
|
276
|
+
* Supports:
|
|
277
|
+
* export const prerender = true;
|
|
278
|
+
* export const prerender = false;
|
|
279
|
+
* export const prerender = { ttl: 3600, tags: ['docs'] };
|
|
280
|
+
*/
|
|
281
|
+
function getPrerenderExport(filePath) {
|
|
282
|
+
if (!existsSync(filePath)) return void 0;
|
|
283
|
+
try {
|
|
284
|
+
const program = tryParse(readFileCached(filePath));
|
|
285
|
+
if (!program) return void 0;
|
|
286
|
+
for (const stmt of program.body) {
|
|
287
|
+
if (stmt.type !== "ExportNamedDeclaration") continue;
|
|
288
|
+
if (stmt.exportKind === "type") continue;
|
|
289
|
+
if (!stmt.declaration) continue;
|
|
290
|
+
const decl = stmt.declaration;
|
|
291
|
+
if (decl.type !== "VariableDeclaration") continue;
|
|
292
|
+
const declarations = decl.declarations;
|
|
293
|
+
if (!declarations) continue;
|
|
294
|
+
for (const d of declarations) {
|
|
295
|
+
if (d.id?.name !== "prerender" || !d.init) continue;
|
|
296
|
+
const init = d.init;
|
|
297
|
+
if (init.type === "Literal" && typeof init.value === "boolean") return init.value;
|
|
298
|
+
if (init.type === "ObjectExpression") {
|
|
299
|
+
const obj = extractObjectLiteral(init);
|
|
300
|
+
if (!obj) return void 0;
|
|
301
|
+
const result = {};
|
|
302
|
+
if ("ttl" in obj && typeof obj.ttl === "number") result.ttl = obj.ttl;
|
|
303
|
+
if ("tags" in obj && Array.isArray(obj.tags) && obj.tags.every((t) => typeof t === "string")) result.tags = obj.tags;
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return;
|
|
310
|
+
} catch {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Check if a file starts with a specific directive (e.g. "use client").
|
|
316
|
+
* Directives are string literal expression statements at the top of the file.
|
|
317
|
+
*/
|
|
318
|
+
function fileHasDirective(filePath, directive) {
|
|
319
|
+
if (!existsSync(filePath)) return false;
|
|
320
|
+
try {
|
|
321
|
+
const program = tryParse(readFileCached(filePath));
|
|
322
|
+
if (!program) return false;
|
|
323
|
+
for (const stmt of program.body) {
|
|
324
|
+
if (stmt.type !== "ExpressionStatement") break;
|
|
325
|
+
const expr = stmt.expression;
|
|
326
|
+
if (expr?.type !== "Literal" || typeof expr.value !== "string") break;
|
|
327
|
+
if (expr.value === directive) return true;
|
|
328
|
+
}
|
|
329
|
+
return false;
|
|
330
|
+
} catch {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/routing/link-codegen.ts
|
|
336
|
+
/** Shared Link base-props type literal used in every emitted call signature. */
|
|
337
|
+
var LINK_BASE_PROPS_TYPE = "Omit<import('react').AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> & { prefetch?: boolean; scroll?: boolean; preserveSearchParams?: true | string[]; onNavigate?: import('./client/link.js').OnNavigateHandler; children?: import('react').ReactNode }";
|
|
338
|
+
/**
|
|
339
|
+
* Build a TypeScript template literal pattern for a dynamic route.
|
|
340
|
+
* e.g. '/products/[id]' → '/products/${string}'
|
|
341
|
+
* '/blog/[...slug]' → '/blog/${string}'
|
|
342
|
+
* '/docs/[[...path]]' → '/docs/${string}' (also matches /docs)
|
|
343
|
+
* '/[org]/[repo]' → '/${string}/${string}'
|
|
344
|
+
*/
|
|
345
|
+
function buildResolvedPattern(route) {
|
|
346
|
+
return route.urlPath.split("/").map((part) => {
|
|
347
|
+
const seg = classifyUrlSegment(part);
|
|
348
|
+
switch (seg.kind) {
|
|
349
|
+
case "catch-all":
|
|
350
|
+
case "optional-catch-all": return "${string}";
|
|
351
|
+
case "dynamic": return `${seg.prefix ?? ""}\${string}${seg.suffix ?? ""}`;
|
|
352
|
+
default: return part;
|
|
353
|
+
}
|
|
354
|
+
}).join("/");
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Format the segmentParams type for Link overloads.
|
|
358
|
+
*
|
|
359
|
+
* Link params accept `string | number` for single dynamic segments
|
|
360
|
+
* (convenience — values are stringified at runtime). Catch-all and
|
|
361
|
+
* optional catch-all remain `string[]` / `string[] | undefined`.
|
|
362
|
+
*
|
|
363
|
+
* When the segment's params chain (TIM-834) declares a typed codec, the
|
|
364
|
+
* inferred type from the codec wins via a nested conditional.
|
|
365
|
+
*/
|
|
366
|
+
function formatLinkParamsType(params, importBase, hasSchema) {
|
|
367
|
+
if (params.length === 0) return "{}";
|
|
368
|
+
return `{ ${params.map((p) => {
|
|
369
|
+
const fallback = p.type === "string" ? "string | number" : p.type;
|
|
370
|
+
const codecType = hasSchema ? buildSchemaParamType(p, fallback) : buildCodecChainType(p, importBase, fallback);
|
|
371
|
+
return `${p.name}: ${codecType}`;
|
|
372
|
+
}).join("; ")} }`;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Catch-all call signatures for `<Link>` — external hrefs and computed
|
|
376
|
+
* `string` variables. Emitted from codegen in a SEPARATE
|
|
377
|
+
* `declare module` block (declared AFTER the per-route block) so the TS
|
|
378
|
+
* "later overload set ordered first" rule places these catch-all
|
|
379
|
+
* signatures ahead of per-route in resolution order, leaving per-route
|
|
380
|
+
* as the final overload whose error message is reported on failure.
|
|
381
|
+
*
|
|
382
|
+
* The conditional `string extends H ? ... : never` protection preserves
|
|
383
|
+
* TIM-624's guarantee that unknown internal path literals don't match
|
|
384
|
+
* the catch-all — typos like `<Link href="/typo" />` still error.
|
|
385
|
+
*/
|
|
386
|
+
function formatLinkCatchAllOverloads() {
|
|
387
|
+
const lines = [];
|
|
388
|
+
const baseProps = LINK_BASE_PROPS_TYPE;
|
|
389
|
+
const catchAllSearchParams = "{ definition: SearchParamsDefinition<Record<string, unknown>>; values: Record<string, unknown> } | Record<string, unknown>";
|
|
390
|
+
const externalHref = "`http://${string}` | `https://${string}` | `mailto:${string}` | `tel:${string}` | `ftp://${string}` | `//${string}` | `#${string}` | `?${string}`";
|
|
391
|
+
lines.push(" // Typed Link overloads — catch-all (block 2 / emitted second)");
|
|
392
|
+
lines.push(" interface LinkFunction {");
|
|
393
|
+
lines.push(` (props: ${baseProps} & {`);
|
|
394
|
+
lines.push(` href: ${externalHref}`);
|
|
395
|
+
lines.push(` segmentParams?: Record<string, unknown>`);
|
|
396
|
+
lines.push(` searchParams?: ${catchAllSearchParams}`);
|
|
397
|
+
lines.push(` }): import('react').JSX.Element`);
|
|
398
|
+
lines.push(` <H extends string>(`);
|
|
399
|
+
lines.push(` props: ${baseProps} & {`);
|
|
400
|
+
lines.push(` href: string extends H ? H : never`);
|
|
401
|
+
lines.push(` segmentParams?: Record<string, string | number | string[]>`);
|
|
402
|
+
lines.push(` searchParams?: ${catchAllSearchParams}`);
|
|
403
|
+
lines.push(` }`);
|
|
404
|
+
lines.push(` ): import('react').JSX.Element`);
|
|
405
|
+
lines.push(" }");
|
|
406
|
+
return lines;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Generate typed per-route Link call signatures via LinkFunction
|
|
410
|
+
* interface merging.
|
|
411
|
+
*
|
|
412
|
+
* TIM-835: This emits a SINGLE call signature whose props is a
|
|
413
|
+
* discriminated union keyed on `href`. TypeScript narrows the union by
|
|
414
|
+
* the literal `href` at the call site, then checks the rest of the
|
|
415
|
+
* props against the matched variant. When `segmentParams` or
|
|
416
|
+
* `searchParams` is wrong, TS reports the error against the matched
|
|
417
|
+
* variant — naming the user's actual `href` and the offending field.
|
|
418
|
+
*
|
|
419
|
+
* Before TIM-835, this function emitted N separate per-route overloads
|
|
420
|
+
* (one per route, sometimes two for dynamic routes). When ALL overloads
|
|
421
|
+
* failed, TS would pick an arbitrary failed overload (heuristically the
|
|
422
|
+
* "last tried") to render the diagnostic, often pointing at a route
|
|
423
|
+
* completely unrelated to the one the user wrote. The discriminated
|
|
424
|
+
* union sidesteps overload-resolution heuristics entirely.
|
|
425
|
+
*
|
|
426
|
+
* Open property shapes (`Record<string, unknown>` instead of `never`)
|
|
427
|
+
* for `segmentParams` on routes that don't declare them keep generic
|
|
428
|
+
* `LinkProps`-spreading wrappers compiling. (Aligned with TIM-833.)
|
|
429
|
+
*
|
|
430
|
+
* TIM-832: this function still emits the per-route block FIRST and the
|
|
431
|
+
* catch-all block follows, so per-route remains the LAST overload set in
|
|
432
|
+
* resolution order — the one TS reports against on failure. With a
|
|
433
|
+
* discriminated union there is only one call signature in this block,
|
|
434
|
+
* so the resolved-template-vs-pattern ordering reduces to placing the
|
|
435
|
+
* pattern variant before the resolved-template variant inside the union.
|
|
436
|
+
*/
|
|
437
|
+
function formatTypedLinkOverloads(routes, importBase, hasSchema) {
|
|
438
|
+
const lines = [];
|
|
439
|
+
const baseProps = LINK_BASE_PROPS_TYPE;
|
|
440
|
+
const variants = [];
|
|
441
|
+
for (const route of routes) {
|
|
442
|
+
const hasDynamicParams = route.params.length > 0;
|
|
443
|
+
const paramsProp = hasDynamicParams ? `segmentParams: ${formatLinkParamsType(route.params, importBase, hasSchema)}` : "segmentParams?: Record<string, unknown>";
|
|
444
|
+
const searchParamsType = route.hasSearchParams ? formatSearchParamsType(route, importBase) : null;
|
|
445
|
+
const patternSearchParamsProp = searchParamsType ? `searchParams?: Partial<${searchParamsType}>` : "searchParams?: Record<string, unknown>";
|
|
446
|
+
variants.push(`${baseProps} & { href: '${route.urlPath}'; ${paramsProp}; ${patternSearchParamsProp} }`);
|
|
447
|
+
if (hasDynamicParams) {
|
|
448
|
+
const templatePattern = buildResolvedPattern(route);
|
|
449
|
+
if (templatePattern) {
|
|
450
|
+
const resolvedSearchParamsProp = searchParamsType ? `searchParams?: { definition: SearchParamsDefinition<${searchParamsType}>; values: Partial<${searchParamsType}> }` : "searchParams?: Record<string, unknown>";
|
|
451
|
+
variants.push(`${baseProps} & { href: \`${templatePattern}\`; segmentParams?: Record<string, never>; ${resolvedSearchParamsProp} }`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
lines.push(" interface LinkFunction {");
|
|
456
|
+
if (variants.length === 0) {
|
|
457
|
+
lines.push(" }");
|
|
458
|
+
return lines;
|
|
459
|
+
}
|
|
460
|
+
lines.push(" (");
|
|
461
|
+
lines.push(" props:");
|
|
462
|
+
for (const variant of variants) lines.push(` | (${variant})`);
|
|
463
|
+
lines.push(` ): import('react').JSX.Element`);
|
|
464
|
+
lines.push(" }");
|
|
465
|
+
return lines;
|
|
466
|
+
}
|
|
467
|
+
//#endregion
|
|
468
|
+
//#region src/routing/codegen.ts
|
|
469
|
+
/**
|
|
470
|
+
* Route map codegen.
|
|
471
|
+
*
|
|
472
|
+
* Walks the scanned RouteTree and generates a TypeScript declaration file
|
|
473
|
+
* mapping every route to its params and searchParams shapes.
|
|
474
|
+
*
|
|
475
|
+
* This runs at build time and in dev (regenerated on file changes).
|
|
476
|
+
* No runtime overhead — purely static type generation.
|
|
477
|
+
*/
|
|
478
|
+
/**
|
|
479
|
+
* Generate a TypeScript declaration file string from a scanned route tree.
|
|
480
|
+
*
|
|
481
|
+
* The output is a `declare module '@timber-js/app'` block containing the Routes
|
|
482
|
+
* interface that maps every route path to its params and searchParams shape.
|
|
483
|
+
*/
|
|
484
|
+
function generateRouteMap(tree, options = {}) {
|
|
485
|
+
const hasSchema = options.hasSchema ?? detectSchema(options.appDir);
|
|
486
|
+
const routes = [];
|
|
487
|
+
collectRoutes(tree.root, [], [], "", routes, hasSchema, false);
|
|
488
|
+
routes.sort((a, b) => a.urlPath.localeCompare(b.urlPath));
|
|
489
|
+
return formatDeclarationFile(routes, options.outputDir ?? options.appDir, hasSchema, options.appDir);
|
|
490
|
+
}
|
|
491
|
+
/** Schema file extensions to check, in priority order. */
|
|
492
|
+
var SCHEMA_EXTENSIONS = [
|
|
493
|
+
".ts",
|
|
494
|
+
".tsx",
|
|
495
|
+
".js",
|
|
496
|
+
".jsx"
|
|
497
|
+
];
|
|
498
|
+
/**
|
|
499
|
+
* Detect whether app/schema.{ts,tsx,js,jsx} exists.
|
|
500
|
+
*/
|
|
501
|
+
function detectSchema(appDir) {
|
|
502
|
+
if (!appDir) return false;
|
|
503
|
+
return SCHEMA_EXTENSIONS.some((ext) => existsSync(join(appDir, `schema${ext}`)));
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Recursively walk the segment tree and collect route entries.
|
|
507
|
+
*
|
|
508
|
+
* A route entry is created for any segment that has a `page` or `route` file.
|
|
509
|
+
* Params accumulate from ancestor dynamic segments.
|
|
510
|
+
*/
|
|
511
|
+
function collectRoutes(node, ancestorParams, ancestorParamsFiles, parentTreePath, routes, hasSchema, insideSlot) {
|
|
512
|
+
const treePath = node.segmentName ? `${parentTreePath}/${node.segmentName}` : parentTreePath;
|
|
513
|
+
const ownParamsFile = node.params && fileHasExport(node.params.filePath, "segmentParams") ? node.params.filePath : void 0;
|
|
514
|
+
const params = [...ancestorParams];
|
|
515
|
+
if (node.paramName) {
|
|
516
|
+
const legacyFallback = ownParamsFile ? void 0 : findLegacyParamsExport(node);
|
|
517
|
+
params.push({
|
|
518
|
+
name: node.paramName,
|
|
519
|
+
bracketName: bracketNameForSegment(node),
|
|
520
|
+
type: paramTypeForSegment(node.segmentType),
|
|
521
|
+
legacyCodecFilePath: legacyFallback
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
const nextAncestorFiles = ownParamsFile ? [...ancestorParamsFiles, ownParamsFile] : ancestorParamsFiles;
|
|
525
|
+
const isPage = !!node.page;
|
|
526
|
+
const isApiRoute = !!node.route;
|
|
527
|
+
if (isPage || isApiRoute) {
|
|
528
|
+
const leafFirstChain = nextAncestorFiles.length > 0 ? [...nextAncestorFiles].reverse() : [];
|
|
529
|
+
const resolvedParams = params.map((p) => {
|
|
530
|
+
const codecFilePaths = leafFirstChain.length > 0 ? leafFirstChain : p.legacyCodecFilePath ? [p.legacyCodecFilePath] : void 0;
|
|
531
|
+
return {
|
|
532
|
+
name: p.name,
|
|
533
|
+
bracketName: p.bracketName,
|
|
534
|
+
type: p.type,
|
|
535
|
+
codecFilePaths
|
|
536
|
+
};
|
|
537
|
+
});
|
|
538
|
+
const entry = {
|
|
539
|
+
urlPath: node.urlPath,
|
|
540
|
+
segmentPath: treePath || "/",
|
|
541
|
+
params: resolvedParams,
|
|
542
|
+
hasSearchParams: false,
|
|
543
|
+
isApiRoute,
|
|
544
|
+
isSlotRoute: insideSlot,
|
|
545
|
+
hasSchema
|
|
546
|
+
};
|
|
547
|
+
if (isPage) {
|
|
548
|
+
if (node.params && fileHasExport(node.params.filePath, "searchParams")) {
|
|
549
|
+
entry.hasSearchParams = true;
|
|
550
|
+
entry.searchParamsPagePath = node.params.filePath;
|
|
551
|
+
} else if (node.page && fileHasExport(node.page.filePath, "searchParams")) {
|
|
552
|
+
entry.hasSearchParams = true;
|
|
553
|
+
entry.searchParamsPagePath = node.page.filePath;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
routes.push(entry);
|
|
557
|
+
}
|
|
558
|
+
for (const child of node.children) collectRoutes(child, params, nextAncestorFiles, treePath, routes, hasSchema, insideSlot);
|
|
559
|
+
for (const slot of Object.values(node.slots)) collectRoutes(slot, params, nextAncestorFiles, treePath, routes, hasSchema, true);
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Dedupe route entries by urlPath for urlPath-keyed emissions (the Routes
|
|
563
|
+
* interface, useQueryStates overloads, and typed Link variants).
|
|
564
|
+
*
|
|
565
|
+
* Parallel-slot pages share their parent's urlPath; emitting one entry per
|
|
566
|
+
* slot page produced duplicate interface keys (TS2300/TS2717 under
|
|
567
|
+
* skipLibCheck:false) and duplicate overloads. The non-slot entry is the
|
|
568
|
+
* canonical one; when only slot entries exist (parent has no page), the
|
|
569
|
+
* lexicographically smallest segmentPath wins so output is independent of
|
|
570
|
+
* slot scan order. A slot's searchParams definition is carried onto the
|
|
571
|
+
* merged entry when the canonical entry has none — never silently dropped.
|
|
572
|
+
*
|
|
573
|
+
* segmentPath-keyed emissions (getSegmentParams, useSegmentParams,
|
|
574
|
+
* TimberSegmentParams) must NOT use this — segmentPaths are already unique
|
|
575
|
+
* and slot entries feed those APIs directly.
|
|
576
|
+
*/
|
|
577
|
+
function dedupeRoutesByUrlPath(routes) {
|
|
578
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
579
|
+
for (const route of routes) {
|
|
580
|
+
const existing = byPath.get(route.urlPath);
|
|
581
|
+
if (!existing) {
|
|
582
|
+
byPath.set(route.urlPath, route);
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
let winner = existing;
|
|
586
|
+
let loser = route;
|
|
587
|
+
if (existing.isSlotRoute && !route.isSlotRoute || !!existing.isSlotRoute === !!route.isSlotRoute && route.segmentPath.localeCompare(existing.segmentPath) < 0) {
|
|
588
|
+
winner = route;
|
|
589
|
+
loser = existing;
|
|
590
|
+
}
|
|
591
|
+
if (!winner.hasSearchParams && loser.hasSearchParams) winner = {
|
|
592
|
+
...winner,
|
|
593
|
+
hasSearchParams: true,
|
|
594
|
+
searchParamsPagePath: loser.searchParamsPagePath
|
|
595
|
+
};
|
|
596
|
+
byPath.set(route.urlPath, winner);
|
|
597
|
+
}
|
|
598
|
+
return [...byPath.values()];
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Determine the TypeScript type for a segment's param.
|
|
602
|
+
*/
|
|
603
|
+
/**
|
|
604
|
+
* Derive the bracket key for schema/codegen lookup.
|
|
605
|
+
* For bare segments like `[id]` this is the segmentName itself.
|
|
606
|
+
* For affixed segments like `img-[id].png` this is `[id]` — the bare bracket form.
|
|
607
|
+
*/
|
|
608
|
+
function bracketNameForSegment(node) {
|
|
609
|
+
if (node.paramPrefix || node.paramSuffix) return `[${node.paramName}]`;
|
|
610
|
+
return node.segmentName;
|
|
611
|
+
}
|
|
612
|
+
function paramTypeForSegment(segmentType) {
|
|
613
|
+
switch (segmentType) {
|
|
614
|
+
case "catch-all": return "string[]";
|
|
615
|
+
case "optional-catch-all": return "string[] | undefined";
|
|
616
|
+
default: return "string";
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Find a legacy `segmentParams` export on layout.tsx or page.tsx.
|
|
621
|
+
*
|
|
622
|
+
* Backward-compat shim: TIM-508 made params.ts the canonical location
|
|
623
|
+
* for `segmentParams`. Layout/page exports are still accepted for the
|
|
624
|
+
* OWN segment only (not inherited by descendants — see TIM-834).
|
|
625
|
+
*/
|
|
626
|
+
function findLegacyParamsExport(node) {
|
|
627
|
+
if (node.layout && fileHasExport(node.layout.filePath, "segmentParams")) return node.layout.filePath;
|
|
628
|
+
if (node.page && fileHasExport(node.page.filePath, "segmentParams")) return node.page.filePath;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Emit the schema-based type exports: TimberSegmentParams, TimberRoute,
|
|
632
|
+
* AllSegmentParams, RoutesWithParams.
|
|
633
|
+
*
|
|
634
|
+
* These types use InferCodecType references so they stay in sync with
|
|
635
|
+
* the schema without hardcoding resolved types.
|
|
636
|
+
*
|
|
637
|
+
* Design doc: design/41-global-params.md §Codegen Output
|
|
638
|
+
*/
|
|
639
|
+
function formatSchemaTypes(routes) {
|
|
640
|
+
const lines = [];
|
|
641
|
+
lines.push("/** Union of all valid route patterns. */");
|
|
642
|
+
lines.push("export type TimberRoute = keyof TimberSegmentParams;");
|
|
643
|
+
lines.push("");
|
|
644
|
+
lines.push("/** Maps each segment path to its accumulated segment params. */");
|
|
645
|
+
lines.push("export interface TimberSegmentParams {");
|
|
646
|
+
for (const route of routes) if (route.params.length === 0) lines.push(` '${route.segmentPath}': {};`);
|
|
647
|
+
else {
|
|
648
|
+
lines.push(` '${route.segmentPath}': {`);
|
|
649
|
+
for (const p of route.params) lines.push(` ${p.name}: ${buildSchemaParamType(p)};`);
|
|
650
|
+
lines.push(" };");
|
|
651
|
+
}
|
|
652
|
+
lines.push("}");
|
|
653
|
+
lines.push("");
|
|
654
|
+
lines.push("/** All segment params (union of all route params). */");
|
|
655
|
+
lines.push("export type AllSegmentParams = {");
|
|
656
|
+
lines.push(" [K in keyof TimberSegmentParams as TimberSegmentParams[K] extends Record<string, never>");
|
|
657
|
+
lines.push(" ? never");
|
|
658
|
+
lines.push(" : K]: TimberSegmentParams[K];");
|
|
659
|
+
lines.push("} extends infer U");
|
|
660
|
+
lines.push(" ? { [K in keyof U[keyof U]]: U[keyof U][K] }");
|
|
661
|
+
lines.push(" : never;");
|
|
662
|
+
lines.push("");
|
|
663
|
+
lines.push("/** Filters TimberRoute to routes whose accumulated params include all listed keys. */");
|
|
664
|
+
lines.push("export type RoutesWithParams<K extends keyof AllSegmentParams> = {");
|
|
665
|
+
lines.push(" [R in TimberRoute]: K extends keyof TimberSegmentParams[R] ? R : never;");
|
|
666
|
+
lines.push("}[TimberRoute];");
|
|
667
|
+
return lines;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Format the collected routes into a TypeScript declaration file.
|
|
671
|
+
*/
|
|
672
|
+
function formatDeclarationFile(routes, importBase, hasSchema, appDir) {
|
|
673
|
+
const lines = [];
|
|
674
|
+
lines.push("// This file is auto-generated by timber.js route map codegen.");
|
|
675
|
+
lines.push("// Do not edit manually. Regenerated on build and in dev mode.");
|
|
676
|
+
lines.push("");
|
|
677
|
+
lines.push("export {};");
|
|
678
|
+
lines.push("");
|
|
679
|
+
if (hasSchema) {
|
|
680
|
+
const schemaImport = appDir && importBase ? "./" + relative(importBase, join(appDir, "schema")).replace(/\\/g, "/") : "../app/schema";
|
|
681
|
+
lines.push(`import type schema from '${schemaImport}';`);
|
|
682
|
+
lines.push("import type { InferCodecType, SegmentParamCodec } from '@timber-js/app/params';");
|
|
683
|
+
lines.push("");
|
|
684
|
+
const allBracketKeys = /* @__PURE__ */ new Set();
|
|
685
|
+
for (const route of routes) for (const p of route.params) allBracketKeys.add(p.bracketName);
|
|
686
|
+
if (allBracketKeys.size > 0) {
|
|
687
|
+
lines.push("declare module '@timber-js/app/params' {");
|
|
688
|
+
lines.push(" interface ValidDynamicSegmentKeysRegistry {");
|
|
689
|
+
for (const key of [...allBracketKeys].sort()) lines.push(` ${JSON.stringify(key)}: true;`);
|
|
690
|
+
lines.push(" }");
|
|
691
|
+
lines.push("}");
|
|
692
|
+
lines.push("");
|
|
693
|
+
}
|
|
694
|
+
lines.push("type _AssertSchemaValues = {");
|
|
695
|
+
lines.push(" [K in keyof typeof schema['segmentParams']]: typeof schema['segmentParams'][K] extends SegmentParamCodec ? true : ['Error: value for', K, 'is not a valid Codec or Standard Schema'];");
|
|
696
|
+
lines.push("};");
|
|
697
|
+
lines.push("type _EnforceSchemaValues<_T extends Record<string, true> = _AssertSchemaValues> = true;");
|
|
698
|
+
lines.push("");
|
|
699
|
+
}
|
|
700
|
+
if (!hasSchema) {
|
|
701
|
+
lines.push(emitResolveSegmentFieldHelper());
|
|
702
|
+
lines.push("");
|
|
703
|
+
}
|
|
704
|
+
const uniqueByUrlPath = dedupeRoutesByUrlPath(routes);
|
|
705
|
+
lines.push("declare module '@timber-js/app' {");
|
|
706
|
+
lines.push(" interface Routes {");
|
|
707
|
+
for (const route of uniqueByUrlPath) {
|
|
708
|
+
const paramsType = formatParamsType(route.params, importBase, hasSchema);
|
|
709
|
+
const searchParamsType = formatSearchParamsType(route, importBase);
|
|
710
|
+
lines.push(` '${route.urlPath}': {`);
|
|
711
|
+
lines.push(` segmentParams: ${paramsType}`);
|
|
712
|
+
lines.push(` searchParams: ${searchParamsType}`);
|
|
713
|
+
lines.push(` }`);
|
|
714
|
+
}
|
|
715
|
+
lines.push(" }");
|
|
716
|
+
if (hasSchema) {
|
|
717
|
+
lines.push("");
|
|
718
|
+
lines.push(...formatSchemaTypes(routes).map((l) => ` ${l}`));
|
|
719
|
+
}
|
|
720
|
+
lines.push("}");
|
|
721
|
+
lines.push("");
|
|
722
|
+
const pageRoutes = uniqueByUrlPath.filter((r) => !r.isApiRoute);
|
|
723
|
+
const dynamicRoutes = routes.filter((r) => r.params.length > 0);
|
|
724
|
+
if (dynamicRoutes.length > 0) {
|
|
725
|
+
lines.push("declare module '@timber-js/app/server' {");
|
|
726
|
+
if (hasSchema) lines.push(" import type { AllSegmentParams } from '@timber-js/app'");
|
|
727
|
+
for (const route of dynamicRoutes) {
|
|
728
|
+
const paramsType = formatParamsType(route.params, importBase, hasSchema);
|
|
729
|
+
lines.push(` export function getSegmentParams(segmentPath: '${route.segmentPath}'): ${paramsType}`);
|
|
730
|
+
}
|
|
731
|
+
lines.push(hasSchema ? " export function getSegmentParams(): Partial<AllSegmentParams>" : " export function getSegmentParams(): Record<string, string | string[]>");
|
|
732
|
+
lines.push("}");
|
|
733
|
+
lines.push("");
|
|
734
|
+
}
|
|
735
|
+
if (dynamicRoutes.length > 0 || pageRoutes.length > 0) {
|
|
736
|
+
lines.push("declare module '@timber-js/app/client' {");
|
|
737
|
+
lines.push(" import type { SearchParamsDefinition, SetParams, QueryStatesOptions, SearchParamCodec } from '@timber-js/app/search-params'");
|
|
738
|
+
if (hasSchema) lines.push(" import type { AllSegmentParams } from '@timber-js/app'");
|
|
739
|
+
lines.push("");
|
|
740
|
+
if (dynamicRoutes.length > 0) {
|
|
741
|
+
for (const route of dynamicRoutes) {
|
|
742
|
+
const paramsType = formatParamsType(route.params, importBase, hasSchema);
|
|
743
|
+
lines.push(` export function useSegmentParams(segmentPath: '${route.segmentPath}'): ${paramsType}`);
|
|
744
|
+
}
|
|
745
|
+
lines.push(hasSchema ? " export function useSegmentParams(): Partial<AllSegmentParams>" : " export function useSegmentParams(): Record<string, string | string[]>");
|
|
746
|
+
lines.push("");
|
|
747
|
+
}
|
|
748
|
+
if (pageRoutes.length > 0) {
|
|
749
|
+
lines.push(...formatUseQueryStatesOverloads(pageRoutes, importBase));
|
|
750
|
+
lines.push("");
|
|
751
|
+
}
|
|
752
|
+
if (pageRoutes.length > 0) {
|
|
753
|
+
lines.push(" // Typed Link overloads — per-route (block 1 / emitted first)");
|
|
754
|
+
lines.push(...formatTypedLinkOverloads(pageRoutes, importBase, hasSchema));
|
|
755
|
+
lines.push("");
|
|
756
|
+
}
|
|
757
|
+
lines.push("}");
|
|
758
|
+
lines.push("");
|
|
759
|
+
}
|
|
760
|
+
lines.push("declare module '@timber-js/app/client' {");
|
|
761
|
+
lines.push(" import type { SearchParamsDefinition } from '@timber-js/app/search-params'");
|
|
762
|
+
lines.push("");
|
|
763
|
+
lines.push(...formatLinkCatchAllOverloads());
|
|
764
|
+
lines.push("}");
|
|
765
|
+
lines.push("");
|
|
766
|
+
return lines.join("\n");
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Format the params type for a route entry.
|
|
770
|
+
*/
|
|
771
|
+
function formatParamsType(params, importBase, hasSchema) {
|
|
772
|
+
if (params.length === 0) return "{}";
|
|
773
|
+
return `{ ${params.map((p) => {
|
|
774
|
+
const codecType = hasSchema ? buildSchemaParamType(p) : buildCodecChainType(p, importBase, p.type);
|
|
775
|
+
return `${p.name}: ${codecType}`;
|
|
776
|
+
}).join("; ")} }`;
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Generate useQueryStates overloads.
|
|
780
|
+
*
|
|
781
|
+
* For each page route:
|
|
782
|
+
* - Routes with search-params.ts get a typed overload returning the inferred T
|
|
783
|
+
* - Routes without search-params.ts get an overload returning [{}, SetParams<{}>]
|
|
784
|
+
*
|
|
785
|
+
* A fallback overload for standalone codecs (existing API) is emitted last.
|
|
786
|
+
*/
|
|
787
|
+
function formatUseQueryStatesOverloads(routes, importBase) {
|
|
788
|
+
const lines = [];
|
|
789
|
+
for (const route of routes) {
|
|
790
|
+
const searchParamsType = route.hasSearchParams ? formatSearchParamsType(route, importBase) : "{}";
|
|
791
|
+
lines.push(` export function useQueryStates<R extends '${route.urlPath}'>(route: R, options?: QueryStatesOptions): [${searchParamsType}, SetParams<${searchParamsType}>]`);
|
|
792
|
+
}
|
|
793
|
+
lines.push(" export function useQueryStates<T extends Record<string, unknown>>(codecs: { [K in keyof T]: SearchParamCodec<T[K]> }, options?: QueryStatesOptions): [T, SetParams<T>]");
|
|
794
|
+
return lines;
|
|
795
|
+
}
|
|
796
|
+
//#endregion
|
|
797
|
+
//#region src/routing/schema-validation.ts
|
|
798
|
+
/**
|
|
799
|
+
* Schema key/value validation against the filesystem route tree.
|
|
800
|
+
*
|
|
801
|
+
* Runs at codegen time (build + dev) to catch mismatches between
|
|
802
|
+
* app/schema.ts keys and the actual dynamic segments on disk.
|
|
803
|
+
*
|
|
804
|
+
* Design doc: design/41-global-params.md
|
|
805
|
+
*/
|
|
806
|
+
/**
|
|
807
|
+
* Collect all unique bracket-keyed dynamic segment names from a route tree.
|
|
808
|
+
* Returns entries like '[artistSlug]', '[...slug]', '[[...topic]]'.
|
|
809
|
+
*/
|
|
810
|
+
function collectDynamicSegmentsFromTree(tree) {
|
|
811
|
+
const segments = /* @__PURE__ */ new Set();
|
|
812
|
+
walkTree(tree.root, segments);
|
|
813
|
+
return segments;
|
|
814
|
+
}
|
|
815
|
+
function walkTree(node, segments) {
|
|
816
|
+
if (node.paramName && node.segmentName) {
|
|
817
|
+
const classified = classifyUrlSegment(node.segmentName);
|
|
818
|
+
if (classified.kind !== "static") if (classified.kind === "dynamic" && (classified.prefix || classified.suffix)) segments.add(`[${classified.name}]`);
|
|
819
|
+
else segments.add(node.segmentName);
|
|
820
|
+
}
|
|
821
|
+
for (const child of node.children) walkTree(child, segments);
|
|
822
|
+
for (const slot of Object.values(node.slots)) walkTree(slot, segments);
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* Extract the param name from a bracket key.
|
|
826
|
+
* '[id]' → 'id', '[...slug]' → 'slug', '[[...topic]]' → 'topic'
|
|
827
|
+
*/
|
|
828
|
+
function extractParamName(bracketKey) {
|
|
829
|
+
const seg = classifyUrlSegment(bracketKey);
|
|
830
|
+
if (seg.kind === "static") return null;
|
|
831
|
+
return seg.name;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Validate schema keys against the filesystem route tree.
|
|
835
|
+
*
|
|
836
|
+
* Returns warnings for:
|
|
837
|
+
* - Stale keys: schema keys that don't match any filesystem segment
|
|
838
|
+
* - Bracket form mismatches: same param name, different bracket form
|
|
839
|
+
* - Missing keys: filesystem segments not registered in schema (informational)
|
|
840
|
+
*/
|
|
841
|
+
function validateSchemaAgainstRoutes(tree, appDir) {
|
|
842
|
+
const schemaPath = findSchemaFile(appDir);
|
|
843
|
+
if (!schemaPath) return [];
|
|
844
|
+
const schemaKeys = parseExistingSchemaKeys(readFileCached(schemaPath));
|
|
845
|
+
if (schemaKeys.length === 0) return [];
|
|
846
|
+
return validateKeys(schemaKeys, collectDynamicSegmentsFromTree(tree));
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Core validation: compare schema keys against filesystem segments.
|
|
850
|
+
* Exported separately for testing without filesystem dependencies.
|
|
851
|
+
*/
|
|
852
|
+
function validateKeys(schemaKeys, filesystemSegments) {
|
|
853
|
+
const warnings = [];
|
|
854
|
+
const fsParamToKey = /* @__PURE__ */ new Map();
|
|
855
|
+
for (const fsKey of filesystemSegments) {
|
|
856
|
+
const name = extractParamName(fsKey);
|
|
857
|
+
if (name) fsParamToKey.set(name, fsKey);
|
|
858
|
+
}
|
|
859
|
+
const schemaParamNames = /* @__PURE__ */ new Set();
|
|
860
|
+
for (const schemaKey of schemaKeys) {
|
|
861
|
+
const schemaParamName = extractParamName(schemaKey);
|
|
862
|
+
if (!schemaParamName) continue;
|
|
863
|
+
schemaParamNames.add(schemaParamName);
|
|
864
|
+
if (filesystemSegments.has(schemaKey)) continue;
|
|
865
|
+
const fsKey = fsParamToKey.get(schemaParamName);
|
|
866
|
+
if (fsKey) warnings.push({
|
|
867
|
+
type: "bracket-mismatch",
|
|
868
|
+
key: schemaKey,
|
|
869
|
+
filesystemKey: fsKey,
|
|
870
|
+
message: `Schema key '${schemaKey}' does not match filesystem bracket form '${fsKey}'. Update the schema key to '${fsKey}'.`
|
|
871
|
+
});
|
|
872
|
+
else warnings.push({
|
|
873
|
+
type: "stale-key",
|
|
874
|
+
key: schemaKey,
|
|
875
|
+
message: `Schema key '${schemaKey}' does not match any dynamic segment in the filesystem. Remove it from app/schema.ts or create the corresponding route segment.`
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
for (const fsKey of filesystemSegments) {
|
|
879
|
+
const name = extractParamName(fsKey);
|
|
880
|
+
if (name && !schemaParamNames.has(name)) warnings.push({
|
|
881
|
+
type: "missing-key",
|
|
882
|
+
key: fsKey,
|
|
883
|
+
message: `Dynamic segment '${fsKey}' has no codec in app/schema.ts (defaults to string). Run: timber schema sync`
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
return warnings;
|
|
887
|
+
}
|
|
888
|
+
//#endregion
|
|
889
|
+
//#region src/routing/interception.ts
|
|
890
|
+
/**
|
|
891
|
+
* Collect all interception rewrite rules from the route tree.
|
|
892
|
+
*
|
|
893
|
+
* Walks the tree recursively. For each intercepting segment, computes the
|
|
894
|
+
* intercepted URL based on the marker and the segment's position.
|
|
895
|
+
*/
|
|
896
|
+
function collectInterceptionRewrites(root) {
|
|
897
|
+
const rewrites = [];
|
|
898
|
+
walkForInterceptions(root, [root], rewrites);
|
|
899
|
+
return rewrites;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Recursively walk the segment tree to find intercepting routes.
|
|
903
|
+
*/
|
|
904
|
+
function walkForInterceptions(node, ancestors, rewrites) {
|
|
905
|
+
for (const child of node.children) if (child.segmentType === "intercepting" && child.interceptionMarker) collectFromInterceptingNode(child, ancestors, rewrites);
|
|
906
|
+
else walkForInterceptions(child, [...ancestors, child], rewrites);
|
|
907
|
+
for (const slot of Object.values(node.slots)) walkForInterceptions(slot, ancestors, rewrites);
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* For an intercepting segment, find all leaf pages in its sub-tree and
|
|
911
|
+
* generate rewrite rules for each.
|
|
912
|
+
*/
|
|
913
|
+
function collectFromInterceptingNode(interceptingNode, ancestors, rewrites) {
|
|
914
|
+
const marker = interceptingNode.interceptionMarker;
|
|
915
|
+
const segmentName = interceptingNode.interceptedSegmentName;
|
|
916
|
+
const parentUrlPath = ancestors[ancestors.length - 1].urlPath;
|
|
917
|
+
const interceptedBase = computeInterceptedBase(parentUrlPath, marker);
|
|
918
|
+
collectLeavesWithRewrites(interceptingNode, interceptedBase === "/" ? `/${segmentName}` : `${interceptedBase}/${segmentName}`, parentUrlPath, rewrites);
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Recursively find leaf pages in an intercepting sub-tree and generate
|
|
922
|
+
* rewrite rules for each.
|
|
923
|
+
*/
|
|
924
|
+
function collectLeavesWithRewrites(node, interceptedUrlPath, interceptingPrefix, rewrites) {
|
|
925
|
+
if (node.page) rewrites.push({
|
|
926
|
+
interceptedPattern: interceptedUrlPath,
|
|
927
|
+
interceptingPrefix
|
|
928
|
+
});
|
|
929
|
+
for (const child of node.children) collectLeavesWithRewrites(child, child.segmentType === "group" ? interceptedUrlPath : `${interceptedUrlPath}/${child.segmentName}`, interceptingPrefix, rewrites);
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Compute the base URL that an intercepting route intercepts, given the
|
|
933
|
+
* parent's URL path and the interception marker.
|
|
934
|
+
*
|
|
935
|
+
* - (.) — same level: parent's URL path
|
|
936
|
+
* - (..) — one level up: parent's parent URL path
|
|
937
|
+
* - (...) — root level: /
|
|
938
|
+
* - (..)(..) — two levels up: parent's grandparent URL path
|
|
939
|
+
*
|
|
940
|
+
* Level counting operates on URL path segments, NOT filesystem directories.
|
|
941
|
+
* Route groups and parallel slots are already excluded from urlPath (they
|
|
942
|
+
* don't add URL depth), so (..) correctly climbs visible segments. This
|
|
943
|
+
* avoids the Vinext bug where path.dirname() on filesystem paths would
|
|
944
|
+
* waste climbs on invisible route groups.
|
|
945
|
+
*/
|
|
946
|
+
function computeInterceptedBase(parentUrlPath, marker) {
|
|
947
|
+
switch (marker) {
|
|
948
|
+
case "(.)": return parentUrlPath;
|
|
949
|
+
case "(..)": {
|
|
950
|
+
const parts = parentUrlPath.split("/").filter(Boolean);
|
|
951
|
+
parts.pop();
|
|
952
|
+
return parts.length === 0 ? "/" : `/${parts.join("/")}`;
|
|
953
|
+
}
|
|
954
|
+
case "(...)": return "/";
|
|
955
|
+
case "(..)(..)": {
|
|
956
|
+
const parts = parentUrlPath.split("/").filter(Boolean);
|
|
957
|
+
parts.pop();
|
|
958
|
+
parts.pop();
|
|
959
|
+
return parts.length === 0 ? "/" : `/${parts.join("/")}`;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
//#endregion
|
|
964
|
+
//#region src/routing/walkers.ts
|
|
965
|
+
/**
|
|
966
|
+
* Walk a segment tree and collect every leaf with a `page` or `route`
|
|
967
|
+
* handler. Generic over `TFile` so it works on both the build-time
|
|
968
|
+
* scanner output and the runtime manifest tree.
|
|
969
|
+
*
|
|
970
|
+
* - Pages and route handlers at the same URL produce two distinct
|
|
971
|
+
* entries (the build report deduplicates by URL afterward).
|
|
972
|
+
* - Parallel slots are skipped unless `includeSlots: true` (slots
|
|
973
|
+
* share their parent's URL and are not addressable on their own).
|
|
974
|
+
* - Result is sorted by `urlPath` for deterministic output.
|
|
975
|
+
*/
|
|
976
|
+
function collectLeafRoutes(root, options = {}) {
|
|
977
|
+
const { includeSlots = false } = options;
|
|
978
|
+
const result = [];
|
|
979
|
+
walk(root, [], result, includeSlots);
|
|
980
|
+
result.sort((a, b) => a.urlPath.localeCompare(b.urlPath));
|
|
981
|
+
return result;
|
|
982
|
+
}
|
|
983
|
+
function walk(node, chain, result, includeSlots) {
|
|
984
|
+
const currentChain = [...chain, node];
|
|
985
|
+
const path = node.urlPath || "/";
|
|
986
|
+
if (node.page) result.push({
|
|
987
|
+
urlPath: path,
|
|
988
|
+
segments: currentChain,
|
|
989
|
+
page: node.page
|
|
990
|
+
});
|
|
991
|
+
if (node.route) result.push({
|
|
992
|
+
urlPath: path,
|
|
993
|
+
segments: currentChain,
|
|
994
|
+
route: node.route
|
|
995
|
+
});
|
|
996
|
+
for (const child of node.children) walk(child, currentChain, result, includeSlots);
|
|
997
|
+
if (includeSlots) for (const slotNode of Object.values(node.slots)) walk(slotNode, currentChain, result, includeSlots);
|
|
998
|
+
}
|
|
999
|
+
//#endregion
|
|
1000
|
+
export { generateRouteMap as a, fileHasDirective as c, getPrerenderExport as d, validateSchemaAgainstRoutes as i, fileHasExport as l, collectInterceptionRewrites as n, fileHasAnyExport as o, collectDynamicSegmentsFromTree as r, fileHasDefaultExport as s, collectLeafRoutes as t, fileHasStarExport as u };
|
|
1001
|
+
|
|
1002
|
+
//# sourceMappingURL=walkers-BtTlKviE.js.map
|