@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.141
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 +293 -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 +2508 -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 +24 -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-snapshot.ts +368 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +222 -211
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1113 -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 +173 -35
- package/src/index.ts +241 -73
- 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 +527 -0
- package/src/rsc/runtime-warnings.ts +55 -0
- package/src/rsc/server-action.ts +522 -0
- package/src/rsc/shell-capture.ts +897 -0
- package/src/rsc/shell-serve.ts +124 -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 +459 -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/loader-registry.ts +51 -100
- package/src/server/request-context.ts +848 -157
- package/src/server.ts +15 -8
- package/src/ssr/index.tsx +443 -135
- 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 +76 -98
- 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 +44 -0
- package/src/urls/path-helper-types.ts +413 -0
- package/src/urls/path-helper.ts +280 -0
- package/src/urls/pattern-types.ts +160 -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
|
@@ -22,43 +22,62 @@ export const urlpatterns = urls(({ path, layout, include }) => [
|
|
|
22
22
|
path("/about", AboutPage, { name: "about" }),
|
|
23
23
|
|
|
24
24
|
// JSON API route (inline, alongside RSC routes)
|
|
25
|
-
path.json(
|
|
26
|
-
status
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
path.json(
|
|
26
|
+
"/api/status",
|
|
27
|
+
(ctx) => ({
|
|
28
|
+
status: "ok",
|
|
29
|
+
timestamp: Date.now(),
|
|
30
|
+
}),
|
|
31
|
+
{ name: "status" },
|
|
32
|
+
),
|
|
29
33
|
|
|
30
34
|
// Text route
|
|
31
|
-
path.text(
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
path.text(
|
|
36
|
+
"/robots.txt",
|
|
37
|
+
(ctx) => {
|
|
38
|
+
return "User-agent: *\nAllow: /\nDisallow: /api/\n";
|
|
39
|
+
},
|
|
40
|
+
{ name: "robots" },
|
|
41
|
+
),
|
|
34
42
|
|
|
35
43
|
// Markdown route
|
|
36
|
-
path.md(
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
path.md(
|
|
45
|
+
"/docs/:slug.md",
|
|
46
|
+
(ctx) => {
|
|
47
|
+
return `# ${ctx.params.slug}\n\nDocumentation content here.`;
|
|
48
|
+
},
|
|
49
|
+
{ name: "docs" },
|
|
50
|
+
),
|
|
39
51
|
|
|
40
52
|
// Response route (full control, returns Response directly)
|
|
41
|
-
path.image(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
path.image(
|
|
54
|
+
"/og/:slug.png",
|
|
55
|
+
async (ctx) => {
|
|
56
|
+
const image = await generateOgImage(ctx.params.slug);
|
|
57
|
+
return new Response(image, {
|
|
58
|
+
headers: {
|
|
59
|
+
"Content-Type": "image/png",
|
|
60
|
+
"Cache-Control": "public, max-age=86400",
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
{ name: "ogImage" },
|
|
65
|
+
),
|
|
47
66
|
]);
|
|
48
67
|
```
|
|
49
68
|
|
|
50
69
|
## Available Tags
|
|
51
70
|
|
|
52
|
-
| Tag
|
|
53
|
-
|
|
54
|
-
| `json`
|
|
55
|
-
| `text`
|
|
56
|
-
| `html`
|
|
57
|
-
| `xml`
|
|
58
|
-
| `md`
|
|
59
|
-
| `image`
|
|
60
|
-
| `stream` | `path.stream()` | Response
|
|
61
|
-
| `any`
|
|
71
|
+
| Tag | Usage | Handler returns | Auto-wrap |
|
|
72
|
+
| -------- | --------------- | ------------------ | ----------------------------- |
|
|
73
|
+
| `json` | `path.json()` | plain object/array | bare JSON value (no envelope) |
|
|
74
|
+
| `text` | `path.text()` | string | text/plain Response |
|
|
75
|
+
| `html` | `path.html()` | string | text/html Response |
|
|
76
|
+
| `xml` | `path.xml()` | string | application/xml Response |
|
|
77
|
+
| `md` | `path.md()` | string | text/markdown Response |
|
|
78
|
+
| `image` | `path.image()` | Response | pass-through |
|
|
79
|
+
| `stream` | `path.stream()` | Response | pass-through |
|
|
80
|
+
| `any` | `path.any()` | Response | pass-through |
|
|
62
81
|
|
|
63
82
|
## ResponseHandlerContext
|
|
64
83
|
|
|
@@ -67,14 +86,15 @@ Response route handlers receive a lighter context (no `ctx.use()`, no `ctx.res`)
|
|
|
67
86
|
```typescript
|
|
68
87
|
interface ResponseHandlerContext<TParams, TEnv> {
|
|
69
88
|
request: Request;
|
|
70
|
-
params: TParams;
|
|
71
|
-
env:
|
|
89
|
+
params: TParams; // Typed from URL pattern
|
|
90
|
+
env: TEnv; // Plain bindings (DB, KV, etc.)
|
|
72
91
|
searchParams: URLSearchParams;
|
|
73
92
|
url: URL;
|
|
74
93
|
pathname: string;
|
|
75
|
-
|
|
94
|
+
reverse: (name: string, params?: Record<string, string>) => string;
|
|
95
|
+
get: GetVariableFn; // Read middleware variables
|
|
76
96
|
header: (name: string, value: string) => void;
|
|
77
|
-
|
|
97
|
+
// Use cookies().set(name, value, opts) for cookie mutations (standalone API)
|
|
78
98
|
}
|
|
79
99
|
```
|
|
80
100
|
|
|
@@ -84,63 +104,86 @@ String-returning handlers (json, text, html, xml, md) can set custom headers and
|
|
|
84
104
|
without constructing a full Response:
|
|
85
105
|
|
|
86
106
|
```typescript
|
|
87
|
-
path.md(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
107
|
+
path.md(
|
|
108
|
+
"/docs/:slug.md",
|
|
109
|
+
(ctx) => {
|
|
110
|
+
ctx.header("Cache-Control", "public, max-age=3600");
|
|
111
|
+
cookies().set("last-doc", ctx.params.slug, { path: "/" });
|
|
112
|
+
return `# ${ctx.params.slug}\n\nContent here.`;
|
|
113
|
+
},
|
|
114
|
+
{ name: "docs" },
|
|
115
|
+
);
|
|
92
116
|
```
|
|
93
117
|
|
|
94
|
-
Headers
|
|
118
|
+
Headers set via `ctx.header()` and cookies set via `cookies().set()` are merged into the
|
|
95
119
|
auto-wrapped Response. If the handler returns a `Response` directly, these are ignored
|
|
96
120
|
(use the Response headers instead).
|
|
97
121
|
|
|
98
|
-
### Environment
|
|
122
|
+
### Environment Access
|
|
99
123
|
|
|
100
|
-
`env`
|
|
124
|
+
`ctx.env` is always the plain bindings passed as TEnv to `createRouter<TEnv>()`:
|
|
101
125
|
|
|
102
126
|
```typescript
|
|
103
|
-
|
|
127
|
+
// createRouter<{ DB: D1Database; KV: KVNamespace }>({ ... })
|
|
104
128
|
|
|
105
129
|
// In a response handler:
|
|
106
|
-
path.json(
|
|
107
|
-
|
|
108
|
-
ctx
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
130
|
+
path.json(
|
|
131
|
+
"/api/data",
|
|
132
|
+
(ctx) => {
|
|
133
|
+
ctx.env.DB; // D1Database (plain bindings)
|
|
134
|
+
ctx.env.KV; // KVNamespace
|
|
135
|
+
// Variables are accessed via ctx.get("key") or ctx.get(ContextVar)
|
|
136
|
+
return { data: "ok" };
|
|
137
|
+
},
|
|
138
|
+
{ name: "data" },
|
|
139
|
+
);
|
|
112
140
|
```
|
|
113
141
|
|
|
114
|
-
## JSON
|
|
142
|
+
## JSON Wire Shape
|
|
115
143
|
|
|
116
|
-
`path.json()` handlers return plain data. The framework
|
|
117
|
-
|
|
144
|
+
`path.json()` handlers return plain data. The framework serializes the handler's
|
|
145
|
+
return value **verbatim** (no envelope) on success, and an RFC 9457 `problem+json`
|
|
146
|
+
body on error. Discriminate with `res.ok` / the HTTP status — there is no in-body
|
|
147
|
+
`data`/`error` union:
|
|
118
148
|
|
|
119
149
|
```typescript
|
|
120
|
-
// Success: HTTP 200
|
|
121
|
-
{ "
|
|
122
|
-
|
|
123
|
-
// Error: HTTP 404 (or whatever status RouterError specifies)
|
|
124
|
-
|
|
150
|
+
// Success: HTTP 200, content-type application/json
|
|
151
|
+
{ "status": "ok", "timestamp": 1700000000 }
|
|
152
|
+
|
|
153
|
+
// Error: HTTP 404 (or whatever status RouterError specifies),
|
|
154
|
+
// content-type application/problem+json
|
|
155
|
+
{
|
|
156
|
+
"title": "Not Found",
|
|
157
|
+
"status": 404,
|
|
158
|
+
"detail": "Product 999 not found",
|
|
159
|
+
"code": "NOT_FOUND"
|
|
160
|
+
// "stack": included in development only
|
|
161
|
+
}
|
|
125
162
|
```
|
|
126
163
|
|
|
127
164
|
### Error Handling with RouterError
|
|
128
165
|
|
|
129
|
-
Throw `RouterError` to return structured
|
|
166
|
+
Throw `RouterError` to return a structured `problem+json` body:
|
|
130
167
|
|
|
131
168
|
```typescript
|
|
132
169
|
import { RouterError } from "@rangojs/router";
|
|
133
170
|
|
|
134
|
-
path.json(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
171
|
+
path.json(
|
|
172
|
+
"/api/users/:id",
|
|
173
|
+
(ctx) => {
|
|
174
|
+
const user = users.get(ctx.params.id);
|
|
175
|
+
if (!user) {
|
|
176
|
+
throw new RouterError("NOT_FOUND", `User ${ctx.params.id} not found`, {
|
|
177
|
+
status: 404,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (!hasPermission(ctx)) {
|
|
181
|
+
throw new RouterError("FORBIDDEN", "Access denied", { status: 403 });
|
|
182
|
+
}
|
|
183
|
+
return user;
|
|
184
|
+
},
|
|
185
|
+
{ name: "user" },
|
|
186
|
+
);
|
|
144
187
|
```
|
|
145
188
|
|
|
146
189
|
### Returning Response Directly
|
|
@@ -148,38 +191,44 @@ path.json("/api/users/:id", (ctx) => {
|
|
|
148
191
|
JSON handlers can return `Response` to bypass auto-wrap (custom status, headers, streaming):
|
|
149
192
|
|
|
150
193
|
```typescript
|
|
151
|
-
path.json(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
},
|
|
194
|
+
path.json(
|
|
195
|
+
"/api/export",
|
|
196
|
+
(ctx) => {
|
|
197
|
+
const csv = generateCsv();
|
|
198
|
+
return new Response(csv, {
|
|
199
|
+
headers: {
|
|
200
|
+
"Content-Type": "text/csv",
|
|
201
|
+
"Content-Disposition": "attachment; filename=export.csv",
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
{ name: "export" },
|
|
206
|
+
);
|
|
160
207
|
```
|
|
161
208
|
|
|
162
209
|
## Client-Side Type Safety
|
|
163
210
|
|
|
164
|
-
###
|
|
211
|
+
### Discriminating success vs. error with res.ok
|
|
212
|
+
|
|
213
|
+
Success bodies are the bare value; error bodies are RFC 9457 `ProblemDetails`.
|
|
214
|
+
Branch on `res.ok` (or the HTTP status) — not an in-body union:
|
|
165
215
|
|
|
166
216
|
```typescript
|
|
167
217
|
"use client";
|
|
168
|
-
import type {
|
|
169
|
-
import { isResponseError } from "@rangojs/router/client";
|
|
218
|
+
import type { ProblemDetails } from "@rangojs/router";
|
|
170
219
|
|
|
171
220
|
// Fetch a typed response
|
|
172
221
|
const res = await fetch("/api/products/1");
|
|
173
|
-
const result: ResponseEnvelope<Product> = await res.json();
|
|
174
222
|
|
|
175
|
-
if (
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
223
|
+
if (!res.ok) {
|
|
224
|
+
// Error body: application/problem+json
|
|
225
|
+
const problem: ProblemDetails = await res.json();
|
|
226
|
+
// problem.detail: string, problem.code: string, problem.status: number
|
|
227
|
+
console.error(problem.code, problem.detail);
|
|
179
228
|
} else {
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
console.log(
|
|
229
|
+
// Success body: the bare value (no envelope)
|
|
230
|
+
const product: Product = await res.json();
|
|
231
|
+
console.log(product.name);
|
|
183
232
|
}
|
|
184
233
|
```
|
|
185
234
|
|
|
@@ -192,32 +241,82 @@ import type { RouteResponse } from "@rangojs/router";
|
|
|
192
241
|
|
|
193
242
|
// From the apiPatterns module (before include)
|
|
194
243
|
type HealthData = RouteResponse<typeof apiPatterns, "health">;
|
|
195
|
-
// =
|
|
244
|
+
// = { status: string; timestamp: number }
|
|
196
245
|
|
|
197
246
|
type ProductsData = RouteResponse<typeof apiPatterns, "products">;
|
|
198
|
-
// =
|
|
247
|
+
// = { id: string; name: string; price: number }[]
|
|
199
248
|
```
|
|
200
249
|
|
|
201
|
-
|
|
250
|
+
`RouteResponse` is the bare success payload (the JSON wire shape) — the same value
|
|
251
|
+
a `fetch().then(r => r.json())` yields on a 2xx. Error bodies are `ProblemDetails`,
|
|
252
|
+
keyed off `res.ok` at runtime, not part of this type.
|
|
253
|
+
|
|
254
|
+
### Rango.PathResponse (global lookup by URL pattern or concrete path)
|
|
202
255
|
|
|
203
|
-
|
|
256
|
+
`Rango.PathResponse` is ambient (no import) and reads from `RegisteredRoutes`,
|
|
257
|
+
which carries response payload metadata. That surface is **not** auto-wired —
|
|
258
|
+
without the augmentation below, `Rango.PathResponse` falls back to the generated
|
|
259
|
+
path/search map, or to a permissive map when nothing is generated. Either way, it
|
|
260
|
+
has no response payload metadata, so response routes resolve to `never`:
|
|
204
261
|
|
|
205
262
|
```typescript
|
|
206
|
-
|
|
263
|
+
// router.tsx
|
|
264
|
+
export const router = createRouter({ document: Document }).routes(urlpatterns);
|
|
207
265
|
|
|
266
|
+
declare global {
|
|
267
|
+
namespace Rango {
|
|
268
|
+
interface RegisteredRoutes extends typeof router.routeMap {}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
With that in place, look up the response type by URL pattern (ambient, no import):
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
208
276
|
// After include("/api", apiPatterns) in main urls
|
|
209
|
-
type Health = PathResponse<"/api/health">;
|
|
210
|
-
// =
|
|
277
|
+
type Health = Rango.PathResponse<"/api/health">;
|
|
278
|
+
// = { status: string; timestamp: number }
|
|
279
|
+
|
|
280
|
+
// RSC routes (no JSON payload) return never
|
|
281
|
+
type Home = Rango.PathResponse<"/">;
|
|
282
|
+
// = never
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`Rango.PathResponse` also accepts a **concrete path**, so it types a `fetch`
|
|
286
|
+
wrapper whose response is inferred from the path you pass:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
import { href } from "@rangojs/router/client";
|
|
290
|
+
|
|
291
|
+
async function get<T extends Rango.Path>(
|
|
292
|
+
path: T,
|
|
293
|
+
): Promise<Rango.PathResponse<T>> {
|
|
294
|
+
return fetch(href(path)).then((r) => r.json());
|
|
295
|
+
}
|
|
211
296
|
|
|
212
|
-
//
|
|
213
|
-
type Home = PathResponse<"/">;
|
|
214
|
-
// = ResponseEnvelope<never>
|
|
297
|
+
const product = await get("/api/products/42"); // Product (bare value)
|
|
215
298
|
```
|
|
216
299
|
|
|
300
|
+
Pattern keys (`/:id`) match exactly; a concrete path under a _nested_ dynamic
|
|
301
|
+
route can match several patterns and union their responses.
|
|
302
|
+
|
|
303
|
+
`Rango.PathResponse` reports the JSON **wire** shape, not the handler's raw
|
|
304
|
+
return: `path.json()` serializes with `JSON.stringify`, so a handler returning
|
|
305
|
+
`{ createdAt: Date }` resolves to the bare `{ createdAt: string }`. This
|
|
306
|
+
runs through the ambient `Rango.JsonSerialize<T>` transform (`Date -> string`,
|
|
307
|
+
honors `toJSON()`, drops functions/`undefined`, `bigint -> never`). The
|
|
308
|
+
`RouteResponse` surface below applies the same `Rango.JsonSerialize` transform, so
|
|
309
|
+
both response lookups report the identical wire shape.
|
|
310
|
+
|
|
311
|
+
For local/scoped response typing without global augmentation, prefer
|
|
312
|
+
`RouteResponse<typeof patterns, "routeName">` (see the section above) — it reads
|
|
313
|
+
the response payload straight from the `urls()` patterns and needs no
|
|
314
|
+
`RegisteredRoutes` wiring.
|
|
315
|
+
|
|
217
316
|
### ParamsFor with Response Routes
|
|
218
317
|
|
|
219
318
|
```typescript
|
|
220
|
-
import type { ParamsFor } from "@rangojs/router
|
|
319
|
+
import type { ParamsFor } from "@rangojs/router";
|
|
221
320
|
|
|
222
321
|
// Works for both RSC and response routes
|
|
223
322
|
type ProductParams = ParamsFor<"api.productDetail">;
|
|
@@ -272,18 +371,29 @@ A self-contained module with RSC pages + JSON APIs, mountable via `include()`:
|
|
|
272
371
|
import { urls, RouterError } from "@rangojs/router";
|
|
273
372
|
|
|
274
373
|
export const blogApiPatterns = urls(({ path }) => [
|
|
275
|
-
path.json(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
path.json(
|
|
285
|
-
|
|
286
|
-
|
|
374
|
+
path.json(
|
|
375
|
+
"/stats",
|
|
376
|
+
(ctx) => ({
|
|
377
|
+
views: 1200,
|
|
378
|
+
visitors: 450,
|
|
379
|
+
}),
|
|
380
|
+
{ name: "stats" },
|
|
381
|
+
),
|
|
382
|
+
|
|
383
|
+
path.json(
|
|
384
|
+
"/:slug/likes",
|
|
385
|
+
(ctx) => ({
|
|
386
|
+
slug: ctx.params.slug,
|
|
387
|
+
count: 42,
|
|
388
|
+
}),
|
|
389
|
+
{ name: "likes" },
|
|
390
|
+
),
|
|
391
|
+
|
|
392
|
+
path.json(
|
|
393
|
+
"/:slug/comments",
|
|
394
|
+
(ctx) => [{ id: "c1", body: "Great post", author: "alice" }],
|
|
395
|
+
{ name: "comments" },
|
|
396
|
+
),
|
|
287
397
|
]);
|
|
288
398
|
|
|
289
399
|
// blog/urls.tsx
|
|
@@ -308,19 +418,35 @@ export const urlpatterns = urls(({ path, include }) => [
|
|
|
308
418
|
]);
|
|
309
419
|
```
|
|
310
420
|
|
|
421
|
+
A heavy module like this is a good code-split candidate. Pass an async provider
|
|
422
|
+
and the module — its handlers, response serializers, and any nested
|
|
423
|
+
`include()`s — loads on the first request under the prefix instead of at startup:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
// blog/urls.tsx: `export default blogPatterns`
|
|
427
|
+
include("/blog", () => import("./blog/urls"), { name: "blog" }),
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Named routes and response types still resolve through the split: `TRoutes` and
|
|
431
|
+
the `_responses` phantom are inferred from the resolved `urls()` value, so
|
|
432
|
+
`Rango.PathResponse<"/blog/api/stats">` and `ctx.reverse` are unchanged. See
|
|
433
|
+
`/composability`.
|
|
434
|
+
|
|
311
435
|
### Type safety after mounting
|
|
312
436
|
|
|
313
437
|
```typescript
|
|
314
438
|
import type { RouteResponse } from "@rangojs/router";
|
|
315
|
-
import type {
|
|
439
|
+
import type { ParamsFor } from "@rangojs/router";
|
|
316
440
|
|
|
317
|
-
// Scoped (before mount) -- use the module directly
|
|
441
|
+
// Scoped (before mount) -- use the module directly, no global wiring needed
|
|
318
442
|
type Stats = RouteResponse<typeof blogApiPatterns, "stats">;
|
|
319
|
-
// =
|
|
443
|
+
// = { views: number; visitors: number }
|
|
320
444
|
|
|
321
|
-
// After mounting -- names get prefixed
|
|
322
|
-
|
|
323
|
-
//
|
|
445
|
+
// After mounting -- names get prefixed.
|
|
446
|
+
// Rango.PathResponse needs `RegisteredRoutes extends typeof router.routeMap` (see above),
|
|
447
|
+
// otherwise it resolves to never.
|
|
448
|
+
type BlogStats = Rango.PathResponse<"/blog/api/stats">;
|
|
449
|
+
// = { views: number; visitors: number }
|
|
324
450
|
|
|
325
451
|
// Params work through nested includes
|
|
326
452
|
type LikesParams = ParamsFor<"blog.api.likes">;
|
|
@@ -333,13 +459,17 @@ Response route handlers inside a mounted module can reference local names:
|
|
|
333
459
|
|
|
334
460
|
```typescript
|
|
335
461
|
// Inside blogApiPatterns handler
|
|
336
|
-
path(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
462
|
+
path(
|
|
463
|
+
"/:slug/likes",
|
|
464
|
+
(ctx) => {
|
|
465
|
+
// ctx.reverse resolves names relative to the mount point
|
|
466
|
+
const commentsUrl = ctx.reverse("comments", { slug: ctx.params.slug });
|
|
467
|
+
// -> "/blog/api/my-post/comments"
|
|
468
|
+
|
|
469
|
+
return { slug: ctx.params.slug, count: 42, commentsUrl };
|
|
470
|
+
},
|
|
471
|
+
{ name: "likes" },
|
|
472
|
+
);
|
|
343
473
|
```
|
|
344
474
|
|
|
345
475
|
## Content Negotiation
|
|
@@ -347,12 +477,24 @@ path("/:slug/likes", (ctx) => {
|
|
|
347
477
|
Multiple response types can share the same URL pattern. See `/mime-routes` for the
|
|
348
478
|
full content negotiation API (Accept header matching, Vary: Accept, multi-variant routes).
|
|
349
479
|
|
|
480
|
+
## Long-Lived Responses (SSE / WebSocket)
|
|
481
|
+
|
|
482
|
+
For Server-Sent Events (`path.stream`) and WebSocket upgrades (`path.any`
|
|
483
|
+
returning a 101 / `webSocket` Response), see `/streams-and-websockets`.
|
|
484
|
+
Upgrade responses flow through without reconstruction; `Vary` and
|
|
485
|
+
`Server-Timing` are skipped, and stub headers are applied in place on a
|
|
486
|
+
best-effort basis.
|
|
487
|
+
|
|
350
488
|
## How It Works
|
|
351
489
|
|
|
352
490
|
1. `path.json()` tags the route at the trie level with a MIME type
|
|
353
491
|
2. `coreRequestHandler()` checks the tag before the RSC pipeline
|
|
354
492
|
3. Tagged routes short-circuit: handler runs, Response is returned directly
|
|
355
|
-
4. JSON routes
|
|
493
|
+
4. JSON routes serialize the return value verbatim (bare) on success; a thrown error becomes an RFC 9457 `problem+json` body (`application/problem+json`)
|
|
356
494
|
5. Client-side navigation to response routes gets `X-RSC-Reload` header, triggering hard navigation
|
|
357
495
|
6. Response types flow through `_responses` phantom type on `UrlPatterns`, propagated by `include()`
|
|
358
496
|
7. When multiple routes share a URL pattern, the trie merges them for content negotiation (see `/mime-routes`)
|
|
497
|
+
|
|
498
|
+
## Consuming response routes
|
|
499
|
+
|
|
500
|
+
To call your own response-route JSON APIs from first-party TypeScript with a typed client (typed params, typed payloads inferred from the handler, no `.data`, typed `ProblemDetails` errors), see `/api-client` — a copy-paste recipe over `RouteResponse` + `ExtractParams` + a client-safe path builder. External/third-party consumers use the plain wire directly: bare JSON on success, `application/problem+json` on error.
|