@rangojs/router 0.0.0-experimental.19 → 0.0.0-experimental.1c0bdfad
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 +291 -61
- package/dist/bin/rango.js +544 -143
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3744 -1329
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +67 -13
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +312 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +247 -23
- package/skills/caching/SKILL.md +322 -19
- package/skills/composability/SKILL.md +27 -2
- 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 +282 -60
- package/skills/host-router/SKILL.md +278 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +50 -6
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +297 -31
- 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 +203 -7
- package/skills/prerender/SKILL.md +155 -111
- package/skills/rango/SKILL.md +251 -23
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +123 -48
- package/skills/route/SKILL.md +104 -9
- package/skills/router-setup/SKILL.md +124 -11
- 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 +125 -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 +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 +123 -0
- package/skills/typesafety/SKILL.md +357 -52
- package/skills/use-cache/SKILL.md +46 -14
- 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/bin/rango.ts +18 -0
- 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 +197 -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/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +200 -30
- package/src/browser/navigation-client.ts +217 -58
- 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/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +187 -112
- package/src/browser/prefetch/cache.ts +312 -30
- package/src/browser/prefetch/fetch.ts +344 -47
- 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 +125 -18
- package/src/browser/react/NavigationProvider.tsx +135 -120
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- 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 +80 -5
- package/src/browser/rsc-router.tsx +226 -75
- package/src/browser/scroll-restoration.ts +54 -42
- package/src/browser/segment-reconciler.ts +36 -9
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +619 -442
- package/src/browser/types.ts +115 -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 +7 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +182 -37
- 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 +392 -106
- 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 +214 -48
- package/src/cache/cache-scope.ts +236 -89
- 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 +2224 -171
- 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 +11 -17
- package/src/cache/document-cache.ts +89 -27
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +11 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +31 -31
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +55 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +45 -21
- package/src/client.tsx +120 -336
- 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 +84 -2
- package/src/debug.ts +2 -2
- 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 +56 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +95 -0
- 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 -5
- 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 +79 -29
- package/src/index.ts +149 -65
- 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 +63 -26
- 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 +7 -72
- package/src/route-definition/dsl-helpers.ts +469 -276
- 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 -3
- package/src/route-definition/redirect.ts +53 -12
- 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 +164 -17
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +45 -22
- package/src/router/handler-context.ts +110 -39
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +50 -24
- package/src/router/lazy-includes.ts +19 -53
- package/src/router/loader-resolution.ts +274 -56
- package/src/router/logging.ts +5 -8
- package/src/router/manifest.ts +49 -45
- package/src/router/match-api.ts +121 -205
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +33 -6
- package/src/router/match-middleware/cache-lookup.ts +214 -263
- package/src/router/match-middleware/cache-store.ts +73 -33
- 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 -49
- package/src/router/metrics.ts +217 -26
- package/src/router/middleware-types.ts +24 -110
- package/src/router/middleware.ts +384 -197
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +148 -91
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +199 -56
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +144 -74
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +8 -28
- package/src/router/router-interfaces.ts +129 -36
- package/src/router/router-options.ts +185 -23
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +281 -76
- package/src/router/segment-resolution/helpers.ts +116 -31
- package/src/router/segment-resolution/loader-cache.ts +63 -37
- package/src/router/segment-resolution/revalidation.ts +493 -391
- 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 +5 -1
- package/src/router/segment-wrappers.ts +8 -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 +180 -58
- package/src/router/types.ts +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +182 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +702 -460
- package/src/rsc/helpers.ts +168 -46
- package/src/rsc/index.ts +2 -25
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +127 -31
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +98 -19
- 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 +126 -106
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +269 -114
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/types.ts +34 -6
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +49 -41
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +281 -129
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +317 -63
- 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 +26 -46
- package/src/server/request-context.ts +425 -177
- package/src/server.ts +6 -0
- package/src/ssr/index.tsx +25 -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 +99 -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 +343 -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/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 +3 -19
- 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 +236 -88
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +44 -15
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +10 -45
- package/src/types/route-entry.ts +19 -7
- package/src/types/segments.ts +37 -19
- 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 +64 -91
- package/src/vite/discovery/discover-routers.ts +147 -88
- 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 +247 -145
- 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 +61 -13
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +10 -3
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +155 -65
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- package/src/vite/plugins/client-ref-dedup.ts +120 -0
- 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 +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 +89 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/version-injector.ts +21 -25
- package/src/vite/plugins/version-plugin.ts +46 -37
- package/src/vite/plugins/virtual-entries.ts +13 -18
- package/src/vite/rango.ts +241 -287
- package/src/vite/router-discovery.ts +956 -149
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- 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/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 +141 -34
- package/src/vite/utils/shared-utils.ts +92 -42
- package/CLAUDE.md +0 -5
- 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 -6
- package/src/network-error-thrower.tsx +0 -23
- package/src/route-definition/route-function.ts +0 -119
- package/src/router/middleware-cookies.ts +0 -55
package/src/__internal.ts
CHANGED
|
@@ -9,10 +9,6 @@
|
|
|
9
9
|
* adding them to the public API.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
// ============================================================================
|
|
13
|
-
// Segment Resolution (Internal)
|
|
14
|
-
// ============================================================================
|
|
15
|
-
|
|
16
12
|
/**
|
|
17
13
|
* @internal
|
|
18
14
|
* Internal representation of a resolved route segment.
|
|
@@ -26,10 +22,6 @@ export type { ResolvedSegment, SegmentMetadata } from "./types.js";
|
|
|
26
22
|
*/
|
|
27
23
|
export type { MatchResult, SlotState } from "./types.js";
|
|
28
24
|
|
|
29
|
-
// ============================================================================
|
|
30
|
-
// Intercept System (Internal)
|
|
31
|
-
// ============================================================================
|
|
32
|
-
|
|
33
25
|
/**
|
|
34
26
|
* @internal
|
|
35
27
|
* Context for intercept route selection.
|
|
@@ -40,10 +32,6 @@ export type {
|
|
|
40
32
|
InterceptWhenFn,
|
|
41
33
|
} from "./server/context.js";
|
|
42
34
|
|
|
43
|
-
// ============================================================================
|
|
44
|
-
// Browser State (Internal)
|
|
45
|
-
// ============================================================================
|
|
46
|
-
|
|
47
35
|
/**
|
|
48
36
|
* @internal
|
|
49
37
|
* RSC protocol payload structure.
|
|
@@ -68,10 +56,6 @@ export type {
|
|
|
68
56
|
NavigationUpdate,
|
|
69
57
|
} from "./browser/types.js";
|
|
70
58
|
|
|
71
|
-
// ============================================================================
|
|
72
|
-
// Handle System (Internal)
|
|
73
|
-
// ============================================================================
|
|
74
|
-
|
|
75
59
|
/**
|
|
76
60
|
* @internal
|
|
77
61
|
* Internal handle storage mechanism.
|
|
@@ -84,26 +68,17 @@ export type { HandleStore, HandleData } from "./server/handle-store.js";
|
|
|
84
68
|
*/
|
|
85
69
|
export type { SegmentHandleData } from "./cache/types.js";
|
|
86
70
|
|
|
87
|
-
// ============================================================================
|
|
88
|
-
// Cache Internals
|
|
89
|
-
// ============================================================================
|
|
90
|
-
|
|
91
71
|
/**
|
|
92
72
|
* @internal
|
|
93
73
|
* Internal cache entry data structure.
|
|
94
74
|
*/
|
|
95
75
|
export type {
|
|
96
76
|
CachedEntryData,
|
|
97
|
-
CachedEntryResult,
|
|
98
77
|
CacheGetResult,
|
|
99
78
|
SerializedSegmentData,
|
|
100
79
|
CacheDefaults,
|
|
101
80
|
} from "./cache/types.js";
|
|
102
81
|
|
|
103
|
-
// ============================================================================
|
|
104
|
-
// Router Context (Internal)
|
|
105
|
-
// ============================================================================
|
|
106
|
-
|
|
107
82
|
/**
|
|
108
83
|
* @internal
|
|
109
84
|
* Router context for AsyncLocalStorage.
|
|
@@ -114,10 +89,6 @@ export type {
|
|
|
114
89
|
InterceptResult,
|
|
115
90
|
} from "./router/router-context.js";
|
|
116
91
|
|
|
117
|
-
// ============================================================================
|
|
118
|
-
// Match Pipeline (Internal)
|
|
119
|
-
// ============================================================================
|
|
120
|
-
|
|
121
92
|
/**
|
|
122
93
|
* @internal
|
|
123
94
|
* Route match context during pipeline processing.
|
|
@@ -133,10 +104,6 @@ export type {
|
|
|
133
104
|
*/
|
|
134
105
|
export type { RouteMatchResult } from "./router/pattern-matching.js";
|
|
135
106
|
|
|
136
|
-
// ============================================================================
|
|
137
|
-
// Server Context (Internal)
|
|
138
|
-
// ============================================================================
|
|
139
|
-
|
|
140
107
|
/**
|
|
141
108
|
* @internal
|
|
142
109
|
* Entry data during route traversal.
|
|
@@ -153,10 +120,6 @@ export type {
|
|
|
153
120
|
EntryPropSegments,
|
|
154
121
|
} from "./server/context.js";
|
|
155
122
|
|
|
156
|
-
// ============================================================================
|
|
157
|
-
// Handler Context (Internal)
|
|
158
|
-
// ============================================================================
|
|
159
|
-
|
|
160
123
|
/**
|
|
161
124
|
* @internal
|
|
162
125
|
* Internal handler context with additional props for router internals.
|
|
@@ -164,9 +127,73 @@ export type {
|
|
|
164
127
|
*/
|
|
165
128
|
export type { InternalHandlerContext } from "./types.js";
|
|
166
129
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
130
|
+
/**
|
|
131
|
+
* @internal
|
|
132
|
+
* Builds React element trees from route segments.
|
|
133
|
+
*/
|
|
134
|
+
export { renderSegments } from "./segment-system.js";
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @internal
|
|
138
|
+
* Error sanitization and network error utilities.
|
|
139
|
+
*/
|
|
140
|
+
export { sanitizeError, NetworkError, isNetworkError } from "./errors.js";
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @internal
|
|
144
|
+
* Scoped view of GeneratedRouteMap for Handler<"localName", ScopedRouteMap<"prefix">>.
|
|
145
|
+
*/
|
|
146
|
+
export type { ScopedRouteMap } from "./types.js";
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @internal
|
|
150
|
+
* Type-level utilities for reverse URL generation.
|
|
151
|
+
*/
|
|
152
|
+
export type { MergeRoutes, SanitizePrefix } from "./reverse.js";
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @internal
|
|
156
|
+
* Individual telemetry event types.
|
|
157
|
+
*/
|
|
158
|
+
export type {
|
|
159
|
+
RequestStartEvent,
|
|
160
|
+
RequestEndEvent,
|
|
161
|
+
RequestErrorEvent,
|
|
162
|
+
RequestTimeoutEvent,
|
|
163
|
+
LoaderStartEvent,
|
|
164
|
+
LoaderEndEvent,
|
|
165
|
+
LoaderErrorEvent,
|
|
166
|
+
HandlerErrorEvent,
|
|
167
|
+
CacheDecisionEvent,
|
|
168
|
+
RevalidationDecisionEvent,
|
|
169
|
+
} from "./router/telemetry.js";
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @internal
|
|
173
|
+
* Type guard for prerender handler definitions.
|
|
174
|
+
*/
|
|
175
|
+
export { isPrerenderHandler, isPassthroughHandler } from "./prerender.js";
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @internal
|
|
179
|
+
* Type guard for static handler definitions.
|
|
180
|
+
*/
|
|
181
|
+
export { isStaticHandler } from "./static-handler.js";
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @internal
|
|
185
|
+
* Sentinel used to tag response-type route entries.
|
|
186
|
+
*/
|
|
187
|
+
export { RESPONSE_TYPE } from "./urls.js";
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @internal
|
|
191
|
+
* Debug utilities for route matching performance analysis.
|
|
192
|
+
*/
|
|
193
|
+
export {
|
|
194
|
+
enableMatchDebug,
|
|
195
|
+
getMatchDebugStats,
|
|
196
|
+
} from "./router/pattern-matching.js";
|
|
170
197
|
|
|
171
198
|
/**
|
|
172
199
|
* @internal
|
package/src/bin/rango.ts
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
writeCombinedRouteTypes,
|
|
7
7
|
detectUnresolvableIncludes,
|
|
8
8
|
detectUnresolvableIncludesForUrlsFile,
|
|
9
|
+
findNestedRouterConflict,
|
|
10
|
+
formatNestedRouterConflictError,
|
|
9
11
|
type UnresolvableInclude,
|
|
10
12
|
} from "../build/generate-route-types.ts";
|
|
11
13
|
|
|
@@ -205,6 +207,14 @@ function runStaticGeneration(args: string[], mode: "default" | "static") {
|
|
|
205
207
|
console.warn("");
|
|
206
208
|
}
|
|
207
209
|
|
|
210
|
+
const nestedRouterConflict = findNestedRouterConflict(routerFiles);
|
|
211
|
+
if (nestedRouterConflict) {
|
|
212
|
+
console.error(
|
|
213
|
+
`\n${formatNestedRouterConflictError(nestedRouterConflict, "[rango]")}\n`,
|
|
214
|
+
);
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
|
|
208
218
|
// Phase 3: Write all outputs (only reached if diagnostics pass or --static)
|
|
209
219
|
for (const urlsFile of urlsFiles) {
|
|
210
220
|
writePerModuleRouteTypesForFile(urlsFile);
|
|
@@ -259,6 +269,14 @@ async function runRuntimeDiscovery(args: string[], configFile?: string) {
|
|
|
259
269
|
process.exit(1);
|
|
260
270
|
}
|
|
261
271
|
|
|
272
|
+
const nestedRouterConflict = findNestedRouterConflict(routerEntries);
|
|
273
|
+
if (nestedRouterConflict) {
|
|
274
|
+
console.error(
|
|
275
|
+
`\n${formatNestedRouterConflictError(nestedRouterConflict, "[rango]")}\n`,
|
|
276
|
+
);
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
|
|
262
280
|
let discoverAndWriteRouteTypes: typeof import("../build/runtime-discovery.ts").discoverAndWriteRouteTypes;
|
|
263
281
|
try {
|
|
264
282
|
const mod = await import("../build/runtime-discovery.ts");
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
classifyActionResponse,
|
|
3
|
-
type ActionScenario,
|
|
4
|
-
} from "./action-response-classifier.js";
|
|
5
1
|
import type { ActionEntry } from "./event-controller.js";
|
|
6
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Post-reconciliation action outcome (discriminated union). Error and
|
|
5
|
+
* full-update-unsupported cases are handled inline in the bridge before
|
|
6
|
+
* reconciliation; this only covers successfully-reconciled partial responses.
|
|
7
|
+
*/
|
|
8
|
+
type ActionScenario =
|
|
9
|
+
| {
|
|
10
|
+
type: "navigated-away";
|
|
11
|
+
historyKeyChanged: boolean;
|
|
12
|
+
onInterceptRoute: boolean;
|
|
13
|
+
}
|
|
14
|
+
| { type: "hmr-missing" }
|
|
15
|
+
| { type: "consolidation-needed"; segmentIds: string[] }
|
|
16
|
+
| { type: "concurrent-skip"; otherFetchingCount: number }
|
|
17
|
+
| { type: "normal" };
|
|
18
|
+
|
|
7
19
|
/**
|
|
8
20
|
* Plain data inputs for classifying a post-reconciliation action outcome.
|
|
9
21
|
* No browser objects or controller references — all values are snapshots.
|
|
@@ -33,20 +45,15 @@ export interface ActionOutcomeInput {
|
|
|
33
45
|
currentInterceptSource: string | null;
|
|
34
46
|
}
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* Returns segment IDs that need re-fetching when concurrent actions
|
|
40
|
-
* have each revalidated different parts of the tree, or null if
|
|
41
|
-
* consolidation is not needed.
|
|
42
|
-
*/
|
|
48
|
+
// Segment IDs to re-fetch when concurrent actions each revalidated different
|
|
49
|
+
// parts of the tree; null when consolidation does not apply. Returns null while
|
|
50
|
+
// any action is still fetching — consolidation must wait for all to land.
|
|
43
51
|
function computeConsolidationSegments(
|
|
44
52
|
input: ActionOutcomeInput,
|
|
45
53
|
): string[] | null {
|
|
46
54
|
if (!input.hadAnyConcurrentActions) return null;
|
|
47
55
|
if (input.revalidatedSegments.size === 0) return null;
|
|
48
56
|
|
|
49
|
-
// Can't consolidate while any action is still waiting for a server response
|
|
50
57
|
const stillFetchingCount = [...input.inflightActions.values()].filter(
|
|
51
58
|
(a) => a.phase === "fetching",
|
|
52
59
|
).length;
|
|
@@ -55,9 +62,6 @@ function computeConsolidationSegments(
|
|
|
55
62
|
return Array.from(input.revalidatedSegments);
|
|
56
63
|
}
|
|
57
64
|
|
|
58
|
-
/**
|
|
59
|
-
* Count other actions still in "fetching" phase (excluding this handle).
|
|
60
|
-
*/
|
|
61
65
|
function countOtherFetchingActions(input: ActionOutcomeInput): number {
|
|
62
66
|
let count = 0;
|
|
63
67
|
for (const [, a] of input.inflightActions) {
|
|
@@ -69,29 +73,42 @@ function countOtherFetchingActions(input: ActionOutcomeInput): number {
|
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
/**
|
|
72
|
-
* Classify a post-reconciliation action outcome
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* then delegates to the pure classifyActionResponse function.
|
|
77
|
-
*
|
|
78
|
-
* The server-action-bridge calls this after reconciliation to decide
|
|
79
|
-
* whether to render, skip, consolidate, or refetch.
|
|
76
|
+
* Classify a post-reconciliation action outcome. Ordered priority chain: each
|
|
77
|
+
* case assumes the earlier ones are false (e.g. concurrent-skip only applies on
|
|
78
|
+
* the still-current route, consolidation only once no action is still fetching).
|
|
79
|
+
* The bridge calls this to decide whether to render, skip, consolidate, or refetch.
|
|
80
80
|
*/
|
|
81
81
|
export function classifyActionOutcome(
|
|
82
82
|
input: ActionOutcomeInput,
|
|
83
83
|
): ActionScenario {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
84
|
+
if (
|
|
85
|
+
input.currentPathname !== input.actionStartPathname ||
|
|
86
|
+
input.currentLocationKey !== input.actionStartLocationKey
|
|
87
|
+
) {
|
|
88
|
+
return {
|
|
89
|
+
type: "navigated-away",
|
|
90
|
+
historyKeyChanged:
|
|
91
|
+
input.currentLocationKey !== input.actionStartLocationKey,
|
|
92
|
+
onInterceptRoute: input.currentInterceptSource !== null,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (input.reconciledSegmentCount < input.matchedCount) {
|
|
97
|
+
return { type: "hmr-missing" };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const consolidationSegments = computeConsolidationSegments(input);
|
|
101
|
+
if (consolidationSegments && consolidationSegments.length > 0) {
|
|
102
|
+
return { type: "consolidation-needed", segmentIds: consolidationSegments };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const otherFetchingActionCount = countOtherFetchingActions(input);
|
|
106
|
+
if (otherFetchingActionCount > 0) {
|
|
107
|
+
return {
|
|
108
|
+
type: "concurrent-skip",
|
|
109
|
+
otherFetchingCount: otherFetchingActionCount,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
96
112
|
|
|
97
|
-
|
|
113
|
+
return { type: "normal" };
|
|
114
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action fence: a refcounted flag that is raised while a server action is in
|
|
3
|
+
* flight and lowered when it resolves.
|
|
4
|
+
*
|
|
5
|
+
* It replaces the eager cache clear the action bridge used to do at action
|
|
6
|
+
* start. While the fence is up, the decision of whether the action invalidated
|
|
7
|
+
* anything is deferred to the response:
|
|
8
|
+
*
|
|
9
|
+
* - prefetch consumption is suspended (a queued prefetch result is not served),
|
|
10
|
+
* - a genuine navigation during the flight fetches with `cache: "no-store"` so
|
|
11
|
+
* it cannot be served stale bytes from the browser's Vary-keyed HTTP cache,
|
|
12
|
+
* - popstate reads are treated as stale-while-revalidate.
|
|
13
|
+
*
|
|
14
|
+
* Nothing is wiped, rotated, or broadcast while the fence is up — that is what
|
|
15
|
+
* keeps a sibling tab from seeing a pre-commit signal. Refcounted so concurrent
|
|
16
|
+
* actions compose: each action raises and lowers its own reference, and the
|
|
17
|
+
* fence is down only when the count reaches zero.
|
|
18
|
+
*
|
|
19
|
+
* The refcount is a single module-level counter, not keyed by routerId.
|
|
20
|
+
* Consumers (navigation-client.ts, prefetch/fetch.ts, navigation-bridge.ts)
|
|
21
|
+
* read it unscoped, so an action in one router would suppress another router's
|
|
22
|
+
* navigation/prefetch caches. This is correct only because two routers cannot
|
|
23
|
+
* coexist in one live document: an SPA navigation crossing a host-router
|
|
24
|
+
* boundary forces a full document reload (src/router/request-classification.ts
|
|
25
|
+
* app-switch terminal), so there is always exactly one live router per
|
|
26
|
+
* document. A future multi-router-in-one-document feature must not silently
|
|
27
|
+
* inherit this global, cross-router cache suppression.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
let fenceCount = 0;
|
|
31
|
+
|
|
32
|
+
export function enterActionFence(): void {
|
|
33
|
+
fenceCount++;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function exitActionFence(): void {
|
|
37
|
+
if (fenceCount > 0) fenceCount--;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isActionFenceActive(): boolean {
|
|
41
|
+
return fenceCount > 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Test-only: reset the refcount between cases. */
|
|
45
|
+
export function __resetActionFence(): void {
|
|
46
|
+
fenceCount = 0;
|
|
47
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ComponentType, ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* App-shell metadata: the per-router fields describing the "envelope" around
|
|
5
|
+
* the current app's segment tree — the rootLayout (Document), basename,
|
|
6
|
+
* version, and router identity. Set once from the initial RSC payload and read
|
|
7
|
+
* through the AppShellRef when rendering segments.
|
|
8
|
+
*
|
|
9
|
+
* This is a per-document value. A navigation that crosses a host-router app
|
|
10
|
+
* boundary is a full document load (the server returns X-RSC-Reload for it;
|
|
11
|
+
* see request-classification.ts, mode "app-switch"), so the target app's shell
|
|
12
|
+
* — along with everything else document-level (theme, warmup, prefetch-TTL) —
|
|
13
|
+
* is established fresh by the target app's own load. The shell is never swapped
|
|
14
|
+
* in place within a session.
|
|
15
|
+
*/
|
|
16
|
+
export interface AppShell {
|
|
17
|
+
/** Router identity. Used to namespace per-app client state (e.g. the
|
|
18
|
+
* rango-state localStorage key) so sibling apps on the same origin
|
|
19
|
+
* cannot observe each other's cache invalidations. */
|
|
20
|
+
routerId?: string;
|
|
21
|
+
rootLayout?: ComponentType<{ children: ReactNode }>;
|
|
22
|
+
basename?: string;
|
|
23
|
+
version?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Container for the active app shell. Read-through via `get()` so closures
|
|
28
|
+
* (e.g. the segment renderer) capture the ref and read the shell at call time
|
|
29
|
+
* rather than closing over a stale snapshot.
|
|
30
|
+
*/
|
|
31
|
+
export interface AppShellRef {
|
|
32
|
+
get(): AppShell;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function createAppShellRef(initial: AppShell): AppShellRef {
|
|
36
|
+
return {
|
|
37
|
+
get: () => initial,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mutable app version — updated after HMR revalidation.
|
|
3
|
+
* Read by prefetch, navigation, and context code.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
let currentVersion: string | undefined;
|
|
7
|
+
|
|
8
|
+
export function getAppVersion(): string | undefined {
|
|
9
|
+
return currentVersion;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function setAppVersion(version: string | undefined): void {
|
|
13
|
+
currentVersion = version;
|
|
14
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection warmup: keep TLS alive after idle periods.
|
|
3
|
+
*
|
|
4
|
+
* After IDLE_TIMEOUT of no user interaction the connection is marked "cold".
|
|
5
|
+
* On the next pointer/touch interaction or a visibility change, a HEAD request
|
|
6
|
+
* warms the TLS connection before the user actually clicks a link.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from NavigationProvider so the idle/cold/warmup state machine is
|
|
9
|
+
* unit-testable with an injected environment (document, fetch, timers).
|
|
10
|
+
*
|
|
11
|
+
* Ordering bug this guards against: the warmup listeners (mousemove/touchstart)
|
|
12
|
+
* share events with the idle-reset listeners, and the idle-reset listener is
|
|
13
|
+
* registered first, so it clears the live "cold" flag before the warmup
|
|
14
|
+
* listener reads it on the same event. A separate coldLatch — set when the
|
|
15
|
+
* connection goes cold and cleared only when warmup fires or listeners detach,
|
|
16
|
+
* never by the idle reset — lets the warmup decision see the pre-reset cold
|
|
17
|
+
* state regardless of listener ordering.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const IDLE_TIMEOUT = 60_000;
|
|
21
|
+
const DEBOUNCE_DELAY = 150;
|
|
22
|
+
|
|
23
|
+
type TimerHandle = ReturnType<typeof setTimeout>;
|
|
24
|
+
|
|
25
|
+
export interface WarmupEnv {
|
|
26
|
+
doc: Pick<
|
|
27
|
+
Document,
|
|
28
|
+
"addEventListener" | "removeEventListener" | "visibilityState"
|
|
29
|
+
>;
|
|
30
|
+
fetch: typeof fetch;
|
|
31
|
+
setTimeout: (fn: () => void, ms: number) => TimerHandle;
|
|
32
|
+
clearTimeout: (handle: TimerHandle | undefined) => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function defaultEnv(): WarmupEnv {
|
|
36
|
+
return {
|
|
37
|
+
doc: document,
|
|
38
|
+
fetch: (...args) => fetch(...args),
|
|
39
|
+
setTimeout: (fn, ms) => setTimeout(fn, ms),
|
|
40
|
+
clearTimeout: (handle) => clearTimeout(handle),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Start the connection-warmup state machine. Returns a cleanup function that
|
|
46
|
+
* cancels timers and removes all listeners.
|
|
47
|
+
*/
|
|
48
|
+
export function startConnectionWarmup(
|
|
49
|
+
env: WarmupEnv = defaultEnv(),
|
|
50
|
+
): () => void {
|
|
51
|
+
const { doc, setTimeout: setT, clearTimeout: clearT } = env;
|
|
52
|
+
|
|
53
|
+
let idleTimer: TimerHandle | undefined;
|
|
54
|
+
let debounceTimer: TimerHandle | undefined;
|
|
55
|
+
// Cold latch for the warmup decision — see module header. Set in markCold;
|
|
56
|
+
// cleared only when warmup fires or listeners detach, NOT by resetIdleTimer,
|
|
57
|
+
// so triggerWarmup sees the pre-reset cold state regardless of listener
|
|
58
|
+
// ordering (the idle-reset listener runs first on a shared mousemove event).
|
|
59
|
+
let coldLatch = false;
|
|
60
|
+
let warmupListenersAttached = false;
|
|
61
|
+
|
|
62
|
+
function sendWarmup() {
|
|
63
|
+
coldLatch = false;
|
|
64
|
+
env.fetch("/?_rsc_warmup", { method: "HEAD" }).catch(() => {});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function triggerWarmup() {
|
|
68
|
+
if (!coldLatch) return;
|
|
69
|
+
clearT(debounceTimer);
|
|
70
|
+
debounceTimer = setT(() => {
|
|
71
|
+
sendWarmup();
|
|
72
|
+
detachWarmupListeners();
|
|
73
|
+
resetIdleTimer();
|
|
74
|
+
}, DEBOUNCE_DELAY);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function onVisibilityChange() {
|
|
78
|
+
if (doc.visibilityState === "visible" && coldLatch) {
|
|
79
|
+
triggerWarmup();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function attachWarmupListeners() {
|
|
84
|
+
if (warmupListenersAttached) return;
|
|
85
|
+
warmupListenersAttached = true;
|
|
86
|
+
doc.addEventListener("visibilitychange", onVisibilityChange);
|
|
87
|
+
doc.addEventListener("mousemove", triggerWarmup, { once: true });
|
|
88
|
+
doc.addEventListener("touchstart", triggerWarmup, { once: true });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function detachWarmupListeners() {
|
|
92
|
+
warmupListenersAttached = false;
|
|
93
|
+
coldLatch = false;
|
|
94
|
+
doc.removeEventListener("visibilitychange", onVisibilityChange);
|
|
95
|
+
doc.removeEventListener("mousemove", triggerWarmup);
|
|
96
|
+
doc.removeEventListener("touchstart", triggerWarmup);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function markCold() {
|
|
100
|
+
coldLatch = true;
|
|
101
|
+
attachWarmupListeners();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function resetIdleTimer() {
|
|
105
|
+
clearT(idleTimer);
|
|
106
|
+
idleTimer = setT(markCold, IDLE_TIMEOUT);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Activity events that reset the idle timer. mousemove/touchstart overlap
|
|
110
|
+
// with the warmup listeners; this listener is registered first, which is the
|
|
111
|
+
// ordering the coldLatch defends against.
|
|
112
|
+
const activityEvents = [
|
|
113
|
+
"mousemove",
|
|
114
|
+
"keydown",
|
|
115
|
+
"touchstart",
|
|
116
|
+
"scroll",
|
|
117
|
+
] as const;
|
|
118
|
+
const activityOptions: AddEventListenerOptions = { passive: true };
|
|
119
|
+
|
|
120
|
+
for (const event of activityEvents) {
|
|
121
|
+
doc.addEventListener(event, resetIdleTimer, activityOptions);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
resetIdleTimer();
|
|
125
|
+
|
|
126
|
+
return () => {
|
|
127
|
+
clearT(idleTimer);
|
|
128
|
+
clearT(debounceTimer);
|
|
129
|
+
detachWarmupListeners();
|
|
130
|
+
for (const event of activityEvents) {
|
|
131
|
+
doc.removeEventListener(event, resetIdleTimer);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|