@rangojs/router 0.16.0 → 0.17.0
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/README.md +254 -89
- package/dist/testing/vitest.js +252 -0
- package/dist/types/browser/navigation-transaction.d.ts +6 -0
- package/dist/types/browser/partial-update.d.ts +11 -0
- package/dist/types/browser/react/ScrollRestoration.d.ts +6 -6
- package/dist/types/browser/rsc-router.d.ts +1 -1
- package/dist/types/browser/scroll-restoration.d.ts +7 -0
- package/dist/types/cache/cache-exec-scope.d.ts +18 -1
- package/dist/types/cache/cache-scope.d.ts +34 -5
- package/dist/types/cache/handle-capture.d.ts +41 -3
- package/dist/types/cache/handle-snapshot.d.ts +53 -13
- package/dist/types/cache/segment-codec.d.ts +10 -3
- package/dist/types/cache/taint.d.ts +1 -1
- package/dist/types/cache/types.d.ts +15 -3
- package/dist/types/client.d.ts +4 -4
- package/dist/types/client.rsc.d.ts +4 -5
- package/dist/types/components/DefaultDocument.d.ts +5 -2
- package/dist/types/context-var.d.ts +6 -5
- package/dist/types/escape-script.d.ts +1 -1
- package/dist/types/handles/MetaTags.d.ts +5 -4
- package/dist/types/handles/Scripts.d.ts +8 -7
- package/dist/types/handles/meta.d.ts +2 -2
- package/dist/types/handles/script.d.ts +17 -16
- package/dist/types/href-client.d.ts +1 -1
- package/dist/types/html.d.ts +12 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.rsc.d.ts +3 -2
- package/dist/types/loader-store.d.ts +7 -4
- package/dist/types/reverse.d.ts +36 -4
- package/dist/types/route-definition/dsl-helpers.d.ts +3 -3
- package/dist/types/route-definition/helpers-types.d.ts +33 -9
- package/dist/types/route-definition/resolve-handler-use.d.ts +23 -1
- package/dist/types/route-types.d.ts +1 -1
- package/dist/types/router/debug-manifest.d.ts +3 -2
- package/dist/types/router/error-handling.d.ts +20 -0
- package/dist/types/router/handler-context.d.ts +6 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +46 -5
- package/dist/types/router/middleware-types.d.ts +3 -2
- package/dist/types/router/router-context.d.ts +3 -1
- package/dist/types/router/router-interfaces.d.ts +24 -2
- package/dist/types/router/router-options.d.ts +8 -5
- package/dist/types/router/segment-resolution/fresh.d.ts +10 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +37 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +9 -19
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +3 -3
- package/dist/types/router/segment-resolution/mask-nested.d.ts +7 -7
- package/dist/types/router/segment-resolution/revalidation.d.ts +6 -2
- package/dist/types/router/segment-wrappers.d.ts +1 -1
- package/dist/types/rsc/response-route-handler.d.ts +1 -1
- package/dist/types/rsc/rsc-rendering.d.ts +1 -2
- package/dist/types/rsc/shell-capture-constants.d.ts +8 -0
- package/dist/types/rsc/shell-capture.d.ts +5 -4
- package/dist/types/rsc/ssr-setup.d.ts +6 -6
- package/dist/types/rsc/types.d.ts +10 -0
- package/dist/types/server/context.d.ts +33 -3
- package/dist/types/server/handle-store.d.ts +26 -2
- package/dist/types/server/request-context.d.ts +24 -21
- package/dist/types/ssr/index.d.ts +15 -0
- package/dist/types/static-handler.d.ts +4 -1
- package/dist/types/testing/generated-routes.d.ts +2 -2
- package/dist/types/testing/internal/context.d.ts +1 -1
- package/dist/types/testing/render-route.d.ts +32 -6
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +28 -5
- package/dist/types/testing/vitest.d.ts +35 -1
- package/dist/types/theme/ThemeScript.d.ts +3 -3
- package/dist/types/types/cache-types.d.ts +14 -10
- package/dist/types/types/handler-context.d.ts +14 -0
- package/dist/types/types/loader-types.d.ts +8 -6
- package/dist/types/urls/response-types.d.ts +3 -12
- package/dist/types/use-loader.d.ts +12 -3
- package/dist/types/vite/plugins/use-cache-transform.d.ts +33 -2
- package/dist/types/vite/rango.d.ts +1 -1
- package/dist/vite/index.js +1381 -1346
- package/package.json +2 -2
- package/skills/api-client/SKILL.md +22 -10
- package/skills/breadcrumbs/SKILL.md +65 -22
- package/skills/bundle-analysis/SKILL.md +22 -22
- package/skills/cache-guide/SKILL.md +207 -97
- package/skills/caching/SKILL.md +295 -93
- package/skills/catalog.json +16 -16
- package/skills/client-urls/SKILL.md +53 -31
- package/skills/cloudflare/SKILL.md +72 -20
- package/skills/cloudflare/references/d1-and-local-dev.md +15 -2
- package/skills/cloudflare/references/streaming-and-deploy.md +10 -3
- package/skills/cloudflare/references/webhooks-and-crypto.md +9 -2
- package/skills/comparison/SKILL.md +5 -0
- package/skills/comparison/references/framework-comparison.md +39 -33
- package/skills/composability/SKILL.md +38 -29
- package/skills/css/SKILL.md +10 -13
- package/skills/debug-manifest/SKILL.md +74 -31
- package/skills/defer-hydration/SKILL.md +2 -1
- package/skills/deployment-caching/SKILL.md +6 -1
- package/skills/document-cache/SKILL.md +92 -28
- package/skills/fonts/SKILL.md +16 -8
- package/skills/handler-use/SKILL.md +53 -17
- package/skills/hooks/SKILL.md +28 -20
- package/skills/hooks/data.md +23 -3
- package/skills/hooks/handle-and-actions.md +31 -16
- package/skills/hooks/navigation.md +39 -10
- package/skills/hooks/outlets.md +13 -6
- package/skills/hooks/state.md +37 -15
- package/skills/hooks/urls.md +7 -5
- package/skills/host-router/SKILL.md +64 -12
- package/skills/i18n/SKILL.md +60 -34
- package/skills/intercept/SKILL.md +161 -26
- package/skills/layout/SKILL.md +106 -50
- package/skills/links/SKILL.md +51 -19
- package/skills/loader/SKILL.md +242 -106
- package/skills/middleware/SKILL.md +119 -23
- package/skills/migrate-nextjs/SKILL.md +100 -45
- package/skills/migrate-nextjs/backend-host-swap.md +5 -2
- package/skills/migrate-react-router/SKILL.md +49 -38
- package/skills/migrate-react-router/component-migration.md +25 -6
- package/skills/migrate-react-router/data-and-actions.md +18 -5
- package/skills/migrate-react-router/route-mapping.md +12 -6
- package/skills/mime-routes/SKILL.md +12 -7
- package/skills/observability/SKILL.md +28 -14
- package/skills/parallel/SKILL.md +75 -39
- package/skills/ppr/SKILL.md +345 -150
- package/skills/prerender/SKILL.md +189 -100
- package/skills/rango/SKILL.md +65 -34
- package/skills/react-compiler/SKILL.md +6 -5
- package/skills/response-routes/SKILL.md +133 -25
- package/skills/route/SKILL.md +165 -60
- package/skills/router-setup/SKILL.md +418 -240
- package/skills/scripts/SKILL.md +31 -20
- package/skills/server-actions/SKILL.md +220 -59
- package/skills/shell-manifest/SKILL.md +12 -7
- package/skills/streams-and-websockets/SKILL.md +32 -14
- package/skills/tailwind/SKILL.md +37 -33
- package/skills/testing/SKILL.md +68 -32
- package/skills/testing/cache-prerender.md +55 -29
- package/skills/testing/client-components.md +59 -6
- package/skills/testing/e2e-parity.md +12 -2
- package/skills/testing/flight.md +19 -11
- package/skills/testing/handles.md +8 -5
- package/skills/testing/loader.md +8 -5
- package/skills/testing/middleware.md +8 -3
- package/skills/testing/predicates.md +120 -0
- package/skills/testing/render-handler.md +70 -22
- package/skills/testing/response-routes.md +11 -4
- package/skills/testing/reverse-and-types.md +20 -14
- package/skills/testing/server-actions.md +12 -3
- package/skills/testing/server-tree.md +9 -0
- package/skills/testing/setup.md +9 -5
- package/skills/theme/SKILL.md +106 -29
- package/skills/typesafety/SKILL.md +20 -9
- package/skills/typesafety/env-and-bindings.md +126 -47
- package/skills/typesafety/generated-files-and-cli.md +26 -14
- package/skills/typesafety/params-and-search.md +44 -19
- package/skills/typesafety/route-types.md +50 -14
- package/skills/use-cache/SKILL.md +200 -82
- package/skills/vercel/SKILL.md +21 -11
- package/skills/view-transitions/SKILL.md +41 -20
- package/src/__augment-tests__/augmented.check.ts +26 -1
- package/src/browser/index.ts +2 -2
- package/src/browser/navigation-bridge.ts +3 -4
- package/src/browser/navigation-transaction.ts +22 -2
- package/src/browser/partial-update.ts +35 -25
- package/src/browser/react/ScrollRestoration.tsx +6 -6
- package/src/browser/rsc-router.tsx +1 -1
- package/src/browser/scroll-restoration.ts +53 -6
- package/src/cache/cache-exec-scope.ts +37 -4
- package/src/cache/cache-key-utils.ts +1 -6
- package/src/cache/cache-runtime.ts +230 -61
- package/src/cache/cache-scope.ts +76 -12
- package/src/cache/document-cache.ts +15 -0
- package/src/cache/handle-capture.ts +90 -10
- package/src/cache/handle-snapshot.ts +132 -28
- package/src/cache/segment-codec.ts +26 -7
- package/src/cache/tag-invalidation.ts +4 -3
- package/src/cache/taint.ts +1 -1
- package/src/cache/types.ts +16 -3
- package/src/client.rsc.tsx +10 -9
- package/src/client.tsx +5 -4
- package/src/components/DefaultDocument.tsx +7 -2
- package/src/context-var.ts +6 -5
- package/src/escape-script.ts +1 -1
- package/src/handles/MetaTags.tsx +13 -11
- package/src/handles/Scripts.tsx +11 -10
- package/src/handles/meta.ts +2 -2
- package/src/handles/script.ts +17 -16
- package/src/href-client.ts +1 -1
- package/src/html.ts +12 -0
- package/src/index.rsc.ts +5 -0
- package/src/index.ts +1 -0
- package/src/loader-store.ts +7 -4
- package/src/prerender/build-shell-capture.ts +8 -11
- package/src/reverse.ts +44 -4
- package/src/route-definition/dsl-helpers.ts +117 -30
- package/src/route-definition/helpers-types.ts +33 -9
- package/src/route-definition/resolve-handler-use.ts +121 -6
- package/src/route-types.ts +0 -3
- package/src/router/debug-manifest.ts +10 -2
- package/src/router/error-handling.ts +51 -15
- package/src/router/handler-context.ts +34 -25
- package/src/router/intercept-resolution.ts +125 -39
- package/src/router/loader-resolution.ts +56 -11
- package/src/router/match-api.ts +12 -17
- package/src/router/match-middleware/background-revalidation.ts +161 -96
- package/src/router/match-middleware/cache-lookup.ts +93 -10
- package/src/router/match-middleware/cache-store.ts +17 -90
- package/src/router/middleware-types.ts +3 -5
- package/src/router/middleware.ts +52 -9
- package/src/router/prerender-match.ts +53 -19
- package/src/router/route-snapshot.ts +11 -1
- package/src/router/router-context.ts +2 -0
- package/src/router/router-interfaces.ts +25 -2
- package/src/router/router-options.ts +8 -5
- package/src/router/segment-resolution/fresh.ts +44 -12
- package/src/router/segment-resolution/loader-cache.ts +205 -45
- package/src/router/segment-resolution/loader-mask.ts +12 -22
- package/src/router/segment-resolution/loader-snapshot.ts +6 -6
- package/src/router/segment-resolution/mask-nested.ts +7 -7
- package/src/router/segment-resolution/revalidation.ts +34 -6
- package/src/router/segment-wrappers.ts +4 -0
- package/src/rsc/render-pipeline.ts +3 -0
- package/src/rsc/response-route-handler.ts +11 -3
- package/src/rsc/rsc-rendering.ts +8 -45
- package/src/rsc/shell-capture-constants.ts +13 -0
- package/src/rsc/shell-capture.ts +111 -90
- package/src/rsc/ssr-setup.ts +14 -8
- package/src/rsc/types.ts +11 -0
- package/src/server/context.ts +88 -11
- package/src/server/cookie-store.ts +5 -4
- package/src/server/handle-store.ts +232 -7
- package/src/server/request-context.ts +35 -30
- package/src/ssr/index.tsx +40 -7
- package/src/static-handler.ts +4 -1
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/generated-routes.ts +2 -2
- package/src/testing/internal/context.ts +1 -1
- package/src/testing/internal/flight-client-globals.ts +7 -5
- package/src/testing/render-route.tsx +85 -24
- package/src/testing/run-loader.ts +5 -1
- package/src/testing/vitest-stubs/plugin-rsc.ts +123 -20
- package/src/testing/vitest.ts +62 -1
- package/src/theme/ThemeScript.tsx +3 -3
- package/src/types/cache-types.ts +14 -10
- package/src/types/handler-context.ts +14 -0
- package/src/types/loader-types.ts +8 -6
- package/src/urls/response-types.ts +3 -23
- package/src/use-loader.tsx +12 -3
- package/src/vite/plugins/use-cache-transform.ts +118 -74
- package/src/vite/rango.ts +7 -3
package/dist/vite/index.js
CHANGED
|
@@ -22,26 +22,26 @@ function createRangoDebugger(namespace) {
|
|
|
22
22
|
if (shadow.enabled) return shadow;
|
|
23
23
|
return void 0;
|
|
24
24
|
}
|
|
25
|
-
async function timed(
|
|
26
|
-
if (!
|
|
25
|
+
async function timed(debug13, label, fn) {
|
|
26
|
+
if (!debug13) return await fn();
|
|
27
27
|
const start = performance.now();
|
|
28
28
|
try {
|
|
29
29
|
return await fn();
|
|
30
30
|
} finally {
|
|
31
|
-
|
|
31
|
+
debug13("%s (%sms)", label, (performance.now() - start).toFixed(1));
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
function timedSync(
|
|
35
|
-
if (!
|
|
34
|
+
function timedSync(debug13, label, fn) {
|
|
35
|
+
if (!debug13) return fn();
|
|
36
36
|
const start = performance.now();
|
|
37
37
|
try {
|
|
38
38
|
return fn();
|
|
39
39
|
} finally {
|
|
40
|
-
|
|
40
|
+
debug13("%s (%sms)", label, (performance.now() - start).toFixed(1));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
function createCounter(
|
|
44
|
-
if (!
|
|
43
|
+
function createCounter(debug13, label) {
|
|
44
|
+
if (!debug13) return void 0;
|
|
45
45
|
let n = 0;
|
|
46
46
|
let totalMs = 0;
|
|
47
47
|
let slowestMs = 0;
|
|
@@ -75,7 +75,7 @@ function createCounter(debug14, label) {
|
|
|
75
75
|
},
|
|
76
76
|
flush() {
|
|
77
77
|
if (n === 0) return;
|
|
78
|
-
|
|
78
|
+
debug13(
|
|
79
79
|
"%s: %d files, %sms total, slowest %sms %s",
|
|
80
80
|
label,
|
|
81
81
|
n,
|
|
@@ -158,7 +158,7 @@ function transformClientRefs(code, projectRoot) {
|
|
|
158
158
|
return hasReplacement ? result : null;
|
|
159
159
|
}
|
|
160
160
|
function hashClientRefs(projectRoot) {
|
|
161
|
-
const counter = createCounter(
|
|
161
|
+
const counter = createCounter(debug6, "hash-client-refs");
|
|
162
162
|
return {
|
|
163
163
|
name: "@rangojs/router:hash-client-refs",
|
|
164
164
|
enforce: "post",
|
|
@@ -180,12 +180,12 @@ function hashClientRefs(projectRoot) {
|
|
|
180
180
|
}
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
|
-
var
|
|
183
|
+
var debug6, CLIENT_PKG_PROXY_PREFIX, CLIENT_IN_SERVER_PKG_PROXY_PREFIX, FS_PREFIX, REGISTER_CLIENT_REF_RE;
|
|
184
184
|
var init_client_ref_hashing = __esm({
|
|
185
185
|
"src/vite/plugins/client-ref-hashing.ts"() {
|
|
186
186
|
"use strict";
|
|
187
187
|
init_debug();
|
|
188
|
-
|
|
188
|
+
debug6 = createRangoDebugger(NS.transform);
|
|
189
189
|
CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
190
190
|
CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
191
191
|
FS_PREFIX = "/@fs/";
|
|
@@ -193,6 +193,30 @@ var init_client_ref_hashing = __esm({
|
|
|
193
193
|
}
|
|
194
194
|
});
|
|
195
195
|
|
|
196
|
+
// src/internal-debug.ts
|
|
197
|
+
var INTERNAL_RANGO_DEBUG;
|
|
198
|
+
var init_internal_debug = __esm({
|
|
199
|
+
"src/internal-debug.ts"() {
|
|
200
|
+
"use strict";
|
|
201
|
+
INTERNAL_RANGO_DEBUG = typeof process !== "undefined" && Boolean(process.env?.INTERNAL_RANGO_DEBUG);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// src/browser/logging.ts
|
|
206
|
+
function debugLog(msg, ...args) {
|
|
207
|
+
if (INTERNAL_RANGO_DEBUG) {
|
|
208
|
+
console.log(msg, ...args);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
var IS_BROWSER_DEBUG;
|
|
212
|
+
var init_logging = __esm({
|
|
213
|
+
"src/browser/logging.ts"() {
|
|
214
|
+
"use strict";
|
|
215
|
+
init_internal_debug();
|
|
216
|
+
IS_BROWSER_DEBUG = INTERNAL_RANGO_DEBUG;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
196
220
|
// src/browser/notify-listeners.ts
|
|
197
221
|
function notifyListeners(entries, notify, isActive, shouldContinue) {
|
|
198
222
|
const errors = [];
|
|
@@ -627,30 +651,6 @@ var init_policy = __esm({
|
|
|
627
651
|
}
|
|
628
652
|
});
|
|
629
653
|
|
|
630
|
-
// src/internal-debug.ts
|
|
631
|
-
var INTERNAL_RANGO_DEBUG;
|
|
632
|
-
var init_internal_debug = __esm({
|
|
633
|
-
"src/internal-debug.ts"() {
|
|
634
|
-
"use strict";
|
|
635
|
-
INTERNAL_RANGO_DEBUG = typeof process !== "undefined" && Boolean(process.env?.INTERNAL_RANGO_DEBUG);
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
// src/browser/logging.ts
|
|
640
|
-
function debugLog(msg, ...args) {
|
|
641
|
-
if (INTERNAL_RANGO_DEBUG) {
|
|
642
|
-
console.log(msg, ...args);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
var IS_BROWSER_DEBUG;
|
|
646
|
-
var init_logging = __esm({
|
|
647
|
-
"src/browser/logging.ts"() {
|
|
648
|
-
"use strict";
|
|
649
|
-
init_internal_debug();
|
|
650
|
-
IS_BROWSER_DEBUG = INTERNAL_RANGO_DEBUG;
|
|
651
|
-
}
|
|
652
|
-
});
|
|
653
|
-
|
|
654
654
|
// src/redirect-origin.ts
|
|
655
655
|
var init_redirect_origin = __esm({
|
|
656
656
|
"src/redirect-origin.ts"() {
|
|
@@ -3050,17 +3050,12 @@ ${lazyImports.join(",\n")}
|
|
|
3050
3050
|
|
|
3051
3051
|
// src/vite/plugins/use-cache-transform.ts
|
|
3052
3052
|
import path5 from "node:path";
|
|
3053
|
-
import MagicString4 from "magic-string";
|
|
3054
|
-
init_debug();
|
|
3055
|
-
var debug4 = createRangoDebugger(NS.transform);
|
|
3056
3053
|
var CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
3057
3054
|
var LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
3058
3055
|
var USE_CACHE_DIRECTIVE_RE = /^use cache(:\s*[\w-]+)?$/;
|
|
3059
|
-
function useCacheTransform() {
|
|
3056
|
+
function useCacheTransform(counter) {
|
|
3060
3057
|
let projectRoot = "";
|
|
3061
3058
|
let isBuild = false;
|
|
3062
|
-
let rscTransforms = null;
|
|
3063
|
-
const counter = createCounter(debug4, "use-cache");
|
|
3064
3059
|
return {
|
|
3065
3060
|
name: "@rangojs/router:use-cache",
|
|
3066
3061
|
enforce: "post",
|
|
@@ -3073,62 +3068,73 @@ function useCacheTransform() {
|
|
|
3073
3068
|
},
|
|
3074
3069
|
async transform(code, id) {
|
|
3075
3070
|
if (this.environment?.name !== "rsc") return;
|
|
3076
|
-
if (!code
|
|
3077
|
-
if (id.includes("/node_modules/") || id.startsWith("\0")) return;
|
|
3078
|
-
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return;
|
|
3071
|
+
if (!isUseCacheCandidate(code, id)) return;
|
|
3079
3072
|
const start = counter ? performance.now() : 0;
|
|
3080
3073
|
try {
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
rscTransforms = await import("@vitejs/plugin-rsc/transforms");
|
|
3084
|
-
} catch {
|
|
3085
|
-
return;
|
|
3086
|
-
}
|
|
3087
|
-
}
|
|
3088
|
-
const {
|
|
3089
|
-
hasDirective: hasDirective2,
|
|
3090
|
-
transformWrapExport,
|
|
3091
|
-
transformHoistInlineDirective
|
|
3092
|
-
} = rscTransforms;
|
|
3093
|
-
let ast;
|
|
3094
|
-
try {
|
|
3095
|
-
const { parseAst: parseAst6 } = await import("vite");
|
|
3096
|
-
ast = parseAst6(code, { lang: "tsx" });
|
|
3097
|
-
} catch {
|
|
3098
|
-
return;
|
|
3099
|
-
}
|
|
3100
|
-
stripNullDirectiveFields(ast);
|
|
3101
|
-
const filePath = normalizePath(path5.relative(projectRoot, id));
|
|
3102
|
-
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
3103
|
-
if (hasDirective2(ast.body, "use cache")) {
|
|
3104
|
-
return transformFileLevelUseCache(
|
|
3105
|
-
code,
|
|
3106
|
-
ast,
|
|
3107
|
-
filePath,
|
|
3108
|
-
id,
|
|
3109
|
-
isBuild,
|
|
3110
|
-
isLayoutOrTemplate,
|
|
3111
|
-
transformWrapExport,
|
|
3112
|
-
hasDirective2
|
|
3113
|
-
);
|
|
3114
|
-
}
|
|
3115
|
-
const functionResult = transformFunctionLevelUseCache(
|
|
3116
|
-
code,
|
|
3117
|
-
ast,
|
|
3118
|
-
filePath,
|
|
3119
|
-
id,
|
|
3074
|
+
return await transformUseCache(code, id, {
|
|
3075
|
+
root: projectRoot,
|
|
3120
3076
|
isBuild,
|
|
3121
|
-
|
|
3122
|
-
);
|
|
3123
|
-
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
3124
|
-
if (functionResult) return functionResult;
|
|
3077
|
+
warn: (message) => this.warn(message)
|
|
3078
|
+
});
|
|
3125
3079
|
} finally {
|
|
3126
3080
|
counter?.record(id, performance.now() - start);
|
|
3127
3081
|
}
|
|
3128
3082
|
}
|
|
3129
3083
|
};
|
|
3130
3084
|
}
|
|
3131
|
-
function
|
|
3085
|
+
function isUseCacheCandidate(code, id) {
|
|
3086
|
+
return (
|
|
3087
|
+
// Quick bail: no "use cache" in source
|
|
3088
|
+
code.includes("use cache") && // Skip node_modules and virtual modules
|
|
3089
|
+
!id.includes("/node_modules/") && !id.startsWith("\0") && // Only JS/TS files
|
|
3090
|
+
/\.(tsx?|jsx?|mjs)$/.test(id)
|
|
3091
|
+
);
|
|
3092
|
+
}
|
|
3093
|
+
var rscTransforms = null;
|
|
3094
|
+
async function transformUseCache(code, id, options) {
|
|
3095
|
+
if (!rscTransforms) {
|
|
3096
|
+
try {
|
|
3097
|
+
rscTransforms = await import("@vitejs/plugin-rsc/transforms");
|
|
3098
|
+
} catch (error) {
|
|
3099
|
+
options.onTransformsError?.(error);
|
|
3100
|
+
return;
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
const { hasDirective: hasDirective2, transformWrapExport, transformHoistInlineDirective } = rscTransforms;
|
|
3104
|
+
let ast;
|
|
3105
|
+
try {
|
|
3106
|
+
const { parseAst: parseAst6 } = await import("vite");
|
|
3107
|
+
ast = parseAst6(code, { lang: "tsx" });
|
|
3108
|
+
} catch {
|
|
3109
|
+
return;
|
|
3110
|
+
}
|
|
3111
|
+
stripNullDirectiveFields(ast);
|
|
3112
|
+
const filePath = normalizePath(path5.relative(options.root, id));
|
|
3113
|
+
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
3114
|
+
if (hasDirective2(ast.body, "use cache")) {
|
|
3115
|
+
return transformFileLevelUseCache(
|
|
3116
|
+
code,
|
|
3117
|
+
ast,
|
|
3118
|
+
filePath,
|
|
3119
|
+
id,
|
|
3120
|
+
options.isBuild,
|
|
3121
|
+
isLayoutOrTemplate,
|
|
3122
|
+
transformWrapExport,
|
|
3123
|
+
hasDirective2
|
|
3124
|
+
);
|
|
3125
|
+
}
|
|
3126
|
+
const functionResult = transformFunctionLevelUseCache(
|
|
3127
|
+
code,
|
|
3128
|
+
ast,
|
|
3129
|
+
filePath,
|
|
3130
|
+
id,
|
|
3131
|
+
options.isBuild,
|
|
3132
|
+
transformHoistInlineDirective
|
|
3133
|
+
);
|
|
3134
|
+
warnOnNearMissDirectives(ast, id, options.warn);
|
|
3135
|
+
if (functionResult) return functionResult;
|
|
3136
|
+
}
|
|
3137
|
+
async function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild, isLayoutOrTemplate, transformWrapExport, hasDirective2) {
|
|
3132
3138
|
const unconfirmedExports = [];
|
|
3133
3139
|
const { exportNames, output } = transformWrapExport(code, ast, {
|
|
3134
3140
|
runtime: (value, name) => {
|
|
@@ -3157,6 +3163,7 @@ function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild, isLa
|
|
|
3157
3163
|
);
|
|
3158
3164
|
}
|
|
3159
3165
|
if (exportNames.length === 0) {
|
|
3166
|
+
const { default: MagicString4 } = await import("magic-string");
|
|
3160
3167
|
const s = new MagicString4(code);
|
|
3161
3168
|
const directive2 = findFileLevelDirective(ast);
|
|
3162
3169
|
if (directive2) {
|
|
@@ -3285,7 +3292,7 @@ function warnOnNearMissDirectives(ast, fileId, warn) {
|
|
|
3285
3292
|
init_debug();
|
|
3286
3293
|
import { existsSync, readFileSync } from "node:fs";
|
|
3287
3294
|
import { isAbsolute, join, normalize, relative } from "node:path";
|
|
3288
|
-
var
|
|
3295
|
+
var debug4 = createRangoDebugger(NS.transform);
|
|
3289
3296
|
var CLIENT_IN_SERVER_PROXY_PREFIX = "virtual:vite-rsc/client-in-server-package-proxy/";
|
|
3290
3297
|
var DEDUP_PREFIX = "\0rango:dedup/";
|
|
3291
3298
|
function extractPackageName(absolutePath) {
|
|
@@ -3462,8 +3469,8 @@ function clientRefDedup() {
|
|
|
3462
3469
|
resolvePackage = config.createResolver({ scan: true });
|
|
3463
3470
|
},
|
|
3464
3471
|
buildEnd() {
|
|
3465
|
-
if (
|
|
3466
|
-
|
|
3472
|
+
if (debug4 && dedupedPackages.size > 0) {
|
|
3473
|
+
debug4(
|
|
3467
3474
|
"client-ref-dedup: redirected %d package(s) (%s)",
|
|
3468
3475
|
dedupedPackages.size,
|
|
3469
3476
|
[...dedupedPackages].join(",")
|
|
@@ -3505,7 +3512,7 @@ function clientRefDedup() {
|
|
|
3505
3512
|
}
|
|
3506
3513
|
return specifierPromise.then((specifier) => {
|
|
3507
3514
|
if (!specifier) return;
|
|
3508
|
-
if (
|
|
3515
|
+
if (debug4) dedupedPackages.add(packageName);
|
|
3509
3516
|
return `${DEDUP_PREFIX}${encodeURIComponent(specifier)}`;
|
|
3510
3517
|
});
|
|
3511
3518
|
},
|
|
@@ -3795,7 +3802,7 @@ import { resolve } from "node:path";
|
|
|
3795
3802
|
// package.json
|
|
3796
3803
|
var package_default = {
|
|
3797
3804
|
name: "@rangojs/router",
|
|
3798
|
-
version: "0.
|
|
3805
|
+
version: "0.17.0",
|
|
3799
3806
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
3800
3807
|
keywords: [
|
|
3801
3808
|
"react",
|
|
@@ -4006,7 +4013,7 @@ var package_default = {
|
|
|
4006
4013
|
"@opentelemetry/api": "^1.9.0",
|
|
4007
4014
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
4008
4015
|
"@opentelemetry/sdk-trace-base": "^2.9.0",
|
|
4009
|
-
"@playwright/test": "^1.
|
|
4016
|
+
"@playwright/test": "^1.62.0",
|
|
4010
4017
|
"@shared/e2e": "workspace:*",
|
|
4011
4018
|
"@testing-library/dom": "^10.4.1",
|
|
4012
4019
|
"@testing-library/react": "^16.3.2",
|
|
@@ -5482,7 +5489,7 @@ import { isAbsolute as isAbsolute2, resolve as resolve4 } from "node:path";
|
|
|
5482
5489
|
// src/vite/plugins/performance-tracks.ts
|
|
5483
5490
|
init_debug();
|
|
5484
5491
|
import { readFile } from "node:fs/promises";
|
|
5485
|
-
var
|
|
5492
|
+
var debug5 = createRangoDebugger(NS.transform);
|
|
5486
5493
|
var RSDW_PATCH_RE = /((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
5487
5494
|
function buildPatchReplacement(match, debugInfoVar) {
|
|
5488
5495
|
return `${match}
|
|
@@ -5517,7 +5524,7 @@ function performanceTracksOptimizeDepsPlugin() {
|
|
|
5517
5524
|
};
|
|
5518
5525
|
}
|
|
5519
5526
|
function performanceTracksPlugin() {
|
|
5520
|
-
const counter = createCounter(
|
|
5527
|
+
const counter = createCounter(debug5, "performance-tracks");
|
|
5521
5528
|
return {
|
|
5522
5529
|
name: "@rangojs/router:performance-tracks",
|
|
5523
5530
|
buildEnd() {
|
|
@@ -5529,7 +5536,7 @@ function performanceTracksPlugin() {
|
|
|
5529
5536
|
try {
|
|
5530
5537
|
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
5531
5538
|
if (!patched.debugInfoVar) return;
|
|
5532
|
-
|
|
5539
|
+
debug5?.("patched RSDW client (var: %s)", patched.debugInfoVar);
|
|
5533
5540
|
return patched.code;
|
|
5534
5541
|
} finally {
|
|
5535
5542
|
counter?.record(id, performance.now() - start);
|
|
@@ -6060,7 +6067,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
6060
6067
|
|
|
6061
6068
|
// src/vite/plugins/cjs-to-esm.ts
|
|
6062
6069
|
init_debug();
|
|
6063
|
-
var
|
|
6070
|
+
var debug7 = createRangoDebugger(NS.transform);
|
|
6064
6071
|
function createCjsToEsmPlugin() {
|
|
6065
6072
|
let isProduction = false;
|
|
6066
6073
|
return {
|
|
@@ -6074,7 +6081,7 @@ function createCjsToEsmPlugin() {
|
|
|
6074
6081
|
if (cleanId.includes("vendor/react-server-dom/client.browser.js")) {
|
|
6075
6082
|
const isProd = isProduction;
|
|
6076
6083
|
const cjsFile = isProd ? "./cjs/react-server-dom-webpack-client.browser.production.js" : "./cjs/react-server-dom-webpack-client.browser.development.js";
|
|
6077
|
-
|
|
6084
|
+
debug7?.("cjs-to-esm entry redirect %s", id);
|
|
6078
6085
|
return {
|
|
6079
6086
|
code: `export * from "${cjsFile}";`,
|
|
6080
6087
|
map: null
|
|
@@ -6110,7 +6117,7 @@ function createCjsToEsmPlugin() {
|
|
|
6110
6117
|
"export const $1 ="
|
|
6111
6118
|
);
|
|
6112
6119
|
transformed = license + "\n" + transformed;
|
|
6113
|
-
|
|
6120
|
+
debug7?.("cjs-to-esm body rewrite %s", id);
|
|
6114
6121
|
return {
|
|
6115
6122
|
code: transformed,
|
|
6116
6123
|
map: null
|
|
@@ -6138,17 +6145,35 @@ var DEV_DISCOVERY_EPOCH_HEADER = "x-rango-dev-discovery-epoch";
|
|
|
6138
6145
|
import React from "react";
|
|
6139
6146
|
|
|
6140
6147
|
// src/server/context.ts
|
|
6148
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
6149
|
+
|
|
6150
|
+
// src/cache/cache-exec-scope.ts
|
|
6141
6151
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6152
|
+
|
|
6153
|
+
// src/cache/taint.ts
|
|
6154
|
+
var cacheExecScopeProbe = () => false;
|
|
6155
|
+
function _setCacheExecScopeProbe(probe) {
|
|
6156
|
+
cacheExecScopeProbe = probe;
|
|
6157
|
+
}
|
|
6158
|
+
|
|
6159
|
+
// src/cache/cache-exec-scope.ts
|
|
6160
|
+
var cacheExecStorage = new AsyncLocalStorage();
|
|
6161
|
+
function isInsideCacheExecScope() {
|
|
6162
|
+
return cacheExecStorage.getStore() !== void 0;
|
|
6163
|
+
}
|
|
6164
|
+
_setCacheExecScopeProbe(isInsideCacheExecScope);
|
|
6165
|
+
|
|
6166
|
+
// src/server/context.ts
|
|
6142
6167
|
var RSC_CONTEXT_KEY = /* @__PURE__ */ Symbol.for("rangojs-router:rsc-context");
|
|
6143
|
-
var RangoContext = globalThis[RSC_CONTEXT_KEY] ??= new
|
|
6168
|
+
var RangoContext = globalThis[RSC_CONTEXT_KEY] ??= new AsyncLocalStorage2();
|
|
6144
6169
|
var LOADER_SCOPE_KEY = /* @__PURE__ */ Symbol.for("rangojs-router:loader-scope");
|
|
6145
|
-
var loaderScopeALS = globalThis[LOADER_SCOPE_KEY] ??= new
|
|
6170
|
+
var loaderScopeALS = globalThis[LOADER_SCOPE_KEY] ??= new AsyncLocalStorage2();
|
|
6146
6171
|
var LOADER_BODY_SCOPE_KEY = /* @__PURE__ */ Symbol.for("rangojs-router:loader-body-scope");
|
|
6147
|
-
var loaderBodyScopeALS = globalThis[LOADER_BODY_SCOPE_KEY] ??= new
|
|
6172
|
+
var loaderBodyScopeALS = globalThis[LOADER_BODY_SCOPE_KEY] ??= new AsyncLocalStorage2();
|
|
6148
6173
|
var PUSH_CALLBACK_SCOPE_KEY = /* @__PURE__ */ Symbol.for(
|
|
6149
6174
|
"rangojs-router:push-callback-scope"
|
|
6150
6175
|
);
|
|
6151
|
-
var pushCallbackScopeALS = globalThis[PUSH_CALLBACK_SCOPE_KEY] ??= new
|
|
6176
|
+
var pushCallbackScopeALS = globalThis[PUSH_CALLBACK_SCOPE_KEY] ??= new AsyncLocalStorage2();
|
|
6152
6177
|
|
|
6153
6178
|
// src/rsc/shell-capture-constants.ts
|
|
6154
6179
|
var SHELL_CAPTURE_MAX_WAIT_MS = 15e3;
|
|
@@ -6325,7 +6350,7 @@ init_client_ref_hashing();
|
|
|
6325
6350
|
// src/vite/plugins/server-ref-hashing.ts
|
|
6326
6351
|
init_debug();
|
|
6327
6352
|
init_client_ref_hashing();
|
|
6328
|
-
var
|
|
6353
|
+
var debug8 = createRangoDebugger(NS.transform);
|
|
6329
6354
|
function transformServerRefs(code, projectRoot) {
|
|
6330
6355
|
if (!code.includes("registerServerReference")) return null;
|
|
6331
6356
|
let hasReplacement = false;
|
|
@@ -6342,7 +6367,7 @@ function transformServerRefs(code, projectRoot) {
|
|
|
6342
6367
|
return hasReplacement ? result : null;
|
|
6343
6368
|
}
|
|
6344
6369
|
function hashServerRefs(projectRoot) {
|
|
6345
|
-
const counter = createCounter(
|
|
6370
|
+
const counter = createCounter(debug8, "hash-server-refs");
|
|
6346
6371
|
return {
|
|
6347
6372
|
name: "@rangojs/router:hash-server-refs",
|
|
6348
6373
|
enforce: "post",
|
|
@@ -7207,11 +7232,11 @@ function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
|
7207
7232
|
|
|
7208
7233
|
// src/vite/discovery/prerender-collection.ts
|
|
7209
7234
|
init_debug();
|
|
7210
|
-
var
|
|
7235
|
+
var debug9 = createRangoDebugger(NS.prerender);
|
|
7211
7236
|
async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
7212
7237
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode) return;
|
|
7213
|
-
const overallStart =
|
|
7214
|
-
|
|
7238
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
7239
|
+
debug9?.(
|
|
7215
7240
|
"expandPrerenderRoutes: start (%d router manifest(s))",
|
|
7216
7241
|
allManifests.length
|
|
7217
7242
|
);
|
|
@@ -7264,7 +7289,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
7264
7289
|
});
|
|
7265
7290
|
} else {
|
|
7266
7291
|
if (def?.getParams) {
|
|
7267
|
-
const getParamsStart =
|
|
7292
|
+
const getParamsStart = debug9 ? performance.now() : 0;
|
|
7268
7293
|
try {
|
|
7269
7294
|
const buildVars = {};
|
|
7270
7295
|
const buildEnv = state.resolvedBuildEnv;
|
|
@@ -7283,7 +7308,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
7283
7308
|
}
|
|
7284
7309
|
};
|
|
7285
7310
|
const paramsList = await def.getParams(getParamsCtx);
|
|
7286
|
-
|
|
7311
|
+
debug9?.(
|
|
7287
7312
|
"getParams %s -> %d params (%sms)",
|
|
7288
7313
|
routeName,
|
|
7289
7314
|
paramsList.length,
|
|
@@ -7355,7 +7380,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
7355
7380
|
}
|
|
7356
7381
|
}
|
|
7357
7382
|
if (entries.length === 0) {
|
|
7358
|
-
|
|
7383
|
+
debug9?.(
|
|
7359
7384
|
"no prerender entries (done in %sms)",
|
|
7360
7385
|
(performance.now() - overallStart).toFixed(1)
|
|
7361
7386
|
);
|
|
@@ -7366,7 +7391,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
7366
7391
|
console.log(
|
|
7367
7392
|
`[rango] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
7368
7393
|
);
|
|
7369
|
-
|
|
7394
|
+
debug9?.(
|
|
7370
7395
|
"prerender loop: %d entries, max concurrency %d",
|
|
7371
7396
|
entries.length,
|
|
7372
7397
|
maxConcurrency
|
|
@@ -7474,7 +7499,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
7474
7499
|
console.log(
|
|
7475
7500
|
`[rango] Pre-render complete: ${parts.join(", ")} (${totalElapsed}ms total)`
|
|
7476
7501
|
);
|
|
7477
|
-
|
|
7502
|
+
debug9?.(
|
|
7478
7503
|
"expandPrerenderRoutes done: %d done, %d skipped, %sms (overall %sms)",
|
|
7479
7504
|
doneCount,
|
|
7480
7505
|
skipCount,
|
|
@@ -7485,8 +7510,8 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
7485
7510
|
async function renderStaticHandlers(state, rscEnv, registry) {
|
|
7486
7511
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
|
|
7487
7512
|
return;
|
|
7488
|
-
const overallStart =
|
|
7489
|
-
|
|
7513
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
7514
|
+
debug9?.(
|
|
7490
7515
|
"renderStaticHandlers: start (%d static module(s))",
|
|
7491
7516
|
state.resolvedStaticModules.size
|
|
7492
7517
|
);
|
|
@@ -7576,7 +7601,7 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
7576
7601
|
console.log(
|
|
7577
7602
|
`[rango] Static render complete: ${staticParts.join(", ")} (${totalStaticElapsed}ms total)`
|
|
7578
7603
|
);
|
|
7579
|
-
|
|
7604
|
+
debug9?.(
|
|
7580
7605
|
"renderStaticHandlers done: %d done, %d skipped, %sms (overall %sms)",
|
|
7581
7606
|
staticDone,
|
|
7582
7607
|
staticSkip,
|
|
@@ -7707,1313 +7732,1316 @@ import {
|
|
|
7707
7732
|
Suspense as Suspense2
|
|
7708
7733
|
} from "react";
|
|
7709
7734
|
|
|
7710
|
-
// src/
|
|
7711
|
-
import { createContext } from "react";
|
|
7712
|
-
var OutletContext = createContext(null);
|
|
7713
|
-
|
|
7714
|
-
// src/route-content-wrapper.tsx
|
|
7715
|
-
import { Component, Suspense, use } from "react";
|
|
7716
|
-
|
|
7717
|
-
// src/outlet-provider.tsx
|
|
7718
|
-
import { useContext, useMemo } from "react";
|
|
7719
|
-
import { jsx } from "react/jsx-runtime";
|
|
7720
|
-
|
|
7721
|
-
// src/decode-loader-results.ts
|
|
7722
|
-
import { createElement as createElement2 } from "react";
|
|
7723
|
-
|
|
7724
|
-
// src/loader-redirect.tsx
|
|
7725
|
-
import { useEffect } from "react";
|
|
7726
|
-
|
|
7727
|
-
// src/browser/react/use-router.ts
|
|
7728
|
-
import { useContext as useContext3, useMemo as useMemo2 } from "react";
|
|
7729
|
-
|
|
7730
|
-
// src/browser/react/context.ts
|
|
7731
|
-
import { createContext as createContext2 } from "react";
|
|
7732
|
-
var NavigationStoreContext = createContext2(null);
|
|
7733
|
-
|
|
7734
|
-
// src/browser/react/use-mount.ts
|
|
7735
|
-
import { useContext as useContext2 } from "react";
|
|
7736
|
-
|
|
7737
|
-
// src/browser/react/mount-context.ts
|
|
7738
|
-
import {
|
|
7739
|
-
createContext as createContext3,
|
|
7740
|
-
createElement
|
|
7741
|
-
} from "react";
|
|
7742
|
-
var MountContext = createContext3("/");
|
|
7743
|
-
|
|
7744
|
-
// src/browser/react/use-router.ts
|
|
7745
|
-
init_loader();
|
|
7746
|
-
|
|
7747
|
-
// src/browser/app-version.ts
|
|
7748
|
-
var currentVersion2;
|
|
7749
|
-
function getAppVersion() {
|
|
7750
|
-
return currentVersion2;
|
|
7751
|
-
}
|
|
7752
|
-
|
|
7753
|
-
// src/loader-redirect.tsx
|
|
7754
|
-
init_validate_redirect_origin();
|
|
7755
|
-
init_redirect_origin();
|
|
7756
|
-
|
|
7757
|
-
// src/route-content-wrapper.tsx
|
|
7758
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
7759
|
-
|
|
7760
|
-
// src/use-loader.tsx
|
|
7735
|
+
// src/browser/react/use-handle.ts
|
|
7761
7736
|
import {
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
useCallback,
|
|
7766
|
-
useContext as useContext4,
|
|
7767
|
-
useEffect as useEffect2,
|
|
7768
|
-
useMemo as useMemo3,
|
|
7769
|
-
useOptimistic,
|
|
7737
|
+
useContext,
|
|
7738
|
+
useState,
|
|
7739
|
+
useEffect,
|
|
7770
7740
|
useRef,
|
|
7771
|
-
|
|
7741
|
+
useOptimistic,
|
|
7742
|
+
startTransition
|
|
7772
7743
|
} from "react";
|
|
7773
7744
|
|
|
7774
|
-
// src/
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7745
|
+
// src/missing-id-error.ts
|
|
7746
|
+
var SELF_FILES = /* @__PURE__ */ new Set([
|
|
7747
|
+
"missing-id-error",
|
|
7748
|
+
"loader",
|
|
7749
|
+
"loader.rsc",
|
|
7750
|
+
"handle"
|
|
7751
|
+
]);
|
|
7752
|
+
function findUserCallSite() {
|
|
7753
|
+
try {
|
|
7754
|
+
const stack = new Error().stack;
|
|
7755
|
+
if (!stack) return void 0;
|
|
7756
|
+
for (const frame of stack.split("\n").slice(1)) {
|
|
7757
|
+
const m = frame.match(
|
|
7758
|
+
/(?:\(|@|\s)(?:file:\/\/)?((?:\/|[A-Za-z]:[\\/])[^()\s]+?\.(?:ts|tsx|js|jsx|mts|cts)):(\d+):(\d+)\)?/
|
|
7759
|
+
);
|
|
7760
|
+
if (!m) continue;
|
|
7761
|
+
const path6 = m[1];
|
|
7762
|
+
if (path6.includes("node_modules") || path6.includes("@rangojs/router")) {
|
|
7763
|
+
continue;
|
|
7764
|
+
}
|
|
7765
|
+
const base = path6.split(/[\\/]/).pop().replace(/\.(?:ts|tsx|js|jsx|mts|cts)$/, "");
|
|
7766
|
+
if (SELF_FILES.has(base)) continue;
|
|
7767
|
+
return `${path6}:${m[2]}:${m[3]}`;
|
|
7768
|
+
}
|
|
7769
|
+
} catch {
|
|
7770
|
+
}
|
|
7771
|
+
return void 0;
|
|
7772
|
+
}
|
|
7773
|
+
function missingInjectedIdError(kind, fnName) {
|
|
7774
|
+
const site = findUserCallSite();
|
|
7775
|
+
const at = site ? ` (created at ${site})` : "";
|
|
7776
|
+
return new Error(
|
|
7777
|
+
`[rango] ${kind} is missing $$id${at}.
|
|
7778
|
+
The @rangojs/router:expose-internal-ids Vite transform injects ${fnName}()'s stable $$id from an EXPORTED const declaration only:
|
|
7779
|
+
export const X = ${fnName}(...)
|
|
7780
|
+
const X = ${fnName}(...); export { X }
|
|
7781
|
+
A non-exported const, an \`export let/var\`, or an inline ${fnName}(...) call gets no $$id \u2014 export it as \`export const\`. (A matching "Unsupported ${fnName} shape" warning names the exact file:line.)`
|
|
7782
|
+
);
|
|
7778
7783
|
}
|
|
7779
7784
|
|
|
7780
|
-
// src/
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
hasValue: false,
|
|
7784
|
-
error: null,
|
|
7785
|
-
isLoading: false,
|
|
7786
|
-
requestId: 0
|
|
7787
|
-
});
|
|
7788
|
-
function normalizeGroups(group) {
|
|
7789
|
-
if (group === void 0) return [];
|
|
7790
|
-
if (typeof group === "string") return [group];
|
|
7791
|
-
return [...new Set(group)];
|
|
7785
|
+
// src/handle.ts
|
|
7786
|
+
function defaultCollect(segments) {
|
|
7787
|
+
return segments;
|
|
7792
7788
|
}
|
|
7793
|
-
var
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
* lands (use-loader.tsx). The new tree's own read of the loader suspends at
|
|
7807
|
-
* the read site and never observes the flag. A Set, not a flag: overlapping
|
|
7808
|
-
* navigations (second click before the first stream lands) keep the family
|
|
7809
|
-
* pending until the LAST stream settles.
|
|
7810
|
-
*/
|
|
7811
|
-
this.pendingStreams = /* @__PURE__ */ new Map();
|
|
7812
|
-
}
|
|
7813
|
-
getOrCreate(bucketKey) {
|
|
7814
|
-
let e = this.entries.get(bucketKey);
|
|
7815
|
-
if (!e) {
|
|
7816
|
-
e = {
|
|
7817
|
-
snapshot: EMPTY_SNAPSHOT,
|
|
7818
|
-
listeners: /* @__PURE__ */ new Set(),
|
|
7819
|
-
latestRequestId: 0,
|
|
7820
|
-
loaderId: bucketKey,
|
|
7821
|
-
sticky: false,
|
|
7822
|
-
pendingClear: false,
|
|
7823
|
-
clearWhenSettled: false,
|
|
7824
|
-
groups: /* @__PURE__ */ new Map(),
|
|
7825
|
-
refetch: void 0,
|
|
7826
|
-
streamPendingListeners: /* @__PURE__ */ new Set()
|
|
7827
|
-
};
|
|
7828
|
-
this.entries.set(bucketKey, e);
|
|
7789
|
+
var collectRegistry = /* @__PURE__ */ new Map();
|
|
7790
|
+
var runtimeHandleIdCounter = 0;
|
|
7791
|
+
function createHandle(collect, __injectedId) {
|
|
7792
|
+
let handleId = __injectedId ?? "";
|
|
7793
|
+
if (!handleId) {
|
|
7794
|
+
if (isUnderTestRunner()) {
|
|
7795
|
+
handleId = `__rango_runtime_handle_${runtimeHandleIdCounter++}`;
|
|
7796
|
+
} else if (process.env.NODE_ENV !== "production") {
|
|
7797
|
+
throw missingInjectedIdError("Handle", "createHandle");
|
|
7798
|
+
} else {
|
|
7799
|
+
throw new Error(
|
|
7800
|
+
"[rango] Handle is missing $$id \u2014 the build plugin did not inject one. Export it as `export const X = createHandle(...)`."
|
|
7801
|
+
);
|
|
7829
7802
|
}
|
|
7830
|
-
return e;
|
|
7831
7803
|
}
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7804
|
+
const collectFn = collect ?? defaultCollect;
|
|
7805
|
+
collectRegistry.set(
|
|
7806
|
+
handleId,
|
|
7807
|
+
collectFn
|
|
7808
|
+
);
|
|
7809
|
+
return {
|
|
7810
|
+
__brand: "handle",
|
|
7811
|
+
$$id: handleId
|
|
7812
|
+
};
|
|
7813
|
+
}
|
|
7814
|
+
|
|
7815
|
+
// src/browser/react/context.ts
|
|
7816
|
+
import { createContext } from "react";
|
|
7817
|
+
var NavigationStoreContext = createContext(null);
|
|
7818
|
+
|
|
7819
|
+
// src/handles/meta.ts
|
|
7820
|
+
function isUnsetDescriptor(descriptor) {
|
|
7821
|
+
return typeof descriptor === "object" && descriptor !== null && "unset" in descriptor && typeof descriptor.unset === "string";
|
|
7822
|
+
}
|
|
7823
|
+
function isTitleDescriptor(descriptor) {
|
|
7824
|
+
return typeof descriptor === "object" && descriptor !== null && "title" in descriptor;
|
|
7825
|
+
}
|
|
7826
|
+
function isTitleTemplate(title) {
|
|
7827
|
+
return typeof title === "object" && title !== null && "template" in title && "default" in title;
|
|
7828
|
+
}
|
|
7829
|
+
function isAbsoluteTitle(title) {
|
|
7830
|
+
return typeof title === "object" && title !== null && "absolute" in title;
|
|
7831
|
+
}
|
|
7832
|
+
function getMetaKey(descriptor) {
|
|
7833
|
+
if (isUnsetDescriptor(descriptor)) {
|
|
7834
|
+
return void 0;
|
|
7839
7835
|
}
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
* Returns an unsubscribe function. A sticky bucket's entry is kept around even
|
|
7843
|
-
* after the last subscriber leaves so that an in-flight `load()` can still
|
|
7844
|
-
* commit if the consumer remounts. An ephemeral bucket is dropped once its
|
|
7845
|
-
* last subscriber leaves (deferred, see maybeScheduleRefcountClear).
|
|
7846
|
-
*/
|
|
7847
|
-
subscribe(bucketKey, cb, options) {
|
|
7848
|
-
const e = this.getOrCreate(bucketKey);
|
|
7849
|
-
const loaderId = options?.loaderId ?? bucketKey;
|
|
7850
|
-
e.loaderId = loaderId;
|
|
7851
|
-
this.registerFamily(loaderId, bucketKey);
|
|
7852
|
-
if (options?.ephemeral !== true) e.sticky = true;
|
|
7853
|
-
const groups = normalizeGroups(options?.group);
|
|
7854
|
-
for (const group of groups) {
|
|
7855
|
-
this.addToGroup(group, bucketKey, e, options?.refetch);
|
|
7856
|
-
}
|
|
7857
|
-
e.pendingClear = false;
|
|
7858
|
-
e.clearWhenSettled = false;
|
|
7859
|
-
e.listeners.add(cb);
|
|
7860
|
-
const onStreamPending = options?.onStreamPending;
|
|
7861
|
-
if (onStreamPending) e.streamPendingListeners.add(onStreamPending);
|
|
7862
|
-
return () => {
|
|
7863
|
-
e.listeners.delete(cb);
|
|
7864
|
-
if (onStreamPending) e.streamPendingListeners.delete(onStreamPending);
|
|
7865
|
-
for (const group of groups) this.releaseGroup(group, bucketKey, e);
|
|
7866
|
-
this.maybeScheduleRefcountClear(bucketKey, e);
|
|
7867
|
-
};
|
|
7836
|
+
if ("charSet" in descriptor) {
|
|
7837
|
+
return "charSet";
|
|
7868
7838
|
}
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
if (refetch) e.refetch = refetch;
|
|
7872
|
-
let members = this.groups.get(group);
|
|
7873
|
-
if (!members) {
|
|
7874
|
-
members = /* @__PURE__ */ new Set();
|
|
7875
|
-
this.groups.set(group, members);
|
|
7876
|
-
}
|
|
7877
|
-
members.add(bucketKey);
|
|
7839
|
+
if ("title" in descriptor) {
|
|
7840
|
+
return "title";
|
|
7878
7841
|
}
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
if (next > 0) {
|
|
7882
|
-
e.groups.set(group, next);
|
|
7883
|
-
return;
|
|
7884
|
-
}
|
|
7885
|
-
e.groups.delete(group);
|
|
7886
|
-
const members = this.groups.get(group);
|
|
7887
|
-
if (members) {
|
|
7888
|
-
members.delete(bucketKey);
|
|
7889
|
-
if (members.size === 0) this.groups.delete(group);
|
|
7890
|
-
}
|
|
7842
|
+
if ("name" in descriptor && "content" in descriptor) {
|
|
7843
|
+
return `name:${descriptor.name}`;
|
|
7891
7844
|
}
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
|
|
7898
|
-
|
|
7845
|
+
if ("property" in descriptor && "content" in descriptor) {
|
|
7846
|
+
return `property:${descriptor.property}`;
|
|
7847
|
+
}
|
|
7848
|
+
if ("httpEquiv" in descriptor && "content" in descriptor) {
|
|
7849
|
+
return `httpEquiv:${descriptor.httpEquiv}`;
|
|
7850
|
+
}
|
|
7851
|
+
if ("script:ld+json" in descriptor) {
|
|
7852
|
+
return void 0;
|
|
7853
|
+
}
|
|
7854
|
+
if ("tagName" in descriptor) {
|
|
7855
|
+
if (descriptor.tagName === "link" && "rel" in descriptor) {
|
|
7856
|
+
const uniqueRels = ["canonical", "icon", "apple-touch-icon"];
|
|
7857
|
+
if (uniqueRels.includes(descriptor.rel)) {
|
|
7858
|
+
return `link:${descriptor.rel}`;
|
|
7899
7859
|
}
|
|
7900
7860
|
}
|
|
7901
|
-
|
|
7861
|
+
return void 0;
|
|
7902
7862
|
}
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
for (const name of names) {
|
|
7916
|
-
const members = this.groups.get(name);
|
|
7917
|
-
if (!members) continue;
|
|
7918
|
-
for (const bucketKey of members) buckets.add(bucketKey);
|
|
7919
|
-
}
|
|
7920
|
-
if (buckets.size === 0) return;
|
|
7921
|
-
const thunks = [];
|
|
7922
|
-
for (const bucketKey of buckets) {
|
|
7923
|
-
const e = this.entries.get(bucketKey);
|
|
7924
|
-
if (!e || e.listeners.size === 0 || !e.refetch) continue;
|
|
7925
|
-
thunks.push(e.refetch);
|
|
7926
|
-
}
|
|
7927
|
-
if (thunks.length === 0) return;
|
|
7928
|
-
const results = await Promise.allSettled(thunks.map((t) => t()));
|
|
7929
|
-
const reasons = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
7930
|
-
if (reasons.length > 0) {
|
|
7931
|
-
const label = names.map((n) => `"${n}"`).join(", ");
|
|
7932
|
-
throw new AggregateError(
|
|
7933
|
-
reasons,
|
|
7934
|
-
`refreshGroups(${label}) had ${reasons.length} failure(s)`
|
|
7935
|
-
);
|
|
7863
|
+
return void 0;
|
|
7864
|
+
}
|
|
7865
|
+
var defaultMetaDescriptors = [
|
|
7866
|
+
{ charSet: "utf-8" },
|
|
7867
|
+
{ name: "viewport", content: "width=device-width, initial-scale=1" }
|
|
7868
|
+
];
|
|
7869
|
+
function addOrReplace(result, keyToIndex, descriptor, key) {
|
|
7870
|
+
if (key !== void 0 && keyToIndex.has(key)) {
|
|
7871
|
+
result[keyToIndex.get(key)] = descriptor;
|
|
7872
|
+
} else {
|
|
7873
|
+
if (key !== void 0) {
|
|
7874
|
+
keyToIndex.set(key, result.length);
|
|
7936
7875
|
}
|
|
7876
|
+
result.push(descriptor);
|
|
7937
7877
|
}
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
if (e.listeners.size > 0) return;
|
|
7945
|
-
if (e.sticky) return;
|
|
7946
|
-
if (e.pendingClear) return;
|
|
7947
|
-
e.pendingClear = true;
|
|
7948
|
-
queueMicrotask(() => {
|
|
7949
|
-
if (!e.pendingClear) return;
|
|
7950
|
-
e.pendingClear = false;
|
|
7951
|
-
if (e.listeners.size > 0) return;
|
|
7952
|
-
if (e.snapshot.isLoading) {
|
|
7953
|
-
e.clearWhenSettled = true;
|
|
7954
|
-
return;
|
|
7955
|
-
}
|
|
7956
|
-
this.dropBucket(bucketKey);
|
|
7957
|
-
});
|
|
7878
|
+
}
|
|
7879
|
+
function updateIndicesAfterRemoval(keyToIndex, removedIndex) {
|
|
7880
|
+
for (const [key, index] of keyToIndex) {
|
|
7881
|
+
if (index > removedIndex) {
|
|
7882
|
+
keyToIndex.set(key, index - 1);
|
|
7883
|
+
}
|
|
7958
7884
|
}
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
const
|
|
7966
|
-
if (
|
|
7967
|
-
|
|
7968
|
-
if (fam.size === 0) this.families.delete(e.loaderId);
|
|
7885
|
+
}
|
|
7886
|
+
function collectMeta(segments) {
|
|
7887
|
+
const result = [];
|
|
7888
|
+
const keyToIndex = /* @__PURE__ */ new Map();
|
|
7889
|
+
let titleTemplate;
|
|
7890
|
+
for (const descriptor of defaultMetaDescriptors) {
|
|
7891
|
+
const key = getMetaKey(descriptor);
|
|
7892
|
+
if (key !== void 0) {
|
|
7893
|
+
keyToIndex.set(key, result.length);
|
|
7969
7894
|
}
|
|
7895
|
+
result.push(descriptor);
|
|
7970
7896
|
}
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7897
|
+
for (const descriptors of segments) {
|
|
7898
|
+
for (const descriptor of descriptors) {
|
|
7899
|
+
if (isUnsetDescriptor(descriptor)) {
|
|
7900
|
+
const keyToRemove = descriptor.unset;
|
|
7901
|
+
if (keyToIndex.has(keyToRemove)) {
|
|
7902
|
+
const idx = keyToIndex.get(keyToRemove);
|
|
7903
|
+
result.splice(idx, 1);
|
|
7904
|
+
keyToIndex.delete(keyToRemove);
|
|
7905
|
+
updateIndicesAfterRemoval(keyToIndex, idx);
|
|
7906
|
+
}
|
|
7907
|
+
continue;
|
|
7908
|
+
}
|
|
7909
|
+
if (isTitleDescriptor(descriptor)) {
|
|
7910
|
+
const titleValue = descriptor.title;
|
|
7911
|
+
if (isTitleTemplate(titleValue)) {
|
|
7912
|
+
titleTemplate = titleValue.template;
|
|
7913
|
+
addOrReplace(
|
|
7914
|
+
result,
|
|
7915
|
+
keyToIndex,
|
|
7916
|
+
{ title: titleValue.default },
|
|
7917
|
+
"title"
|
|
7918
|
+
);
|
|
7919
|
+
continue;
|
|
7920
|
+
}
|
|
7921
|
+
if (isAbsoluteTitle(titleValue)) {
|
|
7922
|
+
addOrReplace(
|
|
7923
|
+
result,
|
|
7924
|
+
keyToIndex,
|
|
7925
|
+
{ title: titleValue.absolute },
|
|
7926
|
+
"title"
|
|
7927
|
+
);
|
|
7928
|
+
continue;
|
|
7929
|
+
}
|
|
7930
|
+
const finalTitle = titleTemplate ? titleTemplate.split("%s").join(titleValue) : titleValue;
|
|
7931
|
+
addOrReplace(
|
|
7932
|
+
result,
|
|
7933
|
+
keyToIndex,
|
|
7934
|
+
{ title: finalTitle },
|
|
7935
|
+
"title"
|
|
7936
|
+
);
|
|
7937
|
+
continue;
|
|
7938
|
+
}
|
|
7939
|
+
const key = getMetaKey(descriptor);
|
|
7940
|
+
addOrReplace(result, keyToIndex, descriptor, key);
|
|
7976
7941
|
}
|
|
7977
7942
|
}
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
8010
|
-
|
|
8011
|
-
|
|
8012
|
-
e.snapshot = Object.freeze({
|
|
8013
|
-
value: e.snapshot.value,
|
|
8014
|
-
hasValue: e.snapshot.hasValue,
|
|
8015
|
-
error: null,
|
|
8016
|
-
isLoading: true,
|
|
8017
|
-
requestId
|
|
8018
|
-
});
|
|
8019
|
-
this.notify(e);
|
|
8020
|
-
}
|
|
8021
|
-
/**
|
|
8022
|
-
* Commit a successful result. No-op if `requestId` is not the latest
|
|
8023
|
-
* (a newer `load()` was issued or `clear()` ran). Clearing `error` is
|
|
8024
|
-
* intentional: a successful refetch should hide the previous failure.
|
|
8025
|
-
*/
|
|
8026
|
-
finishData(bucketKey, requestId, value) {
|
|
8027
|
-
const e = this.entries.get(bucketKey);
|
|
8028
|
-
if (!e || requestId !== e.latestRequestId) return;
|
|
8029
|
-
e.snapshot = Object.freeze({
|
|
8030
|
-
value,
|
|
8031
|
-
hasValue: true,
|
|
8032
|
-
error: null,
|
|
8033
|
-
isLoading: false,
|
|
8034
|
-
requestId
|
|
8035
|
-
});
|
|
8036
|
-
this.notify(e);
|
|
8037
|
-
this.dropIfSettled(bucketKey, e);
|
|
8038
|
-
}
|
|
8039
|
-
/**
|
|
8040
|
-
* Commit an error. Preserves the last good `value` so consumers can keep
|
|
8041
|
-
* showing previous data while displaying the error if they choose. No-op
|
|
8042
|
-
* if `requestId` is not the latest.
|
|
8043
|
-
*/
|
|
8044
|
-
finishError(bucketKey, requestId, error) {
|
|
8045
|
-
const e = this.entries.get(bucketKey);
|
|
8046
|
-
if (!e || requestId !== e.latestRequestId) return;
|
|
8047
|
-
e.snapshot = Object.freeze({
|
|
8048
|
-
value: e.snapshot.value,
|
|
8049
|
-
hasValue: e.snapshot.hasValue,
|
|
8050
|
-
error,
|
|
8051
|
-
isLoading: false,
|
|
8052
|
-
requestId
|
|
8053
|
-
});
|
|
8054
|
-
this.notify(e);
|
|
8055
|
-
this.dropIfSettled(bucketKey, e);
|
|
8056
|
-
}
|
|
8057
|
-
/**
|
|
8058
|
-
* Update loading flag. Gated on `requestId` to fix the race where an old
|
|
8059
|
-
* load() finishes after a new one started — its `setLoading(false)` would
|
|
8060
|
-
* otherwise hide the new request's spinner.
|
|
8061
|
-
*/
|
|
8062
|
-
setLoading(bucketKey, requestId, isLoading) {
|
|
8063
|
-
const e = this.entries.get(bucketKey);
|
|
8064
|
-
if (!e || requestId !== e.latestRequestId) return;
|
|
8065
|
-
if (e.snapshot.isLoading === isLoading) return;
|
|
8066
|
-
e.snapshot = Object.freeze({
|
|
8067
|
-
...e.snapshot,
|
|
8068
|
-
isLoading
|
|
8069
|
-
});
|
|
8070
|
-
this.notify(e);
|
|
8071
|
-
}
|
|
8072
|
-
/**
|
|
8073
|
-
* Reset a single bucket entry. Bumps `latestRequestId` so any in-flight
|
|
8074
|
-
* `load()` whose promise is still pending will fail its gate when it resolves
|
|
8075
|
-
* and be dropped — prevents pre-navigation loads from clobbering the new
|
|
8076
|
-
* route's context. The entry itself is kept (sticky-bucket semantics).
|
|
8077
|
-
*/
|
|
8078
|
-
clear(bucketKey) {
|
|
8079
|
-
const e = this.entries.get(bucketKey);
|
|
8080
|
-
if (!e) return;
|
|
8081
|
-
e.latestRequestId++;
|
|
8082
|
-
if (e.snapshot === EMPTY_SNAPSHOT) return;
|
|
8083
|
-
e.snapshot = EMPTY_SNAPSHOT;
|
|
8084
|
-
this.notify(e);
|
|
8085
|
-
}
|
|
8086
|
-
/**
|
|
8087
|
-
* Reset every sticky bucket belonging to `loaderId`. Called on navigation /
|
|
8088
|
-
* route-context change: all route-registered reads of the loader (keyed or
|
|
8089
|
-
* not) drop back to seeding from fresh `loaderData`. Ephemeral buckets are
|
|
8090
|
-
* intentionally left alone — they are governed by subscriber refcount, so a
|
|
8091
|
-
* persistent keyed reader outside the outlet keeps its value across a
|
|
8092
|
-
* navigation rather than blanking out.
|
|
8093
|
-
*/
|
|
8094
|
-
clearFamily(loaderId) {
|
|
8095
|
-
const fam = this.families.get(loaderId);
|
|
8096
|
-
if (!fam) return;
|
|
8097
|
-
for (const bucketKey of fam) {
|
|
8098
|
-
const e = this.entries.get(bucketKey);
|
|
8099
|
-
if (!e || !e.sticky) continue;
|
|
8100
|
-
this.clear(bucketKey);
|
|
8101
|
-
}
|
|
8102
|
-
}
|
|
8103
|
-
notify(e) {
|
|
8104
|
-
for (const cb of e.listeners) cb();
|
|
8105
|
-
}
|
|
8106
|
-
/**
|
|
8107
|
-
* Register a still-streaming per-loader result for `loaderId`. No-op for a
|
|
8108
|
-
* settled Flight chunk (unwrapsSynchronously / "rejected"): the forceAwait
|
|
8109
|
-
* and action lanes commit settled chunks, and a { ssr: false } loader is
|
|
8110
|
-
* awaited before flush. Released as the stream settles, either way.
|
|
8111
|
-
*/
|
|
8112
|
-
trackPendingStream(loaderId, stream) {
|
|
8113
|
-
if (unwrapsSynchronously(stream) || stream.status === "rejected") {
|
|
8114
|
-
return;
|
|
8115
|
-
}
|
|
8116
|
-
let set = this.pendingStreams.get(loaderId);
|
|
8117
|
-
if (set?.has(stream)) return;
|
|
8118
|
-
if (!set) {
|
|
8119
|
-
set = /* @__PURE__ */ new Set();
|
|
8120
|
-
this.pendingStreams.set(loaderId, set);
|
|
8121
|
-
}
|
|
8122
|
-
set.add(stream);
|
|
8123
|
-
const release = () => {
|
|
8124
|
-
const current = this.pendingStreams.get(loaderId);
|
|
8125
|
-
if (!current || !current.delete(stream)) return;
|
|
8126
|
-
if (current.size === 0) this.pendingStreams.delete(loaderId);
|
|
8127
|
-
};
|
|
8128
|
-
stream.then(release, release);
|
|
7943
|
+
return result;
|
|
7944
|
+
}
|
|
7945
|
+
var Meta = createHandle(collectMeta, "__rsc_router_meta__");
|
|
7946
|
+
|
|
7947
|
+
// src/theme/theme-context.ts
|
|
7948
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
7949
|
+
var ThemeContext = createContext2(null);
|
|
7950
|
+
|
|
7951
|
+
// src/browser/react/nonce-context.ts
|
|
7952
|
+
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
7953
|
+
var NonceContext = createContext3(void 0);
|
|
7954
|
+
|
|
7955
|
+
// src/handles/MetaTags.tsx
|
|
7956
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7957
|
+
|
|
7958
|
+
// src/handles/Scripts.tsx
|
|
7959
|
+
import { useState as useState2 } from "react";
|
|
7960
|
+
|
|
7961
|
+
// src/handles/script.ts
|
|
7962
|
+
function validateConfigDev(config) {
|
|
7963
|
+
if (process.env.NODE_ENV === "production") return;
|
|
7964
|
+
const c = config;
|
|
7965
|
+
if (c.src != null && c.children != null) {
|
|
7966
|
+
console.warn(
|
|
7967
|
+
`[Script] A config has both "src" and "children"; they are mutually exclusive \u2014 "src" wins and the inline body is ignored.`
|
|
7968
|
+
);
|
|
7969
|
+
} else if (c.src == null && c.children == null) {
|
|
7970
|
+
console.warn(
|
|
7971
|
+
`[Script] A config has neither "src" nor "children"; it injects nothing.`
|
|
7972
|
+
);
|
|
7973
|
+
} else if (c.src == null && c.id == null) {
|
|
7974
|
+
console.warn(
|
|
7975
|
+
`[Script] An inline script was pushed without an "id" and cannot be deduplicated. Pass an "id" so a layout + child pushing the same script inject it only once.`
|
|
7976
|
+
);
|
|
8129
7977
|
}
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
7978
|
+
if (c.async && c.defer) {
|
|
7979
|
+
console.warn(
|
|
7980
|
+
`[Script] A config has both "async" and "defer"; they are mutually exclusive.`
|
|
7981
|
+
);
|
|
8133
7982
|
}
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
*/
|
|
8147
|
-
announcePendingStreams(segments) {
|
|
8148
|
-
for (const segment of segments) {
|
|
8149
|
-
if (segment.type === "loader" && segment.loaderId && segment.loaderData instanceof Promise) {
|
|
8150
|
-
this.trackPendingStream(segment.loaderId, segment.loaderData);
|
|
7983
|
+
}
|
|
7984
|
+
function collectScripts(segments) {
|
|
7985
|
+
const result = [];
|
|
7986
|
+
const keyToIndex = /* @__PURE__ */ new Map();
|
|
7987
|
+
for (const configs of segments) {
|
|
7988
|
+
for (const config of configs) {
|
|
7989
|
+
validateConfigDev(config);
|
|
7990
|
+
const isAsyncResource = config.src != null && config.async === true;
|
|
7991
|
+
const key = isAsyncResource ? config.src : config.id ?? config.src;
|
|
7992
|
+
if (key === void 0) {
|
|
7993
|
+
result.push(config);
|
|
7994
|
+
continue;
|
|
8151
7995
|
}
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
if (!e) continue;
|
|
8159
|
-
for (const cb of e.streamPendingListeners) cb();
|
|
7996
|
+
const existing = keyToIndex.get(key);
|
|
7997
|
+
if (existing !== void 0) {
|
|
7998
|
+
result[existing] = config;
|
|
7999
|
+
} else {
|
|
8000
|
+
keyToIndex.set(key, result.length);
|
|
8001
|
+
result.push(config);
|
|
8160
8002
|
}
|
|
8161
8003
|
}
|
|
8162
8004
|
}
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
* @internal
|
|
8167
|
-
*/
|
|
8168
|
-
reset() {
|
|
8169
|
-
this.entries.clear();
|
|
8170
|
-
this.families.clear();
|
|
8171
|
-
this.groups.clear();
|
|
8172
|
-
this.pendingStreams.clear();
|
|
8173
|
-
}
|
|
8174
|
-
};
|
|
8175
|
-
var loaderStore = new LoaderStore();
|
|
8005
|
+
return result;
|
|
8006
|
+
}
|
|
8007
|
+
var Script = createHandle(collectScripts, "__rsc_router_script__");
|
|
8176
8008
|
|
|
8177
|
-
// src/
|
|
8178
|
-
import {
|
|
8179
|
-
useContext as useContext5,
|
|
8180
|
-
useState as useState2,
|
|
8181
|
-
useEffect as useEffect3,
|
|
8182
|
-
useOptimistic as useOptimistic2,
|
|
8183
|
-
startTransition as startTransition2,
|
|
8184
|
-
useRef as useRef2
|
|
8185
|
-
} from "react";
|
|
8009
|
+
// src/handles/Scripts.tsx
|
|
8010
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
8186
8011
|
|
|
8187
|
-
// src/browser/react/
|
|
8188
|
-
import {
|
|
8012
|
+
// src/browser/react/ScrollRestoration.tsx
|
|
8013
|
+
import { useEffect as useEffect2 } from "react";
|
|
8189
8014
|
|
|
8190
|
-
// src/
|
|
8015
|
+
// src/browser/scroll-restoration.ts
|
|
8016
|
+
init_logging();
|
|
8017
|
+
|
|
8018
|
+
// src/outlet-context.ts
|
|
8191
8019
|
import { createContext as createContext4 } from "react";
|
|
8192
|
-
var
|
|
8020
|
+
var OutletContext = createContext4(null);
|
|
8193
8021
|
|
|
8194
|
-
// src/
|
|
8195
|
-
import {
|
|
8196
|
-
useCallback as useCallback2,
|
|
8197
|
-
useContext as useContext7,
|
|
8198
|
-
useEffect as useEffect5,
|
|
8199
|
-
useMemo as useMemo4,
|
|
8200
|
-
useRef as useRef4,
|
|
8201
|
-
useState as useState4
|
|
8202
|
-
} from "react";
|
|
8203
|
-
|
|
8204
|
-
// src/browser/react/use-params.ts
|
|
8205
|
-
import { useContext as useContext8, useState as useState5, useEffect as useEffect6, useRef as useRef5 } from "react";
|
|
8206
|
-
var EMPTY_PARAMS = Object.freeze({});
|
|
8022
|
+
// src/route-content-wrapper.tsx
|
|
8023
|
+
import { Component, Suspense, use } from "react";
|
|
8207
8024
|
|
|
8208
|
-
// src/
|
|
8209
|
-
import {
|
|
8210
|
-
|
|
8025
|
+
// src/outlet-provider.tsx
|
|
8026
|
+
import { useContext as useContext4, useMemo } from "react";
|
|
8027
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
8211
8028
|
|
|
8212
|
-
// src/
|
|
8213
|
-
import {
|
|
8214
|
-
useContext as useContext10,
|
|
8215
|
-
useState as useState6,
|
|
8216
|
-
useEffect as useEffect7,
|
|
8217
|
-
useRef as useRef6,
|
|
8218
|
-
useOptimistic as useOptimistic3,
|
|
8219
|
-
startTransition as startTransition3
|
|
8220
|
-
} from "react";
|
|
8029
|
+
// src/decode-loader-results.ts
|
|
8030
|
+
import { createElement as createElement2 } from "react";
|
|
8221
8031
|
|
|
8222
|
-
// src/
|
|
8223
|
-
import {
|
|
8032
|
+
// src/loader-redirect.tsx
|
|
8033
|
+
import { useEffect as useEffect3 } from "react";
|
|
8224
8034
|
|
|
8225
|
-
// src/browser/react/
|
|
8226
|
-
import {
|
|
8227
|
-
useState as useState10,
|
|
8228
|
-
useEffect as useEffect10,
|
|
8229
|
-
useLayoutEffect,
|
|
8230
|
-
useCallback as useCallback4,
|
|
8231
|
-
useMemo as useMemo6,
|
|
8232
|
-
useRef as useRef9,
|
|
8233
|
-
use as use3
|
|
8234
|
-
} from "react";
|
|
8035
|
+
// src/browser/react/use-router.ts
|
|
8036
|
+
import { useContext as useContext6, useMemo as useMemo2 } from "react";
|
|
8235
8037
|
|
|
8236
|
-
// src/
|
|
8237
|
-
import {
|
|
8238
|
-
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
8038
|
+
// src/browser/react/use-mount.ts
|
|
8039
|
+
import { useContext as useContext5 } from "react";
|
|
8239
8040
|
|
|
8240
|
-
// src/
|
|
8041
|
+
// src/browser/react/mount-context.ts
|
|
8241
8042
|
import {
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
useMemo as useMemo5,
|
|
8245
|
-
useState as useState9
|
|
8043
|
+
createContext as createContext5,
|
|
8044
|
+
createElement
|
|
8246
8045
|
} from "react";
|
|
8046
|
+
var MountContext = createContext5("/");
|
|
8247
8047
|
|
|
8248
|
-
// src/
|
|
8249
|
-
import { createContext as createContext6, useContext as useContext12 } from "react";
|
|
8250
|
-
var ThemeContext = createContext6(null);
|
|
8251
|
-
|
|
8252
|
-
// src/theme/constants.ts
|
|
8253
|
-
var THEME_COOKIE = {
|
|
8254
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
8255
|
-
// 1 year
|
|
8256
|
-
path: "/",
|
|
8257
|
-
sameSite: "lax"
|
|
8258
|
-
};
|
|
8259
|
-
|
|
8260
|
-
// src/theme/ThemeProvider.tsx
|
|
8261
|
-
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
8262
|
-
|
|
8263
|
-
// src/browser/react/NavigationProvider.tsx
|
|
8048
|
+
// src/browser/react/use-router.ts
|
|
8264
8049
|
init_loader();
|
|
8265
8050
|
|
|
8266
|
-
// src/browser/
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8272
|
-
// src/browser/navigation-store.ts
|
|
8273
|
-
init_cache();
|
|
8274
|
-
init_rango_state();
|
|
8051
|
+
// src/browser/app-version.ts
|
|
8052
|
+
var currentVersion2;
|
|
8053
|
+
function getAppVersion() {
|
|
8054
|
+
return currentVersion2;
|
|
8055
|
+
}
|
|
8275
8056
|
|
|
8276
|
-
// src/
|
|
8277
|
-
|
|
8057
|
+
// src/loader-redirect.tsx
|
|
8058
|
+
init_validate_redirect_origin();
|
|
8059
|
+
init_redirect_origin();
|
|
8278
8060
|
|
|
8279
|
-
// src/
|
|
8280
|
-
import {
|
|
8281
|
-
forwardRef,
|
|
8282
|
-
useCallback as useCallback5,
|
|
8283
|
-
useContext as useContext14,
|
|
8284
|
-
useEffect as useEffect13,
|
|
8285
|
-
useMemo as useMemo7,
|
|
8286
|
-
useRef as useRef12,
|
|
8287
|
-
useSyncExternalStore
|
|
8288
|
-
} from "react";
|
|
8061
|
+
// src/route-content-wrapper.tsx
|
|
8062
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
8289
8063
|
|
|
8290
|
-
// src/
|
|
8064
|
+
// src/use-loader.tsx
|
|
8291
8065
|
import {
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8066
|
+
isValidElement,
|
|
8067
|
+
startTransition as startTransition2,
|
|
8068
|
+
use as use2,
|
|
8069
|
+
useCallback,
|
|
8070
|
+
useContext as useContext7,
|
|
8071
|
+
useEffect as useEffect4,
|
|
8072
|
+
useMemo as useMemo3,
|
|
8073
|
+
useOptimistic as useOptimistic2,
|
|
8074
|
+
useRef as useRef2,
|
|
8075
|
+
useState as useState3
|
|
8299
8076
|
} from "react";
|
|
8300
|
-
var LinkContext = createContext7(
|
|
8301
|
-
null
|
|
8302
|
-
);
|
|
8303
8077
|
|
|
8304
|
-
// src/
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8078
|
+
// src/thenable-status.ts
|
|
8079
|
+
function unwrapsSynchronously(stream) {
|
|
8080
|
+
const status = stream.status;
|
|
8081
|
+
return status === "fulfilled" || status === "resolved_model" || status === "resolved_module";
|
|
8308
8082
|
}
|
|
8309
|
-
|
|
8310
|
-
|
|
8083
|
+
|
|
8084
|
+
// src/loader-store.ts
|
|
8085
|
+
var EMPTY_SNAPSHOT = Object.freeze({
|
|
8086
|
+
value: void 0,
|
|
8087
|
+
hasValue: false,
|
|
8088
|
+
error: null,
|
|
8089
|
+
isLoading: false,
|
|
8090
|
+
requestId: 0
|
|
8091
|
+
});
|
|
8092
|
+
function normalizeGroups(group) {
|
|
8093
|
+
if (group === void 0) return [];
|
|
8094
|
+
if (typeof group === "string") return [group];
|
|
8095
|
+
return [...new Set(group)];
|
|
8311
8096
|
}
|
|
8312
|
-
var
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
([token2, registration]) => currentSubscription.registrations.get(token2) === registration,
|
|
8335
|
-
() => notificationVersion === currentSubscription.notificationVersion
|
|
8336
|
-
);
|
|
8337
|
-
});
|
|
8097
|
+
var LoaderStore = class {
|
|
8098
|
+
constructor() {
|
|
8099
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
8100
|
+
/** loader.$$id -> set of bucket keys, so clearFamily() can reach every bucket. */
|
|
8101
|
+
this.families = /* @__PURE__ */ new Map();
|
|
8102
|
+
/** refresh group name -> set of bucket keys, for refreshGroups(). */
|
|
8103
|
+
this.groups = /* @__PURE__ */ new Map();
|
|
8104
|
+
/**
|
|
8105
|
+
* loader.$$id -> per-loader streams a committed navigation is still
|
|
8106
|
+
* receiving. Registered and announced by announcePendingStreams(), which
|
|
8107
|
+
* browser/partial-update.ts calls INSIDE every transition commit, so a
|
|
8108
|
+
* reader whose content is held on screen by that transition pins
|
|
8109
|
+
* `isLoading: true` for the data it is still showing until the transition
|
|
8110
|
+
* lands (use-loader.tsx). Family-keyed on purpose: a persisting layout
|
|
8111
|
+
* reader of the same createLoader the child is re-running is pinned too
|
|
8112
|
+
* (the loader is in flight; not "this segment's copy is being replaced" —
|
|
8113
|
+
* issue #862, working as designed). The new tree's own read of the loader
|
|
8114
|
+
* suspends at the read site and never observes the flag. A Set, not a
|
|
8115
|
+
* flag: overlapping navigations (second click before the first stream
|
|
8116
|
+
* lands) keep the family pending until the LAST stream settles.
|
|
8117
|
+
*/
|
|
8118
|
+
this.pendingStreams = /* @__PURE__ */ new Map();
|
|
8338
8119
|
}
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8120
|
+
getOrCreate(bucketKey) {
|
|
8121
|
+
let e = this.entries.get(bucketKey);
|
|
8122
|
+
if (!e) {
|
|
8123
|
+
e = {
|
|
8124
|
+
snapshot: EMPTY_SNAPSHOT,
|
|
8125
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
8126
|
+
latestRequestId: 0,
|
|
8127
|
+
loaderId: bucketKey,
|
|
8128
|
+
sticky: false,
|
|
8129
|
+
pendingClear: false,
|
|
8130
|
+
clearWhenSettled: false,
|
|
8131
|
+
groups: /* @__PURE__ */ new Map(),
|
|
8132
|
+
refetch: void 0,
|
|
8133
|
+
streamPendingListeners: /* @__PURE__ */ new Set()
|
|
8134
|
+
};
|
|
8135
|
+
this.entries.set(bucketKey, e);
|
|
8352
8136
|
}
|
|
8353
|
-
|
|
8354
|
-
};
|
|
8355
|
-
}
|
|
8356
|
-
|
|
8357
|
-
// src/browser/prefetch/default-strategy.ts
|
|
8358
|
-
var hoverNoneQuery = null;
|
|
8359
|
-
var defaultStrategy = process.env.NODE_ENV === "production" ? "viewport" : "none";
|
|
8360
|
-
function getHoverNoneQuery() {
|
|
8361
|
-
if (typeof window === "undefined") return null;
|
|
8362
|
-
if (!hoverNoneQuery) {
|
|
8363
|
-
hoverNoneQuery = window.matchMedia("(hover: none)");
|
|
8137
|
+
return e;
|
|
8364
8138
|
}
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
return getHoverNoneQuery()?.matches ? "viewport" : "hover";
|
|
8373
|
-
}
|
|
8374
|
-
function subscribeToAdaptiveStrategyChange(listener) {
|
|
8375
|
-
const query = getHoverNoneQuery();
|
|
8376
|
-
if (!query) return () => {
|
|
8377
|
-
};
|
|
8378
|
-
if (typeof query.addEventListener === "function") {
|
|
8379
|
-
query.addEventListener("change", listener);
|
|
8380
|
-
return () => query.removeEventListener("change", listener);
|
|
8139
|
+
registerFamily(loaderId, bucketKey) {
|
|
8140
|
+
let fam = this.families.get(loaderId);
|
|
8141
|
+
if (!fam) {
|
|
8142
|
+
fam = /* @__PURE__ */ new Set();
|
|
8143
|
+
this.families.set(loaderId, fam);
|
|
8144
|
+
}
|
|
8145
|
+
fam.add(bucketKey);
|
|
8381
8146
|
}
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
if (subscriptions) {
|
|
8399
|
-
currentObserver.unobserve(entry.target);
|
|
8400
|
-
callbacks.delete(entry.target);
|
|
8401
|
-
for (const [subscription, callback] of subscriptions) {
|
|
8402
|
-
yield [subscriptions, subscription, callback];
|
|
8403
|
-
}
|
|
8404
|
-
}
|
|
8405
|
-
}
|
|
8406
|
-
}
|
|
8407
|
-
}
|
|
8408
|
-
notifyListeners(
|
|
8409
|
-
intersectingCallbacks(),
|
|
8410
|
-
([, , callback]) => callback(),
|
|
8411
|
-
([subscriptions, subscription]) => subscriptions.has(subscription)
|
|
8412
|
-
);
|
|
8413
|
-
},
|
|
8414
|
-
{ rootMargin: "200px" }
|
|
8415
|
-
);
|
|
8416
|
-
for (const element of callbacks.keys()) observer.observe(element);
|
|
8417
|
-
}
|
|
8418
|
-
return observer;
|
|
8419
|
-
}
|
|
8420
|
-
function observeForPrefetch(element, onVisible) {
|
|
8421
|
-
if (typeof IntersectionObserver === "undefined") return () => {
|
|
8422
|
-
};
|
|
8423
|
-
const currentObserver = getObserver();
|
|
8424
|
-
let subscriptions = callbacks.get(element);
|
|
8425
|
-
if (!subscriptions) {
|
|
8426
|
-
subscriptions = /* @__PURE__ */ new Map();
|
|
8427
|
-
callbacks.set(element, subscriptions);
|
|
8428
|
-
}
|
|
8429
|
-
const subscription = /* @__PURE__ */ Symbol();
|
|
8430
|
-
subscriptions.set(subscription, onVisible);
|
|
8431
|
-
if (subscriptions.size === 1) currentObserver.observe(element);
|
|
8432
|
-
return () => {
|
|
8433
|
-
const current = callbacks.get(element);
|
|
8434
|
-
subscriptions.delete(subscription);
|
|
8435
|
-
if (current !== subscriptions) return;
|
|
8436
|
-
if (current.size > 0) return;
|
|
8437
|
-
callbacks.delete(element);
|
|
8438
|
-
observer?.unobserve(element);
|
|
8439
|
-
};
|
|
8440
|
-
}
|
|
8441
|
-
|
|
8442
|
-
// src/browser/link-interceptor.ts
|
|
8443
|
-
init_invalidation();
|
|
8444
|
-
init_notify_listeners();
|
|
8445
|
-
var ELIGIBILITY_ATTRIBUTES = {
|
|
8446
|
-
href: "href",
|
|
8447
|
-
target: "target",
|
|
8448
|
-
download: "download",
|
|
8449
|
-
noIntercept: "data-no-intercept",
|
|
8450
|
-
linkComponent: "data-link-component",
|
|
8451
|
-
external: "data-external",
|
|
8452
|
-
prefetch: "data-prefetch",
|
|
8453
|
-
prefetchScope: "data-prefetch-scope"
|
|
8454
|
-
};
|
|
8455
|
-
var ELIGIBILITY_ATTRIBUTE_FILTER = Object.values(ELIGIBILITY_ATTRIBUTES);
|
|
8456
|
-
var ELIGIBLE_ANCHOR_SELECTOR = `a[${ELIGIBILITY_ATTRIBUTES.href}]`;
|
|
8457
|
-
var LINK_COMPONENT_SELECTOR = `a[${ELIGIBILITY_ATTRIBUTES.linkComponent}]`;
|
|
8458
|
-
var PREFETCH_SCOPE_OPT_OUT_SELECTOR = `[${ELIGIBILITY_ATTRIBUTES.prefetchScope}="false"],[${ELIGIBILITY_ATTRIBUTES.prefetchScope}="none"]`;
|
|
8459
|
-
function isElementNode(value) {
|
|
8460
|
-
return typeof value === "object" && value !== null && value.nodeType === 1 && typeof value.matches === "function";
|
|
8461
|
-
}
|
|
8462
|
-
var prefetchScopeObservers = /* @__PURE__ */ new WeakMap();
|
|
8463
|
-
function createPrefetchScopeObserverState(ownerDocument) {
|
|
8464
|
-
if (typeof MutationObserver === "undefined" || !ownerDocument.documentElement) {
|
|
8465
|
-
return void 0;
|
|
8466
|
-
}
|
|
8467
|
-
const subscriptions = /* @__PURE__ */ new Map();
|
|
8468
|
-
const observer2 = new MutationObserver((mutations) => {
|
|
8469
|
-
const affected = /* @__PURE__ */ new Set();
|
|
8470
|
-
const collect = (element) => {
|
|
8471
|
-
subscriptions.get(element)?.forEach((listener) => affected.add(listener));
|
|
8472
|
-
};
|
|
8473
|
-
for (const mutation of mutations) {
|
|
8474
|
-
if (!isElementNode(mutation.target)) continue;
|
|
8475
|
-
collect(mutation.target);
|
|
8476
|
-
mutation.target.querySelectorAll(LINK_COMPONENT_SELECTOR).forEach(collect);
|
|
8147
|
+
/**
|
|
8148
|
+
* Subscribe to entry changes for `bucketKey`.
|
|
8149
|
+
* Returns an unsubscribe function. A sticky bucket's entry is kept around even
|
|
8150
|
+
* after the last subscriber leaves so that an in-flight `load()` can still
|
|
8151
|
+
* commit if the consumer remounts. An ephemeral bucket is dropped once its
|
|
8152
|
+
* last subscriber leaves (deferred, see maybeScheduleRefcountClear).
|
|
8153
|
+
*/
|
|
8154
|
+
subscribe(bucketKey, cb, options) {
|
|
8155
|
+
const e = this.getOrCreate(bucketKey);
|
|
8156
|
+
const loaderId = options?.loaderId ?? bucketKey;
|
|
8157
|
+
e.loaderId = loaderId;
|
|
8158
|
+
this.registerFamily(loaderId, bucketKey);
|
|
8159
|
+
if (options?.ephemeral !== true) e.sticky = true;
|
|
8160
|
+
const groups = normalizeGroups(options?.group);
|
|
8161
|
+
for (const group of groups) {
|
|
8162
|
+
this.addToGroup(group, bucketKey, e, options?.refetch);
|
|
8477
8163
|
}
|
|
8478
|
-
|
|
8479
|
-
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
const ownerDocument = element.ownerDocument;
|
|
8489
|
-
let state = prefetchScopeObservers.get(ownerDocument);
|
|
8490
|
-
if (!state) {
|
|
8491
|
-
state = createPrefetchScopeObserverState(ownerDocument);
|
|
8492
|
-
if (!state) return () => {
|
|
8164
|
+
e.pendingClear = false;
|
|
8165
|
+
e.clearWhenSettled = false;
|
|
8166
|
+
e.listeners.add(cb);
|
|
8167
|
+
const onStreamPending = options?.onStreamPending;
|
|
8168
|
+
if (onStreamPending) e.streamPendingListeners.add(onStreamPending);
|
|
8169
|
+
return () => {
|
|
8170
|
+
e.listeners.delete(cb);
|
|
8171
|
+
if (onStreamPending) e.streamPendingListeners.delete(onStreamPending);
|
|
8172
|
+
for (const group of groups) this.releaseGroup(group, bucketKey, e);
|
|
8173
|
+
this.maybeScheduleRefcountClear(bucketKey, e);
|
|
8493
8174
|
};
|
|
8494
|
-
prefetchScopeObservers.set(ownerDocument, state);
|
|
8495
8175
|
}
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8176
|
+
addToGroup(group, bucketKey, e, refetch) {
|
|
8177
|
+
e.groups.set(group, (e.groups.get(group) ?? 0) + 1);
|
|
8178
|
+
if (refetch) e.refetch = refetch;
|
|
8179
|
+
let members = this.groups.get(group);
|
|
8180
|
+
if (!members) {
|
|
8181
|
+
members = /* @__PURE__ */ new Set();
|
|
8182
|
+
this.groups.set(group, members);
|
|
8183
|
+
}
|
|
8184
|
+
members.add(bucketKey);
|
|
8500
8185
|
}
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
listeners.delete(listener);
|
|
8507
|
-
if (listeners.size === 0 && state.subscriptions.get(element) === listeners) {
|
|
8508
|
-
state.subscriptions.delete(element);
|
|
8186
|
+
releaseGroup(group, bucketKey, e) {
|
|
8187
|
+
const next = (e.groups.get(group) ?? 0) - 1;
|
|
8188
|
+
if (next > 0) {
|
|
8189
|
+
e.groups.set(group, next);
|
|
8190
|
+
return;
|
|
8509
8191
|
}
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8192
|
+
e.groups.delete(group);
|
|
8193
|
+
const members = this.groups.get(group);
|
|
8194
|
+
if (members) {
|
|
8195
|
+
members.delete(bucketKey);
|
|
8196
|
+
if (members.size === 0) this.groups.delete(group);
|
|
8513
8197
|
}
|
|
8514
|
-
};
|
|
8515
|
-
}
|
|
8516
|
-
function isHashOnlyNavigationToPath(anchor, pathname) {
|
|
8517
|
-
return pathname === window.location.pathname && anchor.search === window.location.search && !!anchor.hash;
|
|
8518
|
-
}
|
|
8519
|
-
function isHashOnlyNavigation(anchor) {
|
|
8520
|
-
return isHashOnlyNavigationToPath(anchor, anchor.pathname);
|
|
8521
|
-
}
|
|
8522
|
-
function isPrefetchScopeDisabled(element) {
|
|
8523
|
-
return typeof element.closest === "function" && element.closest(PREFETCH_SCOPE_OPT_OUT_SELECTOR) !== null;
|
|
8524
|
-
}
|
|
8525
|
-
|
|
8526
|
-
// src/browser/react/location-state.ts
|
|
8527
|
-
import { useState as useState12, useEffect as useEffect12, useRef as useRef11 } from "react";
|
|
8528
|
-
|
|
8529
|
-
// src/browser/react/location-state-shared.ts
|
|
8530
|
-
function isLocationStateEntry(value) {
|
|
8531
|
-
return value !== null && typeof value === "object" && "__rsc_ls_key" in value && "__rsc_ls_value" in value && typeof value.__rsc_ls_key === "string";
|
|
8532
|
-
}
|
|
8533
|
-
function resolveLocationStateEntries(entries) {
|
|
8534
|
-
const result = {};
|
|
8535
|
-
for (const entry of entries) {
|
|
8536
|
-
result[entry.__rsc_ls_key] = entry.__rsc_ls_lazy ? entry.__rsc_ls_value() : entry.__rsc_ls_value;
|
|
8537
8198
|
}
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
}
|
|
8546
|
-
function isExternalUrl(href2, origin) {
|
|
8547
|
-
if (href2.startsWith("//")) return true;
|
|
8548
|
-
if (href2.startsWith("http://") || href2.startsWith("https://")) {
|
|
8549
|
-
if (!origin) return false;
|
|
8550
|
-
try {
|
|
8551
|
-
return new URL(href2).origin !== origin;
|
|
8552
|
-
} catch {
|
|
8553
|
-
return false;
|
|
8199
|
+
/** Remove a bucket from every group it belongs to (used when it is dropped). */
|
|
8200
|
+
removeFromAllGroups(bucketKey, e) {
|
|
8201
|
+
for (const group of e.groups.keys()) {
|
|
8202
|
+
const members = this.groups.get(group);
|
|
8203
|
+
if (members) {
|
|
8204
|
+
members.delete(bucketKey);
|
|
8205
|
+
if (members.size === 0) this.groups.delete(group);
|
|
8206
|
+
}
|
|
8554
8207
|
}
|
|
8208
|
+
e.groups.clear();
|
|
8555
8209
|
}
|
|
8556
|
-
|
|
8557
|
-
|
|
8210
|
+
/**
|
|
8211
|
+
* Refresh every currently-mounted bucket tagged with ANY of the given group
|
|
8212
|
+
* names, with a plain GET (no params/body). Accepts a single name or an array
|
|
8213
|
+
* of names. A bucket that belongs to more than one of the named groups is
|
|
8214
|
+
* refreshed exactly once (members are unioned and deduped by bucket key), as
|
|
8215
|
+
* are multiple reads of one bucket. Resolves when all refreshes settle; rejects
|
|
8216
|
+
* with an `AggregateError` of the failures if any member fails — each failing
|
|
8217
|
+
* member also records its error on its own snapshot.
|
|
8218
|
+
*/
|
|
8219
|
+
async refreshGroups(groups) {
|
|
8220
|
+
const names = typeof groups === "string" ? [groups] : groups;
|
|
8221
|
+
const buckets = /* @__PURE__ */ new Set();
|
|
8222
|
+
for (const name of names) {
|
|
8223
|
+
const members = this.groups.get(name);
|
|
8224
|
+
if (!members) continue;
|
|
8225
|
+
for (const bucketKey of members) buckets.add(bucketKey);
|
|
8226
|
+
}
|
|
8227
|
+
if (buckets.size === 0) return;
|
|
8228
|
+
const thunks = [];
|
|
8229
|
+
for (const bucketKey of buckets) {
|
|
8230
|
+
const e = this.entries.get(bucketKey);
|
|
8231
|
+
if (!e || e.listeners.size === 0 || !e.refetch) continue;
|
|
8232
|
+
thunks.push(e.refetch);
|
|
8233
|
+
}
|
|
8234
|
+
if (thunks.length === 0) return;
|
|
8235
|
+
const results = await Promise.allSettled(thunks.map((t) => t()));
|
|
8236
|
+
const reasons = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
8237
|
+
if (reasons.length > 0) {
|
|
8238
|
+
const label = names.map((n) => `"${n}"`).join(", ");
|
|
8239
|
+
throw new AggregateError(
|
|
8240
|
+
reasons,
|
|
8241
|
+
`refreshGroups(${label}) had ${reasons.length} failure(s)`
|
|
8242
|
+
);
|
|
8243
|
+
}
|
|
8558
8244
|
}
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
const storeLocation = ctx?.eventController.getState().location;
|
|
8576
|
-
const origin = storeLocation?.origin ?? (typeof window !== "undefined" ? window.location.origin : void 0);
|
|
8577
|
-
const isExternal = isExternalUrl(to, origin);
|
|
8578
|
-
const resolvedTo = useMemo7(() => {
|
|
8579
|
-
if (isExternal) return to;
|
|
8580
|
-
const bn = ctx?.basename;
|
|
8581
|
-
if (!bn || !to.startsWith("/") || to.startsWith(bn + "/") || to === bn)
|
|
8582
|
-
return to;
|
|
8583
|
-
return to === "/" ? bn : bn + to;
|
|
8584
|
-
}, [to, isExternal, ctx?.basename]);
|
|
8585
|
-
const configuredStrategy = prefetch ?? ctx?.defaultPrefetch ?? getDefaultPrefetchStrategy();
|
|
8586
|
-
const resolvedStrategy = useSyncExternalStore(
|
|
8587
|
-
configuredStrategy === "adaptive" ? subscribeToAdaptiveStrategyChange : IGNORE_STRATEGY_CHANGES,
|
|
8588
|
-
() => resolveAdaptiveStrategy(configuredStrategy),
|
|
8589
|
-
() => configuredStrategy === "adaptive" ? "hover" : configuredStrategy
|
|
8590
|
-
);
|
|
8591
|
-
const internalRef = useRef12(null);
|
|
8592
|
-
const setRef = useCallback5(
|
|
8593
|
-
(node) => {
|
|
8594
|
-
internalRef.current = node;
|
|
8595
|
-
if (typeof ref === "function") {
|
|
8596
|
-
ref(node);
|
|
8597
|
-
} else if (ref) {
|
|
8598
|
-
ref.current = node;
|
|
8599
|
-
}
|
|
8600
|
-
},
|
|
8601
|
-
[ref]
|
|
8602
|
-
);
|
|
8603
|
-
const stateRef = useRef12(state);
|
|
8604
|
-
stateRef.current = state;
|
|
8605
|
-
const handleClick = useCallback5(
|
|
8606
|
-
(e) => {
|
|
8607
|
-
onClick?.(e);
|
|
8608
|
-
if (e.defaultPrevented) return;
|
|
8609
|
-
if (isExternal) return;
|
|
8610
|
-
if (reloadDocument) return;
|
|
8611
|
-
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
8612
|
-
if (e.currentTarget.hasAttribute("download"))
|
|
8613
|
-
return;
|
|
8614
|
-
const target = e.currentTarget.target;
|
|
8615
|
-
if (target && target !== "_self") return;
|
|
8616
|
-
if (isHashOnlyNavigation(e.currentTarget)) {
|
|
8617
|
-
return;
|
|
8618
|
-
}
|
|
8619
|
-
if (!ctx?.navigate) {
|
|
8245
|
+
/**
|
|
8246
|
+
* Schedule a deferred drop for an ad-hoc (never-sticky) bucket whose last
|
|
8247
|
+
* subscriber just left. Deferred to a microtask so a StrictMode / transition
|
|
8248
|
+
* remount that resubscribes in the same tick cancels it.
|
|
8249
|
+
*/
|
|
8250
|
+
maybeScheduleRefcountClear(bucketKey, e) {
|
|
8251
|
+
if (e.listeners.size > 0) return;
|
|
8252
|
+
if (e.sticky) return;
|
|
8253
|
+
if (e.pendingClear) return;
|
|
8254
|
+
e.pendingClear = true;
|
|
8255
|
+
queueMicrotask(() => {
|
|
8256
|
+
if (!e.pendingClear) return;
|
|
8257
|
+
e.pendingClear = false;
|
|
8258
|
+
if (e.listeners.size > 0) return;
|
|
8259
|
+
if (e.snapshot.isLoading) {
|
|
8260
|
+
e.clearWhenSettled = true;
|
|
8620
8261
|
return;
|
|
8621
8262
|
}
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
ctx.navigate(resolvedTo, {
|
|
8636
|
-
replace,
|
|
8637
|
-
scroll,
|
|
8638
|
-
state: resolvedState,
|
|
8639
|
-
revalidate: revalidate2
|
|
8640
|
-
});
|
|
8641
|
-
},
|
|
8642
|
-
[
|
|
8643
|
-
resolvedTo,
|
|
8644
|
-
isExternal,
|
|
8645
|
-
reloadDocument,
|
|
8646
|
-
replace,
|
|
8647
|
-
scroll,
|
|
8648
|
-
revalidate2,
|
|
8649
|
-
ctx,
|
|
8650
|
-
onClick
|
|
8651
|
-
]
|
|
8652
|
-
);
|
|
8653
|
-
const handleMouseEnter = useCallback5(() => {
|
|
8654
|
-
const element = internalRef.current;
|
|
8655
|
-
if ((resolvedStrategy === "hover" || resolvedStrategy === "viewport") && !isExternal && ctx?.store && (!element || !isHashOnlyNavigation(element) && !isPrefetchScopeDisabled(element))) {
|
|
8656
|
-
const segmentState = ctx.store.getSegmentState();
|
|
8657
|
-
prefetchDirect2(
|
|
8658
|
-
resolvedTo,
|
|
8659
|
-
segmentState.currentSegmentIds,
|
|
8660
|
-
getAppVersion(),
|
|
8661
|
-
ctx.store.getRouterId?.(),
|
|
8662
|
-
prefetchKey
|
|
8663
|
-
);
|
|
8263
|
+
this.dropBucket(bucketKey);
|
|
8264
|
+
});
|
|
8265
|
+
}
|
|
8266
|
+
/** Remove a bucket entry entirely and prune it from its family/group indexes. */
|
|
8267
|
+
dropBucket(bucketKey) {
|
|
8268
|
+
const e = this.entries.get(bucketKey);
|
|
8269
|
+
if (!e) return;
|
|
8270
|
+
this.removeFromAllGroups(bucketKey, e);
|
|
8271
|
+
this.entries.delete(bucketKey);
|
|
8272
|
+
const fam = this.families.get(e.loaderId);
|
|
8273
|
+
if (fam) {
|
|
8274
|
+
fam.delete(bucketKey);
|
|
8275
|
+
if (fam.size === 0) this.families.delete(e.loaderId);
|
|
8664
8276
|
}
|
|
8665
|
-
}
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8277
|
+
}
|
|
8278
|
+
/** Drop an ephemeral bucket that settled with no subscribers left. */
|
|
8279
|
+
dropIfSettled(bucketKey, e) {
|
|
8280
|
+
if (e.clearWhenSettled && e.listeners.size === 0) {
|
|
8281
|
+
e.clearWhenSettled = false;
|
|
8282
|
+
this.dropBucket(bucketKey);
|
|
8283
|
+
}
|
|
8284
|
+
}
|
|
8285
|
+
/**
|
|
8286
|
+
* Returns the current snapshot for `bucketKey`. Stable reference between
|
|
8287
|
+
* mutations — subscribers rely on this to avoid spurious re-renders.
|
|
8288
|
+
* Returns `EMPTY_SNAPSHOT` (a singleton) when the entry has never been
|
|
8289
|
+
* mutated or has been cleared.
|
|
8290
|
+
*/
|
|
8291
|
+
getSnapshot(bucketKey) {
|
|
8292
|
+
return this.entries.get(bucketKey)?.snapshot ?? EMPTY_SNAPSHOT;
|
|
8293
|
+
}
|
|
8294
|
+
/**
|
|
8295
|
+
* Reserve a fresh request id for an upcoming `load()` call. The returned id
|
|
8296
|
+
* is the new "latest"; any older in-flight requests will fail their gating
|
|
8297
|
+
* check on `finishData` / `finishError` / `finishLoading` and be dropped.
|
|
8298
|
+
*
|
|
8299
|
+
* Callers should follow with `beginRequest(id, requestId)` to flip the
|
|
8300
|
+
* loading flag on AND clear any leftover error from a previous attempt
|
|
8301
|
+
* — the latter matters for `throwOnError: false` consumers, which would
|
|
8302
|
+
* otherwise keep showing the stale error throughout the retry.
|
|
8303
|
+
*/
|
|
8304
|
+
reserveRequestId(bucketKey) {
|
|
8305
|
+
const e = this.getOrCreate(bucketKey);
|
|
8306
|
+
e.latestRequestId++;
|
|
8307
|
+
return e.latestRequestId;
|
|
8308
|
+
}
|
|
8309
|
+
/**
|
|
8310
|
+
* Mark the request as in-flight: `isLoading = true`, `error = null`.
|
|
8311
|
+
* Combines the two operations so a retry doesn't render the previous
|
|
8312
|
+
* error during the new request. Gated on `requestId === latestRequestId`
|
|
8313
|
+
* for symmetry with the other mutators.
|
|
8314
|
+
*/
|
|
8315
|
+
beginRequest(bucketKey, requestId) {
|
|
8316
|
+
const e = this.entries.get(bucketKey);
|
|
8317
|
+
if (!e || requestId !== e.latestRequestId) return;
|
|
8318
|
+
if (e.snapshot.isLoading && e.snapshot.error === null) return;
|
|
8319
|
+
e.snapshot = Object.freeze({
|
|
8320
|
+
value: e.snapshot.value,
|
|
8321
|
+
hasValue: e.snapshot.hasValue,
|
|
8322
|
+
error: null,
|
|
8323
|
+
isLoading: true,
|
|
8324
|
+
requestId
|
|
8325
|
+
});
|
|
8326
|
+
this.notify(e);
|
|
8327
|
+
}
|
|
8328
|
+
/**
|
|
8329
|
+
* Commit a successful result. No-op if `requestId` is not the latest
|
|
8330
|
+
* (a newer `load()` was issued or `clear()` ran). Clearing `error` is
|
|
8331
|
+
* intentional: a successful refetch should hide the previous failure.
|
|
8332
|
+
*/
|
|
8333
|
+
finishData(bucketKey, requestId, value) {
|
|
8334
|
+
const e = this.entries.get(bucketKey);
|
|
8335
|
+
if (!e || requestId !== e.latestRequestId) return;
|
|
8336
|
+
e.snapshot = Object.freeze({
|
|
8337
|
+
value,
|
|
8338
|
+
hasValue: true,
|
|
8339
|
+
error: null,
|
|
8340
|
+
isLoading: false,
|
|
8341
|
+
requestId
|
|
8342
|
+
});
|
|
8343
|
+
this.notify(e);
|
|
8344
|
+
this.dropIfSettled(bucketKey, e);
|
|
8345
|
+
}
|
|
8346
|
+
/**
|
|
8347
|
+
* Commit an error. Preserves the last good `value` so consumers can keep
|
|
8348
|
+
* showing previous data while displaying the error if they choose. No-op
|
|
8349
|
+
* if `requestId` is not the latest.
|
|
8350
|
+
*/
|
|
8351
|
+
finishError(bucketKey, requestId, error) {
|
|
8352
|
+
const e = this.entries.get(bucketKey);
|
|
8353
|
+
if (!e || requestId !== e.latestRequestId) return;
|
|
8354
|
+
e.snapshot = Object.freeze({
|
|
8355
|
+
value: e.snapshot.value,
|
|
8356
|
+
hasValue: e.snapshot.hasValue,
|
|
8357
|
+
error,
|
|
8358
|
+
isLoading: false,
|
|
8359
|
+
requestId
|
|
8360
|
+
});
|
|
8361
|
+
this.notify(e);
|
|
8362
|
+
this.dropIfSettled(bucketKey, e);
|
|
8363
|
+
}
|
|
8364
|
+
/**
|
|
8365
|
+
* Update loading flag. Gated on `requestId` to fix the race where an old
|
|
8366
|
+
* load() finishes after a new one started — its `setLoading(false)` would
|
|
8367
|
+
* otherwise hide the new request's spinner.
|
|
8368
|
+
*/
|
|
8369
|
+
setLoading(bucketKey, requestId, isLoading) {
|
|
8370
|
+
const e = this.entries.get(bucketKey);
|
|
8371
|
+
if (!e || requestId !== e.latestRequestId) return;
|
|
8372
|
+
if (e.snapshot.isLoading === isLoading) return;
|
|
8373
|
+
e.snapshot = Object.freeze({
|
|
8374
|
+
...e.snapshot,
|
|
8375
|
+
isLoading
|
|
8376
|
+
});
|
|
8377
|
+
this.notify(e);
|
|
8378
|
+
}
|
|
8379
|
+
/**
|
|
8380
|
+
* Reset a single bucket entry. Bumps `latestRequestId` so any in-flight
|
|
8381
|
+
* `load()` whose promise is still pending will fail its gate when it resolves
|
|
8382
|
+
* and be dropped — prevents pre-navigation loads from clobbering the new
|
|
8383
|
+
* route's context. The entry itself is kept (sticky-bucket semantics).
|
|
8384
|
+
*/
|
|
8385
|
+
clear(bucketKey) {
|
|
8386
|
+
const e = this.entries.get(bucketKey);
|
|
8387
|
+
if (!e) return;
|
|
8388
|
+
e.latestRequestId++;
|
|
8389
|
+
if (e.snapshot === EMPTY_SNAPSHOT) return;
|
|
8390
|
+
e.snapshot = EMPTY_SNAPSHOT;
|
|
8391
|
+
this.notify(e);
|
|
8392
|
+
}
|
|
8393
|
+
/**
|
|
8394
|
+
* Reset every sticky bucket belonging to `loaderId`. Called on navigation /
|
|
8395
|
+
* route-context change: all route-registered reads of the loader (keyed or
|
|
8396
|
+
* not) drop back to seeding from fresh `loaderData`. Ephemeral buckets are
|
|
8397
|
+
* intentionally left alone — they are governed by subscriber refcount, so a
|
|
8398
|
+
* persistent keyed reader outside the outlet keeps its value across a
|
|
8399
|
+
* navigation rather than blanking out.
|
|
8400
|
+
*/
|
|
8401
|
+
clearFamily(loaderId) {
|
|
8402
|
+
const fam = this.families.get(loaderId);
|
|
8403
|
+
if (!fam) return;
|
|
8404
|
+
for (const bucketKey of fam) {
|
|
8405
|
+
const e = this.entries.get(bucketKey);
|
|
8406
|
+
if (!e || !e.sticky) continue;
|
|
8407
|
+
this.clear(bucketKey);
|
|
8408
|
+
}
|
|
8409
|
+
}
|
|
8410
|
+
notify(e) {
|
|
8411
|
+
for (const cb of e.listeners) cb();
|
|
8412
|
+
}
|
|
8413
|
+
/**
|
|
8414
|
+
* Register a still-streaming per-loader result for `loaderId`. No-op for a
|
|
8415
|
+
* settled Flight chunk (unwrapsSynchronously / "rejected"): the forceAwait
|
|
8416
|
+
* and action lanes commit settled chunks, and a { ssr: false } loader is
|
|
8417
|
+
* awaited before flush. Released as the stream settles, either way.
|
|
8418
|
+
*/
|
|
8419
|
+
trackPendingStream(loaderId, stream) {
|
|
8420
|
+
if (unwrapsSynchronously(stream) || stream.status === "rejected") {
|
|
8421
|
+
return;
|
|
8422
|
+
}
|
|
8423
|
+
let set = this.pendingStreams.get(loaderId);
|
|
8424
|
+
if (set?.has(stream)) return;
|
|
8425
|
+
if (!set) {
|
|
8426
|
+
set = /* @__PURE__ */ new Set();
|
|
8427
|
+
this.pendingStreams.set(loaderId, set);
|
|
8428
|
+
}
|
|
8429
|
+
set.add(stream);
|
|
8430
|
+
const release = () => {
|
|
8431
|
+
const current = this.pendingStreams.get(loaderId);
|
|
8432
|
+
if (!current || !current.delete(stream)) return;
|
|
8433
|
+
if (current.size === 0) this.pendingStreams.delete(loaderId);
|
|
8714
8434
|
};
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
|
|
8721
|
-
|
|
8722
|
-
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8435
|
+
stream.then(release, release);
|
|
8436
|
+
}
|
|
8437
|
+
/** True while any navigation stream for `loaderId` is still pending. */
|
|
8438
|
+
isStreamPending(loaderId) {
|
|
8439
|
+
return this.pendingStreams.has(loaderId);
|
|
8440
|
+
}
|
|
8441
|
+
/**
|
|
8442
|
+
* Register the loader segments of a tree being committed whose data is
|
|
8443
|
+
* still a pending promise, then fire `onStreamPending` on every subscriber
|
|
8444
|
+
* of every family with a pending stream. MUST run inside the startTransition
|
|
8445
|
+
* that commits the tree: the hook answers with a useOptimistic update, which
|
|
8446
|
+
* React reverts exactly when that transition commits — so the held reader
|
|
8447
|
+
* reports isLoading:true for as long as its data stays on screen and not a
|
|
8448
|
+
* frame longer. Outside a transition React reverts an optimistic update on
|
|
8449
|
+
* the next render, pinning nothing useful. Registering here rather than in
|
|
8450
|
+
* the tree build keeps register + announce in one call; settled chunks
|
|
8451
|
+
* (cached/reused segments, forceAwait lanes) are skipped by
|
|
8452
|
+
* trackPendingStream.
|
|
8453
|
+
*/
|
|
8454
|
+
announcePendingStreams(segments) {
|
|
8455
|
+
for (const segment of segments) {
|
|
8456
|
+
if (segment.type === "loader" && segment.loaderId && segment.loaderData instanceof Promise) {
|
|
8457
|
+
this.trackPendingStream(segment.loaderId, segment.loaderData);
|
|
8458
|
+
}
|
|
8459
|
+
}
|
|
8460
|
+
for (const loaderId of this.pendingStreams.keys()) {
|
|
8461
|
+
const fam = this.families.get(loaderId);
|
|
8462
|
+
if (!fam) continue;
|
|
8463
|
+
for (const bucketKey of fam) {
|
|
8464
|
+
const e = this.entries.get(bucketKey);
|
|
8465
|
+
if (!e) continue;
|
|
8466
|
+
for (const cb of e.streamPendingListeners) cb();
|
|
8726
8467
|
}
|
|
8727
|
-
);
|
|
8728
|
-
return () => {
|
|
8729
|
-
unsubscribeScope?.();
|
|
8730
|
-
unsubscribeLocation();
|
|
8731
|
-
disarmPrefetch();
|
|
8732
|
-
};
|
|
8733
|
-
}, [resolvedStrategy, resolvedTo, isExternal, ctx, prefetchKey]);
|
|
8734
|
-
return /* @__PURE__ */ jsx6(
|
|
8735
|
-
"a",
|
|
8736
|
-
{
|
|
8737
|
-
ref: setRef,
|
|
8738
|
-
href: resolvedTo,
|
|
8739
|
-
onClick: handleClick,
|
|
8740
|
-
onMouseEnter: handleMouseEnter,
|
|
8741
|
-
"data-link-component": true,
|
|
8742
|
-
"data-external": isExternal ? "" : void 0,
|
|
8743
|
-
"data-scroll": scroll === false ? "false" : void 0,
|
|
8744
|
-
"data-replace": replace ? "true" : void 0,
|
|
8745
|
-
"data-revalidate": revalidate2 === false ? "false" : void 0,
|
|
8746
|
-
...props,
|
|
8747
|
-
children: /* @__PURE__ */ jsx6(LinkContext.Provider, { value: resolvedTo, children })
|
|
8748
8468
|
}
|
|
8749
|
-
|
|
8750
|
-
|
|
8469
|
+
}
|
|
8470
|
+
/**
|
|
8471
|
+
* Test-only escape hatch. Drops every entry. Production code should never
|
|
8472
|
+
* call this; the store is process-scoped and lives for the tab's lifetime.
|
|
8473
|
+
* @internal
|
|
8474
|
+
*/
|
|
8475
|
+
reset() {
|
|
8476
|
+
this.entries.clear();
|
|
8477
|
+
this.families.clear();
|
|
8478
|
+
this.groups.clear();
|
|
8479
|
+
this.pendingStreams.clear();
|
|
8480
|
+
}
|
|
8481
|
+
};
|
|
8482
|
+
var loaderStore = new LoaderStore();
|
|
8751
8483
|
|
|
8752
|
-
// src/browser/react/
|
|
8753
|
-
import {
|
|
8484
|
+
// src/browser/react/use-navigation.ts
|
|
8485
|
+
import {
|
|
8486
|
+
useContext as useContext8,
|
|
8487
|
+
useState as useState4,
|
|
8488
|
+
useEffect as useEffect5,
|
|
8489
|
+
useOptimistic as useOptimistic3,
|
|
8490
|
+
startTransition as startTransition3,
|
|
8491
|
+
useRef as useRef3
|
|
8492
|
+
} from "react";
|
|
8754
8493
|
|
|
8755
|
-
// src/browser/react/use-
|
|
8494
|
+
// src/browser/react/use-pathname.ts
|
|
8495
|
+
import { useContext as useContext9, useState as useState5, useEffect as useEffect6, useRef as useRef4 } from "react";
|
|
8496
|
+
|
|
8497
|
+
// src/client-urls/optimistic-location.ts
|
|
8498
|
+
import { createContext as createContext6 } from "react";
|
|
8499
|
+
var OptimisticLocationContext = createContext6(null);
|
|
8500
|
+
|
|
8501
|
+
// src/browser/react/use-search-params.ts
|
|
8502
|
+
import {
|
|
8503
|
+
useCallback as useCallback2,
|
|
8504
|
+
useContext as useContext10,
|
|
8505
|
+
useEffect as useEffect7,
|
|
8506
|
+
useMemo as useMemo4,
|
|
8507
|
+
useRef as useRef5,
|
|
8508
|
+
useState as useState6
|
|
8509
|
+
} from "react";
|
|
8510
|
+
|
|
8511
|
+
// src/browser/react/use-params.ts
|
|
8512
|
+
import { useContext as useContext11, useState as useState7, useEffect as useEffect8, useRef as useRef6 } from "react";
|
|
8513
|
+
var EMPTY_PARAMS = Object.freeze({});
|
|
8514
|
+
|
|
8515
|
+
// src/browser/react/use-action.ts
|
|
8516
|
+
import {
|
|
8517
|
+
useContext as useContext12,
|
|
8518
|
+
useState as useState8,
|
|
8519
|
+
useEffect as useEffect9,
|
|
8520
|
+
useRef as useRef7,
|
|
8521
|
+
useOptimistic as useOptimistic4,
|
|
8522
|
+
startTransition as startTransition4
|
|
8523
|
+
} from "react";
|
|
8524
|
+
|
|
8525
|
+
// src/browser/react/use-segments.ts
|
|
8526
|
+
import { useContext as useContext13, useState as useState9, useEffect as useEffect10, useRef as useRef8 } from "react";
|
|
8527
|
+
|
|
8528
|
+
// src/browser/react/NavigationProvider.tsx
|
|
8529
|
+
import {
|
|
8530
|
+
useState as useState12,
|
|
8531
|
+
useEffect as useEffect12,
|
|
8532
|
+
useLayoutEffect,
|
|
8533
|
+
useCallback as useCallback4,
|
|
8534
|
+
useMemo as useMemo6,
|
|
8535
|
+
useRef as useRef10,
|
|
8536
|
+
use as use3
|
|
8537
|
+
} from "react";
|
|
8538
|
+
|
|
8539
|
+
// src/root-error-boundary.tsx
|
|
8540
|
+
import { Component as Component2, useState as useState10 } from "react";
|
|
8541
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
8542
|
+
|
|
8543
|
+
// src/theme/ThemeProvider.tsx
|
|
8544
|
+
import {
|
|
8545
|
+
useCallback as useCallback3,
|
|
8546
|
+
useEffect as useEffect11,
|
|
8547
|
+
useMemo as useMemo5,
|
|
8548
|
+
useState as useState11
|
|
8549
|
+
} from "react";
|
|
8550
|
+
|
|
8551
|
+
// src/theme/constants.ts
|
|
8552
|
+
var THEME_COOKIE = {
|
|
8553
|
+
maxAge: 60 * 60 * 24 * 365,
|
|
8554
|
+
// 1 year
|
|
8555
|
+
path: "/",
|
|
8556
|
+
sameSite: "lax"
|
|
8557
|
+
};
|
|
8558
|
+
|
|
8559
|
+
// src/theme/ThemeProvider.tsx
|
|
8560
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
8561
|
+
|
|
8562
|
+
// src/browser/react/NavigationProvider.tsx
|
|
8563
|
+
init_loader();
|
|
8564
|
+
init_logging();
|
|
8565
|
+
|
|
8566
|
+
// src/browser/navigation-store.ts
|
|
8567
|
+
init_cache();
|
|
8568
|
+
init_rango_state();
|
|
8569
|
+
|
|
8570
|
+
// src/browser/react/NavigationProvider.tsx
|
|
8571
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
8572
|
+
|
|
8573
|
+
// src/browser/react/Link.tsx
|
|
8756
8574
|
import {
|
|
8575
|
+
forwardRef,
|
|
8576
|
+
useCallback as useCallback5,
|
|
8757
8577
|
useContext as useContext15,
|
|
8758
|
-
useState as useState13,
|
|
8759
8578
|
useEffect as useEffect15,
|
|
8579
|
+
useMemo as useMemo7,
|
|
8760
8580
|
useRef as useRef13,
|
|
8581
|
+
useSyncExternalStore
|
|
8582
|
+
} from "react";
|
|
8583
|
+
|
|
8584
|
+
// src/browser/react/use-link-status.ts
|
|
8585
|
+
import {
|
|
8586
|
+
createContext as createContext7,
|
|
8587
|
+
useContext as useContext14,
|
|
8588
|
+
useState as useState13,
|
|
8589
|
+
useEffect as useEffect13,
|
|
8590
|
+
useRef as useRef11,
|
|
8761
8591
|
useOptimistic as useOptimistic5,
|
|
8762
8592
|
startTransition as startTransition5
|
|
8763
8593
|
} from "react";
|
|
8594
|
+
var LinkContext = createContext7(
|
|
8595
|
+
null
|
|
8596
|
+
);
|
|
8764
8597
|
|
|
8765
|
-
// src/
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
"
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
const path6 = m[1];
|
|
8782
|
-
if (path6.includes("node_modules") || path6.includes("@rangojs/router")) {
|
|
8783
|
-
continue;
|
|
8598
|
+
// src/browser/event-controller.ts
|
|
8599
|
+
init_notify_listeners();
|
|
8600
|
+
if (typeof Symbol.dispose === "undefined") {
|
|
8601
|
+
Symbol.dispose = /* @__PURE__ */ Symbol("Symbol.dispose");
|
|
8602
|
+
}
|
|
8603
|
+
if (typeof Symbol.asyncDispose === "undefined") {
|
|
8604
|
+
Symbol.asyncDispose = /* @__PURE__ */ Symbol("Symbol.asyncDispose");
|
|
8605
|
+
}
|
|
8606
|
+
var locationChangeSubscriptions = /* @__PURE__ */ new WeakMap();
|
|
8607
|
+
function subscribeToLocationChange(eventController, listener) {
|
|
8608
|
+
let subscription = locationChangeSubscriptions.get(eventController);
|
|
8609
|
+
if (!subscription) {
|
|
8610
|
+
subscription = {
|
|
8611
|
+
registrations: /* @__PURE__ */ new Map(),
|
|
8612
|
+
notificationVersion: 0,
|
|
8613
|
+
unsubscribe: () => {
|
|
8784
8614
|
}
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8615
|
+
};
|
|
8616
|
+
locationChangeSubscriptions.set(eventController, subscription);
|
|
8617
|
+
const currentSubscription = subscription;
|
|
8618
|
+
subscription.unsubscribe = eventController.subscribe(() => {
|
|
8619
|
+
const notificationVersion = ++currentSubscription.notificationVersion;
|
|
8620
|
+
const nextHref = eventController.getState().location.href;
|
|
8621
|
+
notifyListeners(
|
|
8622
|
+
[...currentSubscription.registrations],
|
|
8623
|
+
([, registration]) => {
|
|
8624
|
+
if (registration.href === nextHref) return;
|
|
8625
|
+
registration.href = nextHref;
|
|
8626
|
+
registration.listener(nextHref);
|
|
8627
|
+
},
|
|
8628
|
+
([token2, registration]) => currentSubscription.registrations.get(token2) === registration,
|
|
8629
|
+
() => notificationVersion === currentSubscription.notificationVersion
|
|
8630
|
+
);
|
|
8631
|
+
});
|
|
8632
|
+
}
|
|
8633
|
+
const token = /* @__PURE__ */ Symbol();
|
|
8634
|
+
subscription.registrations.set(token, {
|
|
8635
|
+
href: eventController.getState().location.href,
|
|
8636
|
+
listener
|
|
8637
|
+
});
|
|
8638
|
+
let active2 = true;
|
|
8639
|
+
return () => {
|
|
8640
|
+
if (!active2) return;
|
|
8641
|
+
active2 = false;
|
|
8642
|
+
subscription.registrations.delete(token);
|
|
8643
|
+
if (subscription.registrations.size > 0) return;
|
|
8644
|
+
if (locationChangeSubscriptions.get(eventController) === subscription) {
|
|
8645
|
+
locationChangeSubscriptions.delete(eventController);
|
|
8788
8646
|
}
|
|
8789
|
-
|
|
8647
|
+
subscription.unsubscribe();
|
|
8648
|
+
};
|
|
8649
|
+
}
|
|
8650
|
+
|
|
8651
|
+
// src/browser/prefetch/default-strategy.ts
|
|
8652
|
+
var hoverNoneQuery = null;
|
|
8653
|
+
var defaultStrategy = process.env.NODE_ENV === "production" ? "viewport" : "none";
|
|
8654
|
+
function getHoverNoneQuery() {
|
|
8655
|
+
if (typeof window === "undefined") return null;
|
|
8656
|
+
if (!hoverNoneQuery) {
|
|
8657
|
+
hoverNoneQuery = window.matchMedia("(hover: none)");
|
|
8658
|
+
}
|
|
8659
|
+
return hoverNoneQuery;
|
|
8660
|
+
}
|
|
8661
|
+
function getDefaultPrefetchStrategy() {
|
|
8662
|
+
return defaultStrategy;
|
|
8663
|
+
}
|
|
8664
|
+
function resolveAdaptiveStrategy(strategy) {
|
|
8665
|
+
if (strategy !== "adaptive") return strategy;
|
|
8666
|
+
return getHoverNoneQuery()?.matches ? "viewport" : "hover";
|
|
8667
|
+
}
|
|
8668
|
+
function subscribeToAdaptiveStrategyChange(listener) {
|
|
8669
|
+
const query = getHoverNoneQuery();
|
|
8670
|
+
if (!query) return () => {
|
|
8671
|
+
};
|
|
8672
|
+
if (typeof query.addEventListener === "function") {
|
|
8673
|
+
query.addEventListener("change", listener);
|
|
8674
|
+
return () => query.removeEventListener("change", listener);
|
|
8675
|
+
}
|
|
8676
|
+
query.addListener(listener);
|
|
8677
|
+
return () => query.removeListener(listener);
|
|
8678
|
+
}
|
|
8679
|
+
|
|
8680
|
+
// src/browser/prefetch/observer.ts
|
|
8681
|
+
init_notify_listeners();
|
|
8682
|
+
var callbacks = /* @__PURE__ */ new Map();
|
|
8683
|
+
var observer = null;
|
|
8684
|
+
function getObserver() {
|
|
8685
|
+
if (!observer) {
|
|
8686
|
+
observer = new IntersectionObserver(
|
|
8687
|
+
(entries, currentObserver) => {
|
|
8688
|
+
function* intersectingCallbacks() {
|
|
8689
|
+
for (const entry of entries) {
|
|
8690
|
+
if (entry.isIntersecting) {
|
|
8691
|
+
const subscriptions = callbacks.get(entry.target);
|
|
8692
|
+
if (subscriptions) {
|
|
8693
|
+
currentObserver.unobserve(entry.target);
|
|
8694
|
+
callbacks.delete(entry.target);
|
|
8695
|
+
for (const [subscription, callback] of subscriptions) {
|
|
8696
|
+
yield [subscriptions, subscription, callback];
|
|
8697
|
+
}
|
|
8698
|
+
}
|
|
8699
|
+
}
|
|
8700
|
+
}
|
|
8701
|
+
}
|
|
8702
|
+
notifyListeners(
|
|
8703
|
+
intersectingCallbacks(),
|
|
8704
|
+
([, , callback]) => callback(),
|
|
8705
|
+
([subscriptions, subscription]) => subscriptions.has(subscription)
|
|
8706
|
+
);
|
|
8707
|
+
},
|
|
8708
|
+
{ rootMargin: "200px" }
|
|
8709
|
+
);
|
|
8710
|
+
for (const element of callbacks.keys()) observer.observe(element);
|
|
8790
8711
|
}
|
|
8791
|
-
return
|
|
8792
|
-
}
|
|
8793
|
-
function missingInjectedIdError(kind, fnName) {
|
|
8794
|
-
const site = findUserCallSite();
|
|
8795
|
-
const at = site ? ` (created at ${site})` : "";
|
|
8796
|
-
return new Error(
|
|
8797
|
-
`[rango] ${kind} is missing $$id${at}.
|
|
8798
|
-
The @rangojs/router:expose-internal-ids Vite transform injects ${fnName}()'s stable $$id from an EXPORTED const declaration only:
|
|
8799
|
-
export const X = ${fnName}(...)
|
|
8800
|
-
const X = ${fnName}(...); export { X }
|
|
8801
|
-
A non-exported const, an \`export let/var\`, or an inline ${fnName}(...) call gets no $$id \u2014 export it as \`export const\`. (A matching "Unsupported ${fnName} shape" warning names the exact file:line.)`
|
|
8802
|
-
);
|
|
8803
|
-
}
|
|
8804
|
-
|
|
8805
|
-
// src/handle.ts
|
|
8806
|
-
function defaultCollect(segments) {
|
|
8807
|
-
return segments;
|
|
8712
|
+
return observer;
|
|
8808
8713
|
}
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
throw missingInjectedIdError("Handle", "createHandle");
|
|
8818
|
-
} else {
|
|
8819
|
-
throw new Error(
|
|
8820
|
-
"[rango] Handle is missing $$id \u2014 the build plugin did not inject one. Export it as `export const X = createHandle(...)`."
|
|
8821
|
-
);
|
|
8822
|
-
}
|
|
8714
|
+
function observeForPrefetch(element, onVisible) {
|
|
8715
|
+
if (typeof IntersectionObserver === "undefined") return () => {
|
|
8716
|
+
};
|
|
8717
|
+
const currentObserver = getObserver();
|
|
8718
|
+
let subscriptions = callbacks.get(element);
|
|
8719
|
+
if (!subscriptions) {
|
|
8720
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
8721
|
+
callbacks.set(element, subscriptions);
|
|
8823
8722
|
}
|
|
8824
|
-
const
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8723
|
+
const subscription = /* @__PURE__ */ Symbol();
|
|
8724
|
+
subscriptions.set(subscription, onVisible);
|
|
8725
|
+
if (subscriptions.size === 1) currentObserver.observe(element);
|
|
8726
|
+
return () => {
|
|
8727
|
+
const current = callbacks.get(element);
|
|
8728
|
+
subscriptions.delete(subscription);
|
|
8729
|
+
if (current !== subscriptions) return;
|
|
8730
|
+
if (current.size > 0) return;
|
|
8731
|
+
callbacks.delete(element);
|
|
8732
|
+
observer?.unobserve(element);
|
|
8832
8733
|
};
|
|
8833
8734
|
}
|
|
8834
8735
|
|
|
8835
|
-
// src/
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8736
|
+
// src/browser/link-interceptor.ts
|
|
8737
|
+
init_invalidation();
|
|
8738
|
+
init_notify_listeners();
|
|
8739
|
+
var ELIGIBILITY_ATTRIBUTES = {
|
|
8740
|
+
href: "href",
|
|
8741
|
+
target: "target",
|
|
8742
|
+
download: "download",
|
|
8743
|
+
noIntercept: "data-no-intercept",
|
|
8744
|
+
linkComponent: "data-link-component",
|
|
8745
|
+
external: "data-external",
|
|
8746
|
+
prefetch: "data-prefetch",
|
|
8747
|
+
prefetchScope: "data-prefetch-scope"
|
|
8748
|
+
};
|
|
8749
|
+
var ELIGIBILITY_ATTRIBUTE_FILTER = Object.values(ELIGIBILITY_ATTRIBUTES);
|
|
8750
|
+
var ELIGIBLE_ANCHOR_SELECTOR = `a[${ELIGIBILITY_ATTRIBUTES.href}]`;
|
|
8751
|
+
var LINK_COMPONENT_SELECTOR = `a[${ELIGIBILITY_ATTRIBUTES.linkComponent}]`;
|
|
8752
|
+
var PREFETCH_SCOPE_OPT_OUT_SELECTOR = `[${ELIGIBILITY_ATTRIBUTES.prefetchScope}="false"],[${ELIGIBILITY_ATTRIBUTES.prefetchScope}="none"]`;
|
|
8753
|
+
function isElementNode(value) {
|
|
8754
|
+
return typeof value === "object" && value !== null && value.nodeType === 1 && typeof value.matches === "function";
|
|
8847
8755
|
}
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
}
|
|
8852
|
-
if ("charSet" in descriptor) {
|
|
8853
|
-
return "charSet";
|
|
8854
|
-
}
|
|
8855
|
-
if ("title" in descriptor) {
|
|
8856
|
-
return "title";
|
|
8857
|
-
}
|
|
8858
|
-
if ("name" in descriptor && "content" in descriptor) {
|
|
8859
|
-
return `name:${descriptor.name}`;
|
|
8860
|
-
}
|
|
8861
|
-
if ("property" in descriptor && "content" in descriptor) {
|
|
8862
|
-
return `property:${descriptor.property}`;
|
|
8863
|
-
}
|
|
8864
|
-
if ("httpEquiv" in descriptor && "content" in descriptor) {
|
|
8865
|
-
return `httpEquiv:${descriptor.httpEquiv}`;
|
|
8866
|
-
}
|
|
8867
|
-
if ("script:ld+json" in descriptor) {
|
|
8756
|
+
var prefetchScopeObservers = /* @__PURE__ */ new WeakMap();
|
|
8757
|
+
function createPrefetchScopeObserverState(ownerDocument) {
|
|
8758
|
+
if (typeof MutationObserver === "undefined" || !ownerDocument.documentElement) {
|
|
8868
8759
|
return void 0;
|
|
8869
8760
|
}
|
|
8870
|
-
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8761
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
8762
|
+
const observer2 = new MutationObserver((mutations) => {
|
|
8763
|
+
const affected = /* @__PURE__ */ new Set();
|
|
8764
|
+
const collect = (element) => {
|
|
8765
|
+
subscriptions.get(element)?.forEach((listener) => affected.add(listener));
|
|
8766
|
+
};
|
|
8767
|
+
for (const mutation of mutations) {
|
|
8768
|
+
if (!isElementNode(mutation.target)) continue;
|
|
8769
|
+
collect(mutation.target);
|
|
8770
|
+
mutation.target.querySelectorAll(LINK_COMPONENT_SELECTOR).forEach(collect);
|
|
8876
8771
|
}
|
|
8877
|
-
|
|
8878
|
-
}
|
|
8879
|
-
|
|
8772
|
+
notifyListeners(affected, (listener) => listener());
|
|
8773
|
+
});
|
|
8774
|
+
observer2.observe(ownerDocument.documentElement, {
|
|
8775
|
+
subtree: true,
|
|
8776
|
+
attributes: true,
|
|
8777
|
+
attributeFilter: [ELIGIBILITY_ATTRIBUTES.prefetchScope]
|
|
8778
|
+
});
|
|
8779
|
+
return { observer: observer2, subscriptions };
|
|
8880
8780
|
}
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
if (key !== void 0) {
|
|
8890
|
-
keyToIndex.set(key, result.length);
|
|
8891
|
-
}
|
|
8892
|
-
result.push(descriptor);
|
|
8781
|
+
function subscribeToPrefetchScopeChange(element, listener) {
|
|
8782
|
+
const ownerDocument = element.ownerDocument;
|
|
8783
|
+
let state = prefetchScopeObservers.get(ownerDocument);
|
|
8784
|
+
if (!state) {
|
|
8785
|
+
state = createPrefetchScopeObserverState(ownerDocument);
|
|
8786
|
+
if (!state) return () => {
|
|
8787
|
+
};
|
|
8788
|
+
prefetchScopeObservers.set(ownerDocument, state);
|
|
8893
8789
|
}
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
keyToIndex.set(key, index - 1);
|
|
8899
|
-
}
|
|
8790
|
+
let listeners = state.subscriptions.get(element);
|
|
8791
|
+
if (!listeners) {
|
|
8792
|
+
listeners = /* @__PURE__ */ new Set();
|
|
8793
|
+
state.subscriptions.set(element, listeners);
|
|
8900
8794
|
}
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
keyToIndex.set(key, result.length);
|
|
8795
|
+
listeners.add(listener);
|
|
8796
|
+
let active2 = true;
|
|
8797
|
+
return () => {
|
|
8798
|
+
if (!active2) return;
|
|
8799
|
+
active2 = false;
|
|
8800
|
+
listeners.delete(listener);
|
|
8801
|
+
if (listeners.size === 0 && state.subscriptions.get(element) === listeners) {
|
|
8802
|
+
state.subscriptions.delete(element);
|
|
8910
8803
|
}
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
for (const descriptor of descriptors) {
|
|
8915
|
-
if (isUnsetDescriptor(descriptor)) {
|
|
8916
|
-
const keyToRemove = descriptor.unset;
|
|
8917
|
-
if (keyToIndex.has(keyToRemove)) {
|
|
8918
|
-
const idx = keyToIndex.get(keyToRemove);
|
|
8919
|
-
result.splice(idx, 1);
|
|
8920
|
-
keyToIndex.delete(keyToRemove);
|
|
8921
|
-
updateIndicesAfterRemoval(keyToIndex, idx);
|
|
8922
|
-
}
|
|
8923
|
-
continue;
|
|
8924
|
-
}
|
|
8925
|
-
if (isTitleDescriptor(descriptor)) {
|
|
8926
|
-
const titleValue = descriptor.title;
|
|
8927
|
-
if (isTitleTemplate(titleValue)) {
|
|
8928
|
-
titleTemplate = titleValue.template;
|
|
8929
|
-
addOrReplace(
|
|
8930
|
-
result,
|
|
8931
|
-
keyToIndex,
|
|
8932
|
-
{ title: titleValue.default },
|
|
8933
|
-
"title"
|
|
8934
|
-
);
|
|
8935
|
-
continue;
|
|
8936
|
-
}
|
|
8937
|
-
if (isAbsoluteTitle(titleValue)) {
|
|
8938
|
-
addOrReplace(
|
|
8939
|
-
result,
|
|
8940
|
-
keyToIndex,
|
|
8941
|
-
{ title: titleValue.absolute },
|
|
8942
|
-
"title"
|
|
8943
|
-
);
|
|
8944
|
-
continue;
|
|
8945
|
-
}
|
|
8946
|
-
const finalTitle = titleTemplate ? titleTemplate.split("%s").join(titleValue) : titleValue;
|
|
8947
|
-
addOrReplace(
|
|
8948
|
-
result,
|
|
8949
|
-
keyToIndex,
|
|
8950
|
-
{ title: finalTitle },
|
|
8951
|
-
"title"
|
|
8952
|
-
);
|
|
8953
|
-
continue;
|
|
8954
|
-
}
|
|
8955
|
-
const key = getMetaKey(descriptor);
|
|
8956
|
-
addOrReplace(result, keyToIndex, descriptor, key);
|
|
8804
|
+
if (state.subscriptions.size === 0 && prefetchScopeObservers.get(ownerDocument) === state) {
|
|
8805
|
+
state.observer.disconnect();
|
|
8806
|
+
prefetchScopeObservers.delete(ownerDocument);
|
|
8957
8807
|
}
|
|
8808
|
+
};
|
|
8809
|
+
}
|
|
8810
|
+
function isHashOnlyNavigationToPath(anchor, pathname) {
|
|
8811
|
+
return pathname === window.location.pathname && anchor.search === window.location.search && !!anchor.hash;
|
|
8812
|
+
}
|
|
8813
|
+
function isHashOnlyNavigation(anchor) {
|
|
8814
|
+
return isHashOnlyNavigationToPath(anchor, anchor.pathname);
|
|
8815
|
+
}
|
|
8816
|
+
function isPrefetchScopeDisabled(element) {
|
|
8817
|
+
return typeof element.closest === "function" && element.closest(PREFETCH_SCOPE_OPT_OUT_SELECTOR) !== null;
|
|
8818
|
+
}
|
|
8819
|
+
|
|
8820
|
+
// src/browser/react/location-state.ts
|
|
8821
|
+
import { useState as useState14, useEffect as useEffect14, useRef as useRef12 } from "react";
|
|
8822
|
+
|
|
8823
|
+
// src/browser/react/location-state-shared.ts
|
|
8824
|
+
function isLocationStateEntry(value) {
|
|
8825
|
+
return value !== null && typeof value === "object" && "__rsc_ls_key" in value && "__rsc_ls_value" in value && typeof value.__rsc_ls_key === "string";
|
|
8826
|
+
}
|
|
8827
|
+
function resolveLocationStateEntries(entries) {
|
|
8828
|
+
const result = {};
|
|
8829
|
+
for (const entry of entries) {
|
|
8830
|
+
result[entry.__rsc_ls_key] = entry.__rsc_ls_lazy ? entry.__rsc_ls_value() : entry.__rsc_ls_value;
|
|
8958
8831
|
}
|
|
8959
8832
|
return result;
|
|
8960
8833
|
}
|
|
8961
|
-
var Meta = createHandle(collectMeta, "__rsc_router_meta__");
|
|
8962
|
-
|
|
8963
|
-
// src/handles/MetaTags.tsx
|
|
8964
|
-
import { Fragment, jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
8965
8834
|
|
|
8966
|
-
// src/
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
`[Script] An inline script was pushed without an "id" and cannot be deduplicated. Pass an "id" so a layout + child pushing the same script inject it only once.`
|
|
8981
|
-
);
|
|
8835
|
+
// src/browser/react/Link.tsx
|
|
8836
|
+
init_loader();
|
|
8837
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
8838
|
+
var IGNORE_STRATEGY_CHANGES = (_listener) => () => {
|
|
8839
|
+
};
|
|
8840
|
+
function isExternalUrl(href2, origin) {
|
|
8841
|
+
if (href2.startsWith("//")) return true;
|
|
8842
|
+
if (href2.startsWith("http://") || href2.startsWith("https://")) {
|
|
8843
|
+
if (!origin) return false;
|
|
8844
|
+
try {
|
|
8845
|
+
return new URL(href2).origin !== origin;
|
|
8846
|
+
} catch {
|
|
8847
|
+
return false;
|
|
8848
|
+
}
|
|
8982
8849
|
}
|
|
8983
|
-
if (
|
|
8984
|
-
|
|
8985
|
-
`[Script] A config has both "async" and "defer"; they are mutually exclusive.`
|
|
8986
|
-
);
|
|
8850
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(href2)) {
|
|
8851
|
+
return true;
|
|
8987
8852
|
}
|
|
8853
|
+
return false;
|
|
8988
8854
|
}
|
|
8989
|
-
function
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
8855
|
+
var Link = forwardRef(function Link2({
|
|
8856
|
+
to,
|
|
8857
|
+
replace = false,
|
|
8858
|
+
scroll = true,
|
|
8859
|
+
reloadDocument = false,
|
|
8860
|
+
revalidate: revalidate2,
|
|
8861
|
+
prefetch,
|
|
8862
|
+
prefetchKey,
|
|
8863
|
+
state,
|
|
8864
|
+
children,
|
|
8865
|
+
onClick,
|
|
8866
|
+
...props
|
|
8867
|
+
}, ref) {
|
|
8868
|
+
const ctx = useContext15(NavigationStoreContext);
|
|
8869
|
+
const storeLocation = ctx?.eventController.getState().location;
|
|
8870
|
+
const origin = storeLocation?.origin ?? (typeof window !== "undefined" ? window.location.origin : void 0);
|
|
8871
|
+
const isExternal = isExternalUrl(to, origin);
|
|
8872
|
+
const resolvedTo = useMemo7(() => {
|
|
8873
|
+
if (isExternal) return to;
|
|
8874
|
+
const bn = ctx?.basename;
|
|
8875
|
+
if (!bn || !to.startsWith("/") || to.startsWith(bn + "/") || to === bn)
|
|
8876
|
+
return to;
|
|
8877
|
+
return to === "/" ? bn : bn + to;
|
|
8878
|
+
}, [to, isExternal, ctx?.basename]);
|
|
8879
|
+
const configuredStrategy = prefetch ?? ctx?.defaultPrefetch ?? getDefaultPrefetchStrategy();
|
|
8880
|
+
const resolvedStrategy = useSyncExternalStore(
|
|
8881
|
+
configuredStrategy === "adaptive" ? subscribeToAdaptiveStrategyChange : IGNORE_STRATEGY_CHANGES,
|
|
8882
|
+
() => resolveAdaptiveStrategy(configuredStrategy),
|
|
8883
|
+
() => configuredStrategy === "adaptive" ? "hover" : configuredStrategy
|
|
8884
|
+
);
|
|
8885
|
+
const internalRef = useRef13(null);
|
|
8886
|
+
const setRef = useCallback5(
|
|
8887
|
+
(node) => {
|
|
8888
|
+
internalRef.current = node;
|
|
8889
|
+
if (typeof ref === "function") {
|
|
8890
|
+
ref(node);
|
|
8891
|
+
} else if (ref) {
|
|
8892
|
+
ref.current = node;
|
|
9000
8893
|
}
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
8894
|
+
},
|
|
8895
|
+
[ref]
|
|
8896
|
+
);
|
|
8897
|
+
const stateRef = useRef13(state);
|
|
8898
|
+
stateRef.current = state;
|
|
8899
|
+
const handleClick = useCallback5(
|
|
8900
|
+
(e) => {
|
|
8901
|
+
onClick?.(e);
|
|
8902
|
+
if (e.defaultPrevented) return;
|
|
8903
|
+
if (isExternal) return;
|
|
8904
|
+
if (reloadDocument) return;
|
|
8905
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
8906
|
+
if (e.currentTarget.hasAttribute("download"))
|
|
8907
|
+
return;
|
|
8908
|
+
const target = e.currentTarget.target;
|
|
8909
|
+
if (target && target !== "_self") return;
|
|
8910
|
+
if (isHashOnlyNavigation(e.currentTarget)) {
|
|
8911
|
+
return;
|
|
8912
|
+
}
|
|
8913
|
+
if (!ctx?.navigate) {
|
|
8914
|
+
return;
|
|
8915
|
+
}
|
|
8916
|
+
e.preventDefault();
|
|
8917
|
+
e.stopPropagation();
|
|
8918
|
+
const currentState = stateRef.current;
|
|
8919
|
+
let resolvedState;
|
|
8920
|
+
if (Array.isArray(currentState) && currentState.length > 0 && isLocationStateEntry(currentState[0])) {
|
|
8921
|
+
resolvedState = resolveLocationStateEntries(
|
|
8922
|
+
currentState
|
|
8923
|
+
);
|
|
8924
|
+
} else if (typeof currentState === "function") {
|
|
8925
|
+
resolvedState = currentState();
|
|
8926
|
+
} else if (currentState != null) {
|
|
8927
|
+
resolvedState = currentState;
|
|
8928
|
+
}
|
|
8929
|
+
ctx.navigate(resolvedTo, {
|
|
8930
|
+
replace,
|
|
8931
|
+
scroll,
|
|
8932
|
+
state: resolvedState,
|
|
8933
|
+
revalidate: revalidate2
|
|
8934
|
+
});
|
|
8935
|
+
},
|
|
8936
|
+
[
|
|
8937
|
+
resolvedTo,
|
|
8938
|
+
isExternal,
|
|
8939
|
+
reloadDocument,
|
|
8940
|
+
replace,
|
|
8941
|
+
scroll,
|
|
8942
|
+
revalidate2,
|
|
8943
|
+
ctx,
|
|
8944
|
+
onClick
|
|
8945
|
+
]
|
|
8946
|
+
);
|
|
8947
|
+
const handleMouseEnter = useCallback5(() => {
|
|
8948
|
+
const element = internalRef.current;
|
|
8949
|
+
if ((resolvedStrategy === "hover" || resolvedStrategy === "viewport") && !isExternal && ctx?.store && (!element || !isHashOnlyNavigation(element) && !isPrefetchScopeDisabled(element))) {
|
|
8950
|
+
const segmentState = ctx.store.getSegmentState();
|
|
8951
|
+
prefetchDirect2(
|
|
8952
|
+
resolvedTo,
|
|
8953
|
+
segmentState.currentSegmentIds,
|
|
8954
|
+
getAppVersion(),
|
|
8955
|
+
ctx.store.getRouterId?.(),
|
|
8956
|
+
prefetchKey
|
|
8957
|
+
);
|
|
8958
|
+
}
|
|
8959
|
+
}, [resolvedStrategy, resolvedTo, isExternal, ctx, prefetchKey]);
|
|
8960
|
+
useEffect15(() => {
|
|
8961
|
+
if (isExternal || !ctx?.store) return;
|
|
8962
|
+
const isViewport = resolvedStrategy === "viewport";
|
|
8963
|
+
const isRender = resolvedStrategy === "render";
|
|
8964
|
+
if (!isViewport && !isRender) return;
|
|
8965
|
+
const armPrefetch = () => {
|
|
8966
|
+
const element2 = internalRef.current;
|
|
8967
|
+
if (element2 && (isHashOnlyNavigation(element2) || isPrefetchScopeDisabled(element2))) {
|
|
8968
|
+
return () => {
|
|
8969
|
+
};
|
|
8970
|
+
}
|
|
8971
|
+
let cancelled = false;
|
|
8972
|
+
let unsubIdle;
|
|
8973
|
+
let stopObserving;
|
|
8974
|
+
const triggerPrefetch = () => {
|
|
8975
|
+
if (cancelled) return;
|
|
8976
|
+
const currentElement = internalRef.current;
|
|
8977
|
+
if (currentElement && isPrefetchScopeDisabled(currentElement)) return;
|
|
8978
|
+
const segmentState = ctx.store.getSegmentState();
|
|
8979
|
+
prefetchQueued2(
|
|
8980
|
+
resolvedTo,
|
|
8981
|
+
segmentState.currentSegmentIds,
|
|
8982
|
+
getAppVersion(),
|
|
8983
|
+
ctx.store.getRouterId?.(),
|
|
8984
|
+
prefetchKey
|
|
8985
|
+
);
|
|
8986
|
+
};
|
|
8987
|
+
if (isRender) {
|
|
8988
|
+
unsubIdle = schedulePrefetchWhenRouterIdle(
|
|
8989
|
+
ctx.eventController,
|
|
8990
|
+
triggerPrefetch
|
|
8991
|
+
);
|
|
9004
8992
|
} else {
|
|
9005
|
-
|
|
9006
|
-
|
|
8993
|
+
const viewportElement = internalRef.current;
|
|
8994
|
+
if (viewportElement) {
|
|
8995
|
+
stopObserving = observeForPrefetch(viewportElement, () => {
|
|
8996
|
+
unsubIdle = schedulePrefetchWhenRouterIdle(
|
|
8997
|
+
ctx.eventController,
|
|
8998
|
+
triggerPrefetch
|
|
8999
|
+
);
|
|
9000
|
+
});
|
|
9001
|
+
}
|
|
9002
|
+
}
|
|
9003
|
+
return () => {
|
|
9004
|
+
cancelled = true;
|
|
9005
|
+
unsubIdle?.();
|
|
9006
|
+
stopObserving?.();
|
|
9007
|
+
};
|
|
9008
|
+
};
|
|
9009
|
+
let disarmPrefetch = armPrefetch();
|
|
9010
|
+
const element = internalRef.current;
|
|
9011
|
+
const unsubscribeScope = element ? subscribeToPrefetchScopeChange(element, () => {
|
|
9012
|
+
disarmPrefetch();
|
|
9013
|
+
disarmPrefetch = armPrefetch();
|
|
9014
|
+
}) : void 0;
|
|
9015
|
+
const unsubscribeLocation = subscribeToLocationChange(
|
|
9016
|
+
ctx.eventController,
|
|
9017
|
+
() => {
|
|
9018
|
+
disarmPrefetch();
|
|
9019
|
+
disarmPrefetch = armPrefetch();
|
|
9007
9020
|
}
|
|
9021
|
+
);
|
|
9022
|
+
return () => {
|
|
9023
|
+
unsubscribeScope?.();
|
|
9024
|
+
unsubscribeLocation();
|
|
9025
|
+
disarmPrefetch();
|
|
9026
|
+
};
|
|
9027
|
+
}, [resolvedStrategy, resolvedTo, isExternal, ctx, prefetchKey]);
|
|
9028
|
+
return /* @__PURE__ */ jsx8(
|
|
9029
|
+
"a",
|
|
9030
|
+
{
|
|
9031
|
+
ref: setRef,
|
|
9032
|
+
href: resolvedTo,
|
|
9033
|
+
onClick: handleClick,
|
|
9034
|
+
onMouseEnter: handleMouseEnter,
|
|
9035
|
+
"data-link-component": true,
|
|
9036
|
+
"data-external": isExternal ? "" : void 0,
|
|
9037
|
+
"data-scroll": scroll === false ? "false" : void 0,
|
|
9038
|
+
"data-replace": replace ? "true" : void 0,
|
|
9039
|
+
"data-revalidate": revalidate2 === false ? "false" : void 0,
|
|
9040
|
+
...props,
|
|
9041
|
+
children: /* @__PURE__ */ jsx8(LinkContext.Provider, { value: resolvedTo, children })
|
|
9008
9042
|
}
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
}
|
|
9012
|
-
var Script = createHandle(collectScripts, "__rsc_router_script__");
|
|
9013
|
-
|
|
9014
|
-
// src/handles/Scripts.tsx
|
|
9015
|
-
import { useState as useState14 } from "react";
|
|
9016
|
-
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
9043
|
+
);
|
|
9044
|
+
});
|
|
9017
9045
|
|
|
9018
9046
|
// src/handles/breadcrumbs.ts
|
|
9019
9047
|
function collectBreadcrumbs(segments) {
|
|
@@ -9105,15 +9133,18 @@ var ALL_USE_ITEM_TYPES = new Set(
|
|
|
9105
9133
|
);
|
|
9106
9134
|
|
|
9107
9135
|
// src/server/request-context.ts
|
|
9108
|
-
import { AsyncLocalStorage as
|
|
9136
|
+
import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
|
|
9109
9137
|
init_cookie_name();
|
|
9110
9138
|
|
|
9139
|
+
// src/server/handle-store.ts
|
|
9140
|
+
var LOADER_SLOT = Object.freeze({ loader: true });
|
|
9141
|
+
|
|
9111
9142
|
// src/router/router-context.ts
|
|
9112
|
-
import { AsyncLocalStorage as
|
|
9113
|
-
var routerContext = new
|
|
9143
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
9144
|
+
var routerContext = new AsyncLocalStorage3();
|
|
9114
9145
|
|
|
9115
9146
|
// src/server/request-context.ts
|
|
9116
|
-
var requestContextStorage = new
|
|
9147
|
+
var requestContextStorage = new AsyncLocalStorage4();
|
|
9117
9148
|
|
|
9118
9149
|
// src/route-definition/redirect.ts
|
|
9119
9150
|
init_redirect_origin();
|
|
@@ -9307,7 +9338,7 @@ function serializeClientUrlPatterns(patterns) {
|
|
|
9307
9338
|
// src/vite/discovery/client-urls-projection.ts
|
|
9308
9339
|
init_client_ref_hashing();
|
|
9309
9340
|
init_debug();
|
|
9310
|
-
var
|
|
9341
|
+
var debug10 = createRangoDebugger(NS.discovery);
|
|
9311
9342
|
function hasDefaultExport(code) {
|
|
9312
9343
|
let program;
|
|
9313
9344
|
try {
|
|
@@ -9396,7 +9427,7 @@ async function refreshRecordedClientUrlProjections(state, ssrEnv, serverMod) {
|
|
|
9396
9427
|
const projection = serializeClientUrlPatterns(
|
|
9397
9428
|
definition
|
|
9398
9429
|
);
|
|
9399
|
-
|
|
9430
|
+
debug10?.(
|
|
9400
9431
|
"pre-entry refresh %s -> [%s]",
|
|
9401
9432
|
source,
|
|
9402
9433
|
projection.routes.map((route2) => route2.pattern).join(", ")
|
|
@@ -9478,21 +9509,21 @@ async function discoverClientUrlProjections(state, ssrEnv, serverMod) {
|
|
|
9478
9509
|
}
|
|
9479
9510
|
|
|
9480
9511
|
// src/vite/discovery/discover-routers.ts
|
|
9481
|
-
var
|
|
9512
|
+
var debug11 = createRangoDebugger(NS.discovery);
|
|
9482
9513
|
async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
9483
9514
|
if (!state.resolvedEntryPath) return;
|
|
9484
9515
|
const serverMod = await timed(
|
|
9485
|
-
|
|
9516
|
+
debug11,
|
|
9486
9517
|
"inner: import @rangojs/router/server",
|
|
9487
9518
|
() => rscEnv.runner.import("@rangojs/router/server")
|
|
9488
9519
|
);
|
|
9489
9520
|
await timed(
|
|
9490
|
-
|
|
9521
|
+
debug11,
|
|
9491
9522
|
"inner: refresh recorded client URL projections",
|
|
9492
9523
|
() => refreshRecordedClientUrlProjections(state, ssrEnv, serverMod)
|
|
9493
9524
|
);
|
|
9494
9525
|
await timed(
|
|
9495
|
-
|
|
9526
|
+
debug11,
|
|
9496
9527
|
"inner: import entry",
|
|
9497
9528
|
() => rscEnv.runner.import(state.resolvedEntryPath)
|
|
9498
9529
|
);
|
|
@@ -9508,7 +9539,7 @@ async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
|
9508
9539
|
const handlerErrors = await resolveHostRouterHandlers(hostRegistry);
|
|
9509
9540
|
discoveryErrors.push(...handlerErrors);
|
|
9510
9541
|
for (const { context, error } of handlerErrors) {
|
|
9511
|
-
|
|
9542
|
+
debug11?.("caught error while resolving %s: %O", context, error);
|
|
9512
9543
|
}
|
|
9513
9544
|
const freshServerMod = await rscEnv.runner.import(
|
|
9514
9545
|
"@rangojs/router/server"
|
|
@@ -9527,17 +9558,17 @@ async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
|
9527
9558
|
}
|
|
9528
9559
|
}
|
|
9529
9560
|
await timed(
|
|
9530
|
-
|
|
9561
|
+
debug11,
|
|
9531
9562
|
"inner: discover client URL projections",
|
|
9532
9563
|
() => discoverClientUrlProjections(state, ssrEnv, serverMod)
|
|
9533
9564
|
);
|
|
9534
9565
|
const buildMod = await timed(
|
|
9535
|
-
|
|
9566
|
+
debug11,
|
|
9536
9567
|
"inner: import @rangojs/router/build",
|
|
9537
9568
|
() => rscEnv.runner.import("@rangojs/router/build")
|
|
9538
9569
|
);
|
|
9539
9570
|
const generateManifestFull = buildMod.generateManifestFull;
|
|
9540
|
-
|
|
9571
|
+
debug11?.("inner: found %d router(s) in registry", registry.size);
|
|
9541
9572
|
const nestedRouterConflict = findNestedRouterConflict(
|
|
9542
9573
|
[...registry.values()].map((router) => router.__sourceFile).filter(
|
|
9543
9574
|
(sourceFile) => typeof sourceFile === "string"
|
|
@@ -9562,7 +9593,7 @@ async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
|
9562
9593
|
collectFallbackClientRefs(node, collectClientFallbackRef);
|
|
9563
9594
|
}
|
|
9564
9595
|
};
|
|
9565
|
-
const manifestGenStart =
|
|
9596
|
+
const manifestGenStart = debug11 ? performance.now() : 0;
|
|
9566
9597
|
for (const [id, router] of registry) {
|
|
9567
9598
|
if (!generateManifestFull) {
|
|
9568
9599
|
continue;
|
|
@@ -9640,12 +9671,12 @@ async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
|
9640
9671
|
);
|
|
9641
9672
|
}
|
|
9642
9673
|
}
|
|
9643
|
-
|
|
9674
|
+
debug11?.(
|
|
9644
9675
|
"inner: generated manifests for %d router(s) (%sms)",
|
|
9645
9676
|
allManifests.length,
|
|
9646
9677
|
(performance.now() - manifestGenStart).toFixed(1)
|
|
9647
9678
|
);
|
|
9648
|
-
const trieStart =
|
|
9679
|
+
const trieStart = debug11 ? performance.now() : 0;
|
|
9649
9680
|
if (Object.keys(newMergedRouteManifest).length > 0) {
|
|
9650
9681
|
for (const { id, manifest } of allManifests) {
|
|
9651
9682
|
const perRouterTrie = buildPerRouterTrie(manifest);
|
|
@@ -9654,7 +9685,7 @@ async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
|
9654
9685
|
}
|
|
9655
9686
|
}
|
|
9656
9687
|
}
|
|
9657
|
-
|
|
9688
|
+
debug11?.(
|
|
9658
9689
|
"inner: trie build done (%sms)",
|
|
9659
9690
|
(performance.now() - trieStart).toFixed(1)
|
|
9660
9691
|
);
|
|
@@ -9689,7 +9720,7 @@ function buildShellManifestKey(pathname) {
|
|
|
9689
9720
|
|
|
9690
9721
|
// src/vite/discovery/shell-prerender-phase.ts
|
|
9691
9722
|
init_debug();
|
|
9692
|
-
var
|
|
9723
|
+
var debug12 = createRangoDebugger(NS.prerender);
|
|
9693
9724
|
async function runShellPrerenderPhase(s, builder) {
|
|
9694
9725
|
const tempServer = s.shellPhaseTempServer;
|
|
9695
9726
|
if (!s.isBuildMode || !s.shellCandidates?.length || !tempServer) return;
|
|
@@ -9745,7 +9776,7 @@ async function runShellPrerenderPhase(s, builder) {
|
|
|
9745
9776
|
const base = builder?.config?.base ?? "/";
|
|
9746
9777
|
const normalizedBase = base.endsWith("/") ? base : `${base}/`;
|
|
9747
9778
|
const bootstrapContent = `import("${normalizedBase}assets/${entryFile}")`;
|
|
9748
|
-
|
|
9779
|
+
debug12?.("shell prerender bootstrap: %s", bootstrapContent);
|
|
9749
9780
|
const minimalPlugin = (tempServer.config?.plugins ?? []).find(
|
|
9750
9781
|
(p) => p?.name === "rsc:minimal"
|
|
9751
9782
|
);
|
|
@@ -9832,7 +9863,7 @@ async function runShellPrerenderPhase(s, builder) {
|
|
|
9832
9863
|
buildEnv: s.resolvedBuildEnv,
|
|
9833
9864
|
buildVersion,
|
|
9834
9865
|
captureShellHTML,
|
|
9835
|
-
debug: !!
|
|
9866
|
+
debug: !!debug12
|
|
9836
9867
|
});
|
|
9837
9868
|
if (res.outcome === "route-mismatch") {
|
|
9838
9869
|
mismatches.push(res.matchedRouteName ?? "(no match)");
|
|
@@ -10414,7 +10445,7 @@ function postprocessBundle(state) {
|
|
|
10414
10445
|
}
|
|
10415
10446
|
|
|
10416
10447
|
// src/vite/discovery/gate-state.ts
|
|
10417
|
-
function createDiscoveryGate(s,
|
|
10448
|
+
function createDiscoveryGate(s, debug13) {
|
|
10418
10449
|
let gatePending = false;
|
|
10419
10450
|
let gateResolver = () => {
|
|
10420
10451
|
};
|
|
@@ -10431,7 +10462,7 @@ function createDiscoveryGate(s, debug14) {
|
|
|
10431
10462
|
const resolveGate = () => {
|
|
10432
10463
|
if (!gatePending) return;
|
|
10433
10464
|
if (inProgress || queued2 || pendingEvents) {
|
|
10434
|
-
|
|
10465
|
+
debug13?.(
|
|
10435
10466
|
"hmr: resolveGate deferred \u2014 work in flight (inProgress=%s queued=%s pendingEvents=%s)",
|
|
10436
10467
|
inProgress,
|
|
10437
10468
|
queued2,
|
|
@@ -10440,7 +10471,7 @@ function createDiscoveryGate(s, debug14) {
|
|
|
10440
10471
|
return;
|
|
10441
10472
|
}
|
|
10442
10473
|
gatePending = false;
|
|
10443
|
-
|
|
10474
|
+
debug13?.("hmr: discoveryDone resolved");
|
|
10444
10475
|
gateResolver();
|
|
10445
10476
|
};
|
|
10446
10477
|
const noteRouteEvent = () => {
|
|
@@ -10450,7 +10481,7 @@ function createDiscoveryGate(s, debug14) {
|
|
|
10450
10481
|
const runRefreshCycle = async (work) => {
|
|
10451
10482
|
if (inProgress) {
|
|
10452
10483
|
queued2 = true;
|
|
10453
|
-
|
|
10484
|
+
debug13?.("hmr: rediscovery in flight \u2014 queued for a follow-up cycle");
|
|
10454
10485
|
return;
|
|
10455
10486
|
}
|
|
10456
10487
|
pendingEvents = false;
|
|
@@ -10461,16 +10492,16 @@ function createDiscoveryGate(s, debug14) {
|
|
|
10461
10492
|
inProgress = false;
|
|
10462
10493
|
if (queued2) {
|
|
10463
10494
|
queued2 = false;
|
|
10464
|
-
|
|
10495
|
+
debug13?.("hmr: consuming queued rediscovery");
|
|
10465
10496
|
runRefreshCycle(work).catch((err) => {
|
|
10466
|
-
|
|
10497
|
+
debug13?.(
|
|
10467
10498
|
"hmr: queued cycle rejected \u2014 releasing gate (%s)",
|
|
10468
10499
|
err instanceof Error ? err.message : String(err)
|
|
10469
10500
|
);
|
|
10470
10501
|
resolveGate();
|
|
10471
10502
|
});
|
|
10472
10503
|
} else if (pendingEvents) {
|
|
10473
|
-
|
|
10504
|
+
debug13?.(
|
|
10474
10505
|
"hmr: holding gate for pending events (debounce not yet fired)"
|
|
10475
10506
|
);
|
|
10476
10507
|
} else {
|
|
@@ -12437,7 +12468,11 @@ If this is a multi-app host router, export a createHostRouter() instance and set
|
|
|
12437
12468
|
plugins.push(createLoaderDirectiveGuardPlugin());
|
|
12438
12469
|
plugins.push(createLoaderScanStubPlugin());
|
|
12439
12470
|
plugins.push(exposeActionId());
|
|
12440
|
-
plugins.push(
|
|
12471
|
+
plugins.push(
|
|
12472
|
+
useCacheTransform(
|
|
12473
|
+
createCounter(createRangoDebugger(NS.transform), "use-cache")
|
|
12474
|
+
)
|
|
12475
|
+
);
|
|
12441
12476
|
plugins.push(exposeInternalIds());
|
|
12442
12477
|
plugins.push(exposeRouterId());
|
|
12443
12478
|
plugins.push(createVersionPlugin());
|
|
@@ -12481,7 +12516,7 @@ function poke() {
|
|
|
12481
12516
|
apply: "serve",
|
|
12482
12517
|
configureServer(server) {
|
|
12483
12518
|
const stdin = process.stdin;
|
|
12484
|
-
const
|
|
12519
|
+
const debug13 = process.env.RANGO_POKE_DEBUG === "1";
|
|
12485
12520
|
const triggerReload = (source) => {
|
|
12486
12521
|
server.hot.send({ type: "full-reload", path: "*" });
|
|
12487
12522
|
server.config.logger.info(` browser reload (${source})`, {
|
|
@@ -12514,7 +12549,7 @@ function poke() {
|
|
|
12514
12549
|
lines.pop();
|
|
12515
12550
|
return lines;
|
|
12516
12551
|
};
|
|
12517
|
-
if (
|
|
12552
|
+
if (debug13) {
|
|
12518
12553
|
server.config.logger.info(
|
|
12519
12554
|
` poke debug enabled (isTTY=${stdin.isTTY ? "yes" : "no"}, isRaw=${stdin.isTTY ? stdin.isRaw ? "yes" : "no" : "n/a"})`,
|
|
12520
12555
|
{ timestamp: true }
|
|
@@ -12527,7 +12562,7 @@ function poke() {
|
|
|
12527
12562
|
);
|
|
12528
12563
|
}
|
|
12529
12564
|
const onData = (data) => {
|
|
12530
|
-
if (
|
|
12565
|
+
if (debug13) {
|
|
12531
12566
|
server.config.logger.info(` poke stdin ${formatChunk(data)}`, {
|
|
12532
12567
|
timestamp: true
|
|
12533
12568
|
});
|