@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
|
@@ -8,12 +8,107 @@ argument-hint: [middleware-name]
|
|
|
8
8
|
|
|
9
9
|
Middleware runs before/after route handlers using the onion model.
|
|
10
10
|
|
|
11
|
+
## Execution Model
|
|
12
|
+
|
|
13
|
+
There are two levels of middleware with different execution scopes:
|
|
14
|
+
|
|
15
|
+
### Global middleware (`router.use()`)
|
|
16
|
+
|
|
17
|
+
Registered on the router instance. Wraps the **entire request**, including server actions, rendering, and progressive enhancement (PE) re-renders.
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
const router = createRouter<AppEnv>({})
|
|
21
|
+
.use(loggerMiddleware) // all routes
|
|
22
|
+
.use("/admin/*", authMiddleware) // pattern-scoped
|
|
23
|
+
.routes(urlpatterns);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
When the router has a `basename`, pattern-scoped `.use()` patterns are automatically prefixed. For example, with `basename: "/app"`, `.use("/admin/*", mw)` matches `/app/admin/*`.
|
|
27
|
+
|
|
28
|
+
### Route middleware (`middleware()` in `urls()`)
|
|
29
|
+
|
|
30
|
+
Registered inside `urls()` callback. Wraps **rendering only** -- it does NOT wrap server action execution. Actions run before route middleware, so when route middleware executes during post-action revalidation, it can observe state that the action set (cookies, context variables, headers).
|
|
31
|
+
|
|
32
|
+
> **Implication for auth:** route middleware cannot guard server actions. Use `router.use("/admin/*", requireAuth)` (global, scoped) for action protection, or check inside the action body. See `/server-actions` for action-side auth patterns.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Request flow (with action):
|
|
36
|
+
global mw -> action executes -> route mw -> render pass
|
|
37
|
+
|
|
38
|
+
Request flow (no action):
|
|
39
|
+
global mw -> route mw -> render pass
|
|
40
|
+
|
|
41
|
+
Progressive enhancement (no-JS form POST):
|
|
42
|
+
global mw -> action executes -> route mw -> full page re-render
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The **render pass** resolves handler, layouts, parallels, and loaders together —
|
|
46
|
+
it is not a handler-then-loaders sequence. Handler-first ordering is guaranteed
|
|
47
|
+
only between a route handler and its child/orphan layouts and parallels (so
|
|
48
|
+
`ctx.set` is visible); loaders run **concurrently** and stream their results, so
|
|
49
|
+
their latency overlaps rendering rather than blocking it. See `/loader` →
|
|
50
|
+
"Parallel and streaming".
|
|
51
|
+
|
|
52
|
+
The contract is: **route middleware wraps rendering regardless of transport** (JS-enabled RSC stream or no-JS HTML). During PE re-render, route middleware observes action-set state (cookies, context variables) the same way it does during JS-enabled post-action revalidation.
|
|
53
|
+
|
|
54
|
+
Revalidation is still partial. Route middleware wraps the render pass that
|
|
55
|
+
does happen, but it does not force unrelated outer segments to recompute.
|
|
56
|
+
If a child segment depends on data established by an outer handler/layout,
|
|
57
|
+
revalidate that outer segment too, or have the child guard/reload the
|
|
58
|
+
data itself.
|
|
59
|
+
|
|
60
|
+
### Revalidation Contracts with Middleware-Backed Trees
|
|
61
|
+
|
|
62
|
+
Middleware can establish request-level context (`ctx.set`) for segments that
|
|
63
|
+
execute in the current render pass. Because route middleware wraps **every**
|
|
64
|
+
render pass — normal renders, post-action revalidation, PE re-renders — its
|
|
65
|
+
variables are never stale: middleware is the safest `ctx.set` rung on the
|
|
66
|
+
data-passing ladder (`/rango` → "Passing data down the tree"). But it does
|
|
67
|
+
not change partial revalidation boundaries between handler/layout/parallel
|
|
68
|
+
segments.
|
|
69
|
+
|
|
70
|
+
For shared segment data, use named revalidation contracts on both the producer
|
|
71
|
+
and consumer segments, even when middleware is present in the chain.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import * as CartActions from "./actions/cart";
|
|
75
|
+
|
|
76
|
+
export const revalidateCartData = (ctx) =>
|
|
77
|
+
ctx.isAction(CartActions) || undefined;
|
|
78
|
+
|
|
79
|
+
layout(CartLayout, () => [
|
|
80
|
+
middleware(cartRenderMiddleware),
|
|
81
|
+
revalidate(revalidateCartData), // producer reruns
|
|
82
|
+
parallel(
|
|
83
|
+
{ "@cart": CartSummary },
|
|
84
|
+
() => [revalidate(revalidateCartData)], // consumer reruns
|
|
85
|
+
),
|
|
86
|
+
]);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You can package those contracts as importable helpers to avoid repeating
|
|
90
|
+
`revalidate(...)` at each segment:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { revalidate } from "@rangojs/router";
|
|
94
|
+
|
|
95
|
+
export const revalidateCart = () => [revalidate(revalidateCartData)];
|
|
96
|
+
|
|
97
|
+
layout(CartLayout, () => [
|
|
98
|
+
middleware(cartRenderMiddleware),
|
|
99
|
+
revalidateCart(),
|
|
100
|
+
parallel({ "@cart": CartSummary }, () => [revalidateCart()]),
|
|
101
|
+
]);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Route middleware is the right place for per-route concerns that affect rendering (setting context variables for handlers, adding response headers, reading cookies set by actions). It is NOT the right place for action guards -- use global middleware for that.
|
|
105
|
+
|
|
11
106
|
## Basic Middleware
|
|
12
107
|
|
|
13
108
|
```typescript
|
|
14
|
-
import {
|
|
109
|
+
import type { Middleware } from "@rangojs/router";
|
|
15
110
|
|
|
16
|
-
export const authMiddleware =
|
|
111
|
+
export const authMiddleware: Middleware = async (ctx, next) => {
|
|
17
112
|
const token = ctx.request.headers.get("Authorization");
|
|
18
113
|
|
|
19
114
|
if (!token) {
|
|
@@ -21,10 +116,10 @@ export const authMiddleware = createMiddleware(async (ctx, next) => {
|
|
|
21
116
|
}
|
|
22
117
|
|
|
23
118
|
const user = await verifyToken(token);
|
|
24
|
-
ctx.
|
|
119
|
+
ctx.set("user", user);
|
|
25
120
|
|
|
26
121
|
await next();
|
|
27
|
-
}
|
|
122
|
+
};
|
|
28
123
|
```
|
|
29
124
|
|
|
30
125
|
## Using Middleware in Routes
|
|
@@ -54,56 +149,141 @@ export const urlpatterns = urls(({ path, layout, middleware }) => [
|
|
|
54
149
|
## Middleware with Multiple Handlers
|
|
55
150
|
|
|
56
151
|
```typescript
|
|
57
|
-
//
|
|
152
|
+
// Group multiple middleware in an array
|
|
58
153
|
export const shopMiddleware = [loggerMiddleware, mockAuthMiddleware];
|
|
59
154
|
|
|
60
|
-
// In routes
|
|
155
|
+
// In routes — pass the array directly
|
|
61
156
|
layout(<ShopLayout />, () => [
|
|
62
|
-
middleware(
|
|
157
|
+
middleware(shopMiddleware),
|
|
63
158
|
|
|
64
159
|
path("/shop", ShopIndex, { name: "shop" }),
|
|
65
160
|
])
|
|
66
161
|
```
|
|
67
162
|
|
|
163
|
+
## Wrapping Middleware (Scoped to Children)
|
|
164
|
+
|
|
165
|
+
Use the wrapping form to scope middleware to a subset of routes without
|
|
166
|
+
introducing a visible layout:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
urls(({ path, middleware }) => [
|
|
170
|
+
// authMw only applies to /admin and /admin/settings
|
|
171
|
+
middleware(authMw, () => [
|
|
172
|
+
path("/admin", AdminPage, { name: "admin" }),
|
|
173
|
+
path("/admin/settings", SettingsPage, { name: "settings" }),
|
|
174
|
+
]),
|
|
175
|
+
|
|
176
|
+
// Public route — no authMw
|
|
177
|
+
path("/", HomePage, { name: "home" }),
|
|
178
|
+
]);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Multiple middleware with wrapping:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
middleware([authMw, loggingMw], () => [
|
|
185
|
+
path("/admin", AdminPage, { name: "admin" }),
|
|
186
|
+
]);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
This creates a transparent layout (`<Outlet />`) that carries the middleware.
|
|
190
|
+
The middleware does not affect sibling routes outside the callback.
|
|
191
|
+
|
|
68
192
|
## Middleware Context
|
|
69
193
|
|
|
70
194
|
```typescript
|
|
71
|
-
export const myMiddleware =
|
|
195
|
+
export const myMiddleware: Middleware = async (ctx, next) => {
|
|
72
196
|
// Access request
|
|
73
|
-
ctx.request;
|
|
74
|
-
ctx.url;
|
|
75
|
-
ctx.params;
|
|
197
|
+
ctx.request; // Request object
|
|
198
|
+
ctx.url; // Parsed URL
|
|
199
|
+
ctx.params; // Route parameters
|
|
76
200
|
|
|
77
|
-
// Access
|
|
78
|
-
ctx.env.
|
|
79
|
-
ctx.env.
|
|
201
|
+
// Access platform bindings (plain bindings from createRouter<TEnv>())
|
|
202
|
+
ctx.env.DB; // D1Database
|
|
203
|
+
ctx.env.KV; // KVNamespace
|
|
80
204
|
|
|
81
|
-
// Set variables for downstream handlers
|
|
82
|
-
ctx.
|
|
205
|
+
// Set variables for downstream handlers (typed via Rango.Vars)
|
|
206
|
+
ctx.set("user", { id: "123", name: "John" });
|
|
83
207
|
|
|
84
208
|
// Continue to next middleware/handler
|
|
85
209
|
await next();
|
|
86
210
|
|
|
87
211
|
// After handler (response intercepting)
|
|
88
212
|
console.log("Handler completed");
|
|
213
|
+
};
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Typed context variables in middleware
|
|
217
|
+
|
|
218
|
+
Use `createVar<T>()` for type-safe data sharing between middleware and handlers:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import { createVar } from "@rangojs/router";
|
|
222
|
+
import type { Middleware } from "@rangojs/router";
|
|
223
|
+
|
|
224
|
+
interface AuthUser { id: string; email: string; role: string }
|
|
225
|
+
export const CurrentUser = createVar<AuthUser>();
|
|
226
|
+
|
|
227
|
+
export const authMiddleware: Middleware = async (ctx, next) => {
|
|
228
|
+
const token = ctx.request.headers.get("Authorization");
|
|
229
|
+
if (!token) throw new Response("Unauthorized", { status: 401 });
|
|
230
|
+
|
|
231
|
+
const user = await verifyToken(token);
|
|
232
|
+
ctx.set(CurrentUser, user); // type-checked
|
|
233
|
+
await next();
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// In a handler -- typed read
|
|
237
|
+
import { CurrentUser } from "./middleware";
|
|
238
|
+
|
|
239
|
+
const Dashboard: Handler<"dashboard"> = (ctx) => {
|
|
240
|
+
const user = ctx.get(CurrentUser); // typed as AuthUser | undefined
|
|
241
|
+
return <DashboardPage user={user!} />;
|
|
242
|
+
};
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
This works alongside `ctx.get("key")` / `ctx.set("key", value)` (global typing
|
|
246
|
+
via Rango.Vars augmentation). Use `createVar` for route-local or feature-scoped
|
|
247
|
+
data; use Rango.Vars for app-wide middleware state.
|
|
248
|
+
|
|
249
|
+
## Redirect with State in Middleware
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
import { redirect, createLocationState } from "@rangojs/router";
|
|
253
|
+
import type { Middleware } from "@rangojs/router";
|
|
254
|
+
|
|
255
|
+
export const FlashMessage = createLocationState<{ text: string }>({
|
|
256
|
+
flash: true,
|
|
89
257
|
});
|
|
258
|
+
|
|
259
|
+
export const requireAuthMiddleware: Middleware = async (ctx, next) => {
|
|
260
|
+
const token = ctx.request.headers.get("Authorization");
|
|
261
|
+
if (!token) {
|
|
262
|
+
return redirect("/login", {
|
|
263
|
+
state: [FlashMessage({ text: "Please log in to continue" })],
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
await next();
|
|
267
|
+
};
|
|
90
268
|
```
|
|
91
269
|
|
|
270
|
+
Read the flash on the target page with `useLocationState(FlashMessage)`. The `{ flash: true }` option makes it auto-clear after first render. See `/hooks`.
|
|
271
|
+
|
|
92
272
|
## Authentication Middleware
|
|
93
273
|
|
|
94
274
|
```typescript
|
|
95
|
-
export const requireAuthMiddleware =
|
|
96
|
-
const user = ctx.
|
|
275
|
+
export const requireAuthMiddleware: Middleware = async (ctx, next) => {
|
|
276
|
+
const user = ctx.get("user");
|
|
97
277
|
|
|
98
278
|
if (!user) {
|
|
99
279
|
throw new Response("Unauthorized", { status: 401 });
|
|
100
280
|
}
|
|
101
281
|
|
|
102
282
|
await next();
|
|
103
|
-
}
|
|
283
|
+
};
|
|
104
284
|
|
|
105
|
-
export const permissionsMiddleware =
|
|
106
|
-
const user = ctx.
|
|
285
|
+
export const permissionsMiddleware: Middleware = async (ctx, next) => {
|
|
286
|
+
const user = ctx.get("user");
|
|
107
287
|
const requiredPermission = "admin";
|
|
108
288
|
|
|
109
289
|
if (!user?.permissions?.includes(requiredPermission)) {
|
|
@@ -111,13 +291,13 @@ export const permissionsMiddleware = createMiddleware(async (ctx, next) => {
|
|
|
111
291
|
}
|
|
112
292
|
|
|
113
293
|
await next();
|
|
114
|
-
}
|
|
294
|
+
};
|
|
115
295
|
```
|
|
116
296
|
|
|
117
297
|
## Logger Middleware
|
|
118
298
|
|
|
119
299
|
```typescript
|
|
120
|
-
export const loggerMiddleware =
|
|
300
|
+
export const loggerMiddleware: Middleware = async (ctx, next) => {
|
|
121
301
|
const start = Date.now();
|
|
122
302
|
|
|
123
303
|
console.log(`[${ctx.request.method}] ${ctx.url.pathname}`);
|
|
@@ -126,54 +306,54 @@ export const loggerMiddleware = createMiddleware(async (ctx, next) => {
|
|
|
126
306
|
|
|
127
307
|
const duration = Date.now() - start;
|
|
128
308
|
console.log(`[${ctx.request.method}] ${ctx.url.pathname} - ${duration}ms`);
|
|
129
|
-
}
|
|
309
|
+
};
|
|
130
310
|
```
|
|
131
311
|
|
|
132
312
|
## Rate Limiting Middleware
|
|
133
313
|
|
|
134
314
|
```typescript
|
|
135
|
-
export const rateLimitMiddleware =
|
|
315
|
+
export const rateLimitMiddleware: Middleware = async (ctx, next) => {
|
|
136
316
|
const ip = ctx.request.headers.get("CF-Connecting-IP") ?? "unknown";
|
|
137
317
|
const key = `rate-limit:${ip}`;
|
|
138
318
|
|
|
139
|
-
const count = await ctx.env.
|
|
319
|
+
const count = await ctx.env.KV.get(key);
|
|
140
320
|
const requests = count ? parseInt(count) : 0;
|
|
141
321
|
|
|
142
322
|
if (requests > 100) {
|
|
143
323
|
throw new Response("Too Many Requests", { status: 429 });
|
|
144
324
|
}
|
|
145
325
|
|
|
146
|
-
await ctx.env.
|
|
326
|
+
await ctx.env.KV.put(key, String(requests + 1), {
|
|
147
327
|
expirationTtl: 60,
|
|
148
328
|
});
|
|
149
329
|
|
|
150
330
|
await next();
|
|
151
|
-
}
|
|
331
|
+
};
|
|
152
332
|
```
|
|
153
333
|
|
|
154
334
|
## Complete Example
|
|
155
335
|
|
|
156
336
|
```typescript
|
|
157
337
|
// middleware/index.ts
|
|
158
|
-
import {
|
|
338
|
+
import type { Middleware } from "@rangojs/router";
|
|
159
339
|
|
|
160
|
-
export const loggerMiddleware =
|
|
340
|
+
export const loggerMiddleware: Middleware = async (ctx, next) => {
|
|
161
341
|
console.log(`[${ctx.request.method}] ${ctx.url.pathname}`);
|
|
162
342
|
await next();
|
|
163
|
-
}
|
|
343
|
+
};
|
|
164
344
|
|
|
165
|
-
export const mockAuthMiddleware =
|
|
345
|
+
export const mockAuthMiddleware: Middleware = async (ctx, next) => {
|
|
166
346
|
// Mock user for development
|
|
167
|
-
ctx.
|
|
347
|
+
ctx.set("user", { id: "1", name: "Demo User" });
|
|
168
348
|
await next();
|
|
169
|
-
}
|
|
349
|
+
};
|
|
170
350
|
|
|
171
|
-
export const requireAuthMiddleware =
|
|
172
|
-
if (!ctx.
|
|
351
|
+
export const requireAuthMiddleware: Middleware = async (ctx, next) => {
|
|
352
|
+
if (!ctx.get("user")) {
|
|
173
353
|
throw new Response("Unauthorized", { status: 401 });
|
|
174
354
|
}
|
|
175
355
|
await next();
|
|
176
|
-
}
|
|
356
|
+
};
|
|
177
357
|
|
|
178
358
|
// urls.tsx
|
|
179
359
|
import { urls } from "@rangojs/router";
|