@rangojs/router 0.0.0-experimental.2 → 0.0.0-experimental.21
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/AGENTS.md +5 -0
- package/README.md +850 -4
- package/dist/__internal.d.ts +83 -0
- package/dist/__internal.d.ts.map +1 -0
- package/dist/__internal.js +19 -0
- package/dist/__internal.js.map +1 -0
- package/dist/__mocks__/version.d.ts +7 -0
- package/dist/__mocks__/version.d.ts.map +1 -0
- package/{src/__mocks__/version.ts → dist/__mocks__/version.js} +1 -0
- package/dist/__mocks__/version.js.map +1 -0
- package/dist/__tests__/client-href.test.d.ts +2 -0
- package/dist/__tests__/client-href.test.d.ts.map +1 -0
- package/dist/__tests__/client-href.test.js +74 -0
- package/dist/__tests__/client-href.test.js.map +1 -0
- package/dist/__tests__/component-utils.test.d.ts +2 -0
- package/dist/__tests__/component-utils.test.d.ts.map +1 -0
- package/dist/__tests__/component-utils.test.js +51 -0
- package/dist/__tests__/component-utils.test.js.map +1 -0
- package/dist/__tests__/event-controller.test.d.ts +2 -0
- package/dist/__tests__/event-controller.test.d.ts.map +1 -0
- package/dist/__tests__/event-controller.test.js +538 -0
- package/dist/__tests__/event-controller.test.js.map +1 -0
- package/dist/__tests__/helpers/route-tree.d.ts +118 -0
- package/dist/__tests__/helpers/route-tree.d.ts.map +1 -0
- package/dist/__tests__/helpers/route-tree.js +374 -0
- package/dist/__tests__/helpers/route-tree.js.map +1 -0
- package/dist/__tests__/match-result.test.d.ts +2 -0
- package/dist/__tests__/match-result.test.d.ts.map +1 -0
- package/dist/__tests__/match-result.test.js +154 -0
- package/dist/__tests__/match-result.test.js.map +1 -0
- package/dist/__tests__/navigation-store.test.d.ts +2 -0
- package/dist/__tests__/navigation-store.test.d.ts.map +1 -0
- package/dist/__tests__/navigation-store.test.js +440 -0
- package/dist/__tests__/navigation-store.test.js.map +1 -0
- package/dist/__tests__/partial-update.test.d.ts +2 -0
- package/dist/__tests__/partial-update.test.d.ts.map +1 -0
- package/dist/__tests__/partial-update.test.js +1009 -0
- package/dist/__tests__/partial-update.test.js.map +1 -0
- package/dist/__tests__/reverse-types.test.d.ts +8 -0
- package/dist/__tests__/reverse-types.test.d.ts.map +1 -0
- package/dist/__tests__/reverse-types.test.js +656 -0
- package/dist/__tests__/reverse-types.test.js.map +1 -0
- package/dist/__tests__/route-definition.test.d.ts +2 -0
- package/dist/__tests__/route-definition.test.d.ts.map +1 -0
- package/dist/__tests__/route-definition.test.js +55 -0
- package/dist/__tests__/route-definition.test.js.map +1 -0
- package/dist/__tests__/router-helpers.test.d.ts +2 -0
- package/dist/__tests__/router-helpers.test.d.ts.map +1 -0
- package/dist/__tests__/router-helpers.test.js +377 -0
- package/dist/__tests__/router-helpers.test.js.map +1 -0
- package/dist/__tests__/router-integration-2.test.d.ts +2 -0
- package/dist/__tests__/router-integration-2.test.d.ts.map +1 -0
- package/dist/__tests__/router-integration-2.test.js +426 -0
- package/dist/__tests__/router-integration-2.test.js.map +1 -0
- package/dist/__tests__/router-integration.test.d.ts +2 -0
- package/dist/__tests__/router-integration.test.d.ts.map +1 -0
- package/dist/__tests__/router-integration.test.js +1051 -0
- package/dist/__tests__/router-integration.test.js.map +1 -0
- package/dist/__tests__/search-params.test.d.ts +5 -0
- package/dist/__tests__/search-params.test.d.ts.map +1 -0
- package/dist/__tests__/search-params.test.js +306 -0
- package/dist/__tests__/search-params.test.js.map +1 -0
- package/dist/__tests__/segment-system.test.d.ts +2 -0
- package/dist/__tests__/segment-system.test.d.ts.map +1 -0
- package/dist/__tests__/segment-system.test.js +627 -0
- package/dist/__tests__/segment-system.test.js.map +1 -0
- package/dist/__tests__/static-handler-types.test.d.ts +8 -0
- package/dist/__tests__/static-handler-types.test.d.ts.map +1 -0
- package/dist/__tests__/static-handler-types.test.js +63 -0
- package/dist/__tests__/static-handler-types.test.js.map +1 -0
- package/dist/__tests__/urls.test.d.ts +2 -0
- package/dist/__tests__/urls.test.d.ts.map +1 -0
- package/dist/__tests__/urls.test.js +421 -0
- package/dist/__tests__/urls.test.js.map +1 -0
- package/dist/__tests__/use-mount.test.d.ts +2 -0
- package/dist/__tests__/use-mount.test.d.ts.map +1 -0
- package/dist/__tests__/use-mount.test.js +35 -0
- package/dist/__tests__/use-mount.test.js.map +1 -0
- package/dist/bin/rango.d.ts +2 -0
- package/dist/bin/rango.d.ts.map +1 -0
- package/dist/bin/rango.js +1601 -0
- package/dist/bin/rango.js.map +1 -0
- package/dist/browser/event-controller.d.ts +191 -0
- package/dist/browser/event-controller.d.ts.map +1 -0
- package/dist/browser/event-controller.js +559 -0
- package/dist/browser/event-controller.js.map +1 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +14 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/link-interceptor.d.ts +38 -0
- package/dist/browser/link-interceptor.d.ts.map +1 -0
- package/dist/browser/link-interceptor.js +99 -0
- package/dist/browser/link-interceptor.js.map +1 -0
- package/dist/browser/logging.d.ts +10 -0
- package/dist/browser/logging.d.ts.map +1 -0
- package/dist/browser/logging.js +29 -0
- package/dist/browser/logging.js.map +1 -0
- package/dist/browser/lru-cache.d.ts +17 -0
- package/dist/browser/lru-cache.d.ts.map +1 -0
- package/dist/browser/lru-cache.js +50 -0
- package/dist/browser/lru-cache.js.map +1 -0
- package/dist/browser/merge-segment-loaders.d.ts +39 -0
- package/dist/browser/merge-segment-loaders.d.ts.map +1 -0
- package/dist/browser/merge-segment-loaders.js +102 -0
- package/dist/browser/merge-segment-loaders.js.map +1 -0
- package/dist/browser/navigation-bridge.d.ts +102 -0
- package/dist/browser/navigation-bridge.d.ts.map +1 -0
- package/dist/browser/navigation-bridge.js +708 -0
- package/dist/browser/navigation-bridge.js.map +1 -0
- package/dist/browser/navigation-client.d.ts +25 -0
- package/dist/browser/navigation-client.d.ts.map +1 -0
- package/dist/browser/navigation-client.js +157 -0
- package/dist/browser/navigation-client.js.map +1 -0
- package/dist/browser/navigation-store.d.ts +101 -0
- package/dist/browser/navigation-store.d.ts.map +1 -0
- package/dist/browser/navigation-store.js +625 -0
- package/dist/browser/navigation-store.js.map +1 -0
- package/dist/browser/partial-update.d.ts +75 -0
- package/dist/browser/partial-update.d.ts.map +1 -0
- package/dist/browser/partial-update.js +426 -0
- package/dist/browser/partial-update.js.map +1 -0
- package/dist/browser/react/Link.d.ts +86 -0
- package/dist/browser/react/Link.d.ts.map +1 -0
- package/dist/browser/react/Link.js +128 -0
- package/dist/browser/react/Link.js.map +1 -0
- package/dist/browser/react/NavigationProvider.d.ts +63 -0
- package/dist/browser/react/NavigationProvider.d.ts.map +1 -0
- package/dist/browser/react/NavigationProvider.js +216 -0
- package/dist/browser/react/NavigationProvider.js.map +1 -0
- package/dist/browser/react/ScrollRestoration.d.ts +75 -0
- package/dist/browser/react/ScrollRestoration.d.ts.map +1 -0
- package/dist/browser/react/ScrollRestoration.js +57 -0
- package/dist/browser/react/ScrollRestoration.js.map +1 -0
- package/dist/browser/react/context.d.ts +46 -0
- package/dist/browser/react/context.d.ts.map +1 -0
- package/dist/browser/react/context.js +10 -0
- package/dist/browser/react/context.js.map +1 -0
- package/dist/browser/react/index.d.ts +11 -0
- package/dist/browser/react/index.d.ts.map +1 -0
- package/dist/browser/react/index.js +22 -0
- package/dist/browser/react/index.js.map +1 -0
- package/dist/browser/react/location-state-shared.d.ts +63 -0
- package/dist/browser/react/location-state-shared.d.ts.map +1 -0
- package/dist/browser/react/location-state-shared.js +81 -0
- package/dist/browser/react/location-state-shared.js.map +1 -0
- package/dist/browser/react/location-state.d.ts +23 -0
- package/dist/browser/react/location-state.d.ts.map +1 -0
- package/dist/browser/react/location-state.js +29 -0
- package/dist/browser/react/location-state.js.map +1 -0
- package/dist/browser/react/mount-context.d.ts +24 -0
- package/dist/browser/react/mount-context.d.ts.map +1 -0
- package/dist/browser/react/mount-context.js +24 -0
- package/dist/browser/react/mount-context.js.map +1 -0
- package/dist/browser/react/use-action.d.ts +64 -0
- package/dist/browser/react/use-action.d.ts.map +1 -0
- package/dist/browser/react/use-action.js +134 -0
- package/dist/browser/react/use-action.js.map +1 -0
- package/dist/browser/react/use-client-cache.d.ts +41 -0
- package/dist/browser/react/use-client-cache.d.ts.map +1 -0
- package/dist/browser/react/use-client-cache.js +39 -0
- package/dist/browser/react/use-client-cache.js.map +1 -0
- package/dist/browser/react/use-handle.d.ts +31 -0
- package/dist/browser/react/use-handle.d.ts.map +1 -0
- package/dist/browser/react/use-handle.js +144 -0
- package/dist/browser/react/use-handle.js.map +1 -0
- package/dist/browser/react/use-href.d.ts +33 -0
- package/dist/browser/react/use-href.d.ts.map +1 -0
- package/dist/browser/react/use-href.js +39 -0
- package/dist/browser/react/use-href.js.map +1 -0
- package/dist/browser/react/use-link-status.d.ts +37 -0
- package/dist/browser/react/use-link-status.d.ts.map +1 -0
- package/dist/browser/react/use-link-status.js +99 -0
- package/dist/browser/react/use-link-status.js.map +1 -0
- package/dist/browser/react/use-mount.d.ts +25 -0
- package/dist/browser/react/use-mount.d.ts.map +1 -0
- package/dist/browser/react/use-mount.js +30 -0
- package/dist/browser/react/use-mount.js.map +1 -0
- package/dist/browser/react/use-navigation.d.ts +27 -0
- package/dist/browser/react/use-navigation.d.ts.map +1 -0
- package/dist/browser/react/use-navigation.js +87 -0
- package/dist/browser/react/use-navigation.js.map +1 -0
- package/dist/browser/react/use-segments.d.ts +38 -0
- package/dist/browser/react/use-segments.d.ts.map +1 -0
- package/dist/browser/react/use-segments.js +130 -0
- package/dist/browser/react/use-segments.js.map +1 -0
- package/dist/browser/request-controller.d.ts +26 -0
- package/dist/browser/request-controller.d.ts.map +1 -0
- package/dist/browser/request-controller.js +147 -0
- package/dist/browser/request-controller.js.map +1 -0
- package/dist/browser/rsc-router.d.ts +129 -0
- package/dist/browser/rsc-router.d.ts.map +1 -0
- package/dist/browser/rsc-router.js +195 -0
- package/dist/browser/rsc-router.js.map +1 -0
- package/dist/browser/scroll-restoration.d.ts +93 -0
- package/dist/browser/scroll-restoration.d.ts.map +1 -0
- package/dist/browser/scroll-restoration.js +321 -0
- package/dist/browser/scroll-restoration.js.map +1 -0
- package/dist/browser/segment-structure-assert.d.ts +17 -0
- package/dist/browser/segment-structure-assert.d.ts.map +1 -0
- package/dist/browser/segment-structure-assert.js +59 -0
- package/dist/browser/segment-structure-assert.js.map +1 -0
- package/dist/browser/server-action-bridge.d.ts +26 -0
- package/dist/browser/server-action-bridge.d.ts.map +1 -0
- package/dist/browser/server-action-bridge.js +668 -0
- package/dist/browser/server-action-bridge.js.map +1 -0
- package/dist/browser/shallow.d.ts +12 -0
- package/dist/browser/shallow.d.ts.map +1 -0
- package/dist/browser/shallow.js +34 -0
- package/dist/browser/shallow.js.map +1 -0
- package/dist/browser/types.d.ts +369 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/build/__tests__/generate-cli.test.d.ts +2 -0
- package/dist/build/__tests__/generate-cli.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-cli.test.js +237 -0
- package/dist/build/__tests__/generate-cli.test.js.map +1 -0
- package/dist/build/__tests__/generate-manifest.test.d.ts +2 -0
- package/dist/build/__tests__/generate-manifest.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-manifest.test.js +119 -0
- package/dist/build/__tests__/generate-manifest.test.js.map +1 -0
- package/dist/build/__tests__/generate-route-types.test.d.ts +2 -0
- package/dist/build/__tests__/generate-route-types.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-route-types.test.js +620 -0
- package/dist/build/__tests__/generate-route-types.test.js.map +1 -0
- package/dist/build/__tests__/per-router-manifest.test.d.ts +2 -0
- package/dist/build/__tests__/per-router-manifest.test.d.ts.map +1 -0
- package/dist/build/__tests__/per-router-manifest.test.js +308 -0
- package/dist/build/__tests__/per-router-manifest.test.js.map +1 -0
- package/dist/build/generate-manifest.d.ts +81 -0
- package/dist/build/generate-manifest.d.ts.map +1 -0
- package/dist/build/generate-manifest.js +276 -0
- package/dist/build/generate-manifest.js.map +1 -0
- package/dist/build/generate-route-types.d.ts +115 -0
- package/dist/build/generate-route-types.d.ts.map +1 -0
- package/dist/build/generate-route-types.js +740 -0
- package/dist/build/generate-route-types.js.map +1 -0
- package/dist/build/index.d.ts +21 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +21 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/route-trie.d.ts +71 -0
- package/dist/build/route-trie.d.ts.map +1 -0
- package/dist/build/route-trie.js +175 -0
- package/dist/build/route-trie.js.map +1 -0
- package/dist/cache/__tests__/cache-scope.test.d.ts +2 -0
- package/dist/cache/__tests__/cache-scope.test.d.ts.map +1 -0
- package/dist/cache/__tests__/cache-scope.test.js +208 -0
- package/dist/cache/__tests__/cache-scope.test.js.map +1 -0
- package/dist/cache/__tests__/document-cache.test.d.ts +2 -0
- package/dist/cache/__tests__/document-cache.test.d.ts.map +1 -0
- package/dist/cache/__tests__/document-cache.test.js +345 -0
- package/dist/cache/__tests__/document-cache.test.js.map +1 -0
- package/dist/cache/__tests__/memory-segment-store.test.d.ts +2 -0
- package/dist/cache/__tests__/memory-segment-store.test.d.ts.map +1 -0
- package/dist/cache/__tests__/memory-segment-store.test.js +425 -0
- package/dist/cache/__tests__/memory-segment-store.test.js.map +1 -0
- package/dist/cache/__tests__/memory-store.test.d.ts +2 -0
- package/dist/cache/__tests__/memory-store.test.d.ts.map +1 -0
- package/dist/cache/__tests__/memory-store.test.js +367 -0
- package/dist/cache/__tests__/memory-store.test.js.map +1 -0
- package/dist/cache/cache-scope.d.ts +102 -0
- package/dist/cache/cache-scope.d.ts.map +1 -0
- package/dist/cache/cache-scope.js +440 -0
- package/dist/cache/cache-scope.js.map +1 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts +2 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts.map +1 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.js +330 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.js.map +1 -0
- package/dist/cache/cf/cf-cache-store.d.ts +165 -0
- package/dist/cache/cf/cf-cache-store.d.ts.map +1 -0
- package/dist/cache/cf/cf-cache-store.js +242 -0
- package/dist/cache/cf/cf-cache-store.js.map +1 -0
- package/dist/cache/cf/index.d.ts +14 -0
- package/dist/cache/cf/index.d.ts.map +1 -0
- package/dist/cache/cf/index.js +17 -0
- package/dist/cache/cf/index.js.map +1 -0
- package/dist/cache/document-cache.d.ts +64 -0
- package/dist/cache/document-cache.d.ts.map +1 -0
- package/dist/cache/document-cache.js +228 -0
- package/dist/cache/document-cache.js.map +1 -0
- package/dist/cache/index.d.ts +19 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +21 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/memory-segment-store.d.ts +110 -0
- package/dist/cache/memory-segment-store.d.ts.map +1 -0
- package/dist/cache/memory-segment-store.js +117 -0
- package/dist/cache/memory-segment-store.js.map +1 -0
- package/dist/cache/memory-store.d.ts +41 -0
- package/dist/cache/memory-store.d.ts.map +1 -0
- package/dist/cache/memory-store.js +191 -0
- package/dist/cache/memory-store.js.map +1 -0
- package/dist/cache/types.d.ts +317 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +12 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/client.d.ts +248 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +367 -0
- package/dist/client.js.map +1 -0
- package/dist/client.rsc.d.ts +26 -0
- package/dist/client.rsc.d.ts.map +1 -0
- package/dist/client.rsc.js +46 -0
- package/dist/client.rsc.js.map +1 -0
- package/dist/component-utils.d.ts +36 -0
- package/dist/component-utils.d.ts.map +1 -0
- package/dist/component-utils.js +61 -0
- package/dist/component-utils.js.map +1 -0
- package/dist/components/DefaultDocument.d.ts +13 -0
- package/dist/components/DefaultDocument.d.ts.map +1 -0
- package/dist/components/DefaultDocument.js +15 -0
- package/dist/components/DefaultDocument.js.map +1 -0
- package/dist/debug.d.ts +58 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +157 -0
- package/dist/debug.js.map +1 -0
- package/dist/default-error-boundary.d.ts +11 -0
- package/dist/default-error-boundary.d.ts.map +1 -0
- package/dist/default-error-boundary.js +45 -0
- package/dist/default-error-boundary.js.map +1 -0
- package/dist/deps/browser.d.ts +2 -0
- package/dist/deps/browser.d.ts.map +1 -0
- package/dist/deps/browser.js +3 -0
- package/dist/deps/browser.js.map +1 -0
- package/dist/deps/html-stream-client.d.ts +2 -0
- package/dist/deps/html-stream-client.d.ts.map +1 -0
- package/dist/deps/html-stream-client.js +3 -0
- package/dist/deps/html-stream-client.js.map +1 -0
- package/dist/deps/html-stream-server.d.ts +2 -0
- package/dist/deps/html-stream-server.d.ts.map +1 -0
- package/dist/deps/html-stream-server.js +3 -0
- package/dist/deps/html-stream-server.js.map +1 -0
- package/dist/deps/rsc.d.ts +2 -0
- package/dist/deps/rsc.d.ts.map +1 -0
- package/dist/deps/rsc.js +4 -0
- package/dist/deps/rsc.js.map +1 -0
- package/dist/deps/ssr.d.ts +2 -0
- package/dist/deps/ssr.d.ts.map +1 -0
- package/dist/deps/ssr.js +3 -0
- package/dist/deps/ssr.js.map +1 -0
- package/dist/errors.d.ts +174 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +241 -0
- package/dist/errors.js.map +1 -0
- package/dist/handle.d.ts +78 -0
- package/dist/handle.d.ts.map +1 -0
- package/dist/handle.js +82 -0
- package/dist/handle.js.map +1 -0
- package/dist/handles/MetaTags.d.ts +14 -0
- package/dist/handles/MetaTags.d.ts.map +1 -0
- package/dist/handles/MetaTags.js +136 -0
- package/dist/handles/MetaTags.js.map +1 -0
- package/dist/handles/index.d.ts +6 -0
- package/dist/handles/index.d.ts.map +1 -0
- package/dist/handles/index.js +6 -0
- package/dist/handles/index.js.map +1 -0
- package/dist/handles/meta.d.ts +39 -0
- package/dist/handles/meta.d.ts.map +1 -0
- package/dist/handles/meta.js +202 -0
- package/dist/handles/meta.js.map +1 -0
- package/dist/host/__tests__/errors.test.d.ts +2 -0
- package/dist/host/__tests__/errors.test.d.ts.map +1 -0
- package/dist/host/__tests__/errors.test.js +76 -0
- package/dist/host/__tests__/errors.test.js.map +1 -0
- package/dist/host/__tests__/pattern-comprehensive.test.d.ts +2 -0
- package/dist/host/__tests__/pattern-comprehensive.test.d.ts.map +1 -0
- package/dist/host/__tests__/pattern-comprehensive.test.js +732 -0
- package/dist/host/__tests__/pattern-comprehensive.test.js.map +1 -0
- package/dist/host/__tests__/pattern-matcher.test.d.ts +2 -0
- package/dist/host/__tests__/pattern-matcher.test.d.ts.map +1 -0
- package/dist/host/__tests__/pattern-matcher.test.js +251 -0
- package/dist/host/__tests__/pattern-matcher.test.js.map +1 -0
- package/dist/host/__tests__/router.test.d.ts +2 -0
- package/dist/host/__tests__/router.test.d.ts.map +1 -0
- package/dist/host/__tests__/router.test.js +241 -0
- package/dist/host/__tests__/router.test.js.map +1 -0
- package/dist/host/__tests__/testing.test.d.ts +2 -0
- package/dist/host/__tests__/testing.test.d.ts.map +1 -0
- package/dist/host/__tests__/testing.test.js +64 -0
- package/dist/host/__tests__/testing.test.js.map +1 -0
- package/dist/host/__tests__/utils.test.d.ts +2 -0
- package/dist/host/__tests__/utils.test.d.ts.map +1 -0
- package/dist/host/__tests__/utils.test.js +29 -0
- package/dist/host/__tests__/utils.test.js.map +1 -0
- package/dist/host/cookie-handler.d.ts +34 -0
- package/dist/host/cookie-handler.d.ts.map +1 -0
- package/dist/host/cookie-handler.js +124 -0
- package/dist/host/cookie-handler.js.map +1 -0
- package/dist/host/errors.d.ts +56 -0
- package/dist/host/errors.d.ts.map +1 -0
- package/dist/host/errors.js +79 -0
- package/dist/host/errors.js.map +1 -0
- package/dist/host/index.d.ts +29 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +32 -0
- package/dist/host/index.js.map +1 -0
- package/dist/host/pattern-matcher.d.ts +36 -0
- package/dist/host/pattern-matcher.d.ts.map +1 -0
- package/dist/host/pattern-matcher.js +172 -0
- package/dist/host/pattern-matcher.js.map +1 -0
- package/dist/host/router.d.ts +26 -0
- package/dist/host/router.d.ts.map +1 -0
- package/dist/host/router.js +218 -0
- package/dist/host/router.js.map +1 -0
- package/dist/host/testing.d.ts +36 -0
- package/dist/host/testing.d.ts.map +1 -0
- package/dist/host/testing.js +55 -0
- package/dist/host/testing.js.map +1 -0
- package/dist/host/types.d.ts +115 -0
- package/dist/host/types.d.ts.map +1 -0
- package/dist/host/types.js +7 -0
- package/dist/host/types.js.map +1 -0
- package/dist/host/utils.d.ts +21 -0
- package/dist/host/utils.d.ts.map +1 -0
- package/dist/host/utils.js +23 -0
- package/dist/host/utils.js.map +1 -0
- package/dist/href-client.d.ts +131 -0
- package/dist/href-client.d.ts.map +1 -0
- package/dist/href-client.js +64 -0
- package/dist/href-client.js.map +1 -0
- package/{src/href-context.ts → dist/href-context.d.ts} +7 -11
- package/dist/href-context.d.ts.map +1 -0
- package/dist/href-context.js +21 -0
- package/dist/href-context.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/index.rsc.d.ts +32 -0
- package/dist/index.rsc.d.ts.map +1 -0
- package/dist/index.rsc.js +40 -0
- package/dist/index.rsc.js.map +1 -0
- package/dist/internal-debug.d.ts +2 -0
- package/dist/internal-debug.d.ts.map +1 -0
- package/dist/internal-debug.js +5 -0
- package/dist/internal-debug.js.map +1 -0
- package/dist/loader.d.ts +14 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +20 -0
- package/dist/loader.js.map +1 -0
- package/dist/loader.rsc.d.ts +19 -0
- package/dist/loader.rsc.d.ts.map +1 -0
- package/dist/loader.rsc.js +99 -0
- package/dist/loader.rsc.js.map +1 -0
- package/dist/network-error-thrower.d.ts +17 -0
- package/dist/network-error-thrower.d.ts.map +1 -0
- package/dist/network-error-thrower.js +14 -0
- package/dist/network-error-thrower.js.map +1 -0
- package/dist/outlet-context.d.ts +13 -0
- package/dist/outlet-context.d.ts.map +1 -0
- package/dist/outlet-context.js +3 -0
- package/dist/outlet-context.js.map +1 -0
- package/dist/prerender/__tests__/param-hash.test.d.ts +2 -0
- package/dist/prerender/__tests__/param-hash.test.d.ts.map +1 -0
- package/dist/prerender/__tests__/param-hash.test.js +148 -0
- package/dist/prerender/__tests__/param-hash.test.js.map +1 -0
- package/dist/prerender/param-hash.d.ts +16 -0
- package/dist/prerender/param-hash.d.ts.map +1 -0
- package/dist/prerender/param-hash.js +36 -0
- package/dist/prerender/param-hash.js.map +1 -0
- package/dist/prerender/store.d.ts +38 -0
- package/dist/prerender/store.d.ts.map +1 -0
- package/dist/prerender/store.js +61 -0
- package/dist/prerender/store.js.map +1 -0
- package/dist/prerender.d.ts +66 -0
- package/dist/prerender.d.ts.map +1 -0
- package/dist/prerender.js +57 -0
- package/dist/prerender.js.map +1 -0
- package/dist/reverse.d.ts +196 -0
- package/dist/reverse.d.ts.map +1 -0
- package/dist/reverse.js +78 -0
- package/dist/reverse.js.map +1 -0
- package/dist/root-error-boundary.d.ts +33 -0
- package/dist/root-error-boundary.d.ts.map +1 -0
- package/dist/root-error-boundary.js +165 -0
- package/dist/root-error-boundary.js.map +1 -0
- package/dist/route-content-wrapper.d.ts +46 -0
- package/dist/route-content-wrapper.d.ts.map +1 -0
- package/dist/route-content-wrapper.js +77 -0
- package/dist/route-content-wrapper.js.map +1 -0
- package/dist/route-definition.d.ts +421 -0
- package/dist/route-definition.d.ts.map +1 -0
- package/dist/route-definition.js +868 -0
- package/dist/route-definition.js.map +1 -0
- package/dist/route-map-builder.d.ts +155 -0
- package/dist/route-map-builder.d.ts.map +1 -0
- package/dist/route-map-builder.js +237 -0
- package/dist/route-map-builder.js.map +1 -0
- package/dist/route-types.d.ts +165 -0
- package/dist/route-types.d.ts.map +1 -0
- package/dist/route-types.js +7 -0
- package/dist/route-types.js.map +1 -0
- package/dist/router/__tests__/handler-context.test.d.ts +2 -0
- package/dist/router/__tests__/handler-context.test.d.ts.map +1 -0
- package/dist/router/__tests__/handler-context.test.js +65 -0
- package/dist/router/__tests__/handler-context.test.js.map +1 -0
- package/dist/router/__tests__/loader-cycle-detection.test.d.ts +2 -0
- package/dist/router/__tests__/loader-cycle-detection.test.d.ts.map +1 -0
- package/dist/router/__tests__/loader-cycle-detection.test.js +221 -0
- package/dist/router/__tests__/loader-cycle-detection.test.js.map +1 -0
- package/dist/router/__tests__/match-context.test.d.ts +2 -0
- package/dist/router/__tests__/match-context.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-context.test.js +92 -0
- package/dist/router/__tests__/match-context.test.js.map +1 -0
- package/dist/router/__tests__/match-pipelines.test.d.ts +2 -0
- package/dist/router/__tests__/match-pipelines.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-pipelines.test.js +417 -0
- package/dist/router/__tests__/match-pipelines.test.js.map +1 -0
- package/dist/router/__tests__/match-result.test.d.ts +2 -0
- package/dist/router/__tests__/match-result.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-result.test.js +457 -0
- package/dist/router/__tests__/match-result.test.js.map +1 -0
- package/dist/router/__tests__/on-error.test.d.ts +2 -0
- package/dist/router/__tests__/on-error.test.d.ts.map +1 -0
- package/dist/router/__tests__/on-error.test.js +678 -0
- package/dist/router/__tests__/on-error.test.js.map +1 -0
- package/dist/router/__tests__/pattern-matching.test.d.ts +2 -0
- package/dist/router/__tests__/pattern-matching.test.d.ts.map +1 -0
- package/dist/router/__tests__/pattern-matching.test.js +629 -0
- package/dist/router/__tests__/pattern-matching.test.js.map +1 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts +2 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts.map +1 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.js +155 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.js.map +1 -0
- package/dist/router/error-handling.d.ts +77 -0
- package/dist/router/error-handling.d.ts.map +1 -0
- package/dist/router/error-handling.js +202 -0
- package/dist/router/error-handling.js.map +1 -0
- package/dist/router/handler-context.d.ts +20 -0
- package/dist/router/handler-context.d.ts.map +1 -0
- package/dist/router/handler-context.js +198 -0
- package/dist/router/handler-context.js.map +1 -0
- package/dist/router/intercept-resolution.d.ts +66 -0
- package/dist/router/intercept-resolution.d.ts.map +1 -0
- package/dist/router/intercept-resolution.js +246 -0
- package/dist/router/intercept-resolution.js.map +1 -0
- package/dist/router/loader-resolution.d.ts +64 -0
- package/dist/router/loader-resolution.d.ts.map +1 -0
- package/dist/router/loader-resolution.js +284 -0
- package/dist/router/loader-resolution.js.map +1 -0
- package/dist/router/logging.d.ts +15 -0
- package/dist/router/logging.d.ts.map +1 -0
- package/dist/router/logging.js +99 -0
- package/dist/router/logging.js.map +1 -0
- package/dist/router/manifest.d.ts +22 -0
- package/dist/router/manifest.d.ts.map +1 -0
- package/dist/router/manifest.js +181 -0
- package/dist/router/manifest.js.map +1 -0
- package/dist/router/match-api.d.ts +35 -0
- package/dist/router/match-api.d.ts.map +1 -0
- package/dist/router/match-api.js +406 -0
- package/dist/router/match-api.js.map +1 -0
- package/dist/router/match-context.d.ts +206 -0
- package/dist/router/match-context.d.ts.map +1 -0
- package/dist/router/match-context.js +17 -0
- package/dist/router/match-context.js.map +1 -0
- package/dist/router/match-middleware/background-revalidation.d.ts +127 -0
- package/dist/router/match-middleware/background-revalidation.d.ts.map +1 -0
- package/dist/router/match-middleware/background-revalidation.js +75 -0
- package/dist/router/match-middleware/background-revalidation.js.map +1 -0
- package/dist/router/match-middleware/cache-lookup.d.ts +112 -0
- package/dist/router/match-middleware/cache-lookup.d.ts.map +1 -0
- package/dist/router/match-middleware/cache-lookup.js +257 -0
- package/dist/router/match-middleware/cache-lookup.js.map +1 -0
- package/dist/router/match-middleware/cache-store.d.ts +113 -0
- package/dist/router/match-middleware/cache-store.d.ts.map +1 -0
- package/dist/router/match-middleware/cache-store.js +108 -0
- package/dist/router/match-middleware/cache-store.js.map +1 -0
- package/dist/router/match-middleware/index.d.ts +81 -0
- package/dist/router/match-middleware/index.d.ts.map +1 -0
- package/dist/router/match-middleware/index.js +80 -0
- package/dist/router/match-middleware/index.js.map +1 -0
- package/dist/router/match-middleware/intercept-resolution.d.ts +117 -0
- package/dist/router/match-middleware/intercept-resolution.d.ts.map +1 -0
- package/dist/router/match-middleware/intercept-resolution.js +134 -0
- package/dist/router/match-middleware/intercept-resolution.js.map +1 -0
- package/dist/router/match-middleware/segment-resolution.d.ts +99 -0
- package/dist/router/match-middleware/segment-resolution.d.ts.map +1 -0
- package/dist/router/match-middleware/segment-resolution.js +53 -0
- package/dist/router/match-middleware/segment-resolution.js.map +1 -0
- package/dist/router/match-pipelines.d.ts +147 -0
- package/dist/router/match-pipelines.d.ts.map +1 -0
- package/dist/router/match-pipelines.js +82 -0
- package/dist/router/match-pipelines.js.map +1 -0
- package/dist/router/match-result.d.ts +126 -0
- package/dist/router/match-result.d.ts.map +1 -0
- package/dist/router/match-result.js +93 -0
- package/dist/router/match-result.js.map +1 -0
- package/dist/router/metrics.d.ts +20 -0
- package/dist/router/metrics.d.ts.map +1 -0
- package/dist/router/metrics.js +47 -0
- package/dist/router/metrics.js.map +1 -0
- package/dist/router/middleware.d.ts +249 -0
- package/dist/router/middleware.d.ts.map +1 -0
- package/dist/router/middleware.js +434 -0
- package/dist/router/middleware.js.map +1 -0
- package/dist/router/middleware.test.d.ts +2 -0
- package/dist/router/middleware.test.d.ts.map +1 -0
- package/dist/router/middleware.test.js +816 -0
- package/dist/router/middleware.test.js.map +1 -0
- package/dist/router/pattern-matching.d.ts +149 -0
- package/dist/router/pattern-matching.d.ts.map +1 -0
- package/dist/router/pattern-matching.js +349 -0
- package/dist/router/pattern-matching.js.map +1 -0
- package/dist/router/revalidation.d.ts +44 -0
- package/dist/router/revalidation.d.ts.map +1 -0
- package/dist/router/revalidation.js +147 -0
- package/dist/router/revalidation.js.map +1 -0
- package/dist/router/router-context.d.ts +135 -0
- package/dist/router/router-context.d.ts.map +1 -0
- package/dist/router/router-context.js +36 -0
- package/dist/router/router-context.js.map +1 -0
- package/dist/router/segment-resolution.d.ts +127 -0
- package/dist/router/segment-resolution.d.ts.map +1 -0
- package/dist/router/segment-resolution.js +919 -0
- package/dist/router/segment-resolution.js.map +1 -0
- package/dist/router/trie-matching.d.ts +40 -0
- package/dist/router/trie-matching.d.ts.map +1 -0
- package/dist/router/trie-matching.js +127 -0
- package/dist/router/trie-matching.js.map +1 -0
- package/dist/router/types.d.ts +136 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +7 -0
- package/dist/router/types.js.map +1 -0
- package/dist/router.d.ts +753 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.gen.d.ts +6 -0
- package/dist/router.gen.d.ts.map +1 -0
- package/dist/router.gen.js +6 -0
- package/dist/router.gen.js.map +1 -0
- package/dist/router.js +1304 -0
- package/dist/router.js.map +1 -0
- package/dist/rsc/__tests__/helpers.test.d.ts +2 -0
- package/dist/rsc/__tests__/helpers.test.d.ts.map +1 -0
- package/dist/rsc/__tests__/helpers.test.js +140 -0
- package/dist/rsc/__tests__/helpers.test.js.map +1 -0
- package/dist/rsc/handler.d.ts +45 -0
- package/dist/rsc/handler.d.ts.map +1 -0
- package/dist/rsc/handler.js +1172 -0
- package/dist/rsc/handler.js.map +1 -0
- package/dist/rsc/helpers.d.ts +16 -0
- package/dist/rsc/helpers.d.ts.map +1 -0
- package/dist/rsc/helpers.js +55 -0
- package/dist/rsc/helpers.js.map +1 -0
- package/dist/rsc/index.d.ts +22 -0
- package/dist/rsc/index.d.ts.map +1 -0
- package/dist/rsc/index.js +23 -0
- package/dist/rsc/index.js.map +1 -0
- package/dist/rsc/nonce.d.ts +9 -0
- package/dist/rsc/nonce.d.ts.map +1 -0
- package/dist/rsc/nonce.js +18 -0
- package/dist/rsc/nonce.js.map +1 -0
- package/dist/rsc/types.d.ts +206 -0
- package/dist/rsc/types.d.ts.map +1 -0
- package/dist/rsc/types.js +8 -0
- package/dist/rsc/types.js.map +1 -0
- package/dist/search-params.d.ts +103 -0
- package/dist/search-params.d.ts.map +1 -0
- package/dist/search-params.js +74 -0
- package/dist/search-params.js.map +1 -0
- package/dist/segment-system.d.ts +75 -0
- package/dist/segment-system.d.ts.map +1 -0
- package/dist/segment-system.js +336 -0
- package/dist/segment-system.js.map +1 -0
- package/dist/server/context.d.ts +245 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +197 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/fetchable-loader-store.d.ts +18 -0
- package/dist/server/fetchable-loader-store.d.ts.map +1 -0
- package/dist/server/fetchable-loader-store.js +18 -0
- package/dist/server/fetchable-loader-store.js.map +1 -0
- package/dist/server/handle-store.d.ts +85 -0
- package/dist/server/handle-store.d.ts.map +1 -0
- package/dist/server/handle-store.js +142 -0
- package/dist/server/handle-store.js.map +1 -0
- package/dist/server/loader-registry.d.ts +55 -0
- package/dist/server/loader-registry.d.ts.map +1 -0
- package/dist/server/loader-registry.js +132 -0
- package/dist/server/loader-registry.js.map +1 -0
- package/dist/server/request-context.d.ts +226 -0
- package/dist/server/request-context.d.ts.map +1 -0
- package/dist/server/request-context.js +290 -0
- package/dist/server/request-context.js.map +1 -0
- package/dist/server/root-layout.d.ts +4 -0
- package/dist/server/root-layout.d.ts.map +1 -0
- package/dist/server/root-layout.js +5 -0
- package/dist/server/root-layout.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +20 -0
- package/dist/server.js.map +1 -0
- package/dist/ssr/__tests__/ssr-handler.test.d.ts +2 -0
- package/dist/ssr/__tests__/ssr-handler.test.d.ts.map +1 -0
- package/dist/ssr/__tests__/ssr-handler.test.js +132 -0
- package/dist/ssr/__tests__/ssr-handler.test.js.map +1 -0
- package/dist/ssr/index.d.ts +98 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/index.js +158 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/static-handler.d.ts +50 -0
- package/dist/static-handler.d.ts.map +1 -0
- package/dist/static-handler.gen.d.ts +5 -0
- package/dist/static-handler.gen.d.ts.map +1 -0
- package/dist/static-handler.gen.js +5 -0
- package/dist/static-handler.gen.js.map +1 -0
- package/dist/static-handler.js +29 -0
- package/dist/static-handler.js.map +1 -0
- package/dist/theme/ThemeProvider.d.ts +20 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +240 -0
- package/dist/theme/ThemeProvider.js.map +1 -0
- package/dist/theme/ThemeScript.d.ts +48 -0
- package/dist/theme/ThemeScript.d.ts.map +1 -0
- package/dist/theme/ThemeScript.js +13 -0
- package/dist/theme/ThemeScript.js.map +1 -0
- package/dist/theme/__tests__/theme.test.d.ts +2 -0
- package/dist/theme/__tests__/theme.test.d.ts.map +1 -0
- package/dist/theme/__tests__/theme.test.js +103 -0
- package/dist/theme/__tests__/theme.test.js.map +1 -0
- package/dist/theme/constants.d.ts +29 -0
- package/dist/theme/constants.d.ts.map +1 -0
- package/dist/theme/constants.js +48 -0
- package/dist/theme/constants.js.map +1 -0
- package/dist/theme/index.d.ts +31 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +36 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/theme-context.d.ts +40 -0
- package/dist/theme/theme-context.d.ts.map +1 -0
- package/dist/theme/theme-context.js +60 -0
- package/dist/theme/theme-context.js.map +1 -0
- package/dist/theme/theme-script.d.ts +27 -0
- package/dist/theme/theme-script.d.ts.map +1 -0
- package/dist/theme/theme-script.js +147 -0
- package/dist/theme/theme-script.js.map +1 -0
- package/dist/theme/types.d.ts +163 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +11 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/theme/use-theme.d.ts +12 -0
- package/dist/theme/use-theme.d.ts.map +1 -0
- package/dist/theme/use-theme.js +40 -0
- package/dist/theme/use-theme.js.map +1 -0
- package/dist/types.d.ts +1479 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/urls.d.ts +441 -0
- package/dist/urls.d.ts.map +1 -0
- package/dist/urls.gen.d.ts +8 -0
- package/dist/urls.gen.d.ts.map +1 -0
- package/dist/urls.gen.js +8 -0
- package/dist/urls.gen.js.map +1 -0
- package/dist/urls.js +443 -0
- package/dist/urls.js.map +1 -0
- package/dist/use-loader.d.ts +127 -0
- package/dist/use-loader.d.ts.map +1 -0
- package/dist/use-loader.js +237 -0
- package/dist/use-loader.js.map +1 -0
- package/dist/vite/__tests__/ast-handler-extract.test.d.ts +2 -0
- package/dist/vite/__tests__/ast-handler-extract.test.d.ts.map +1 -0
- package/dist/vite/__tests__/ast-handler-extract.test.js +294 -0
- package/dist/vite/__tests__/ast-handler-extract.test.js.map +1 -0
- package/dist/vite/__tests__/expose-id-utils.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-id-utils.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-id-utils.test.js +224 -0
- package/dist/vite/__tests__/expose-id-utils.test.js.map +1 -0
- package/dist/vite/__tests__/expose-internal-ids.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-internal-ids.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-internal-ids.test.js +647 -0
- package/dist/vite/__tests__/expose-internal-ids.test.js.map +1 -0
- package/dist/vite/__tests__/expose-router-id.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-router-id.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-router-id.test.js +39 -0
- package/dist/vite/__tests__/expose-router-id.test.js.map +1 -0
- package/dist/vite/ast-handler-extract.d.ts +49 -0
- package/dist/vite/ast-handler-extract.d.ts.map +1 -0
- package/dist/vite/ast-handler-extract.js +249 -0
- package/dist/vite/ast-handler-extract.js.map +1 -0
- package/dist/vite/expose-action-id.d.ts +19 -0
- package/dist/vite/expose-action-id.d.ts.map +1 -0
- package/dist/vite/expose-action-id.js +250 -0
- package/dist/vite/expose-action-id.js.map +1 -0
- package/dist/vite/expose-id-utils.d.ts +69 -0
- package/dist/vite/expose-id-utils.d.ts.map +1 -0
- package/dist/vite/expose-id-utils.js +289 -0
- package/dist/vite/expose-id-utils.js.map +1 -0
- package/dist/vite/expose-internal-ids.d.ts +22 -0
- package/dist/vite/expose-internal-ids.d.ts.map +1 -0
- package/dist/vite/expose-internal-ids.js +886 -0
- package/dist/vite/expose-internal-ids.js.map +1 -0
- package/dist/vite/index.d.ts +149 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +4630 -749
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/index.named-routes.gen.ts +103 -0
- package/dist/vite/package-resolution.d.ts +43 -0
- package/dist/vite/package-resolution.d.ts.map +1 -0
- package/dist/vite/package-resolution.js +112 -0
- package/dist/vite/package-resolution.js.map +1 -0
- package/dist/vite/virtual-entries.d.ts +25 -0
- package/dist/vite/virtual-entries.d.ts.map +1 -0
- package/{src/vite/virtual-entries.ts → dist/vite/virtual-entries.js} +18 -17
- package/dist/vite/virtual-entries.js.map +1 -0
- package/package.json +82 -46
- package/skills/cache-guide/SKILL.md +262 -0
- package/skills/caching/SKILL.md +139 -238
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +112 -0
- package/skills/document-cache/SKILL.md +87 -57
- package/skills/fonts/SKILL.md +167 -0
- package/skills/hooks/SKILL.md +403 -60
- package/skills/intercept/SKILL.md +224 -203
- package/skills/layout/SKILL.md +243 -149
- package/skills/links/SKILL.md +239 -0
- package/skills/loader/SKILL.md +444 -253
- package/skills/middleware/SKILL.md +222 -325
- package/skills/mime-routes/SKILL.md +128 -0
- package/skills/parallel/SKILL.md +220 -170
- package/skills/prerender/SKILL.md +643 -0
- package/skills/rango/SKILL.md +119 -0
- package/skills/response-routes/SKILL.md +411 -0
- package/skills/route/SKILL.md +334 -89
- package/skills/router-setup/SKILL.md +305 -274
- package/skills/tailwind/SKILL.md +129 -0
- package/skills/testing/SKILL.md +226 -0
- package/skills/theme/SKILL.md +36 -11
- package/skills/typesafety/SKILL.md +437 -168
- package/skills/use-cache/SKILL.md +324 -0
- package/src/__internal.ts +181 -0
- package/src/bin/rango.ts +321 -0
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/event-controller.ts +87 -64
- package/src/browser/history-state.ts +80 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +20 -4
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +217 -549
- package/src/browser/navigation-client.ts +74 -46
- package/src/browser/navigation-store.ts +33 -50
- package/src/browser/navigation-transaction.ts +295 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +288 -297
- package/src/browser/prefetch/cache.ts +67 -0
- package/src/browser/prefetch/fetch.ts +137 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +42 -0
- package/src/browser/prefetch/queue.ts +88 -0
- package/src/browser/rango-state.ts +112 -0
- package/src/browser/react/Link.tsx +173 -73
- package/src/browser/react/NavigationProvider.tsx +138 -27
- package/src/browser/react/context.ts +6 -0
- package/src/browser/react/filter-segment-order.ts +11 -0
- package/src/browser/react/index.ts +12 -12
- package/src/browser/react/location-state-shared.ts +95 -53
- package/src/browser/react/location-state.ts +60 -15
- package/src/browser/react/mount-context.ts +37 -0
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +29 -51
- package/src/browser/react/use-client-cache.ts +5 -3
- package/src/browser/react/use-handle.ts +49 -65
- package/src/browser/react/use-href.tsx +20 -188
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-mount.ts +31 -0
- package/src/browser/react/use-navigation.ts +27 -78
- package/src/browser/react/use-params.ts +65 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-router.ts +63 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +80 -97
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +104 -34
- package/src/browser/scroll-restoration.ts +92 -16
- package/src/browser/segment-reconciler.ts +216 -0
- package/src/browser/segment-structure-assert.ts +83 -0
- package/src/browser/server-action-bridge.ts +504 -584
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +107 -57
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +438 -0
- package/src/build/generate-route-types.ts +36 -0
- package/src/build/index.ts +35 -0
- package/src/build/route-trie.ts +249 -0
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +411 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +469 -0
- package/src/build/route-types/scan-filter.ts +78 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +338 -0
- package/src/cache/cache-scope.ts +120 -303
- package/src/cache/cf/cf-cache-store.ts +119 -7
- package/src/cache/cf/index.ts +8 -2
- package/src/cache/document-cache.ts +101 -72
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +0 -15
- package/src/cache/memory-segment-store.ts +191 -13
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +98 -0
- package/src/cache/types.ts +76 -121
- package/src/client.rsc.tsx +10 -14
- package/src/client.tsx +114 -89
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +6 -2
- package/src/context-var.ts +86 -0
- package/src/debug.ts +243 -0
- package/src/errors.ts +108 -2
- package/src/handle.ts +34 -19
- package/src/handles/MetaTags.tsx +76 -23
- package/src/handles/meta.ts +32 -15
- package/src/host/cookie-handler.ts +165 -0
- package/src/host/errors.ts +97 -0
- package/src/host/index.ts +56 -0
- package/src/host/pattern-matcher.ts +214 -0
- package/src/host/router.ts +352 -0
- package/src/host/testing.ts +79 -0
- package/src/host/types.ts +146 -0
- package/src/host/utils.ts +25 -0
- package/src/href-client.ts +141 -47
- package/src/index.rsc.ts +209 -23
- package/src/index.ts +256 -32
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +27 -142
- package/src/loader.ts +27 -10
- package/src/network-error-thrower.tsx +3 -1
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +37 -0
- package/src/prerender/store.ts +185 -0
- package/src/prerender.ts +463 -0
- package/src/reverse.ts +330 -0
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +9 -11
- package/src/route-definition/dsl-helpers.ts +934 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +430 -0
- package/src/route-definition/index.ts +55 -0
- package/src/route-definition/redirect.ts +93 -0
- package/src/route-definition/route-function.ts +119 -0
- package/src/route-definition.ts +1 -1371
- package/src/route-map-builder.ts +241 -112
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +70 -9
- package/src/router/content-negotiation.ts +116 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +9 -9
- package/src/router/find-match.ts +158 -0
- package/src/router/handler-context.ts +348 -82
- package/src/router/intercept-resolution.ts +395 -0
- package/src/router/lazy-includes.ts +234 -0
- package/src/router/loader-resolution.ts +215 -121
- package/src/router/logging.ts +248 -0
- package/src/router/manifest.ts +172 -43
- package/src/router/match-api.ts +620 -0
- package/src/router/match-context.ts +6 -4
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +80 -93
- package/src/router/match-middleware/cache-lookup.ts +382 -9
- package/src/router/match-middleware/cache-store.ts +51 -22
- package/src/router/match-middleware/intercept-resolution.ts +55 -17
- package/src/router/match-middleware/segment-resolution.ts +24 -6
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +34 -20
- package/src/router/metrics.ts +3 -3
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +179 -0
- package/src/router/middleware.ts +239 -328
- package/src/router/pattern-matching.ts +302 -26
- package/src/router/prerender-match.ts +398 -0
- package/src/router/preview-match.ts +170 -0
- package/src/router/revalidation.ts +112 -33
- package/src/router/router-context.ts +40 -23
- package/src/router/router-interfaces.ts +439 -0
- package/src/router/router-options.ts +587 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +552 -0
- package/src/router/segment-resolution/helpers.ts +263 -0
- package/src/router/segment-resolution/loader-cache.ts +198 -0
- package/src/router/segment-resolution/revalidation.ts +1226 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -0
- package/src/router/segment-wrappers.ts +289 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +221 -0
- package/src/router/types.ts +78 -4
- package/src/router.ts +672 -3566
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +691 -757
- package/src/rsc/helpers.ts +140 -6
- package/src/rsc/index.ts +5 -5
- package/src/rsc/loader-fetch.ts +209 -0
- package/src/rsc/manifest-init.ts +86 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +366 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +347 -0
- package/src/rsc/rsc-rendering.ts +250 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +344 -0
- package/src/rsc/types.ts +38 -14
- package/src/search-params.ts +227 -0
- package/src/segment-system.tsx +59 -61
- package/src/server/context.ts +217 -49
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +98 -20
- package/src/server/loader-registry.ts +15 -56
- package/src/server/request-context.ts +406 -65
- package/src/server.ts +32 -133
- package/src/ssr/index.tsx +157 -26
- package/src/static-handler.ts +114 -0
- package/src/theme/ThemeProvider.tsx +21 -15
- package/src/theme/ThemeScript.tsx +5 -5
- package/src/theme/constants.ts +11 -4
- package/src/theme/index.ts +6 -7
- package/src/theme/theme-context.ts +5 -31
- package/src/theme/theme-script.ts +21 -18
- package/src/theme/types.ts +1 -1
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +691 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +183 -0
- package/src/types/route-config.ts +161 -0
- package/src/types/route-entry.ts +102 -0
- package/src/types/segments.ts +153 -0
- package/src/types.ts +1 -1561
- package/src/urls/include-helper.ts +197 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +339 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +95 -0
- package/src/urls/response-types.ts +106 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -726
- package/src/use-loader.tsx +85 -77
- package/src/vite/discovery/bundle-postprocess.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +345 -0
- package/src/vite/discovery/prerender-collection.ts +385 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +47 -0
- package/src/vite/discovery/state.ts +110 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +10 -782
- package/src/vite/plugin-types.ts +131 -0
- package/src/vite/plugins/cjs-to-esm.ts +93 -0
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/client-ref-hashing.ts +105 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +72 -51
- package/src/vite/plugins/expose-id-utils.ts +287 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +569 -0
- package/src/vite/plugins/use-cache-transform.ts +323 -0
- package/src/vite/plugins/version-injector.ts +83 -0
- package/src/vite/plugins/version-plugin.ts +254 -0
- package/src/vite/plugins/virtual-entries.ts +123 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +510 -0
- package/src/vite/router-discovery.ts +785 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/{package-resolution.ts → utils/package-resolution.ts} +25 -29
- package/src/vite/utils/prerender-utils.ts +189 -0
- package/src/vite/utils/shared-utils.ts +169 -0
- package/CLAUDE.md +0 -7
- package/src/__tests__/component-utils.test.ts +0 -76
- package/src/__tests__/route-definition.test.ts +0 -63
- package/src/__tests__/urls.test.tsx +0 -436
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/request-controller.ts +0 -164
- package/src/cache/__tests__/document-cache.test.ts +0 -522
- package/src/cache/__tests__/memory-segment-store.test.ts +0 -487
- package/src/cache/__tests__/memory-store.test.ts +0 -484
- package/src/cache/cf/__tests__/cf-cache-store.test.ts +0 -428
- package/src/cache/memory-store.ts +0 -253
- package/src/href.ts +0 -177
- package/src/route-utils.ts +0 -89
- package/src/router/__tests__/match-context.test.ts +0 -104
- package/src/router/__tests__/match-pipelines.test.ts +0 -537
- package/src/router/__tests__/match-result.test.ts +0 -566
- package/src/router/__tests__/on-error.test.ts +0 -935
- package/src/router/__tests__/pattern-matching.test.ts +0 -577
- package/src/router/middleware.test.ts +0 -1355
- package/src/rsc/__tests__/helpers.test.ts +0 -175
- package/src/server/__tests__/request-context.test.ts +0 -171
- package/src/ssr/__tests__/ssr-handler.test.tsx +0 -188
- package/src/theme/__tests__/theme.test.ts +0 -120
- package/src/vite/__tests__/expose-loader-id.test.ts +0 -117
- package/src/vite/expose-handle-id.ts +0 -209
- package/src/vite/expose-loader-id.ts +0 -357
- package/src/vite/expose-location-state-id.ts +0 -177
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
package/dist/router.js
ADDED
|
@@ -0,0 +1,1304 @@
|
|
|
1
|
+
import { createCacheScope } from "./cache/cache-scope.js";
|
|
2
|
+
import { assertClientComponent } from "./component-utils.js";
|
|
3
|
+
import { DefaultDocument } from "./components/DefaultDocument.js";
|
|
4
|
+
import { sanitizeError, } from "./errors";
|
|
5
|
+
import { serializeManifest } from "./debug.js";
|
|
6
|
+
import { createReverse, } from "./reverse.js";
|
|
7
|
+
import { registerRouteMap, getGlobalRouteMap, getPrecomputedEntries, getRouteTrie, getRouterManifest, getRouterTrie, getRouterPrecomputedEntries, ensureRouterManifest, } from "./route-map-builder.js";
|
|
8
|
+
import { tryTrieMatch } from "./router/trie-matching.js";
|
|
9
|
+
import { createRouteHelpers, } from "./route-definition.js";
|
|
10
|
+
import MapRootLayout from "./server/root-layout.js";
|
|
11
|
+
import { getContext, RSCRouterContext, runWithPrefixes, } from "./server/context";
|
|
12
|
+
import { createHandleStore } from "./server/handle-store.js";
|
|
13
|
+
import { getRequestContext } from "./server/request-context.js";
|
|
14
|
+
import { runWithRequestContext, } from "./server/request-context.js";
|
|
15
|
+
// Extracted router utilities
|
|
16
|
+
import { createErrorInfo, findNearestErrorBoundary as findErrorBoundary, findNearestNotFoundBoundary as findNotFoundBoundary, invokeOnError, } from "./router/error-handling.js";
|
|
17
|
+
// Extracted segment resolution functions
|
|
18
|
+
import { resolveAllSegments as _resolveAllSegments, resolveLoadersOnly as _resolveLoadersOnly, resolveLoadersOnlyWithRevalidation as _resolveLoadersOnlyWithRevalidation, buildEntryRevalidateMap as _buildEntryRevalidateMap, resolveAllSegmentsWithRevalidation as _resolveAllSegmentsWithRevalidation, } from "./router/segment-resolution.js";
|
|
19
|
+
// Extracted intercept resolution functions
|
|
20
|
+
import { findInterceptForRoute as _findInterceptForRoute, resolveInterceptEntry as _resolveInterceptEntry, resolveInterceptLoadersOnly as _resolveInterceptLoadersOnly, } from "./router/intercept-resolution.js";
|
|
21
|
+
// Extracted match API functions
|
|
22
|
+
import { createMatchContextForFull as _createMatchContextForFull, createMatchContextForPartial as _createMatchContextForPartial, matchError as _matchError, } from "./router/match-api.js";
|
|
23
|
+
import { createHandlerContext } from "./router/handler-context.js";
|
|
24
|
+
import { setupLoaderAccess, setupLoaderAccessSilent, setupBuildUse, wrapLoaderWithErrorHandling, } from "./router/loader-resolution.js";
|
|
25
|
+
import { loadManifest } from "./router/manifest.js";
|
|
26
|
+
import { createMetricsStore, } from "./router/metrics.js";
|
|
27
|
+
import { collectRouteMiddleware, parsePattern, } from "./router/middleware.js";
|
|
28
|
+
import { extractStaticPrefix, findMatch as findRouteMatch, isLazyEvaluationNeeded, traverseBack, } from "./router/pattern-matching.js";
|
|
29
|
+
import { evaluateRevalidation } from "./router/revalidation.js";
|
|
30
|
+
import { runWithRouterContext, } from "./router/router-context.js";
|
|
31
|
+
import { createPipelineState, } from "./router/match-context.js";
|
|
32
|
+
import { createMatchPartialPipeline } from "./router/match-pipelines.js";
|
|
33
|
+
import { collectMatchResult } from "./router/match-result.js";
|
|
34
|
+
import { runWithRouterLogContext, withRouterLogScope, } from "./router/logging.js";
|
|
35
|
+
import { resolveThemeConfig } from "./theme/constants.js";
|
|
36
|
+
// Response type -> MIME type used for Accept header matching
|
|
37
|
+
const RESPONSE_TYPE_MIME = {
|
|
38
|
+
json: "application/json",
|
|
39
|
+
text: "text/plain",
|
|
40
|
+
xml: "application/xml",
|
|
41
|
+
html: "text/html",
|
|
42
|
+
md: "text/markdown",
|
|
43
|
+
};
|
|
44
|
+
// Reverse lookup: MIME type -> response type tag (e.g. "text/html" -> "html")
|
|
45
|
+
const MIME_RESPONSE_TYPE = Object.fromEntries(Object.entries(RESPONSE_TYPE_MIME).map(([tag, mime]) => [mime, tag]));
|
|
46
|
+
/**
|
|
47
|
+
* Parse an Accept header into a sorted array of MIME entries.
|
|
48
|
+
* Respects q-values (default 1.0) and uses client order as tiebreaker
|
|
49
|
+
* when q-values are equal (matching Express/Hono behavior).
|
|
50
|
+
*/
|
|
51
|
+
function parseAcceptTypes(accept) {
|
|
52
|
+
const entries = [];
|
|
53
|
+
const parts = accept.split(",");
|
|
54
|
+
for (let i = 0; i < parts.length; i++) {
|
|
55
|
+
const part = parts[i];
|
|
56
|
+
const segments = part.split(";");
|
|
57
|
+
const mime = segments[0].trim();
|
|
58
|
+
if (!mime)
|
|
59
|
+
continue;
|
|
60
|
+
let q = 1.0;
|
|
61
|
+
for (let j = 1; j < segments.length; j++) {
|
|
62
|
+
const param = segments[j].trim();
|
|
63
|
+
if (param.startsWith("q=")) {
|
|
64
|
+
q = Math.max(0, Math.min(1, Number(param.slice(2)) || 0));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
entries.push({ mime, q, order: i });
|
|
68
|
+
}
|
|
69
|
+
// Sort: highest q first, then lowest client order first (stable)
|
|
70
|
+
entries.sort((a, b) => b.q - a.q || a.order - b.order);
|
|
71
|
+
return entries;
|
|
72
|
+
}
|
|
73
|
+
// Sentinel response type for RSC routes in negotiation candidates
|
|
74
|
+
const RSC_RESPONSE_TYPE = "__rsc__";
|
|
75
|
+
/**
|
|
76
|
+
* Pick the best negotiate variant by walking the client's sorted Accept list.
|
|
77
|
+
* For each accepted MIME type (in q-value/order priority), check if any
|
|
78
|
+
* candidate serves that type. Wildcards (*\/*) match the first candidate.
|
|
79
|
+
* Falls back to the first candidate if nothing matches.
|
|
80
|
+
*/
|
|
81
|
+
function pickNegotiateVariant(acceptEntries, candidates) {
|
|
82
|
+
// Build a MIME -> candidate lookup for O(1) matching
|
|
83
|
+
const byCandidateMime = new Map();
|
|
84
|
+
for (const c of candidates) {
|
|
85
|
+
const mime = c.responseType === RSC_RESPONSE_TYPE ? "text/html" : RESPONSE_TYPE_MIME[c.responseType];
|
|
86
|
+
if (mime && !byCandidateMime.has(mime)) {
|
|
87
|
+
byCandidateMime.set(mime, c);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const entry of acceptEntries) {
|
|
91
|
+
if (entry.q === 0)
|
|
92
|
+
continue;
|
|
93
|
+
// Wildcard matches first candidate
|
|
94
|
+
if (entry.mime === "*/*")
|
|
95
|
+
return candidates[0];
|
|
96
|
+
// Type wildcard (e.g. "text/*") — match first candidate with that type
|
|
97
|
+
if (entry.mime.endsWith("/*")) {
|
|
98
|
+
const typePrefix = entry.mime.slice(0, entry.mime.indexOf("/"));
|
|
99
|
+
for (const [mime, candidate] of byCandidateMime) {
|
|
100
|
+
if (mime.startsWith(typePrefix + "/"))
|
|
101
|
+
return candidate;
|
|
102
|
+
}
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const match = byCandidateMime.get(entry.mime);
|
|
106
|
+
if (match)
|
|
107
|
+
return match;
|
|
108
|
+
}
|
|
109
|
+
// No match — use first candidate as default
|
|
110
|
+
return candidates[0];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Router configuration options
|
|
114
|
+
*/
|
|
115
|
+
/**
|
|
116
|
+
* Brand marker for identifying router instances at build time.
|
|
117
|
+
* Used by the Vite plugin to auto-discover routers from module exports.
|
|
118
|
+
*/
|
|
119
|
+
export const RSC_ROUTER_BRAND = "__rsc_router__";
|
|
120
|
+
/**
|
|
121
|
+
* Global registry of all router instances created via createRouter().
|
|
122
|
+
* Each router is keyed by its id (auto-generated or user-provided).
|
|
123
|
+
* Used by the Vite plugin at build time to discover routers and extract
|
|
124
|
+
* manifests, prefix trees, and pre-render candidates.
|
|
125
|
+
*/
|
|
126
|
+
export const RouterRegistry = new Map();
|
|
127
|
+
let routerAutoId = 0;
|
|
128
|
+
/**
|
|
129
|
+
* Create an RSC router with generic context type
|
|
130
|
+
* Route types are accumulated automatically through the builder chain
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* interface AppContext {
|
|
135
|
+
* db: Database;
|
|
136
|
+
* user?: User;
|
|
137
|
+
* }
|
|
138
|
+
*
|
|
139
|
+
* const router = createRouter<AppContext>({
|
|
140
|
+
* debugPerformance: true // Enable metrics
|
|
141
|
+
* });
|
|
142
|
+
*
|
|
143
|
+
* // Route types accumulate through the chain - no module augmentation needed!
|
|
144
|
+
* // Keys stay unchanged, only URL patterns get the prefix
|
|
145
|
+
* router
|
|
146
|
+
* .routes(homeRoutes) // accumulates homeRoutes
|
|
147
|
+
* .map(() => import('./home'))
|
|
148
|
+
* .routes('/shop', shopRoutes) // accumulates shopRoutes with prefixed URLs
|
|
149
|
+
* .map(() => import('./shop'));
|
|
150
|
+
*
|
|
151
|
+
* // router.reverse now has type-safe autocomplete for all registered routes
|
|
152
|
+
* // Given shopRoutes = { cart: "/cart" }, reverse uses original key:
|
|
153
|
+
* router.reverse("cart"); // "/shop/cart"
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export function createRouter(options = {}) {
|
|
157
|
+
const { id: userProvidedId, $$id: injectedId, debugPerformance = false, document: documentOption, defaultErrorBoundary, defaultNotFoundBoundary, notFound, onError, cache, theme: themeOption, urls: urlsOption, $$routeNames: staticRouteNames, nonce, version, warmup: warmupOption, allowDebugManifest: allowDebugManifestOption = true, } = options;
|
|
158
|
+
// Capture the source file that called createRouter() via stack trace parsing.
|
|
159
|
+
// Used by the Vite plugin to write per-router named-routes.gen.ts files.
|
|
160
|
+
let __sourceFile;
|
|
161
|
+
try {
|
|
162
|
+
const stack = new Error().stack;
|
|
163
|
+
if (stack) {
|
|
164
|
+
const lines = stack.split("\n");
|
|
165
|
+
for (const line of lines) {
|
|
166
|
+
const match = line.match(/\((.+?\.(ts|tsx|js|jsx)):\d+:\d+\)/);
|
|
167
|
+
if (match && !match[1].endsWith("/router.ts") && !match[1].includes("@rangojs/router") && !match[1].includes("node_modules")) {
|
|
168
|
+
// Strip file: URL protocol prefix from Vite module runner stack traces
|
|
169
|
+
__sourceFile = match[1].startsWith("file:") ? match[1].slice(5) : match[1];
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch { }
|
|
176
|
+
// Router ID priority: explicit id > Vite-injected $$id > counter fallback.
|
|
177
|
+
// $$id is a hash of filename+line injected by the Vite transform at compile
|
|
178
|
+
// time, so it's stable across build/runtime regardless of module evaluation
|
|
179
|
+
// order (unlike the counter which depends on import order).
|
|
180
|
+
const routerId = userProvidedId ?? injectedId ?? `router_${routerAutoId++}`;
|
|
181
|
+
// Resolve warmup enabled flag (default: true)
|
|
182
|
+
const warmupEnabled = warmupOption !== false;
|
|
183
|
+
// Resolve theme config (null if theme not enabled)
|
|
184
|
+
const resolvedThemeConfig = themeOption
|
|
185
|
+
? resolveThemeConfig(themeOption)
|
|
186
|
+
: null;
|
|
187
|
+
/**
|
|
188
|
+
* Wrapper for invokeOnError that binds the router's onError callback.
|
|
189
|
+
* Uses the shared utility from router/error-handling.ts for consistent behavior.
|
|
190
|
+
*/
|
|
191
|
+
function callOnError(error, phase, context) {
|
|
192
|
+
invokeOnError(onError, error, phase, context, "Router");
|
|
193
|
+
}
|
|
194
|
+
// Validate document is a client component
|
|
195
|
+
if (documentOption !== undefined) {
|
|
196
|
+
assertClientComponent(documentOption, "document");
|
|
197
|
+
}
|
|
198
|
+
// Use default document if none provided (keeps internal name as rootLayout)
|
|
199
|
+
const rootLayout = documentOption ?? DefaultDocument;
|
|
200
|
+
const routesEntries = [];
|
|
201
|
+
let mountIndex = 0;
|
|
202
|
+
// Store reference to urlpatterns for runtime manifest generation
|
|
203
|
+
let storedUrlPatterns = null;
|
|
204
|
+
// Global middleware storage
|
|
205
|
+
const globalMiddleware = [];
|
|
206
|
+
// Helper to add middleware entry
|
|
207
|
+
function addMiddleware(patternOrMiddleware, middleware, mountPrefix = null) {
|
|
208
|
+
let pattern = null;
|
|
209
|
+
let handler;
|
|
210
|
+
if (typeof patternOrMiddleware === "string") {
|
|
211
|
+
// Pattern + middleware
|
|
212
|
+
pattern = patternOrMiddleware;
|
|
213
|
+
if (!middleware) {
|
|
214
|
+
throw new Error("Middleware function required when pattern is provided");
|
|
215
|
+
}
|
|
216
|
+
handler = middleware;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// Just middleware (no pattern)
|
|
220
|
+
handler = patternOrMiddleware;
|
|
221
|
+
}
|
|
222
|
+
// If mount-scoped, prepend mount prefix to pattern
|
|
223
|
+
let fullPattern = pattern;
|
|
224
|
+
if (mountPrefix && pattern) {
|
|
225
|
+
// e.g., mountPrefix="/blog", pattern="/admin/*" → "/blog/admin/*"
|
|
226
|
+
fullPattern =
|
|
227
|
+
pattern === "*" ? `${mountPrefix}/*` : `${mountPrefix}${pattern}`;
|
|
228
|
+
}
|
|
229
|
+
else if (mountPrefix && !pattern) {
|
|
230
|
+
// Mount-scoped middleware without pattern applies to all of mount
|
|
231
|
+
fullPattern = `${mountPrefix}/*`;
|
|
232
|
+
}
|
|
233
|
+
// Parse pattern into regex
|
|
234
|
+
let regex = null;
|
|
235
|
+
let paramNames = [];
|
|
236
|
+
if (fullPattern) {
|
|
237
|
+
const parsed = parsePattern(fullPattern);
|
|
238
|
+
regex = parsed.regex;
|
|
239
|
+
paramNames = parsed.paramNames;
|
|
240
|
+
}
|
|
241
|
+
globalMiddleware.push({
|
|
242
|
+
pattern: fullPattern,
|
|
243
|
+
regex,
|
|
244
|
+
paramNames,
|
|
245
|
+
handler,
|
|
246
|
+
mountPrefix,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
// Track all registered routes with their prefixes for reverse()
|
|
250
|
+
const mergedRouteMap = {};
|
|
251
|
+
// Lazy precomputed entries lookup: rebuilt when per-router data arrives.
|
|
252
|
+
// In production multi-router setups, per-router data is loaded lazily via
|
|
253
|
+
// ensureRouterManifest(). At createRouter() time the data isn't available yet,
|
|
254
|
+
// so we defer building the Map until first use and invalidate when the
|
|
255
|
+
// per-router source changes.
|
|
256
|
+
let precomputedByPrefix = null;
|
|
257
|
+
let precomputedSource;
|
|
258
|
+
function getPrecomputedByPrefix() {
|
|
259
|
+
const current = getRouterPrecomputedEntries(routerId) ?? getPrecomputedEntries();
|
|
260
|
+
if (current !== precomputedSource) {
|
|
261
|
+
precomputedSource = current;
|
|
262
|
+
precomputedByPrefix = current
|
|
263
|
+
? new Map(current.map((e) => [e.staticPrefix, e.routes]))
|
|
264
|
+
: null;
|
|
265
|
+
}
|
|
266
|
+
return precomputedByPrefix;
|
|
267
|
+
}
|
|
268
|
+
// Wrapper to pass debugPerformance to external createMetricsStore
|
|
269
|
+
const getMetricsStore = () => createMetricsStore(debugPerformance);
|
|
270
|
+
// Wrapper to pass defaults to error/notFound boundary finders
|
|
271
|
+
const findNearestErrorBoundary = (entry) => findErrorBoundary(entry, defaultErrorBoundary);
|
|
272
|
+
const findNearestNotFoundBoundary = (entry) => findNotFoundBoundary(entry, defaultNotFoundBoundary);
|
|
273
|
+
// Helper to get handleStore from request context
|
|
274
|
+
const getHandleStore = () => {
|
|
275
|
+
return getRequestContext()?._handleStore;
|
|
276
|
+
};
|
|
277
|
+
// Track a pending handler promise (non-blocking)
|
|
278
|
+
const trackHandler = (promise) => {
|
|
279
|
+
const store = getHandleStore();
|
|
280
|
+
return store ? store.track(promise) : promise;
|
|
281
|
+
};
|
|
282
|
+
// Wrapper for wrapLoaderWithErrorHandling that uses router's error boundary finder
|
|
283
|
+
// Includes onError callback for loader error notification
|
|
284
|
+
function wrapLoaderPromise(promise, entry, segmentId, pathname, errorContext) {
|
|
285
|
+
return wrapLoaderWithErrorHandling(promise, entry, segmentId, pathname, findNearestErrorBoundary, createErrorInfo,
|
|
286
|
+
// Invoke onError when loader fails
|
|
287
|
+
errorContext
|
|
288
|
+
? (error, ctx) => {
|
|
289
|
+
callOnError(error, "loader", {
|
|
290
|
+
request: errorContext.request,
|
|
291
|
+
url: errorContext.url,
|
|
292
|
+
routeKey: errorContext.routeKey,
|
|
293
|
+
params: errorContext.params,
|
|
294
|
+
segmentId: ctx.segmentId,
|
|
295
|
+
segmentType: "loader",
|
|
296
|
+
loaderName: ctx.loaderName,
|
|
297
|
+
env: errorContext.env,
|
|
298
|
+
isPartial: errorContext.isPartial,
|
|
299
|
+
handledByBoundary: ctx.handledByBoundary,
|
|
300
|
+
requestStartTime: errorContext.requestStartTime,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
: undefined);
|
|
304
|
+
}
|
|
305
|
+
// Dependencies object for extracted segment resolution functions.
|
|
306
|
+
// Captures closure-bound helpers from createRouter.
|
|
307
|
+
const segmentDeps = {
|
|
308
|
+
wrapLoaderPromise,
|
|
309
|
+
trackHandler,
|
|
310
|
+
findNearestErrorBoundary,
|
|
311
|
+
findNearestNotFoundBoundary,
|
|
312
|
+
callOnError,
|
|
313
|
+
};
|
|
314
|
+
// Match API dependencies
|
|
315
|
+
const matchApiDeps = {
|
|
316
|
+
findMatch: (pathname, ms) => findMatch(pathname, ms),
|
|
317
|
+
getMetricsStore,
|
|
318
|
+
findInterceptForRoute: (routeKey, parentEntry, selectorContext, isAction) => findInterceptForRoute(routeKey, parentEntry, selectorContext, isAction),
|
|
319
|
+
callOnError,
|
|
320
|
+
findNearestErrorBoundary,
|
|
321
|
+
getRouteMap: () => getRouterManifest(routerId) ?? getGlobalRouteMap(),
|
|
322
|
+
};
|
|
323
|
+
// Thin wrappers that bind the deps to extracted functions.
|
|
324
|
+
// These maintain the same signatures as the original inline functions
|
|
325
|
+
// so that RouterContext and call sites don't need to change.
|
|
326
|
+
function resolveAllSegments(entries, routeKey, params, context, loaderPromises, options) {
|
|
327
|
+
return _resolveAllSegments(entries, routeKey, params, context, loaderPromises, segmentDeps, options);
|
|
328
|
+
}
|
|
329
|
+
function resolveLoadersOnly(entries, context) {
|
|
330
|
+
return _resolveLoadersOnly(entries, context, segmentDeps);
|
|
331
|
+
}
|
|
332
|
+
function resolveLoadersOnlyWithRevalidation(entries, context, clientSegmentIds, prevParams, request, prevUrl, nextUrl, routeKey, actionContext) {
|
|
333
|
+
return _resolveLoadersOnlyWithRevalidation(entries, context, clientSegmentIds, prevParams, request, prevUrl, nextUrl, routeKey, segmentDeps, actionContext);
|
|
334
|
+
}
|
|
335
|
+
function buildEntryRevalidateMap(entries) {
|
|
336
|
+
return _buildEntryRevalidateMap(entries);
|
|
337
|
+
}
|
|
338
|
+
function resolveAllSegmentsWithRevalidation(entries, routeKey, params, context, clientSegmentSet, prevParams, request, prevUrl, nextUrl, loaderPromises, actionContext, interceptResult, localRouteName, pathname) {
|
|
339
|
+
return _resolveAllSegmentsWithRevalidation(entries, routeKey, params, context, clientSegmentSet, prevParams, request, prevUrl, nextUrl, loaderPromises, actionContext, interceptResult, localRouteName, pathname, segmentDeps);
|
|
340
|
+
}
|
|
341
|
+
function findInterceptForRoute(targetRouteKey, fromEntry, selectorContext = null, isAction = false) {
|
|
342
|
+
return _findInterceptForRoute(targetRouteKey, fromEntry, selectorContext, isAction);
|
|
343
|
+
}
|
|
344
|
+
function resolveInterceptEntry(interceptEntry, parentEntry, params, context, belongsToRoute = true, revalidationContext) {
|
|
345
|
+
return _resolveInterceptEntry(interceptEntry, parentEntry, params, context, belongsToRoute, segmentDeps, revalidationContext);
|
|
346
|
+
}
|
|
347
|
+
function resolveInterceptLoadersOnly(interceptEntry, parentEntry, params, context, belongsToRoute = true, revalidationContext) {
|
|
348
|
+
return _resolveInterceptLoadersOnly(interceptEntry, parentEntry, params, context, belongsToRoute, segmentDeps, revalidationContext);
|
|
349
|
+
}
|
|
350
|
+
// Detect lazy includes in handler result and create placeholder entries
|
|
351
|
+
// Lazy includes are IncludeItem with lazy: true and _lazyContext
|
|
352
|
+
// Moved to outer scope so it can be reused by evaluateLazyEntry for nested includes
|
|
353
|
+
function findLazyIncludes(items) {
|
|
354
|
+
const lazyItems = [];
|
|
355
|
+
for (const item of items) {
|
|
356
|
+
if (!item)
|
|
357
|
+
continue;
|
|
358
|
+
if (item.type === "include") {
|
|
359
|
+
const includeItem = item;
|
|
360
|
+
if (includeItem.lazy === true && includeItem._lazyContext) {
|
|
361
|
+
lazyItems.push({
|
|
362
|
+
prefix: includeItem.prefix,
|
|
363
|
+
patterns: includeItem.patterns,
|
|
364
|
+
context: includeItem._lazyContext,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// Recursively check nested items (in layouts, etc.)
|
|
369
|
+
if (item.uses && Array.isArray(item.uses)) {
|
|
370
|
+
lazyItems.push(...findLazyIncludes(item.uses));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return lazyItems;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Evaluate a lazy entry's patterns and populate its routes
|
|
377
|
+
* This runs the lazy patterns handler and updates the entry in-place
|
|
378
|
+
* Also detects nested lazy includes and registers them as new entries
|
|
379
|
+
*/
|
|
380
|
+
function evaluateLazyEntry(entry) {
|
|
381
|
+
if (!entry.lazy || entry.lazyEvaluated || !entry.lazyPatterns) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
// Check for pre-computed routes from build-time data.
|
|
385
|
+
// Only leaf nodes (no nested includes) are precomputed, so entries with
|
|
386
|
+
// nested lazy includes fall through to the handler below.
|
|
387
|
+
// When multiple entries share the same staticPrefix (e.g., several
|
|
388
|
+
// include("/", ...) calls), the precomputed data merges all their routes
|
|
389
|
+
// into one entry. Assigning that merged set to the first matching entry
|
|
390
|
+
// causes findMatch to pick the wrong handler for routes belonging to a
|
|
391
|
+
// different include. Skip the shortcut when the prefix is shared.
|
|
392
|
+
const currentPrecomputed = getPrecomputedByPrefix();
|
|
393
|
+
if (currentPrecomputed) {
|
|
394
|
+
const routes = currentPrecomputed.get(entry.staticPrefix);
|
|
395
|
+
if (routes) {
|
|
396
|
+
const prefixIsShared = routesEntries.filter((e) => e.staticPrefix === entry.staticPrefix).length > 1;
|
|
397
|
+
if (!prefixIsShared) {
|
|
398
|
+
entry.lazyEvaluated = true;
|
|
399
|
+
entry.routes = routes;
|
|
400
|
+
for (const [name, pattern] of Object.entries(routes)) {
|
|
401
|
+
mergedRouteMap[name] = pattern;
|
|
402
|
+
}
|
|
403
|
+
registerRouteMap(mergedRouteMap);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
// Mark as evaluated immediately to prevent concurrent evaluation.
|
|
409
|
+
// JS is single-threaded but handlers.handler() could theoretically yield,
|
|
410
|
+
// and the while-loop in findMatch retries after evaluation.
|
|
411
|
+
entry.lazyEvaluated = true;
|
|
412
|
+
const lazyPatterns = entry.lazyPatterns;
|
|
413
|
+
const lazyContext = entry.lazyContext;
|
|
414
|
+
// Create a new context for evaluating the lazy patterns
|
|
415
|
+
const manifest = new Map();
|
|
416
|
+
const patterns = new Map();
|
|
417
|
+
const patternsByPrefix = new Map();
|
|
418
|
+
const trailingSlashMap = new Map();
|
|
419
|
+
// Capture the handler result to detect nested lazy includes
|
|
420
|
+
let handlerResult = [];
|
|
421
|
+
// Merge captured counters from include() to maintain consistent
|
|
422
|
+
// shortCode indices with sibling entries from pattern extraction
|
|
423
|
+
const lazyCounters = {};
|
|
424
|
+
if (lazyContext && lazyContext.counters) {
|
|
425
|
+
const captured = lazyContext.counters;
|
|
426
|
+
for (const [key, value] of Object.entries(captured)) {
|
|
427
|
+
lazyCounters[key] = value;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
RSCRouterContext.run({
|
|
431
|
+
manifest,
|
|
432
|
+
patterns,
|
|
433
|
+
patternsByPrefix,
|
|
434
|
+
trailingSlash: trailingSlashMap,
|
|
435
|
+
namespace: "lazy",
|
|
436
|
+
parent: lazyContext?.parent ?? null,
|
|
437
|
+
counters: lazyCounters,
|
|
438
|
+
}, () => {
|
|
439
|
+
// Run the lazy patterns handler with the original context prefixes
|
|
440
|
+
// The prefix comes from the IncludeItem stored in lazyPatterns
|
|
441
|
+
const includePrefix = entry._lazyPrefix || "";
|
|
442
|
+
const fullPrefix = (lazyContext?.urlPrefix || "") + includePrefix;
|
|
443
|
+
if (fullPrefix || lazyContext?.namePrefix) {
|
|
444
|
+
runWithPrefixes(fullPrefix, lazyContext?.namePrefix, () => {
|
|
445
|
+
handlerResult = lazyPatterns.handler();
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
handlerResult = lazyPatterns.handler();
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
// Populate the entry's routes from the patterns
|
|
453
|
+
const routesObject = {};
|
|
454
|
+
for (const [name, pattern] of patterns.entries()) {
|
|
455
|
+
routesObject[name] = pattern;
|
|
456
|
+
// Also add to merged route map for reverse() support
|
|
457
|
+
const existingPattern = mergedRouteMap[name];
|
|
458
|
+
if (existingPattern !== undefined && existingPattern !== pattern) {
|
|
459
|
+
console.warn(`[@rangojs/router] Route name conflict: "${name}" already maps to "${existingPattern}", ` +
|
|
460
|
+
`overwriting with "${pattern}" (from lazy include). Use unique route names to avoid this.`);
|
|
461
|
+
}
|
|
462
|
+
mergedRouteMap[name] = pattern;
|
|
463
|
+
}
|
|
464
|
+
// Update the entry in-place
|
|
465
|
+
entry.routes = routesObject;
|
|
466
|
+
// Note: Do NOT clear lazyPatterns/lazyContext here.
|
|
467
|
+
// loadManifest() needs them on every request to re-run the handler
|
|
468
|
+
// in the correct AsyncLocalStorage context (Store.manifest).
|
|
469
|
+
// Update trailing slash config if available
|
|
470
|
+
if (trailingSlashMap.size > 0) {
|
|
471
|
+
entry.trailingSlash = Object.fromEntries(trailingSlashMap);
|
|
472
|
+
}
|
|
473
|
+
// Detect nested lazy includes and register them as new entries
|
|
474
|
+
const nestedLazyIncludes = findLazyIncludes(handlerResult);
|
|
475
|
+
for (const lazyInclude of nestedLazyIncludes) {
|
|
476
|
+
// Compute the full URL prefix (combining parent prefix if any)
|
|
477
|
+
const fullPrefix = lazyInclude.context.urlPrefix
|
|
478
|
+
? lazyInclude.context.urlPrefix + lazyInclude.prefix
|
|
479
|
+
: lazyInclude.prefix;
|
|
480
|
+
const nestedEntry = {
|
|
481
|
+
prefix: "",
|
|
482
|
+
staticPrefix: extractStaticPrefix(fullPrefix),
|
|
483
|
+
routes: {}, // Empty until first match
|
|
484
|
+
trailingSlash: entry.trailingSlash,
|
|
485
|
+
handler: lazyInclude.patterns.handler,
|
|
486
|
+
mountIndex: mountIndex++,
|
|
487
|
+
// Lazy evaluation fields
|
|
488
|
+
lazy: true,
|
|
489
|
+
lazyPatterns: lazyInclude.patterns,
|
|
490
|
+
lazyContext: lazyInclude.context,
|
|
491
|
+
lazyEvaluated: false,
|
|
492
|
+
// Store the include prefix for evaluation
|
|
493
|
+
_lazyPrefix: lazyInclude.prefix,
|
|
494
|
+
};
|
|
495
|
+
// Insert nested lazy entry before any entry whose staticPrefix is a
|
|
496
|
+
// prefix of (but shorter than) this lazy entry's staticPrefix.
|
|
497
|
+
// This ensures more specific lazy includes are matched before
|
|
498
|
+
// less specific eager entries (e.g., "/href/nested" before "/href/:id").
|
|
499
|
+
const nestedPrefix = nestedEntry.staticPrefix;
|
|
500
|
+
let insertIndex = routesEntries.length;
|
|
501
|
+
if (nestedPrefix) {
|
|
502
|
+
for (let i = 0; i < routesEntries.length; i++) {
|
|
503
|
+
const existing = routesEntries[i];
|
|
504
|
+
if (nestedPrefix.startsWith(existing.staticPrefix) &&
|
|
505
|
+
nestedPrefix.length > existing.staticPrefix.length) {
|
|
506
|
+
insertIndex = i;
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
routesEntries.splice(insertIndex, 0, nestedEntry);
|
|
512
|
+
}
|
|
513
|
+
// Re-register route map for runtime reverse() usage
|
|
514
|
+
registerRouteMap(mergedRouteMap);
|
|
515
|
+
}
|
|
516
|
+
// Single-entry cache for findMatch to avoid redundant matching within the same request.
|
|
517
|
+
// previewMatch and match both call findMatch with the same pathname — this ensures
|
|
518
|
+
// the route matching work (which may check thousands of routes) only happens once.
|
|
519
|
+
let lastFindMatchPathname = null;
|
|
520
|
+
let lastFindMatchResult = null;
|
|
521
|
+
// Wrapper for findMatch that uses routesEntries
|
|
522
|
+
// Handles lazy evaluation by evaluating lazy entries on first match.
|
|
523
|
+
// Phase 1: try O(path_length) trie match.
|
|
524
|
+
// Phase 2: fall back to regex iteration.
|
|
525
|
+
function findMatch(pathname, ms) {
|
|
526
|
+
// Return cached result if same pathname (avoids double-match per request)
|
|
527
|
+
if (lastFindMatchPathname === pathname) {
|
|
528
|
+
return lastFindMatchResult;
|
|
529
|
+
}
|
|
530
|
+
// Helper to push sub-metrics
|
|
531
|
+
const pushMetric = ms
|
|
532
|
+
? (label, start) => {
|
|
533
|
+
ms.metrics.push({
|
|
534
|
+
label,
|
|
535
|
+
duration: performance.now() - start,
|
|
536
|
+
startTime: start - ms.requestStart,
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
: undefined;
|
|
540
|
+
// Phase 1: Try trie match (O(path_length))
|
|
541
|
+
// Prefer per-router trie (isolated) over global trie (merged).
|
|
542
|
+
const routeTrie = getRouterTrie(routerId) ?? getRouteTrie();
|
|
543
|
+
if (routeTrie) {
|
|
544
|
+
const trieStart = performance.now();
|
|
545
|
+
const trieResult = tryTrieMatch(routeTrie, pathname);
|
|
546
|
+
pushMetric?.("match:trie", trieStart);
|
|
547
|
+
if (trieResult) {
|
|
548
|
+
// Find the RouteEntry that contains this route.
|
|
549
|
+
// Multiple entries can share the same staticPrefix (e.g., several
|
|
550
|
+
// include("/", patterns) calls all produce staticPrefix=""). Evaluate
|
|
551
|
+
// each candidate and pick the one whose routes include the matched key.
|
|
552
|
+
const entryStart = performance.now();
|
|
553
|
+
let entry;
|
|
554
|
+
let fallbackEntry;
|
|
555
|
+
for (const e of routesEntries) {
|
|
556
|
+
if (e.staticPrefix !== trieResult.sp)
|
|
557
|
+
continue;
|
|
558
|
+
if (!fallbackEntry)
|
|
559
|
+
fallbackEntry = e;
|
|
560
|
+
evaluateLazyEntry(e);
|
|
561
|
+
if (e.routes &&
|
|
562
|
+
trieResult.routeKey in e.routes) {
|
|
563
|
+
entry = e;
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
// If no entry had the route in its routes map, use the first matching
|
|
568
|
+
// entry as fallback (handles main entry with inline routes not yet
|
|
569
|
+
// reflected in its routes object).
|
|
570
|
+
if (!entry)
|
|
571
|
+
entry = fallbackEntry;
|
|
572
|
+
// If entry not found (nested include not yet discovered), evaluate parent
|
|
573
|
+
if (!entry) {
|
|
574
|
+
const parent = routesEntries.find((e) => trieResult.sp.startsWith(e.staticPrefix) &&
|
|
575
|
+
e.staticPrefix !== trieResult.sp);
|
|
576
|
+
if (parent) {
|
|
577
|
+
const lazyStart = performance.now();
|
|
578
|
+
evaluateLazyEntry(parent);
|
|
579
|
+
pushMetric?.("match:lazy-eval", lazyStart);
|
|
580
|
+
}
|
|
581
|
+
entry = routesEntries.find((e) => e.staticPrefix === trieResult.sp);
|
|
582
|
+
}
|
|
583
|
+
pushMetric?.("match:entry-resolve", entryStart);
|
|
584
|
+
if (entry) {
|
|
585
|
+
lastFindMatchPathname = pathname;
|
|
586
|
+
lastFindMatchResult = {
|
|
587
|
+
entry,
|
|
588
|
+
routeKey: trieResult.routeKey,
|
|
589
|
+
params: trieResult.params,
|
|
590
|
+
optionalParams: new Set(trieResult.optionalParams || []),
|
|
591
|
+
redirectTo: trieResult.redirectTo,
|
|
592
|
+
ancestry: trieResult.ancestry,
|
|
593
|
+
...(trieResult.pr ? { pr: true } : {}),
|
|
594
|
+
...(trieResult.pt ? { pt: true } : {}),
|
|
595
|
+
...(trieResult.responseType ? { responseType: trieResult.responseType } : {}),
|
|
596
|
+
...(trieResult.negotiateVariants ? { negotiateVariants: trieResult.negotiateVariants } : {}),
|
|
597
|
+
...(trieResult.rscFirst ? { rscFirst: true } : {}),
|
|
598
|
+
};
|
|
599
|
+
return lastFindMatchResult;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
// Phase 2: Fall back to existing matching (regex iteration)
|
|
604
|
+
const regexStart = performance.now();
|
|
605
|
+
let result = findRouteMatch(pathname, routesEntries);
|
|
606
|
+
// If we hit a lazy entry that needs evaluation, evaluate and retry.
|
|
607
|
+
// Cap iterations to prevent infinite loops from pathological nesting.
|
|
608
|
+
const MAX_LAZY_ITERATIONS = 100;
|
|
609
|
+
let iterations = 0;
|
|
610
|
+
while (isLazyEvaluationNeeded(result)) {
|
|
611
|
+
if (++iterations > MAX_LAZY_ITERATIONS) {
|
|
612
|
+
console.error(`[@rangojs/router] Exceeded ${MAX_LAZY_ITERATIONS} lazy evaluation iterations ` +
|
|
613
|
+
`for pathname "${pathname}". This likely indicates circular lazy includes.`);
|
|
614
|
+
lastFindMatchPathname = pathname;
|
|
615
|
+
lastFindMatchResult = null;
|
|
616
|
+
return null;
|
|
617
|
+
}
|
|
618
|
+
evaluateLazyEntry(result.lazyEntry);
|
|
619
|
+
result = findRouteMatch(pathname, routesEntries);
|
|
620
|
+
}
|
|
621
|
+
pushMetric?.("match:regex-fallback", regexStart);
|
|
622
|
+
lastFindMatchPathname = pathname;
|
|
623
|
+
lastFindMatchResult = result;
|
|
624
|
+
return result;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Build-time pre-render match. Resolves segments with a BuildContext
|
|
628
|
+
* (no request/env/headers/cookies), skipping middleware and loaders.
|
|
629
|
+
*/
|
|
630
|
+
async function matchForPrerender(pathname, params) {
|
|
631
|
+
// 1. Find the matching route entry
|
|
632
|
+
const matched = findMatch(pathname);
|
|
633
|
+
if (!matched)
|
|
634
|
+
return null;
|
|
635
|
+
// Use params from trie match if available, fall back to provided params
|
|
636
|
+
const matchedParams = matched.params ?? params;
|
|
637
|
+
// Build a minimal RouterContext for loadManifest/traverseBack
|
|
638
|
+
const routerCtx = {
|
|
639
|
+
findMatch,
|
|
640
|
+
loadManifest,
|
|
641
|
+
traverseBack,
|
|
642
|
+
createHandlerContext,
|
|
643
|
+
setupLoaderAccess,
|
|
644
|
+
setupLoaderAccessSilent,
|
|
645
|
+
getContext,
|
|
646
|
+
getMetricsStore,
|
|
647
|
+
createCacheScope,
|
|
648
|
+
findInterceptForRoute,
|
|
649
|
+
resolveAllSegmentsWithRevalidation,
|
|
650
|
+
resolveInterceptEntry,
|
|
651
|
+
evaluateRevalidation,
|
|
652
|
+
getRequestContext,
|
|
653
|
+
resolveAllSegments,
|
|
654
|
+
createHandleStore,
|
|
655
|
+
buildEntryRevalidateMap,
|
|
656
|
+
resolveLoadersOnlyWithRevalidation,
|
|
657
|
+
resolveInterceptLoadersOnly,
|
|
658
|
+
resolveLoadersOnly,
|
|
659
|
+
};
|
|
660
|
+
return runWithRouterContext(routerCtx, async () => {
|
|
661
|
+
// 2. Load the manifest entry tree
|
|
662
|
+
const manifestEntry = await loadManifest(matched.entry, matched.routeKey, pathname, undefined, false);
|
|
663
|
+
// 3. Build ancestor chain [root, ..., route]
|
|
664
|
+
const entries = [];
|
|
665
|
+
for (const entry of traverseBack(manifestEntry)) {
|
|
666
|
+
entries.push(entry);
|
|
667
|
+
}
|
|
668
|
+
// 4. Create handle store for collecting handle data
|
|
669
|
+
const handleStore = createHandleStore();
|
|
670
|
+
// 5. Create a minimal request context with the handle store
|
|
671
|
+
const stubRes = new Response(null, { status: 200 });
|
|
672
|
+
const minimalRequestContext = {
|
|
673
|
+
env: {},
|
|
674
|
+
request: new Request("http://prerender" + pathname),
|
|
675
|
+
url: new URL("http://prerender" + pathname),
|
|
676
|
+
pathname,
|
|
677
|
+
searchParams: new URLSearchParams(),
|
|
678
|
+
var: {},
|
|
679
|
+
get: () => undefined,
|
|
680
|
+
set: () => { },
|
|
681
|
+
params: matchedParams,
|
|
682
|
+
res: stubRes,
|
|
683
|
+
cookie: () => undefined,
|
|
684
|
+
cookies: () => ({}),
|
|
685
|
+
setCookie: () => { },
|
|
686
|
+
deleteCookie: () => { },
|
|
687
|
+
header: () => { },
|
|
688
|
+
use: (() => {
|
|
689
|
+
throw new Error("use() not available during pre-rendering");
|
|
690
|
+
}),
|
|
691
|
+
method: "GET",
|
|
692
|
+
_handleStore: handleStore,
|
|
693
|
+
waitUntil: () => { },
|
|
694
|
+
onResponse: () => { },
|
|
695
|
+
_onResponseCallbacks: [],
|
|
696
|
+
};
|
|
697
|
+
return runWithRequestContext(minimalRequestContext, async () => {
|
|
698
|
+
// 6. Create handler context with synthetic request for pre-rendering.
|
|
699
|
+
// The synthetic request and route map are available at build time,
|
|
700
|
+
// so reverse() and other context properties work normally.
|
|
701
|
+
const buildCtx = createHandlerContext(matchedParams, minimalRequestContext.request, minimalRequestContext.url.searchParams, pathname, minimalRequestContext.url, {}, mergedRouteMap, matched.routeKey);
|
|
702
|
+
// 7. Wire use() for handles only (loaders throw)
|
|
703
|
+
setupBuildUse(buildCtx);
|
|
704
|
+
// 8. Resolve all segments with skipLoaders
|
|
705
|
+
const loaderPromises = new Map();
|
|
706
|
+
const allSegments = await resolveAllSegments(entries, matched.routeKey, matchedParams, buildCtx, loaderPromises, { skipLoaders: true });
|
|
707
|
+
// 9. Filter out any loader segments (belt-and-suspenders)
|
|
708
|
+
const nonLoaderSegments = allSegments.filter((s) => s.type !== "loader");
|
|
709
|
+
// 10. Wait for handles to settle
|
|
710
|
+
await handleStore.settled;
|
|
711
|
+
// 11. Serialize segments using the cache serializer
|
|
712
|
+
const { serializeSegments } = await import("./cache/cache-scope.js");
|
|
713
|
+
const serializedSegments = await serializeSegments(nonLoaderSegments);
|
|
714
|
+
// 12. Collect handle data per segment (skip segments with no handle data)
|
|
715
|
+
const handles = {};
|
|
716
|
+
for (const seg of nonLoaderSegments) {
|
|
717
|
+
const segHandles = handleStore.getDataForSegment(seg.id);
|
|
718
|
+
if (Object.keys(segHandles).length > 0) {
|
|
719
|
+
handles[seg.id] = segHandles;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
// Use the trie-level route key (e.g., "docs", "docs.article")
|
|
723
|
+
const routeName = matched.routeKey;
|
|
724
|
+
return {
|
|
725
|
+
segments: serializedSegments,
|
|
726
|
+
handles,
|
|
727
|
+
routeName,
|
|
728
|
+
params: matchedParams,
|
|
729
|
+
};
|
|
730
|
+
});
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Match request and return segments (document/SSR requests)
|
|
735
|
+
*
|
|
736
|
+
* Uses generator middleware pipeline for clean separation of concerns:
|
|
737
|
+
* - cache-lookup: Check cache first
|
|
738
|
+
* - segment-resolution: Resolve segments on cache miss
|
|
739
|
+
* - cache-store: Store results in cache
|
|
740
|
+
* - background-revalidation: SWR revalidation
|
|
741
|
+
*/
|
|
742
|
+
async function match(request, env) {
|
|
743
|
+
// Build RouterContext with all closure functions needed by middleware
|
|
744
|
+
const routerCtx = {
|
|
745
|
+
findMatch,
|
|
746
|
+
loadManifest,
|
|
747
|
+
traverseBack,
|
|
748
|
+
createHandlerContext,
|
|
749
|
+
setupLoaderAccess,
|
|
750
|
+
setupLoaderAccessSilent,
|
|
751
|
+
getContext,
|
|
752
|
+
getMetricsStore,
|
|
753
|
+
createCacheScope,
|
|
754
|
+
findInterceptForRoute,
|
|
755
|
+
resolveAllSegmentsWithRevalidation,
|
|
756
|
+
resolveInterceptEntry,
|
|
757
|
+
evaluateRevalidation,
|
|
758
|
+
getRequestContext,
|
|
759
|
+
resolveAllSegments,
|
|
760
|
+
createHandleStore,
|
|
761
|
+
buildEntryRevalidateMap,
|
|
762
|
+
resolveLoadersOnlyWithRevalidation,
|
|
763
|
+
resolveInterceptLoadersOnly,
|
|
764
|
+
resolveLoadersOnly,
|
|
765
|
+
};
|
|
766
|
+
return runWithRouterLogContext({ request, transaction: "match" }, () => runWithRouterContext(routerCtx, async () => withRouterLogScope("match", async () => {
|
|
767
|
+
const result = await createMatchContextForFull(request, env);
|
|
768
|
+
// Handle redirect case
|
|
769
|
+
if ("type" in result && result.type === "redirect") {
|
|
770
|
+
return {
|
|
771
|
+
segments: [],
|
|
772
|
+
matched: [],
|
|
773
|
+
diff: [],
|
|
774
|
+
params: {},
|
|
775
|
+
redirect: result.redirectUrl,
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
const ctx = result;
|
|
779
|
+
try {
|
|
780
|
+
const state = createPipelineState();
|
|
781
|
+
const pipeline = createMatchPartialPipeline(ctx, state);
|
|
782
|
+
return await collectMatchResult(pipeline, ctx, state);
|
|
783
|
+
}
|
|
784
|
+
catch (error) {
|
|
785
|
+
if (error instanceof Response)
|
|
786
|
+
throw error;
|
|
787
|
+
// Report unhandled errors during full match pipeline
|
|
788
|
+
callOnError(error, "routing", {
|
|
789
|
+
request,
|
|
790
|
+
url: ctx.url,
|
|
791
|
+
env,
|
|
792
|
+
isPartial: false,
|
|
793
|
+
handledByBoundary: false,
|
|
794
|
+
});
|
|
795
|
+
throw sanitizeError(error);
|
|
796
|
+
}
|
|
797
|
+
})));
|
|
798
|
+
}
|
|
799
|
+
async function matchError(request, _context, error, segmentType = "route") {
|
|
800
|
+
return runWithRouterLogContext({ request, transaction: "matchError" }, () => withRouterLogScope("matchError", () => _matchError(request, _context, error, matchApiDeps, defaultErrorBoundary, segmentType)));
|
|
801
|
+
}
|
|
802
|
+
async function createMatchContextForFull(request, env) {
|
|
803
|
+
return _createMatchContextForFull(request, env, matchApiDeps, findInterceptForRoute);
|
|
804
|
+
}
|
|
805
|
+
async function createMatchContextForPartial(request, env, actionContext) {
|
|
806
|
+
return _createMatchContextForPartial(request, env, matchApiDeps, findInterceptForRoute, actionContext);
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Match partial request with revalidation
|
|
810
|
+
*
|
|
811
|
+
* Uses generator middleware pipeline for clean separation of concerns:
|
|
812
|
+
* - cache-lookup: Check cache first
|
|
813
|
+
* - segment-resolution: Resolve segments on cache miss
|
|
814
|
+
* - intercept-resolution: Handle intercept routes
|
|
815
|
+
* - cache-store: Store results in cache
|
|
816
|
+
* - background-revalidation: SWR revalidation
|
|
817
|
+
*/
|
|
818
|
+
async function matchPartial(request, context, actionContext) {
|
|
819
|
+
// Build RouterContext with all closure functions needed by middleware
|
|
820
|
+
const routerCtx = {
|
|
821
|
+
findMatch,
|
|
822
|
+
loadManifest,
|
|
823
|
+
traverseBack,
|
|
824
|
+
createHandlerContext,
|
|
825
|
+
setupLoaderAccess,
|
|
826
|
+
setupLoaderAccessSilent,
|
|
827
|
+
getContext,
|
|
828
|
+
getMetricsStore,
|
|
829
|
+
createCacheScope,
|
|
830
|
+
findInterceptForRoute,
|
|
831
|
+
resolveAllSegmentsWithRevalidation,
|
|
832
|
+
resolveInterceptEntry,
|
|
833
|
+
evaluateRevalidation,
|
|
834
|
+
getRequestContext,
|
|
835
|
+
resolveAllSegments,
|
|
836
|
+
createHandleStore,
|
|
837
|
+
buildEntryRevalidateMap,
|
|
838
|
+
resolveLoadersOnlyWithRevalidation,
|
|
839
|
+
resolveInterceptLoadersOnly,
|
|
840
|
+
};
|
|
841
|
+
return runWithRouterLogContext({ request, transaction: "matchPartial" }, () => runWithRouterContext(routerCtx, async () => withRouterLogScope("matchPartial", async () => {
|
|
842
|
+
const ctx = await createMatchContextForPartial(request, context, actionContext);
|
|
843
|
+
if (!ctx)
|
|
844
|
+
return null;
|
|
845
|
+
try {
|
|
846
|
+
const state = createPipelineState();
|
|
847
|
+
const pipeline = createMatchPartialPipeline(ctx, state);
|
|
848
|
+
return await collectMatchResult(pipeline, ctx, state);
|
|
849
|
+
}
|
|
850
|
+
catch (error) {
|
|
851
|
+
if (error instanceof Response)
|
|
852
|
+
throw error;
|
|
853
|
+
// Report unhandled errors during partial match pipeline
|
|
854
|
+
callOnError(error, actionContext ? "action" : "revalidation", {
|
|
855
|
+
request,
|
|
856
|
+
url: ctx.url,
|
|
857
|
+
env: context,
|
|
858
|
+
actionId: actionContext?.actionId,
|
|
859
|
+
isPartial: true,
|
|
860
|
+
handledByBoundary: false,
|
|
861
|
+
});
|
|
862
|
+
throw sanitizeError(error);
|
|
863
|
+
}
|
|
864
|
+
})));
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Preview match - returns route middleware without segment resolution.
|
|
868
|
+
* Also returns responseType and handler for response routes (non-RSC short-circuit).
|
|
869
|
+
*/
|
|
870
|
+
async function previewMatch(request, _context) {
|
|
871
|
+
return runWithRouterLogContext({ request, transaction: "previewMatch" }, async () => withRouterLogScope("previewMatch", async () => {
|
|
872
|
+
const url = new URL(request.url);
|
|
873
|
+
const pathname = url.pathname;
|
|
874
|
+
// Quick route matching
|
|
875
|
+
const matched = findMatch(pathname);
|
|
876
|
+
if (!matched) {
|
|
877
|
+
return null;
|
|
878
|
+
}
|
|
879
|
+
// Skip redirect check - will be handled in full match
|
|
880
|
+
if (matched.redirectTo) {
|
|
881
|
+
return { routeMiddleware: undefined };
|
|
882
|
+
}
|
|
883
|
+
// Load manifest (without segment resolution)
|
|
884
|
+
const manifestEntry = await loadManifest(matched.entry, matched.routeKey, pathname, undefined, // No metrics store for preview
|
|
885
|
+
false);
|
|
886
|
+
// Collect route-level middleware from entry tree
|
|
887
|
+
// Includes middleware from orphan layouts (inline layouts within routes)
|
|
888
|
+
const routeMiddleware = collectRouteMiddleware(traverseBack(manifestEntry), matched.params);
|
|
889
|
+
// Check for response type (from trie match or manifest entry)
|
|
890
|
+
const responseType = matched.responseType ||
|
|
891
|
+
(manifestEntry.type === "route" ? manifestEntry.responseType : undefined);
|
|
892
|
+
// Content negotiation: when negotiate variants exist, pick the best
|
|
893
|
+
// handler based on the Accept header. Uses q-values and client order
|
|
894
|
+
// as tiebreaker (matching Express/Hono behavior). RSC routes participate
|
|
895
|
+
// as text/html candidates so browsers naturally get HTML without
|
|
896
|
+
// special-casing.
|
|
897
|
+
if (matched.negotiateVariants && matched.negotiateVariants.length > 0) {
|
|
898
|
+
const acceptEntries = parseAcceptTypes(request.headers.get("accept") || "");
|
|
899
|
+
// Build candidate list preserving definition order.
|
|
900
|
+
// For wildcard (*/*) and no-Accept fallback, the first candidate wins.
|
|
901
|
+
const variants = matched.negotiateVariants;
|
|
902
|
+
let candidates;
|
|
903
|
+
if (responseType) {
|
|
904
|
+
// Primary is response-type — include it as a candidate
|
|
905
|
+
candidates = [...variants, { routeKey: matched.routeKey, responseType }];
|
|
906
|
+
}
|
|
907
|
+
else {
|
|
908
|
+
// Primary is RSC — insert as text/html candidate in definition order
|
|
909
|
+
const rscCandidate = { routeKey: matched.routeKey, responseType: RSC_RESPONSE_TYPE };
|
|
910
|
+
candidates = matched.rscFirst
|
|
911
|
+
? [rscCandidate, ...variants]
|
|
912
|
+
: [...variants, rscCandidate];
|
|
913
|
+
}
|
|
914
|
+
const variant = pickNegotiateVariant(acceptEntries, candidates);
|
|
915
|
+
// If the winner is RSC, fall through to default RSC handling
|
|
916
|
+
if (variant.responseType === RSC_RESPONSE_TYPE) {
|
|
917
|
+
// Fall through — RSC won negotiation
|
|
918
|
+
}
|
|
919
|
+
else if (responseType && variant.routeKey === matched.routeKey) {
|
|
920
|
+
// Fall through — response-type primary won, already set
|
|
921
|
+
}
|
|
922
|
+
else {
|
|
923
|
+
const negotiateEntry = await loadManifest(matched.entry, variant.routeKey, pathname, undefined, false);
|
|
924
|
+
return {
|
|
925
|
+
routeMiddleware: routeMiddleware.length > 0 ? routeMiddleware : undefined,
|
|
926
|
+
responseType: variant.responseType,
|
|
927
|
+
handler: negotiateEntry.type === "route" ? negotiateEntry.handler : undefined,
|
|
928
|
+
params: matched.params,
|
|
929
|
+
negotiated: true,
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
// If we passed through the negotiation block (variants exist), mark as
|
|
934
|
+
// negotiated so the handler sets Vary: Accept on the response.
|
|
935
|
+
const hasVariants = matched.negotiateVariants && matched.negotiateVariants.length > 0;
|
|
936
|
+
return {
|
|
937
|
+
routeMiddleware: routeMiddleware.length > 0 ? routeMiddleware : undefined,
|
|
938
|
+
...(responseType ? {
|
|
939
|
+
responseType,
|
|
940
|
+
handler: manifestEntry.type === "route" ? manifestEntry.handler : undefined,
|
|
941
|
+
params: matched.params,
|
|
942
|
+
} : {}),
|
|
943
|
+
...(hasVariants ? { negotiated: true } : {}),
|
|
944
|
+
};
|
|
945
|
+
}));
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Create route builder with accumulated route types
|
|
949
|
+
* The TNewRoutes type parameter captures the new routes being added
|
|
950
|
+
*/
|
|
951
|
+
function createRouteBuilder(prefix, routes) {
|
|
952
|
+
const currentMountIndex = mountIndex++;
|
|
953
|
+
// Merge routes into the reverse map
|
|
954
|
+
// Keys stay unchanged for composability - only URL patterns get prefixed
|
|
955
|
+
const routeEntries = routes;
|
|
956
|
+
for (const [key, pattern] of Object.entries(routeEntries)) {
|
|
957
|
+
// Build prefixed pattern: "/shop" + "/cart" -> "/shop/cart"
|
|
958
|
+
// Root prefix "/" is a no-op — don't double the leading slash.
|
|
959
|
+
const effectivePrefix = prefix === "/" ? "" : prefix;
|
|
960
|
+
const prefixedPattern = effectivePrefix && pattern !== "/"
|
|
961
|
+
? `${effectivePrefix}${pattern}`
|
|
962
|
+
: effectivePrefix && pattern === "/"
|
|
963
|
+
? effectivePrefix
|
|
964
|
+
: pattern;
|
|
965
|
+
// Runtime validation: warn if key already exists with different pattern
|
|
966
|
+
const existingPattern = mergedRouteMap[key];
|
|
967
|
+
if (existingPattern !== undefined &&
|
|
968
|
+
existingPattern !== prefixedPattern) {
|
|
969
|
+
console.warn(`[rsc-router] Route key conflict: "${key}" already maps to "${existingPattern}", ` +
|
|
970
|
+
`overwriting with "${prefixedPattern}". Use unique key names to avoid this.`);
|
|
971
|
+
}
|
|
972
|
+
// Use original key - enables reusable route modules
|
|
973
|
+
mergedRouteMap[key] = prefixedPattern;
|
|
974
|
+
}
|
|
975
|
+
// Auto-register route map for runtime reverse() usage
|
|
976
|
+
registerRouteMap(mergedRouteMap);
|
|
977
|
+
// Extract trailing slash config if present (attached by route())
|
|
978
|
+
const trailingSlashConfig = routes.__trailingSlash;
|
|
979
|
+
// Create builder object so .use() can return it
|
|
980
|
+
const builder = {
|
|
981
|
+
use(patternOrMiddleware, middleware) {
|
|
982
|
+
// Mount-scoped middleware - prefix is the mount prefix
|
|
983
|
+
addMiddleware(patternOrMiddleware, middleware, prefix || null);
|
|
984
|
+
return builder;
|
|
985
|
+
},
|
|
986
|
+
map(handler) {
|
|
987
|
+
// Store handler as-is - detection happens at call time based on return type
|
|
988
|
+
// Both patterns use the same signature:
|
|
989
|
+
// - Inline: ({ route }) => [...] - receives helpers, returns Array
|
|
990
|
+
// - Lazy: () => import(...) - ignores helpers, returns Promise
|
|
991
|
+
routesEntries.push({
|
|
992
|
+
prefix,
|
|
993
|
+
staticPrefix: extractStaticPrefix(prefix),
|
|
994
|
+
routes: routes,
|
|
995
|
+
trailingSlash: trailingSlashConfig,
|
|
996
|
+
handler: handler,
|
|
997
|
+
mountIndex: currentMountIndex,
|
|
998
|
+
});
|
|
999
|
+
// Return router with accumulated types
|
|
1000
|
+
// At runtime this is the same object, but TypeScript tracks the accumulated route types
|
|
1001
|
+
return router;
|
|
1002
|
+
},
|
|
1003
|
+
// Expose accumulated route map for typeof extraction
|
|
1004
|
+
get routeMap() {
|
|
1005
|
+
return mergedRouteMap;
|
|
1006
|
+
},
|
|
1007
|
+
};
|
|
1008
|
+
return builder;
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Router instance
|
|
1012
|
+
* The type system tracks accumulated routes through the builder chain
|
|
1013
|
+
* Initial TRoutes is {} (empty) to avoid poisoning accumulated types with Record<string, string>
|
|
1014
|
+
*/
|
|
1015
|
+
const router = {
|
|
1016
|
+
__brand: RSC_ROUTER_BRAND,
|
|
1017
|
+
id: routerId,
|
|
1018
|
+
routes(prefixOrRoutes, maybeRoutes) {
|
|
1019
|
+
// Note: Multiple .routes() calls are allowed for backwards compatibility
|
|
1020
|
+
// with the old map() pattern. For new code, prefer urls() with include().
|
|
1021
|
+
// Check if argument is UrlPatterns (new Django-style API)
|
|
1022
|
+
// Detect by checking for handler and definitions properties
|
|
1023
|
+
if (typeof prefixOrRoutes === "object" &&
|
|
1024
|
+
prefixOrRoutes !== null &&
|
|
1025
|
+
"handler" in prefixOrRoutes &&
|
|
1026
|
+
"definitions" in prefixOrRoutes &&
|
|
1027
|
+
typeof prefixOrRoutes.handler === "function") {
|
|
1028
|
+
const urlPatterns = prefixOrRoutes;
|
|
1029
|
+
// Store reference for runtime manifest generation
|
|
1030
|
+
storedUrlPatterns = urlPatterns;
|
|
1031
|
+
const currentMountIndex = mountIndex++;
|
|
1032
|
+
// Create manifest and patterns maps for route registration
|
|
1033
|
+
const manifest = new Map();
|
|
1034
|
+
const patterns = new Map();
|
|
1035
|
+
const patternsByPrefix = new Map();
|
|
1036
|
+
const trailingSlashMap = new Map();
|
|
1037
|
+
// Run the handler once to extract patterns for route matching.
|
|
1038
|
+
// Note: loadManifest will re-run the handler to register entries in its context.
|
|
1039
|
+
// Lazy includes are detected in the return value and handled separately.
|
|
1040
|
+
//
|
|
1041
|
+
// Pattern extraction must use the same mountIndex and MapRootLayout root
|
|
1042
|
+
// parent as loadManifest so that shortCodes produced here match those at
|
|
1043
|
+
// runtime. include() captures the current parent and counters; if those
|
|
1044
|
+
// shortCodes diverge from the runtime tree the segment reconciliation on
|
|
1045
|
+
// the client will see a full mismatch and remount the entire page.
|
|
1046
|
+
const syntheticMapRoot = {
|
|
1047
|
+
type: "layout",
|
|
1048
|
+
id: `#synthetic-maproot-M${currentMountIndex}`,
|
|
1049
|
+
shortCode: `M${currentMountIndex}L0`,
|
|
1050
|
+
parent: null,
|
|
1051
|
+
handler: MapRootLayout,
|
|
1052
|
+
middleware: [],
|
|
1053
|
+
revalidate: [],
|
|
1054
|
+
errorBoundary: [],
|
|
1055
|
+
notFoundBoundary: [],
|
|
1056
|
+
layout: [],
|
|
1057
|
+
parallel: [],
|
|
1058
|
+
intercept: [],
|
|
1059
|
+
loader: [],
|
|
1060
|
+
};
|
|
1061
|
+
let handlerResult = [];
|
|
1062
|
+
RSCRouterContext.run({
|
|
1063
|
+
manifest,
|
|
1064
|
+
patterns,
|
|
1065
|
+
patternsByPrefix,
|
|
1066
|
+
trailingSlash: trailingSlashMap,
|
|
1067
|
+
namespace: "root",
|
|
1068
|
+
parent: syntheticMapRoot,
|
|
1069
|
+
counters: {},
|
|
1070
|
+
mountIndex: currentMountIndex,
|
|
1071
|
+
}, () => {
|
|
1072
|
+
handlerResult = urlPatterns.handler();
|
|
1073
|
+
});
|
|
1074
|
+
// Store the ORIGINAL handler - loadManifest will re-run it to register manifest entries
|
|
1075
|
+
// Convert trailingSlash map to object for the router
|
|
1076
|
+
const trailingSlashConfig = trailingSlashMap.size > 0
|
|
1077
|
+
? Object.fromEntries(trailingSlashMap)
|
|
1078
|
+
: undefined;
|
|
1079
|
+
// Collect route keys that have prerender handlers (for non-trie match path)
|
|
1080
|
+
let prerenderRouteKeys;
|
|
1081
|
+
for (const [name, entry] of manifest.entries()) {
|
|
1082
|
+
if (entry.type === "route" && entry.isPrerender) {
|
|
1083
|
+
if (!prerenderRouteKeys)
|
|
1084
|
+
prerenderRouteKeys = new Set();
|
|
1085
|
+
prerenderRouteKeys.add(name);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
// Create separate RouteEntry for each URL prefix group
|
|
1089
|
+
// This enables prefix-based short-circuit optimization
|
|
1090
|
+
if (patternsByPrefix.size > 0) {
|
|
1091
|
+
for (const [prefix, prefixPatterns] of patternsByPrefix.entries()) {
|
|
1092
|
+
const routesObject = {};
|
|
1093
|
+
for (const [name, pattern] of prefixPatterns.entries()) {
|
|
1094
|
+
routesObject[name] = pattern;
|
|
1095
|
+
}
|
|
1096
|
+
routesEntries.push({
|
|
1097
|
+
// prefix is "" because patterns already include the URL prefix
|
|
1098
|
+
// (e.g., "/site/:locale/user1/:id" not just "/user1/:id")
|
|
1099
|
+
prefix: "",
|
|
1100
|
+
// staticPrefix is the actual prefix for short-circuit optimization
|
|
1101
|
+
staticPrefix: extractStaticPrefix(prefix),
|
|
1102
|
+
routes: routesObject,
|
|
1103
|
+
trailingSlash: trailingSlashConfig,
|
|
1104
|
+
handler: urlPatterns.handler,
|
|
1105
|
+
mountIndex: currentMountIndex,
|
|
1106
|
+
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
else {
|
|
1111
|
+
// Fallback: no prefix grouping, use flat patterns map
|
|
1112
|
+
const routesObject = {};
|
|
1113
|
+
for (const [name, pattern] of patterns.entries()) {
|
|
1114
|
+
routesObject[name] = pattern;
|
|
1115
|
+
}
|
|
1116
|
+
routesEntries.push({
|
|
1117
|
+
prefix: "",
|
|
1118
|
+
staticPrefix: "",
|
|
1119
|
+
routes: routesObject,
|
|
1120
|
+
trailingSlash: trailingSlashConfig,
|
|
1121
|
+
handler: urlPatterns.handler,
|
|
1122
|
+
mountIndex: currentMountIndex,
|
|
1123
|
+
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
// Build route map from registered patterns
|
|
1127
|
+
for (const [name, pattern] of patterns.entries()) {
|
|
1128
|
+
// Runtime validation: warn if key already exists with different pattern
|
|
1129
|
+
const existingPattern = mergedRouteMap[name];
|
|
1130
|
+
if (existingPattern !== undefined && existingPattern !== pattern) {
|
|
1131
|
+
console.warn(`[@rangojs/router] Route name conflict: "${name}" already maps to "${existingPattern}", ` +
|
|
1132
|
+
`overwriting with "${pattern}". Use unique route names to avoid this.`);
|
|
1133
|
+
}
|
|
1134
|
+
mergedRouteMap[name] = pattern;
|
|
1135
|
+
}
|
|
1136
|
+
// Detect lazy includes in handler result and create placeholder entries
|
|
1137
|
+
// Uses findLazyIncludes from outer scope (shared with evaluateLazyEntry)
|
|
1138
|
+
const lazyIncludes = findLazyIncludes(handlerResult);
|
|
1139
|
+
// Create placeholder RouteEntry for each lazy include
|
|
1140
|
+
for (const lazyInclude of lazyIncludes) {
|
|
1141
|
+
// Compute the full URL prefix (combining parent prefix if any)
|
|
1142
|
+
const fullPrefix = lazyInclude.context.urlPrefix
|
|
1143
|
+
? lazyInclude.context.urlPrefix + lazyInclude.prefix
|
|
1144
|
+
: lazyInclude.prefix;
|
|
1145
|
+
const lazyEntry = {
|
|
1146
|
+
prefix: "",
|
|
1147
|
+
staticPrefix: extractStaticPrefix(fullPrefix),
|
|
1148
|
+
routes: {}, // Empty until first match
|
|
1149
|
+
trailingSlash: trailingSlashConfig,
|
|
1150
|
+
handler: urlPatterns.handler,
|
|
1151
|
+
mountIndex: mountIndex++,
|
|
1152
|
+
// Lazy evaluation fields
|
|
1153
|
+
lazy: true,
|
|
1154
|
+
lazyPatterns: lazyInclude.patterns,
|
|
1155
|
+
lazyContext: lazyInclude.context,
|
|
1156
|
+
lazyEvaluated: false,
|
|
1157
|
+
// Store the include prefix for evaluation
|
|
1158
|
+
_lazyPrefix: lazyInclude.prefix,
|
|
1159
|
+
};
|
|
1160
|
+
// Insert lazy entry before any entry whose staticPrefix is a
|
|
1161
|
+
// prefix of (but shorter than) this lazy entry's staticPrefix.
|
|
1162
|
+
// This ensures more specific lazy includes are matched before
|
|
1163
|
+
// less specific eager entries (e.g., "/href/nested" before "/href/:id").
|
|
1164
|
+
const lazyPrefix = lazyEntry.staticPrefix;
|
|
1165
|
+
let insertIndex = routesEntries.length;
|
|
1166
|
+
if (lazyPrefix) {
|
|
1167
|
+
for (let i = 0; i < routesEntries.length; i++) {
|
|
1168
|
+
const existing = routesEntries[i];
|
|
1169
|
+
if (lazyPrefix.startsWith(existing.staticPrefix) &&
|
|
1170
|
+
lazyPrefix.length > existing.staticPrefix.length) {
|
|
1171
|
+
insertIndex = i;
|
|
1172
|
+
break;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
routesEntries.splice(insertIndex, 0, lazyEntry);
|
|
1177
|
+
}
|
|
1178
|
+
// Auto-register route map for runtime reverse() usage
|
|
1179
|
+
registerRouteMap(mergedRouteMap);
|
|
1180
|
+
// Return the router (no .map() needed for UrlPatterns)
|
|
1181
|
+
return router;
|
|
1182
|
+
}
|
|
1183
|
+
// Legacy API: route() + map() pattern
|
|
1184
|
+
// If second argument exists, first is prefix
|
|
1185
|
+
if (maybeRoutes !== undefined) {
|
|
1186
|
+
return createRouteBuilder(prefixOrRoutes, maybeRoutes);
|
|
1187
|
+
}
|
|
1188
|
+
// Otherwise, first argument is routes with empty prefix
|
|
1189
|
+
return createRouteBuilder("", prefixOrRoutes);
|
|
1190
|
+
},
|
|
1191
|
+
use(patternOrMiddleware, middleware) {
|
|
1192
|
+
// Global middleware - no mount prefix
|
|
1193
|
+
addMiddleware(patternOrMiddleware, middleware, null);
|
|
1194
|
+
return router;
|
|
1195
|
+
},
|
|
1196
|
+
// Type-safe URL builder using merged route map
|
|
1197
|
+
// Types are tracked through the builder chain via TRoutes parameter
|
|
1198
|
+
// Falls back to static route names from the generated file (injected by Vite)
|
|
1199
|
+
reverse: createReverse(mergedRouteMap, () => staticRouteNames),
|
|
1200
|
+
// Expose accumulated route map for typeof extraction
|
|
1201
|
+
// Returns {} initially, but builder chain accumulates specific route types
|
|
1202
|
+
get routeMap() {
|
|
1203
|
+
return mergedRouteMap;
|
|
1204
|
+
},
|
|
1205
|
+
// Expose rootLayout for renderSegments
|
|
1206
|
+
rootLayout,
|
|
1207
|
+
// Expose onError callback for error handling
|
|
1208
|
+
onError,
|
|
1209
|
+
// Expose cache configuration for RSC handler
|
|
1210
|
+
cache,
|
|
1211
|
+
// Expose notFound component for RSC handler
|
|
1212
|
+
notFound,
|
|
1213
|
+
// Expose resolved theme configuration for NavigationProvider and MetaTags
|
|
1214
|
+
themeConfig: resolvedThemeConfig,
|
|
1215
|
+
// Expose warmup enabled flag for handler and client
|
|
1216
|
+
warmupEnabled,
|
|
1217
|
+
// Expose debug manifest flag for handler
|
|
1218
|
+
allowDebugManifest: allowDebugManifestOption,
|
|
1219
|
+
// Expose global middleware for RSC handler
|
|
1220
|
+
middleware: globalMiddleware,
|
|
1221
|
+
match,
|
|
1222
|
+
matchForPrerender,
|
|
1223
|
+
matchPartial,
|
|
1224
|
+
matchError,
|
|
1225
|
+
previewMatch,
|
|
1226
|
+
// Expose nonce provider for fetch
|
|
1227
|
+
nonce,
|
|
1228
|
+
// Expose version for fetch
|
|
1229
|
+
version,
|
|
1230
|
+
// Expose urlpatterns for runtime manifest generation
|
|
1231
|
+
get urlpatterns() {
|
|
1232
|
+
return storedUrlPatterns ?? undefined;
|
|
1233
|
+
},
|
|
1234
|
+
// Expose source file for per-router type generation
|
|
1235
|
+
__sourceFile,
|
|
1236
|
+
// RSC request handler (lazily created on first call)
|
|
1237
|
+
fetch: (() => {
|
|
1238
|
+
// Handler is created on first call and reused
|
|
1239
|
+
let handler = null;
|
|
1240
|
+
return async (request, env) => {
|
|
1241
|
+
// Trigger lazy import of per-router manifest data before route matching.
|
|
1242
|
+
// No-op if data is already loaded or no loader is registered.
|
|
1243
|
+
await ensureRouterManifest(routerId);
|
|
1244
|
+
if (!handler) {
|
|
1245
|
+
// Lazy import deferred to first request to avoid dev mode issues
|
|
1246
|
+
const { createRSCHandler } = await import("./rsc/handler.js");
|
|
1247
|
+
handler = createRSCHandler({
|
|
1248
|
+
router: router,
|
|
1249
|
+
cache,
|
|
1250
|
+
nonce,
|
|
1251
|
+
version,
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
return handler(request, env);
|
|
1255
|
+
};
|
|
1256
|
+
})(),
|
|
1257
|
+
// Debug utility for manifest inspection
|
|
1258
|
+
async debugManifest() {
|
|
1259
|
+
const manifest = new Map();
|
|
1260
|
+
for (const entry of routesEntries) {
|
|
1261
|
+
const Store = {
|
|
1262
|
+
manifest,
|
|
1263
|
+
namespace: `debug.M${entry.mountIndex}`,
|
|
1264
|
+
parent: null,
|
|
1265
|
+
counters: {},
|
|
1266
|
+
mountIndex: entry.mountIndex,
|
|
1267
|
+
patterns: new Map(),
|
|
1268
|
+
trailingSlash: new Map(),
|
|
1269
|
+
};
|
|
1270
|
+
await getContext().runWithStore(Store, `debug.M${entry.mountIndex}`, null, async () => {
|
|
1271
|
+
const helpers = createRouteHelpers();
|
|
1272
|
+
// Wrap handler execution in root layout (same as loadManifest)
|
|
1273
|
+
let promiseResult = null;
|
|
1274
|
+
helpers.layout(MapRootLayout, () => {
|
|
1275
|
+
const result = entry.handler();
|
|
1276
|
+
if (result instanceof Promise) {
|
|
1277
|
+
promiseResult = result;
|
|
1278
|
+
return [];
|
|
1279
|
+
}
|
|
1280
|
+
return result;
|
|
1281
|
+
});
|
|
1282
|
+
if (promiseResult !== null) {
|
|
1283
|
+
const load = await promiseResult;
|
|
1284
|
+
if (load && typeof load === "object" && "default" in load) {
|
|
1285
|
+
const useItems = load.default;
|
|
1286
|
+
if (typeof useItems === "function") {
|
|
1287
|
+
useItems(helpers);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
return serializeManifest(manifest);
|
|
1294
|
+
},
|
|
1295
|
+
};
|
|
1296
|
+
// Register router in the global registry for build-time discovery
|
|
1297
|
+
RouterRegistry.set(routerId, router);
|
|
1298
|
+
// If urls option was provided, auto-register them
|
|
1299
|
+
if (urlsOption) {
|
|
1300
|
+
return router.routes(urlsOption);
|
|
1301
|
+
}
|
|
1302
|
+
return router;
|
|
1303
|
+
}
|
|
1304
|
+
//# sourceMappingURL=router.js.map
|