@timber-js/app 0.2.0-alpha.12 → 0.2.0-alpha.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/actions-Cw-7NfJJ.js +1101 -0
- package/dist/_chunks/actions-Cw-7NfJJ.js.map +1 -0
- package/dist/_chunks/build-output-helper-DhxiT18k.js +61 -0
- package/dist/_chunks/build-output-helper-DhxiT18k.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-XV0I47Gj.js +2 -0
- package/dist/_chunks/cli-schema-sync-q2wB0DyJ.js +358 -0
- package/dist/_chunks/cli-schema-sync-q2wB0DyJ.js.map +1 -0
- package/dist/_chunks/codec-registry-V7ARyeLN.js +21 -0
- package/dist/_chunks/codec-registry-V7ARyeLN.js.map +1 -0
- package/dist/_chunks/define-8zQ8Vm7x.js +195 -0
- package/dist/_chunks/define-8zQ8Vm7x.js.map +1 -0
- package/dist/_chunks/define-zQX6e1tN.js +124 -0
- package/dist/_chunks/define-zQX6e1tN.js.map +1 -0
- package/dist/_chunks/format-CR6v1pWE.js +14 -0
- package/dist/_chunks/format-CR6v1pWE.js.map +1 -0
- package/dist/_chunks/handler-store-iqnt2ghN.js +54 -0
- package/dist/_chunks/handler-store-iqnt2ghN.js.map +1 -0
- package/dist/_chunks/logger-DDmK5skc.js +291 -0
- package/dist/_chunks/logger-DDmK5skc.js.map +1 -0
- package/dist/_chunks/merge-search-params-CwxJzBLS.js +41 -0
- package/dist/_chunks/merge-search-params-CwxJzBLS.js.map +1 -0
- package/dist/_chunks/navigation-root-DKsJ5Di7.js +96 -0
- package/dist/_chunks/navigation-root-DKsJ5Di7.js.map +1 -0
- package/dist/_chunks/registry-Dp_hJL4s.js +20 -0
- package/dist/_chunks/registry-Dp_hJL4s.js.map +1 -0
- package/dist/_chunks/resolve-schema-23Mc8aLi.js +65 -0
- package/dist/_chunks/resolve-schema-23Mc8aLi.js.map +1 -0
- package/dist/_chunks/router-ref-sektkr-t.js +28 -0
- package/dist/_chunks/router-ref-sektkr-t.js.map +1 -0
- package/dist/_chunks/scanner-DmfoB7iK.js +336 -0
- package/dist/_chunks/scanner-DmfoB7iK.js.map +1 -0
- package/dist/_chunks/schema-bridge-eL5vQDSA.js +86 -0
- package/dist/_chunks/schema-bridge-eL5vQDSA.js.map +1 -0
- package/dist/_chunks/segment-classify-CnfLLvir.js +137 -0
- package/dist/_chunks/segment-classify-CnfLLvir.js.map +1 -0
- package/dist/_chunks/segment-context-Bg0pFbLT.js +34 -0
- package/dist/_chunks/segment-context-Bg0pFbLT.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BO5OvEvg.js} +1 -1
- package/dist/_chunks/ssr-data-BO5OvEvg.js.map +1 -0
- package/dist/_chunks/stale-reload-BCPRG0Cv.js +64 -0
- package/dist/_chunks/stale-reload-BCPRG0Cv.js.map +1 -0
- package/dist/_chunks/tracing-DvKLzCFa.js +329 -0
- package/dist/_chunks/tracing-DvKLzCFa.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-D9SBlAfp.js} +7 -20
- package/dist/_chunks/use-query-states-D9SBlAfp.js.map +1 -0
- package/dist/_chunks/use-segment-params-CskiK-59.js +185 -0
- package/dist/_chunks/use-segment-params-CskiK-59.js.map +1 -0
- package/dist/_chunks/validation-Bm3Je-09.js +84 -0
- package/dist/_chunks/validation-Bm3Je-09.js.map +1 -0
- package/dist/_chunks/walkers-DgOXkTts.js +609 -0
- package/dist/_chunks/walkers-DgOXkTts.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → warnings-B30wpfaS.js} +6 -45
- package/dist/_chunks/warnings-B30wpfaS.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +28 -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 +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +95 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +148 -12
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +142 -38
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +143 -45
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +16 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/cache/cache-api.d.ts +24 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +23 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +151 -81
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cli-schema-sync.d.ts +37 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +42 -6
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +34 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +30 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +23 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +19 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- package/dist/client/error-boundary.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +29 -6
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +54 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +16 -27
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +19 -4
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +9 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +172 -1100
- 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 +964 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link-pending-store.d.ts +63 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +62 -55
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +36 -0
- package/dist/client/nav-link-store.d.ts.map +1 -0
- package/dist/client/navigation-api-types.d.ts +90 -0
- package/dist/client/navigation-api-types.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts +115 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +13 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router.d.ts +70 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +63 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/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-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/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 +51 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +46 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +294 -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 +251 -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 +46 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/dev-tools/404-page.d.ts +46 -0
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/dev-tools/browser-logs.d.ts +84 -0
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/dev-tools/error-page.d.ts +58 -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/index.d.ts +31 -0
- package/dist/dev-tools/index.d.ts.map +1 -0
- package/dist/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
- 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} +2 -2
- 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/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +2 -22
- package/dist/dev-tools/warnings.d.ts.map +1 -0
- package/dist/fonts/ast.d.ts +98 -6
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +48 -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/local.d.ts +1 -1
- package/dist/fonts/pipeline.d.ts +167 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +78 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +45 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +94 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +46 -190
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4799 -12730
- 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 +53 -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 +107 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +2 -2
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +9 -7
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +32 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +17 -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/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +6 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +5 -26
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +63 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +60 -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/index.d.ts +5 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -2
- package/dist/routing/link-codegen.d.ts +90 -0
- package/dist/routing/link-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/segment-classify.d.ts +75 -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 +77 -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 +76 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +157 -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 +95 -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 +41 -6
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts +35 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +3 -6
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +53 -5
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +1 -15
- package/dist/server/asset-headers.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +2 -2
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/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 +51 -0
- package/dist/server/cookie-parsing.d.ts.map +1 -0
- package/dist/server/debug.d.ts +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-boundary.d.ts +90 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- 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 -5
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +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/flush.d.ts.map +1 -1
- package/dist/server/form-data.d.ts +29 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts +213 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +81 -41
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +10 -46
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +155 -2905
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +48 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +2947 -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/middleware-runner.d.ts +36 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +112 -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 +52 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +118 -23
- 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/primitives.d.ts +69 -18
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-timeout.d.ts +51 -0
- package/dist/server/render-timeout.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +62 -107
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +27 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +21 -34
- 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 +2 -2
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +49 -6
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +19 -8
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +50 -0
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +17 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -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 +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +30 -0
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +39 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +16 -11
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +36 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +5 -5
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +62 -30
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/tree-match.d.ts +41 -0
- package/dist/server/tree-match.d.ts.map +1 -0
- package/dist/server/types.d.ts +49 -4
- 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/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/headers.d.ts +2 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +3 -1
- 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/package.json +56 -16
- package/src/adapters/build-output-helper.ts +77 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/adapters/cloudflare.ts +350 -76
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +142 -59
- package/src/adapters/shared.ts +40 -0
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +81 -18
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/sizeof.ts +33 -0
- package/src/cache/timber-cache.ts +25 -20
- package/src/cli-schema-sync.ts +207 -0
- package/src/cli.ts +65 -8
- package/src/client/browser-dev.ts +153 -1
- package/src/client/browser-entry/action-dispatch.ts +126 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +145 -0
- package/src/client/browser-entry/index.ts +149 -0
- package/src/client/browser-entry/post-hydration.ts +119 -0
- package/src/client/browser-entry/router-init.ts +193 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +27 -0
- package/src/client/error-boundary.tsx +99 -22
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +69 -44
- package/src/client/internal.ts +58 -0
- package/src/client/link-pending-store.ts +111 -0
- package/src/client/link.tsx +366 -113
- package/src/client/nav-link-store.ts +47 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +332 -0
- package/src/client/navigation-context.ts +31 -6
- package/src/client/navigation-root.tsx +342 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +300 -73
- package/src/client/rsc-fetch.ts +112 -8
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +72 -3
- package/src/client/state.ts +2 -2
- package/src/client/top-loader.tsx +18 -6
- package/src/client/use-cookie.ts +31 -2
- package/src/client/use-link-status.ts +7 -7
- package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
- package/src/client/use-query-states.ts +9 -3
- package/src/client/use-router.ts +1 -1
- package/src/client/{use-params.ts → use-segment-params.ts} +8 -6
- package/src/codec.ts +97 -0
- package/src/config-types.ts +292 -0
- package/src/config-validation.ts +303 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +233 -53
- package/src/cookies/index.ts +12 -1
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +134 -0
- package/src/dev-tools/404-page.ts +387 -0
- package/src/dev-tools/browser-logs.ts +291 -0
- package/src/dev-tools/error-page.ts +506 -0
- package/src/dev-tools/holding-server.ts +187 -0
- package/src/dev-tools/index.ts +90 -0
- package/src/dev-tools/instrumentation.ts +176 -0
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +9 -5
- package/src/dev-tools/overlay.ts +469 -0
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/dev-tools/terminal.ts +183 -0
- package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +5 -50
- package/src/fonts/ast.ts +525 -16
- package/src/fonts/bundle.ts +142 -0
- package/src/fonts/dev-middleware.ts +74 -0
- package/src/fonts/local.ts +1 -1
- package/src/fonts/pipeline.ts +314 -0
- package/src/fonts/transform.ts +317 -0
- package/src/fonts/types.ts +50 -1
- package/src/fonts/virtual-modules.ts +233 -0
- package/src/index.ts +409 -357
- package/src/params/codec-registry.ts +34 -0
- package/src/params/define-schema.ts +73 -0
- package/src/params/index.ts +11 -0
- package/src/params/resolve-schema.ts +88 -0
- package/src/plugin-context.ts +240 -0
- package/src/plugins/adapter-build.ts +12 -4
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +16 -25
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +175 -35
- package/src/plugins/entries.ts +111 -9
- package/src/plugins/fonts.ts +157 -654
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/routing.ts +374 -45
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +136 -35
- package/src/plugins/static-build.ts +15 -89
- package/src/routing/codegen-shared.ts +109 -0
- package/src/routing/codegen-types.ts +61 -0
- package/src/routing/codegen.ts +269 -179
- package/src/routing/convention-lint.ts +357 -0
- package/src/routing/index.ts +5 -1
- package/src/routing/interception.ts +1 -1
- package/src/routing/link-codegen.ts +308 -0
- package/src/routing/scanner.ts +107 -110
- package/src/routing/segment-classify.ts +188 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/types.ts +78 -25
- package/src/routing/walkers.ts +90 -0
- package/src/rsc-runtime/rsc.ts +2 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
- package/src/search-params/define.ts +538 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +92 -0
- package/src/segment-params/define.ts +336 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +76 -34
- package/src/server/action-client.ts +88 -15
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +112 -14
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +55 -7
- package/src/server/asset-headers.ts +8 -34
- package/src/server/build-manifest.ts +10 -4
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +25 -7
- package/src/server/cookie-context.ts +468 -0
- package/src/server/cookie-parsing.ts +135 -0
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-boundary.ts +218 -0
- package/src/server/deny-renderer.ts +31 -50
- package/src/server/dev-source-map.ts +31 -0
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +74 -102
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/flush.ts +2 -1
- package/src/server/form-data.ts +76 -0
- package/src/server/html-injector-core.ts +417 -0
- package/src/server/html-injectors.ts +235 -223
- package/src/server/index.ts +29 -183
- package/src/server/internal.ts +176 -0
- package/src/server/logger.ts +67 -36
- package/src/server/middleware-runner.ts +75 -4
- package/src/server/node-stream-transforms.ts +361 -0
- package/src/server/param-coercion.ts +206 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +17 -16
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline-outcome.ts +176 -0
- package/src/server/pipeline-phases.ts +460 -0
- package/src/server/pipeline.ts +154 -394
- package/src/server/port-resolution.ts +215 -0
- package/src/server/primitives.ts +111 -28
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +168 -333
- package/src/server/route-element-builder.ts +309 -195
- package/src/server/route-handler.ts +24 -4
- package/src/server/route-matcher.ts +50 -231
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +16 -17
- package/src/server/rsc-entry/error-renderer.ts +305 -89
- package/src/server/rsc-entry/helpers.ts +137 -12
- package/src/server/rsc-entry/index.ts +316 -352
- package/src/server/rsc-entry/render-route.ts +307 -0
- package/src/server/rsc-entry/rsc-payload.ts +65 -18
- package/src/server/rsc-entry/rsc-stream.ts +85 -13
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +187 -38
- package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +126 -0
- package/src/server/slot-resolver.ts +228 -246
- package/src/server/ssr-entry.ts +229 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/state-tree-diff.ts +4 -1
- package/src/server/status-code-resolver.ts +112 -128
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +21 -10
- package/src/server/tree-builder.ts +202 -90
- package/src/server/tree-match.ts +198 -0
- package/src/server/types.ts +55 -6
- package/src/server/utils/escape-html.ts +20 -0
- package/src/server/version-skew.ts +104 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +5 -1
- package/src/shims/navigation-client.ts +4 -3
- 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-gwlJkDuf.js +0 -108
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/format-DviM89f0.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js +0 -676
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/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/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/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/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.map +0 -1
- package/dist/server/dev-warnings.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/server/response-cache.d.ts +0 -54
- package/dist/server/response-cache.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/link-status-provider.tsx +0 -30
- package/src/client/transition-root.tsx +0 -166
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/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/create.ts +0 -321
- package/src/server/dev-fetch-instrumentation.ts +0 -96
- package/src/server/dev-span-processor.ts +0 -78
- package/src/server/manifest-status-resolver.ts +0 -215
- package/src/server/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -410
- package/src/utils/directive-parser.ts +0 -529
- /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
package/src/routing/scanner.ts
CHANGED
|
@@ -18,8 +18,10 @@ import type {
|
|
|
18
18
|
ScannerConfig,
|
|
19
19
|
InterceptionMarker,
|
|
20
20
|
} from './types.js';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
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';
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* Pattern matching encoded path delimiters that must be rejected during route discovery.
|
|
@@ -53,7 +55,7 @@ const LEGACY_STATUS_FILES: Record<string, number> = {
|
|
|
53
55
|
/**
|
|
54
56
|
* File convention names that are always .ts/.tsx (never .mdx etc.)
|
|
55
57
|
*/
|
|
56
|
-
const FIXED_CONVENTIONS = new Set(['middleware', 'access', 'route', '
|
|
58
|
+
const FIXED_CONVENTIONS = new Set(['middleware', 'access', 'route', 'params']);
|
|
57
59
|
|
|
58
60
|
/**
|
|
59
61
|
* Status-code file patterns:
|
|
@@ -83,6 +85,14 @@ export function scanRoutes(appDir: string, config: ScannerConfig = {}): RouteTre
|
|
|
83
85
|
tree.proxy = proxyFile;
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
// Check for global-error.{tsx,ts,jsx,js} at app root.
|
|
89
|
+
// Tier 2 error page — renders standalone (no layouts) when no segment-level
|
|
90
|
+
// error file is found. See design/10-error-handling.md §"Tier 2".
|
|
91
|
+
const globalErrorFile = findPageExtFile(appDir, 'global-error', extSet);
|
|
92
|
+
if (globalErrorFile) {
|
|
93
|
+
tree.globalError = globalErrorFile;
|
|
94
|
+
}
|
|
95
|
+
|
|
86
96
|
// Scan the root directory's files
|
|
87
97
|
scanSegmentFiles(appDir, tree.root, extSet);
|
|
88
98
|
|
|
@@ -92,6 +102,10 @@ export function scanRoutes(appDir: string, config: ScannerConfig = {}): RouteTre
|
|
|
92
102
|
// Validate: detect route group collisions (different groups producing pages at the same URL)
|
|
93
103
|
validateRouteGroupCollisions(tree.root);
|
|
94
104
|
|
|
105
|
+
// Validate: detect duplicate param names in nested dynamic segments
|
|
106
|
+
// e.g., /[id]/items/[id] — same param name in ancestor and descendant
|
|
107
|
+
validateDuplicateParamNames(tree.root);
|
|
108
|
+
|
|
95
109
|
return tree;
|
|
96
110
|
}
|
|
97
111
|
|
|
@@ -114,96 +128,10 @@ function createSegmentNode(
|
|
|
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
|
|
|
@@ -278,11 +207,8 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
278
207
|
case 'route':
|
|
279
208
|
node.route = file;
|
|
280
209
|
break;
|
|
281
|
-
case '
|
|
282
|
-
node.
|
|
283
|
-
break;
|
|
284
|
-
case 'search-params':
|
|
285
|
-
node.searchParams = file;
|
|
210
|
+
case 'params':
|
|
211
|
+
node.params = file;
|
|
286
212
|
break;
|
|
287
213
|
}
|
|
288
214
|
continue;
|
|
@@ -292,27 +218,27 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
292
218
|
// Recognized regardless of pageExtensions — .json is a data format, not a page extension.
|
|
293
219
|
if (STATUS_CODE_PATTERN.test(name) && ext === 'json') {
|
|
294
220
|
if (!node.jsonStatusFiles) {
|
|
295
|
-
node.jsonStatusFiles =
|
|
221
|
+
node.jsonStatusFiles = {};
|
|
296
222
|
}
|
|
297
|
-
node.jsonStatusFiles
|
|
223
|
+
node.jsonStatusFiles[name] = { filePath: fullPath, extension: ext };
|
|
298
224
|
continue;
|
|
299
225
|
}
|
|
300
226
|
|
|
301
227
|
// Status-code files (401.tsx, 4xx.tsx, 503.tsx, 5xx.tsx)
|
|
302
228
|
if (STATUS_CODE_PATTERN.test(name) && extSet.has(ext)) {
|
|
303
229
|
if (!node.statusFiles) {
|
|
304
|
-
node.statusFiles =
|
|
230
|
+
node.statusFiles = {};
|
|
305
231
|
}
|
|
306
|
-
node.statusFiles
|
|
232
|
+
node.statusFiles[name] = { filePath: fullPath, extension: ext };
|
|
307
233
|
continue;
|
|
308
234
|
}
|
|
309
235
|
|
|
310
236
|
// Legacy compat files (not-found.tsx, forbidden.tsx, unauthorized.tsx)
|
|
311
237
|
if (name in LEGACY_STATUS_FILES && extSet.has(ext)) {
|
|
312
238
|
if (!node.legacyStatusFiles) {
|
|
313
|
-
node.legacyStatusFiles =
|
|
239
|
+
node.legacyStatusFiles = {};
|
|
314
240
|
}
|
|
315
|
-
node.legacyStatusFiles
|
|
241
|
+
node.legacyStatusFiles[name] = { filePath: fullPath, extension: ext };
|
|
316
242
|
continue;
|
|
317
243
|
}
|
|
318
244
|
|
|
@@ -323,19 +249,19 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
323
249
|
const metaInfo = classifyMetadataRoute(entry);
|
|
324
250
|
if (metaInfo) {
|
|
325
251
|
if (!node.metadataRoutes) {
|
|
326
|
-
node.metadataRoutes =
|
|
252
|
+
node.metadataRoutes = {};
|
|
327
253
|
}
|
|
328
|
-
const existing = node.metadataRoutes
|
|
254
|
+
const existing = node.metadataRoutes[name];
|
|
329
255
|
if (existing) {
|
|
330
256
|
// Dynamic > static precedence: only overwrite if the new file is dynamic
|
|
331
257
|
// or the existing file is static (dynamic always wins).
|
|
332
258
|
const existingIsDynamic = isDynamicMetadataExtension(name, existing.extension);
|
|
333
259
|
const newIsDynamic = isDynamicMetadataExtension(name, ext);
|
|
334
260
|
if (newIsDynamic || !existingIsDynamic) {
|
|
335
|
-
node.metadataRoutes
|
|
261
|
+
node.metadataRoutes[name] = { filePath: fullPath, extension: ext };
|
|
336
262
|
}
|
|
337
263
|
} else {
|
|
338
|
-
node.metadataRoutes
|
|
264
|
+
node.metadataRoutes[name] = { filePath: fullPath, extension: ext };
|
|
339
265
|
}
|
|
340
266
|
}
|
|
341
267
|
}
|
|
@@ -358,7 +284,8 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
|
|
|
358
284
|
let entries: string[];
|
|
359
285
|
try {
|
|
360
286
|
entries = readdirSync(dirPath);
|
|
361
|
-
} catch {
|
|
287
|
+
} catch (err) {
|
|
288
|
+
swallow(err, `scanChildren: unreadable directory ${dirPath}`, { level: 'warn' });
|
|
362
289
|
return;
|
|
363
290
|
}
|
|
364
291
|
|
|
@@ -412,10 +339,10 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
|
|
|
412
339
|
// Recurse into subdirectories
|
|
413
340
|
scanChildren(fullPath, childNode, extSet);
|
|
414
341
|
|
|
415
|
-
// Attach to parent: slots go into slots
|
|
342
|
+
// Attach to parent: slots go into slots record, everything else is a child
|
|
416
343
|
if (type === 'slot') {
|
|
417
344
|
const slotName = entry.slice(1); // remove @
|
|
418
|
-
parentNode.slots
|
|
345
|
+
parentNode.slots[slotName] = childNode;
|
|
419
346
|
} else {
|
|
420
347
|
parentNode.children.push(childNode);
|
|
421
348
|
}
|
|
@@ -477,11 +404,59 @@ function collectRoutableLeaves(
|
|
|
477
404
|
}
|
|
478
405
|
|
|
479
406
|
// Recurse into slots — each slot is its own parallel route space
|
|
480
|
-
for (const
|
|
407
|
+
for (const slotNode of Object.values(node.slots)) {
|
|
481
408
|
collectRoutableLeaves(slotNode, seen, currentPath, true);
|
|
482
409
|
}
|
|
483
410
|
}
|
|
484
411
|
|
|
412
|
+
/**
|
|
413
|
+
* Validate that no route chain contains duplicate dynamic param names.
|
|
414
|
+
*
|
|
415
|
+
* Example violation:
|
|
416
|
+
* app/[id]/items/[id]/page.tsx — 'id' appears twice in the ancestor chain.
|
|
417
|
+
*
|
|
418
|
+
* Route groups are transparent — params accumulate through them.
|
|
419
|
+
* Slots are independent — duplicate detection does NOT cross slot boundaries.
|
|
420
|
+
*
|
|
421
|
+
* See design/07-routing.md §"Duplicate Param Name Detection"
|
|
422
|
+
*/
|
|
423
|
+
function validateDuplicateParamNames(root: SegmentNode): void {
|
|
424
|
+
walkForDuplicateParams(root, new Map());
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Recursively walk the segment tree, tracking seen param names → segment paths.
|
|
429
|
+
* Throws on the first duplicate found.
|
|
430
|
+
*/
|
|
431
|
+
function walkForDuplicateParams(node: SegmentNode, seen: Map<string, string>): void {
|
|
432
|
+
// If this node introduces a param name, check for duplicates
|
|
433
|
+
if (node.paramName) {
|
|
434
|
+
const existing = seen.get(node.paramName);
|
|
435
|
+
if (existing) {
|
|
436
|
+
throw new Error(
|
|
437
|
+
`[timber] Duplicate param name '${node.paramName}' in route chain.\n` +
|
|
438
|
+
` First defined at: ${existing}\n` +
|
|
439
|
+
` Duplicate at: ${node.urlPath || '/'}\n` +
|
|
440
|
+
` Rename one of the segments to avoid ambiguity.`
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
// Add to seen for descendants (use a new Map to avoid polluting siblings)
|
|
444
|
+
seen = new Map(seen);
|
|
445
|
+
seen.set(node.paramName, node.urlPath || '/');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Recurse into children (they inherit the accumulated params)
|
|
449
|
+
for (const child of node.children) {
|
|
450
|
+
walkForDuplicateParams(child, seen);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Slots are independent parallel routes — start fresh param tracking
|
|
454
|
+
// (a slot's params don't conflict with the main route's params)
|
|
455
|
+
for (const slotNode of Object.values(node.slots)) {
|
|
456
|
+
walkForDuplicateParams(slotNode, new Map(seen));
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
485
460
|
/**
|
|
486
461
|
* Find a fixed-extension file (proxy.ts) in a directory.
|
|
487
462
|
*/
|
|
@@ -498,3 +473,25 @@ function findFixedFile(dirPath: string, name: string): RouteFile | undefined {
|
|
|
498
473
|
}
|
|
499
474
|
return undefined;
|
|
500
475
|
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Find a file using the configured page extensions (tsx, ts, jsx, js, mdx, etc.).
|
|
479
|
+
* Used for app-root conventions like global-error that aren't per-segment.
|
|
480
|
+
*/
|
|
481
|
+
function findPageExtFile(
|
|
482
|
+
dirPath: string,
|
|
483
|
+
name: string,
|
|
484
|
+
extSet: Set<string>
|
|
485
|
+
): RouteFile | undefined {
|
|
486
|
+
for (const ext of extSet) {
|
|
487
|
+
const fullPath = join(dirPath, `${name}.${ext}`);
|
|
488
|
+
try {
|
|
489
|
+
if (statSync(fullPath).isFile()) {
|
|
490
|
+
return { filePath: fullPath, extension: ext };
|
|
491
|
+
}
|
|
492
|
+
} catch {
|
|
493
|
+
// File doesn't exist
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return undefined;
|
|
497
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared segment classifier — both URL tokens and filesystem directory names.
|
|
3
|
+
*
|
|
4
|
+
* `classifyUrlSegment(token)` is a pure single-pass character parser that
|
|
5
|
+
* classifies a route segment token (e.g. "dashboard", "[id]", "[...slug]",
|
|
6
|
+
* "[[...path]]") into a typed discriminated union. NO regex, NO Node.js-only
|
|
7
|
+
* APIs — safe to import from browser code (used by `Link` interpolation).
|
|
8
|
+
*
|
|
9
|
+
* `classifySegment(dirName)` is the build-time directory-name classifier
|
|
10
|
+
* used by the scanner. It recognizes timber-only conventions (private
|
|
11
|
+
* `_*`, parallel `@*`, route groups `(name)`, intercepting routes
|
|
12
|
+
* `(.)`/`(..)`/`(...)`/`(..)(..)`) and delegates bracket syntax to
|
|
13
|
+
* `classifyUrlSegment`. It is the **single source of truth** for what
|
|
14
|
+
* counts as a routing segment — there is no separate copy in the
|
|
15
|
+
* scanner. (TIM-848.)
|
|
16
|
+
*
|
|
17
|
+
* Malformed input falls through to `{ kind: 'static' }` — the safe default.
|
|
18
|
+
*
|
|
19
|
+
* If you change the bracket syntax, update ONLY this file. Every
|
|
20
|
+
* consumer imports from here.
|
|
21
|
+
*
|
|
22
|
+
* See design/07-routing.md §"Route Segments"
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type { InterceptionMarker, SegmentType } from './types.js';
|
|
26
|
+
import { INTERCEPTION_MARKERS } from './types.js';
|
|
27
|
+
|
|
28
|
+
export type UrlSegment =
|
|
29
|
+
| { kind: 'static'; value: string }
|
|
30
|
+
| { kind: 'dynamic'; name: string }
|
|
31
|
+
| { kind: 'catch-all'; name: string }
|
|
32
|
+
| { kind: 'optional-catch-all'; name: string };
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Classify a URL path segment token.
|
|
36
|
+
*
|
|
37
|
+
* Walks the string left-to-right in one pass:
|
|
38
|
+
* 1. If it doesn't start with '[', it's static.
|
|
39
|
+
* 2. Count opening brackets (1 or 2) to detect optional.
|
|
40
|
+
* 3. Check for '...' to detect catch-all.
|
|
41
|
+
* 4. Read the param name up to the closing bracket.
|
|
42
|
+
* 5. Validate the expected closing sequence (']' or ']]').
|
|
43
|
+
* 6. Reject if there are leftover characters after the close.
|
|
44
|
+
*
|
|
45
|
+
* Any structural violation → static (safe default).
|
|
46
|
+
*/
|
|
47
|
+
export function classifyUrlSegment(token: string): UrlSegment {
|
|
48
|
+
const len = token.length;
|
|
49
|
+
|
|
50
|
+
// Must start with '[' to be dynamic
|
|
51
|
+
if (len === 0 || token[0] !== '[') {
|
|
52
|
+
return { kind: 'static', value: token };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let i = 1;
|
|
56
|
+
|
|
57
|
+
// Check for optional: '[[...'
|
|
58
|
+
const optional = token[i] === '[';
|
|
59
|
+
if (optional) i++;
|
|
60
|
+
|
|
61
|
+
// Check for catch-all: '...'
|
|
62
|
+
const catchAll = i + 2 < len && token[i] === '.' && token[i + 1] === '.' && token[i + 2] === '.';
|
|
63
|
+
if (catchAll) i += 3;
|
|
64
|
+
|
|
65
|
+
// Read param name — everything up to ']'
|
|
66
|
+
const nameStart = i;
|
|
67
|
+
while (i < len && token[i] !== ']') i++;
|
|
68
|
+
|
|
69
|
+
// Must have found a ']' and name must be non-empty
|
|
70
|
+
if (i >= len || i === nameStart) {
|
|
71
|
+
return { kind: 'static', value: token };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const name = token.slice(nameStart, i);
|
|
75
|
+
i++; // skip first ']'
|
|
76
|
+
|
|
77
|
+
// Optional requires a second ']'
|
|
78
|
+
if (optional) {
|
|
79
|
+
if (i >= len || token[i] !== ']') {
|
|
80
|
+
return { kind: 'static', value: token };
|
|
81
|
+
}
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Must be at end of string — no trailing characters
|
|
86
|
+
if (i !== len) {
|
|
87
|
+
return { kind: 'static', value: token };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (optional && catchAll) return { kind: 'optional-catch-all', name };
|
|
91
|
+
if (catchAll) return { kind: 'catch-all', name };
|
|
92
|
+
if (optional) {
|
|
93
|
+
// '[[name]]' without '...' is malformed — not a valid segment syntax
|
|
94
|
+
return { kind: 'static', value: token };
|
|
95
|
+
}
|
|
96
|
+
return { kind: 'dynamic', name };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ─── Directory-name classifier (build-time scanner) ─────────────────────────
|
|
100
|
+
|
|
101
|
+
/** Result of classifying a filesystem directory name. */
|
|
102
|
+
export interface SegmentClassification {
|
|
103
|
+
type: SegmentType;
|
|
104
|
+
paramName?: string;
|
|
105
|
+
interceptionMarker?: InterceptionMarker;
|
|
106
|
+
interceptedSegmentName?: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Classify a directory name into its segment type.
|
|
111
|
+
*
|
|
112
|
+
* Recognizes all timber file-system conventions in priority order:
|
|
113
|
+
* 1. Private folders: `_name` (excluded from routing)
|
|
114
|
+
* 2. Parallel route slots: `@name`
|
|
115
|
+
* 3. Intercepting routes: `(.)name`, `(..)name`, `(...)name`, `(..)(..)name`
|
|
116
|
+
* 4. Route groups: `(name)`
|
|
117
|
+
* 5. Bracket syntax: `[id]`, `[...slug]`, `[[...path]]` (delegated to
|
|
118
|
+
* `classifyUrlSegment`)
|
|
119
|
+
* 6. Static: anything else
|
|
120
|
+
*
|
|
121
|
+
* If you change the bracket syntax, update only `classifyUrlSegment`.
|
|
122
|
+
* If you change the directory-prefix conventions, update this function.
|
|
123
|
+
*/
|
|
124
|
+
export function classifySegment(dirName: string): SegmentClassification {
|
|
125
|
+
// Private folder: _name (excluded from routing)
|
|
126
|
+
if (dirName.startsWith('_')) {
|
|
127
|
+
return { type: 'private' };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Parallel route slot: @name
|
|
131
|
+
if (dirName.startsWith('@')) {
|
|
132
|
+
return { type: 'slot' };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Intercepting routes: (.)name, (..)name, (...)name, (..)(..)name
|
|
136
|
+
// Check before route groups since intercepting markers also start with (
|
|
137
|
+
const interception = parseInterceptionMarker(dirName);
|
|
138
|
+
if (interception) {
|
|
139
|
+
return {
|
|
140
|
+
type: 'intercepting',
|
|
141
|
+
interceptionMarker: interception.marker,
|
|
142
|
+
interceptedSegmentName: interception.segmentName,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Route group: (name)
|
|
147
|
+
if (dirName.startsWith('(') && dirName.endsWith(')')) {
|
|
148
|
+
return { type: 'group' };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Bracket-syntax segments: [param], [...param], [[...param]]
|
|
152
|
+
const urlSeg = classifyUrlSegment(dirName);
|
|
153
|
+
if (urlSeg.kind !== 'static') {
|
|
154
|
+
return { type: urlSeg.kind, paramName: urlSeg.name };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return { type: 'static' };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Parse an interception marker from a directory name.
|
|
162
|
+
*
|
|
163
|
+
* Returns the marker and the remaining segment name, or null if not an
|
|
164
|
+
* intercepting route. Markers are checked longest-first to avoid `(..)`
|
|
165
|
+
* matching before `(..)(..)`.
|
|
166
|
+
*
|
|
167
|
+
* Examples:
|
|
168
|
+
* "(.)photo" → { marker: "(.)", segmentName: "photo" }
|
|
169
|
+
* "(..)feed" → { marker: "(..)", segmentName: "feed" }
|
|
170
|
+
* "(...)photos" → { marker: "(...)", segmentName: "photos" }
|
|
171
|
+
* "(..)(..)admin" → { marker: "(..)(..)", segmentName: "admin" }
|
|
172
|
+
* "(marketing)" → null (route group, not interception)
|
|
173
|
+
*/
|
|
174
|
+
function parseInterceptionMarker(
|
|
175
|
+
dirName: string
|
|
176
|
+
): { marker: InterceptionMarker; segmentName: string } | null {
|
|
177
|
+
for (const marker of INTERCEPTION_MARKERS) {
|
|
178
|
+
if (dirName.startsWith(marker)) {
|
|
179
|
+
const rest = dirName.slice(marker.length);
|
|
180
|
+
// Must have a segment name after the marker, and the rest must not
|
|
181
|
+
// be empty or end with ) (which would be a route group like "(auth)")
|
|
182
|
+
if (rest.length > 0 && !rest.endsWith(')')) {
|
|
183
|
+
return { marker, segmentName: rest };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* $segment type generation and directory-to-route mapping.
|
|
3
|
+
*
|
|
4
|
+
* Generates per-route $segment.d.ts files in .timber/types/ that mirror
|
|
5
|
+
* the app/ directory structure. TypeScript's rootDirs feature makes these
|
|
6
|
+
* importable as './$segment' from route files.
|
|
7
|
+
*
|
|
8
|
+
* Design doc: design/41-global-params.md §The $segment Module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import type { RouteTree, SegmentNode } from './types.js';
|
|
14
|
+
|
|
15
|
+
/** Info carried per directory for type generation. */
|
|
16
|
+
export interface SegmentInfo {
|
|
17
|
+
/** The URL route pattern (groups and slots stripped). e.g. '/[artistSlug]/[year]' */
|
|
18
|
+
route: string;
|
|
19
|
+
/** The full tree path including groups and slots — uniquely identifies a segment.
|
|
20
|
+
* e.g. '/(browse)/[artistSlug]/@shows/[year]' */
|
|
21
|
+
segmentPath: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Build a map of absolute filesystem directory → segment info.
|
|
26
|
+
* Used by resolveId to map a $segment import's importer to the correct route,
|
|
27
|
+
* and by writeSegmentTypes to generate per-route $segment.d.ts files.
|
|
28
|
+
*
|
|
29
|
+
* Walks every segment (not just leaves) so layouts and middleware
|
|
30
|
+
* at any depth can import $segment.
|
|
31
|
+
*/
|
|
32
|
+
export function buildDirToRouteMap(tree: RouteTree, appDir: string): Map<string, SegmentInfo> {
|
|
33
|
+
const map = new Map<string, SegmentInfo>();
|
|
34
|
+
|
|
35
|
+
function walk(node: SegmentNode, fsPath: string, treePath: string): void {
|
|
36
|
+
map.set(fsPath, {
|
|
37
|
+
route: node.urlPath || '/',
|
|
38
|
+
segmentPath: treePath || '/',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
for (const child of node.children) {
|
|
42
|
+
const childDir = join(fsPath, child.segmentName);
|
|
43
|
+
const childTreePath = `${treePath}/${child.segmentName}`;
|
|
44
|
+
walk(child, childDir, childTreePath);
|
|
45
|
+
}
|
|
46
|
+
for (const [slotName, slotNode] of Object.entries(node.slots)) {
|
|
47
|
+
const slotDir = join(fsPath, `@${slotName}`);
|
|
48
|
+
const slotTreePath = `${treePath}/@${slotName}`;
|
|
49
|
+
walk(slotNode, slotDir, slotTreePath);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
walk(tree.root, appDir, '');
|
|
54
|
+
return map;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Generate the full $segment.d.ts content for a segment.
|
|
59
|
+
*/
|
|
60
|
+
export function generateSegmentDts(info: SegmentInfo): string {
|
|
61
|
+
return [
|
|
62
|
+
`export const ROUTE: '${info.route}';`,
|
|
63
|
+
`export const SEGMENT_PATH: '${info.segmentPath}';`,
|
|
64
|
+
'',
|
|
65
|
+
].join('\n');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Generate per-route $segment.d.ts files in .timber/types/ mirroring
|
|
70
|
+
* the app/ directory structure. These files are importable via TypeScript's
|
|
71
|
+
* rootDirs feature.
|
|
72
|
+
*/
|
|
73
|
+
export async function writeSegmentTypes(
|
|
74
|
+
routeTree: RouteTree,
|
|
75
|
+
appDir: string,
|
|
76
|
+
root: string
|
|
77
|
+
): Promise<void> {
|
|
78
|
+
// Compute the relative prefix from project root to appDir.
|
|
79
|
+
// e.g. if appDir is /project/src/app, relative is 'src/app'
|
|
80
|
+
const relative = appDir.slice(root.length + 1);
|
|
81
|
+
const typesBase = join(root, '.timber', 'types', relative);
|
|
82
|
+
const map = buildDirToRouteMap(routeTree, appDir);
|
|
83
|
+
|
|
84
|
+
const writes: Promise<void>[] = [];
|
|
85
|
+
for (const [fsDir, info] of map) {
|
|
86
|
+
// Mirror the app/ structure under .timber/types/
|
|
87
|
+
const relDir = fsDir.slice(appDir.length); // e.g. '/[artistSlug]/[year]'
|
|
88
|
+
const segmentDir = join(typesBase, relDir);
|
|
89
|
+
const segmentFile = join(segmentDir, '$segment.d.ts');
|
|
90
|
+
const content = generateSegmentDts(info);
|
|
91
|
+
|
|
92
|
+
writes.push(
|
|
93
|
+
mkdir(segmentDir, { recursive: true }).then(() => writeFile(segmentFile, content, 'utf-8'))
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await Promise.all(writes);
|
|
98
|
+
}
|