@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.140
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 +17 -0
- package/README.md +432 -7
- package/dist/bin/rango.js +2073 -213
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +7258 -2714
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +140 -67
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +329 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +487 -0
- package/skills/caching/SKILL.md +357 -25
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/composability/SKILL.md +246 -0
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +16 -10
- package/skills/document-cache/SKILL.md +87 -62
- package/skills/fonts/SKILL.md +6 -4
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +557 -79
- package/skills/host-router/SKILL.md +320 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +207 -15
- package/skills/layout/SKILL.md +146 -6
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +616 -54
- package/skills/middleware/SKILL.md +217 -37
- package/skills/migrate-nextjs/SKILL.md +611 -0
- package/skills/migrate-react-router/SKILL.md +927 -0
- package/skills/mime-routes/SKILL.md +42 -11
- package/skills/observability/SKILL.md +194 -0
- package/skills/parallel/SKILL.md +284 -3
- package/skills/ppr/SKILL.md +426 -0
- package/skills/prerender/SKILL.md +437 -52
- package/skills/rango/SKILL.md +369 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +263 -121
- package/skills/route/SKILL.md +350 -21
- package/skills/router-setup/SKILL.md +246 -33
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +126 -222
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +131 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +122 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +85 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +123 -0
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +532 -103
- package/skills/use-cache/SKILL.md +367 -0
- package/skills/vercel/SKILL.md +128 -0
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +77 -44
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +114 -0
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +293 -202
- package/src/browser/history-state.ts +101 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +11 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +385 -576
- package/src/browser/navigation-client.ts +245 -75
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +184 -118
- package/src/browser/navigation-transaction.ts +247 -0
- package/src/browser/network-error-handler.ts +88 -0
- package/src/browser/partial-update.ts +412 -364
- package/src/browser/prefetch/cache.ts +359 -0
- package/src/browser/prefetch/fetch.ts +452 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +209 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +194 -0
- package/src/browser/react/Link.tsx +275 -68
- package/src/browser/react/NavigationProvider.tsx +265 -109
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +70 -0
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +272 -60
- package/src/browser/react/location-state.ts +90 -20
- package/src/browser/react/mount-context.ts +6 -1
- 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 +35 -66
- package/src/browser/react/use-handle.ts +39 -126
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +39 -13
- package/src/browser/react/use-navigation.ts +53 -69
- package/src/browser/react/use-params.ts +75 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +98 -0
- package/src/browser/react/use-search-params.ts +51 -0
- package/src/browser/react/use-segments.ts +72 -99
- package/src/browser/response-adapter.ts +164 -0
- package/src/browser/rsc-router.tsx +300 -72
- package/src/browser/scroll-restoration.ts +138 -50
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +17 -1
- package/src/browser/server-action-bridge.ts +668 -613
- package/src/browser/types.ts +223 -51
- package/src/browser/validate-redirect-origin.ts +56 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +252 -161
- package/src/build/generate-route-types.ts +41 -1038
- package/src/build/index.ts +12 -7
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +225 -42
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +105 -0
- package/src/build/route-types/codegen.ts +113 -0
- package/src/build/route-types/include-resolution.ts +812 -0
- package/src/build/route-types/param-extraction.ts +51 -0
- package/src/build/route-types/per-module-writer.ts +144 -0
- package/src/build/route-types/router-processing.ts +695 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +223 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +60 -0
- package/src/cache/cache-policy.ts +199 -0
- package/src/cache/cache-runtime.ts +525 -0
- package/src/cache/cache-scope.ts +298 -332
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +2500 -158
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +17 -17
- package/src/cache/document-cache.ts +199 -92
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +111 -0
- package/src/cache/index.ts +29 -35
- package/src/cache/memory-segment-store.ts +363 -30
- package/src/cache/profile-registry.ts +88 -0
- package/src/cache/read-through-swr.ts +178 -0
- package/src/cache/segment-codec.ts +248 -0
- package/src/cache/shell-cache.ts +386 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +156 -211
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1102 -0
- package/src/client.rsc.tsx +43 -21
- package/src/client.tsx +131 -347
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +23 -4
- package/src/components/DefaultDocument.tsx +13 -3
- package/src/context-var.ts +168 -0
- package/src/debug.ts +19 -9
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +106 -10
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +110 -35
- package/src/handles/MetaTags.tsx +83 -59
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +93 -0
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +44 -53
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +20 -65
- package/src/host/errors.ts +21 -30
- package/src/host/index.ts +13 -9
- package/src/host/pattern-matcher.ts +50 -79
- package/src/host/router.ts +151 -121
- package/src/host/testing.ts +45 -32
- package/src/host/types.ts +52 -11
- package/src/host/utils.ts +2 -2
- package/src/href-client.ts +192 -57
- package/src/index.rsc.ts +177 -35
- package/src/index.ts +255 -71
- package/src/internal-debug.ts +9 -2
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +31 -99
- package/src/loader.ts +30 -12
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +41 -0
- package/src/prerender/param-hash.ts +16 -14
- package/src/prerender/store.ts +121 -21
- package/src/prerender.ts +460 -26
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +62 -0
- package/src/reverse.ts +198 -128
- package/src/root-error-boundary.tsx +42 -48
- package/src/route-content-wrapper.tsx +22 -77
- package/src/route-definition/dsl-helpers.ts +1116 -0
- package/src/route-definition/helper-factories.ts +88 -0
- package/src/route-definition/helpers-types.ts +505 -0
- package/src/route-definition/index.ts +54 -0
- package/src/route-definition/redirect.ts +134 -0
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-definition.ts +1 -1481
- package/src/route-map-builder.ts +82 -144
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +71 -45
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +263 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +54 -27
- package/src/router/find-match.ts +245 -0
- package/src/router/handler-context.ts +377 -125
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +59 -28
- package/src/router/lazy-includes.ts +254 -0
- package/src/router/loader-resolution.ts +421 -157
- package/src/router/logging.ts +106 -6
- package/src/router/manifest.ts +131 -57
- package/src/router/match-api.ts +167 -246
- package/src/router/match-context.ts +4 -24
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +117 -93
- package/src/router/match-middleware/cache-lookup.ts +297 -150
- package/src/router/match-middleware/cache-store.ts +123 -51
- package/src/router/match-middleware/intercept-resolution.ts +44 -43
- package/src/router/match-middleware/segment-resolution.ts +64 -22
- package/src/router/match-pipelines.ts +11 -87
- package/src/router/match-result.ts +121 -50
- package/src/router/metrics.ts +219 -28
- package/src/router/middleware-types.ts +93 -0
- package/src/router/middleware.ts +505 -441
- package/src/router/navigation-snapshot.ts +133 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +311 -142
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +547 -0
- package/src/router/preview-match.ts +102 -0
- package/src/router/request-classification.ts +278 -0
- package/src/router/revalidation.ts +203 -62
- package/src/router/route-snapshot.ts +246 -0
- package/src/router/router-context.ts +45 -48
- package/src/router/router-interfaces.ts +554 -0
- package/src/router/router-options.ts +779 -0
- package/src/router/router-registry.ts +21 -0
- package/src/router/segment-resolution/fresh.ts +772 -0
- package/src/router/segment-resolution/helpers.ts +348 -0
- package/src/router/segment-resolution/loader-cache.ts +250 -0
- package/src/router/segment-resolution/loader-mask.ts +44 -0
- package/src/router/segment-resolution/revalidation.ts +1331 -0
- package/src/router/segment-resolution/static-store.ts +81 -0
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +56 -0
- package/src/router/segment-resolution.ts +25 -1354
- package/src/router/segment-wrappers.ts +292 -0
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +75 -0
- package/src/router/telemetry-otel.ts +261 -0
- package/src/router/telemetry.ts +377 -0
- package/src/router/timeout.ts +128 -0
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +240 -61
- package/src/router/types.ts +23 -70
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +781 -2378
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +46 -0
- package/src/rsc/handler.ts +905 -1142
- package/src/rsc/helpers.ts +275 -19
- package/src/rsc/index.ts +2 -25
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +305 -0
- package/src/rsc/manifest-init.ts +77 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +155 -0
- package/src/rsc/progressive-enhancement.ts +502 -0
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +104 -0
- package/src/rsc/response-route-handler.ts +257 -0
- package/src/rsc/rsc-rendering.ts +337 -0
- package/src/rsc/runtime-warnings.ts +55 -0
- package/src/rsc/server-action.ts +522 -0
- package/src/rsc/shell-capture.ts +439 -0
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +95 -12
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +99 -82
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +349 -134
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +452 -85
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +310 -0
- package/src/server/fetchable-loader-store.ts +11 -6
- package/src/server/handle-store.ts +123 -42
- package/src/server/live.ts +130 -0
- package/src/server/loader-registry.ts +51 -100
- package/src/server/request-context.ts +842 -157
- package/src/server.ts +15 -8
- package/src/ssr/index.tsx +412 -136
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +45 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +701 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +257 -0
- package/src/testing/generated-routes.ts +199 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +357 -0
- package/src/testing/render-route.tsx +584 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +40 -72
- package/src/theme/ThemeScript.tsx +12 -14
- package/src/theme/constants.ts +57 -15
- package/src/theme/index.ts +3 -20
- package/src/theme/theme-context.ts +5 -35
- package/src/theme/theme-script.ts +43 -39
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +123 -0
- package/src/types/cache-types.ts +207 -0
- package/src/types/error-types.ts +132 -0
- package/src/types/global-namespace.ts +113 -0
- package/src/types/handler-context.ts +839 -0
- package/src/types/index.ts +81 -0
- package/src/types/loader-types.ts +212 -0
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +138 -0
- package/src/types/route-entry.ts +114 -0
- package/src/types/segments.ts +271 -0
- package/src/types.ts +1 -1795
- package/src/urls/include-helper.ts +162 -0
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +43 -0
- package/src/urls/path-helper-types.ts +413 -0
- package/src/urls/path-helper.ts +275 -0
- package/src/urls/pattern-types.ts +124 -0
- package/src/urls/response-types.ts +109 -0
- package/src/urls/type-extraction.ts +316 -0
- package/src/urls/urls-function.ts +80 -0
- package/src/urls.ts +1 -1341
- package/src/use-loader.tsx +406 -141
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +182 -0
- package/src/vite/discovery/discover-routers.ts +389 -0
- package/src/vite/discovery/discovery-errors.ts +255 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +467 -0
- package/src/vite/discovery/route-types-writer.ts +214 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +161 -0
- package/src/vite/discovery/virtual-module-codegen.ts +183 -0
- package/src/vite/index.ts +23 -2255
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +303 -0
- package/src/vite/plugins/cjs-to-esm.ts +90 -0
- package/src/vite/plugins/client-ref-dedup.ts +120 -0
- package/src/vite/plugins/client-ref-hashing.ts +118 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
- package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
- package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +805 -0
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +313 -0
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +94 -0
- package/src/vite/plugins/version-plugin.ts +263 -0
- package/src/vite/plugins/virtual-entries.ts +234 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +560 -0
- package/src/vite/router-discovery.ts +1638 -0
- package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +132 -0
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +15 -0
- package/src/vite/utils/package-resolution.ts +89 -0
- package/src/vite/utils/prerender-utils.ts +249 -0
- package/src/vite/utils/shared-utils.ts +269 -0
- package/CLAUDE.md +0 -43
- package/dist/vite/index.named-routes.gen.ts +0 -103
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/react/use-client-cache.ts +0 -56
- package/src/browser/request-controller.ts +0 -164
- package/src/browser/shallow.ts +0 -35
- package/src/cache/memory-store.ts +0 -253
- package/src/handles/index.ts +0 -6
- package/src/href-context.ts +0 -33
- package/src/network-error-thrower.tsx +0 -21
- package/src/router.gen.ts +0 -6
- package/src/static-handler.gen.ts +0 -5
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-internal-ids.ts +0 -1167
- package/src/vite/package-resolution.ts +0 -125
- package/src/vite/virtual-entries.ts +0 -114
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -12,27 +12,27 @@
|
|
|
12
12
|
* - `**.example.com` - any depth subdomain
|
|
13
13
|
* - `admin.*` - admin subdomain of any apex
|
|
14
14
|
* - `example.com/admin` - specific domain with path prefix
|
|
15
|
+
*
|
|
16
|
+
* Apex vs subdomain is classified purely by dot-part COUNT (apex == exactly 2
|
|
17
|
+
* parts) — there is no Public Suffix List. A registrable domain under a
|
|
18
|
+
* multi-label public suffix (example.co.uk, shop.com.au) has 3+ parts and is
|
|
19
|
+
* therefore treated as a SUBDOMAIN, not an apex: `.`/`*` will NOT match it and
|
|
20
|
+
* `*.` WILL. If registrable-domain accuracy matters for a host-router consumer,
|
|
21
|
+
* supply an explicit apex/host hint rather than relying on the part count.
|
|
15
22
|
*/
|
|
16
23
|
|
|
17
|
-
import { InvalidPatternError } from
|
|
24
|
+
import { InvalidPatternError } from "./errors.js";
|
|
18
25
|
|
|
19
|
-
/**
|
|
20
|
-
* Normalize a pattern by removing trailing slashes from paths
|
|
21
|
-
*/
|
|
22
26
|
export function normalizePattern(pattern: string): string {
|
|
23
|
-
|
|
24
|
-
const slashIndex = pattern.indexOf('/');
|
|
27
|
+
const slashIndex = pattern.indexOf("/");
|
|
25
28
|
if (slashIndex !== -1) {
|
|
26
29
|
const domain = pattern.slice(0, slashIndex);
|
|
27
|
-
const path = pattern.slice(slashIndex).replace(/\/$/,
|
|
30
|
+
const path = pattern.slice(slashIndex).replace(/\/$/, "");
|
|
28
31
|
return domain + path;
|
|
29
32
|
}
|
|
30
33
|
return pattern;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
/**
|
|
34
|
-
* Parse hostname and path from request URL
|
|
35
|
-
*/
|
|
36
36
|
export function parseRequest(request: Request): {
|
|
37
37
|
hostname: string;
|
|
38
38
|
pathname: string;
|
|
@@ -41,135 +41,115 @@ export function parseRequest(request: Request): {
|
|
|
41
41
|
const url = new URL(request.url);
|
|
42
42
|
const hostname = url.hostname;
|
|
43
43
|
const pathname = url.pathname;
|
|
44
|
-
const parts = hostname.split(
|
|
44
|
+
const parts = hostname.split(".");
|
|
45
45
|
|
|
46
46
|
return { hostname, pathname, parts };
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
/**
|
|
50
|
-
* Count subdomain levels (0 for apex, 1+ for subdomains)
|
|
51
|
-
*/
|
|
52
49
|
function getSubdomainLevel(parts: string[]): number {
|
|
53
|
-
// Apex domain has 2 parts (example.com)
|
|
54
|
-
// Single subdomain has 3 parts (www.example.com)
|
|
55
|
-
// Multi-level has 4+ parts (a.b.example.com)
|
|
56
50
|
return Math.max(0, parts.length - 2);
|
|
57
51
|
}
|
|
58
52
|
|
|
59
|
-
/**
|
|
60
|
-
* Check if hostname is an apex domain (no subdomains)
|
|
61
|
-
*/
|
|
62
53
|
function isApexDomain(parts: string[]): boolean {
|
|
63
54
|
return parts.length === 2;
|
|
64
55
|
}
|
|
65
56
|
|
|
66
|
-
/**
|
|
67
|
-
* Match a single pattern against hostname and path
|
|
68
|
-
*/
|
|
69
57
|
export function matchPattern(
|
|
70
58
|
pattern: string,
|
|
71
59
|
hostname: string,
|
|
72
60
|
pathname: string,
|
|
73
|
-
parts: string[]
|
|
61
|
+
parts: string[],
|
|
74
62
|
): boolean {
|
|
75
63
|
const normalized = normalizePattern(pattern);
|
|
76
64
|
|
|
77
|
-
|
|
78
|
-
const slashIndex = normalized.indexOf('/');
|
|
65
|
+
const slashIndex = normalized.indexOf("/");
|
|
79
66
|
const hasPath = slashIndex !== -1;
|
|
80
|
-
|
|
67
|
+
// Hosts are case-insensitive (RFC 3986): lowercase the domain literal and the
|
|
68
|
+
// request host once so matching folds case. Wildcards (*, **, .) are
|
|
69
|
+
// unaffected by lowercasing. The path is left untouched (paths are
|
|
70
|
+
// case-sensitive).
|
|
71
|
+
const domainPattern = (
|
|
72
|
+
hasPath ? normalized.slice(0, slashIndex) : normalized
|
|
73
|
+
).toLowerCase();
|
|
81
74
|
const pathPattern = hasPath ? normalized.slice(slashIndex) : null;
|
|
82
75
|
|
|
83
|
-
|
|
84
|
-
const
|
|
76
|
+
const lowerHostname = hostname.toLowerCase();
|
|
77
|
+
const lowerParts =
|
|
78
|
+
lowerHostname === hostname ? parts : lowerHostname.split(".");
|
|
79
|
+
|
|
80
|
+
const domainMatch = matchDomainPattern(
|
|
81
|
+
domainPattern,
|
|
82
|
+
lowerHostname,
|
|
83
|
+
lowerParts,
|
|
84
|
+
);
|
|
85
85
|
if (!domainMatch) {
|
|
86
86
|
return false;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
// Then match path (prefix match)
|
|
90
89
|
if (pathPattern) {
|
|
91
|
-
return pathname === pathPattern || pathname.startsWith(pathPattern +
|
|
90
|
+
return pathname === pathPattern || pathname.startsWith(pathPattern + "/");
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
return true;
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
/**
|
|
98
|
-
* Match domain pattern against hostname
|
|
99
|
-
*/
|
|
100
96
|
function matchDomainPattern(
|
|
101
97
|
pattern: string,
|
|
102
98
|
hostname: string,
|
|
103
|
-
parts: string[]
|
|
99
|
+
parts: string[],
|
|
104
100
|
): boolean {
|
|
105
|
-
// Exact match
|
|
106
101
|
if (pattern === hostname) {
|
|
107
102
|
return true;
|
|
108
103
|
}
|
|
109
104
|
|
|
110
|
-
|
|
111
|
-
if (pattern === '.' || pattern === '*') {
|
|
105
|
+
if (pattern === "." || pattern === "*") {
|
|
112
106
|
return isApexDomain(parts);
|
|
113
107
|
}
|
|
114
108
|
|
|
115
|
-
|
|
116
|
-
if (pattern === '**') {
|
|
109
|
+
if (pattern === "**") {
|
|
117
110
|
return true;
|
|
118
111
|
}
|
|
119
112
|
|
|
120
|
-
|
|
121
|
-
if (pattern === '*.') {
|
|
113
|
+
if (pattern === "*.") {
|
|
122
114
|
return getSubdomainLevel(parts) === 1;
|
|
123
115
|
}
|
|
124
116
|
|
|
125
|
-
|
|
126
|
-
if (pattern === '**.') {
|
|
117
|
+
if (pattern === "**.") {
|
|
127
118
|
return getSubdomainLevel(parts) >= 2;
|
|
128
119
|
}
|
|
129
120
|
|
|
130
|
-
|
|
131
|
-
if (pattern.startsWith('*.') && !pattern.includes('.', 2)) {
|
|
121
|
+
if (pattern.startsWith("*.") && !pattern.includes(".", 2)) {
|
|
132
122
|
const tld = pattern.slice(2);
|
|
133
|
-
return isApexDomain(parts) && hostname.endsWith(
|
|
123
|
+
return isApexDomain(parts) && hostname.endsWith("." + tld);
|
|
134
124
|
}
|
|
135
125
|
|
|
136
|
-
|
|
137
|
-
if (pattern.startsWith('*.')) {
|
|
126
|
+
if (pattern.startsWith("*.")) {
|
|
138
127
|
const baseDomain = pattern.slice(2);
|
|
139
|
-
if (hostname.endsWith(
|
|
140
|
-
|
|
141
|
-
// hostname should have exactly 4 parts (www.example.com)
|
|
142
|
-
const patternParts = baseDomain.split('.');
|
|
128
|
+
if (hostname.endsWith("." + baseDomain)) {
|
|
129
|
+
const patternParts = baseDomain.split(".");
|
|
143
130
|
return parts.length === patternParts.length + 1;
|
|
144
131
|
}
|
|
145
132
|
return false;
|
|
146
133
|
}
|
|
147
134
|
|
|
148
|
-
|
|
149
|
-
if (pattern.startsWith('**.')) {
|
|
135
|
+
if (pattern.startsWith("**.")) {
|
|
150
136
|
const baseDomain = pattern.slice(3);
|
|
151
|
-
if (hostname.endsWith(
|
|
152
|
-
const patternParts = baseDomain.split(
|
|
153
|
-
// Must have more parts than the base domain (i.e., has subdomains)
|
|
137
|
+
if (hostname.endsWith("." + baseDomain)) {
|
|
138
|
+
const patternParts = baseDomain.split(".");
|
|
154
139
|
return parts.length > patternParts.length;
|
|
155
140
|
}
|
|
156
141
|
return false;
|
|
157
142
|
}
|
|
158
143
|
|
|
159
|
-
|
|
160
|
-
// e.g., admin.* matches admin.example.com, admin.google.com
|
|
161
|
-
if (pattern.endsWith('.*')) {
|
|
144
|
+
if (pattern.endsWith(".*")) {
|
|
162
145
|
const subdomain = pattern.slice(0, -2);
|
|
163
|
-
// Must be single-level subdomain (3 parts total)
|
|
164
146
|
if (parts.length === 3 && parts[0] === subdomain) {
|
|
165
147
|
return true;
|
|
166
148
|
}
|
|
167
149
|
return false;
|
|
168
150
|
}
|
|
169
151
|
|
|
170
|
-
|
|
171
|
-
// e.g., admin.** matches admin.example.com, admin.sub.example.com
|
|
172
|
-
if (pattern.endsWith('.**')) {
|
|
152
|
+
if (pattern.endsWith(".**")) {
|
|
173
153
|
const subdomain = pattern.slice(0, -3);
|
|
174
154
|
if (parts.length >= 3 && parts[0] === subdomain) {
|
|
175
155
|
return true;
|
|
@@ -177,11 +157,8 @@ function matchDomainPattern(
|
|
|
177
157
|
return false;
|
|
178
158
|
}
|
|
179
159
|
|
|
180
|
-
|
|
181
|
-
// e.g., admin. matches admin.example.com, admin.google.com
|
|
182
|
-
if (pattern.endsWith('.') && !pattern.includes('*')) {
|
|
160
|
+
if (pattern.endsWith(".") && !pattern.includes("*")) {
|
|
183
161
|
const subdomain = pattern.slice(0, -1);
|
|
184
|
-
// Must be exactly 3 parts (subdomain.domain.tld)
|
|
185
162
|
if (parts.length === 3 && parts[0] === subdomain) {
|
|
186
163
|
return true;
|
|
187
164
|
}
|
|
@@ -191,24 +168,18 @@ function matchDomainPattern(
|
|
|
191
168
|
return false;
|
|
192
169
|
}
|
|
193
170
|
|
|
194
|
-
/**
|
|
195
|
-
* Validate pattern format
|
|
196
|
-
*/
|
|
197
171
|
export function validatePattern(pattern: string): void {
|
|
198
|
-
if (!pattern || typeof pattern !==
|
|
172
|
+
if (!pattern || typeof pattern !== "string") {
|
|
199
173
|
throw new InvalidPatternError(
|
|
200
174
|
pattern,
|
|
201
|
-
|
|
202
|
-
{ cause: { type: typeof pattern, value: pattern } }
|
|
175
|
+
"Pattern must be a non-empty string",
|
|
176
|
+
{ cause: { type: typeof pattern, value: pattern } },
|
|
203
177
|
);
|
|
204
178
|
}
|
|
205
179
|
|
|
206
|
-
// Check for invalid characters (spaces, etc.)
|
|
207
180
|
if (/\s/.test(pattern)) {
|
|
208
|
-
throw new InvalidPatternError(pattern,
|
|
181
|
+
throw new InvalidPatternError(pattern, "contains whitespace", {
|
|
209
182
|
cause: { pattern },
|
|
210
183
|
});
|
|
211
184
|
}
|
|
212
|
-
|
|
213
|
-
// Additional validation can be added here
|
|
214
185
|
}
|
package/src/host/router.ts
CHANGED
|
@@ -14,45 +14,55 @@ import type {
|
|
|
14
14
|
HostPattern,
|
|
15
15
|
RouteEntry,
|
|
16
16
|
HostMatchResult,
|
|
17
|
-
} from
|
|
17
|
+
} from "./types.js";
|
|
18
|
+
import type { RouterRequestInput } from "../router/router-interfaces.js";
|
|
18
19
|
import {
|
|
19
20
|
matchPattern,
|
|
20
21
|
parseRequest,
|
|
21
22
|
normalizePattern,
|
|
22
23
|
validatePattern,
|
|
23
|
-
} from
|
|
24
|
+
} from "./pattern-matcher.js";
|
|
24
25
|
import {
|
|
25
26
|
handleCookieOverride,
|
|
26
27
|
createCookieErrorResponse,
|
|
27
|
-
} from
|
|
28
|
+
} from "./cookie-handler.js";
|
|
28
29
|
import {
|
|
29
30
|
HostRouterError,
|
|
30
31
|
NoRouteMatchError,
|
|
31
32
|
InvalidHandlerError,
|
|
32
|
-
} from
|
|
33
|
+
} from "./errors.js";
|
|
33
34
|
|
|
34
|
-
/**
|
|
35
|
-
* Registry entry for a host router instance.
|
|
36
|
-
* Stores references to the live routes array and fallback, so the discovery
|
|
37
|
-
* plugin can iterate handlers registered after createHostRouter() returns.
|
|
38
|
-
*/
|
|
39
35
|
export interface HostRouterRegistryEntry {
|
|
40
36
|
routes: RouteEntry[];
|
|
41
37
|
fallback: RouteEntry | null;
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* Populated by createHostRouter() so the build-time discovery plugin can find
|
|
47
|
-
* host routers and resolve their lazy handlers to trigger sub-app createRouter() calls.
|
|
48
|
-
*/
|
|
49
|
-
export const HostRouterRegistry: Map<string, HostRouterRegistryEntry> = new Map();
|
|
40
|
+
export const HostRouterRegistry: Map<string, HostRouterRegistryEntry> =
|
|
41
|
+
new Map();
|
|
50
42
|
|
|
51
43
|
let hostRouterAutoId = 0;
|
|
52
44
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
function isThenable(value: unknown): value is PromiseLike<unknown> {
|
|
46
|
+
return (
|
|
47
|
+
value !== null &&
|
|
48
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
49
|
+
typeof (value as { then?: unknown }).then === "function"
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function looksLikeLazyModule(value: unknown): boolean {
|
|
54
|
+
if (value === null || typeof value !== "object" || !("default" in value)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const defaultExport = (value as { default: unknown }).default;
|
|
58
|
+
return (
|
|
59
|
+
typeof defaultExport === "function" ||
|
|
60
|
+
(typeof defaultExport === "object" &&
|
|
61
|
+
defaultExport !== null &&
|
|
62
|
+
"match" in defaultExport)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
56
66
|
export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
57
67
|
const routes: RouteEntry[] = [];
|
|
58
68
|
const globalMiddleware: Middleware[] = [];
|
|
@@ -66,53 +76,59 @@ export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
|
66
76
|
}
|
|
67
77
|
}
|
|
68
78
|
|
|
69
|
-
/**
|
|
70
|
-
* Create a route builder for chaining
|
|
71
|
-
*/
|
|
72
79
|
function createRouteBuilder(
|
|
73
80
|
patterns: string[],
|
|
74
|
-
isFallback = false
|
|
81
|
+
isFallback = false,
|
|
75
82
|
): HostRouteBuilder {
|
|
76
83
|
const middleware: Middleware[] = [];
|
|
77
84
|
|
|
85
|
+
function register(
|
|
86
|
+
handler: Handler | LazyHandler,
|
|
87
|
+
kind: RouteEntry["kind"],
|
|
88
|
+
): HostRouter {
|
|
89
|
+
const entry: RouteEntry = {
|
|
90
|
+
patterns,
|
|
91
|
+
middleware,
|
|
92
|
+
handler,
|
|
93
|
+
kind,
|
|
94
|
+
isFallback,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
if (isFallback) {
|
|
98
|
+
fallbackRoute = entry;
|
|
99
|
+
} else {
|
|
100
|
+
routes.push(entry);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
log(
|
|
104
|
+
`Registered ${isFallback ? "fallback" : "route"} (${kind}):`,
|
|
105
|
+
patterns.join(", "),
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
return router;
|
|
109
|
+
}
|
|
110
|
+
|
|
78
111
|
return {
|
|
79
112
|
use(...mw: Middleware[]): HostRouteBuilder {
|
|
80
113
|
middleware.push(...mw);
|
|
81
114
|
return this;
|
|
82
115
|
},
|
|
83
116
|
|
|
84
|
-
map(handler: Handler
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
middleware,
|
|
88
|
-
handler,
|
|
89
|
-
isFallback,
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
if (isFallback) {
|
|
93
|
-
fallbackRoute = entry;
|
|
94
|
-
} else {
|
|
95
|
-
routes.push(entry);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
log(
|
|
99
|
-
`Registered ${isFallback ? 'fallback' : 'route'}:`,
|
|
100
|
-
patterns.join(', ')
|
|
101
|
-
);
|
|
117
|
+
map(handler: Handler): HostRouter {
|
|
118
|
+
return register(handler, "handler");
|
|
119
|
+
},
|
|
102
120
|
|
|
103
|
-
|
|
121
|
+
lazy(handler: LazyHandler): HostRouter {
|
|
122
|
+
return register(handler, "lazy");
|
|
104
123
|
},
|
|
105
124
|
};
|
|
106
125
|
}
|
|
107
126
|
|
|
108
|
-
/**
|
|
109
|
-
* Find matching route for hostname and path
|
|
110
|
-
*/
|
|
111
127
|
function findMatchingRoute(
|
|
112
128
|
hostname: string,
|
|
113
|
-
pathname: string
|
|
129
|
+
pathname: string,
|
|
114
130
|
): RouteEntry | null {
|
|
115
|
-
const parts = hostname.split(
|
|
131
|
+
const parts = hostname.split(".");
|
|
116
132
|
|
|
117
133
|
for (const route of routes) {
|
|
118
134
|
for (const pattern of route.patterns) {
|
|
@@ -126,14 +142,11 @@ export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
|
126
142
|
return null;
|
|
127
143
|
}
|
|
128
144
|
|
|
129
|
-
/**
|
|
130
|
-
* Execute middleware chain
|
|
131
|
-
*/
|
|
132
145
|
async function executeMiddleware(
|
|
133
146
|
middleware: Middleware[],
|
|
134
147
|
request: Request,
|
|
135
|
-
|
|
136
|
-
finalHandler: () => Promise<Response
|
|
148
|
+
input: RouterRequestInput<any>,
|
|
149
|
+
finalHandler: () => Promise<Response>,
|
|
137
150
|
): Promise<Response> {
|
|
138
151
|
let index = 0;
|
|
139
152
|
|
|
@@ -147,68 +160,90 @@ export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
|
147
160
|
return finalHandler();
|
|
148
161
|
}
|
|
149
162
|
|
|
150
|
-
|
|
163
|
+
let nextCalled = false;
|
|
164
|
+
const guardedNext = (): Promise<Response> => {
|
|
165
|
+
if (nextCalled) {
|
|
166
|
+
throw new Error(
|
|
167
|
+
`[HostRouter] Middleware called next() more than once.`,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
nextCalled = true;
|
|
171
|
+
return next();
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return mw(request, input, guardedNext);
|
|
151
175
|
}
|
|
152
176
|
|
|
153
177
|
return next();
|
|
154
178
|
}
|
|
155
179
|
|
|
156
|
-
/**
|
|
157
|
-
* Execute handler (lazy or direct)
|
|
158
|
-
*/
|
|
159
180
|
async function executeHandler(
|
|
160
|
-
|
|
181
|
+
entry: RouteEntry,
|
|
161
182
|
request: Request,
|
|
162
|
-
|
|
183
|
+
input: RouterRequestInput<any>,
|
|
163
184
|
): Promise<Response> {
|
|
164
|
-
|
|
165
|
-
if (typeof handler === 'function') {
|
|
166
|
-
const result = handler(request, context);
|
|
167
|
-
|
|
168
|
-
// If it returns a promise with default export
|
|
169
|
-
if (result && typeof result === 'object' && 'then' in result) {
|
|
170
|
-
const module = await result;
|
|
171
|
-
if (
|
|
172
|
-
typeof module === 'object' &&
|
|
173
|
-
module !== null &&
|
|
174
|
-
'default' in module
|
|
175
|
-
) {
|
|
176
|
-
const defaultExport = (module as { default: Handler | HostRouter })
|
|
177
|
-
.default;
|
|
178
|
-
|
|
179
|
-
// If default export is a router with match method
|
|
180
|
-
if (
|
|
181
|
-
typeof defaultExport === 'object' &&
|
|
182
|
-
defaultExport !== null &&
|
|
183
|
-
'match' in defaultExport
|
|
184
|
-
) {
|
|
185
|
-
return (defaultExport as HostRouter).match(request, context);
|
|
186
|
-
}
|
|
185
|
+
const { handler, kind } = entry;
|
|
187
186
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
187
|
+
if (typeof handler !== "function") {
|
|
188
|
+
throw new InvalidHandlerError(handler, {
|
|
189
|
+
cause: { handlerType: typeof handler },
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (kind === "lazy") {
|
|
194
|
+
return executeLazyMount(handler as LazyHandler, request, input);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const result = (handler as Handler)(request, input);
|
|
198
|
+
|
|
199
|
+
if (isThenable(result)) {
|
|
200
|
+
const awaited = await result;
|
|
201
|
+
if (looksLikeLazyModule(awaited)) {
|
|
202
|
+
throw new HostRouterError(
|
|
203
|
+
".map() is for inline request handlers; use .lazy(() => import(...)) for lazy host mounts.",
|
|
204
|
+
);
|
|
193
205
|
}
|
|
206
|
+
return awaited as Response;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
194
211
|
|
|
195
|
-
|
|
196
|
-
|
|
212
|
+
async function executeLazyMount(
|
|
213
|
+
loader: LazyHandler,
|
|
214
|
+
request: Request,
|
|
215
|
+
input: RouterRequestInput<any>,
|
|
216
|
+
): Promise<Response> {
|
|
217
|
+
const module = await loader();
|
|
218
|
+
|
|
219
|
+
if (typeof module === "object" && module !== null && "default" in module) {
|
|
220
|
+
const defaultExport = (module as { default: Handler | HostRouter })
|
|
221
|
+
.default;
|
|
222
|
+
|
|
223
|
+
if (
|
|
224
|
+
typeof defaultExport === "object" &&
|
|
225
|
+
defaultExport !== null &&
|
|
226
|
+
"match" in defaultExport
|
|
227
|
+
) {
|
|
228
|
+
return (defaultExport as HostRouter).match(request, input);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return (defaultExport as Handler)(request, input);
|
|
197
232
|
}
|
|
198
233
|
|
|
199
|
-
throw new InvalidHandlerError(
|
|
200
|
-
cause: {
|
|
234
|
+
throw new InvalidHandlerError(loader, {
|
|
235
|
+
cause: {
|
|
236
|
+
reason:
|
|
237
|
+
"lazy mount did not resolve to a module with a default export; " +
|
|
238
|
+
"use .lazy(() => import('./sub-app')) where the module default-exports a handler or host router",
|
|
239
|
+
},
|
|
201
240
|
});
|
|
202
241
|
}
|
|
203
242
|
|
|
204
|
-
/**
|
|
205
|
-
* Router instance
|
|
206
|
-
*/
|
|
207
243
|
const router: HostRouter = {
|
|
208
244
|
host(patterns: HostPattern): HostRouteBuilder {
|
|
209
245
|
const patternsArray = Array.isArray(patterns) ? patterns : [patterns];
|
|
210
246
|
|
|
211
|
-
// Validate and normalize patterns
|
|
212
247
|
const normalized = patternsArray.map((p) => {
|
|
213
248
|
validatePattern(p);
|
|
214
249
|
return normalizePattern(p);
|
|
@@ -227,9 +262,8 @@ export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
|
227
262
|
return createRouteBuilder([], true);
|
|
228
263
|
},
|
|
229
264
|
|
|
230
|
-
test(hostname: string): HostMatchResult | null {
|
|
231
|
-
const parts = hostname.split(
|
|
232
|
-
const pathname = '/';
|
|
265
|
+
test(hostname: string, pathname = "/"): HostMatchResult | null {
|
|
266
|
+
const parts = hostname.split(".");
|
|
233
267
|
|
|
234
268
|
for (const route of routes) {
|
|
235
269
|
for (const pattern of route.patterns) {
|
|
@@ -237,6 +271,7 @@ export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
|
237
271
|
return {
|
|
238
272
|
pattern,
|
|
239
273
|
handler: route.handler,
|
|
274
|
+
kind: route.kind,
|
|
240
275
|
};
|
|
241
276
|
}
|
|
242
277
|
}
|
|
@@ -245,46 +280,43 @@ export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
|
245
280
|
return null;
|
|
246
281
|
},
|
|
247
282
|
|
|
248
|
-
async match(
|
|
283
|
+
async match(
|
|
284
|
+
request: Request,
|
|
285
|
+
input: RouterRequestInput<any> = {},
|
|
286
|
+
): Promise<Response> {
|
|
249
287
|
log(`Request: ${request.url}`);
|
|
250
288
|
|
|
251
289
|
let effectiveHostname: string;
|
|
252
290
|
|
|
253
291
|
try {
|
|
254
|
-
|
|
255
|
-
effectiveHostname = handleCookieOverride(
|
|
256
|
-
request,
|
|
257
|
-
hostOverride,
|
|
258
|
-
context
|
|
259
|
-
);
|
|
292
|
+
effectiveHostname = handleCookieOverride(request, hostOverride, input);
|
|
260
293
|
} catch (error) {
|
|
261
|
-
// If it's a HostRouterError from cookie override
|
|
262
294
|
if (error instanceof HostRouterError) {
|
|
263
295
|
log(`Cookie override error: ${error.message}`);
|
|
264
296
|
|
|
265
|
-
// If fallback exists, use it
|
|
266
297
|
if (fallbackRoute) {
|
|
267
|
-
|
|
298
|
+
const fallbackInput = { ...input, error };
|
|
268
299
|
const allMiddleware = [
|
|
269
300
|
...globalMiddleware,
|
|
270
301
|
...fallbackRoute.middleware,
|
|
271
302
|
];
|
|
272
303
|
|
|
273
|
-
return executeMiddleware(
|
|
274
|
-
|
|
304
|
+
return executeMiddleware(
|
|
305
|
+
allMiddleware,
|
|
306
|
+
request,
|
|
307
|
+
fallbackInput,
|
|
308
|
+
() => executeHandler(fallbackRoute!, request, fallbackInput),
|
|
275
309
|
);
|
|
276
310
|
}
|
|
277
311
|
|
|
278
|
-
// Otherwise return error response with cookie deletion
|
|
279
312
|
if (hostOverride) {
|
|
280
313
|
return createCookieErrorResponse(
|
|
281
314
|
hostOverride.cookieName,
|
|
282
|
-
error.message
|
|
315
|
+
error.message,
|
|
283
316
|
);
|
|
284
317
|
}
|
|
285
318
|
}
|
|
286
319
|
|
|
287
|
-
// Re-throw non-HostRouterErrors
|
|
288
320
|
throw error;
|
|
289
321
|
}
|
|
290
322
|
|
|
@@ -294,7 +326,6 @@ export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
|
294
326
|
log(`Cookie override: ${effectiveHostname}`);
|
|
295
327
|
}
|
|
296
328
|
|
|
297
|
-
// Find matching route
|
|
298
329
|
const matchedRoute = findMatchingRoute(effectiveHostname, pathname);
|
|
299
330
|
|
|
300
331
|
if (!matchedRoute) {
|
|
@@ -307,23 +338,22 @@ export function createHostRouter(options: HostRouterOptions = {}): HostRouter {
|
|
|
307
338
|
});
|
|
308
339
|
}
|
|
309
340
|
|
|
310
|
-
// Combine global and route-specific middleware
|
|
311
341
|
const allMiddleware = [...globalMiddleware, ...matchedRoute.middleware];
|
|
312
342
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
executeHandler(matchedRoute.handler, request, context)
|
|
343
|
+
return executeMiddleware(allMiddleware, request, input, () =>
|
|
344
|
+
executeHandler(matchedRoute, request, input),
|
|
316
345
|
);
|
|
317
346
|
},
|
|
318
347
|
};
|
|
319
348
|
|
|
320
|
-
// Register in the global HostRouterRegistry for build-time discovery.
|
|
321
|
-
// The routes array and fallbackRoute ref are live - they reflect routes
|
|
322
|
-
// added via .host().map() after this point.
|
|
323
349
|
const registryId = `host-router-${hostRouterAutoId++}`;
|
|
324
350
|
HostRouterRegistry.set(registryId, {
|
|
325
|
-
get routes() {
|
|
326
|
-
|
|
351
|
+
get routes() {
|
|
352
|
+
return routes;
|
|
353
|
+
},
|
|
354
|
+
get fallback() {
|
|
355
|
+
return fallbackRoute;
|
|
356
|
+
},
|
|
327
357
|
});
|
|
328
358
|
|
|
329
359
|
return router;
|