@rangojs/router 0.0.0-experimental.32 → 0.0.0-experimental.3232cd17
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 +4 -0
- package/README.md +198 -44
- package/dist/bin/rango.js +287 -105
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3248 -1117
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +73 -21
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +107 -1
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +245 -21
- package/skills/caching/SKILL.md +302 -6
- package/skills/composability/SKILL.md +27 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +270 -30
- package/skills/host-router/SKILL.md +82 -22
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +49 -5
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +294 -30
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +203 -7
- package/skills/prerender/SKILL.md +123 -100
- package/skills/rango/SKILL.md +250 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +122 -47
- package/skills/route/SKILL.md +97 -5
- package/skills/router-setup/SKILL.md +90 -5
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +129 -0
- package/skills/testing/bindings.md +89 -0
- package/skills/testing/cache-prerender.md +124 -0
- package/skills/testing/client-components.md +122 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +92 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +121 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +84 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +120 -0
- package/skills/typesafety/SKILL.md +329 -27
- package/skills/use-cache/SKILL.md +36 -5
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +67 -40
- package/src/browser/action-coordinator.ts +53 -36
- 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/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +86 -147
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +148 -19
- package/src/browser/navigation-client.ts +187 -67
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +76 -67
- package/src/browser/navigation-transaction.ts +18 -66
- package/src/browser/partial-update.ts +123 -94
- package/src/browser/prefetch/cache.ts +214 -36
- package/src/browser/prefetch/fetch.ts +260 -38
- package/src/browser/prefetch/policy.ts +6 -0
- package/src/browser/prefetch/queue.ts +126 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +93 -11
- package/src/browser/react/NavigationProvider.tsx +115 -34
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/filter-segment-order.ts +49 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +166 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +23 -69
- package/src/browser/react/use-link-status.ts +0 -4
- package/src/browser/react/use-navigation.ts +22 -5
- package/src/browser/react/use-params.ts +20 -10
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +46 -11
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +11 -21
- package/src/browser/response-adapter.ts +52 -1
- package/src/browser/rsc-router.tsx +215 -76
- package/src/browser/scroll-restoration.ts +46 -39
- package/src/browser/segment-reconciler.ts +36 -9
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +176 -50
- package/src/browser/types.ts +95 -11
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +65 -40
- package/src/build/generate-route-types.ts +5 -0
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +137 -32
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +9 -2
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +278 -96
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-policy.ts +68 -28
- package/src/cache/cache-runtime.ts +149 -43
- package/src/cache/cache-scope.ts +148 -81
- package/src/cache/cache-tag.ts +98 -0
- package/src/cache/cf/cf-cache-store.ts +2550 -93
- package/src/cache/cf/index.ts +11 -17
- package/src/cache/document-cache.ts +78 -27
- package/src/cache/handle-snapshot.ts +63 -0
- package/src/cache/index.ts +23 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +6 -30
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +0 -16
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +55 -0
- package/src/cache/types.ts +33 -100
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +799 -0
- package/src/client.rsc.tsx +6 -21
- package/src/client.tsx +108 -290
- package/src/component-utils.ts +19 -0
- package/src/context-var.ts +84 -2
- package/src/debug.ts +2 -2
- package/src/decode-loader-results.ts +36 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/errors.ts +30 -4
- package/src/handle.ts +70 -22
- package/src/handles/MetaTags.tsx +0 -14
- package/src/handles/breadcrumbs.ts +16 -5
- package/src/handles/meta.ts +0 -39
- package/src/host/cookie-handler.ts +0 -36
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +7 -50
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +52 -26
- package/src/index.ts +100 -38
- package/src/internal-debug.ts +2 -4
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/network-error-thrower.tsx +1 -6
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +10 -11
- package/src/prerender/store.ts +37 -41
- package/src/prerender.ts +198 -82
- package/src/redirect-origin.ts +100 -0
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +65 -15
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +7 -72
- package/src/route-definition/dsl-helpers.ts +437 -274
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +113 -37
- package/src/route-definition/index.ts +3 -0
- package/src/route-definition/redirect.ts +52 -10
- package/src/route-definition/resolve-handler-use.ts +161 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +7 -17
- package/src/route-types.ts +37 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +108 -9
- package/src/router/error-handling.ts +13 -17
- package/src/router/find-match.ts +45 -22
- package/src/router/handler-context.ts +83 -41
- package/src/router/intercept-resolution.ts +25 -23
- package/src/router/lazy-includes.ts +19 -53
- package/src/router/loader-resolution.ts +213 -30
- package/src/router/logging.ts +5 -8
- package/src/router/manifest.ts +49 -45
- package/src/router/match-api.ts +120 -204
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +27 -6
- package/src/router/match-middleware/cache-lookup.ts +205 -249
- package/src/router/match-middleware/cache-store.ts +45 -32
- package/src/router/match-middleware/intercept-resolution.ts +8 -28
- package/src/router/match-middleware/segment-resolution.ts +52 -18
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +104 -40
- package/src/router/metrics.ts +5 -34
- package/src/router/middleware-types.ts +13 -142
- package/src/router/middleware.ts +173 -143
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +109 -63
- package/src/router/prerender-match.ts +190 -54
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +63 -55
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +6 -28
- package/src/router/router-interfaces.ts +100 -35
- package/src/router/router-options.ts +91 -11
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +242 -75
- package/src/router/segment-resolution/helpers.ts +63 -24
- package/src/router/segment-resolution/loader-cache.ts +41 -37
- package/src/router/segment-resolution/revalidation.ts +456 -372
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/segment-resolution.ts +4 -1
- package/src/router/segment-wrappers.ts +2 -3
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +0 -20
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/trie-matching.ts +91 -46
- package/src/router/types.ts +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +134 -43
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +492 -383
- package/src/rsc/helpers.ts +162 -46
- package/src/rsc/index.ts +1 -1
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +23 -3
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +30 -3
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +90 -63
- package/src/rsc/rsc-rendering.ts +56 -54
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +74 -67
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/types.ts +25 -6
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +4 -20
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +134 -0
- package/src/segment-system.tsx +272 -129
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +309 -61
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +26 -24
- package/src/server/loader-registry.ts +10 -28
- package/src/server/request-context.ts +338 -126
- package/src/ssr/index.tsx +23 -15
- package/src/static-handler.ts +27 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +618 -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 +232 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +99 -0
- package/src/testing/internal/context.ts +348 -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 +330 -0
- package/src/testing/render-route.tsx +566 -0
- package/src/testing/run-loader.ts +378 -0
- package/src/testing/run-middleware.ts +205 -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 +0 -52
- package/src/theme/ThemeScript.tsx +0 -6
- package/src/theme/constants.ts +0 -12
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +0 -14
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +17 -8
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +233 -81
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +44 -15
- package/src/types/request-scope.ts +107 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +19 -7
- package/src/types/segments.ts +37 -14
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +58 -11
- package/src/urls/path-helper.ts +57 -111
- package/src/urls/pattern-types.ts +48 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -18
- package/src/use-loader.tsx +346 -89
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +36 -38
- package/src/vite/discovery/discover-routers.ts +130 -85
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +192 -99
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- package/src/vite/discovery/state.ts +51 -6
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +8 -0
- package/src/vite/plugin-types.ts +187 -69
- package/src/vite/plugins/cjs-to-esm.ts +8 -18
- package/src/vite/plugins/client-ref-dedup.ts +16 -11
- package/src/vite/plugins/client-ref-hashing.ts +28 -15
- 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/plugins/expose-action-id.ts +49 -98
- package/src/vite/plugins/expose-id-utils.ts +11 -50
- package/src/vite/plugins/expose-ids/export-analysis.ts +76 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +10 -48
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -16
- package/src/vite/plugins/expose-internal-ids.ts +554 -317
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +89 -27
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/vercel-output.ts +258 -0
- package/src/vite/plugins/version-injector.ts +21 -25
- package/src/vite/plugins/version-plugin.ts +41 -20
- package/src/vite/plugins/virtual-entries.ts +2 -17
- package/src/vite/rango.ts +257 -289
- package/src/vite/router-discovery.ts +930 -140
- package/src/vite/utils/ast-handler-extract.ts +15 -31
- package/src/vite/utils/banner.ts +4 -4
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +20 -52
- package/src/vite/utils/prerender-utils.ts +27 -29
- package/src/vite/utils/shared-utils.ts +92 -42
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Router Error Handling Utilities
|
|
3
3
|
*
|
|
4
|
-
* Error boundary and not-found boundary handling for
|
|
4
|
+
* Error boundary and not-found boundary handling for Rango.
|
|
5
5
|
* Also includes the shared invokeOnError utility for error callback invocation.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -117,16 +117,10 @@ export function findNearestErrorBoundary(
|
|
|
117
117
|
let current: EntryData | null = entry;
|
|
118
118
|
|
|
119
119
|
while (current) {
|
|
120
|
-
// Check if this entry has error boundaries defined
|
|
121
120
|
if (current.errorBoundary && current.errorBoundary.length > 0) {
|
|
122
|
-
// Return the last error boundary (most recently defined takes precedence)
|
|
123
121
|
return current.errorBoundary[current.errorBoundary.length - 1];
|
|
124
122
|
}
|
|
125
123
|
|
|
126
|
-
// Check orphan layouts for error boundaries
|
|
127
|
-
// Orphan layouts are siblings that render alongside the main route chain
|
|
128
|
-
// They can define error boundaries that catch errors from routes in the same route group
|
|
129
|
-
// Check from first to last (first sibling takes precedence as the "outer" wrapper)
|
|
130
124
|
if (current.layout && current.layout.length > 0) {
|
|
131
125
|
for (const orphan of current.layout) {
|
|
132
126
|
if (orphan.errorBoundary && orphan.errorBoundary.length > 0) {
|
|
@@ -153,11 +147,21 @@ export function findNearestNotFoundBoundary(
|
|
|
153
147
|
let current: EntryData | null = entry;
|
|
154
148
|
|
|
155
149
|
while (current) {
|
|
156
|
-
// Check if this entry has notFound boundaries defined
|
|
157
150
|
if (current.notFoundBoundary && current.notFoundBoundary.length > 0) {
|
|
158
|
-
// Return the last notFound boundary (most recently defined takes precedence)
|
|
159
151
|
return current.notFoundBoundary[current.notFoundBoundary.length - 1];
|
|
160
152
|
}
|
|
153
|
+
|
|
154
|
+
// Check orphan layouts mirroring findNearestErrorBoundary: notFoundBoundary
|
|
155
|
+
// attaches identically (onto parent.notFoundBoundary), and an orphan layout
|
|
156
|
+
// (parent=null) is reachable only via this scan. First sibling is "outer".
|
|
157
|
+
if (current.layout && current.layout.length > 0) {
|
|
158
|
+
for (const orphan of current.layout) {
|
|
159
|
+
if (orphan.notFoundBoundary && orphan.notFoundBoundary.length > 0) {
|
|
160
|
+
return orphan.notFoundBoundary[orphan.notFoundBoundary.length - 1];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
161
165
|
current = current.parent;
|
|
162
166
|
}
|
|
163
167
|
|
|
@@ -207,22 +211,17 @@ export function createErrorSegment(
|
|
|
207
211
|
entry: EntryData,
|
|
208
212
|
params: Record<string, string>,
|
|
209
213
|
): ResolvedSegment {
|
|
210
|
-
// Determine the component to render
|
|
211
214
|
let component: ReactNode;
|
|
212
215
|
|
|
213
216
|
if (typeof fallback === "function") {
|
|
214
|
-
// ErrorBoundaryHandler - call with error info
|
|
215
217
|
const props: ErrorBoundaryFallbackProps = {
|
|
216
218
|
error: errorInfo,
|
|
217
219
|
};
|
|
218
220
|
component = fallback(props);
|
|
219
221
|
} else {
|
|
220
|
-
// Static ReactNode fallback
|
|
221
222
|
component = fallback;
|
|
222
223
|
}
|
|
223
224
|
|
|
224
|
-
// Error segment uses the same ID as the layout that has the error boundary
|
|
225
|
-
// The error boundary content replaces the layout's outlet content
|
|
226
225
|
return {
|
|
227
226
|
id: entry.shortCode,
|
|
228
227
|
namespace: entry.id,
|
|
@@ -261,17 +260,14 @@ export function createNotFoundSegment(
|
|
|
261
260
|
entry: EntryData,
|
|
262
261
|
params: Record<string, string>,
|
|
263
262
|
): ResolvedSegment {
|
|
264
|
-
// Determine the component to render
|
|
265
263
|
let component: ReactNode;
|
|
266
264
|
|
|
267
265
|
if (typeof fallback === "function") {
|
|
268
|
-
// NotFoundBoundaryHandler - call with props
|
|
269
266
|
const props: NotFoundBoundaryFallbackProps = {
|
|
270
267
|
notFound: notFoundInfo,
|
|
271
268
|
};
|
|
272
269
|
component = fallback(props);
|
|
273
270
|
} else {
|
|
274
|
-
// Static ReactNode fallback
|
|
275
271
|
component = fallback;
|
|
276
272
|
}
|
|
277
273
|
|
package/src/router/find-match.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { tryTrieMatch } from "./trie-matching.js";
|
|
2
|
-
import {
|
|
2
|
+
import { getRouterTrie } from "../route-map-builder.js";
|
|
3
3
|
import {
|
|
4
4
|
findMatch as findRouteMatch,
|
|
5
5
|
isLazyEvaluationNeeded,
|
|
@@ -8,6 +8,16 @@ import {
|
|
|
8
8
|
import type { MetricsStore } from "../server/context";
|
|
9
9
|
import type { RouteEntry } from "../types";
|
|
10
10
|
|
|
11
|
+
// The single-entry cache is module-lifetime, keyed only on pathname, so the same
|
|
12
|
+
// result object is handed to every same-pathname request. ctx.params aliases
|
|
13
|
+
// this object, so handlers mutating it would corrupt the cache for later requests.
|
|
14
|
+
// Clone params; entry/flags are read-only and shared safely.
|
|
15
|
+
function cloneMatchResult<TEnv>(
|
|
16
|
+
r: RouteMatchResult<TEnv> | null,
|
|
17
|
+
): RouteMatchResult<TEnv> | null {
|
|
18
|
+
return r ? { ...r, params: { ...r.params } } : null;
|
|
19
|
+
}
|
|
20
|
+
|
|
11
21
|
export interface FindMatchDeps<TEnv = any> {
|
|
12
22
|
routesEntries: RouteEntry<TEnv>[];
|
|
13
23
|
evaluateLazyEntry: (entry: RouteEntry<TEnv>) => void;
|
|
@@ -27,20 +37,14 @@ export function createFindMatch<TEnv = any>(
|
|
|
27
37
|
let lastFindMatchPathname: string | null = null;
|
|
28
38
|
let lastFindMatchResult: RouteMatchResult<TEnv> | null = null;
|
|
29
39
|
|
|
30
|
-
// Wrapper for findMatch that uses routesEntries
|
|
31
|
-
// Handles lazy evaluation by evaluating lazy entries on first match.
|
|
32
|
-
// Phase 1: try O(path_length) trie match.
|
|
33
|
-
// Phase 2: fall back to regex iteration.
|
|
34
40
|
return function findMatch(
|
|
35
41
|
pathname: string,
|
|
36
42
|
ms?: MetricsStore,
|
|
37
43
|
): RouteMatchResult<TEnv> | null {
|
|
38
|
-
// Return cached result if same pathname (avoids double-match per request)
|
|
39
44
|
if (lastFindMatchPathname === pathname) {
|
|
40
|
-
return lastFindMatchResult;
|
|
45
|
+
return cloneMatchResult(lastFindMatchResult);
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
// Helper to push sub-metrics
|
|
44
48
|
const pushMetric = ms
|
|
45
49
|
? (label: string, start: number) => {
|
|
46
50
|
ms.metrics.push({
|
|
@@ -51,15 +55,15 @@ export function createFindMatch<TEnv = any>(
|
|
|
51
55
|
}
|
|
52
56
|
: undefined;
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const routeTrie = getRouterTrie(deps.routerId) ?? getRouteTrie();
|
|
58
|
+
const routeTrie = getRouterTrie(deps.routerId);
|
|
59
|
+
let trieMatched = false;
|
|
57
60
|
if (routeTrie) {
|
|
58
61
|
const trieStart = performance.now();
|
|
59
62
|
const trieResult = tryTrieMatch(routeTrie, pathname);
|
|
60
63
|
pushMetric?.("match:trie", trieStart);
|
|
61
64
|
|
|
62
65
|
if (trieResult) {
|
|
66
|
+
trieMatched = true;
|
|
63
67
|
// Find the RouteEntry that contains this route.
|
|
64
68
|
// Multiple entries can share the same staticPrefix (e.g., several
|
|
65
69
|
// include("/", patterns) calls all produce staticPrefix=""). Evaluate
|
|
@@ -81,12 +85,8 @@ export function createFindMatch<TEnv = any>(
|
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
// If no entry had the route in its routes map, use the first matching
|
|
85
|
-
// entry as fallback (handles main entry with inline routes not yet
|
|
86
|
-
// reflected in its routes object).
|
|
87
88
|
if (!entry) entry = fallbackEntry;
|
|
88
89
|
|
|
89
|
-
// If entry not found (nested include not yet discovered), evaluate parent
|
|
90
90
|
if (!entry) {
|
|
91
91
|
const parent = deps.routesEntries.find(
|
|
92
92
|
(e) =>
|
|
@@ -110,9 +110,7 @@ export function createFindMatch<TEnv = any>(
|
|
|
110
110
|
entry,
|
|
111
111
|
routeKey: trieResult.routeKey,
|
|
112
112
|
params: trieResult.params,
|
|
113
|
-
optionalParams: new Set(trieResult.optionalParams || []),
|
|
114
113
|
redirectTo: trieResult.redirectTo,
|
|
115
|
-
ancestry: trieResult.ancestry,
|
|
116
114
|
...(trieResult.pr ? { pr: true } : {}),
|
|
117
115
|
...(trieResult.pt ? { pt: true } : {}),
|
|
118
116
|
...(trieResult.responseType
|
|
@@ -123,17 +121,14 @@ export function createFindMatch<TEnv = any>(
|
|
|
123
121
|
: {}),
|
|
124
122
|
...(trieResult.rscFirst ? { rscFirst: true } : {}),
|
|
125
123
|
};
|
|
126
|
-
return lastFindMatchResult;
|
|
124
|
+
return cloneMatchResult(lastFindMatchResult);
|
|
127
125
|
}
|
|
128
126
|
}
|
|
129
127
|
}
|
|
130
128
|
|
|
131
|
-
// Phase 2: Fall back to existing matching (regex iteration)
|
|
132
129
|
const regexStart = performance.now();
|
|
133
130
|
let result = findRouteMatch(pathname, deps.routesEntries);
|
|
134
131
|
|
|
135
|
-
// If we hit a lazy entry that needs evaluation, evaluate and retry.
|
|
136
|
-
// Cap iterations to prevent infinite loops from pathological nesting.
|
|
137
132
|
const MAX_LAZY_ITERATIONS = 100;
|
|
138
133
|
let iterations = 0;
|
|
139
134
|
while (isLazyEvaluationNeeded(result)) {
|
|
@@ -151,8 +146,36 @@ export function createFindMatch<TEnv = any>(
|
|
|
151
146
|
}
|
|
152
147
|
pushMetric?.("match:regex-fallback", regexStart);
|
|
153
148
|
|
|
149
|
+
// The trie is the single source of truth and is built before findMatch in
|
|
150
|
+
// both dev (handler rebuild) and production (ensureRouterManifest). If the
|
|
151
|
+
// trie was present yet the regex fallback resolved a real match, the trie
|
|
152
|
+
// has a gap (e.g. a route shape it cannot represent) and dev/prod could
|
|
153
|
+
// diverge if the trie were ever absent. Surface it in dev; folded out in
|
|
154
|
+
// production builds.
|
|
155
|
+
//
|
|
156
|
+
// Suppress when the trie DID match (`trieMatched`): that path falls through
|
|
157
|
+
// to the regex fallback only on the first request to a not-yet-spliced lazy
|
|
158
|
+
// entry (e.g. a 2+-level nested include whose deeper parent has not been
|
|
159
|
+
// evaluated). The trie knew the route; runtime lazy discovery simply lagged.
|
|
160
|
+
// That is the supported lazy-include flow, not a trie gap, so warning on it
|
|
161
|
+
// is a false positive (it manufactures bug reports and erodes the signal).
|
|
162
|
+
if (
|
|
163
|
+
process.env.NODE_ENV !== "production" &&
|
|
164
|
+
routeTrie &&
|
|
165
|
+
!trieMatched &&
|
|
166
|
+
result &&
|
|
167
|
+
!isLazyEvaluationNeeded(result)
|
|
168
|
+
) {
|
|
169
|
+
console.warn(
|
|
170
|
+
`[@rangojs/router] Route "${pathname}" resolved via the regex fallback ` +
|
|
171
|
+
`even though the route trie was present. The trie should be the single ` +
|
|
172
|
+
`matching source of truth; this indicates a trie gap. Please report this ` +
|
|
173
|
+
`with your route configuration.`,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
154
177
|
lastFindMatchPathname = pathname;
|
|
155
178
|
lastFindMatchResult = result;
|
|
156
|
-
return result;
|
|
179
|
+
return cloneMatchResult(result);
|
|
157
180
|
};
|
|
158
181
|
}
|
|
@@ -8,10 +8,18 @@ import type { HandlerContext, InternalHandlerContext } from "../types";
|
|
|
8
8
|
import { _getRequestContext } from "../server/request-context.js";
|
|
9
9
|
import { getSearchSchema, isRouteRootScoped } from "../route-map-builder.js";
|
|
10
10
|
import { parseSearchParams, serializeSearchParams } from "../search-params.js";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
contextGet,
|
|
13
|
+
contextSet,
|
|
14
|
+
isNonCacheable,
|
|
15
|
+
type ContextSetOptions,
|
|
16
|
+
} from "../context-var.js";
|
|
17
|
+
import { isInsideCacheScope } from "../server/context.js";
|
|
12
18
|
import { NOCACHE_SYMBOL, assertNotInsideCacheExec } from "../cache/taint.js";
|
|
13
19
|
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
14
20
|
import { PRERENDER_PASSTHROUGH } from "../prerender.js";
|
|
21
|
+
import { substitutePatternParams } from "./substitute-pattern-params.js";
|
|
22
|
+
import { fireAndForgetWaitUntil } from "../types/request-scope.js";
|
|
15
23
|
|
|
16
24
|
/**
|
|
17
25
|
* Strip internal _rsc* query params from a URL.
|
|
@@ -108,9 +116,9 @@ function createPrerenderPassthroughFn(
|
|
|
108
116
|
}
|
|
109
117
|
if (!isPassthroughRoute) {
|
|
110
118
|
throw new Error(
|
|
111
|
-
"ctx.passthrough() is only available on routes
|
|
112
|
-
"
|
|
113
|
-
"
|
|
119
|
+
"ctx.passthrough() is only available on routes wrapped with " +
|
|
120
|
+
"Passthrough(). Remove the passthrough() call or wrap the " +
|
|
121
|
+
"Prerender definition with Passthrough(prerenderDef, liveHandler).",
|
|
114
122
|
);
|
|
115
123
|
}
|
|
116
124
|
return PRERENDER_PASSTHROUGH;
|
|
@@ -152,26 +160,14 @@ export function createReverseFunction(
|
|
|
152
160
|
);
|
|
153
161
|
}
|
|
154
162
|
|
|
155
|
-
let result = pattern;
|
|
156
|
-
|
|
157
163
|
// Merge current request params as defaults, explicit params override
|
|
158
164
|
const effectiveParams = currentParams
|
|
159
165
|
? { ...currentParams, ...hrefParams }
|
|
160
166
|
: hrefParams;
|
|
161
167
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?\??/g,
|
|
166
|
-
(_, key) => {
|
|
167
|
-
const value = effectiveParams[key];
|
|
168
|
-
if (value === undefined) {
|
|
169
|
-
throw new Error(`Missing param "${key}" for route "${name}"`);
|
|
170
|
-
}
|
|
171
|
-
return encodeURIComponent(value);
|
|
172
|
-
},
|
|
173
|
-
);
|
|
174
|
-
}
|
|
168
|
+
let result = effectiveParams
|
|
169
|
+
? substitutePatternParams(pattern, effectiveParams, name)
|
|
170
|
+
: pattern;
|
|
175
171
|
|
|
176
172
|
// Append search params as query string
|
|
177
173
|
if (search) {
|
|
@@ -201,7 +197,7 @@ export function createHandlerContext<TEnv>(
|
|
|
201
197
|
// Get variables from request context - this is the unified context
|
|
202
198
|
// shared between middleware and route handlers
|
|
203
199
|
const requestContext = _getRequestContext();
|
|
204
|
-
const variables: any = requestContext?.
|
|
200
|
+
const variables: any = requestContext?._variables ?? {};
|
|
205
201
|
|
|
206
202
|
// If route has a search schema, parse URLSearchParams into typed object
|
|
207
203
|
const searchSchema = routeName ? getSearchSchema(routeName) : undefined;
|
|
@@ -213,15 +209,25 @@ export function createHandlerContext<TEnv>(
|
|
|
213
209
|
const stubResponse =
|
|
214
210
|
requestContext?.res ?? new Response(null, { status: 200 });
|
|
215
211
|
|
|
216
|
-
// Guard mutating Headers methods so they throw inside "use cache"
|
|
212
|
+
// Guard mutating Headers methods so they throw inside "use cache" or cache() scope.
|
|
213
|
+
// Uses lazy `ctx` reference (assigned below) — only the specific handler ctx
|
|
214
|
+
// is stamped by cache-runtime, not the shared request context.
|
|
217
215
|
const MUTATING_HEADERS_METHODS = new Set(["set", "append", "delete"]);
|
|
216
|
+
let ctx: InternalHandlerContext<any, TEnv>;
|
|
218
217
|
const guardedHeaders = new Proxy(stubResponse.headers, {
|
|
219
218
|
get(target, prop, receiver) {
|
|
220
219
|
const value = Reflect.get(target, prop, receiver);
|
|
221
220
|
if (typeof value === "function") {
|
|
222
221
|
if (MUTATING_HEADERS_METHODS.has(prop as string)) {
|
|
223
222
|
return (...args: any[]) => {
|
|
224
|
-
assertNotInsideCacheExec(
|
|
223
|
+
assertNotInsideCacheExec(ctx, "headers");
|
|
224
|
+
if (isInsideCacheScope()) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
`ctx.headers.${String(prop)}() cannot be called inside a cache() boundary. ` +
|
|
227
|
+
`On cache hit the handler is skipped, so this side effect would be lost. ` +
|
|
228
|
+
`Move header mutations to a middleware or layout outside the cache() scope.`,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
225
231
|
return value.apply(target, args);
|
|
226
232
|
};
|
|
227
233
|
}
|
|
@@ -231,24 +237,39 @@ export function createHandlerContext<TEnv>(
|
|
|
231
237
|
},
|
|
232
238
|
});
|
|
233
239
|
|
|
234
|
-
|
|
240
|
+
ctx = {
|
|
235
241
|
params,
|
|
236
242
|
build: false,
|
|
243
|
+
dev: false,
|
|
237
244
|
request,
|
|
238
245
|
searchParams,
|
|
239
246
|
search: searchSchema ? resolvedSearchParams : {},
|
|
240
247
|
pathname,
|
|
241
248
|
url,
|
|
242
|
-
originalUrl: new URL(request.url),
|
|
249
|
+
originalUrl: requestContext?.originalUrl ?? new URL(request.url),
|
|
243
250
|
env: bindings,
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
waitUntil: requestContext
|
|
252
|
+
? requestContext.waitUntil.bind(requestContext)
|
|
253
|
+
: fireAndForgetWaitUntil,
|
|
254
|
+
executionContext: requestContext?.executionContext,
|
|
255
|
+
_variables: variables,
|
|
256
|
+
get: ((keyOrVar: any) => {
|
|
257
|
+
// Read-time guard: non-cacheable var inside cache() → throw.
|
|
258
|
+
// Works for both ContextVar tokens and string keys.
|
|
259
|
+
if (isNonCacheable(variables, keyOrVar) && isInsideCacheScope()) {
|
|
260
|
+
throw new Error(
|
|
261
|
+
`ctx.get() for a non-cacheable variable cannot be called inside a cache() boundary. ` +
|
|
262
|
+
`The variable was created with { cache: false } or set with { cache: false }, ` +
|
|
263
|
+
`and its value would be stale on cache hit. Move the read outside the cached scope.`,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
return contextGet(variables, keyOrVar);
|
|
267
|
+
}) as HandlerContext<any, TEnv>["get"],
|
|
268
|
+
set: ((keyOrVar: any, value: any, options?: ContextSetOptions) => {
|
|
269
|
+
assertNotInsideCacheExec(ctx, "set");
|
|
270
|
+
// Write is dumb: store value + non-cacheable metadata.
|
|
271
|
+
// Enforcement happens at read time via ctx.get().
|
|
272
|
+
contextSet(variables, keyOrVar, value, options);
|
|
252
273
|
}) as HandlerContext<any, TEnv>["set"],
|
|
253
274
|
res: stubResponse, // Stub response for setting headers
|
|
254
275
|
headers: guardedHeaders, // Guarded shorthand for res.headers
|
|
@@ -294,7 +315,7 @@ export function createHandlerContext<TEnv>(
|
|
|
294
315
|
*
|
|
295
316
|
* Returns an InternalHandlerContext where params, pathname, url, searchParams,
|
|
296
317
|
* search, reverse, and use(handle) work. Request-time properties
|
|
297
|
-
* (request, env, headers, cookies,
|
|
318
|
+
* (request, env, headers, cookies, get, set, res) throw with a clear error.
|
|
298
319
|
*/
|
|
299
320
|
export function createPrerenderContext<TEnv>(
|
|
300
321
|
params: Record<string, string>,
|
|
@@ -303,6 +324,8 @@ export function createPrerenderContext<TEnv>(
|
|
|
303
324
|
routeName?: string,
|
|
304
325
|
buildVars?: Record<string, any>,
|
|
305
326
|
isPassthroughRoute?: boolean,
|
|
327
|
+
buildEnv?: TEnv,
|
|
328
|
+
devMode?: boolean,
|
|
306
329
|
): InternalHandlerContext<any, TEnv> {
|
|
307
330
|
const syntheticUrl = new URL(`http://prerender${pathname}`);
|
|
308
331
|
const variables = buildVars ?? {};
|
|
@@ -317,6 +340,7 @@ export function createPrerenderContext<TEnv>(
|
|
|
317
340
|
return {
|
|
318
341
|
params,
|
|
319
342
|
build: true,
|
|
343
|
+
dev: devMode ?? false,
|
|
320
344
|
get request(): Request {
|
|
321
345
|
return throwUnavailable("request");
|
|
322
346
|
},
|
|
@@ -326,11 +350,19 @@ export function createPrerenderContext<TEnv>(
|
|
|
326
350
|
url: syntheticUrl,
|
|
327
351
|
originalUrl: syntheticUrl,
|
|
328
352
|
get env(): TEnv {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
353
|
+
if (buildEnv !== undefined) return buildEnv;
|
|
354
|
+
throw new Error(
|
|
355
|
+
"ctx.env is not available during pre-rendering. " +
|
|
356
|
+
"Configure buildEnv in your rango() plugin options to enable build-time env access.",
|
|
357
|
+
);
|
|
333
358
|
},
|
|
359
|
+
// Build-time prerender has no live request. waitUntil is a true no-op
|
|
360
|
+
// (running fn() here would fire side effects during build, which is
|
|
361
|
+
// incorrect — these are meant to outlive the live response).
|
|
362
|
+
// executionContext is absent for the same reason.
|
|
363
|
+
waitUntil: () => {},
|
|
364
|
+
executionContext: undefined,
|
|
365
|
+
_variables: variables,
|
|
334
366
|
get: ((keyOrVar: any) => contextGet(variables, keyOrVar)) as any,
|
|
335
367
|
set: ((keyOrVar: any, value: any) => {
|
|
336
368
|
contextSet(variables, keyOrVar, value);
|
|
@@ -376,6 +408,8 @@ export function createPrerenderContext<TEnv>(
|
|
|
376
408
|
export function createStaticContext<TEnv>(
|
|
377
409
|
routeMap: Record<string, string>,
|
|
378
410
|
routeName?: string,
|
|
411
|
+
buildEnv?: TEnv,
|
|
412
|
+
devMode?: boolean,
|
|
379
413
|
): InternalHandlerContext<any, TEnv> {
|
|
380
414
|
const variables: Record<string, any> = {};
|
|
381
415
|
|
|
@@ -391,6 +425,7 @@ export function createStaticContext<TEnv>(
|
|
|
391
425
|
return throwUnavailable("params");
|
|
392
426
|
},
|
|
393
427
|
build: true,
|
|
428
|
+
dev: devMode ?? false,
|
|
394
429
|
get request(): Request {
|
|
395
430
|
return throwUnavailable("request");
|
|
396
431
|
},
|
|
@@ -410,11 +445,18 @@ export function createStaticContext<TEnv>(
|
|
|
410
445
|
return throwUnavailable("originalUrl");
|
|
411
446
|
},
|
|
412
447
|
get env(): TEnv {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
448
|
+
if (buildEnv !== undefined) return buildEnv;
|
|
449
|
+
throw new Error(
|
|
450
|
+
"ctx.env is not available in Static() handlers. " +
|
|
451
|
+
"Configure buildEnv in your rango() plugin options to enable build-time env access.",
|
|
452
|
+
);
|
|
417
453
|
},
|
|
454
|
+
// Static() handlers have no live request. waitUntil is a true no-op
|
|
455
|
+
// (running fn() here would fire side effects during build, which is
|
|
456
|
+
// incorrect). executionContext is absent for the same reason.
|
|
457
|
+
waitUntil: () => {},
|
|
458
|
+
executionContext: undefined,
|
|
459
|
+
_variables: variables,
|
|
418
460
|
get: ((keyOrVar: any) => contextGet(variables, keyOrVar)) as any,
|
|
419
461
|
set: ((keyOrVar: any, value: any) => {
|
|
420
462
|
contextSet(variables, keyOrVar, value);
|
|
@@ -11,15 +11,23 @@ import type {
|
|
|
11
11
|
InterceptEntry,
|
|
12
12
|
InterceptSelectorContext,
|
|
13
13
|
} from "../server/context";
|
|
14
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
HandlerContext,
|
|
16
|
+
InternalHandlerContext,
|
|
17
|
+
ResolvedSegment,
|
|
18
|
+
} from "../types";
|
|
15
19
|
import { evaluateRevalidation } from "./revalidation.js";
|
|
16
20
|
import { getRequestContext } from "../server/request-context.js";
|
|
17
21
|
import { executeInterceptMiddleware } from "./middleware.js";
|
|
18
22
|
import { createReverseFunction } from "./handler-context.js";
|
|
19
23
|
import { getGlobalRouteMap } from "../route-map-builder.js";
|
|
20
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
handleHandlerResult,
|
|
26
|
+
warnOnStreamedResponse,
|
|
27
|
+
} from "./segment-resolution.js";
|
|
21
28
|
import type { SegmentResolutionDeps } from "./types.js";
|
|
22
29
|
import { debugLog } from "./logging.js";
|
|
30
|
+
import { runInsideLoaderScope } from "../server/context.js";
|
|
23
31
|
|
|
24
32
|
/**
|
|
25
33
|
* Check if an intercept's when conditions are satisfied.
|
|
@@ -61,28 +69,14 @@ export function findInterceptForRoute(
|
|
|
61
69
|
let current: EntryData | null = fromEntry;
|
|
62
70
|
|
|
63
71
|
while (current) {
|
|
64
|
-
|
|
65
|
-
|
|
72
|
+
// current first, then its sibling layouts — same order as before.
|
|
73
|
+
for (const source of [current, ...current.layout]) {
|
|
74
|
+
for (const intercept of source.intercept) {
|
|
66
75
|
if (
|
|
67
76
|
intercept.routeName === targetRouteKey &&
|
|
68
77
|
evaluateInterceptWhen(intercept, selectorContext, isAction)
|
|
69
78
|
) {
|
|
70
|
-
return { intercept, entry:
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (current.layout && current.layout.length > 0) {
|
|
76
|
-
for (const siblingLayout of current.layout) {
|
|
77
|
-
if (siblingLayout.intercept && siblingLayout.intercept.length > 0) {
|
|
78
|
-
for (const intercept of siblingLayout.intercept) {
|
|
79
|
-
if (
|
|
80
|
-
intercept.routeName === targetRouteKey &&
|
|
81
|
-
evaluateInterceptWhen(intercept, selectorContext, isAction)
|
|
82
|
-
) {
|
|
83
|
-
return { intercept, entry: siblingLayout };
|
|
84
|
-
}
|
|
85
|
-
}
|
|
79
|
+
return { intercept, entry: source };
|
|
86
80
|
}
|
|
87
81
|
}
|
|
88
82
|
}
|
|
@@ -133,7 +127,7 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
133
127
|
context.request,
|
|
134
128
|
context.env,
|
|
135
129
|
params,
|
|
136
|
-
context
|
|
130
|
+
(context as InternalHandlerContext<any, TEnv>)._variables,
|
|
137
131
|
requestCtx.res,
|
|
138
132
|
createReverseFunction(getGlobalRouteMap()),
|
|
139
133
|
);
|
|
@@ -188,6 +182,7 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
188
182
|
context,
|
|
189
183
|
actionContext,
|
|
190
184
|
stale,
|
|
185
|
+
traceSource: "intercept-loader",
|
|
191
186
|
});
|
|
192
187
|
|
|
193
188
|
if (!shouldRevalidate) {
|
|
@@ -206,7 +201,7 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
206
201
|
loaderIds.push(loader.$$id);
|
|
207
202
|
loaderPromises.push(
|
|
208
203
|
deps.wrapLoaderPromise(
|
|
209
|
-
context.use(loader),
|
|
204
|
+
runInsideLoaderScope(() => context.use(loader)),
|
|
210
205
|
parentEntry,
|
|
211
206
|
segmentId,
|
|
212
207
|
context.pathname,
|
|
@@ -236,6 +231,12 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
236
231
|
let loaderDataPromise: Promise<any[]> | any[] | undefined;
|
|
237
232
|
|
|
238
233
|
if (interceptEntry.loading && loaderPromises.length > 0) {
|
|
234
|
+
if (handlerResult instanceof Promise) {
|
|
235
|
+
warnOnStreamedResponse(
|
|
236
|
+
handlerResult,
|
|
237
|
+
`intercept ${interceptEntry.slotName}`,
|
|
238
|
+
);
|
|
239
|
+
}
|
|
239
240
|
component =
|
|
240
241
|
handlerResult instanceof Promise
|
|
241
242
|
? handlerResult
|
|
@@ -355,6 +356,7 @@ export async function resolveInterceptLoadersOnly<TEnv>(
|
|
|
355
356
|
context,
|
|
356
357
|
actionContext,
|
|
357
358
|
stale,
|
|
359
|
+
traceSource: "intercept-loader",
|
|
358
360
|
});
|
|
359
361
|
|
|
360
362
|
if (!shouldRevalidate) {
|
|
@@ -372,7 +374,7 @@ export async function resolveInterceptLoadersOnly<TEnv>(
|
|
|
372
374
|
loaderIds.push(loader.$$id);
|
|
373
375
|
loaderPromises.push(
|
|
374
376
|
deps.wrapLoaderPromise(
|
|
375
|
-
context.use(loader),
|
|
377
|
+
runInsideLoaderScope(() => context.use(loader)),
|
|
376
378
|
parentEntry,
|
|
377
379
|
segmentId,
|
|
378
380
|
context.pathname,
|