@timber-js/app 0.2.0-alpha.18 → 0.2.0-alpha.180
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 +887 -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 +48 -15
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +26 -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 +565 -212
- package/src/client/rsc-fetch.ts +215 -34
- package/src/client/segment-cache.ts +91 -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
package/src/routing/scanner.ts
CHANGED
|
@@ -18,21 +18,11 @@ import type {
|
|
|
18
18
|
ScannerConfig,
|
|
19
19
|
InterceptionMarker,
|
|
20
20
|
} from './types.js';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* %2F / %2f (forward slash) and %5C / %5c (backslash) can cause route collisions
|
|
27
|
-
* when decoded. See design/13-security.md §"Encoded separators rejected".
|
|
28
|
-
*/
|
|
29
|
-
const ENCODED_SEPARATOR_PATTERN = /%(?:2[fF]|5[cC])/;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Pattern matching encoded null bytes (%00) that must be rejected.
|
|
33
|
-
* See design/13-security.md §"Null bytes rejected".
|
|
34
|
-
*/
|
|
35
|
-
const ENCODED_NULL_PATTERN = /%00/;
|
|
21
|
+
import { classifySegment } from './segment-classify.js';
|
|
22
|
+
import { DEFAULT_PAGE_EXTENSIONS } from './types.js';
|
|
23
|
+
import { classifyMetadataRoute, isDynamicMetadataExtension } from '../server/metadata-routes.js';
|
|
24
|
+
import { swallow } from '../server/logger.js';
|
|
25
|
+
import { ENCODED_SEPARATOR_RE, NULL_BYTE_RE } from '../server/canonicalize.js';
|
|
36
26
|
|
|
37
27
|
/**
|
|
38
28
|
* File convention names that use pageExtensions (can be .tsx, .ts, .jsx, .js, .mdx, etc.)
|
|
@@ -53,7 +43,7 @@ const LEGACY_STATUS_FILES: Record<string, number> = {
|
|
|
53
43
|
/**
|
|
54
44
|
* File convention names that are always .ts/.tsx (never .mdx etc.)
|
|
55
45
|
*/
|
|
56
|
-
const FIXED_CONVENTIONS = new Set(['middleware', 'access', 'route', '
|
|
46
|
+
const FIXED_CONVENTIONS = new Set(['middleware', 'access', 'route', 'params']);
|
|
57
47
|
|
|
58
48
|
/**
|
|
59
49
|
* Status-code file patterns:
|
|
@@ -83,6 +73,14 @@ export function scanRoutes(appDir: string, config: ScannerConfig = {}): RouteTre
|
|
|
83
73
|
tree.proxy = proxyFile;
|
|
84
74
|
}
|
|
85
75
|
|
|
76
|
+
// Check for global-error.{tsx,ts,jsx,js} at app root.
|
|
77
|
+
// Tier 2 error page — renders standalone (no layouts) when no segment-level
|
|
78
|
+
// error file is found. See design/10-error-handling.md §"Tier 2".
|
|
79
|
+
const globalErrorFile = findPageExtFile(appDir, 'global-error', extSet);
|
|
80
|
+
if (globalErrorFile) {
|
|
81
|
+
tree.globalError = globalErrorFile;
|
|
82
|
+
}
|
|
83
|
+
|
|
86
84
|
// Scan the root directory's files
|
|
87
85
|
scanSegmentFiles(appDir, tree.root, extSet);
|
|
88
86
|
|
|
@@ -92,6 +90,18 @@ export function scanRoutes(appDir: string, config: ScannerConfig = {}): RouteTre
|
|
|
92
90
|
// Validate: detect route group collisions (different groups producing pages at the same URL)
|
|
93
91
|
validateRouteGroupCollisions(tree.root);
|
|
94
92
|
|
|
93
|
+
// Validate: detect duplicate param names in nested dynamic segments
|
|
94
|
+
// e.g., /[id]/items/[id] — same param name in ancestor and descendant
|
|
95
|
+
validateDuplicateParamNames(tree.root);
|
|
96
|
+
|
|
97
|
+
// Validate: detect same param name used with different bracket forms
|
|
98
|
+
// e.g., [id] in one route and [...id] in another
|
|
99
|
+
validateUniqueBracketForms(tree.root);
|
|
100
|
+
|
|
101
|
+
// Validate: detect affixed dynamic siblings with equal specificity
|
|
102
|
+
// e.g., a-[id] and [slug]-b both have prefix+suffix length = 2
|
|
103
|
+
validateAffixedSiblingConflicts(tree.root);
|
|
104
|
+
|
|
95
105
|
return tree;
|
|
96
106
|
}
|
|
97
107
|
|
|
@@ -104,106 +114,24 @@ function createSegmentNode(
|
|
|
104
114
|
urlPath: string,
|
|
105
115
|
paramName?: string,
|
|
106
116
|
interceptionMarker?: InterceptionMarker,
|
|
107
|
-
interceptedSegmentName?: string
|
|
117
|
+
interceptedSegmentName?: string,
|
|
118
|
+
paramPrefix?: string,
|
|
119
|
+
paramSuffix?: string
|
|
108
120
|
): SegmentNode {
|
|
109
121
|
return {
|
|
110
122
|
segmentName,
|
|
111
123
|
segmentType,
|
|
112
124
|
urlPath,
|
|
113
125
|
paramName,
|
|
126
|
+
paramPrefix,
|
|
127
|
+
paramSuffix,
|
|
114
128
|
interceptionMarker,
|
|
115
129
|
interceptedSegmentName,
|
|
116
130
|
children: [],
|
|
117
|
-
slots:
|
|
131
|
+
slots: {},
|
|
118
132
|
};
|
|
119
133
|
}
|
|
120
134
|
|
|
121
|
-
/**
|
|
122
|
-
* Classify a directory name into its segment type.
|
|
123
|
-
*/
|
|
124
|
-
export function classifySegment(dirName: string): {
|
|
125
|
-
type: SegmentType;
|
|
126
|
-
paramName?: string;
|
|
127
|
-
interceptionMarker?: InterceptionMarker;
|
|
128
|
-
interceptedSegmentName?: string;
|
|
129
|
-
} {
|
|
130
|
-
// Private folder: _name (excluded from routing)
|
|
131
|
-
if (dirName.startsWith('_')) {
|
|
132
|
-
return { type: 'private' };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Parallel route slot: @name
|
|
136
|
-
if (dirName.startsWith('@')) {
|
|
137
|
-
return { type: 'slot' };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Intercepting routes: (.)name, (..)name, (...)name, (..)(..)name
|
|
141
|
-
// Check before route groups since intercepting markers also start with (
|
|
142
|
-
const interception = parseInterceptionMarker(dirName);
|
|
143
|
-
if (interception) {
|
|
144
|
-
return {
|
|
145
|
-
type: 'intercepting',
|
|
146
|
-
interceptionMarker: interception.marker,
|
|
147
|
-
interceptedSegmentName: interception.segmentName,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Route group: (name)
|
|
152
|
-
if (dirName.startsWith('(') && dirName.endsWith(')')) {
|
|
153
|
-
return { type: 'group' };
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Optional catch-all: [[...name]]
|
|
157
|
-
if (dirName.startsWith('[[...') && dirName.endsWith(']]')) {
|
|
158
|
-
const paramName = dirName.slice(5, -2);
|
|
159
|
-
return { type: 'optional-catch-all', paramName };
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Catch-all: [...name]
|
|
163
|
-
if (dirName.startsWith('[...') && dirName.endsWith(']')) {
|
|
164
|
-
const paramName = dirName.slice(4, -1);
|
|
165
|
-
return { type: 'catch-all', paramName };
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Dynamic: [name]
|
|
169
|
-
if (dirName.startsWith('[') && dirName.endsWith(']')) {
|
|
170
|
-
const paramName = dirName.slice(1, -1);
|
|
171
|
-
return { type: 'dynamic', paramName };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return { type: 'static' };
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Parse an interception marker from a directory name.
|
|
179
|
-
*
|
|
180
|
-
* Returns the marker and the remaining segment name, or null if not an
|
|
181
|
-
* intercepting route. Markers are checked longest-first to avoid (..)
|
|
182
|
-
* matching before (..)(..).
|
|
183
|
-
*
|
|
184
|
-
* Examples:
|
|
185
|
-
* "(.)photo" → { marker: "(.)", segmentName: "photo" }
|
|
186
|
-
* "(..)feed" → { marker: "(..)", segmentName: "feed" }
|
|
187
|
-
* "(...)photos" → { marker: "(...)", segmentName: "photos" }
|
|
188
|
-
* "(..)(..)admin" → { marker: "(..)(..)", segmentName: "admin" }
|
|
189
|
-
* "(marketing)" → null (route group, not interception)
|
|
190
|
-
*/
|
|
191
|
-
function parseInterceptionMarker(
|
|
192
|
-
dirName: string
|
|
193
|
-
): { marker: InterceptionMarker; segmentName: string } | null {
|
|
194
|
-
for (const marker of INTERCEPTION_MARKERS) {
|
|
195
|
-
if (dirName.startsWith(marker)) {
|
|
196
|
-
const rest = dirName.slice(marker.length);
|
|
197
|
-
// Must have a segment name after the marker, and the rest must not
|
|
198
|
-
// be empty or end with ) (which would be a route group like "(auth)")
|
|
199
|
-
if (rest.length > 0 && !rest.endsWith(')')) {
|
|
200
|
-
return { marker, segmentName: rest };
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
135
|
/**
|
|
208
136
|
* Compute the URL path for a child segment given its parent's URL path.
|
|
209
137
|
* Route groups, slots, and intercepting routes do NOT add URL depth.
|
|
@@ -225,7 +153,8 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
225
153
|
let entries: string[];
|
|
226
154
|
try {
|
|
227
155
|
entries = readdirSync(dirPath);
|
|
228
|
-
} catch {
|
|
156
|
+
} catch (err) {
|
|
157
|
+
swallow(err, `scanSegmentFiles: unreadable directory ${dirPath}`, { level: 'warn' });
|
|
229
158
|
return;
|
|
230
159
|
}
|
|
231
160
|
|
|
@@ -244,47 +173,26 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
244
173
|
|
|
245
174
|
// Page-extension conventions (page, layout, error, default, denied)
|
|
246
175
|
if (PAGE_EXT_CONVENTIONS.has(name) && extSet.has(ext)) {
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
break;
|
|
252
|
-
case 'layout':
|
|
253
|
-
node.layout = file;
|
|
254
|
-
break;
|
|
255
|
-
case 'error':
|
|
256
|
-
node.error = file;
|
|
257
|
-
break;
|
|
258
|
-
case 'default':
|
|
259
|
-
node.default = file;
|
|
260
|
-
break;
|
|
261
|
-
case 'denied':
|
|
262
|
-
node.denied = file;
|
|
263
|
-
break;
|
|
176
|
+
const key = name as 'page' | 'layout' | 'error' | 'default' | 'denied';
|
|
177
|
+
const existing = node[key];
|
|
178
|
+
if (existing) {
|
|
179
|
+
throwDuplicateConvention(name, existing.filePath, fullPath);
|
|
264
180
|
}
|
|
181
|
+
node[key] = { filePath: fullPath, extension: ext };
|
|
265
182
|
continue;
|
|
266
183
|
}
|
|
267
184
|
|
|
268
|
-
// Fixed conventions (middleware, access, route) —
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
break;
|
|
278
|
-
case 'route':
|
|
279
|
-
node.route = file;
|
|
280
|
-
break;
|
|
281
|
-
case 'prerender':
|
|
282
|
-
node.prerender = file;
|
|
283
|
-
break;
|
|
284
|
-
case 'search-params':
|
|
285
|
-
node.searchParams = file;
|
|
286
|
-
break;
|
|
185
|
+
// Fixed conventions (middleware, access, route, params) — only
|
|
186
|
+
// .ts/.tsx/.js/.jsx, never pageExtensions like .mdx. The regex is
|
|
187
|
+
// anchored: mts/cts/mjs/cjs (and stray tail matches like `.foots`)
|
|
188
|
+
// are NOT recognized. See design/07-routing.md §"Page Extensions".
|
|
189
|
+
if (FIXED_CONVENTIONS.has(name) && /^[jt]sx?$/.test(ext)) {
|
|
190
|
+
const key = name as 'middleware' | 'access' | 'route' | 'params';
|
|
191
|
+
const existing = node[key];
|
|
192
|
+
if (existing) {
|
|
193
|
+
throwDuplicateConvention(name, existing.filePath, fullPath);
|
|
287
194
|
}
|
|
195
|
+
node[key] = { filePath: fullPath, extension: ext };
|
|
288
196
|
continue;
|
|
289
197
|
}
|
|
290
198
|
|
|
@@ -292,50 +200,69 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
292
200
|
// Recognized regardless of pageExtensions — .json is a data format, not a page extension.
|
|
293
201
|
if (STATUS_CODE_PATTERN.test(name) && ext === 'json') {
|
|
294
202
|
if (!node.jsonStatusFiles) {
|
|
295
|
-
node.jsonStatusFiles =
|
|
203
|
+
node.jsonStatusFiles = {};
|
|
296
204
|
}
|
|
297
|
-
node.jsonStatusFiles
|
|
205
|
+
node.jsonStatusFiles[name] = { filePath: fullPath, extension: ext };
|
|
298
206
|
continue;
|
|
299
207
|
}
|
|
300
208
|
|
|
301
209
|
// Status-code files (401.tsx, 4xx.tsx, 503.tsx, 5xx.tsx)
|
|
302
210
|
if (STATUS_CODE_PATTERN.test(name) && extSet.has(ext)) {
|
|
303
211
|
if (!node.statusFiles) {
|
|
304
|
-
node.statusFiles =
|
|
212
|
+
node.statusFiles = {};
|
|
305
213
|
}
|
|
306
|
-
node.statusFiles
|
|
214
|
+
const existing = node.statusFiles[name];
|
|
215
|
+
if (existing) {
|
|
216
|
+
throwDuplicateConvention(name, existing.filePath, fullPath);
|
|
217
|
+
}
|
|
218
|
+
node.statusFiles[name] = { filePath: fullPath, extension: ext };
|
|
307
219
|
continue;
|
|
308
220
|
}
|
|
309
221
|
|
|
310
222
|
// Legacy compat files (not-found.tsx, forbidden.tsx, unauthorized.tsx)
|
|
311
223
|
if (name in LEGACY_STATUS_FILES && extSet.has(ext)) {
|
|
312
224
|
if (!node.legacyStatusFiles) {
|
|
313
|
-
node.legacyStatusFiles =
|
|
225
|
+
node.legacyStatusFiles = {};
|
|
226
|
+
}
|
|
227
|
+
const existing = node.legacyStatusFiles[name];
|
|
228
|
+
if (existing) {
|
|
229
|
+
throwDuplicateConvention(name, existing.filePath, fullPath);
|
|
314
230
|
}
|
|
315
|
-
node.legacyStatusFiles
|
|
231
|
+
node.legacyStatusFiles[name] = { filePath: fullPath, extension: ext };
|
|
316
232
|
continue;
|
|
317
233
|
}
|
|
318
234
|
|
|
319
235
|
// Metadata route files (sitemap.ts, robots.ts, icon.tsx, opengraph-image.tsx, etc.)
|
|
320
236
|
// Both static (.xml, .txt, .png, .ico, etc.) and dynamic (.ts, .tsx) files are recognized.
|
|
321
237
|
// When both exist for the same base name, dynamic takes precedence.
|
|
238
|
+
// Two files of the SAME kind (static+static or dynamic+dynamic) are a
|
|
239
|
+
// build error — picking one by readdir order is platform-dependent.
|
|
322
240
|
// See design/16-metadata.md §"Metadata Routes"
|
|
323
241
|
const metaInfo = classifyMetadataRoute(entry);
|
|
324
242
|
if (metaInfo) {
|
|
243
|
+
if (!metaInfo.nestable && node.segmentName !== '') {
|
|
244
|
+
throw new Error(
|
|
245
|
+
`Build error: '${name}' is a root-only metadata convention and must be in the app root directory.\n` +
|
|
246
|
+
` File: ${fullPath}\n` +
|
|
247
|
+
` Move this file to the app root (not a route group or nested segment).`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
325
250
|
if (!node.metadataRoutes) {
|
|
326
|
-
node.metadataRoutes =
|
|
251
|
+
node.metadataRoutes = {};
|
|
327
252
|
}
|
|
328
|
-
const existing = node.metadataRoutes
|
|
253
|
+
const existing = node.metadataRoutes[name];
|
|
329
254
|
if (existing) {
|
|
330
|
-
// Dynamic > static precedence: only overwrite if the new file is dynamic
|
|
331
|
-
// or the existing file is static (dynamic always wins).
|
|
332
255
|
const existingIsDynamic = isDynamicMetadataExtension(name, existing.extension);
|
|
333
256
|
const newIsDynamic = isDynamicMetadataExtension(name, ext);
|
|
334
|
-
if (
|
|
335
|
-
|
|
257
|
+
if (existingIsDynamic === newIsDynamic) {
|
|
258
|
+
throwDuplicateConvention(name, existing.filePath, fullPath);
|
|
259
|
+
}
|
|
260
|
+
// Dynamic > static precedence: overwrite only when the new file is dynamic.
|
|
261
|
+
if (newIsDynamic) {
|
|
262
|
+
node.metadataRoutes[name] = { filePath: fullPath, extension: ext };
|
|
336
263
|
}
|
|
337
264
|
} else {
|
|
338
|
-
node.metadataRoutes
|
|
265
|
+
node.metadataRoutes[name] = { filePath: fullPath, extension: ext };
|
|
339
266
|
}
|
|
340
267
|
}
|
|
341
268
|
}
|
|
@@ -351,6 +278,26 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
351
278
|
}
|
|
352
279
|
}
|
|
353
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Throw a build error for two files claiming the same convention slot in
|
|
283
|
+
* one segment (e.g. page.tsx + page.jsx). Which file readdir returns first
|
|
284
|
+
* is platform-dependent (APFS sorts entries, ext4 does not) — silently
|
|
285
|
+
* picking one would let macOS dev and Linux CI serve different
|
|
286
|
+
* implementations of the same route.
|
|
287
|
+
*/
|
|
288
|
+
function throwDuplicateConvention(
|
|
289
|
+
convention: string,
|
|
290
|
+
firstPath: string,
|
|
291
|
+
secondPath: string
|
|
292
|
+
): never {
|
|
293
|
+
throw new Error(
|
|
294
|
+
`Build error: duplicate '${convention}' files in the same route segment.\n` +
|
|
295
|
+
` File 1: ${firstPath}\n` +
|
|
296
|
+
` File 2: ${secondPath}\n` +
|
|
297
|
+
`Each segment may define '${convention}' at most once. Remove one of the files.`
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
354
301
|
/**
|
|
355
302
|
* Recursively scan child directories and build the segment tree.
|
|
356
303
|
*/
|
|
@@ -358,7 +305,8 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
|
|
|
358
305
|
let entries: string[];
|
|
359
306
|
try {
|
|
360
307
|
entries = readdirSync(dirPath);
|
|
361
|
-
} catch {
|
|
308
|
+
} catch (err) {
|
|
309
|
+
swallow(err, `scanChildren: unreadable directory ${dirPath}`, { level: 'warn' });
|
|
362
310
|
return;
|
|
363
311
|
}
|
|
364
312
|
|
|
@@ -374,24 +322,31 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
|
|
|
374
322
|
// Reject directories with encoded path delimiters or null bytes.
|
|
375
323
|
// These can cause route collisions when decoded at the URL boundary.
|
|
376
324
|
// See design/13-security.md §"Encoded separators rejected" and §"Null bytes rejected".
|
|
377
|
-
if (
|
|
325
|
+
if (ENCODED_SEPARATOR_RE.test(entry)) {
|
|
378
326
|
throw new Error(
|
|
379
|
-
`Build error: directory name contains an encoded path delimiter (
|
|
327
|
+
`Build error: directory name contains an encoded path delimiter (%2F or %5C).\n` +
|
|
380
328
|
` Directory: ${fullPath}\n` +
|
|
381
329
|
`Encoded separators in directory names cause route collisions when decoded. ` +
|
|
382
330
|
`Rename the directory to remove the encoded delimiter.`
|
|
383
331
|
);
|
|
384
332
|
}
|
|
385
|
-
if (
|
|
333
|
+
if (NULL_BYTE_RE.test(entry)) {
|
|
386
334
|
throw new Error(
|
|
387
|
-
`Build error: directory name contains an encoded null byte (
|
|
335
|
+
`Build error: directory name contains an encoded null byte (%00).\n` +
|
|
388
336
|
` Directory: ${fullPath}\n` +
|
|
389
337
|
`Encoded null bytes in directory names are not allowed. ` +
|
|
390
338
|
`Rename the directory to remove the null byte encoding.`
|
|
391
339
|
);
|
|
392
340
|
}
|
|
393
341
|
|
|
394
|
-
const {
|
|
342
|
+
const {
|
|
343
|
+
type,
|
|
344
|
+
paramName,
|
|
345
|
+
paramPrefix,
|
|
346
|
+
paramSuffix,
|
|
347
|
+
interceptionMarker,
|
|
348
|
+
interceptedSegmentName,
|
|
349
|
+
} = classifySegment(entry);
|
|
395
350
|
|
|
396
351
|
// Skip private folders — underscore-prefixed dirs are excluded from routing
|
|
397
352
|
if (type === 'private') continue;
|
|
@@ -403,7 +358,9 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
|
|
|
403
358
|
urlPath,
|
|
404
359
|
paramName,
|
|
405
360
|
interceptionMarker,
|
|
406
|
-
interceptedSegmentName
|
|
361
|
+
interceptedSegmentName,
|
|
362
|
+
paramPrefix,
|
|
363
|
+
paramSuffix
|
|
407
364
|
);
|
|
408
365
|
|
|
409
366
|
// Scan this segment's files
|
|
@@ -412,10 +369,10 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
|
|
|
412
369
|
// Recurse into subdirectories
|
|
413
370
|
scanChildren(fullPath, childNode, extSet);
|
|
414
371
|
|
|
415
|
-
// Attach to parent: slots go into slots
|
|
372
|
+
// Attach to parent: slots go into slots record, everything else is a child
|
|
416
373
|
if (type === 'slot') {
|
|
417
374
|
const slotName = entry.slice(1); // remove @
|
|
418
|
-
parentNode.slots
|
|
375
|
+
parentNode.slots[slotName] = childNode;
|
|
419
376
|
} else {
|
|
420
377
|
parentNode.children.push(childNode);
|
|
421
378
|
}
|
|
@@ -428,58 +385,228 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
|
|
|
428
385
|
* Two route groups like (auth)/login/page.tsx and (marketing)/login/page.tsx both claim
|
|
429
386
|
* /login — the scanner must detect and reject this at build time.
|
|
430
387
|
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
388
|
+
* Each parallel slot is validated as its OWN collision space: a slot's pages
|
|
389
|
+
* intentionally share URL paths with the parent tree (that's the point of
|
|
390
|
+
* parallel routes), but two route groups INSIDE one slot claiming the same
|
|
391
|
+
* URL — e.g. @side/(a)/x/page.tsx + @side/(b)/x/page.tsx — still collide.
|
|
433
392
|
*/
|
|
434
393
|
function validateRouteGroupCollisions(root: SegmentNode): void {
|
|
435
394
|
// Map from urlPath → { filePath, source } for the first page/route seen at that path
|
|
436
|
-
|
|
437
|
-
collectRoutableLeaves(root, seen, '', false);
|
|
395
|
+
collectRoutableLeaves(root, new Map(), '');
|
|
438
396
|
}
|
|
439
397
|
|
|
440
398
|
/**
|
|
441
399
|
* Walk the segment tree and collect all routable leaves (page or route files),
|
|
442
|
-
* throwing on collision.
|
|
443
|
-
*
|
|
400
|
+
* throwing on collision. Each slot recurses with a FRESH collision map —
|
|
401
|
+
* slots are parallel routes that intentionally share URL paths with their
|
|
402
|
+
* parent tree, but collisions within a single slot are real errors.
|
|
444
403
|
*/
|
|
445
404
|
function collectRoutableLeaves(
|
|
446
405
|
node: SegmentNode,
|
|
447
406
|
seen: Map<string, { filePath: string; segmentPath: string }>,
|
|
448
|
-
segmentPath: string
|
|
449
|
-
insideSlot: boolean
|
|
407
|
+
segmentPath: string
|
|
450
408
|
): void {
|
|
409
|
+
// Intercepting routes are resolved by the slot resolver, not URL matching,
|
|
410
|
+
// and their computed urlPaths intentionally mirror other routes (e.g. two
|
|
411
|
+
// interceptors in one slot both produce /gallery/[id]). Skip them entirely.
|
|
412
|
+
if (node.segmentType === 'intercepting') return;
|
|
413
|
+
|
|
451
414
|
const currentPath = segmentPath
|
|
452
415
|
? `${segmentPath}/${node.segmentName}`
|
|
453
416
|
: node.segmentName || '(root)';
|
|
454
417
|
|
|
455
|
-
|
|
456
|
-
if (
|
|
457
|
-
const
|
|
458
|
-
if (
|
|
459
|
-
|
|
460
|
-
|
|
418
|
+
const routableFile = node.page ?? node.route;
|
|
419
|
+
if (routableFile) {
|
|
420
|
+
const existing = seen.get(node.urlPath);
|
|
421
|
+
if (existing) {
|
|
422
|
+
throw new Error(
|
|
423
|
+
`Build error: route collision — multiple route groups produce a page/route at the same URL path.\n` +
|
|
424
|
+
` URL path: ${node.urlPath}\n` +
|
|
425
|
+
` File 1: ${existing.filePath} (via ${existing.segmentPath})\n` +
|
|
426
|
+
` File 2: ${routableFile.filePath} (via ${currentPath})\n` +
|
|
427
|
+
`Each URL path must map to exactly one page or route handler. ` +
|
|
428
|
+
`Rename or move one of the conflicting files.`
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
seen.set(node.urlPath, { filePath: routableFile.filePath, segmentPath: currentPath });
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Recurse into children
|
|
435
|
+
for (const child of node.children) {
|
|
436
|
+
collectRoutableLeaves(child, seen, currentPath);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Recurse into slots — each slot gets a fresh map (its own collision space)
|
|
440
|
+
for (const slotNode of Object.values(node.slots)) {
|
|
441
|
+
collectRoutableLeaves(slotNode, new Map(), currentPath);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Validate that no route chain contains duplicate dynamic param names.
|
|
447
|
+
*
|
|
448
|
+
* Example violation:
|
|
449
|
+
* app/[id]/items/[id]/page.tsx — 'id' appears twice in the ancestor chain.
|
|
450
|
+
*
|
|
451
|
+
* Route groups are transparent — params accumulate through them.
|
|
452
|
+
* Slots are independent — duplicate detection does NOT cross slot boundaries.
|
|
453
|
+
*
|
|
454
|
+
* See design/07-routing.md §"Duplicate Param Name Detection"
|
|
455
|
+
*/
|
|
456
|
+
function validateDuplicateParamNames(root: SegmentNode): void {
|
|
457
|
+
walkForDuplicateParams(root, new Map());
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Recursively walk the segment tree, tracking seen param names → segment paths.
|
|
462
|
+
* Throws on the first duplicate found.
|
|
463
|
+
*/
|
|
464
|
+
function walkForDuplicateParams(node: SegmentNode, seen: Map<string, string>): void {
|
|
465
|
+
// If this node introduces a param name, check for duplicates
|
|
466
|
+
if (node.paramName) {
|
|
467
|
+
const existing = seen.get(node.paramName);
|
|
468
|
+
if (existing) {
|
|
469
|
+
throw new Error(
|
|
470
|
+
`[timber] Duplicate param name '${node.paramName}' in route chain.\n` +
|
|
471
|
+
` First defined at: ${existing}\n` +
|
|
472
|
+
` Duplicate at: ${node.urlPath || '/'}\n` +
|
|
473
|
+
` Rename one of the segments to avoid ambiguity.`
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
// Add to seen for descendants (use a new Map to avoid polluting siblings)
|
|
477
|
+
seen = new Map(seen);
|
|
478
|
+
seen.set(node.paramName, node.urlPath || '/');
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Recurse into children (they inherit the accumulated params)
|
|
482
|
+
for (const child of node.children) {
|
|
483
|
+
walkForDuplicateParams(child, seen);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Slots are independent parallel routes — start fresh param tracking
|
|
487
|
+
// (a slot's params don't conflict with the main route's params)
|
|
488
|
+
for (const slotNode of Object.values(node.slots)) {
|
|
489
|
+
walkForDuplicateParams(slotNode, new Map(seen));
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Validate that each param name uses a single bracket form across the entire route tree.
|
|
495
|
+
*
|
|
496
|
+
* Different bracket forms produce different types:
|
|
497
|
+
* [id] → string
|
|
498
|
+
* [...id] → string[]
|
|
499
|
+
* [[...id]] → string[] | undefined
|
|
500
|
+
*
|
|
501
|
+
* If the same param name appears with multiple forms, the no-argument
|
|
502
|
+
* getSegmentParams() / useSegmentParams() return type becomes ambiguous.
|
|
503
|
+
*
|
|
504
|
+
* Same name + same form across different routes is fine and expected.
|
|
505
|
+
*/
|
|
506
|
+
function validateUniqueBracketForms(root: SegmentNode): void {
|
|
507
|
+
const forms = new Map<string, { segmentType: SegmentType; urlPath: string }>();
|
|
508
|
+
collectBracketForms(root, forms);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function collectBracketForms(
|
|
512
|
+
node: SegmentNode,
|
|
513
|
+
forms: Map<string, { segmentType: SegmentType; urlPath: string }>
|
|
514
|
+
): void {
|
|
515
|
+
if (node.paramName && node.segmentType !== 'static' && node.segmentType !== 'group') {
|
|
516
|
+
const existing = forms.get(node.paramName);
|
|
517
|
+
if (existing && existing.segmentType !== node.segmentType) {
|
|
518
|
+
const bracketExamples: Record<string, string> = {
|
|
519
|
+
'dynamic': `[${node.paramName}]`,
|
|
520
|
+
'catch-all': `[...${node.paramName}]`,
|
|
521
|
+
'optional-catch-all': `[[...${node.paramName}]]`,
|
|
522
|
+
};
|
|
523
|
+
throw new Error(
|
|
524
|
+
`[timber] Param name '${node.paramName}' uses multiple bracket forms.\n` +
|
|
525
|
+
` ${bracketExamples[existing.segmentType] ?? existing.segmentType} at: ${existing.urlPath}\n` +
|
|
526
|
+
` ${bracketExamples[node.segmentType] ?? node.segmentType} at: ${node.urlPath || '/'}\n` +
|
|
527
|
+
` Each param name must use a single bracket form across all routes.\n` +
|
|
528
|
+
` Rename one of the segments to fix this (e.g., [${node.paramName}] → [${node.paramName}Id]).`
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
if (!existing) {
|
|
532
|
+
forms.set(node.paramName, {
|
|
533
|
+
segmentType: node.segmentType,
|
|
534
|
+
urlPath: node.urlPath || '/',
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
for (const child of node.children) {
|
|
540
|
+
collectBracketForms(child, forms);
|
|
541
|
+
}
|
|
542
|
+
for (const slotNode of Object.values(node.slots)) {
|
|
543
|
+
collectBracketForms(slotNode, forms);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Validate that no sibling affixed dynamic segments have equal specificity.
|
|
549
|
+
*
|
|
550
|
+
* Among affixed siblings, longer combined prefix+suffix length wins. When two
|
|
551
|
+
* siblings tie (same total affix length), the router would fall back to
|
|
552
|
+
* filesystem scan order — which is platform-dependent. This is a build error.
|
|
553
|
+
*
|
|
554
|
+
* Route groups are URL-transparent, so affixed segments inside different groups
|
|
555
|
+
* at the same level still conflict with each other.
|
|
556
|
+
*
|
|
557
|
+
* See design/07-routing.md §"Priority"
|
|
558
|
+
*/
|
|
559
|
+
function validateAffixedSiblingConflicts(node: SegmentNode): void {
|
|
560
|
+
const affixed = collectEffectiveAffixed(node);
|
|
561
|
+
|
|
562
|
+
if (affixed.length >= 2) {
|
|
563
|
+
const byLength = new Map<number, SegmentNode[]>();
|
|
564
|
+
for (const child of affixed) {
|
|
565
|
+
const len = (child.paramPrefix?.length ?? 0) + (child.paramSuffix?.length ?? 0);
|
|
566
|
+
const group = byLength.get(len);
|
|
567
|
+
if (group) {
|
|
568
|
+
group.push(child);
|
|
569
|
+
} else {
|
|
570
|
+
byLength.set(len, [child]);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
for (const [, group] of byLength) {
|
|
575
|
+
if (group.length >= 2) {
|
|
461
576
|
throw new Error(
|
|
462
|
-
`Build error:
|
|
463
|
-
`
|
|
464
|
-
`
|
|
465
|
-
`
|
|
466
|
-
`
|
|
467
|
-
`Rename
|
|
577
|
+
`Build error: ambiguous affixed dynamic siblings with equal specificity.\n` +
|
|
578
|
+
` Parent: ${node.urlPath || '/'}\n` +
|
|
579
|
+
` Segments: ${group.map((s) => s.segmentName).join(', ')}\n` +
|
|
580
|
+
` Combined prefix+suffix length: ${(group[0]!.paramPrefix?.length ?? 0) + (group[0]!.paramSuffix?.length ?? 0)}\n` +
|
|
581
|
+
`The router cannot deterministically choose between these — filesystem scan order is platform-dependent.\n` +
|
|
582
|
+
`Rename one segment to give it a longer or shorter combined affix.`
|
|
468
583
|
);
|
|
469
584
|
}
|
|
470
|
-
seen.set(node.urlPath, { filePath: routableFile.filePath, segmentPath: currentPath });
|
|
471
585
|
}
|
|
472
586
|
}
|
|
473
587
|
|
|
474
|
-
// Recurse into children
|
|
475
588
|
for (const child of node.children) {
|
|
476
|
-
|
|
589
|
+
validateAffixedSiblingConflicts(child);
|
|
590
|
+
}
|
|
591
|
+
for (const slotNode of Object.values(node.slots)) {
|
|
592
|
+
validateAffixedSiblingConflicts(slotNode);
|
|
477
593
|
}
|
|
594
|
+
}
|
|
478
595
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
596
|
+
/**
|
|
597
|
+
* Collect affixed dynamic segments that are effective children of a node.
|
|
598
|
+
* Route groups are URL-transparent, so we look through them recursively.
|
|
599
|
+
*/
|
|
600
|
+
function collectEffectiveAffixed(node: SegmentNode): SegmentNode[] {
|
|
601
|
+
const result: SegmentNode[] = [];
|
|
602
|
+
for (const child of node.children) {
|
|
603
|
+
if (child.segmentType === 'dynamic' && (child.paramPrefix || child.paramSuffix)) {
|
|
604
|
+
result.push(child);
|
|
605
|
+
} else if (child.segmentType === 'group') {
|
|
606
|
+
result.push(...collectEffectiveAffixed(child));
|
|
607
|
+
}
|
|
482
608
|
}
|
|
609
|
+
return result;
|
|
483
610
|
}
|
|
484
611
|
|
|
485
612
|
/**
|
|
@@ -498,3 +625,25 @@ function findFixedFile(dirPath: string, name: string): RouteFile | undefined {
|
|
|
498
625
|
}
|
|
499
626
|
return undefined;
|
|
500
627
|
}
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Find a file using the configured page extensions (tsx, ts, jsx, js, mdx, etc.).
|
|
631
|
+
* Used for app-root conventions like global-error that aren't per-segment.
|
|
632
|
+
*/
|
|
633
|
+
function findPageExtFile(
|
|
634
|
+
dirPath: string,
|
|
635
|
+
name: string,
|
|
636
|
+
extSet: Set<string>
|
|
637
|
+
): RouteFile | undefined {
|
|
638
|
+
for (const ext of extSet) {
|
|
639
|
+
const fullPath = join(dirPath, `${name}.${ext}`);
|
|
640
|
+
try {
|
|
641
|
+
if (statSync(fullPath).isFile()) {
|
|
642
|
+
return { filePath: fullPath, extension: ext };
|
|
643
|
+
}
|
|
644
|
+
} catch {
|
|
645
|
+
// File doesn't exist
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return undefined;
|
|
649
|
+
}
|