@rangojs/router 0.0.0-experimental.9c9afef3 → 0.0.0-experimental.a014d2b7
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 +8 -0
- package/README.md +245 -49
- package/dist/bin/rango.js +440 -133
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3373 -1176
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +68 -14
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +64 -2
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +224 -32
- package/skills/caching/SKILL.md +279 -17
- package/skills/composability/SKILL.md +27 -3
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +250 -30
- package/skills/host-router/SKILL.md +83 -23
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +87 -18
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +235 -9
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +771 -0
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +77 -7
- package/skills/prerender/SKILL.md +172 -125
- package/skills/rango/SKILL.md +251 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +123 -48
- package/skills/route/SKILL.md +70 -5
- package/skills/router-setup/SKILL.md +65 -8
- package/skills/scripts/SKILL.md +179 -0
- 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 +130 -0
- 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 +129 -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 +84 -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/typesafety/SKILL.md +322 -29
- package/skills/use-cache/SKILL.md +57 -14
- 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 +1 -66
- 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/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +192 -150
- 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/navigation-bridge.ts +131 -30
- package/src/browser/navigation-client.ts +186 -100
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +157 -74
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +165 -112
- package/src/browser/prefetch/cache.ts +205 -62
- package/src/browser/prefetch/fetch.ts +347 -39
- package/src/browser/prefetch/queue.ts +42 -8
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +102 -15
- package/src/browser/react/NavigationProvider.tsx +295 -119
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/deferred-handle-resolution.ts +75 -0
- package/src/browser/react/filter-segment-order.ts +66 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +178 -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-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +32 -7
- 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 +99 -8
- package/src/browser/rsc-router.tsx +114 -24
- package/src/browser/scroll-restoration.ts +37 -22
- package/src/browser/segment-reconciler.ts +36 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +222 -72
- package/src/browser/types.ts +102 -12
- 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 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +165 -36
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +16 -5
- package/src/build/route-types/include-resolution.ts +125 -24
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +22 -6
- package/src/build/route-types/router-processing.ts +260 -94
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +29 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +224 -41
- package/src/cache/cache-scope.ts +188 -82
- 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 +1989 -378
- 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 +6 -16
- package/src/cache/document-cache.ts +89 -21
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +10 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +44 -21
- package/src/client.tsx +119 -290
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +18 -6
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +30 -4
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +70 -22
- package/src/handles/MetaTags.tsx +62 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +37 -8
- package/src/handles/is-thenable.ts +19 -0
- package/src/handles/meta.ts +51 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +23 -52
- 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 +99 -13
- package/src/index.ts +139 -19
- package/src/internal-debug.ts +11 -10
- 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/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +37 -41
- package/src/prerender.ts +198 -82
- 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 +65 -15
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +19 -77
- package/src/route-definition/dsl-helpers.ts +461 -304
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +143 -69
- package/src/route-definition/index.ts +4 -2
- package/src/route-definition/redirect.ts +51 -10
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +37 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +164 -17
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +52 -31
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +48 -24
- package/src/router/lazy-includes.ts +15 -52
- package/src/router/loader-resolution.ts +268 -56
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +40 -42
- package/src/router/match-api.ts +124 -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 +40 -24
- package/src/router/match-middleware/cache-lookup.ts +170 -276
- package/src/router/match-middleware/cache-store.ts +64 -52
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +45 -14
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +87 -39
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -140
- package/src/router/middleware.ts +266 -169
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +132 -90
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +195 -56
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +3 -28
- package/src/router/router-interfaces.ts +115 -35
- package/src/router/router-options.ts +172 -15
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +162 -84
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +76 -39
- package/src/router/segment-resolution/revalidation.ts +351 -321
- 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 +56 -0
- package/src/router/segment-resolution.ts +5 -1
- package/src/router/segment-wrappers.ts +6 -5
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +161 -199
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +163 -59
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +157 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +655 -529
- package/src/rsc/helpers.ts +168 -46
- package/src/rsc/index.ts +2 -5
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +122 -31
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +131 -14
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +99 -189
- package/src/rsc/rsc-rendering.ts +109 -74
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +287 -115
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +29 -9
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +236 -202
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +224 -52
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +40 -38
- package/src/server/loader-registry.ts +38 -46
- package/src/server/request-context.ts +401 -173
- package/src/ssr/index.tsx +24 -16
- 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 +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 +183 -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 +581 -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 +20 -58
- package/src/theme/ThemeScript.tsx +7 -9
- package/src/theme/constants.ts +52 -13
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +22 -21
- 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 +125 -71
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +40 -11
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +12 -7
- package/src/types/segments.ts +136 -15
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +68 -18
- 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 -19
- 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 +214 -132
- 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 +57 -4
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +6 -0
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +178 -5
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- 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 +48 -95
- package/src/vite/plugins/expose-id-utils.ts +96 -51
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
- package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
- package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
- package/src/vite/plugins/expose-internal-ids.ts +553 -317
- package/src/vite/plugins/performance-tracks.ts +64 -170
- package/src/vite/plugins/refresh-cmd.ts +89 -27
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/version-injector.ts +40 -29
- package/src/vite/plugins/version-plugin.ts +37 -40
- package/src/vite/plugins/virtual-entries.ts +39 -25
- package/src/vite/rango.ts +118 -114
- package/src/vite/router-discovery.ts +941 -142
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +10 -15
- 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 +4 -59
- package/src/vite/utils/package-resolution.ts +20 -52
- package/src/vite/utils/prerender-utils.ts +81 -34
- package/src/vite/utils/shared-utils.ts +92 -42
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/debug-channel.ts +0 -93
- 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/network-error-thrower.tsx +0 -23
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -13,6 +13,25 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export type HandleData = Record<string, Record<string, unknown[]>>;
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Build a HandleData snapshot from a HandleStore using segment ordering.
|
|
18
|
+
* Reads data directly from the store for each segment in order.
|
|
19
|
+
*/
|
|
20
|
+
export function buildHandleSnapshot(
|
|
21
|
+
handleStore: HandleStore,
|
|
22
|
+
segmentOrder: string[],
|
|
23
|
+
): HandleData {
|
|
24
|
+
const data: HandleData = {};
|
|
25
|
+
for (const segmentId of segmentOrder) {
|
|
26
|
+
const segData = handleStore.getDataForSegment(segmentId);
|
|
27
|
+
for (const handleName in segData) {
|
|
28
|
+
if (!data[handleName]) data[handleName] = {};
|
|
29
|
+
data[handleName][segmentId] = segData[handleName];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
|
|
16
35
|
function createLateHandlePushError(
|
|
17
36
|
handleName: string,
|
|
18
37
|
segmentId: string,
|
|
@@ -26,10 +45,6 @@ function createLateHandlePushError(
|
|
|
26
45
|
return error;
|
|
27
46
|
}
|
|
28
47
|
|
|
29
|
-
/**
|
|
30
|
-
* Deep clone handle data to create a snapshot.
|
|
31
|
-
* @internal
|
|
32
|
-
*/
|
|
33
48
|
function cloneHandleData(data: HandleData): HandleData {
|
|
34
49
|
const clone: HandleData = {};
|
|
35
50
|
for (const handleName in data) {
|
|
@@ -159,8 +174,10 @@ export function createHandleStore(): HandleStore {
|
|
|
159
174
|
notifyDrain();
|
|
160
175
|
}
|
|
161
176
|
|
|
162
|
-
//
|
|
163
|
-
|
|
177
|
+
// Dirty flag for pending emissions and resolver for waiting consumer.
|
|
178
|
+
// stream() only ever yields the latest full state, so we track a single
|
|
179
|
+
// dirty bit and clone `data` once at yield time instead of per push.
|
|
180
|
+
let hasPendingEmission = false;
|
|
164
181
|
let emissionResolver: (() => void) | null = null;
|
|
165
182
|
let completed = false;
|
|
166
183
|
|
|
@@ -175,7 +192,7 @@ export function createHandleStore(): HandleStore {
|
|
|
175
192
|
|
|
176
193
|
// Wait for the next emission or completion
|
|
177
194
|
function waitForEmission(): Promise<void> {
|
|
178
|
-
if (
|
|
195
|
+
if (hasPendingEmission || completed) {
|
|
179
196
|
return Promise.resolve();
|
|
180
197
|
}
|
|
181
198
|
return new Promise((resolve) => {
|
|
@@ -186,11 +203,9 @@ export function createHandleStore(): HandleStore {
|
|
|
186
203
|
return {
|
|
187
204
|
track<T>(promise: Promise<T>): Promise<T> {
|
|
188
205
|
inflightCount++;
|
|
189
|
-
// Use .then(
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
// rejection on a new branch that nobody catches, which can crash
|
|
193
|
-
// the server process.
|
|
206
|
+
// Use .then() instead of .finally() to avoid creating an unhandled rejection
|
|
207
|
+
// branch when the promise rejects. .finally() re-throws on a new branch that
|
|
208
|
+
// can crash the process if not caught.
|
|
194
209
|
const onSettle = () => {
|
|
195
210
|
inflightCount--;
|
|
196
211
|
notifyDrain();
|
|
@@ -225,8 +240,8 @@ export function createHandleStore(): HandleStore {
|
|
|
225
240
|
}
|
|
226
241
|
data[handleName][segmentId].push(value);
|
|
227
242
|
|
|
228
|
-
//
|
|
229
|
-
|
|
243
|
+
// Mark dirty; the actual snapshot is cloned once at yield time.
|
|
244
|
+
hasPendingEmission = true;
|
|
230
245
|
signalEmission();
|
|
231
246
|
},
|
|
232
247
|
|
|
@@ -236,43 +251,31 @@ export function createHandleStore(): HandleStore {
|
|
|
236
251
|
},
|
|
237
252
|
|
|
238
253
|
async *stream(): AsyncGenerator<HandleData, void, unknown> {
|
|
239
|
-
// Auto-seal: stream() is called after all track() registrations.
|
|
240
254
|
sealInternal();
|
|
241
255
|
|
|
242
|
-
// Set up completion handler
|
|
243
256
|
this.settled.then(() => {
|
|
244
257
|
completed = true;
|
|
245
258
|
signalEmission();
|
|
246
259
|
});
|
|
247
260
|
|
|
248
|
-
//
|
|
249
|
-
// This allows multiple handles pushing in quick succession to be batched
|
|
261
|
+
// Batch rapid synchronous pushes with initial delay
|
|
250
262
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
251
263
|
|
|
252
|
-
// If we already have data, yield the accumulated state
|
|
253
264
|
if (Object.keys(data).length > 0) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const snapshot = cloneHandleData(data);
|
|
257
|
-
yield snapshot;
|
|
265
|
+
hasPendingEmission = false;
|
|
266
|
+
yield cloneHandleData(data);
|
|
258
267
|
}
|
|
259
268
|
|
|
260
|
-
// Continue streaming on each push
|
|
261
269
|
while (!completed) {
|
|
262
270
|
await waitForEmission();
|
|
263
271
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const latest = pendingEmissions[pendingEmissions.length - 1];
|
|
268
|
-
pendingEmissions = [];
|
|
269
|
-
yield latest;
|
|
272
|
+
if (hasPendingEmission) {
|
|
273
|
+
hasPendingEmission = false;
|
|
274
|
+
yield cloneHandleData(data);
|
|
270
275
|
}
|
|
271
276
|
}
|
|
272
277
|
|
|
273
|
-
|
|
274
|
-
// (handles that pushed after our last yield but before completion)
|
|
275
|
-
if (pendingEmissions.length > 0) {
|
|
278
|
+
if (hasPendingEmission) {
|
|
276
279
|
yield cloneHandleData(data);
|
|
277
280
|
}
|
|
278
281
|
},
|
|
@@ -295,13 +298,12 @@ export function createHandleStore(): HandleStore {
|
|
|
295
298
|
if (!data[handleName]) {
|
|
296
299
|
data[handleName] = {};
|
|
297
300
|
}
|
|
298
|
-
// Replace
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
+
// Replace (not append) to avoid handle bleeding between routes.
|
|
302
|
+
// Cached segment restoration should replace existing data for that
|
|
303
|
+
// segment, not accumulate on top of data from a different route.
|
|
301
304
|
data[handleName][segmentId] = [...segmentHandles[handleName]];
|
|
302
305
|
}
|
|
303
|
-
|
|
304
|
-
pendingEmissions.push(cloneHandleData(data));
|
|
306
|
+
hasPendingEmission = true;
|
|
305
307
|
signalEmission();
|
|
306
308
|
},
|
|
307
309
|
};
|
|
@@ -11,17 +11,10 @@ import {
|
|
|
11
11
|
type LoaderRegistryEntry,
|
|
12
12
|
} from "./fetchable-loader-store.js";
|
|
13
13
|
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// The source of truth is fetchableLoaderRegistry in loader.ts, which is populated
|
|
17
|
-
// when createLoader() runs. This cache exists to:
|
|
18
|
-
// 1. Avoid repeated lookups/imports for the same loader
|
|
19
|
-
// 2. Support lazy loading in production (loaders imported on-demand)
|
|
20
|
-
// 3. Provide a stable reference for the RSC handler
|
|
14
|
+
// Cache populated by getLoaderLazy() when loaders are first accessed.
|
|
15
|
+
// Source of truth is fetchableLoaderRegistry in loader.ts (populated on createLoader).
|
|
21
16
|
const loaderRegistry = new Map<string, LoaderRegistryEntry>();
|
|
22
17
|
|
|
23
|
-
// Lazy import map - set by the loader manifest
|
|
24
|
-
// Maps loader $$id to a function that imports the loader module
|
|
25
18
|
type LazyLoaderImport = () => Promise<{ $$id: string }>;
|
|
26
19
|
let lazyLoaderImports: Map<string, LazyLoaderImport> | null = null;
|
|
27
20
|
|
|
@@ -44,59 +37,61 @@ export function setLoaderImports(
|
|
|
44
37
|
export async function getLoaderLazy(
|
|
45
38
|
id: string,
|
|
46
39
|
): Promise<LoaderRegistryEntry | undefined> {
|
|
47
|
-
// Check
|
|
48
|
-
|
|
49
|
-
if (existing) {
|
|
50
|
-
return existing;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Check the fetchable loader registry (populated by createLoader)
|
|
40
|
+
// Check fetchableLoaderRegistry first — it's the source of truth.
|
|
41
|
+
// createLoader() updates it on HMR, ensuring fresh functions after file changes.
|
|
54
42
|
const fetchable = getFetchableLoader(id);
|
|
55
43
|
if (fetchable) {
|
|
56
|
-
// Cache in main registry for future requests
|
|
57
44
|
loaderRegistry.set(id, fetchable);
|
|
58
45
|
return fetchable;
|
|
59
46
|
}
|
|
60
47
|
|
|
61
|
-
|
|
48
|
+
const existing = loaderRegistry.get(id);
|
|
49
|
+
if (existing) {
|
|
50
|
+
return existing;
|
|
51
|
+
}
|
|
52
|
+
|
|
62
53
|
if (lazyLoaderImports && lazyLoaderImports.size > 0) {
|
|
63
54
|
const lazyImport = lazyLoaderImports.get(id);
|
|
64
55
|
if (lazyImport) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
// A failed import is a real server breakage (broken transitive import,
|
|
57
|
+
// syntax error, throw in module top-level code), not a "loader not
|
|
58
|
+
// registered" case. Rethrow so the caller can return a 500 and route
|
|
59
|
+
// the failure through onError, instead of collapsing it to a 404.
|
|
60
|
+
await lazyImport();
|
|
68
61
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return registered;
|
|
74
|
-
}
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.error(`[LoaderRegistry] Failed to load loader "${id}":`, error);
|
|
62
|
+
const registered = getFetchableLoader(id);
|
|
63
|
+
if (registered) {
|
|
64
|
+
loaderRegistry.set(id, registered);
|
|
65
|
+
return registered;
|
|
77
66
|
}
|
|
78
67
|
}
|
|
79
68
|
}
|
|
80
69
|
|
|
81
|
-
//
|
|
82
|
-
//
|
|
70
|
+
// The remaining dev fallback (parse the id as "src/path/file.ts#ExportName"
|
|
71
|
+
// and import it by path) only makes sense in dev, where ids ARE file paths
|
|
72
|
+
// and the dev loader manifest is intentionally empty. In production ids are
|
|
73
|
+
// hashed ("<hash>#ExportName") and every resolvable loader is reached above
|
|
74
|
+
// via the in-memory registry or the lazy import manifest. The hash is not a
|
|
75
|
+
// path, so a production fall-through would run import("/<hash>") and throw a
|
|
76
|
+
// misleading "No such module <hash>" 500 instead of reporting the loader as
|
|
77
|
+
// unregistered. Return undefined in production so a genuinely unknown loader
|
|
78
|
+
// is a clean 404 "not found in registry" from handleLoaderFetch.
|
|
79
|
+
if (process.env.NODE_ENV === "production") {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
83
|
const hashIndex = id.indexOf("#");
|
|
84
84
|
if (hashIndex !== -1) {
|
|
85
85
|
const filePath = id.slice(0, hashIndex);
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
await import(/* @vite-ignore */ `/${filePath}`);
|
|
87
|
+
// Same as the lazy branch: a thrown import is a server error, not a
|
|
88
|
+
// not-found. Let it propagate to the caller for a 500 + onError.
|
|
89
|
+
await import(/* @vite-ignore */ `/${filePath}`);
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return registered;
|
|
97
|
-
}
|
|
98
|
-
} catch (error) {
|
|
99
|
-
console.error(`[LoaderRegistry] Failed to load loader "${id}":`, error);
|
|
91
|
+
const registered = getFetchableLoader(id);
|
|
92
|
+
if (registered) {
|
|
93
|
+
loaderRegistry.set(id, registered);
|
|
94
|
+
return registered;
|
|
100
95
|
}
|
|
101
96
|
}
|
|
102
97
|
|
|
@@ -114,15 +109,12 @@ export function registerLoaderById(loader: {
|
|
|
114
109
|
if (!loader.$$id) {
|
|
115
110
|
return;
|
|
116
111
|
}
|
|
117
|
-
// For fetchable loaders, fn is stored in the fetchable registry by $$id.
|
|
118
|
-
// Always re-check the fetchable registry so HMR picks up the new function.
|
|
119
112
|
const fetchable = getFetchableLoader(loader.$$id);
|
|
120
113
|
if (fetchable) {
|
|
121
114
|
loaderRegistry.set(loader.$$id, fetchable);
|
|
122
115
|
return;
|
|
123
116
|
}
|
|
124
117
|
|
|
125
|
-
// Fall back to using fn from the loader object (non-fetchable loaders)
|
|
126
118
|
if (loader.fn) {
|
|
127
119
|
loaderRegistry.set(loader.$$id, {
|
|
128
120
|
fn: loader.fn,
|