@rangojs/router 0.22.1 → 0.24.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/dist/bin/rango.js +10 -4
- package/dist/testing/vitest.js +31 -1
- package/dist/types/browser/defer.d.ts +48 -0
- package/dist/types/browser/document-revealed.d.ts +17 -0
- package/dist/types/browser/event-controller.d.ts +7 -1
- package/dist/types/browser/merge-segment-loaders.d.ts +5 -2
- package/dist/types/browser/navigation-transaction.d.ts +21 -7
- package/dist/types/browser/partial-update.d.ts +39 -8
- package/dist/types/browser/react/NavigationProvider.d.ts +19 -5
- package/dist/types/browser/react/context.d.ts +3 -2
- package/dist/types/browser/react/filter-segment-order.d.ts +7 -0
- package/dist/types/browser/response-adapter.d.ts +7 -0
- package/dist/types/browser/types.d.ts +24 -10
- package/dist/types/browser/validate-redirect-origin.d.ts +11 -0
- package/dist/types/build/generate-route-types.d.ts +1 -1
- package/dist/types/build/route-types/router-processing.d.ts +1 -1
- package/dist/types/build/route-types/scan-filter.d.ts +22 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +16 -1
- package/dist/types/cache/cf/cf-cache-types.d.ts +23 -2
- package/dist/types/cache/document-cache-policy.d.ts +24 -0
- package/dist/types/cache/document-cache.d.ts +2 -10
- package/dist/types/client-urls/client-urls.d.ts +1 -1
- package/dist/types/client-urls/hoisted-revalidate.d.ts +13 -0
- package/dist/types/client-urls/navigation.d.ts +0 -37
- package/dist/types/client-urls/revalidate-registry.d.ts +4 -0
- package/dist/types/client-urls/server-projection.d.ts +29 -1
- package/dist/types/client-urls/types.d.ts +34 -69
- package/dist/types/client.d.ts +0 -1
- package/dist/types/context-var.d.ts +12 -0
- package/dist/types/errors.d.ts +15 -0
- package/dist/types/handles/deferred-resolution.d.ts +2 -1
- package/dist/types/handles/pushed-by.d.ts +31 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.rsc.d.ts +2 -0
- package/dist/types/loader-store.d.ts +8 -0
- package/dist/types/prefetch-markers.d.ts +11 -0
- package/dist/types/response-utils.d.ts +7 -0
- package/dist/types/reverse.d.ts +8 -8
- package/dist/types/route-definition/helpers-types.d.ts +27 -0
- package/dist/types/route-definition/rewrite.d.ts +56 -0
- package/dist/types/route-map-builder.d.ts +7 -2
- package/dist/types/router/basename.d.ts +7 -0
- package/dist/types/router/handler-context.d.ts +1 -5
- package/dist/types/router/internal-params.d.ts +8 -0
- package/dist/types/router/is-action.d.ts +2 -1
- package/dist/types/router/middleware-types.d.ts +15 -0
- package/dist/types/router/revalidation.d.ts +1 -2
- package/dist/types/router/route-trie-builder.d.ts +10 -0
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -2
- package/dist/types/router/segment-resolution/mask-nested.d.ts +4 -2
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +264 -0
- package/dist/types/rsc/full-payload.d.ts +11 -0
- package/dist/types/rsc/handler.d.ts +33 -0
- package/dist/types/rsc/helpers.d.ts +8 -0
- package/dist/types/rsc/loader-fetch.d.ts +16 -0
- package/dist/types/rsc/rewrite-passes.d.ts +74 -0
- package/dist/types/rsc/ssr-setup.d.ts +3 -1
- package/dist/types/server/context.d.ts +21 -1
- package/dist/types/server/handle-store.d.ts +9 -1
- package/dist/types/server/request-context.d.ts +52 -2
- package/dist/types/server/rewrite-trail.d.ts +49 -0
- package/dist/types/server/slot-accessors.d.ts +29 -0
- package/dist/types/server.d.ts +1 -0
- package/dist/types/testing/flight.entry.d.ts +1 -1
- package/dist/types/testing/index.d.ts +4 -4
- package/dist/types/testing/internal/action-id.d.ts +10 -1
- package/dist/types/testing/internal/client-urls-projection.d.ts +16 -0
- package/dist/types/testing/internal/test-action.d.ts +8 -0
- package/dist/types/testing/render-route.d.ts +8 -0
- package/dist/types/testing/run-loader.d.ts +2 -1
- package/dist/types/testing/run-middleware.d.ts +20 -0
- package/dist/types/testing/run-revalidate.d.ts +74 -0
- package/dist/types/testing/run-transition-when.d.ts +2 -3
- package/dist/types/testing/serve-shell-request.d.ts +40 -1
- package/dist/types/testing/vitest.d.ts +11 -0
- package/dist/types/thenable-status.d.ts +6 -0
- package/dist/types/types/boundaries.d.ts +9 -0
- package/dist/types/types/handler-context.d.ts +14 -0
- package/dist/types/types/loader-types.d.ts +30 -0
- package/dist/types/types/request-scope.d.ts +7 -0
- package/dist/types/types/segments.d.ts +21 -4
- package/dist/types/urls/path-helper-types.d.ts +25 -4
- package/dist/types/urls/type-extraction.d.ts +6 -2
- package/dist/types/vite/discovery/discover-routers.d.ts +9 -0
- package/dist/types/vite/discovery/state.d.ts +14 -4
- package/dist/types/vite/plugins/client-urls-revalidate-hoist.d.ts +54 -0
- package/dist/types/vite/plugins/hoist/literal.d.ts +83 -0
- package/dist/types/vite/plugins/hoist/scope.d.ts +40 -0
- package/dist/types/vite/plugins/hoist/source.d.ts +41 -0
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +8 -11
- package/dist/types/vite/router-discovery.d.ts +10 -0
- package/dist/vite/index.js +974 -379
- package/package.json +1 -1
- package/skills/caching/SKILL.md +54 -5
- package/skills/catalog.json +3 -3
- package/skills/client-urls/SKILL.md +197 -24
- package/skills/cloudflare/SKILL.md +14 -9
- package/skills/hooks/SKILL.md +16 -3
- package/skills/hooks/data.md +3 -1
- package/skills/links/SKILL.md +24 -0
- package/skills/loader/SKILL.md +199 -2
- package/skills/middleware/SKILL.md +183 -2
- package/skills/migrate-nextjs/SKILL.md +2 -2
- package/skills/migrate-react-router/SKILL.md +10 -7
- package/skills/migrate-react-router/data-and-actions.md +1 -1
- package/skills/ppr/SKILL.md +22 -0
- package/skills/prerender/SKILL.md +22 -8
- package/skills/rango/SKILL.md +13 -7
- package/skills/route/SKILL.md +139 -0
- package/skills/server-actions/SKILL.md +27 -0
- package/skills/testing/SKILL.md +3 -2
- package/skills/testing/client-components.md +2 -1
- package/skills/testing/middleware.md +31 -10
- package/skills/testing/predicates.md +67 -32
- package/skills/testing/response-routes.md +1 -0
- package/skills/testing/serve-shell-request.md +107 -19
- package/skills/testing/setup.md +2 -2
- package/skills/typesafety/route-types.md +2 -2
- package/skills/use-cache/SKILL.md +4 -2
- package/skills/view-transitions/SKILL.md +26 -0
- package/src/__augment-tests__/augmented.check.ts +20 -0
- package/src/browser/defer.ts +82 -0
- package/src/browser/document-revealed.ts +52 -0
- package/src/browser/event-controller.ts +46 -32
- package/src/browser/merge-segment-loaders.ts +31 -18
- package/src/browser/navigation-bridge.ts +82 -16
- package/src/browser/navigation-client.ts +48 -36
- package/src/browser/navigation-store.ts +13 -0
- package/src/browser/navigation-transaction.ts +25 -8
- package/src/browser/partial-update.ts +554 -146
- package/src/browser/prefetch/fetch.ts +2 -1
- package/src/browser/react/Link.tsx +7 -9
- package/src/browser/react/NavigationProvider.tsx +88 -49
- package/src/browser/react/context.ts +3 -2
- package/src/browser/react/filter-segment-order.ts +13 -2
- package/src/browser/react/use-router.ts +2 -4
- package/src/browser/response-adapter.ts +20 -0
- package/src/browser/rsc-router.tsx +17 -45
- package/src/browser/server-action-bridge.ts +25 -63
- package/src/browser/types.ts +24 -10
- package/src/browser/validate-redirect-origin.ts +16 -0
- package/src/build/generate-route-types.ts +1 -0
- package/src/build/route-types/router-processing.ts +3 -6
- package/src/build/route-types/scan-filter.ts +45 -11
- package/src/cache/cf/cf-cache-store.ts +59 -21
- package/src/cache/cf/cf-cache-types.ts +24 -2
- package/src/cache/document-cache-policy.ts +131 -0
- package/src/cache/document-cache.ts +21 -107
- package/src/client-urls/client-urls.ts +22 -6
- package/src/client-urls/hoisted-revalidate.ts +25 -0
- package/src/client-urls/navigation.ts +0 -96
- package/src/client-urls/revalidate-registry.ts +30 -0
- package/src/client-urls/server-projection.ts +151 -65
- package/src/client-urls/types.ts +39 -71
- package/src/client.tsx +9 -5
- package/src/context-var.ts +32 -2
- package/src/errors.ts +34 -0
- package/src/handles/deferred-resolution.ts +28 -5
- package/src/handles/pushed-by.ts +148 -0
- package/src/index.rsc.ts +8 -0
- package/src/index.ts +7 -0
- package/src/loader-store.ts +18 -7
- package/src/prefetch-markers.ts +13 -0
- package/src/response-utils.ts +19 -0
- package/src/reverse.ts +17 -14
- package/src/route-content-wrapper.tsx +18 -4
- package/src/route-definition/dsl-helpers.ts +27 -4
- package/src/route-definition/helpers-types.ts +27 -1
- package/src/route-definition/redirect.ts +2 -15
- package/src/route-definition/rewrite.ts +146 -0
- package/src/route-map-builder.ts +14 -11
- package/src/router/basename.ts +20 -0
- package/src/router/handler-context.ts +3 -13
- package/src/router/intercept-resolution.ts +35 -16
- package/src/router/internal-params.ts +16 -0
- package/src/router/is-action.ts +2 -1
- package/src/router/loader-resolution.ts +85 -4
- package/src/router/match-api.ts +36 -1
- package/src/router/match-middleware/background-revalidation.ts +16 -4
- package/src/router/match-middleware/cache-lookup.ts +35 -7
- package/src/router/match-middleware/cache-store.ts +15 -1
- package/src/router/match-middleware/intercept-resolution.ts +4 -2
- package/src/router/match-result.ts +14 -2
- package/src/router/middleware-types.ts +16 -0
- package/src/router/middleware.ts +127 -49
- package/src/router/navigation-snapshot.ts +2 -1
- package/src/router/revalidation.ts +1 -1
- package/src/router/route-trie-builder.ts +28 -1
- package/src/router/segment-resolution/fresh.ts +22 -18
- package/src/router/segment-resolution/loader-cache.ts +2 -1
- package/src/router/segment-resolution/loader-mask.ts +5 -3
- package/src/router/segment-resolution/loader-snapshot.ts +18 -4
- package/src/router/segment-resolution/mask-nested.ts +8 -4
- package/src/router/segment-resolution/prefetch-deferral.ts +583 -0
- package/src/router/segment-resolution/revalidation.ts +215 -82
- package/src/rsc/full-payload.ts +37 -5
- package/src/rsc/handler.ts +82 -55
- package/src/rsc/helpers.ts +24 -0
- package/src/rsc/loader-fetch.ts +79 -24
- package/src/rsc/response-cache-serve.ts +18 -2
- package/src/rsc/response-route-handler.ts +4 -7
- package/src/rsc/rewrite-passes.ts +203 -0
- package/src/rsc/rsc-rendering.ts +54 -9
- package/src/rsc/shell-capture.ts +2 -1
- package/src/rsc/ssr-setup.ts +11 -5
- package/src/segment-loader-promise.ts +23 -20
- package/src/segment-system.tsx +60 -26
- package/src/server/context.ts +39 -5
- package/src/server/cookie-parse.ts +36 -12
- package/src/server/cookie-store.ts +7 -3
- package/src/server/handle-store.ts +152 -25
- package/src/server/request-context.ts +175 -64
- package/src/server/request-headers.ts +4 -14
- package/src/server/rewrite-trail.ts +190 -0
- package/src/server/slot-accessors.ts +57 -0
- package/src/server.ts +4 -0
- package/src/ssr/index.tsx +118 -16
- package/src/testing/action-form.ts +2 -11
- package/src/testing/dispatch.ts +138 -67
- package/src/testing/e2e/page-helpers.ts +3 -1
- package/src/testing/flight.entry.ts +1 -0
- package/src/testing/index.ts +7 -3
- package/src/testing/internal/action-id.ts +16 -1
- package/src/testing/internal/client-urls-projection.ts +70 -0
- package/src/testing/internal/test-action.ts +25 -0
- package/src/testing/render-route.tsx +16 -3
- package/src/testing/run-loader.ts +4 -1
- package/src/testing/run-middleware.ts +56 -11
- package/src/testing/run-revalidate.ts +142 -0
- package/src/testing/run-transition-when.ts +7 -8
- package/src/testing/serve-shell-request.ts +131 -8
- package/src/testing/vitest.ts +67 -1
- package/src/thenable-status.ts +11 -0
- package/src/types/boundaries.ts +12 -0
- package/src/types/handler-context.ts +14 -0
- package/src/types/loader-types.ts +30 -0
- package/src/types/request-scope.ts +8 -0
- package/src/types/segments.ts +26 -4
- package/src/urls/path-helper-types.ts +27 -5
- package/src/urls/type-extraction.ts +30 -10
- package/src/use-loader.tsx +18 -13
- package/src/vite/discovery/client-urls-projection.ts +20 -21
- package/src/vite/discovery/discover-routers.ts +94 -26
- package/src/vite/discovery/state.ts +28 -4
- package/src/vite/discovery/virtual-module-codegen.ts +22 -17
- package/src/vite/plugins/client-urls-revalidate-hoist.ts +564 -0
- package/src/vite/plugins/expose-internal-ids.ts +2 -3
- package/src/vite/plugins/hoist/literal.ts +417 -0
- package/src/vite/plugins/hoist/scope.ts +370 -0
- package/src/vite/plugins/hoist/source.ts +84 -0
- package/src/vite/plugins/transition-when-hoist.ts +113 -779
- package/src/vite/rango.ts +2 -0
- package/src/vite/router-discovery.ts +116 -53
- package/dist/types/client-urls/revalidate-chain.d.ts +0 -33
- package/dist/types/client-urls/revalidation-protocol.d.ts +0 -25
- package/dist/types/testing/run-client-revalidate.d.ts +0 -43
- package/src/client-urls/revalidate-chain.ts +0 -83
- package/src/client-urls/revalidation-protocol.ts +0 -56
- package/src/testing/run-client-revalidate.ts +0 -92
package/dist/vite/index.js
CHANGED
|
@@ -119,10 +119,10 @@ __export(client_ref_hashing_exports, {
|
|
|
119
119
|
hashRefKey: () => hashRefKey,
|
|
120
120
|
transformClientRefs: () => transformClientRefs
|
|
121
121
|
});
|
|
122
|
-
import { relative as
|
|
123
|
-
import { createHash as
|
|
122
|
+
import { relative as relative4 } from "node:path";
|
|
123
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
124
124
|
function hashRefKey(relativeId) {
|
|
125
|
-
return
|
|
125
|
+
return createHash3("sha256").update(relativeId).digest("hex").slice(0, 12);
|
|
126
126
|
}
|
|
127
127
|
function computeProductionHash(projectRoot, refKey) {
|
|
128
128
|
let toHash;
|
|
@@ -132,10 +132,10 @@ function computeProductionHash(projectRoot, refKey) {
|
|
|
132
132
|
const absPath = decodeURIComponent(
|
|
133
133
|
refKey.slice(CLIENT_IN_SERVER_PKG_PROXY_PREFIX.length)
|
|
134
134
|
);
|
|
135
|
-
toHash =
|
|
135
|
+
toHash = relative4(projectRoot, absPath).replaceAll("\\", "/");
|
|
136
136
|
} else if (refKey.startsWith(FS_PREFIX)) {
|
|
137
137
|
const absPath = refKey.slice(FS_PREFIX.length - 1);
|
|
138
|
-
toHash =
|
|
138
|
+
toHash = relative4(projectRoot, absPath).replaceAll("\\", "/");
|
|
139
139
|
} else if (refKey.startsWith("/")) {
|
|
140
140
|
toHash = refKey.slice(1);
|
|
141
141
|
} else {
|
|
@@ -733,6 +733,15 @@ var init_segment_fragments = __esm({
|
|
|
733
733
|
}
|
|
734
734
|
});
|
|
735
735
|
|
|
736
|
+
// src/prefetch-markers.ts
|
|
737
|
+
var PREFETCH_HEADER;
|
|
738
|
+
var init_prefetch_markers = __esm({
|
|
739
|
+
"src/prefetch-markers.ts"() {
|
|
740
|
+
"use strict";
|
|
741
|
+
PREFETCH_HEADER = "X-Rango-Prefetch";
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
|
|
736
745
|
// src/browser/prefetch/fetch.ts
|
|
737
746
|
function setPrefetchDecoder(fn) {
|
|
738
747
|
decoder = fn;
|
|
@@ -826,7 +835,7 @@ function executePrefetchFetch(wildcardKey, sourceKey, fetchUrl, forceSourceScope
|
|
|
826
835
|
headers: {
|
|
827
836
|
"X-Rango-State": rangoState,
|
|
828
837
|
"X-RSC-Router-Client-Path": window.location.href,
|
|
829
|
-
|
|
838
|
+
[PREFETCH_HEADER]: "1",
|
|
830
839
|
...isFragmentPassthroughEnabled() && {
|
|
831
840
|
[SEGMENT_FRAGMENT_CAPABILITY_HEADER]: "1"
|
|
832
841
|
}
|
|
@@ -1006,6 +1015,7 @@ var init_fetch = __esm({
|
|
|
1006
1015
|
init_logging();
|
|
1007
1016
|
init_response_adapter();
|
|
1008
1017
|
init_segment_fragments();
|
|
1018
|
+
init_prefetch_markers();
|
|
1009
1019
|
decoder = null;
|
|
1010
1020
|
PREFETCH_FETCH_TIMEOUT_MS = 3e4;
|
|
1011
1021
|
}
|
|
@@ -1633,10 +1643,10 @@ import path4 from "node:path";
|
|
|
1633
1643
|
function isDirectivePrologueStatement(node) {
|
|
1634
1644
|
return node?.type === "ExpressionStatement" && typeof node.directive === "string";
|
|
1635
1645
|
}
|
|
1636
|
-
function findImportInsertionPos(code,
|
|
1646
|
+
function findImportInsertionPos(code, parseAst9) {
|
|
1637
1647
|
let program;
|
|
1638
1648
|
try {
|
|
1639
|
-
program =
|
|
1649
|
+
program = parseAst9(code, { lang: "tsx" });
|
|
1640
1650
|
} catch {
|
|
1641
1651
|
return 0;
|
|
1642
1652
|
}
|
|
@@ -1673,10 +1683,10 @@ function walkNode(node, parent, ancestors, enter) {
|
|
|
1673
1683
|
}
|
|
1674
1684
|
ancestors.pop();
|
|
1675
1685
|
}
|
|
1676
|
-
function findHandlerCalls(code, fnName,
|
|
1686
|
+
function findHandlerCalls(code, fnName, parseAst9) {
|
|
1677
1687
|
let program;
|
|
1678
1688
|
try {
|
|
1679
|
-
program =
|
|
1689
|
+
program = parseAst9(code, { lang: "tsx" });
|
|
1680
1690
|
} catch {
|
|
1681
1691
|
return [];
|
|
1682
1692
|
}
|
|
@@ -1748,18 +1758,18 @@ function getImportedLocalNamesFromProgram(program, importedName) {
|
|
|
1748
1758
|
}
|
|
1749
1759
|
return localNames;
|
|
1750
1760
|
}
|
|
1751
|
-
function getImportedLocalNames(code, importedName,
|
|
1761
|
+
function getImportedLocalNames(code, importedName, parseAst9) {
|
|
1752
1762
|
try {
|
|
1753
|
-
const program =
|
|
1763
|
+
const program = parseAst9(code, { lang: "tsx" });
|
|
1754
1764
|
return getImportedLocalNamesFromProgram(program, importedName);
|
|
1755
1765
|
} catch {
|
|
1756
1766
|
return /* @__PURE__ */ new Set();
|
|
1757
1767
|
}
|
|
1758
1768
|
}
|
|
1759
|
-
function extractImportDeclarations(code,
|
|
1769
|
+
function extractImportDeclarations(code, parseAst9) {
|
|
1760
1770
|
let program;
|
|
1761
1771
|
try {
|
|
1762
|
-
program =
|
|
1772
|
+
program = parseAst9(code, { lang: "tsx" });
|
|
1763
1773
|
} catch {
|
|
1764
1774
|
return [];
|
|
1765
1775
|
}
|
|
@@ -1816,10 +1826,10 @@ function isSafeVariableDeclaration(node, handlerNames) {
|
|
|
1816
1826
|
(d) => isSafeDeclaratorInit(d.init) && !(d.init?.type === "CallExpression" && d.init.callee?.type === "Identifier" && handlerNames.has(d.init.callee.name))
|
|
1817
1827
|
);
|
|
1818
1828
|
}
|
|
1819
|
-
function extractModuleLevelDeclarations(code,
|
|
1829
|
+
function extractModuleLevelDeclarations(code, parseAst9, handlerNames) {
|
|
1820
1830
|
let program;
|
|
1821
1831
|
try {
|
|
1822
|
-
program =
|
|
1832
|
+
program = parseAst9(code, { lang: "tsx" });
|
|
1823
1833
|
} catch {
|
|
1824
1834
|
return [];
|
|
1825
1835
|
}
|
|
@@ -1850,17 +1860,17 @@ function extractModuleLevelDeclarations(code, parseAst8, handlerNames) {
|
|
|
1850
1860
|
}
|
|
1851
1861
|
return declarations;
|
|
1852
1862
|
}
|
|
1853
|
-
function transformInlineHandlers(fnName, virtualPrefix, s, code, filePath, virtualRegistry, moduleId,
|
|
1854
|
-
const sites = findHandlerCalls(code, fnName,
|
|
1863
|
+
function transformInlineHandlers(fnName, virtualPrefix, s, code, filePath, virtualRegistry, moduleId, parseAst9) {
|
|
1864
|
+
const sites = findHandlerCalls(code, fnName, parseAst9);
|
|
1855
1865
|
const inlineSites = sites.filter((site) => site.exportInfo === null);
|
|
1856
1866
|
if (inlineSites.length === 0) return false;
|
|
1857
|
-
const imports = extractImportDeclarations(code,
|
|
1858
|
-
const staticNames = getImportedLocalNames(code, "Static",
|
|
1859
|
-
const prerenderNames = getImportedLocalNames(code, "Prerender",
|
|
1867
|
+
const imports = extractImportDeclarations(code, parseAst9);
|
|
1868
|
+
const staticNames = getImportedLocalNames(code, "Static", parseAst9);
|
|
1869
|
+
const prerenderNames = getImportedLocalNames(code, "Prerender", parseAst9);
|
|
1860
1870
|
const handlerNames = /* @__PURE__ */ new Set([...staticNames, ...prerenderNames]);
|
|
1861
1871
|
const declarations = extractModuleLevelDeclarations(
|
|
1862
1872
|
code,
|
|
1863
|
-
|
|
1873
|
+
parseAst9,
|
|
1864
1874
|
handlerNames
|
|
1865
1875
|
);
|
|
1866
1876
|
const importStatements = [];
|
|
@@ -1883,7 +1893,7 @@ function transformInlineHandlers(fnName, virtualPrefix, s, code, filePath, virtu
|
|
|
1883
1893
|
}
|
|
1884
1894
|
if (importStatements.length > 0) {
|
|
1885
1895
|
const importBlock = importStatements.join("\n") + "\n";
|
|
1886
|
-
const insertionPos = findImportInsertionPos(code,
|
|
1896
|
+
const insertionPos = findImportInsertionPos(code, parseAst9);
|
|
1887
1897
|
if (insertionPos === 0) {
|
|
1888
1898
|
s.prepend(importBlock);
|
|
1889
1899
|
} else {
|
|
@@ -1893,6 +1903,70 @@ function transformInlineHandlers(fnName, virtualPrefix, s, code, filePath, virtu
|
|
|
1893
1903
|
return true;
|
|
1894
1904
|
}
|
|
1895
1905
|
|
|
1906
|
+
// src/build/route-types/scan-filter.ts
|
|
1907
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
1908
|
+
import { readdirSync } from "node:fs";
|
|
1909
|
+
import picomatch from "picomatch";
|
|
1910
|
+
var DEFAULT_EXCLUDE_PATTERNS = [
|
|
1911
|
+
"**/__tests__/**",
|
|
1912
|
+
"**/__mocks__/**",
|
|
1913
|
+
"**/dist/**",
|
|
1914
|
+
"**/coverage/**",
|
|
1915
|
+
"**/*.test.{ts,tsx,js,jsx}",
|
|
1916
|
+
"**/*.spec.{ts,tsx,js,jsx}"
|
|
1917
|
+
];
|
|
1918
|
+
function createScanFilter(root, opts) {
|
|
1919
|
+
const { include, exclude } = opts;
|
|
1920
|
+
const hasInclude = include && include.length > 0;
|
|
1921
|
+
const hasCustomExclude = exclude !== void 0;
|
|
1922
|
+
if (!hasInclude && !hasCustomExclude) return void 0;
|
|
1923
|
+
const effectiveExclude = exclude ?? DEFAULT_EXCLUDE_PATTERNS;
|
|
1924
|
+
const includeMatcher = hasInclude ? picomatch(include) : null;
|
|
1925
|
+
const excludeMatcher = effectiveExclude.length > 0 ? picomatch(effectiveExclude) : null;
|
|
1926
|
+
return (absolutePath) => {
|
|
1927
|
+
const rel = relative(root, absolutePath);
|
|
1928
|
+
if (excludeMatcher && excludeMatcher(rel)) return false;
|
|
1929
|
+
if (includeMatcher) return includeMatcher(rel);
|
|
1930
|
+
return true;
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
function isUniversallySkippedScanDir(name) {
|
|
1934
|
+
return name === "node_modules" || name === "dist" || name === "coverage" || name.startsWith(".");
|
|
1935
|
+
}
|
|
1936
|
+
function isInSkippedScanDir(root, absolutePath) {
|
|
1937
|
+
const rel = relative(root, absolutePath);
|
|
1938
|
+
if (isAbsolute(rel)) return false;
|
|
1939
|
+
const dirs = rel.split(/[\\/]/).slice(0, -1);
|
|
1940
|
+
if (dirs[0] === "..") return false;
|
|
1941
|
+
return dirs.some(isUniversallySkippedScanDir);
|
|
1942
|
+
}
|
|
1943
|
+
function isSkippedSourceScanDir(name) {
|
|
1944
|
+
return isUniversallySkippedScanDir(name) || name === "build";
|
|
1945
|
+
}
|
|
1946
|
+
function findTsFiles(dir, filter) {
|
|
1947
|
+
const results = [];
|
|
1948
|
+
let entries;
|
|
1949
|
+
try {
|
|
1950
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
1951
|
+
} catch (err) {
|
|
1952
|
+
console.warn(
|
|
1953
|
+
`[rango] Failed to scan directory ${dir}: ${err.message}`
|
|
1954
|
+
);
|
|
1955
|
+
return results;
|
|
1956
|
+
}
|
|
1957
|
+
for (const entry of entries) {
|
|
1958
|
+
const fullPath = join(dir, entry.name);
|
|
1959
|
+
if (entry.isDirectory()) {
|
|
1960
|
+
if (isSkippedSourceScanDir(entry.name)) continue;
|
|
1961
|
+
results.push(...findTsFiles(fullPath, filter));
|
|
1962
|
+
} else if ((entry.name.endsWith(".ts") || entry.name.endsWith(".tsx") || entry.name.endsWith(".js") || entry.name.endsWith(".jsx")) && !entry.name.includes(".gen.")) {
|
|
1963
|
+
if (filter && !filter(fullPath)) continue;
|
|
1964
|
+
results.push(fullPath);
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
return results;
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1896
1970
|
// src/vite/plugins/expose-ids/types.ts
|
|
1897
1971
|
var PRERENDER_CONFIG = {
|
|
1898
1972
|
fnName: "Prerender",
|
|
@@ -2433,6 +2507,15 @@ function compareStrings(a, b) {
|
|
|
2433
2507
|
// src/vite/discovery/state.ts
|
|
2434
2508
|
var VIRTUAL_ROUTES_MANIFEST_ID = "virtual:rsc-router/routes-manifest";
|
|
2435
2509
|
var VIRTUAL_LOADER_MANIFEST_ID = "virtual:rsc-router/loader-manifest";
|
|
2510
|
+
function recordDiscoveryFailure(state, err) {
|
|
2511
|
+
state.lastDiscoveryError = {
|
|
2512
|
+
message: err?.message ?? String(err),
|
|
2513
|
+
at: Date.now()
|
|
2514
|
+
};
|
|
2515
|
+
}
|
|
2516
|
+
function canRefreshRuntimeDiscovery(state) {
|
|
2517
|
+
return state.perRouterManifests.length > 0 || !!state.lastDiscoveryError;
|
|
2518
|
+
}
|
|
2436
2519
|
function createDiscoveryState(entryPath, opts) {
|
|
2437
2520
|
return {
|
|
2438
2521
|
resolvedEntryPath: entryPath,
|
|
@@ -2733,7 +2816,6 @@ ${lazyImports.join(",\n")}
|
|
|
2733
2816
|
if (!isBuild) return;
|
|
2734
2817
|
if (this.environment && this.environment.name !== "rsc") return;
|
|
2735
2818
|
const fs2 = await import("node:fs/promises");
|
|
2736
|
-
const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "coverage"]);
|
|
2737
2819
|
async function scanDir(dir) {
|
|
2738
2820
|
const results = [];
|
|
2739
2821
|
try {
|
|
@@ -2741,7 +2823,7 @@ ${lazyImports.join(",\n")}
|
|
|
2741
2823
|
for (const entry of entries) {
|
|
2742
2824
|
const fullPath = path4.join(dir, entry.name);
|
|
2743
2825
|
if (entry.isDirectory()) {
|
|
2744
|
-
if (!
|
|
2826
|
+
if (!isSkippedSourceScanDir(entry.name)) {
|
|
2745
2827
|
results.push(...await scanDir(fullPath));
|
|
2746
2828
|
}
|
|
2747
2829
|
} else if (/\.(ts|tsx|js|jsx)$/.test(entry.name)) {
|
|
@@ -3201,18 +3283,18 @@ async function transformUseCache(code, id, options) {
|
|
|
3201
3283
|
return;
|
|
3202
3284
|
}
|
|
3203
3285
|
}
|
|
3204
|
-
const { hasDirective:
|
|
3286
|
+
const { hasDirective: hasDirective4, transformWrapExport, transformHoistInlineDirective } = rscTransforms;
|
|
3205
3287
|
let ast;
|
|
3206
3288
|
try {
|
|
3207
|
-
const { parseAst:
|
|
3208
|
-
ast =
|
|
3289
|
+
const { parseAst: parseAst9 } = await import("vite");
|
|
3290
|
+
ast = parseAst9(code, { lang: "tsx" });
|
|
3209
3291
|
} catch {
|
|
3210
3292
|
return;
|
|
3211
3293
|
}
|
|
3212
3294
|
stripNullDirectiveFields(ast);
|
|
3213
3295
|
const filePath = normalizePath(path5.relative(options.root, id));
|
|
3214
3296
|
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
3215
|
-
if (
|
|
3297
|
+
if (hasDirective4(ast.body, "use cache")) {
|
|
3216
3298
|
return transformFileLevelUseCache(
|
|
3217
3299
|
code,
|
|
3218
3300
|
ast,
|
|
@@ -3221,7 +3303,7 @@ async function transformUseCache(code, id, options) {
|
|
|
3221
3303
|
options.isBuild,
|
|
3222
3304
|
isLayoutOrTemplate,
|
|
3223
3305
|
transformWrapExport,
|
|
3224
|
-
|
|
3306
|
+
hasDirective4
|
|
3225
3307
|
);
|
|
3226
3308
|
}
|
|
3227
3309
|
const functionResult = transformFunctionLevelUseCache(
|
|
@@ -3235,7 +3317,7 @@ async function transformUseCache(code, id, options) {
|
|
|
3235
3317
|
warnOnNearMissDirectives(ast, id, options.warn);
|
|
3236
3318
|
if (functionResult) return functionResult;
|
|
3237
3319
|
}
|
|
3238
|
-
async function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild, isLayoutOrTemplate, transformWrapExport,
|
|
3320
|
+
async function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild, isLayoutOrTemplate, transformWrapExport, hasDirective4) {
|
|
3239
3321
|
const unconfirmedExports = [];
|
|
3240
3322
|
const { exportNames, output } = transformWrapExport(code, ast, {
|
|
3241
3323
|
runtime: (value, name) => {
|
|
@@ -3247,7 +3329,7 @@ async function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild
|
|
|
3247
3329
|
if (name === "default" && isLayoutOrTemplate) return false;
|
|
3248
3330
|
if (name.startsWith("$$hoist_")) return false;
|
|
3249
3331
|
if (isHoistedServerReferenceRebind(meta.valueNode)) return false;
|
|
3250
|
-
if (functionHasUseServerDirective(meta.valueNode,
|
|
3332
|
+
if (functionHasUseServerDirective(meta.valueNode, hasDirective4)) {
|
|
3251
3333
|
return false;
|
|
3252
3334
|
}
|
|
3253
3335
|
if (meta.isFunction !== true) {
|
|
@@ -3264,8 +3346,8 @@ async function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild
|
|
|
3264
3346
|
);
|
|
3265
3347
|
}
|
|
3266
3348
|
if (exportNames.length === 0) {
|
|
3267
|
-
const { default:
|
|
3268
|
-
const s = new
|
|
3349
|
+
const { default: MagicString6 } = await import("magic-string");
|
|
3350
|
+
const s = new MagicString6(code);
|
|
3269
3351
|
const directive2 = findFileLevelDirective(ast);
|
|
3270
3352
|
if (directive2) {
|
|
3271
3353
|
s.overwrite(
|
|
@@ -3341,13 +3423,13 @@ function isHoistedServerReferenceRebind(valueNode) {
|
|
|
3341
3423
|
const first = valueNode.arguments[0];
|
|
3342
3424
|
return first !== void 0 && first.type === "Identifier" && first.name.startsWith("$$hoist_");
|
|
3343
3425
|
}
|
|
3344
|
-
function functionHasUseServerDirective(valueNode,
|
|
3426
|
+
function functionHasUseServerDirective(valueNode, hasDirective4) {
|
|
3345
3427
|
if (!valueNode || !("body" in valueNode)) return false;
|
|
3346
3428
|
const { body } = valueNode;
|
|
3347
3429
|
if (!body || Array.isArray(body) || body.type !== "BlockStatement") {
|
|
3348
3430
|
return false;
|
|
3349
3431
|
}
|
|
3350
|
-
return
|
|
3432
|
+
return hasDirective4(
|
|
3351
3433
|
body.body,
|
|
3352
3434
|
"use server"
|
|
3353
3435
|
);
|
|
@@ -3390,10 +3472,10 @@ function warnOnNearMissDirectives(ast, fileId, warn) {
|
|
|
3390
3472
|
}
|
|
3391
3473
|
|
|
3392
3474
|
// src/vite/plugins/transition-when-hoist.ts
|
|
3393
|
-
import { normalizePath as
|
|
3475
|
+
import { normalizePath as normalizePath3, parseAst as parseAst3 } from "vite";
|
|
3394
3476
|
import MagicString4 from "magic-string";
|
|
3395
3477
|
import { builtinModules } from "node:module";
|
|
3396
|
-
import {
|
|
3478
|
+
import { hasDirective as hasDirective2 } from "@vitejs/plugin-rsc/transforms";
|
|
3397
3479
|
|
|
3398
3480
|
// src/route-name.ts
|
|
3399
3481
|
var AUTO_GENERATED_ROUTE_PREFIX = "$path_";
|
|
@@ -3424,10 +3506,7 @@ function findTransitionWhenError(error) {
|
|
|
3424
3506
|
return void 0;
|
|
3425
3507
|
}
|
|
3426
3508
|
|
|
3427
|
-
// src/vite/plugins/
|
|
3428
|
-
var TRANSITION_WHEN_QUERY = "rango-when";
|
|
3429
|
-
var EXPORT_NAME = "__rango_when";
|
|
3430
|
-
var LOCAL_PREFIX = "__rango_when_";
|
|
3509
|
+
// src/vite/plugins/hoist/scope.ts
|
|
3431
3510
|
var Scope = class {
|
|
3432
3511
|
constructor(parent, isFunction, node) {
|
|
3433
3512
|
this.parent = parent;
|
|
@@ -3733,29 +3812,23 @@ function collectImports(program) {
|
|
|
3733
3812
|
}
|
|
3734
3813
|
return imports;
|
|
3735
3814
|
}
|
|
3736
|
-
|
|
3815
|
+
|
|
3816
|
+
// src/vite/plugins/hoist/literal.ts
|
|
3817
|
+
function directivePrologueEnd(program) {
|
|
3818
|
+
let end = 0;
|
|
3737
3819
|
for (const statement of program.body) {
|
|
3738
3820
|
if (statement.type !== "ExpressionStatement" || typeof statement.directive !== "string") {
|
|
3739
|
-
|
|
3821
|
+
break;
|
|
3740
3822
|
}
|
|
3741
|
-
|
|
3823
|
+
end = statement.end;
|
|
3742
3824
|
}
|
|
3743
|
-
return
|
|
3825
|
+
return end;
|
|
3744
3826
|
}
|
|
3745
|
-
function
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
if (code[i] === "\n") {
|
|
3750
|
-
line++;
|
|
3751
|
-
column = 1;
|
|
3752
|
-
} else {
|
|
3753
|
-
column++;
|
|
3754
|
-
}
|
|
3755
|
-
}
|
|
3756
|
-
return `${line}:${column}`;
|
|
3827
|
+
function parseLang(file) {
|
|
3828
|
+
if (/\.[cm]?ts$/.test(file)) return "ts";
|
|
3829
|
+
if (/\.[cm]?jsx?$/.test(file)) return "jsx";
|
|
3830
|
+
return "tsx";
|
|
3757
3831
|
}
|
|
3758
|
-
var ROUTER_SOURCE = "@rangojs/router";
|
|
3759
3832
|
var EXPRESSION_WRAPPERS = /* @__PURE__ */ new Set([
|
|
3760
3833
|
"TSAsExpression",
|
|
3761
3834
|
"TSSatisfiesExpression",
|
|
@@ -3773,51 +3846,50 @@ function isFunctionLiteral(node) {
|
|
|
3773
3846
|
function propertyKeyIs(prop, name) {
|
|
3774
3847
|
return prop?.type === "Property" && !prop.computed && (prop.key.type === "Identifier" && prop.key.name === name || prop.key.type === "Literal" && prop.key.value === name);
|
|
3775
3848
|
}
|
|
3776
|
-
function
|
|
3777
|
-
const
|
|
3849
|
+
function findHelperCalls(program, scopeOf, moduleScope, imports, spec) {
|
|
3850
|
+
const calls = [];
|
|
3778
3851
|
const helpers = /* @__PURE__ */ new Map();
|
|
3779
|
-
const
|
|
3780
|
-
const
|
|
3852
|
+
const sourceExport = (callee, scope) => {
|
|
3853
|
+
const sourceImport = (id) => {
|
|
3781
3854
|
if (id?.type !== "Identifier") return null;
|
|
3782
3855
|
if (scope.lookup(id.name) !== moduleScope) return null;
|
|
3783
3856
|
const binding = imports.get(id.name);
|
|
3784
|
-
return binding
|
|
3857
|
+
return binding && spec.sources.has(binding.source) && !binding.typeOnly ? binding : null;
|
|
3785
3858
|
};
|
|
3786
3859
|
if (callee.type === "Identifier") {
|
|
3787
|
-
const imported =
|
|
3860
|
+
const imported = sourceImport(callee)?.imported;
|
|
3788
3861
|
return imported && imported !== "*" && imported !== "default" ? imported : null;
|
|
3789
3862
|
}
|
|
3790
|
-
if (callee.type === "MemberExpression" && !callee.computed && callee.property.type === "Identifier" &&
|
|
3863
|
+
if (callee.type === "MemberExpression" && !callee.computed && callee.property.type === "Identifier" && sourceImport(callee.object)?.imported === "*") {
|
|
3791
3864
|
return callee.property.name;
|
|
3792
3865
|
}
|
|
3793
3866
|
return null;
|
|
3794
3867
|
};
|
|
3795
|
-
const
|
|
3868
|
+
const registerBuilderCallback = (callback) => {
|
|
3796
3869
|
const fnScope = scopeOf.get(callback);
|
|
3797
3870
|
let param = callback.params[0];
|
|
3798
3871
|
if (param?.type === "AssignmentPattern") param = param.left;
|
|
3799
3872
|
if (!fnScope || !param) return;
|
|
3800
|
-
const bindings = {
|
|
3801
|
-
transitions: /* @__PURE__ */ new Set(),
|
|
3802
|
-
objects: /* @__PURE__ */ new Set()
|
|
3803
|
-
};
|
|
3873
|
+
const bindings = { names: /* @__PURE__ */ new Set(), objects: /* @__PURE__ */ new Set() };
|
|
3804
3874
|
if (param.type === "Identifier") bindings.objects.add(param.name);
|
|
3805
3875
|
if (param.type === "ObjectPattern") {
|
|
3806
3876
|
for (const prop of param.properties) {
|
|
3807
|
-
if (!propertyKeyIs(prop,
|
|
3877
|
+
if (!propertyKeyIs(prop, spec.helper)) continue;
|
|
3808
3878
|
const target = prop.value.type === "AssignmentPattern" ? prop.value.left : prop.value;
|
|
3809
|
-
if (target.type === "Identifier") bindings.
|
|
3879
|
+
if (target.type === "Identifier") bindings.names.add(target.name);
|
|
3810
3880
|
}
|
|
3811
3881
|
}
|
|
3812
3882
|
helpers.set(fnScope, bindings);
|
|
3813
3883
|
};
|
|
3814
|
-
const
|
|
3815
|
-
if (
|
|
3884
|
+
const isHelper = (callee, scope) => {
|
|
3885
|
+
if (spec.directImport && sourceExport(callee, scope) === spec.helper) {
|
|
3886
|
+
return true;
|
|
3887
|
+
}
|
|
3816
3888
|
if (callee.type === "Identifier") {
|
|
3817
3889
|
const decl = scope.lookup(callee.name);
|
|
3818
|
-
return !!decl && !!helpers.get(decl)?.
|
|
3890
|
+
return !!decl && !!helpers.get(decl)?.names.has(callee.name);
|
|
3819
3891
|
}
|
|
3820
|
-
if (callee.type === "MemberExpression" && !callee.computed && callee.property.type === "Identifier" && callee.property.name ===
|
|
3892
|
+
if (callee.type === "MemberExpression" && !callee.computed && callee.property.type === "Identifier" && callee.property.name === spec.helper && callee.object.type === "Identifier") {
|
|
3821
3893
|
const decl = scope.lookup(callee.object.name);
|
|
3822
3894
|
return !!decl && !!helpers.get(decl)?.objects.has(callee.object.name);
|
|
3823
3895
|
}
|
|
@@ -3833,20 +3905,10 @@ function findWhenSites(program, scopeOf, moduleScope, imports) {
|
|
|
3833
3905
|
const own = scopeOf.get(node) ?? scope;
|
|
3834
3906
|
if (node.type === "CallExpression") {
|
|
3835
3907
|
const callback = node.arguments[0];
|
|
3836
|
-
if (isFunctionLiteral(callback) &&
|
|
3837
|
-
|
|
3838
|
-
}
|
|
3839
|
-
if (node.arguments[0]?.type === "ObjectExpression" && isRouterTransition(node.callee, own)) {
|
|
3840
|
-
for (const prop of node.arguments[0].properties) {
|
|
3841
|
-
if (propertyKeyIs(prop, "when")) {
|
|
3842
|
-
sites.push({
|
|
3843
|
-
prop,
|
|
3844
|
-
value: unwrapExpression(prop.value),
|
|
3845
|
-
scope: own
|
|
3846
|
-
});
|
|
3847
|
-
}
|
|
3848
|
-
}
|
|
3908
|
+
if (isFunctionLiteral(callback) && sourceExport(node.callee, own) === spec.builder) {
|
|
3909
|
+
registerBuilderCallback(callback);
|
|
3849
3910
|
}
|
|
3911
|
+
if (isHelper(node.callee, own)) calls.push({ call: node, scope: own });
|
|
3850
3912
|
}
|
|
3851
3913
|
for (const key of Object.keys(node)) {
|
|
3852
3914
|
if (key === "type" || key === "start" || key === "end") continue;
|
|
@@ -3854,27 +3916,21 @@ function findWhenSites(program, scopeOf, moduleScope, imports) {
|
|
|
3854
3916
|
}
|
|
3855
3917
|
};
|
|
3856
3918
|
visit(program.body, moduleScope);
|
|
3857
|
-
return
|
|
3919
|
+
return calls;
|
|
3858
3920
|
}
|
|
3859
|
-
|
|
3860
|
-
this: "`this` in an arrow is the enclosing server function's `this`.",
|
|
3861
|
-
arguments: "`arguments` in an arrow is the enclosing server function's `arguments`.",
|
|
3862
|
-
super: "`super` refers to the enclosing server object.",
|
|
3863
|
-
"new.target": "`new.target` in an arrow is the enclosing server function's."
|
|
3864
|
-
};
|
|
3865
|
-
function findLexicalCapture(literal, references, code) {
|
|
3921
|
+
function findLexicalCapture(literal, references, code, messages) {
|
|
3866
3922
|
const ownArguments = [];
|
|
3867
3923
|
let found = null;
|
|
3868
3924
|
const capture = (node, what) => {
|
|
3869
3925
|
found = {
|
|
3870
3926
|
node,
|
|
3871
|
-
detail: `${
|
|
3927
|
+
detail: `${messages.lexical[what]} ${messages.captureHint}`
|
|
3872
3928
|
};
|
|
3873
3929
|
};
|
|
3874
3930
|
const loads = (node, expression, why) => {
|
|
3875
3931
|
found = {
|
|
3876
3932
|
node,
|
|
3877
|
-
detail: `\`${expression}\` ${why}
|
|
3933
|
+
detail: `\`${expression}\` ${why} ${messages.loadsHint}`
|
|
3878
3934
|
};
|
|
3879
3935
|
};
|
|
3880
3936
|
const visit = (node, boundary) => {
|
|
@@ -3907,7 +3963,7 @@ function findLexicalCapture(literal, references, code) {
|
|
|
3907
3963
|
}
|
|
3908
3964
|
case "MetaProperty":
|
|
3909
3965
|
if (node.meta.name === "import") {
|
|
3910
|
-
loads(node, "import.meta",
|
|
3966
|
+
loads(node, "import.meta", messages.importMetaWhy);
|
|
3911
3967
|
} else if (!boundary) {
|
|
3912
3968
|
capture(node, "new.target");
|
|
3913
3969
|
}
|
|
@@ -3919,7 +3975,7 @@ function findLexicalCapture(literal, references, code) {
|
|
|
3919
3975
|
loads(
|
|
3920
3976
|
node,
|
|
3921
3977
|
node.computed ? "import.meta[...]" : `import.meta.${node.property.name}`,
|
|
3922
|
-
|
|
3978
|
+
messages.importMetaMemberWhy
|
|
3923
3979
|
);
|
|
3924
3980
|
return;
|
|
3925
3981
|
}
|
|
@@ -3928,7 +3984,7 @@ function findLexicalCapture(literal, references, code) {
|
|
|
3928
3984
|
loads(
|
|
3929
3985
|
node,
|
|
3930
3986
|
`import(${code.slice(node.source.start, node.source.end)})`,
|
|
3931
|
-
|
|
3987
|
+
messages.dynamicImportWhy
|
|
3932
3988
|
);
|
|
3933
3989
|
return;
|
|
3934
3990
|
}
|
|
@@ -3953,32 +4009,150 @@ function findLexicalCapture(literal, references, code) {
|
|
|
3953
4009
|
}
|
|
3954
4010
|
return null;
|
|
3955
4011
|
}
|
|
4012
|
+
function collectFreeReferences(literal, references, moduleScope, imports) {
|
|
4013
|
+
const used = /* @__PURE__ */ new Map();
|
|
4014
|
+
const bindings = [];
|
|
4015
|
+
const globals = [];
|
|
4016
|
+
for (const ref of references) {
|
|
4017
|
+
if (ref.node.start < literal.start || ref.node.end > literal.end) continue;
|
|
4018
|
+
const decl = ref.scope.lookup(ref.node.name);
|
|
4019
|
+
if (!decl) {
|
|
4020
|
+
if (!ref.typeOnly) globals.push(ref);
|
|
4021
|
+
continue;
|
|
4022
|
+
}
|
|
4023
|
+
if (decl.node.start >= literal.start && decl.node.end <= literal.end && decl !== moduleScope) {
|
|
4024
|
+
continue;
|
|
4025
|
+
}
|
|
4026
|
+
if (decl === moduleScope && imports.has(ref.node.name)) {
|
|
4027
|
+
const valueUse = !ref.typeOnly && !imports.get(ref.node.name).typeOnly;
|
|
4028
|
+
used.set(ref.node.name, (used.get(ref.node.name) ?? false) || valueUse);
|
|
4029
|
+
continue;
|
|
4030
|
+
}
|
|
4031
|
+
if (ref.typeOnly) continue;
|
|
4032
|
+
bindings.push(ref);
|
|
4033
|
+
}
|
|
4034
|
+
return { imports: used, bindings, globals };
|
|
4035
|
+
}
|
|
4036
|
+
async function emitImports(used, imports, checkValueImport) {
|
|
4037
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
4038
|
+
for (const [local, valueUse] of used) {
|
|
4039
|
+
const binding = imports.get(local);
|
|
4040
|
+
if (valueUse) await checkValueImport(local, binding);
|
|
4041
|
+
const lines = bySource.get(binding.source) ?? [];
|
|
4042
|
+
const typePrefix = valueUse ? "" : "type ";
|
|
4043
|
+
if (binding.imported === "*") {
|
|
4044
|
+
lines.push(
|
|
4045
|
+
`import ${typePrefix}* as ${local} from ${JSON.stringify(binding.source)};`
|
|
4046
|
+
);
|
|
4047
|
+
} else if (binding.imported === "default") {
|
|
4048
|
+
lines.push(
|
|
4049
|
+
`import ${typePrefix}${local} from ${JSON.stringify(binding.source)};`
|
|
4050
|
+
);
|
|
4051
|
+
} else {
|
|
4052
|
+
const spec = binding.imported === local ? local : `${JSON.stringify(binding.imported)} as ${local}`;
|
|
4053
|
+
lines.push(
|
|
4054
|
+
`import ${typePrefix}{ ${spec} } from ${JSON.stringify(binding.source)};`
|
|
4055
|
+
);
|
|
4056
|
+
}
|
|
4057
|
+
bySource.set(binding.source, lines);
|
|
4058
|
+
}
|
|
4059
|
+
return [...bySource.values()].flat();
|
|
4060
|
+
}
|
|
4061
|
+
|
|
4062
|
+
// src/vite/plugins/hoist/source.ts
|
|
4063
|
+
import { readFile } from "node:fs/promises";
|
|
4064
|
+
import { normalizePath as normalizePath2 } from "vite";
|
|
4065
|
+
var SOURCE_FILE_RE = /\.[cm]?[jt]sx?$/;
|
|
4066
|
+
async function readSource(file) {
|
|
4067
|
+
try {
|
|
4068
|
+
return await readFile(file, "utf-8");
|
|
4069
|
+
} catch {
|
|
4070
|
+
return null;
|
|
4071
|
+
}
|
|
4072
|
+
}
|
|
4073
|
+
async function resolveSourceTarget(ctx, source, importer, options) {
|
|
4074
|
+
const resolved2 = await ctx.resolve(source, importer);
|
|
4075
|
+
if (!resolved2 || resolved2.external) return null;
|
|
4076
|
+
const target = resolved2.id.split("?", 1)[0];
|
|
4077
|
+
if (target.startsWith("\0")) return null;
|
|
4078
|
+
if (options.skipNodeModules && target.includes("/node_modules/")) {
|
|
4079
|
+
return null;
|
|
4080
|
+
}
|
|
4081
|
+
return target;
|
|
4082
|
+
}
|
|
4083
|
+
async function recordEmitted(emitted, file, value) {
|
|
4084
|
+
emitted.set(file, { disk: await readSource(file), value });
|
|
4085
|
+
}
|
|
4086
|
+
async function loadEmittedOrDisk(emitted, hoistedFile, rehoist) {
|
|
4087
|
+
const disk = await readSource(hoistedFile);
|
|
4088
|
+
const entry = emitted.get(normalizePath2(hoistedFile));
|
|
4089
|
+
if (entry && (disk === null || entry.disk === disk)) return entry.value;
|
|
4090
|
+
return disk === null ? void 0 : rehoist(disk);
|
|
4091
|
+
}
|
|
4092
|
+
|
|
4093
|
+
// src/vite/plugins/transition-when-hoist.ts
|
|
4094
|
+
var TRANSITION_WHEN_QUERY = "rango-when";
|
|
4095
|
+
var EXPORT_NAME = "__rango_when";
|
|
4096
|
+
var LOCAL_PREFIX = "__rango_when_";
|
|
4097
|
+
var ROUTER_SOURCES = /* @__PURE__ */ new Set(["@rangojs/router"]);
|
|
4098
|
+
function findWhenSites(program, scopeOf, moduleScope, imports) {
|
|
4099
|
+
const sites = [];
|
|
4100
|
+
for (const { call, scope } of findHelperCalls(
|
|
4101
|
+
program,
|
|
4102
|
+
scopeOf,
|
|
4103
|
+
moduleScope,
|
|
4104
|
+
imports,
|
|
4105
|
+
{
|
|
4106
|
+
sources: ROUTER_SOURCES,
|
|
4107
|
+
builder: "urls",
|
|
4108
|
+
helper: "transition",
|
|
4109
|
+
directImport: true
|
|
4110
|
+
}
|
|
4111
|
+
)) {
|
|
4112
|
+
if (call.arguments[0]?.type !== "ObjectExpression") continue;
|
|
4113
|
+
for (const prop of call.arguments[0].properties) {
|
|
4114
|
+
if (propertyKeyIs(prop, "when")) {
|
|
4115
|
+
sites.push({ prop, value: unwrapExpression(prop.value), scope });
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
return sites;
|
|
4120
|
+
}
|
|
4121
|
+
var WHEN_CAPTURE_MESSAGES = {
|
|
4122
|
+
lexical: {
|
|
4123
|
+
this: "`this` in an arrow is the enclosing server function's `this`.",
|
|
4124
|
+
arguments: "`arguments` in an arrow is the enclosing server function's `arguments`.",
|
|
4125
|
+
super: "`super` refers to the enclosing server object.",
|
|
4126
|
+
"new.target": "`new.target` in an arrow is the enclosing server function's."
|
|
4127
|
+
},
|
|
4128
|
+
captureHint: 'Read what you need from `to.params`/`to.state`, or export the predicate from a "use client" module.',
|
|
4129
|
+
loadsHint: 'Import client-safe modules statically, or export the predicate from a "use client" module.',
|
|
4130
|
+
importMetaWhy: "is the server module's.",
|
|
4131
|
+
importMetaMemberWhy: "is resolved against the server module; only `import.meta.env` is available to an inline predicate.",
|
|
4132
|
+
dynamicImportWhy: "loads a module at run time, which the build cannot check is client-safe."
|
|
4133
|
+
};
|
|
3956
4134
|
var NODE_BUILTINS = new Set(builtinModules);
|
|
3957
4135
|
function isServerOnlySpecifier(source) {
|
|
3958
4136
|
return source === "server-only" || source.startsWith("node:") || source.startsWith("cloudflare:") || NODE_BUILTINS.has(source);
|
|
3959
4137
|
}
|
|
3960
4138
|
var ROUTER_IMPORT_RE = /["']@rangojs\/router["']/;
|
|
3961
4139
|
var WHEN_RE = /\bwhen\b/;
|
|
3962
|
-
function parseLang(file) {
|
|
3963
|
-
if (/\.[cm]?ts$/.test(file)) return "ts";
|
|
3964
|
-
if (/\.[cm]?jsx?$/.test(file)) return "jsx";
|
|
3965
|
-
return "tsx";
|
|
3966
|
-
}
|
|
3967
4140
|
function whenError(file, code, node, detail) {
|
|
4141
|
+
const { line, column } = offsetToLineColumn(code, node.start);
|
|
3968
4142
|
return new TransitionWhenError(
|
|
3969
|
-
`[rango] transition({ when }) at ${file}:${
|
|
4143
|
+
`[rango] transition({ when }) at ${file}:${line}:${column}: \`when\` runs in the browser; ${detail}`
|
|
3970
4144
|
);
|
|
3971
4145
|
}
|
|
3972
4146
|
async function hoistTransitionWhens(code, id, deps = {}) {
|
|
3973
4147
|
if (!ROUTER_IMPORT_RE.test(code) || !WHEN_RE.test(code)) return null;
|
|
3974
|
-
const file =
|
|
4148
|
+
const file = normalizePath3(id.split("?", 1)[0]);
|
|
3975
4149
|
let program;
|
|
3976
4150
|
try {
|
|
3977
4151
|
program = parseAst3(code, { lang: parseLang(file) });
|
|
3978
4152
|
} catch {
|
|
3979
4153
|
return null;
|
|
3980
4154
|
}
|
|
3981
|
-
if (
|
|
4155
|
+
if (hasDirective2(program.body, "use client")) return null;
|
|
3982
4156
|
const { moduleScope, references, scopeOf } = analyzeScopes(program);
|
|
3983
4157
|
const imports = collectImports(program);
|
|
3984
4158
|
const sites = findWhenSites(program, scopeOf, moduleScope, imports);
|
|
@@ -4009,66 +4183,43 @@ async function hoistTransitionWhens(code, id, deps = {}) {
|
|
|
4009
4183
|
continue;
|
|
4010
4184
|
}
|
|
4011
4185
|
if (!isFunctionLiteral(value)) continue;
|
|
4012
|
-
const lexical = findLexicalCapture(
|
|
4186
|
+
const lexical = findLexicalCapture(
|
|
4187
|
+
value,
|
|
4188
|
+
references,
|
|
4189
|
+
code,
|
|
4190
|
+
WHEN_CAPTURE_MESSAGES
|
|
4191
|
+
);
|
|
4013
4192
|
if (lexical) throw whenError(file, code, lexical.node, lexical.detail);
|
|
4014
|
-
const
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
const decl = ref.scope.lookup(ref.node.name);
|
|
4018
|
-
if (!decl) continue;
|
|
4019
|
-
if (decl.node.start >= value.start && decl.node.end <= value.end && decl !== moduleScope) {
|
|
4020
|
-
continue;
|
|
4021
|
-
}
|
|
4022
|
-
if (decl === moduleScope && imports.has(ref.node.name)) {
|
|
4023
|
-
const valueUse = !ref.typeOnly && !imports.get(ref.node.name).typeOnly;
|
|
4024
|
-
used.set(ref.node.name, (used.get(ref.node.name) ?? false) || valueUse);
|
|
4025
|
-
continue;
|
|
4026
|
-
}
|
|
4027
|
-
if (ref.typeOnly) continue;
|
|
4193
|
+
const free = collectFreeReferences(value, references, moduleScope, imports);
|
|
4194
|
+
const binding = free.bindings[0];
|
|
4195
|
+
if (binding) {
|
|
4028
4196
|
throw whenError(
|
|
4029
4197
|
file,
|
|
4030
4198
|
code,
|
|
4031
|
-
|
|
4032
|
-
`\`${
|
|
4199
|
+
binding.node,
|
|
4200
|
+
`\`${binding.node.name}\` is a server-module binding. Read it from \`to.params\`/\`to.state\`, or export the predicate from a "use client" module.`
|
|
4033
4201
|
);
|
|
4034
4202
|
}
|
|
4035
|
-
const
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
if (isServerOnlySpecifier(
|
|
4203
|
+
const importLines = await emitImports(
|
|
4204
|
+
free.imports,
|
|
4205
|
+
imports,
|
|
4206
|
+
async (local2, imported) => {
|
|
4207
|
+
if (isServerOnlySpecifier(imported.source) || await deps.isServerOnlyImport?.(imported.source)) {
|
|
4040
4208
|
throw whenError(
|
|
4041
4209
|
file,
|
|
4042
4210
|
code,
|
|
4043
4211
|
value,
|
|
4044
|
-
`\`${local2}\` is imported from "${
|
|
4212
|
+
`\`${local2}\` is imported from "${imported.source}", a server-only module. Import only client-safe modules into an inline predicate, or export it from a "use client" module.`
|
|
4045
4213
|
);
|
|
4046
4214
|
}
|
|
4047
4215
|
}
|
|
4048
|
-
|
|
4049
|
-
const typePrefix = valueUse ? "" : "type ";
|
|
4050
|
-
if (binding.imported === "*") {
|
|
4051
|
-
lines.push(
|
|
4052
|
-
`import ${typePrefix}* as ${local2} from ${JSON.stringify(binding.source)};`
|
|
4053
|
-
);
|
|
4054
|
-
} else if (binding.imported === "default") {
|
|
4055
|
-
lines.push(
|
|
4056
|
-
`import ${typePrefix}${local2} from ${JSON.stringify(binding.source)};`
|
|
4057
|
-
);
|
|
4058
|
-
} else {
|
|
4059
|
-
const spec = binding.imported === local2 ? local2 : `${JSON.stringify(binding.imported)} as ${local2}`;
|
|
4060
|
-
lines.push(
|
|
4061
|
-
`import ${typePrefix}{ ${spec} } from ${JSON.stringify(binding.source)};`
|
|
4062
|
-
);
|
|
4063
|
-
}
|
|
4064
|
-
bySource.set(binding.source, lines);
|
|
4065
|
-
}
|
|
4216
|
+
);
|
|
4066
4217
|
const source = prop.method ? `${value.async ? "async " : ""}function${value.generator ? "*" : ""} ` + code.slice(value.start, value.end) : code.slice(value.start, value.end);
|
|
4067
4218
|
const index = modules.length;
|
|
4068
4219
|
modules.push(
|
|
4069
4220
|
[
|
|
4070
4221
|
`"use client";`,
|
|
4071
|
-
...
|
|
4222
|
+
...importLines,
|
|
4072
4223
|
`export const ${EXPORT_NAME} = ${source};`,
|
|
4073
4224
|
""
|
|
4074
4225
|
].join("\n")
|
|
@@ -4086,13 +4237,7 @@ async function hoistTransitionWhens(code, id, deps = {}) {
|
|
|
4086
4237
|
);
|
|
4087
4238
|
}
|
|
4088
4239
|
if (modules.length === 0) return null;
|
|
4089
|
-
|
|
4090
|
-
for (const statement of program.body) {
|
|
4091
|
-
if (statement.type !== "ExpressionStatement" || typeof statement.directive !== "string") {
|
|
4092
|
-
break;
|
|
4093
|
-
}
|
|
4094
|
-
insertAt = statement.end;
|
|
4095
|
-
}
|
|
4240
|
+
const insertAt = directivePrologueEnd(program);
|
|
4096
4241
|
s.appendLeft(insertAt, `${insertAt ? "\n" : ""}${header.join("\n")}
|
|
4097
4242
|
`);
|
|
4098
4243
|
return {
|
|
@@ -4110,13 +4255,6 @@ function parseHoistedWhenId(id) {
|
|
|
4110
4255
|
return { file: id.slice(0, q), index: Number(raw) };
|
|
4111
4256
|
}
|
|
4112
4257
|
var SERVER_ONLY_IMPORT_RE = /\bimport\s+["']server-only["']/;
|
|
4113
|
-
async function readSource(file) {
|
|
4114
|
-
try {
|
|
4115
|
-
return await readFile(file, "utf-8");
|
|
4116
|
-
} catch {
|
|
4117
|
-
return null;
|
|
4118
|
-
}
|
|
4119
|
-
}
|
|
4120
4258
|
function transitionWhenHoistPlugin() {
|
|
4121
4259
|
const emitted = /* @__PURE__ */ new Map();
|
|
4122
4260
|
return {
|
|
@@ -4125,10 +4263,11 @@ function transitionWhenHoistPlugin() {
|
|
|
4125
4263
|
async load(id) {
|
|
4126
4264
|
const hoisted = parseHoistedWhenId(id);
|
|
4127
4265
|
if (!hoisted) return;
|
|
4128
|
-
const
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4266
|
+
const modules = await loadEmittedOrDisk(
|
|
4267
|
+
emitted,
|
|
4268
|
+
hoisted.file,
|
|
4269
|
+
async (disk) => (await hoistTransitionWhens(disk, hoisted.file))?.modules
|
|
4270
|
+
);
|
|
4132
4271
|
const module = modules?.[hoisted.index];
|
|
4133
4272
|
if (module === void 0) {
|
|
4134
4273
|
throw new TransitionWhenError(
|
|
@@ -4140,35 +4279,397 @@ function transitionWhenHoistPlugin() {
|
|
|
4140
4279
|
async transform(code, id) {
|
|
4141
4280
|
if (this.environment?.name !== "rsc") return;
|
|
4142
4281
|
if (id.includes("/node_modules/") || parseHoistedWhenId(id)) return;
|
|
4143
|
-
const file =
|
|
4144
|
-
if (
|
|
4282
|
+
const file = normalizePath3(id.split("?", 1)[0]);
|
|
4283
|
+
if (!SOURCE_FILE_RE.test(file)) return;
|
|
4145
4284
|
emitted.delete(file);
|
|
4146
4285
|
const result = await hoistTransitionWhens(code, id, {
|
|
4147
4286
|
isServerOnlyImport: async (source) => {
|
|
4148
|
-
const
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
if (target
|
|
4152
|
-
return false;
|
|
4153
|
-
}
|
|
4287
|
+
const target = await resolveSourceTarget(this, source, id, {
|
|
4288
|
+
skipNodeModules: true
|
|
4289
|
+
});
|
|
4290
|
+
if (target === null) return false;
|
|
4154
4291
|
const text = await readSource(target);
|
|
4155
4292
|
return text !== null && SERVER_ONLY_IMPORT_RE.test(text);
|
|
4156
4293
|
}
|
|
4157
4294
|
});
|
|
4158
4295
|
if (!result) return;
|
|
4159
|
-
emitted
|
|
4160
|
-
disk: await readSource(file),
|
|
4161
|
-
modules: result.modules
|
|
4162
|
-
});
|
|
4296
|
+
await recordEmitted(emitted, file, result.modules);
|
|
4163
4297
|
return { code: result.code, map: result.map };
|
|
4164
4298
|
}
|
|
4165
4299
|
};
|
|
4166
4300
|
}
|
|
4167
4301
|
|
|
4302
|
+
// src/vite/plugins/client-urls-revalidate-hoist.ts
|
|
4303
|
+
import { normalizePath as normalizePath4, parseAst as parseAst5 } from "vite";
|
|
4304
|
+
import MagicString5 from "magic-string";
|
|
4305
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
4306
|
+
import { relative as relative2 } from "node:path";
|
|
4307
|
+
import { hasDirective as hasDirective3 } from "@vitejs/plugin-rsc/transforms";
|
|
4308
|
+
|
|
4309
|
+
// src/client-urls/hoisted-revalidate.ts
|
|
4310
|
+
var HOISTED_REVALIDATE_KEY = "$$rangoRevalidate";
|
|
4311
|
+
function isHoistedRevalidateRef(value) {
|
|
4312
|
+
return typeof value === "object" && value !== null && typeof value[HOISTED_REVALIDATE_KEY] === "string";
|
|
4313
|
+
}
|
|
4314
|
+
|
|
4315
|
+
// src/vite/utils/directive-prologue.ts
|
|
4316
|
+
import { parseAst as parseAst4 } from "vite";
|
|
4317
|
+
function hasUseClientDirective(source) {
|
|
4318
|
+
let program;
|
|
4319
|
+
try {
|
|
4320
|
+
program = parseAst4(source, { lang: "tsx" });
|
|
4321
|
+
} catch {
|
|
4322
|
+
return false;
|
|
4323
|
+
}
|
|
4324
|
+
for (const node of program.body ?? []) {
|
|
4325
|
+
if (node?.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string") {
|
|
4326
|
+
if (node.expression.value === "use client") return true;
|
|
4327
|
+
continue;
|
|
4328
|
+
}
|
|
4329
|
+
break;
|
|
4330
|
+
}
|
|
4331
|
+
return false;
|
|
4332
|
+
}
|
|
4333
|
+
|
|
4334
|
+
// src/vite/plugins/client-urls-revalidate-hoist.ts
|
|
4335
|
+
var CLIENT_URLS_REVALIDATE_QUERY = "rango-revalidate";
|
|
4336
|
+
var REGISTER = "__rango_registerClientUrlRevalidators";
|
|
4337
|
+
var CLIENT_SOURCES = /* @__PURE__ */ new Set(["@rangojs/router/client"]);
|
|
4338
|
+
var BROWSER_GLOBALS = /* @__PURE__ */ new Set([
|
|
4339
|
+
"window",
|
|
4340
|
+
"document",
|
|
4341
|
+
"navigator",
|
|
4342
|
+
"localStorage",
|
|
4343
|
+
"sessionStorage",
|
|
4344
|
+
"location",
|
|
4345
|
+
"history"
|
|
4346
|
+
]);
|
|
4347
|
+
var NOT_A_FUNCTION = /* @__PURE__ */ new Set([
|
|
4348
|
+
"ObjectExpression",
|
|
4349
|
+
"ArrayExpression",
|
|
4350
|
+
"Literal",
|
|
4351
|
+
"TemplateLiteral",
|
|
4352
|
+
"ClassExpression"
|
|
4353
|
+
]);
|
|
4354
|
+
var CAPTURE_MESSAGES = {
|
|
4355
|
+
lexical: {
|
|
4356
|
+
this: "`this` in an arrow is the enclosing function's `this`.",
|
|
4357
|
+
arguments: "`arguments` in an arrow is the enclosing function's.",
|
|
4358
|
+
super: "`super` refers to the enclosing object.",
|
|
4359
|
+
"new.target": "`new.target` in an arrow is the enclosing function's."
|
|
4360
|
+
},
|
|
4361
|
+
captureHint: "Read what you need from the predicate's argument.",
|
|
4362
|
+
loadsHint: "Import server-safe modules statically.",
|
|
4363
|
+
importMetaWhy: `is the "use client" module's.`,
|
|
4364
|
+
importMetaMemberWhy: 'is resolved against the "use client" module; only `import.meta.env` is available to a hoisted predicate.',
|
|
4365
|
+
dynamicImportWhy: "loads a module at run time, which the build cannot check is server-safe."
|
|
4366
|
+
};
|
|
4367
|
+
var CLIENT_URLS_RE = /\bclientUrls\b/;
|
|
4368
|
+
var CLIENT_IMPORT_RE = /["']@rangojs\/router\/client["']/;
|
|
4369
|
+
var REVALIDATE_RE = /\brevalidate\b/;
|
|
4370
|
+
function mayHoist(code) {
|
|
4371
|
+
return code.includes("use client") && CLIENT_URLS_RE.test(code) && CLIENT_IMPORT_RE.test(code) && REVALIDATE_RE.test(code);
|
|
4372
|
+
}
|
|
4373
|
+
function revalidateError(file, code, node, detail) {
|
|
4374
|
+
const { line, column } = offsetToLineColumn(code, node.start);
|
|
4375
|
+
return new Error(
|
|
4376
|
+
`[rango] clientUrls() revalidate() at ${file}:${line}:${column}: revalidate() runs on the server; ${detail}`
|
|
4377
|
+
);
|
|
4378
|
+
}
|
|
4379
|
+
var FINGERPRINT_SKIP = /* @__PURE__ */ new Set([
|
|
4380
|
+
"type",
|
|
4381
|
+
"start",
|
|
4382
|
+
"end",
|
|
4383
|
+
"loc",
|
|
4384
|
+
"range",
|
|
4385
|
+
"raw",
|
|
4386
|
+
"extra",
|
|
4387
|
+
"shorthand",
|
|
4388
|
+
// TS-only flags (`let x!: T`), lost with the types.
|
|
4389
|
+
"definite",
|
|
4390
|
+
...TYPE_KEYS
|
|
4391
|
+
]);
|
|
4392
|
+
function fingerprint(node) {
|
|
4393
|
+
const out = [];
|
|
4394
|
+
const visit = (value) => {
|
|
4395
|
+
if (value === null || value === void 0) return;
|
|
4396
|
+
if (Array.isArray(value)) {
|
|
4397
|
+
out.push("[");
|
|
4398
|
+
for (const item of value) visit(item);
|
|
4399
|
+
out.push("]");
|
|
4400
|
+
return;
|
|
4401
|
+
}
|
|
4402
|
+
if (typeof value !== "object") {
|
|
4403
|
+
out.push(JSON.stringify(typeof value === "bigint" ? `${value}n` : value));
|
|
4404
|
+
return;
|
|
4405
|
+
}
|
|
4406
|
+
let entry = value;
|
|
4407
|
+
if (typeof entry.type === "string") {
|
|
4408
|
+
entry = unwrapExpression(entry);
|
|
4409
|
+
if (entry.type.startsWith("TS")) {
|
|
4410
|
+
visit(entry.expression);
|
|
4411
|
+
return;
|
|
4412
|
+
}
|
|
4413
|
+
out.push(entry.type, "(");
|
|
4414
|
+
if (entry.type === "TemplateElement") {
|
|
4415
|
+
out.push(JSON.stringify(entry.value.raw));
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
for (const key of Object.keys(entry)) {
|
|
4419
|
+
if (FINGERPRINT_SKIP.has(key)) continue;
|
|
4420
|
+
if (key === "optional" && entry.type === "Identifier") continue;
|
|
4421
|
+
out.push(key);
|
|
4422
|
+
visit(entry[key]);
|
|
4423
|
+
}
|
|
4424
|
+
if (typeof entry.type === "string") out.push(")");
|
|
4425
|
+
};
|
|
4426
|
+
visit(node);
|
|
4427
|
+
return out.join(" ");
|
|
4428
|
+
}
|
|
4429
|
+
function keyOf(relativeFile, predicate) {
|
|
4430
|
+
return createHash2("sha256").update(relativeFile).update("\0").update(fingerprint(predicate)).digest("hex").slice(0, 12);
|
|
4431
|
+
}
|
|
4432
|
+
async function hoistClientUrlsRevalidates(code, id, deps) {
|
|
4433
|
+
if (!mayHoist(code)) return null;
|
|
4434
|
+
const file = normalizePath4(id.split("?", 1)[0]);
|
|
4435
|
+
let program;
|
|
4436
|
+
try {
|
|
4437
|
+
program = parseAst5(code, { lang: parseLang(file) });
|
|
4438
|
+
} catch {
|
|
4439
|
+
return null;
|
|
4440
|
+
}
|
|
4441
|
+
if (!hasDirective3(program.body, "use client")) return null;
|
|
4442
|
+
const { moduleScope, references, scopeOf } = analyzeScopes(program);
|
|
4443
|
+
const imports = collectImports(program);
|
|
4444
|
+
const calls = findHelperCalls(program, scopeOf, moduleScope, imports, {
|
|
4445
|
+
sources: CLIENT_SOURCES,
|
|
4446
|
+
builder: "clientUrls",
|
|
4447
|
+
helper: "revalidate",
|
|
4448
|
+
directImport: false
|
|
4449
|
+
});
|
|
4450
|
+
if (calls.length === 0) return null;
|
|
4451
|
+
const relativeFile = normalizePath4(relative2(deps.root, file));
|
|
4452
|
+
const s = new MagicString5(code);
|
|
4453
|
+
const used = /* @__PURE__ */ new Map();
|
|
4454
|
+
const entries = /* @__PURE__ */ new Map();
|
|
4455
|
+
for (const { call } of calls) {
|
|
4456
|
+
const [arg, extra] = call.arguments;
|
|
4457
|
+
if (!arg || extra || arg.type === "SpreadElement") {
|
|
4458
|
+
throw revalidateError(
|
|
4459
|
+
file,
|
|
4460
|
+
code,
|
|
4461
|
+
call,
|
|
4462
|
+
"`revalidate()` takes exactly one predicate."
|
|
4463
|
+
);
|
|
4464
|
+
}
|
|
4465
|
+
const value = unwrapExpression(arg);
|
|
4466
|
+
if (NOT_A_FUNCTION.has(value.type)) {
|
|
4467
|
+
throw revalidateError(
|
|
4468
|
+
file,
|
|
4469
|
+
code,
|
|
4470
|
+
value,
|
|
4471
|
+
"`revalidate()` expects a predicate function."
|
|
4472
|
+
);
|
|
4473
|
+
}
|
|
4474
|
+
if (isFunctionLiteral(value) && (value.async || value.generator)) {
|
|
4475
|
+
throw revalidateError(
|
|
4476
|
+
file,
|
|
4477
|
+
code,
|
|
4478
|
+
value,
|
|
4479
|
+
`a${value.async ? "n `async`" : " generator"} function returns ${value.async ? "a Promise" : "an iterator"}, which the router ignores: return a boolean, \`{ defaultShouldRevalidate }\`, or nothing.`
|
|
4480
|
+
);
|
|
4481
|
+
}
|
|
4482
|
+
const lexical = findLexicalCapture(
|
|
4483
|
+
value,
|
|
4484
|
+
references,
|
|
4485
|
+
code,
|
|
4486
|
+
CAPTURE_MESSAGES
|
|
4487
|
+
);
|
|
4488
|
+
if (lexical)
|
|
4489
|
+
throw revalidateError(file, code, lexical.node, lexical.detail);
|
|
4490
|
+
const free = collectFreeReferences(value, references, moduleScope, imports);
|
|
4491
|
+
const binding = free.bindings[0];
|
|
4492
|
+
if (binding) {
|
|
4493
|
+
const name = binding.node.name;
|
|
4494
|
+
throw revalidateError(
|
|
4495
|
+
file,
|
|
4496
|
+
code,
|
|
4497
|
+
binding.node,
|
|
4498
|
+
binding.scope.lookup(name) === moduleScope ? `\`${name}\` is declared in this "use client" module. Move the predicate to its own module (without "use client") and import it, or write it inline.` : `\`${name}\` is a binding of the enclosing function. Read what you need from the predicate's argument (\`currentParams\`, \`nextUrl\`, \`context\`, \`actionResult\`, ...).`
|
|
4499
|
+
);
|
|
4500
|
+
}
|
|
4501
|
+
const browserGlobal = free.globals.find(
|
|
4502
|
+
(ref) => BROWSER_GLOBALS.has(ref.node.name)
|
|
4503
|
+
);
|
|
4504
|
+
if (browserGlobal) {
|
|
4505
|
+
throw revalidateError(
|
|
4506
|
+
file,
|
|
4507
|
+
code,
|
|
4508
|
+
browserGlobal.node,
|
|
4509
|
+
`\`${browserGlobal.node.name}\` is a browser global. Put the input on the request (a cookie or a search param) and read it from the predicate's argument, or refresh the loader with useRefreshLoaders.`
|
|
4510
|
+
);
|
|
4511
|
+
}
|
|
4512
|
+
const unchecked = [...free.imports].filter(
|
|
4513
|
+
([local, valueUse]) => valueUse && !used.get(local)
|
|
4514
|
+
);
|
|
4515
|
+
const clientOnly = await Promise.all(
|
|
4516
|
+
unchecked.map(([local]) => isClientOnly(imports.get(local), deps))
|
|
4517
|
+
);
|
|
4518
|
+
const offender = unchecked.find((_, i) => clientOnly[i]);
|
|
4519
|
+
if (offender) {
|
|
4520
|
+
const [local] = offender;
|
|
4521
|
+
throw revalidateError(
|
|
4522
|
+
file,
|
|
4523
|
+
code,
|
|
4524
|
+
value,
|
|
4525
|
+
`\`${local}\` is imported from "${imports.get(local).source}", a client-only module: on the server a "use client" module's exports are client references and cannot be called. Import the predicate's inputs from a module without "use client".`
|
|
4526
|
+
);
|
|
4527
|
+
}
|
|
4528
|
+
for (const [local, valueUse] of free.imports) {
|
|
4529
|
+
used.set(local, (used.get(local) ?? false) || valueUse);
|
|
4530
|
+
}
|
|
4531
|
+
const source = code.slice(value.start, value.end);
|
|
4532
|
+
const key = keyOf(relativeFile, value);
|
|
4533
|
+
entries.set(key, source);
|
|
4534
|
+
s.overwrite(
|
|
4535
|
+
arg.start,
|
|
4536
|
+
arg.end,
|
|
4537
|
+
`{ ${HOISTED_REVALIDATE_KEY}: ${JSON.stringify(key)} }`
|
|
4538
|
+
);
|
|
4539
|
+
}
|
|
4540
|
+
const importLines = await emitImports(used, imports, () => {
|
|
4541
|
+
});
|
|
4542
|
+
const module = [
|
|
4543
|
+
`import { registerClientUrlRevalidators as ${REGISTER} } from "@rangojs/router/server";`,
|
|
4544
|
+
...importLines,
|
|
4545
|
+
`${REGISTER}({`,
|
|
4546
|
+
...[...entries].map(
|
|
4547
|
+
([key, source]) => ` ${JSON.stringify(key)}: ${source},`
|
|
4548
|
+
),
|
|
4549
|
+
`});`,
|
|
4550
|
+
""
|
|
4551
|
+
].join("\n");
|
|
4552
|
+
return {
|
|
4553
|
+
code: s.toString(),
|
|
4554
|
+
map: s.generateMap({ hires: true, source: file }),
|
|
4555
|
+
module,
|
|
4556
|
+
keys: [...entries.keys()]
|
|
4557
|
+
};
|
|
4558
|
+
}
|
|
4559
|
+
async function isClientOnly(binding, deps) {
|
|
4560
|
+
return binding.source === "client-only" || Boolean(await deps.isClientModule?.(binding.source));
|
|
4561
|
+
}
|
|
4562
|
+
function parseHoistedRevalidateId(id) {
|
|
4563
|
+
const q = id.indexOf("?");
|
|
4564
|
+
if (q === -1) return null;
|
|
4565
|
+
const params = new URLSearchParams(id.slice(q + 1));
|
|
4566
|
+
return params.has(CLIENT_URLS_REVALIDATE_QUERY) ? id.slice(0, q) : null;
|
|
4567
|
+
}
|
|
4568
|
+
var HOISTED_ID_RE = new RegExp(
|
|
4569
|
+
`[?&]${CLIENT_URLS_REVALIDATE_QUERY}(?:[=&]|$)`
|
|
4570
|
+
);
|
|
4571
|
+
var SOURCE_ID_RE = /\.[cm]?[jt]sx?(?:\?|$)/;
|
|
4572
|
+
var NODE_MODULES_RE = /\/node_modules\//;
|
|
4573
|
+
function clientUrlsRevalidateHoistPlugin() {
|
|
4574
|
+
const emitted = /* @__PURE__ */ new Map();
|
|
4575
|
+
const clientModules = /* @__PURE__ */ new Map();
|
|
4576
|
+
let root = process.cwd();
|
|
4577
|
+
const isClientFile = (file) => {
|
|
4578
|
+
let known = clientModules.get(file);
|
|
4579
|
+
if (!known) {
|
|
4580
|
+
known = readSource(file).then(
|
|
4581
|
+
(text) => text !== null && text.includes("use client") && hasUseClientDirective(text)
|
|
4582
|
+
);
|
|
4583
|
+
clientModules.set(file, known);
|
|
4584
|
+
}
|
|
4585
|
+
return known;
|
|
4586
|
+
};
|
|
4587
|
+
return [
|
|
4588
|
+
{
|
|
4589
|
+
name: "@rangojs/router:client-urls-revalidate-hoist",
|
|
4590
|
+
enforce: "pre",
|
|
4591
|
+
configResolved(config) {
|
|
4592
|
+
root = config.root;
|
|
4593
|
+
},
|
|
4594
|
+
buildStart() {
|
|
4595
|
+
clientModules.clear();
|
|
4596
|
+
},
|
|
4597
|
+
watchChange(id) {
|
|
4598
|
+
const file = normalizePath4(id);
|
|
4599
|
+
clientModules.delete(file);
|
|
4600
|
+
emitted.delete(file);
|
|
4601
|
+
},
|
|
4602
|
+
load: {
|
|
4603
|
+
filter: { id: HOISTED_ID_RE },
|
|
4604
|
+
async handler(id) {
|
|
4605
|
+
const hoistedFile = parseHoistedRevalidateId(id);
|
|
4606
|
+
if (hoistedFile === null) return;
|
|
4607
|
+
const module = await loadEmittedOrDisk(
|
|
4608
|
+
emitted,
|
|
4609
|
+
hoistedFile,
|
|
4610
|
+
async (disk) => (await hoistClientUrlsRevalidates(disk, hoistedFile, { root }))?.module
|
|
4611
|
+
);
|
|
4612
|
+
return module ?? "export {};\n";
|
|
4613
|
+
}
|
|
4614
|
+
},
|
|
4615
|
+
transform: {
|
|
4616
|
+
filter: {
|
|
4617
|
+
id: {
|
|
4618
|
+
include: SOURCE_ID_RE,
|
|
4619
|
+
exclude: [NODE_MODULES_RE, HOISTED_ID_RE]
|
|
4620
|
+
},
|
|
4621
|
+
code: CLIENT_URLS_RE
|
|
4622
|
+
},
|
|
4623
|
+
async handler(code, id) {
|
|
4624
|
+
if (id.includes("/node_modules/") || parseHoistedRevalidateId(id)) {
|
|
4625
|
+
return;
|
|
4626
|
+
}
|
|
4627
|
+
const file = normalizePath4(id.split("?", 1)[0]);
|
|
4628
|
+
if (!SOURCE_FILE_RE.test(file)) return;
|
|
4629
|
+
const rsc = this.environment?.name === "rsc";
|
|
4630
|
+
if (rsc) emitted.delete(file);
|
|
4631
|
+
const result = await hoistClientUrlsRevalidates(code, id, {
|
|
4632
|
+
root,
|
|
4633
|
+
isClientModule: rsc ? async (source) => {
|
|
4634
|
+
const target = await resolveSourceTarget(this, source, id, {
|
|
4635
|
+
skipNodeModules: false
|
|
4636
|
+
});
|
|
4637
|
+
return target !== null && await isClientFile(target);
|
|
4638
|
+
} : void 0
|
|
4639
|
+
});
|
|
4640
|
+
if (!result) return;
|
|
4641
|
+
if (rsc) await recordEmitted(emitted, file, result.module);
|
|
4642
|
+
return { code: result.code, map: result.map };
|
|
4643
|
+
}
|
|
4644
|
+
}
|
|
4645
|
+
},
|
|
4646
|
+
{
|
|
4647
|
+
name: "@rangojs/router:client-urls-revalidate-register",
|
|
4648
|
+
enforce: "post",
|
|
4649
|
+
applyToEnvironment: (env) => env.name === "rsc",
|
|
4650
|
+
transform: {
|
|
4651
|
+
filter: { code: "registerClientReference" },
|
|
4652
|
+
handler(code, id) {
|
|
4653
|
+
if (parseHoistedRevalidateId(id)) return;
|
|
4654
|
+
const file = normalizePath4(id.split("?", 1)[0]);
|
|
4655
|
+
if (!emitted.has(file)) return;
|
|
4656
|
+
const s = new MagicString5(code);
|
|
4657
|
+
s.append(
|
|
4658
|
+
`
|
|
4659
|
+
import ${JSON.stringify(`${file}?${CLIENT_URLS_REVALIDATE_QUERY}`)};
|
|
4660
|
+
`
|
|
4661
|
+
);
|
|
4662
|
+
return { code: s.toString(), map: s.generateMap({ hires: true }) };
|
|
4663
|
+
}
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4666
|
+
];
|
|
4667
|
+
}
|
|
4668
|
+
|
|
4168
4669
|
// src/vite/plugins/client-ref-dedup.ts
|
|
4169
4670
|
init_debug();
|
|
4170
4671
|
import { existsSync, readFileSync } from "node:fs";
|
|
4171
|
-
import { isAbsolute, join, normalize, relative } from "node:path";
|
|
4672
|
+
import { isAbsolute as isAbsolute2, join as join2, normalize, relative as relative3 } from "node:path";
|
|
4172
4673
|
var debug4 = createRangoDebugger(NS.transform);
|
|
4173
4674
|
var CLIENT_IN_SERVER_PROXY_PREFIX = "virtual:vite-rsc/client-in-server-package-proxy/";
|
|
4174
4675
|
var DEDUP_PREFIX = "\0rango:dedup/";
|
|
@@ -4201,7 +4702,7 @@ function readPackageMetadata(source, cache3) {
|
|
|
4201
4702
|
if (!root) return;
|
|
4202
4703
|
const cached = cache3.get(root);
|
|
4203
4704
|
if (cached !== void 0) return cached ?? void 0;
|
|
4204
|
-
const packageJsonPath =
|
|
4705
|
+
const packageJsonPath = join2(root, "package.json");
|
|
4205
4706
|
if (!existsSync(packageJsonPath)) {
|
|
4206
4707
|
cache3.set(root, null);
|
|
4207
4708
|
return;
|
|
@@ -4254,8 +4755,8 @@ function getPublicSpecifierCandidates(metadata, packageSpecifier, source) {
|
|
|
4254
4755
|
return [];
|
|
4255
4756
|
}
|
|
4256
4757
|
const candidates = /* @__PURE__ */ new Set();
|
|
4257
|
-
const sourceRelative = `./${
|
|
4258
|
-
if (sourceRelative.startsWith("./../") ||
|
|
4758
|
+
const sourceRelative = `./${relative3(metadata.root, source).replaceAll("\\", "/")}`;
|
|
4759
|
+
if (sourceRelative.startsWith("./../") || isAbsolute2(sourceRelative.slice(2))) {
|
|
4259
4760
|
return [];
|
|
4260
4761
|
}
|
|
4261
4762
|
for (const [exportKey, target] of Object.entries(metadata.exports)) {
|
|
@@ -4342,7 +4843,7 @@ function clientRefDedup() {
|
|
|
4342
4843
|
configResolved(config) {
|
|
4343
4844
|
const clientEnv = config.environments?.["client"];
|
|
4344
4845
|
clientExclude = clientEnv?.optimizeDeps?.exclude ?? config.optimizeDeps?.exclude ?? [];
|
|
4345
|
-
rootImporter =
|
|
4846
|
+
rootImporter = join2(config.root, "index.html");
|
|
4346
4847
|
resolvePackage = config.createResolver({ scan: true });
|
|
4347
4848
|
},
|
|
4348
4849
|
buildEnd() {
|
|
@@ -4411,12 +4912,12 @@ function clientRefDedup() {
|
|
|
4411
4912
|
}
|
|
4412
4913
|
|
|
4413
4914
|
// src/vite/plugins/stable-rsc-output.ts
|
|
4414
|
-
import { parseAst as
|
|
4915
|
+
import { parseAst as parseAst6 } from "vite";
|
|
4415
4916
|
|
|
4416
4917
|
// src/vite/discovery/build-versions.ts
|
|
4417
|
-
import { createHash as
|
|
4918
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
4418
4919
|
import { isBuiltin } from "node:module";
|
|
4419
|
-
import { posix, relative as
|
|
4920
|
+
import { posix, relative as relative5 } from "node:path";
|
|
4420
4921
|
|
|
4421
4922
|
// src/router-versions.ts
|
|
4422
4923
|
var DEFAULT_ROUTER_VERSIONS_KEY = "*";
|
|
@@ -4990,7 +5491,7 @@ function resolveRouterMembers(server, client, routers) {
|
|
|
4990
5491
|
return members;
|
|
4991
5492
|
}
|
|
4992
5493
|
function sha256(value) {
|
|
4993
|
-
return
|
|
5494
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
4994
5495
|
}
|
|
4995
5496
|
var baseName = posix.basename;
|
|
4996
5497
|
function isAbsolutePath(path6) {
|
|
@@ -5011,7 +5512,7 @@ function portableModuleId(id, projectRoot) {
|
|
|
5011
5512
|
return path6.slice(nodeModules + 1).replace(PNPM_PEER_SUFFIX, "$1");
|
|
5012
5513
|
}
|
|
5013
5514
|
if (isAbsolutePath(path6)) {
|
|
5014
|
-
return
|
|
5515
|
+
return relative5(projectRoot, path6).replaceAll("\\", "/");
|
|
5015
5516
|
}
|
|
5016
5517
|
return withoutWorkingDirectory(path6).replace(
|
|
5017
5518
|
/([?&][^=&]+=)([^&]+)/g,
|
|
@@ -5372,7 +5873,7 @@ function literalProperties(object) {
|
|
|
5372
5873
|
function defaultExportProperties(code) {
|
|
5373
5874
|
let program;
|
|
5374
5875
|
try {
|
|
5375
|
-
program =
|
|
5876
|
+
program = parseAst6(code);
|
|
5376
5877
|
} catch {
|
|
5377
5878
|
return void 0;
|
|
5378
5879
|
}
|
|
@@ -5428,7 +5929,7 @@ import { resolve } from "node:path";
|
|
|
5428
5929
|
// package.json
|
|
5429
5930
|
var package_default = {
|
|
5430
5931
|
name: "@rangojs/router",
|
|
5431
|
-
version: "0.
|
|
5932
|
+
version: "0.24.0",
|
|
5432
5933
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
5433
5934
|
keywords: [
|
|
5434
5935
|
"react",
|
|
@@ -5887,58 +6388,6 @@ declare global {
|
|
|
5887
6388
|
`;
|
|
5888
6389
|
}
|
|
5889
6390
|
|
|
5890
|
-
// src/build/route-types/scan-filter.ts
|
|
5891
|
-
import { join as join2, relative as relative4 } from "node:path";
|
|
5892
|
-
import { readdirSync } from "node:fs";
|
|
5893
|
-
import picomatch from "picomatch";
|
|
5894
|
-
var DEFAULT_EXCLUDE_PATTERNS = [
|
|
5895
|
-
"**/__tests__/**",
|
|
5896
|
-
"**/__mocks__/**",
|
|
5897
|
-
"**/dist/**",
|
|
5898
|
-
"**/coverage/**",
|
|
5899
|
-
"**/*.test.{ts,tsx,js,jsx}",
|
|
5900
|
-
"**/*.spec.{ts,tsx,js,jsx}"
|
|
5901
|
-
];
|
|
5902
|
-
function createScanFilter(root, opts) {
|
|
5903
|
-
const { include, exclude } = opts;
|
|
5904
|
-
const hasInclude = include && include.length > 0;
|
|
5905
|
-
const hasCustomExclude = exclude !== void 0;
|
|
5906
|
-
if (!hasInclude && !hasCustomExclude) return void 0;
|
|
5907
|
-
const effectiveExclude = exclude ?? DEFAULT_EXCLUDE_PATTERNS;
|
|
5908
|
-
const includeMatcher = hasInclude ? picomatch(include) : null;
|
|
5909
|
-
const excludeMatcher = effectiveExclude.length > 0 ? picomatch(effectiveExclude) : null;
|
|
5910
|
-
return (absolutePath) => {
|
|
5911
|
-
const rel = relative4(root, absolutePath);
|
|
5912
|
-
if (excludeMatcher && excludeMatcher(rel)) return false;
|
|
5913
|
-
if (includeMatcher) return includeMatcher(rel);
|
|
5914
|
-
return true;
|
|
5915
|
-
};
|
|
5916
|
-
}
|
|
5917
|
-
function findTsFiles(dir, filter) {
|
|
5918
|
-
const results = [];
|
|
5919
|
-
let entries;
|
|
5920
|
-
try {
|
|
5921
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
5922
|
-
} catch (err) {
|
|
5923
|
-
console.warn(
|
|
5924
|
-
`[rango] Failed to scan directory ${dir}: ${err.message}`
|
|
5925
|
-
);
|
|
5926
|
-
return results;
|
|
5927
|
-
}
|
|
5928
|
-
for (const entry of entries) {
|
|
5929
|
-
const fullPath = join2(dir, entry.name);
|
|
5930
|
-
if (entry.isDirectory()) {
|
|
5931
|
-
if (entry.name === "node_modules" || entry.name.startsWith(".") || entry.name === "dist" || entry.name === "build" || entry.name === "coverage")
|
|
5932
|
-
continue;
|
|
5933
|
-
results.push(...findTsFiles(fullPath, filter));
|
|
5934
|
-
} else if ((entry.name.endsWith(".ts") || entry.name.endsWith(".tsx") || entry.name.endsWith(".js") || entry.name.endsWith(".jsx")) && !entry.name.includes(".gen.")) {
|
|
5935
|
-
if (filter && !filter(fullPath)) continue;
|
|
5936
|
-
results.push(fullPath);
|
|
5937
|
-
}
|
|
5938
|
-
}
|
|
5939
|
-
return results;
|
|
5940
|
-
}
|
|
5941
|
-
|
|
5942
6391
|
// src/build/route-types/per-module-writer.ts
|
|
5943
6392
|
import ts4 from "typescript";
|
|
5944
6393
|
|
|
@@ -6513,7 +6962,7 @@ function isRoutableSourceFile(name) {
|
|
|
6513
6962
|
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
6514
6963
|
}
|
|
6515
6964
|
function isExcludedScanDir(name) {
|
|
6516
|
-
return name
|
|
6965
|
+
return isUniversallySkippedScanDir(name) || name === "__tests__" || name === "__mocks__";
|
|
6517
6966
|
}
|
|
6518
6967
|
function findCallSiteFilesRecursive(dir, pattern, patternG, stopAtMatchDir, filter, results) {
|
|
6519
6968
|
let entries;
|
|
@@ -6896,28 +7345,7 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
6896
7345
|
}
|
|
6897
7346
|
|
|
6898
7347
|
// src/vite/plugins/version-plugin.ts
|
|
6899
|
-
import { parseAst as
|
|
6900
|
-
|
|
6901
|
-
// src/vite/utils/directive-prologue.ts
|
|
6902
|
-
import { parseAst as parseAst5 } from "vite";
|
|
6903
|
-
function hasUseClientDirective2(source) {
|
|
6904
|
-
let program;
|
|
6905
|
-
try {
|
|
6906
|
-
program = parseAst5(source, { lang: "tsx" });
|
|
6907
|
-
} catch {
|
|
6908
|
-
return false;
|
|
6909
|
-
}
|
|
6910
|
-
for (const node of program.body ?? []) {
|
|
6911
|
-
if (node?.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string") {
|
|
6912
|
-
if (node.expression.value === "use client") return true;
|
|
6913
|
-
continue;
|
|
6914
|
-
}
|
|
6915
|
-
break;
|
|
6916
|
-
}
|
|
6917
|
-
return false;
|
|
6918
|
-
}
|
|
6919
|
-
|
|
6920
|
-
// src/vite/plugins/version-plugin.ts
|
|
7348
|
+
import { parseAst as parseAst7 } from "vite";
|
|
6921
7349
|
function isCodeModule(id) {
|
|
6922
7350
|
return /\.(tsx?|jsx?)($|\?)/.test(id);
|
|
6923
7351
|
}
|
|
@@ -6925,10 +7353,10 @@ function normalizeModuleId(id) {
|
|
|
6925
7353
|
return id.split("?", 1)[0];
|
|
6926
7354
|
}
|
|
6927
7355
|
function getClientModuleSignature(source) {
|
|
6928
|
-
if (!
|
|
7356
|
+
if (!hasUseClientDirective(source)) return void 0;
|
|
6929
7357
|
let program;
|
|
6930
7358
|
try {
|
|
6931
|
-
program =
|
|
7359
|
+
program = parseAst7(source, { lang: "tsx" });
|
|
6932
7360
|
} catch {
|
|
6933
7361
|
return void 0;
|
|
6934
7362
|
}
|
|
@@ -7103,7 +7531,7 @@ function isViteDepCachePath(filePath, cacheDir) {
|
|
|
7103
7531
|
|
|
7104
7532
|
// src/vite/utils/shared-utils.ts
|
|
7105
7533
|
import * as Vite from "vite";
|
|
7106
|
-
import { isAbsolute as
|
|
7534
|
+
import { isAbsolute as isAbsolute3, resolve as resolve4 } from "node:path";
|
|
7107
7535
|
|
|
7108
7536
|
// src/vite/plugins/performance-tracks.ts
|
|
7109
7537
|
init_debug();
|
|
@@ -7190,7 +7618,7 @@ var sharedRolldownOptions = {
|
|
|
7190
7618
|
function normalizeHostRouterEntry(rawInput, root, exists) {
|
|
7191
7619
|
const raw = rawInput.replaceAll("\\", "/");
|
|
7192
7620
|
const isRelative = raw.startsWith("./") || raw.startsWith("../");
|
|
7193
|
-
const isRooted = raw.startsWith("/") ||
|
|
7621
|
+
const isRooted = raw.startsWith("/") || isAbsolute3(rawInput);
|
|
7194
7622
|
if (isRooted) return raw;
|
|
7195
7623
|
if (isRelative) {
|
|
7196
7624
|
if (!exists(resolve4(root, raw))) {
|
|
@@ -7680,7 +8108,7 @@ function createCjsToEsmPlugin() {
|
|
|
7680
8108
|
}
|
|
7681
8109
|
|
|
7682
8110
|
// src/vite/router-discovery.ts
|
|
7683
|
-
import { createServer as createViteServer } from "vite";
|
|
8111
|
+
import { createServer as createViteServer, normalizePath as normalizePath8 } from "vite";
|
|
7684
8112
|
import { dirname as dirname7, join as join10, resolve as resolve13 } from "node:path";
|
|
7685
8113
|
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
|
|
7686
8114
|
import { createRequire as createRequire3, register } from "node:module";
|
|
@@ -8073,10 +8501,10 @@ function evictHandlerCode(code, exports, fnName, brand) {
|
|
|
8073
8501
|
}
|
|
8074
8502
|
|
|
8075
8503
|
// src/vite/discovery/self-gen-tracking.ts
|
|
8076
|
-
import { createHash as
|
|
8504
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
8077
8505
|
import { readFileSync as readFileSync4 } from "node:fs";
|
|
8078
8506
|
function markSelfGenWrite(state, filePath, content) {
|
|
8079
|
-
const hash =
|
|
8507
|
+
const hash = createHash5("sha256").update(content).digest("hex");
|
|
8080
8508
|
state.selfWrittenGenFiles.set(filePath, { at: Date.now(), hash });
|
|
8081
8509
|
}
|
|
8082
8510
|
function consumeSelfGenWrite(state, filePath) {
|
|
@@ -8094,7 +8522,7 @@ function checkSelfGenWrite(state, filePath, consume) {
|
|
|
8094
8522
|
}
|
|
8095
8523
|
try {
|
|
8096
8524
|
const current = readFileSync4(filePath, "utf-8");
|
|
8097
|
-
const currentHash =
|
|
8525
|
+
const currentHash = createHash5("sha256").update(current).digest("hex");
|
|
8098
8526
|
if (currentHash === info.hash) {
|
|
8099
8527
|
if (consume) state.selfWrittenGenFiles.delete(filePath);
|
|
8100
8528
|
return true;
|
|
@@ -8262,7 +8690,7 @@ function insertSegments(node, segments, index, leafBase, paramNames) {
|
|
|
8262
8690
|
}
|
|
8263
8691
|
const segment = segments[index];
|
|
8264
8692
|
if (segment.type === "static") {
|
|
8265
|
-
if (!node.s) node.s =
|
|
8693
|
+
if (!node.s) node.s = /* @__PURE__ */ Object.create(null);
|
|
8266
8694
|
if (!node.s[segment.value]) node.s[segment.value] = {};
|
|
8267
8695
|
insertSegments(
|
|
8268
8696
|
node.s[segment.value],
|
|
@@ -8562,6 +8990,13 @@ function jsonParseExpression(value) {
|
|
|
8562
8990
|
}
|
|
8563
8991
|
|
|
8564
8992
|
// src/context-var.ts
|
|
8993
|
+
function createVar(options) {
|
|
8994
|
+
return {
|
|
8995
|
+
__brand: "context-var",
|
|
8996
|
+
key: /* @__PURE__ */ Symbol(),
|
|
8997
|
+
cache: options?.cache !== false
|
|
8998
|
+
};
|
|
8999
|
+
}
|
|
8565
9000
|
function hasContextVars(variables) {
|
|
8566
9001
|
return Object.keys(variables).length > 0 || Object.getOwnPropertySymbols(variables).length > 0;
|
|
8567
9002
|
}
|
|
@@ -8574,7 +9009,11 @@ function getNonCacheableKeys(variables) {
|
|
|
8574
9009
|
}
|
|
8575
9010
|
return variables[NON_CACHEABLE_KEYS];
|
|
8576
9011
|
}
|
|
8577
|
-
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
9012
|
+
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
9013
|
+
"__proto__",
|
|
9014
|
+
"constructor",
|
|
9015
|
+
"prototype"
|
|
9016
|
+
]);
|
|
8578
9017
|
function contextSet(variables, keyOrVar, value, options) {
|
|
8579
9018
|
if (typeof keyOrVar === "string") {
|
|
8580
9019
|
if (FORBIDDEN_KEYS.has(keyOrVar)) {
|
|
@@ -8595,7 +9034,7 @@ function contextSet(variables, keyOrVar, value, options) {
|
|
|
8595
9034
|
}
|
|
8596
9035
|
|
|
8597
9036
|
// src/vite/utils/prerender-utils.ts
|
|
8598
|
-
import { createHash as
|
|
9037
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
8599
9038
|
import {
|
|
8600
9039
|
copyFileSync,
|
|
8601
9040
|
existsSync as existsSync6,
|
|
@@ -8768,7 +9207,7 @@ function resetStagedBuildAssets(projectRoot) {
|
|
|
8768
9207
|
}
|
|
8769
9208
|
function writeBuildAssetModule(dir, prefix, exportValue) {
|
|
8770
9209
|
mkdirSync(dir, { recursive: true });
|
|
8771
|
-
const contentHash =
|
|
9210
|
+
const contentHash = createHash6("sha256").update(exportValue).digest("hex").slice(0, 8);
|
|
8772
9211
|
const fileName = `${prefix}-${contentHash}.js`;
|
|
8773
9212
|
const filePath = resolve7(dir, fileName);
|
|
8774
9213
|
if (!existsSync6(filePath)) {
|
|
@@ -9303,8 +9742,8 @@ init_client_ref_hashing();
|
|
|
9303
9742
|
|
|
9304
9743
|
// src/vite/discovery/client-urls-projection.ts
|
|
9305
9744
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
|
|
9306
|
-
import { isAbsolute as
|
|
9307
|
-
import { normalizePath as
|
|
9745
|
+
import { isAbsolute as isAbsolute4, relative as relative6, resolve as resolve8 } from "node:path";
|
|
9746
|
+
import { normalizePath as normalizePath7, parseAst as parseAst8 } from "vite";
|
|
9308
9747
|
|
|
9309
9748
|
// src/client-urls/server-projection.ts
|
|
9310
9749
|
import * as React5 from "react";
|
|
@@ -9614,7 +10053,7 @@ import { createContext as createContext4 } from "react";
|
|
|
9614
10053
|
var OutletContext = createContext4(null);
|
|
9615
10054
|
|
|
9616
10055
|
// src/route-content-wrapper.tsx
|
|
9617
|
-
import { Component, Suspense, use, useMemo as useMemo3 } from "react";
|
|
10056
|
+
import { Component, Suspense, use as use2, useMemo as useMemo3 } from "react";
|
|
9618
10057
|
|
|
9619
10058
|
// src/outlet-provider.tsx
|
|
9620
10059
|
import {
|
|
@@ -9662,10 +10101,27 @@ function getAppVersion() {
|
|
|
9662
10101
|
return currentVersion2;
|
|
9663
10102
|
}
|
|
9664
10103
|
|
|
10104
|
+
// src/router/basename.ts
|
|
10105
|
+
function prefixBasename(path6, basename2) {
|
|
10106
|
+
if (!basename2 || !path6.startsWith("/") || path6 === basename2 || path6.startsWith(basename2 + "/") || path6.startsWith(basename2 + "?") || path6.startsWith(basename2 + "#")) {
|
|
10107
|
+
return path6;
|
|
10108
|
+
}
|
|
10109
|
+
return path6 === "/" ? basename2 : basename2 + path6;
|
|
10110
|
+
}
|
|
10111
|
+
|
|
9665
10112
|
// src/loader-redirect.tsx
|
|
9666
10113
|
init_validate_redirect_origin();
|
|
9667
10114
|
init_redirect_origin();
|
|
9668
10115
|
|
|
10116
|
+
// src/browser/defer.ts
|
|
10117
|
+
import { use } from "react";
|
|
10118
|
+
|
|
10119
|
+
// src/thenable-status.ts
|
|
10120
|
+
var SETTLED_THENABLE = Object.assign(
|
|
10121
|
+
Promise.resolve(void 0),
|
|
10122
|
+
{ status: "fulfilled", value: void 0, _debugInfo: [] }
|
|
10123
|
+
);
|
|
10124
|
+
|
|
9669
10125
|
// src/route-content-wrapper.tsx
|
|
9670
10126
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
9671
10127
|
import { createElement as createElement3 } from "react";
|
|
@@ -9674,7 +10130,7 @@ import { createElement as createElement3 } from "react";
|
|
|
9674
10130
|
import {
|
|
9675
10131
|
isValidElement,
|
|
9676
10132
|
startTransition as startTransition2,
|
|
9677
|
-
use as
|
|
10133
|
+
use as use3,
|
|
9678
10134
|
useCallback,
|
|
9679
10135
|
useContext as useContext7,
|
|
9680
10136
|
useEffect as useEffect5,
|
|
@@ -9684,12 +10140,6 @@ import {
|
|
|
9684
10140
|
useState as useState3
|
|
9685
10141
|
} from "react";
|
|
9686
10142
|
|
|
9687
|
-
// src/thenable-status.ts
|
|
9688
|
-
var SETTLED_THENABLE = Object.assign(
|
|
9689
|
-
Promise.resolve(void 0),
|
|
9690
|
-
{ status: "fulfilled", value: void 0, _debugInfo: [] }
|
|
9691
|
-
);
|
|
9692
|
-
|
|
9693
10143
|
// src/loader-store.ts
|
|
9694
10144
|
var EMPTY_SNAPSHOT = Object.freeze({
|
|
9695
10145
|
value: void 0,
|
|
@@ -9751,7 +10201,7 @@ import {
|
|
|
9751
10201
|
useCallback as useCallback4,
|
|
9752
10202
|
useMemo as useMemo7,
|
|
9753
10203
|
useRef as useRef11,
|
|
9754
|
-
use as
|
|
10204
|
+
use as use4,
|
|
9755
10205
|
startTransition as startTransition5
|
|
9756
10206
|
} from "react";
|
|
9757
10207
|
|
|
@@ -10068,13 +10518,10 @@ var Link = forwardRef(function Link2({
|
|
|
10068
10518
|
}, ref) {
|
|
10069
10519
|
const ctx = useContext15(NavigationStoreContext);
|
|
10070
10520
|
const isExternal = isExternalUrl(to, ctx?.origin);
|
|
10071
|
-
const resolvedTo = useMemo8(
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
return to;
|
|
10076
|
-
return to === "/" ? bn : bn + to;
|
|
10077
|
-
}, [to, isExternal, ctx?.basename]);
|
|
10521
|
+
const resolvedTo = useMemo8(
|
|
10522
|
+
() => isExternal ? to : prefixBasename(to, ctx?.basename),
|
|
10523
|
+
[to, isExternal, ctx?.basename]
|
|
10524
|
+
);
|
|
10078
10525
|
const configuredStrategy = prefetch ?? ctx?.defaultPrefetch ?? ENVIRONMENT_DEFAULT_PREFETCH;
|
|
10079
10526
|
const internalRef = useRef13(null);
|
|
10080
10527
|
const setRef = useCallback5(
|
|
@@ -10331,6 +10778,19 @@ var ALL_USE_ITEM_TYPES = new Set(
|
|
|
10331
10778
|
|
|
10332
10779
|
// src/server/request-context.ts
|
|
10333
10780
|
import { AsyncLocalStorage as AsyncLocalStorage5 } from "node:async_hooks";
|
|
10781
|
+
|
|
10782
|
+
// src/server/slot-accessors.ts
|
|
10783
|
+
function slotAccessor(slot, enumerable) {
|
|
10784
|
+
return {
|
|
10785
|
+
get() {
|
|
10786
|
+
return this[slot]();
|
|
10787
|
+
},
|
|
10788
|
+
enumerable,
|
|
10789
|
+
configurable: true
|
|
10790
|
+
};
|
|
10791
|
+
}
|
|
10792
|
+
|
|
10793
|
+
// src/server/request-context.ts
|
|
10334
10794
|
init_cookie_name();
|
|
10335
10795
|
|
|
10336
10796
|
// src/router/segment-resolution/mask-nested.ts
|
|
@@ -10395,12 +10855,41 @@ var THEME_READ = {
|
|
|
10395
10855
|
}
|
|
10396
10856
|
};
|
|
10397
10857
|
|
|
10858
|
+
// src/router/segment-resolution/prefetch-deferral.ts
|
|
10859
|
+
init_prefetch_markers();
|
|
10860
|
+
|
|
10861
|
+
// src/cache/document-cache-policy.ts
|
|
10862
|
+
init_cookie_name();
|
|
10863
|
+
|
|
10864
|
+
// src/server/rewrite-trail.ts
|
|
10865
|
+
var REWRITE_TRAIL = createVar();
|
|
10866
|
+
|
|
10398
10867
|
// src/cache/invalidation-order.ts
|
|
10399
10868
|
var order = globalThis[/* @__PURE__ */ Symbol.for("rangojs-router:tag-invalidation-order")] ??= { seq: 0, tags: /* @__PURE__ */ new Map(), forgotten: 0 };
|
|
10400
10869
|
var responseStarts = globalThis[/* @__PURE__ */ Symbol.for("rangojs-router:response-execution-start")] ??= /* @__PURE__ */ new WeakMap();
|
|
10401
10870
|
|
|
10402
10871
|
// src/server/request-context.ts
|
|
10403
10872
|
var requestContextStorage = new AsyncLocalStorage5();
|
|
10873
|
+
var RES_SLOT = /* @__PURE__ */ Symbol("rango.requestContext.res");
|
|
10874
|
+
var RENDER_BARRIER_SLOT = /* @__PURE__ */ Symbol(
|
|
10875
|
+
"rango.requestContext.renderBarrier"
|
|
10876
|
+
);
|
|
10877
|
+
var RES_DESCRIPTOR = {
|
|
10878
|
+
...slotAccessor(RES_SLOT, true),
|
|
10879
|
+
set(_) {
|
|
10880
|
+
throw new Error(
|
|
10881
|
+
"ctx.res is read-only. Use ctx.header() to set response headers, or cookies() for cookie mutations."
|
|
10882
|
+
);
|
|
10883
|
+
}
|
|
10884
|
+
};
|
|
10885
|
+
var RENDER_BARRIER_DESCRIPTOR = slotAccessor(
|
|
10886
|
+
RENDER_BARRIER_SLOT,
|
|
10887
|
+
true
|
|
10888
|
+
);
|
|
10889
|
+
var DERIVED_RENDER_BARRIER_DESCRIPTOR = {
|
|
10890
|
+
...RENDER_BARRIER_DESCRIPTOR,
|
|
10891
|
+
enumerable: false
|
|
10892
|
+
};
|
|
10404
10893
|
|
|
10405
10894
|
// src/route-definition/redirect.ts
|
|
10406
10895
|
init_redirect_origin();
|
|
@@ -10542,7 +11031,10 @@ function serializeTransition(route2) {
|
|
|
10542
11031
|
}
|
|
10543
11032
|
return Object.freeze(config);
|
|
10544
11033
|
}
|
|
10545
|
-
function
|
|
11034
|
+
function indicesWhere(items, pred) {
|
|
11035
|
+
return items.flatMap((item, index) => pred(item) ? [index] : []);
|
|
11036
|
+
}
|
|
11037
|
+
function serializeRoute(route2, options) {
|
|
10546
11038
|
const loaderIds = route2.loaders.map(({ loader: loader2 }, index) => {
|
|
10547
11039
|
if (typeof loader2.$$id !== "string" || loader2.$$id.length === 0) {
|
|
10548
11040
|
throw projectionError(
|
|
@@ -10552,7 +11044,25 @@ function serializeRoute(route2) {
|
|
|
10552
11044
|
}
|
|
10553
11045
|
return loader2.$$id;
|
|
10554
11046
|
});
|
|
10555
|
-
const
|
|
11047
|
+
const loaderRevalidate = route2.loaders.map(
|
|
11048
|
+
({ loader: loader2, revalidate: revalidate2 }) => revalidate2.flatMap((entry) => {
|
|
11049
|
+
if (isHoistedRevalidateRef(entry)) return [entry.$$rangoRevalidate];
|
|
11050
|
+
if (options.hoisted) {
|
|
11051
|
+
throw new Error(
|
|
11052
|
+
`clientUrls() revalidate() on loader "${loader2.$$id}" of route "${route2.pattern}" was not hoisted to the server: call the builder's revalidate() helper with an inline function or an imported predicate.`
|
|
11053
|
+
);
|
|
11054
|
+
}
|
|
11055
|
+
return [];
|
|
11056
|
+
})
|
|
11057
|
+
);
|
|
11058
|
+
const awaitedLoaderIndices = indicesWhere(
|
|
11059
|
+
route2.loaders,
|
|
11060
|
+
({ ssr }) => ssr === false
|
|
11061
|
+
);
|
|
11062
|
+
const deferrableLoaderIndices = indicesWhere(
|
|
11063
|
+
route2.loaders,
|
|
11064
|
+
({ prefetch }) => prefetch === false
|
|
11065
|
+
);
|
|
10556
11066
|
const transition2 = serializeTransition(route2);
|
|
10557
11067
|
return Object.freeze({
|
|
10558
11068
|
id: route2.id,
|
|
@@ -10562,6 +11072,12 @@ function serializeRoute(route2) {
|
|
|
10562
11072
|
loaderIds: Object.freeze(loaderIds),
|
|
10563
11073
|
hasLoading: route2.loading !== void 0,
|
|
10564
11074
|
...awaitedLoaderIndices.length > 0 ? { awaitedLoaderIndices: Object.freeze(awaitedLoaderIndices) } : {},
|
|
11075
|
+
...deferrableLoaderIndices.length > 0 ? { deferrableLoaderIndices: Object.freeze(deferrableLoaderIndices) } : {},
|
|
11076
|
+
...loaderRevalidate.some((keys) => keys.length > 0) ? {
|
|
11077
|
+
loaderRevalidate: Object.freeze(
|
|
11078
|
+
loaderRevalidate.map((keys) => Object.freeze(keys))
|
|
11079
|
+
)
|
|
11080
|
+
} : {},
|
|
10565
11081
|
...transition2 ? { transition: transition2 } : {},
|
|
10566
11082
|
...typeof route2.transition?.when === "function" ? { transitionWhen: true } : {}
|
|
10567
11083
|
});
|
|
@@ -10582,15 +11098,24 @@ function serializeIntercept(record, index) {
|
|
|
10582
11098
|
hasLoading: record.loading !== void 0
|
|
10583
11099
|
});
|
|
10584
11100
|
}
|
|
10585
|
-
function serializeClientUrlPatterns(patterns) {
|
|
11101
|
+
function serializeClientUrlPatterns(patterns, options = {}) {
|
|
10586
11102
|
return Object.freeze({
|
|
10587
11103
|
version: 1,
|
|
10588
|
-
routes: Object.freeze(
|
|
11104
|
+
routes: Object.freeze(
|
|
11105
|
+
patterns.routes.map((route2) => serializeRoute(route2, options))
|
|
11106
|
+
),
|
|
10589
11107
|
intercepts: Object.freeze(
|
|
10590
11108
|
(patterns.intercepts ?? []).map(serializeIntercept)
|
|
10591
11109
|
)
|
|
10592
11110
|
});
|
|
10593
11111
|
}
|
|
11112
|
+
function projectClientUrlsModule(namespace, options = {}) {
|
|
11113
|
+
const definition = namespace.default;
|
|
11114
|
+
if (typeof definition !== "object" && typeof definition !== "function" || definition === null || definition.__brand !== "client-urls") {
|
|
11115
|
+
return void 0;
|
|
11116
|
+
}
|
|
11117
|
+
return serializeClientUrlPatterns(definition, options);
|
|
11118
|
+
}
|
|
10594
11119
|
|
|
10595
11120
|
// src/vite/discovery/client-urls-projection.ts
|
|
10596
11121
|
init_client_ref_hashing();
|
|
@@ -10599,7 +11124,7 @@ var debug10 = createRangoDebugger(NS.discovery);
|
|
|
10599
11124
|
function hasDefaultExport(code) {
|
|
10600
11125
|
let program;
|
|
10601
11126
|
try {
|
|
10602
|
-
program =
|
|
11127
|
+
program = parseAst8(code, { lang: "tsx" });
|
|
10603
11128
|
} catch {
|
|
10604
11129
|
return false;
|
|
10605
11130
|
}
|
|
@@ -10615,20 +11140,20 @@ function hasDefaultExport(code) {
|
|
|
10615
11140
|
}
|
|
10616
11141
|
function normalizeSource(state, id) {
|
|
10617
11142
|
const cleanId = id.split("?", 1)[0];
|
|
10618
|
-
const absoluteId =
|
|
10619
|
-
return
|
|
11143
|
+
const absoluteId = isAbsolute4(cleanId) ? cleanId : resolve8(state.projectRoot, cleanId);
|
|
11144
|
+
return normalizePath7(absoluteId);
|
|
10620
11145
|
}
|
|
10621
11146
|
function referenceId(referenceKey) {
|
|
10622
11147
|
return `${referenceKey}#default`;
|
|
10623
11148
|
}
|
|
10624
11149
|
function recordClientUrlsModule(state, code, id) {
|
|
10625
|
-
if (!code.includes("clientUrls(") || !
|
|
11150
|
+
if (!code.includes("clientUrls(") || !hasUseClientDirective(code) || !hasDefaultExport(code)) {
|
|
10626
11151
|
return;
|
|
10627
11152
|
}
|
|
10628
11153
|
const source = normalizeSource(state, id);
|
|
10629
|
-
const projectRoot =
|
|
10630
|
-
const relativeId =
|
|
10631
|
-
const outsideProject = relativeId === ".." || relativeId.startsWith("../") ||
|
|
11154
|
+
const projectRoot = normalizePath7(resolve8(state.projectRoot));
|
|
11155
|
+
const relativeId = normalizePath7(relative6(projectRoot, source));
|
|
11156
|
+
const outsideProject = relativeId === ".." || relativeId.startsWith("../") || isAbsolute4(relativeId);
|
|
10632
11157
|
const devReferenceKey = outsideProject ? `/@fs${source}` : `/${relativeId}`;
|
|
10633
11158
|
const sourceByReferenceId = state.clientUrlSourceByReferenceId ??= /* @__PURE__ */ new Map();
|
|
10634
11159
|
sourceByReferenceId.set(referenceId(devReferenceKey), source);
|
|
@@ -10672,18 +11197,19 @@ async function refreshRecordedClientUrlProjections(state, ssrEnv, serverMod) {
|
|
|
10672
11197
|
}
|
|
10673
11198
|
}
|
|
10674
11199
|
for (const [source, referenceIds] of referenceIdsBySource) {
|
|
10675
|
-
let
|
|
11200
|
+
let module;
|
|
10676
11201
|
try {
|
|
10677
|
-
|
|
11202
|
+
module = await ssrEnv.runner.import(source);
|
|
10678
11203
|
} catch {
|
|
10679
11204
|
continue;
|
|
10680
11205
|
}
|
|
10681
|
-
|
|
11206
|
+
let projection;
|
|
11207
|
+
try {
|
|
11208
|
+
projection = projectClientUrlsModule(module, { hoisted: true });
|
|
11209
|
+
} catch {
|
|
10682
11210
|
continue;
|
|
10683
11211
|
}
|
|
10684
|
-
|
|
10685
|
-
definition
|
|
10686
|
-
);
|
|
11212
|
+
if (!projection) continue;
|
|
10687
11213
|
debug10?.(
|
|
10688
11214
|
"pre-entry refresh %s -> [%s]",
|
|
10689
11215
|
source,
|
|
@@ -10738,17 +11264,24 @@ async function discoverClientUrlProjections(state, ssrEnv, serverMod) {
|
|
|
10738
11264
|
cause
|
|
10739
11265
|
);
|
|
10740
11266
|
}
|
|
10741
|
-
|
|
10742
|
-
|
|
11267
|
+
let projection;
|
|
11268
|
+
try {
|
|
11269
|
+
projection = projectClientUrlsModule(module, { hoisted: true });
|
|
11270
|
+
} catch (cause) {
|
|
11271
|
+
throw projectionError2(
|
|
11272
|
+
referenceIds[0],
|
|
11273
|
+
source,
|
|
11274
|
+
cause instanceof Error ? cause.message : String(cause),
|
|
11275
|
+
cause
|
|
11276
|
+
);
|
|
11277
|
+
}
|
|
11278
|
+
if (!projection) {
|
|
10743
11279
|
throw projectionError2(
|
|
10744
11280
|
referenceIds[0],
|
|
10745
11281
|
source,
|
|
10746
11282
|
'the module default export must be created by clientUrls() and have __brand === "client-urls"'
|
|
10747
11283
|
);
|
|
10748
11284
|
}
|
|
10749
|
-
const projection = serializeClientUrlPatterns(
|
|
10750
|
-
definition
|
|
10751
|
-
);
|
|
10752
11285
|
for (const referenceId2 of referenceIds) {
|
|
10753
11286
|
nextProjections.set(referenceId2, projection);
|
|
10754
11287
|
}
|
|
@@ -10767,13 +11300,51 @@ async function discoverClientUrlProjections(state, ssrEnv, serverMod) {
|
|
|
10767
11300
|
|
|
10768
11301
|
// src/vite/discovery/discover-routers.ts
|
|
10769
11302
|
var debug11 = createRangoDebugger(NS.discovery);
|
|
11303
|
+
var SERVER_MODULE_ID = "@rangojs/router/server";
|
|
11304
|
+
var MAX_DISCOVERY_PASSES = 3;
|
|
11305
|
+
var RUNNER_RELOADED = /* @__PURE__ */ Symbol("rango.discovery.runnerReloaded");
|
|
11306
|
+
async function runnerReloadedSince(rscEnv, serverMod) {
|
|
11307
|
+
try {
|
|
11308
|
+
return await rscEnv.runner.import(SERVER_MODULE_ID) !== serverMod;
|
|
11309
|
+
} catch {
|
|
11310
|
+
return false;
|
|
11311
|
+
}
|
|
11312
|
+
}
|
|
10770
11313
|
async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
11314
|
+
const entryPath = state.resolvedEntryPath;
|
|
11315
|
+
if (!entryPath) return;
|
|
11316
|
+
for (let pass = 1; ; pass++) {
|
|
11317
|
+
const serverMod = await timed(
|
|
11318
|
+
debug11,
|
|
11319
|
+
"inner: import @rangojs/router/server",
|
|
11320
|
+
() => rscEnv.runner.import(SERVER_MODULE_ID)
|
|
11321
|
+
);
|
|
11322
|
+
let result;
|
|
11323
|
+
try {
|
|
11324
|
+
result = await discoverRoutersPass(
|
|
11325
|
+
state,
|
|
11326
|
+
rscEnv,
|
|
11327
|
+
ssrEnv,
|
|
11328
|
+
entryPath,
|
|
11329
|
+
serverMod
|
|
11330
|
+
);
|
|
11331
|
+
} catch (error) {
|
|
11332
|
+
if (!await runnerReloadedSince(rscEnv, serverMod)) throw error;
|
|
11333
|
+
result = RUNNER_RELOADED;
|
|
11334
|
+
}
|
|
11335
|
+
if (result !== RUNNER_RELOADED) return result;
|
|
11336
|
+
if (pass === MAX_DISCOVERY_PASSES) {
|
|
11337
|
+
throw new Error(
|
|
11338
|
+
`[rango] Route discovery did not settle: the RSC module runner reloaded during ${MAX_DISCOVERY_PASSES} consecutive discovery passes.`
|
|
11339
|
+
);
|
|
11340
|
+
}
|
|
11341
|
+
debug11?.(
|
|
11342
|
+
"inner: module runner reloaded mid-pass, redoing discovery (pass %d)",
|
|
11343
|
+
pass + 1
|
|
11344
|
+
);
|
|
11345
|
+
}
|
|
11346
|
+
}
|
|
11347
|
+
async function discoverRoutersPass(state, rscEnv, ssrEnv, entryPath, serverMod) {
|
|
10777
11348
|
await timed(
|
|
10778
11349
|
debug11,
|
|
10779
11350
|
"inner: refresh recorded client URL projections",
|
|
@@ -10782,9 +11353,10 @@ async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
|
10782
11353
|
await timed(
|
|
10783
11354
|
debug11,
|
|
10784
11355
|
"inner: import entry",
|
|
10785
|
-
() => rscEnv.runner.import(
|
|
11356
|
+
() => rscEnv.runner.import(entryPath)
|
|
10786
11357
|
);
|
|
10787
|
-
|
|
11358
|
+
if (await runnerReloadedSince(rscEnv, serverMod)) return RUNNER_RELOADED;
|
|
11359
|
+
const registry = serverMod.RouterRegistry;
|
|
10788
11360
|
if (!registry || registry.size === 0) {
|
|
10789
11361
|
const discoveryErrors = [];
|
|
10790
11362
|
try {
|
|
@@ -10798,20 +11370,15 @@ async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
|
10798
11370
|
for (const { context, error } of handlerErrors) {
|
|
10799
11371
|
debug11?.("caught error while resolving %s: %O", context, error);
|
|
10800
11372
|
}
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
);
|
|
10804
|
-
const freshRegistry = freshServerMod.RouterRegistry;
|
|
10805
|
-
if (freshRegistry && freshRegistry.size > 0) {
|
|
10806
|
-
Object.assign(serverMod, freshServerMod);
|
|
10807
|
-
registry = freshRegistry;
|
|
11373
|
+
if (await runnerReloadedSince(rscEnv, serverMod)) {
|
|
11374
|
+
return RUNNER_RELOADED;
|
|
10808
11375
|
}
|
|
10809
11376
|
}
|
|
10810
11377
|
} catch (error) {
|
|
10811
11378
|
discoveryErrors.push({ context: "host-router discovery", error });
|
|
10812
11379
|
}
|
|
10813
11380
|
if (!registry || registry.size === 0) {
|
|
10814
|
-
throw new DiscoveryError(
|
|
11381
|
+
throw new DiscoveryError(entryPath, discoveryErrors);
|
|
10815
11382
|
}
|
|
10816
11383
|
}
|
|
10817
11384
|
await timed(
|
|
@@ -10960,6 +11527,7 @@ async function discoverRouters(state, rscEnv, ssrEnv) {
|
|
|
10960
11527
|
}
|
|
10961
11528
|
}
|
|
10962
11529
|
}
|
|
11530
|
+
if (await runnerReloadedSince(rscEnv, serverMod)) return RUNNER_RELOADED;
|
|
10963
11531
|
state.mergedRouteManifest = newMergedRouteManifest;
|
|
10964
11532
|
state.perRouterManifests = newPerRouterManifests;
|
|
10965
11533
|
state.perRouterManifestDataMap = newPerRouterManifestDataMap;
|
|
@@ -10997,7 +11565,7 @@ import { dirname as dirname4, join as join6, resolve as resolve9 } from "node:pa
|
|
|
10997
11565
|
init_debug();
|
|
10998
11566
|
|
|
10999
11567
|
// src/vite/discovery/installed-packages.ts
|
|
11000
|
-
import { createHash as
|
|
11568
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
11001
11569
|
import {
|
|
11002
11570
|
existsSync as existsSync8,
|
|
11003
11571
|
readdirSync as readdirSync3,
|
|
@@ -11014,7 +11582,7 @@ function linkTarget(path6) {
|
|
|
11014
11582
|
}
|
|
11015
11583
|
}
|
|
11016
11584
|
function digestDirectory(dir) {
|
|
11017
|
-
const hash =
|
|
11585
|
+
const hash = createHash7("sha256");
|
|
11018
11586
|
const entered = /* @__PURE__ */ new Set();
|
|
11019
11587
|
const visit = (current, prefix) => {
|
|
11020
11588
|
const real = realpathSync(current);
|
|
@@ -11727,6 +12295,17 @@ function devDiscoveryBootstrap(state) {
|
|
|
11727
12295
|
const epoch = state.devDiscoveryEpoch;
|
|
11728
12296
|
return [`globalThis.__RANGO_DEV_DISCOVERY_EPOCH = ${epoch};`];
|
|
11729
12297
|
}
|
|
12298
|
+
function clientUrlProjectionReplay(state) {
|
|
12299
|
+
const projections = [...state.clientUrlProjectionMap ?? []].sort(
|
|
12300
|
+
([a], [b]) => compareStrings(a, b)
|
|
12301
|
+
);
|
|
12302
|
+
return [
|
|
12303
|
+
`clearClientUrlProjections();`,
|
|
12304
|
+
...projections.map(
|
|
12305
|
+
([referenceId2, projection]) => `setClientUrlProjection(${JSON.stringify(referenceId2)}, ${jsonParseExpression(projection)});`
|
|
12306
|
+
)
|
|
12307
|
+
];
|
|
12308
|
+
}
|
|
11730
12309
|
function generateRoutesManifestModule(state) {
|
|
11731
12310
|
const hasManifest = state.mergedRouteManifest && Object.keys(state.mergedRouteManifest).length > 0;
|
|
11732
12311
|
const hasClientUrlModules = Boolean(state.clientUrlSourceByReferenceId?.size);
|
|
@@ -11773,17 +12352,7 @@ function generateRoutesManifestModule(state) {
|
|
|
11773
12352
|
`clearAllRouterData();`,
|
|
11774
12353
|
TRANSITION_WHEN_VALIDATION
|
|
11775
12354
|
];
|
|
11776
|
-
if (hasClientUrlModules)
|
|
11777
|
-
lines2.push(`clearClientUrlProjections();`);
|
|
11778
|
-
const projections = [...state.clientUrlProjectionMap ?? []].sort(
|
|
11779
|
-
([a], [b]) => compareStrings(a, b)
|
|
11780
|
-
);
|
|
11781
|
-
for (const [referenceId2, projection] of projections) {
|
|
11782
|
-
lines2.push(
|
|
11783
|
-
`setClientUrlProjection(${JSON.stringify(referenceId2)}, ${jsonParseExpression(projection)});`
|
|
11784
|
-
);
|
|
11785
|
-
}
|
|
11786
|
-
}
|
|
12355
|
+
if (hasClientUrlModules) lines2.push(...clientUrlProjectionReplay(state));
|
|
11787
12356
|
if (varIdx > 0) {
|
|
11788
12357
|
lines2.push(
|
|
11789
12358
|
`function __flat(r) { const o = {}; for (const [k, v] of Object.entries(r)) o[k] = typeof v === "string" ? v : v.path; return o; }`
|
|
@@ -11825,12 +12394,10 @@ function generateRoutesManifestModule(state) {
|
|
|
11825
12394
|
return lines2.join("\n");
|
|
11826
12395
|
}
|
|
11827
12396
|
const lines = [
|
|
11828
|
-
`import { ${hasClientUrlModules ? "clearClientUrlProjections, " : ""}enableTransitionWhenValidation } from "@rangojs/router/server";`,
|
|
12397
|
+
`import { ${hasClientUrlModules ? "clearClientUrlProjections, setClientUrlProjection, " : ""}enableTransitionWhenValidation } from "@rangojs/router/server";`,
|
|
11829
12398
|
TRANSITION_WHEN_VALIDATION
|
|
11830
12399
|
];
|
|
11831
|
-
if (hasClientUrlModules)
|
|
11832
|
-
lines.push(`clearClientUrlProjections();`);
|
|
11833
|
-
}
|
|
12400
|
+
if (hasClientUrlModules) lines.push(...clientUrlProjectionReplay(state));
|
|
11834
12401
|
if (!state.isBuildMode) {
|
|
11835
12402
|
const origin = state.devServerOrigin || state.devServer?.resolvedUrls?.local?.[0]?.replace(/\/$/, "") || state.devServer && `http://localhost:${state.devServer.config.server.port || 5173}`;
|
|
11836
12403
|
if (origin) {
|
|
@@ -12169,6 +12736,12 @@ var debugDiscovery = createRangoDebugger(NS.discovery);
|
|
|
12169
12736
|
var debugRoutes = createRangoDebugger(NS.routes);
|
|
12170
12737
|
var debugBuild = createRangoDebugger(NS.build);
|
|
12171
12738
|
var debugDev = createRangoDebugger(NS.dev);
|
|
12739
|
+
function modulesForFile(graph, file) {
|
|
12740
|
+
return graph.getModulesByFile(normalizePath8(file));
|
|
12741
|
+
}
|
|
12742
|
+
function isFileOutsideApp(root, file, rscGraph) {
|
|
12743
|
+
return isInSkippedScanDir(root, file) && !(rscGraph && modulesForFile(rscGraph, file)?.size);
|
|
12744
|
+
}
|
|
12172
12745
|
var loaderHookRegistered = false;
|
|
12173
12746
|
function ensureCloudflareProtocolLoaderRegistered() {
|
|
12174
12747
|
if (loaderHookRegistered) return;
|
|
@@ -12261,6 +12834,10 @@ async function createTempRscServer(state, options = {}) {
|
|
|
12261
12834
|
// Inline transition({ when }) literals become client references here
|
|
12262
12835
|
// too, or discovery would see (and reject) the plain function.
|
|
12263
12836
|
transitionWhenHoistPlugin(),
|
|
12837
|
+
// clientUrls() revalidate() predicates move to the server here too:
|
|
12838
|
+
// discovery serializes the SSR copy's markers and the RSC realm
|
|
12839
|
+
// registers the predicates the materialized stubs call.
|
|
12840
|
+
...clientUrlsRevalidateHoistPlugin(),
|
|
12264
12841
|
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
12265
12842
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
12266
12843
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : void 0),
|
|
@@ -12697,12 +13274,18 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
12697
13274
|
"acquireBuildEnv",
|
|
12698
13275
|
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
12699
13276
|
);
|
|
12700
|
-
|
|
13277
|
+
const temp = await timed(
|
|
12701
13278
|
debugDiscovery,
|
|
12702
13279
|
"getOrCreateTempServer",
|
|
12703
13280
|
() => getOrCreateTempServer()
|
|
12704
|
-
)
|
|
12705
|
-
|
|
13281
|
+
);
|
|
13282
|
+
tempRscEnv = temp.env;
|
|
13283
|
+
if (!tempRscEnv) {
|
|
13284
|
+
recordDiscoveryFailure(
|
|
13285
|
+
s,
|
|
13286
|
+
temp.error ?? "temp runner unavailable for discovery"
|
|
13287
|
+
);
|
|
13288
|
+
} else {
|
|
12706
13289
|
optimizerHashBefore2 = tempRscEnv.depsOptimizer?.metadata?.browserHash;
|
|
12707
13290
|
await timed(
|
|
12708
13291
|
debugDiscovery,
|
|
@@ -12720,6 +13303,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
12720
13303
|
);
|
|
12721
13304
|
}
|
|
12722
13305
|
} catch (err) {
|
|
13306
|
+
recordDiscoveryFailure(s, err);
|
|
12723
13307
|
emitDiscoveryFailure(
|
|
12724
13308
|
err,
|
|
12725
13309
|
optimizerHashBefore2,
|
|
@@ -12761,6 +13345,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
12761
13345
|
() => propagateDiscoveryState(rscEnv)
|
|
12762
13346
|
);
|
|
12763
13347
|
} catch (err) {
|
|
13348
|
+
recordDiscoveryFailure(s, err);
|
|
12764
13349
|
emitDiscoveryFailure(
|
|
12765
13350
|
err,
|
|
12766
13351
|
optimizerHashBefore,
|
|
@@ -13117,6 +13702,11 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13117
13702
|
});
|
|
13118
13703
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
13119
13704
|
const isGeneratedRouteFile = (filePath) => filePath.endsWith(".gen.ts") && (filePath.includes("named-routes.gen.ts") || filePath.includes("urls.gen.ts"));
|
|
13705
|
+
const isOutsideApp = (filePath) => isFileOutsideApp(
|
|
13706
|
+
s.projectRoot,
|
|
13707
|
+
filePath,
|
|
13708
|
+
server.environments?.rsc?.moduleGraph
|
|
13709
|
+
);
|
|
13120
13710
|
const regenerateGeneratedRouteFiles = () => {
|
|
13121
13711
|
if (s.perRouterManifests.length > 0) {
|
|
13122
13712
|
writeRouteTypesFiles(s);
|
|
@@ -13148,15 +13738,24 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13148
13738
|
return true;
|
|
13149
13739
|
};
|
|
13150
13740
|
let routeChangeTimer;
|
|
13741
|
+
const invalidateRoutesManifestModule = (rscEnv) => {
|
|
13742
|
+
for (const virtualId of [
|
|
13743
|
+
VIRTUAL_ROUTES_MANIFEST_ID,
|
|
13744
|
+
`\0${VIRTUAL_ROUTES_MANIFEST_ID}`
|
|
13745
|
+
]) {
|
|
13746
|
+
const virtualMod = rscEnv.moduleGraph?.getModuleById?.(virtualId);
|
|
13747
|
+
if (virtualMod) rscEnv.moduleGraph.invalidateModule(virtualMod);
|
|
13748
|
+
}
|
|
13749
|
+
};
|
|
13151
13750
|
const refreshRuntimeDiscovery = async () => {
|
|
13152
13751
|
const rscEnv = server.environments?.rsc;
|
|
13153
13752
|
const hasMainRunner = !!rscEnv?.runner;
|
|
13154
|
-
if (!hasMainRunner && s.perRouterManifests.length === 0) return;
|
|
13155
13753
|
let previousRouteShape = routeShapeSignature();
|
|
13156
13754
|
await gate.runRefreshCycle(async () => {
|
|
13157
13755
|
const hmrStart = performance.now();
|
|
13158
13756
|
try {
|
|
13159
13757
|
if (hasMainRunner) {
|
|
13758
|
+
const recoveringColdStart = s.perRouterManifests.length === 0;
|
|
13160
13759
|
await timed(
|
|
13161
13760
|
debugDiscovery,
|
|
13162
13761
|
"hmr discoverRouters",
|
|
@@ -13172,6 +13771,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13172
13771
|
"hmr propagateDiscoveryState",
|
|
13173
13772
|
() => propagateDiscoveryState(rscEnv)
|
|
13174
13773
|
);
|
|
13774
|
+
if (recoveringColdStart) invalidateRoutesManifestModule(rscEnv);
|
|
13175
13775
|
} else {
|
|
13176
13776
|
const tempRscEnv = await timed(
|
|
13177
13777
|
debugDiscovery,
|
|
@@ -13220,10 +13820,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13220
13820
|
forceCloudflareWorkerReload(rscEnv, expectedEpoch);
|
|
13221
13821
|
}
|
|
13222
13822
|
} catch (err) {
|
|
13223
|
-
s
|
|
13224
|
-
message: err?.message ?? String(err),
|
|
13225
|
-
at: Date.now()
|
|
13226
|
-
};
|
|
13823
|
+
recordDiscoveryFailure(s, err);
|
|
13227
13824
|
const whenError2 = showTransitionWhenError(err);
|
|
13228
13825
|
if (whenError2) {
|
|
13229
13826
|
console.error(whenError2.message);
|
|
@@ -13317,15 +13914,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13317
13914
|
server.environments?.ssr,
|
|
13318
13915
|
serverMod
|
|
13319
13916
|
);
|
|
13320
|
-
|
|
13321
|
-
VIRTUAL_ROUTES_MANIFEST_ID,
|
|
13322
|
-
`\0${VIRTUAL_ROUTES_MANIFEST_ID}`
|
|
13323
|
-
]) {
|
|
13324
|
-
const virtualMod = rscEnv.moduleGraph?.getModuleById?.(virtualId);
|
|
13325
|
-
if (virtualMod) {
|
|
13326
|
-
rscEnv.moduleGraph.invalidateModule(virtualMod);
|
|
13327
|
-
}
|
|
13328
|
-
}
|
|
13917
|
+
invalidateRoutesManifestModule(rscEnv);
|
|
13329
13918
|
} catch (err) {
|
|
13330
13919
|
debugDiscovery?.(
|
|
13331
13920
|
"watcher: clientUrls projection pre-refresh failed: %s",
|
|
@@ -13351,7 +13940,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13351
13940
|
"watcher: regenerated gen files (%sms)",
|
|
13352
13941
|
(performance.now() - regenStart).toFixed(1)
|
|
13353
13942
|
);
|
|
13354
|
-
if (s
|
|
13943
|
+
if (canRefreshRuntimeDiscovery(s)) {
|
|
13355
13944
|
refreshRuntimeDiscovery().catch((err) => {
|
|
13356
13945
|
console.warn(
|
|
13357
13946
|
`[rango] Runtime re-discovery error: ${err.message}`
|
|
@@ -13362,6 +13951,13 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13362
13951
|
}, 100);
|
|
13363
13952
|
};
|
|
13364
13953
|
const handleRouteFileChange = (filePath) => {
|
|
13954
|
+
if (isOutsideApp(filePath)) {
|
|
13955
|
+
debugDiscovery?.(
|
|
13956
|
+
"watcher: skip %s (outside the discovery scan)",
|
|
13957
|
+
filePath
|
|
13958
|
+
);
|
|
13959
|
+
return;
|
|
13960
|
+
}
|
|
13365
13961
|
if (maybeHandleGeneratedRouteFileMutation(filePath)) return;
|
|
13366
13962
|
if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx") && !filePath.endsWith(".js") && !filePath.endsWith(".jsx")) {
|
|
13367
13963
|
if (s.lastDiscoveryError) {
|
|
@@ -13436,9 +14032,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13436
14032
|
}
|
|
13437
14033
|
const seen = /* @__PURE__ */ new Set();
|
|
13438
14034
|
for (const file of routerSourceFiles) {
|
|
13439
|
-
const mods = rscGraph
|
|
13440
|
-
file.replaceAll("\\", "/")
|
|
13441
|
-
);
|
|
14035
|
+
const mods = modulesForFile(rscGraph, file);
|
|
13442
14036
|
if (!mods) {
|
|
13443
14037
|
debugDiscovery?.(
|
|
13444
14038
|
"watcher: clientUrls invalidation found no rsc modules for %s",
|
|
@@ -13470,7 +14064,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13470
14064
|
}
|
|
13471
14065
|
s.cachedRouterFiles = void 0;
|
|
13472
14066
|
}
|
|
13473
|
-
if (s
|
|
14067
|
+
if (canRefreshRuntimeDiscovery(s)) {
|
|
13474
14068
|
gate.noteRouteEvent();
|
|
13475
14069
|
}
|
|
13476
14070
|
scheduleRouteRegeneration();
|
|
@@ -13488,7 +14082,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
13488
14082
|
server.watcher.on("add", handleRouteFileChange);
|
|
13489
14083
|
server.watcher.on("change", handleRouteFileChange);
|
|
13490
14084
|
server.watcher.on("unlink", (filePath) => {
|
|
13491
|
-
if (!isGeneratedRouteFile(filePath)) return;
|
|
14085
|
+
if (!isGeneratedRouteFile(filePath) || isOutsideApp(filePath)) return;
|
|
13492
14086
|
const hasRunner = !!server.environments?.rsc?.runner;
|
|
13493
14087
|
if (!hasRunner) return;
|
|
13494
14088
|
regenerateGeneratedRouteFiles();
|
|
@@ -14166,7 +14760,7 @@ If this is a multi-app host router, export a createHostRouter() instance and set
|
|
|
14166
14760
|
return;
|
|
14167
14761
|
try {
|
|
14168
14762
|
const source = readFileSync12(file, "utf-8");
|
|
14169
|
-
if (
|
|
14763
|
+
if (hasUseClientDirective(source)) {
|
|
14170
14764
|
return [];
|
|
14171
14765
|
}
|
|
14172
14766
|
} catch {
|
|
@@ -14175,6 +14769,7 @@ If this is a multi-app host router, export a createHostRouter() instance and set
|
|
|
14175
14769
|
});
|
|
14176
14770
|
plugins.push(createLoaderDirectiveGuardPlugin());
|
|
14177
14771
|
plugins.push(transitionWhenHoistPlugin());
|
|
14772
|
+
plugins.push(...clientUrlsRevalidateHoistPlugin());
|
|
14178
14773
|
plugins.push(createLoaderScanStubPlugin());
|
|
14179
14774
|
plugins.push(exposeActionId());
|
|
14180
14775
|
plugins.push(
|