@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
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare custom-spans integration.
|
|
3
|
+
*
|
|
4
|
+
* Bridges the router's performance phases (request, middleware, action,
|
|
5
|
+
* loaders, handler, render, ssr) onto Cloudflare Workers custom spans so they show
|
|
6
|
+
* up in the trace waterfall and OpenTelemetry exports next to the platform's
|
|
7
|
+
* automatic spans (KV reads, D1 queries, fetch calls), with correct nesting.
|
|
8
|
+
*
|
|
9
|
+
* Usage (Cloudflare preset only):
|
|
10
|
+
*
|
|
11
|
+
* import { createRouter } from "@rangojs/router";
|
|
12
|
+
* import { createCloudflareTracing } from "@rangojs/router/cloudflare";
|
|
13
|
+
*
|
|
14
|
+
* export const router = createRouter({
|
|
15
|
+
* tracing: createCloudflareTracing(),
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* The runner reads `executionContext.tracing` (the same object as
|
|
19
|
+
* `import { tracing } from "cloudflare:workers"`) at call time. It is therefore
|
|
20
|
+
* dependency-free: no `cloudflare:workers` import and no hard dependency on
|
|
21
|
+
* `@cloudflare/workers-types`, matching the convention in cache/cf. When the
|
|
22
|
+
* worker is not running on a tracing-enabled Cloudflare runtime — Node, dev
|
|
23
|
+
* without a tracing destination, an older runtime — `executionContext.tracing`
|
|
24
|
+
* is undefined and every span call falls through to the work directly, so the
|
|
25
|
+
* request behaves exactly as if tracing were off. Whether spans are actually
|
|
26
|
+
* recorded is governed by the `observability`/tracing block in wrangler config.
|
|
27
|
+
*
|
|
28
|
+
* Span duration note: enterSpan ends a span when its callback's returned value
|
|
29
|
+
* (or promise) settles. For the streaming phases (request/render/ssr) that is at
|
|
30
|
+
* stream CONSTRUCTION, not body-drain. Instrumentation is best-effort and never
|
|
31
|
+
* wraps or buffers the response body, so it cannot regress streaming or latency.
|
|
32
|
+
* A loader/Suspense child that resolves mid-stream therefore keeps a rango.loader
|
|
33
|
+
* span that can extend past its render parent — overlapping spans are valid. Uses
|
|
34
|
+
* only the typed enterSpan API; spans bound work up to stream-handoff, matching
|
|
35
|
+
* the co-emitted perf metric.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { _getRequestContext } from "../server/request-context.js";
|
|
39
|
+
import {
|
|
40
|
+
type RouterTracingConfig,
|
|
41
|
+
type SpanRunner,
|
|
42
|
+
type TracePhaseToggles,
|
|
43
|
+
NOOP_TRACE_SPAN,
|
|
44
|
+
} from "../router/tracing.js";
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Minimal local view of Cloudflare's `Span`. Declared here (not imported from
|
|
48
|
+
* `@cloudflare/workers-types`) to avoid a hard type dependency.
|
|
49
|
+
*/
|
|
50
|
+
interface CloudflareSpan {
|
|
51
|
+
readonly isTraced: boolean;
|
|
52
|
+
setAttribute(key: string, value?: boolean | number | string): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Minimal local view of Cloudflare's `Tracing` (only enterSpan is used). */
|
|
56
|
+
interface CloudflareTracing {
|
|
57
|
+
enterSpan<T>(name: string, callback: (span: CloudflareSpan) => T): T;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Options for createCloudflareTracing. */
|
|
61
|
+
export interface CloudflareTracingOptions {
|
|
62
|
+
/** Master switch. Defaults to true. */
|
|
63
|
+
enabled?: boolean;
|
|
64
|
+
/** Per-phase span toggles. Omitted phases default to enabled. */
|
|
65
|
+
spans?: TracePhaseToggles;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the per-request Cloudflare tracer from the active execution context.
|
|
70
|
+
* Returns undefined off-Cloudflare or when tracing is not enabled for the
|
|
71
|
+
* worker, in which case the caller runs the work without a span.
|
|
72
|
+
*/
|
|
73
|
+
function getRequestTracer(): CloudflareTracing | undefined {
|
|
74
|
+
const executionContext = _getRequestContext()?.executionContext as
|
|
75
|
+
| { tracing?: CloudflareTracing }
|
|
76
|
+
| undefined;
|
|
77
|
+
const tracing = executionContext?.tracing;
|
|
78
|
+
return tracing && typeof tracing.enterSpan === "function"
|
|
79
|
+
? tracing
|
|
80
|
+
: undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const cloudflareSpanRunner: SpanRunner = (name, fn) => {
|
|
84
|
+
const tracer = getRequestTracer();
|
|
85
|
+
if (!tracer) return fn(NOOP_TRACE_SPAN);
|
|
86
|
+
// enterSpan runs the callback now and ends the span when its return value
|
|
87
|
+
// (or returned promise) settles; spans nest by JS async context. fn's param
|
|
88
|
+
// is the narrower TraceSpan, so the wider CloudflareSpan satisfies it directly.
|
|
89
|
+
return tracer.enterSpan(name, fn);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Create the tracing config for a Cloudflare router. Pass the result to
|
|
94
|
+
* `createRouter({ tracing })`. Spans are emitted for the request, middleware,
|
|
95
|
+
* action, loaders, handler, render, and ssr phases; pass `spans` to turn
|
|
96
|
+
* individual phases off.
|
|
97
|
+
*
|
|
98
|
+
* @see createOTelTracing (`@rangojs/router`) for the same slot on any platform
|
|
99
|
+
* with an OpenTelemetry SDK.
|
|
100
|
+
*/
|
|
101
|
+
export function createCloudflareTracing(
|
|
102
|
+
options: CloudflareTracingOptions = {},
|
|
103
|
+
): RouterTracingConfig {
|
|
104
|
+
return {
|
|
105
|
+
runner: cloudflareSpanRunner,
|
|
106
|
+
enabled: options.enabled ?? true,
|
|
107
|
+
spans: options.spans,
|
|
108
|
+
};
|
|
109
|
+
}
|
package/src/component-utils.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { ComponentType } from "react";
|
|
8
|
+
import { isUnderTestRunner } from "./runtime-env.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Symbol used by React to mark client component references.
|
|
@@ -33,7 +34,7 @@ const CLIENT_REFERENCE = Symbol.for("react.client.reference");
|
|
|
33
34
|
* ```
|
|
34
35
|
*/
|
|
35
36
|
export function isClientComponent(
|
|
36
|
-
component: ComponentType<unknown> | unknown
|
|
37
|
+
component: ComponentType<unknown> | unknown,
|
|
37
38
|
): boolean {
|
|
38
39
|
if (typeof component !== "function") {
|
|
39
40
|
return false;
|
|
@@ -48,25 +49,43 @@ export function isClientComponent(
|
|
|
48
49
|
*
|
|
49
50
|
* @param component - The component to check
|
|
50
51
|
* @param name - Name to use in error message (e.g., "document")
|
|
52
|
+
* @param opts.allowServerInTest - When true AND running under a test runner
|
|
53
|
+
* (`isUnderTestRunner()`), relax ONLY the "use client" requirement: a server
|
|
54
|
+
* component is accepted. The plugin's "use client" transform does not run in a
|
|
55
|
+
* bare unit test, so a real exported `document` (almost every app sets one) has
|
|
56
|
+
* no client marker and would otherwise throw at `createRouter`, blocking
|
|
57
|
+
* `dispatch`/`assertGeneratedRoutesMatch` against the real router. The document
|
|
58
|
+
* reference is irrelevant to those (no Flight render). The "not a JSX element"
|
|
59
|
+
* guard still fires, and a real dev/build still throws (mirrors the runtime
|
|
60
|
+
* fallback-id gating in handle.ts/loader.ts).
|
|
51
61
|
* @throws Error if the component is not a client component
|
|
52
62
|
*/
|
|
53
63
|
export function assertClientComponent(
|
|
54
64
|
component: ComponentType<unknown> | unknown,
|
|
55
|
-
name: string
|
|
65
|
+
name: string,
|
|
66
|
+
opts?: { allowServerInTest?: boolean },
|
|
56
67
|
): asserts component is ComponentType<unknown> {
|
|
57
68
|
if (typeof component !== "function") {
|
|
58
69
|
throw new Error(
|
|
59
70
|
`${name} must be a client component function with "use client" directive. ` +
|
|
60
71
|
`Make sure to pass the component itself, not a JSX element: ` +
|
|
61
|
-
`${name}: My${capitalize(name)} (correct) vs ${name}: <My${capitalize(name)} /> (incorrect)
|
|
72
|
+
`${name}: My${capitalize(name)} (correct) vs ${name}: <My${capitalize(name)} /> (incorrect)`,
|
|
62
73
|
);
|
|
63
74
|
}
|
|
64
75
|
|
|
76
|
+
// Under a test runner the "use client" transform did not run, so a real
|
|
77
|
+
// server-rendered `document` has no client marker; accept it (the reference is
|
|
78
|
+
// never serialized in dispatch/route-map checks). Outside a test runner this
|
|
79
|
+
// still throws — the build-time safety net is preserved.
|
|
80
|
+
if (opts?.allowServerInTest && isUnderTestRunner()) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
65
84
|
if (!isClientComponent(component)) {
|
|
66
85
|
throw new Error(
|
|
67
86
|
`${name} must be a client component with "use client" directive at the top of the file. ` +
|
|
68
87
|
`Server components cannot be used as the ${name} because their function reference ` +
|
|
69
|
-
`cannot be serialized in the RSC payload. Add "use client" to your ${name} file
|
|
88
|
+
`cannot be serialized in the RSC payload. Add "use client" to your ${name} file.`,
|
|
70
89
|
);
|
|
71
90
|
}
|
|
72
91
|
}
|
|
@@ -2,22 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
import type { ReactNode, ReactElement } from "react";
|
|
4
4
|
import { MetaTags } from "../handles/MetaTags.js";
|
|
5
|
+
import { Scripts } from "../handles/Scripts.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Default document component that provides a basic HTML structure.
|
|
8
9
|
* Used when no custom document is provided to createRouter.
|
|
9
|
-
* Includes MetaTags for automatic charset, viewport, and route meta support
|
|
10
|
+
* Includes MetaTags for automatic charset, viewport, and route meta support,
|
|
11
|
+
* and Scripts (head + body sites) so the Script handle works out of the box.
|
|
10
12
|
*
|
|
11
13
|
* Uses suppressHydrationWarning on <html> because the theme script
|
|
12
14
|
* may modify class/style attributes before React hydrates.
|
|
13
15
|
*/
|
|
14
|
-
export function DefaultDocument({
|
|
16
|
+
export function DefaultDocument({
|
|
17
|
+
children,
|
|
18
|
+
}: {
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
}): ReactElement {
|
|
15
21
|
return (
|
|
16
22
|
<html lang="en" suppressHydrationWarning>
|
|
17
23
|
<head>
|
|
18
24
|
<MetaTags />
|
|
25
|
+
<Scripts />
|
|
19
26
|
</head>
|
|
20
|
-
<body>
|
|
27
|
+
<body>
|
|
28
|
+
<Scripts position="body" />
|
|
29
|
+
{children}
|
|
30
|
+
</body>
|
|
21
31
|
</html>
|
|
22
32
|
);
|
|
23
33
|
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed context variables for ctx.set() / ctx.get().
|
|
3
|
+
*
|
|
4
|
+
* createVar<T>() produces a typed token that handlers set and layouts/middleware
|
|
5
|
+
* read. The token carries a unique Symbol used as the property key on the
|
|
6
|
+
* per-request variables object — no build-time processing, no IDs.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { createVar } from "@rangojs/router";
|
|
11
|
+
*
|
|
12
|
+
* interface PaginationData { current: number; total: number }
|
|
13
|
+
* export const Pagination = createVar<PaginationData>();
|
|
14
|
+
*
|
|
15
|
+
* // Non-cacheable var — ctx.get(User) throws inside a cache() boundary
|
|
16
|
+
* export const User = createVar<UserData>({ cache: false });
|
|
17
|
+
*
|
|
18
|
+
* // handler
|
|
19
|
+
* ctx.set(Pagination, { current: 1, total: 4 });
|
|
20
|
+
*
|
|
21
|
+
* // layout
|
|
22
|
+
* const pg = ctx.get(Pagination); // PaginationData | undefined
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export interface ContextVar<T> {
|
|
27
|
+
readonly __brand: "context-var";
|
|
28
|
+
readonly key: symbol;
|
|
29
|
+
/** When false, ctx.get(var) throws inside a cache() boundary. */
|
|
30
|
+
readonly cache: boolean;
|
|
31
|
+
/** Phantom field to carry the type parameter. Never set at runtime. */
|
|
32
|
+
readonly __type?: T;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ContextVarOptions {
|
|
36
|
+
/**
|
|
37
|
+
* When false, marks this variable as non-cacheable.
|
|
38
|
+
* Reading this var with ctx.get() inside a cache() boundary throws. Use for
|
|
39
|
+
* inherently request-specific data (user sessions, auth tokens, etc.) that
|
|
40
|
+
* must never be baked into cached segments.
|
|
41
|
+
*
|
|
42
|
+
* @default true
|
|
43
|
+
*/
|
|
44
|
+
cache?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Create a typed context variable token.
|
|
49
|
+
*
|
|
50
|
+
* The returned object is used with ctx.set(token, value) and ctx.get(token)
|
|
51
|
+
* for compile-time-checked data flow between handlers, layouts, and middleware.
|
|
52
|
+
*/
|
|
53
|
+
export function createVar<T>(options?: ContextVarOptions): ContextVar<T> {
|
|
54
|
+
return {
|
|
55
|
+
__brand: "context-var" as const,
|
|
56
|
+
key: Symbol(),
|
|
57
|
+
cache: options?.cache !== false,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Type guard: is the value a ContextVar token?
|
|
63
|
+
*/
|
|
64
|
+
export function isContextVar(value: unknown): value is ContextVar<unknown> {
|
|
65
|
+
return (
|
|
66
|
+
typeof value === "object" &&
|
|
67
|
+
value !== null &&
|
|
68
|
+
"__brand" in value &&
|
|
69
|
+
(value as { __brand: unknown }).__brand === "context-var"
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Does a variables object hold any entries? Counts both string keys and the
|
|
75
|
+
* symbol-keyed entries (context vars are stored under symbols), so an object
|
|
76
|
+
* carrying only symbol-keyed vars is still reported as non-empty.
|
|
77
|
+
*/
|
|
78
|
+
export function hasContextVars(variables: object): boolean {
|
|
79
|
+
return (
|
|
80
|
+
Object.keys(variables).length > 0 ||
|
|
81
|
+
Object.getOwnPropertySymbols(variables).length > 0
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Symbol used as a Set stored on the variables object to track
|
|
87
|
+
* which keys hold non-cacheable values (from write-level { cache: false }).
|
|
88
|
+
*/
|
|
89
|
+
const NON_CACHEABLE_KEYS: unique symbol = Symbol.for(
|
|
90
|
+
"rango:non-cacheable-keys",
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
function getNonCacheableKeys(variables: any): Set<string | symbol> {
|
|
94
|
+
if (!variables[NON_CACHEABLE_KEYS]) {
|
|
95
|
+
variables[NON_CACHEABLE_KEYS] = new Set();
|
|
96
|
+
}
|
|
97
|
+
return variables[NON_CACHEABLE_KEYS];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Check if a variable value is non-cacheable (either var-level or write-level).
|
|
102
|
+
*/
|
|
103
|
+
export function isNonCacheable(
|
|
104
|
+
variables: any,
|
|
105
|
+
keyOrVar: string | ContextVar<any>,
|
|
106
|
+
): boolean {
|
|
107
|
+
if (typeof keyOrVar !== "string" && !keyOrVar.cache) {
|
|
108
|
+
return true; // var-level policy
|
|
109
|
+
}
|
|
110
|
+
const key = typeof keyOrVar === "string" ? keyOrVar : keyOrVar.key;
|
|
111
|
+
const set = variables[NON_CACHEABLE_KEYS] as Set<string | symbol> | undefined;
|
|
112
|
+
return set?.has(key) ?? false; // write-level policy
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Read a variable from the variables store.
|
|
117
|
+
* Accepts either a string key (legacy) or a ContextVar token (typed).
|
|
118
|
+
*/
|
|
119
|
+
export function contextGet(
|
|
120
|
+
variables: any,
|
|
121
|
+
keyOrVar: string | ContextVar<any>,
|
|
122
|
+
): any {
|
|
123
|
+
if (typeof keyOrVar === "string") return variables[keyOrVar];
|
|
124
|
+
return variables[keyOrVar.key];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Keys that must never be used as string variable names */
|
|
128
|
+
const FORBIDDEN_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
129
|
+
|
|
130
|
+
export interface ContextSetOptions {
|
|
131
|
+
/**
|
|
132
|
+
* When false, marks this specific write as non-cacheable.
|
|
133
|
+
* "Least cacheable wins" — if either the var definition or this option
|
|
134
|
+
* says cache: false, the value is non-cacheable.
|
|
135
|
+
*
|
|
136
|
+
* @default true (inherits from createVar)
|
|
137
|
+
*/
|
|
138
|
+
cache?: boolean;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Write a variable to the variables store.
|
|
143
|
+
* Accepts either a string key (legacy) or a ContextVar token (typed).
|
|
144
|
+
*/
|
|
145
|
+
export function contextSet(
|
|
146
|
+
variables: any,
|
|
147
|
+
keyOrVar: string | ContextVar<any>,
|
|
148
|
+
value: any,
|
|
149
|
+
options?: ContextSetOptions,
|
|
150
|
+
): void {
|
|
151
|
+
if (typeof keyOrVar === "string") {
|
|
152
|
+
if (FORBIDDEN_KEYS.has(keyOrVar)) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`ctx.set(): "${keyOrVar}" is a reserved key and cannot be used as a variable name.`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
variables[keyOrVar] = value;
|
|
158
|
+
if (options?.cache === false) {
|
|
159
|
+
getNonCacheableKeys(variables).add(keyOrVar);
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
variables[keyOrVar.key] = value;
|
|
163
|
+
// Track write-level non-cacheable (var-level is checked via keyOrVar.cache)
|
|
164
|
+
if (options?.cache === false) {
|
|
165
|
+
getNonCacheableKeys(variables).add(keyOrVar.key);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
package/src/debug.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Debug utilities for manifest inspection and comparison
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type
|
|
5
|
+
import { getParallelSlotCount, type EntryData } from "./server/context";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Serialized entry for debug output
|
|
@@ -34,7 +34,7 @@ export interface SerializedManifest {
|
|
|
34
34
|
* Serialize a manifest Map into a JSON-friendly structure
|
|
35
35
|
*/
|
|
36
36
|
export function serializeManifest(
|
|
37
|
-
manifest: Map<string, EntryData
|
|
37
|
+
manifest: Map<string, EntryData>,
|
|
38
38
|
): SerializedManifest {
|
|
39
39
|
const routes: Record<string, SerializedEntry> = {};
|
|
40
40
|
const layouts: Record<string, SerializedEntry> = {};
|
|
@@ -64,7 +64,7 @@ export function serializeManifest(
|
|
|
64
64
|
hasLoader: entry.loader?.length > 0,
|
|
65
65
|
hasMiddleware: entry.middleware?.length > 0,
|
|
66
66
|
hasErrorBoundary: entry.errorBoundary?.length > 0,
|
|
67
|
-
parallelCount: entry.parallel
|
|
67
|
+
parallelCount: getParallelSlotCount(entry.parallel),
|
|
68
68
|
interceptCount: entry.intercept?.length ?? 0,
|
|
69
69
|
};
|
|
70
70
|
|
|
@@ -92,7 +92,7 @@ export function serializeManifest(
|
|
|
92
92
|
*/
|
|
93
93
|
export function compareManifests(
|
|
94
94
|
oldManifest: SerializedManifest,
|
|
95
|
-
newManifest: SerializedManifest
|
|
95
|
+
newManifest: SerializedManifest,
|
|
96
96
|
): {
|
|
97
97
|
addedRoutes: string[];
|
|
98
98
|
removedRoutes: string[];
|
|
@@ -113,10 +113,20 @@ export function compareManifests(
|
|
|
113
113
|
} {
|
|
114
114
|
const addedRoutes: string[] = [];
|
|
115
115
|
const removedRoutes: string[] = [];
|
|
116
|
-
const changedRoutes: Array<{
|
|
116
|
+
const changedRoutes: Array<{
|
|
117
|
+
key: string;
|
|
118
|
+
field: string;
|
|
119
|
+
old: any;
|
|
120
|
+
new: any;
|
|
121
|
+
}> = [];
|
|
117
122
|
const addedLayouts: string[] = [];
|
|
118
123
|
const removedLayouts: string[] = [];
|
|
119
|
-
const changedLayouts: Array<{
|
|
124
|
+
const changedLayouts: Array<{
|
|
125
|
+
key: string;
|
|
126
|
+
field: string;
|
|
127
|
+
old: any;
|
|
128
|
+
new: any;
|
|
129
|
+
}> = [];
|
|
120
130
|
|
|
121
131
|
// Compare routes
|
|
122
132
|
const oldRouteKeys = new Set(Object.keys(oldManifest.routes));
|
|
@@ -191,7 +201,7 @@ export function compareManifests(
|
|
|
191
201
|
* Format manifest diff as a human-readable string
|
|
192
202
|
*/
|
|
193
203
|
export function formatManifestDiff(
|
|
194
|
-
diff: ReturnType<typeof compareManifests
|
|
204
|
+
diff: ReturnType<typeof compareManifests>,
|
|
195
205
|
): string {
|
|
196
206
|
const lines: string[] = [];
|
|
197
207
|
|
|
@@ -208,7 +218,7 @@ export function formatManifestDiff(
|
|
|
208
218
|
if (diff.changedRoutes.length > 0) {
|
|
209
219
|
lines.push("Changed routes:");
|
|
210
220
|
diff.changedRoutes.forEach((c) =>
|
|
211
|
-
lines.push(` ~ ${c.key}.${c.field}: ${c.old} -> ${c.new}`)
|
|
221
|
+
lines.push(` ~ ${c.key}.${c.field}: ${c.old} -> ${c.new}`),
|
|
212
222
|
);
|
|
213
223
|
}
|
|
214
224
|
|
|
@@ -225,7 +235,7 @@ export function formatManifestDiff(
|
|
|
225
235
|
if (diff.changedLayouts.length > 0) {
|
|
226
236
|
lines.push("Changed layouts:");
|
|
227
237
|
diff.changedLayouts.forEach((c) =>
|
|
228
|
-
lines.push(` ~ ${c.key}.${c.field}: ${c.old} -> ${c.new}`)
|
|
238
|
+
lines.push(` ~ ${c.key}.${c.field}: ${c.old} -> ${c.new}`),
|
|
229
239
|
);
|
|
230
240
|
}
|
|
231
241
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { isLoaderDataResult } from "./types.js";
|
|
3
|
+
|
|
4
|
+
// Shared by segment-system (server) and LoaderResolver (client) so the
|
|
5
|
+
// legacy/ok/error-fallback/throw decode of resolved loader values lives once.
|
|
6
|
+
// Last failing loader wins errorFallback; an error without a fallback throws.
|
|
7
|
+
export function decodeLoaderResults(
|
|
8
|
+
resolvedData: any[],
|
|
9
|
+
loaderIds: string[],
|
|
10
|
+
): { loaderData: Record<string, any>; errorFallback: ReactNode } {
|
|
11
|
+
const loaderData: Record<string, any> = {};
|
|
12
|
+
let errorFallback: ReactNode = null;
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < loaderIds.length; i++) {
|
|
15
|
+
const id = loaderIds[i];
|
|
16
|
+
const result = resolvedData[i];
|
|
17
|
+
|
|
18
|
+
if (!isLoaderDataResult(result)) {
|
|
19
|
+
loaderData[id] = result;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (result.ok) {
|
|
24
|
+
loaderData[id] = result.data;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// null/undefined is the producer's ONLY "no boundary found" sentinel
|
|
29
|
+
// (loader-resolution.ts sets fallback: null for the no-boundary and the
|
|
30
|
+
// fallback-render-threw cases). A matched boundary's rendered ReactNode can
|
|
31
|
+
// legitimately be falsy (0, "", false), so test for null explicitly rather
|
|
32
|
+
// than truthiness, otherwise a valid falsy fallback is discarded and the
|
|
33
|
+
// original loader error is rethrown.
|
|
34
|
+
if (result.fallback != null) {
|
|
35
|
+
errorFallback = result.fallback;
|
|
36
|
+
} else {
|
|
37
|
+
// No boundary: rethrow preserving the ErrorInfo identity (name/stack/
|
|
38
|
+
// code/cause) instead of a stripped generic Error.
|
|
39
|
+
const info = result.error;
|
|
40
|
+
const err = new Error(
|
|
41
|
+
info.message,
|
|
42
|
+
info.cause !== undefined ? { cause: info.cause } : undefined,
|
|
43
|
+
);
|
|
44
|
+
if (info.name) err.name = info.name;
|
|
45
|
+
if (info.stack) err.stack = info.stack;
|
|
46
|
+
if (info.code !== undefined) (err as { code?: string }).code = info.code;
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { loaderData, errorFallback };
|
|
52
|
+
}
|