@rangojs/router 0.0.0-experimental.d20dd405 → 0.0.0-experimental.d98a8e9d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/bin/rango.js +147 -57
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +917 -500
- package/package.json +55 -11
- package/skills/api-client/SKILL.md +211 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +220 -30
- package/skills/caching/SKILL.md +116 -8
- package/skills/composability/SKILL.md +27 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/hooks/SKILL.md +196 -21
- package/skills/host-router/SKILL.md +45 -20
- package/skills/intercept/SKILL.md +1 -4
- package/skills/layout/SKILL.md +4 -7
- package/skills/links/SKILL.md +22 -10
- package/skills/loader/SKILL.md +166 -23
- package/skills/middleware/SKILL.md +13 -9
- package/skills/migrate-nextjs/SKILL.md +1 -1
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +3 -6
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +243 -26
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +114 -47
- package/skills/route/SKILL.md +9 -4
- package/skills/router-setup/SKILL.md +3 -3
- package/skills/server-actions/SKILL.md +53 -41
- package/skills/testing/SKILL.md +128 -0
- package/skills/testing/bindings.md +89 -0
- package/skills/testing/cache-prerender.md +98 -0
- package/skills/testing/client-components.md +121 -0
- package/skills/testing/e2e-parity.md +124 -0
- package/skills/testing/flight.md +89 -0
- package/skills/testing/handles.md +127 -0
- package/skills/testing/loader.md +108 -0
- package/skills/testing/middleware.md +97 -0
- package/skills/testing/render-handler.md +102 -0
- package/skills/testing/response-routes.md +94 -0
- package/skills/testing/reverse-and-types.md +83 -0
- package/skills/testing/server-actions.md +89 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +120 -0
- package/skills/typesafety/SKILL.md +310 -26
- package/skills/use-cache/SKILL.md +34 -5
- package/skills/view-transitions/SKILL.md +85 -3
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/event-controller.ts +42 -66
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/navigation-bridge.ts +9 -67
- package/src/browser/navigation-client.ts +68 -83
- package/src/browser/navigation-store.ts +7 -8
- package/src/browser/navigation-transaction.ts +10 -28
- package/src/browser/partial-update.ts +8 -16
- package/src/browser/prefetch/cache.ts +58 -27
- package/src/browser/prefetch/fetch.ts +92 -33
- package/src/browser/react/NavigationProvider.tsx +55 -65
- package/src/browser/react/location-state-shared.ts +175 -4
- package/src/browser/react/location-state.ts +39 -13
- package/src/browser/react/use-handle.ts +17 -9
- package/src/browser/react/use-params.ts +3 -4
- package/src/browser/react/use-reverse.ts +19 -12
- package/src/browser/react/use-router.ts +14 -1
- package/src/browser/response-adapter.ts +32 -1
- package/src/browser/rsc-router.tsx +35 -16
- package/src/browser/scroll-restoration.ts +30 -25
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +23 -30
- package/src/browser/types.ts +2 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +2 -0
- package/src/build/index.ts +8 -1
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +43 -0
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +1 -1
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +55 -14
- package/src/build/route-types/scan-filter.ts +1 -1
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-scope.ts +28 -42
- package/src/cache/cf/cf-cache-store.ts +49 -6
- package/src/client.tsx +9 -30
- package/src/context-var.ts +5 -5
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +30 -4
- package/src/handle.ts +32 -14
- package/src/host/index.ts +2 -2
- package/src/host/router.ts +129 -57
- package/src/host/types.ts +31 -2
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +136 -20
- package/src/index.rsc.ts +7 -6
- package/src/index.ts +14 -8
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +25 -7
- package/src/loader.ts +16 -9
- package/src/missing-id-error.ts +68 -0
- package/src/prerender.ts +27 -6
- package/src/response-utils.ts +9 -0
- package/src/reverse.ts +16 -13
- package/src/route-content-wrapper.tsx +6 -28
- package/src/route-definition/dsl-helpers.ts +238 -263
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +37 -14
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-types.ts +19 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +15 -2
- package/src/router/error-handling.ts +1 -1
- package/src/router/find-match.ts +54 -6
- package/src/router/intercept-resolution.ts +4 -18
- package/src/router/lazy-includes.ts +35 -16
- package/src/router/loader-resolution.ts +79 -36
- package/src/router/manifest.ts +19 -6
- package/src/router/match-handlers.ts +62 -20
- package/src/router/match-middleware/cache-lookup.ts +44 -91
- package/src/router/match-middleware/cache-store.ts +3 -2
- package/src/router/match-result.ts +32 -30
- package/src/router/metrics.ts +1 -1
- package/src/router/middleware-types.ts +1 -1
- package/src/router/middleware.ts +46 -78
- package/src/router/pattern-matching.ts +15 -2
- package/src/router/prerender-match.ts +1 -1
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +4 -28
- package/src/router/revalidation.ts +43 -1
- package/src/router/router-interfaces.ts +45 -28
- package/src/router/router-options.ts +40 -1
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +19 -6
- package/src/router/segment-resolution/revalidation.ts +19 -6
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/telemetry.ts +99 -0
- package/src/router/trie-matching.ts +22 -3
- package/src/router/types.ts +8 -0
- package/src/router.ts +51 -28
- package/src/rsc/handler-context.ts +2 -2
- package/src/rsc/handler.ts +20 -65
- package/src/rsc/helpers.ts +22 -2
- package/src/rsc/index.ts +1 -1
- package/src/rsc/manifest-init.ts +28 -41
- package/src/rsc/origin-guard.ts +28 -10
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +43 -60
- package/src/rsc/rsc-rendering.ts +27 -53
- package/src/rsc/runtime-warnings.ts +9 -10
- package/src/rsc/server-action.ts +13 -37
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/types.ts +2 -2
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +4 -4
- package/src/segment-system.tsx +64 -49
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +150 -51
- package/src/server/cookie-store.ts +28 -4
- package/src/server/request-context.ts +57 -9
- package/src/static-handler.ts +25 -3
- package/src/testing/cache-status.ts +166 -0
- package/src/testing/collect-handle.ts +63 -0
- package/src/testing/dispatch.ts +581 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +149 -0
- package/src/testing/e2e/matchers.ts +51 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +326 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +110 -0
- package/src/testing/flight-normalize.ts +38 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +51 -0
- package/src/testing/flight.ts +234 -0
- package/src/testing/generated-routes.ts +223 -0
- package/src/testing/index.ts +106 -0
- package/src/testing/internal/context.ts +304 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +42 -0
- package/src/testing/render-handler.ts +323 -0
- package/src/testing/render-route.tsx +590 -0
- package/src/testing/run-loader.ts +363 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +285 -0
- package/src/types/global-namespace.ts +39 -26
- package/src/types/handler-context.ts +56 -11
- package/src/types/index.ts +1 -0
- package/src/types/loader-types.ts +6 -3
- package/src/types/segments.ts +18 -1
- package/src/urls/include-helper.ts +10 -53
- package/src/urls/index.ts +1 -5
- package/src/urls/path-helper-types.ts +11 -3
- package/src/urls/path-helper.ts +17 -52
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +20 -19
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -5
- package/src/use-loader.tsx +413 -42
- package/src/vite/debug.ts +1 -0
- package/src/vite/discovery/bundle-postprocess.ts +6 -6
- package/src/vite/discovery/discover-routers.ts +75 -72
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/prerender-collection.ts +19 -25
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/state.ts +33 -0
- package/src/vite/discovery/virtual-module-codegen.ts +13 -23
- package/src/vite/index.ts +2 -0
- package/src/vite/plugin-types.ts +67 -0
- package/src/vite/plugins/cjs-to-esm.ts +3 -7
- package/src/vite/plugins/client-ref-hashing.ts +12 -1
- package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -1
- package/src/vite/plugins/expose-action-id.ts +2 -2
- package/src/vite/plugins/expose-id-utils.ts +12 -8
- package/src/vite/plugins/expose-ids/export-analysis.ts +100 -20
- package/src/vite/plugins/expose-ids/handler-transform.ts +8 -61
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -5
- package/src/vite/plugins/expose-internal-ids.ts +47 -67
- package/src/vite/plugins/performance-tracks.ts +12 -16
- package/src/vite/plugins/use-cache-transform.ts +13 -11
- package/src/vite/plugins/version-injector.ts +2 -12
- package/src/vite/plugins/version-plugin.ts +59 -2
- package/src/vite/plugins/virtual-entries.ts +2 -2
- package/src/vite/rango.ts +67 -15
- package/src/vite/router-discovery.ts +208 -63
- package/src/vite/utils/ast-handler-extract.ts +15 -15
- package/src/vite/utils/bundle-analysis.ts +4 -2
- package/src/vite/utils/client-chunks.ts +190 -0
- package/src/vite/utils/forward-user-plugins.ts +193 -0
- package/src/vite/utils/manifest-utils.ts +8 -59
- package/src/vite/utils/shared-utils.ts +107 -26
- package/src/browser/action-response-classifier.ts +0 -99
package/dist/vite/index.js
CHANGED
|
@@ -21,8 +21,8 @@ function hashId(filePath, exportName) {
|
|
|
21
21
|
function makeStubId(filePath, exportName, isBuild) {
|
|
22
22
|
return isBuild ? hashId(filePath, exportName) : `${filePath}#${exportName}`;
|
|
23
23
|
}
|
|
24
|
-
function hashInlineId(filePath,
|
|
25
|
-
const input =
|
|
24
|
+
function hashInlineId(filePath, fnName, index) {
|
|
25
|
+
const input = `${filePath}:${fnName}:${index}`;
|
|
26
26
|
return crypto.createHash("sha256").update(input).digest("hex").slice(0, 8);
|
|
27
27
|
}
|
|
28
28
|
function buildExportMap(program) {
|
|
@@ -200,7 +200,8 @@ var NS = {
|
|
|
200
200
|
prerender: "rango:prerender",
|
|
201
201
|
build: "rango:build",
|
|
202
202
|
dev: "rango:dev",
|
|
203
|
-
transform: "rango:transform"
|
|
203
|
+
transform: "rango:transform",
|
|
204
|
+
chunks: "rango:chunks"
|
|
204
205
|
};
|
|
205
206
|
if (process.env.INTERNAL_RANGO_DEBUG) {
|
|
206
207
|
const existing = debugFactory.disable();
|
|
@@ -292,7 +293,7 @@ function getRscPluginApi(config) {
|
|
|
292
293
|
);
|
|
293
294
|
if (plugin) {
|
|
294
295
|
console.warn(
|
|
295
|
-
`[
|
|
296
|
+
`[rango:expose-action-id] RSC plugin found by API structure (name: "${plugin.name}"). Consider updating the name lookup if the plugin was renamed.`
|
|
296
297
|
);
|
|
297
298
|
}
|
|
298
299
|
}
|
|
@@ -393,7 +394,7 @@ function exposeActionId() {
|
|
|
393
394
|
}
|
|
394
395
|
if (!rscPluginApi) {
|
|
395
396
|
throw new Error(
|
|
396
|
-
"[
|
|
397
|
+
"[rango] Could not find @vitejs/plugin-rsc. @rangojs/router requires the Vite RSC plugin, which is included automatically by rango()."
|
|
397
398
|
);
|
|
398
399
|
}
|
|
399
400
|
if (!isBuild) return;
|
|
@@ -465,7 +466,7 @@ function exposeActionId() {
|
|
|
465
466
|
|
|
466
467
|
// src/vite/plugins/expose-internal-ids.ts
|
|
467
468
|
import { parseAst as parseAst2 } from "vite";
|
|
468
|
-
import
|
|
469
|
+
import MagicString3 from "magic-string";
|
|
469
470
|
import path4 from "node:path";
|
|
470
471
|
|
|
471
472
|
// src/vite/utils/ast-handler-extract.ts
|
|
@@ -475,7 +476,7 @@ function isDirectivePrologueStatement(node) {
|
|
|
475
476
|
function findImportInsertionPos(code, parseAst4) {
|
|
476
477
|
let program;
|
|
477
478
|
try {
|
|
478
|
-
program = parseAst4(code, {
|
|
479
|
+
program = parseAst4(code, { lang: "tsx" });
|
|
479
480
|
} catch {
|
|
480
481
|
return 0;
|
|
481
482
|
}
|
|
@@ -515,7 +516,7 @@ function walkNode(node, parent, ancestors, enter) {
|
|
|
515
516
|
function findHandlerCalls(code, fnName, parseAst4) {
|
|
516
517
|
let program;
|
|
517
518
|
try {
|
|
518
|
-
program = parseAst4(code, {
|
|
519
|
+
program = parseAst4(code, { lang: "tsx" });
|
|
519
520
|
} catch {
|
|
520
521
|
return [];
|
|
521
522
|
}
|
|
@@ -589,7 +590,7 @@ function getImportedLocalNamesFromProgram(program, importedName) {
|
|
|
589
590
|
}
|
|
590
591
|
function getImportedLocalNames(code, importedName, parseAst4) {
|
|
591
592
|
try {
|
|
592
|
-
const program = parseAst4(code, {
|
|
593
|
+
const program = parseAst4(code, { lang: "tsx" });
|
|
593
594
|
return getImportedLocalNamesFromProgram(program, importedName);
|
|
594
595
|
} catch {
|
|
595
596
|
return /* @__PURE__ */ new Set();
|
|
@@ -598,7 +599,7 @@ function getImportedLocalNames(code, importedName, parseAst4) {
|
|
|
598
599
|
function extractImportDeclarations(code, parseAst4) {
|
|
599
600
|
let program;
|
|
600
601
|
try {
|
|
601
|
-
program = parseAst4(code, {
|
|
602
|
+
program = parseAst4(code, { lang: "tsx" });
|
|
602
603
|
} catch {
|
|
603
604
|
return [];
|
|
604
605
|
}
|
|
@@ -653,7 +654,7 @@ function isSafeVariableDeclaration(node, handlerNames) {
|
|
|
653
654
|
function extractModuleLevelDeclarations(code, parseAst4, handlerNames) {
|
|
654
655
|
let program;
|
|
655
656
|
try {
|
|
656
|
-
program = parseAst4(code, {
|
|
657
|
+
program = parseAst4(code, { lang: "tsx" });
|
|
657
658
|
} catch {
|
|
658
659
|
return [];
|
|
659
660
|
}
|
|
@@ -697,14 +698,12 @@ function transformInlineHandlers(fnName, virtualPrefix, s, code, filePath, virtu
|
|
|
697
698
|
parseAst4,
|
|
698
699
|
handlerNames
|
|
699
700
|
);
|
|
700
|
-
const lineCounts = /* @__PURE__ */ new Map();
|
|
701
701
|
const importStatements = [];
|
|
702
|
-
for (const site of inlineSites) {
|
|
703
|
-
const
|
|
704
|
-
lineCounts.set(site.lineNumber, lineCount + 1);
|
|
705
|
-
const hash = hashInlineId(filePath, site.lineNumber, lineCount);
|
|
702
|
+
for (const [siteIndex, site] of inlineSites.entries()) {
|
|
703
|
+
const hash = hashInlineId(filePath, fnName, siteIndex);
|
|
706
704
|
const exportName = `__sh_${hash}`;
|
|
707
|
-
const
|
|
705
|
+
const idSuffix = `${filePath}:${fnName}:${siteIndex}`;
|
|
706
|
+
const virtualId = `\0${virtualPrefix}${idSuffix}`;
|
|
708
707
|
const handlerCode = code.slice(site.callStart, site.callEnd);
|
|
709
708
|
virtualRegistry.set(virtualId, {
|
|
710
709
|
originalModuleId: moduleId,
|
|
@@ -714,7 +713,7 @@ function transformInlineHandlers(fnName, virtualPrefix, s, code, filePath, virtu
|
|
|
714
713
|
exportName
|
|
715
714
|
});
|
|
716
715
|
s.overwrite(site.callStart, site.callEnd, exportName);
|
|
717
|
-
const importId = `${virtualPrefix}${
|
|
716
|
+
const importId = `${virtualPrefix}${idSuffix}`;
|
|
718
717
|
importStatements.push(`import { ${exportName} } from "${importId}";`);
|
|
719
718
|
}
|
|
720
719
|
if (importStatements.length > 0) {
|
|
@@ -746,6 +745,83 @@ var STRICT_CREATE_CONFIGS = [
|
|
|
746
745
|
|
|
747
746
|
// src/vite/plugins/expose-ids/export-analysis.ts
|
|
748
747
|
import { parseAst } from "vite";
|
|
748
|
+
|
|
749
|
+
// src/build/route-types/source-scan.ts
|
|
750
|
+
function isLineTerminator(ch) {
|
|
751
|
+
const c = ch.charCodeAt(0);
|
|
752
|
+
return c === 10 || c === 13 || c === 8232 || c === 8233;
|
|
753
|
+
}
|
|
754
|
+
function makeCodeClassifier(code) {
|
|
755
|
+
const n = code.length;
|
|
756
|
+
let i = 0;
|
|
757
|
+
let skipStart = -1;
|
|
758
|
+
let skipEnd = -1;
|
|
759
|
+
return (q) => {
|
|
760
|
+
if (q >= skipStart && q < skipEnd) return false;
|
|
761
|
+
while (i < n && i <= q) {
|
|
762
|
+
const c = code[i];
|
|
763
|
+
const d = i + 1 < n ? code[i + 1] : "";
|
|
764
|
+
let end = -1;
|
|
765
|
+
if (c === "/" && d === "/") {
|
|
766
|
+
let j = i + 2;
|
|
767
|
+
while (j < n && !isLineTerminator(code[j])) j++;
|
|
768
|
+
end = j;
|
|
769
|
+
} else if (c === "/" && d === "*") {
|
|
770
|
+
let j = i + 2;
|
|
771
|
+
while (j < n && !(code[j] === "*" && code[j + 1] === "/")) j++;
|
|
772
|
+
end = Math.min(n, j + 2);
|
|
773
|
+
} else if (c === '"' || c === "'" || c === "`") {
|
|
774
|
+
let j = i + 1;
|
|
775
|
+
while (j < n) {
|
|
776
|
+
if (code[j] === "\\") {
|
|
777
|
+
j += 2;
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
if (code[j] === c) {
|
|
781
|
+
j++;
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
j++;
|
|
785
|
+
}
|
|
786
|
+
end = j;
|
|
787
|
+
}
|
|
788
|
+
if (end >= 0) {
|
|
789
|
+
if (q < end) {
|
|
790
|
+
skipStart = i;
|
|
791
|
+
skipEnd = end;
|
|
792
|
+
return false;
|
|
793
|
+
}
|
|
794
|
+
i = end;
|
|
795
|
+
} else {
|
|
796
|
+
i++;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return true;
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
function firstCodeMatchIndex(code, pattern) {
|
|
803
|
+
const inCode = makeCodeClassifier(code);
|
|
804
|
+
pattern.lastIndex = 0;
|
|
805
|
+
let m;
|
|
806
|
+
while ((m = pattern.exec(code)) !== null) {
|
|
807
|
+
if (inCode(m.index)) return m.index;
|
|
808
|
+
if (pattern.lastIndex <= m.index) pattern.lastIndex = m.index + 1;
|
|
809
|
+
}
|
|
810
|
+
return -1;
|
|
811
|
+
}
|
|
812
|
+
function codeMatchIndices(code, pattern) {
|
|
813
|
+
const inCode = makeCodeClassifier(code);
|
|
814
|
+
const indices = [];
|
|
815
|
+
pattern.lastIndex = 0;
|
|
816
|
+
let m;
|
|
817
|
+
while ((m = pattern.exec(code)) !== null) {
|
|
818
|
+
if (inCode(m.index)) indices.push(m.index);
|
|
819
|
+
if (pattern.lastIndex <= m.index) pattern.lastIndex = m.index + 1;
|
|
820
|
+
}
|
|
821
|
+
return indices;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// src/vite/plugins/expose-ids/export-analysis.ts
|
|
749
825
|
function isExportOnlyFile(code, bindings) {
|
|
750
826
|
if (bindings.length === 0) return false;
|
|
751
827
|
const knownLocals = /* @__PURE__ */ new Set();
|
|
@@ -774,12 +850,30 @@ function isExportOnlyFile(code, bindings) {
|
|
|
774
850
|
}
|
|
775
851
|
return true;
|
|
776
852
|
}
|
|
777
|
-
function
|
|
778
|
-
|
|
853
|
+
function createCallPattern(fnNames) {
|
|
854
|
+
return new RegExp(
|
|
779
855
|
`\\b(?:${fnNames.map(escapeRegExp).join("|")})\\s*(?:<[^>]*>\\s*)?\\(`,
|
|
780
856
|
"g"
|
|
781
857
|
);
|
|
782
|
-
|
|
858
|
+
}
|
|
859
|
+
function countCreateCallsForNames(code, fnNames) {
|
|
860
|
+
return codeMatchIndices(code, createCallPattern(fnNames)).length;
|
|
861
|
+
}
|
|
862
|
+
function offsetToLineColumn(code, index) {
|
|
863
|
+
let line = 1;
|
|
864
|
+
let lineStart = 0;
|
|
865
|
+
const end = Math.min(index, code.length);
|
|
866
|
+
for (let i = 0; i < end; i++) {
|
|
867
|
+
if (code[i] === "\n") {
|
|
868
|
+
line++;
|
|
869
|
+
lineStart = i + 1;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
return { line, column: index - lineStart + 1 };
|
|
873
|
+
}
|
|
874
|
+
function findUnsupportedCreateCallSites(code, fnNames, supportedBindings) {
|
|
875
|
+
const supported = new Set(supportedBindings.map((b) => b.callExprStart));
|
|
876
|
+
return codeMatchIndices(code, createCallPattern(fnNames)).filter((index) => !supported.has(index)).map((index) => offsetToLineColumn(code, index));
|
|
783
877
|
}
|
|
784
878
|
function getImportedFnNames(code, importedName) {
|
|
785
879
|
const importPattern = /import\s*\{([^}]*)\}\s*from\s*["']@rangojs\/router(?:\/[^"']*)?["']/g;
|
|
@@ -810,6 +904,17 @@ function getCalledIdentifierFromCall(callExpr) {
|
|
|
810
904
|
}
|
|
811
905
|
return null;
|
|
812
906
|
}
|
|
907
|
+
function unwrapSignatureWrappedCall(init, fnNameSet) {
|
|
908
|
+
if (init?.type !== "CallExpression") return init;
|
|
909
|
+
const directId = getCalledIdentifierFromCall(init);
|
|
910
|
+
if (directId && fnNameSet.has(directId)) return init;
|
|
911
|
+
const firstArg = init.arguments?.[0];
|
|
912
|
+
if (firstArg?.type === "CallExpression") {
|
|
913
|
+
const innerId = getCalledIdentifierFromCall(firstArg);
|
|
914
|
+
if (innerId && fnNameSet.has(innerId)) return firstArg;
|
|
915
|
+
}
|
|
916
|
+
return init;
|
|
917
|
+
}
|
|
813
918
|
function collectCreateExportBindingsFallback(code, fnNames) {
|
|
814
919
|
const alternation = fnNames.map(escapeRegExp).join("|");
|
|
815
920
|
const exportConstPattern = new RegExp(
|
|
@@ -869,7 +974,7 @@ function collectCreateExportBindingsFallback(code, fnNames) {
|
|
|
869
974
|
function collectCreateExportBindings(code, fnNames, program) {
|
|
870
975
|
if (!program) {
|
|
871
976
|
try {
|
|
872
|
-
program = parseAst(code, {
|
|
977
|
+
program = parseAst(code, { lang: "tsx" });
|
|
873
978
|
} catch {
|
|
874
979
|
return collectCreateExportBindingsFallback(code, fnNames);
|
|
875
980
|
}
|
|
@@ -882,16 +987,16 @@ function collectCreateExportBindings(code, fnNames, program) {
|
|
|
882
987
|
return;
|
|
883
988
|
}
|
|
884
989
|
for (const decl of varDecl.declarations ?? []) {
|
|
885
|
-
const
|
|
886
|
-
|
|
990
|
+
const callExpr = unwrapSignatureWrappedCall(decl?.init, fnNameSet);
|
|
991
|
+
const calledIdentifier = getCalledIdentifierFromCall(callExpr);
|
|
992
|
+
if (decl?.id?.type !== "Identifier" || callExpr?.type !== "CallExpression" || !calledIdentifier || !fnNameSet.has(calledIdentifier)) {
|
|
887
993
|
continue;
|
|
888
994
|
}
|
|
889
995
|
const localName = decl.id.name;
|
|
890
996
|
const exportNames = exportMap.get(localName) ?? [];
|
|
891
997
|
if (exportNames.length === 0) continue;
|
|
892
|
-
const
|
|
893
|
-
const
|
|
894
|
-
const calleeEnd = decl.init.callee.end;
|
|
998
|
+
const callEnd = callExpr.end;
|
|
999
|
+
const calleeEnd = callExpr.callee.end;
|
|
895
1000
|
let openParenPos = -1;
|
|
896
1001
|
for (let i = calleeEnd; i < callEnd; i++) {
|
|
897
1002
|
if (code[i] === "(") {
|
|
@@ -905,10 +1010,10 @@ function collectCreateExportBindings(code, fnNames, program) {
|
|
|
905
1010
|
bindings.push({
|
|
906
1011
|
localName,
|
|
907
1012
|
exportNames,
|
|
908
|
-
callExprStart:
|
|
1013
|
+
callExprStart: callExpr.start,
|
|
909
1014
|
callOpenParenPos: openParenPos,
|
|
910
1015
|
callCloseParenPos: closeParenPos,
|
|
911
|
-
argCount:
|
|
1016
|
+
argCount: callExpr.arguments?.length ?? 0,
|
|
912
1017
|
statementEnd
|
|
913
1018
|
});
|
|
914
1019
|
}
|
|
@@ -927,9 +1032,20 @@ function collectCreateExportBindings(code, fnNames, program) {
|
|
|
927
1032
|
}
|
|
928
1033
|
return bindings;
|
|
929
1034
|
}
|
|
930
|
-
function buildUnsupportedShapeWarning(filePath, fnName) {
|
|
931
|
-
|
|
932
|
-
|
|
1035
|
+
function buildUnsupportedShapeWarning(filePath, fnName, sites = []) {
|
|
1036
|
+
const lines = [`[rango] Unsupported ${fnName} shape in "${filePath}".`];
|
|
1037
|
+
if (sites.length === 1) {
|
|
1038
|
+
const s = sites[0];
|
|
1039
|
+
lines.push(
|
|
1040
|
+
`The ${fnName}(...) call at ${filePath}:${s.line}:${s.column} has no stable $$id injected \u2014 it is not in a supported shape.`
|
|
1041
|
+
);
|
|
1042
|
+
} else if (sites.length > 1) {
|
|
1043
|
+
lines.push(
|
|
1044
|
+
`These ${fnName}(...) calls have no stable $$id injected \u2014 they are not in a supported shape:`
|
|
1045
|
+
);
|
|
1046
|
+
for (const s of sites) lines.push(` - ${filePath}:${s.line}:${s.column}`);
|
|
1047
|
+
}
|
|
1048
|
+
lines.push(
|
|
933
1049
|
`Supported shapes are:`,
|
|
934
1050
|
` - export const X = ${fnName}(...)`,
|
|
935
1051
|
` - const X = ${fnName}(...); export { X }`,
|
|
@@ -937,7 +1053,8 @@ function buildUnsupportedShapeWarning(filePath, fnName) {
|
|
|
937
1053
|
`Potentially unsupported forms include:`,
|
|
938
1054
|
` - export let/var X = ${fnName}(...)`,
|
|
939
1055
|
` - inline ${fnName}(...) calls`
|
|
940
|
-
|
|
1056
|
+
);
|
|
1057
|
+
return lines.join("\n");
|
|
941
1058
|
}
|
|
942
1059
|
|
|
943
1060
|
// src/vite/plugins/expose-ids/loader-transform.ts
|
|
@@ -951,7 +1068,7 @@ function generateClientLoaderStubs(bindings, code, filePath, isBuild) {
|
|
|
951
1068
|
const lines = [];
|
|
952
1069
|
for (const binding of bindings) {
|
|
953
1070
|
for (const name of binding.exportNames) {
|
|
954
|
-
const loaderId =
|
|
1071
|
+
const loaderId = makeStubId(filePath, name, isBuild);
|
|
955
1072
|
lines.push(
|
|
956
1073
|
`export const ${name} = { __brand: "loader", $$id: "${loaderId}" };`
|
|
957
1074
|
);
|
|
@@ -963,7 +1080,7 @@ function transformLoaders(bindings, s, filePath, isBuild) {
|
|
|
963
1080
|
let hasChanges = false;
|
|
964
1081
|
for (const binding of bindings) {
|
|
965
1082
|
const exportName = binding.exportNames[0];
|
|
966
|
-
const loaderId =
|
|
1083
|
+
const loaderId = makeStubId(filePath, exportName, isBuild);
|
|
967
1084
|
const paramInjection = binding.argCount === 1 ? `, undefined, "${loaderId}"` : `, "${loaderId}"`;
|
|
968
1085
|
s.appendLeft(binding.callCloseParenPos, paramInjection);
|
|
969
1086
|
const propInjection = `
|
|
@@ -975,7 +1092,6 @@ ${binding.localName}.$$id = "${loaderId}";`;
|
|
|
975
1092
|
}
|
|
976
1093
|
|
|
977
1094
|
// src/vite/plugins/expose-ids/handler-transform.ts
|
|
978
|
-
import MagicString2 from "magic-string";
|
|
979
1095
|
function analyzeCreateHandleArgs(code, startPos, endPos) {
|
|
980
1096
|
const content = code.slice(startPos, endPos).trim();
|
|
981
1097
|
return { hasArgs: content.length > 0 };
|
|
@@ -989,7 +1105,7 @@ function transformHandles(bindings, s, code, filePath, isBuild) {
|
|
|
989
1105
|
binding.callOpenParenPos + 1,
|
|
990
1106
|
binding.callCloseParenPos
|
|
991
1107
|
);
|
|
992
|
-
const handleId =
|
|
1108
|
+
const handleId = makeStubId(filePath, exportName, isBuild);
|
|
993
1109
|
let paramInjection;
|
|
994
1110
|
if (!args.hasArgs) {
|
|
995
1111
|
paramInjection = `undefined, "${handleId}"`;
|
|
@@ -1008,7 +1124,7 @@ function transformLocationState(bindings, s, filePath, isBuild) {
|
|
|
1008
1124
|
let hasChanges = false;
|
|
1009
1125
|
for (const binding of bindings) {
|
|
1010
1126
|
const exportName = binding.exportNames[0];
|
|
1011
|
-
const stateKey =
|
|
1127
|
+
const stateKey = makeStubId(filePath, exportName, isBuild);
|
|
1012
1128
|
const propInjection = `
|
|
1013
1129
|
${binding.localName}.__rsc_ls_key = "__rsc_ls_${stateKey}";`;
|
|
1014
1130
|
s.appendRight(binding.statementEnd, propInjection);
|
|
@@ -1020,7 +1136,7 @@ function generateWholeFileStubs(cfg, bindings, code, filePath, isBuild) {
|
|
|
1020
1136
|
if (!isExportOnlyFile(code, bindings)) return null;
|
|
1021
1137
|
const exportNames = bindings.flatMap((b) => b.exportNames);
|
|
1022
1138
|
const stubs = exportNames.map((name) => {
|
|
1023
|
-
const handlerId =
|
|
1139
|
+
const handlerId = makeStubId(filePath, name, isBuild);
|
|
1024
1140
|
return `export const ${name} = { __brand: "${cfg.brand}", $$id: "${handlerId}" };`;
|
|
1025
1141
|
});
|
|
1026
1142
|
return { code: stubs.join("\n") + "\n", map: null };
|
|
@@ -1029,7 +1145,7 @@ function stubHandlerExprs(cfg, bindings, s, filePath, isBuild) {
|
|
|
1029
1145
|
let hasChanges = false;
|
|
1030
1146
|
for (const binding of bindings) {
|
|
1031
1147
|
const exportName = binding.exportNames[0];
|
|
1032
|
-
const handlerId =
|
|
1148
|
+
const handlerId = makeStubId(filePath, exportName, isBuild);
|
|
1033
1149
|
s.overwrite(
|
|
1034
1150
|
binding.callExprStart,
|
|
1035
1151
|
binding.callCloseParenPos + 1,
|
|
@@ -1043,7 +1159,7 @@ function transformHandlerIds(cfg, bindings, s, filePath, isBuild) {
|
|
|
1043
1159
|
let hasChanges = false;
|
|
1044
1160
|
for (const binding of bindings) {
|
|
1045
1161
|
const exportName = binding.exportNames[0];
|
|
1046
|
-
const handlerId =
|
|
1162
|
+
const handlerId = makeStubId(filePath, exportName, isBuild);
|
|
1047
1163
|
let paramInjection;
|
|
1048
1164
|
if (binding.argCount === 0) {
|
|
1049
1165
|
paramInjection = `undefined, "${handlerId}"`;
|
|
@@ -1062,7 +1178,7 @@ ${binding.localName}.$$id = "${handlerId}";`;
|
|
|
1062
1178
|
}
|
|
1063
1179
|
|
|
1064
1180
|
// src/vite/plugins/expose-ids/router-transform.ts
|
|
1065
|
-
import
|
|
1181
|
+
import MagicString2 from "magic-string";
|
|
1066
1182
|
import path3 from "node:path";
|
|
1067
1183
|
import { createHash } from "node:crypto";
|
|
1068
1184
|
var debug2 = createRangoDebugger(NS.transform);
|
|
@@ -1072,10 +1188,10 @@ function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
|
1072
1188
|
"g"
|
|
1073
1189
|
);
|
|
1074
1190
|
let match;
|
|
1075
|
-
const s = new
|
|
1191
|
+
const s = new MagicString2(code);
|
|
1076
1192
|
let changed = false;
|
|
1077
|
-
const
|
|
1078
|
-
const routeNamesImport = `./${
|
|
1193
|
+
const basename2 = path3.basename(filePath).replace(/\.(tsx?|jsx?)$/, "");
|
|
1194
|
+
const routeNamesImport = `./${basename2}.named-routes.gen.js`;
|
|
1079
1195
|
const routeNamesVar = `__rsc_rn`;
|
|
1080
1196
|
while ((match = pat.exec(code)) !== null) {
|
|
1081
1197
|
const callStart = match.index;
|
|
@@ -1335,7 +1451,7 @@ ${lazyImports.join(",\n")}
|
|
|
1335
1451
|
}
|
|
1336
1452
|
if (_cachedAst !== void 0 || _astParseFailed) return _cachedAst;
|
|
1337
1453
|
try {
|
|
1338
|
-
_cachedAst = parseAst2(code, {
|
|
1454
|
+
_cachedAst = parseAst2(code, { lang: "tsx" });
|
|
1339
1455
|
} catch {
|
|
1340
1456
|
_astParseFailed = true;
|
|
1341
1457
|
}
|
|
@@ -1358,13 +1474,16 @@ ${lazyImports.join(",\n")}
|
|
|
1358
1474
|
const hasCode = cfg.fnName === "createLoader" ? hasLoaderCode : cfg.fnName === "createHandle" ? hasHandleCode : hasLocationStateCode;
|
|
1359
1475
|
if (!hasCode) continue;
|
|
1360
1476
|
const fnNames = getFnNames(cfg.fnName);
|
|
1361
|
-
const
|
|
1362
|
-
|
|
1363
|
-
|
|
1477
|
+
const sites = findUnsupportedCreateCallSites(
|
|
1478
|
+
code,
|
|
1479
|
+
fnNames,
|
|
1480
|
+
getBindings(code, fnNames)
|
|
1481
|
+
);
|
|
1482
|
+
if (sites.length === 0) continue;
|
|
1364
1483
|
const warnKey = `${id}::${cfg.fnName}`;
|
|
1365
1484
|
if (unsupportedShapeWarnings.has(warnKey)) continue;
|
|
1366
1485
|
unsupportedShapeWarnings.add(warnKey);
|
|
1367
|
-
this.warn(buildUnsupportedShapeWarning(filePath, cfg.fnName));
|
|
1486
|
+
this.warn(buildUnsupportedShapeWarning(filePath, cfg.fnName, sites));
|
|
1368
1487
|
}
|
|
1369
1488
|
if (hasLoaderCode && isRscEnv) {
|
|
1370
1489
|
const fnNames = getFnNames("createLoader");
|
|
@@ -1401,15 +1520,6 @@ ${lazyImports.join(",\n")}
|
|
|
1401
1520
|
);
|
|
1402
1521
|
if (wholeFile) return wholeFile;
|
|
1403
1522
|
}
|
|
1404
|
-
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1405
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1406
|
-
const exportNames = getBindings(code, fnNames).map(
|
|
1407
|
-
(b) => b.exportNames[0]
|
|
1408
|
-
);
|
|
1409
|
-
if (exportNames.length > 0) {
|
|
1410
|
-
prerenderHandlerModules.set(id, exportNames);
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
1523
|
let changed = false;
|
|
1414
1524
|
const handlerConfigs = [
|
|
1415
1525
|
hasStaticHandlerCode && STATIC_CONFIG,
|
|
@@ -1422,7 +1532,7 @@ ${lazyImports.join(",\n")}
|
|
|
1422
1532
|
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1423
1533
|
const supportedBindings = getBindings(code, fnNames).length;
|
|
1424
1534
|
if (totalCalls > supportedBindings) {
|
|
1425
|
-
const iterS = new
|
|
1535
|
+
const iterS = new MagicString3(code);
|
|
1426
1536
|
const result = transformInlineHandlers(
|
|
1427
1537
|
cfg.fnName,
|
|
1428
1538
|
VIRTUAL_HANDLER_PREFIX,
|
|
@@ -1587,16 +1697,24 @@ ${lazyImports.join(",\n")}
|
|
|
1587
1697
|
return { code: lines.join("\n") + "\n", map: null };
|
|
1588
1698
|
}
|
|
1589
1699
|
}
|
|
1590
|
-
if (
|
|
1591
|
-
const
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1700
|
+
if (isRscEnv && isBuild) {
|
|
1701
|
+
const trackTypes = [
|
|
1702
|
+
[
|
|
1703
|
+
hasPrerenderHandlerCode,
|
|
1704
|
+
PRERENDER_CONFIG,
|
|
1705
|
+
prerenderHandlerModules
|
|
1706
|
+
],
|
|
1707
|
+
[hasStaticHandlerCode, STATIC_CONFIG, staticHandlerModules]
|
|
1708
|
+
];
|
|
1709
|
+
for (const [has2, cfg, trackMap] of trackTypes) {
|
|
1710
|
+
if (!has2) continue;
|
|
1711
|
+
const exportNames = getBindings(code, getFnNames(cfg.fnName)).map(
|
|
1712
|
+
(b) => b.exportNames[0]
|
|
1713
|
+
);
|
|
1714
|
+
if (exportNames.length > 0) trackMap.set(id, exportNames);
|
|
1597
1715
|
}
|
|
1598
1716
|
}
|
|
1599
|
-
const s = new
|
|
1717
|
+
const s = new MagicString3(code);
|
|
1600
1718
|
if (hasLoaderCode) {
|
|
1601
1719
|
const fnNames = getFnNames("createLoader");
|
|
1602
1720
|
changed = transformLoaders(
|
|
@@ -1625,41 +1743,13 @@ ${lazyImports.join(",\n")}
|
|
|
1625
1743
|
isBuild
|
|
1626
1744
|
) || changed;
|
|
1627
1745
|
}
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
s,
|
|
1636
|
-
filePath,
|
|
1637
|
-
isBuild
|
|
1638
|
-
) || changed;
|
|
1639
|
-
} else {
|
|
1640
|
-
changed = stubHandlerExprs(
|
|
1641
|
-
PRERENDER_CONFIG,
|
|
1642
|
-
bindings,
|
|
1643
|
-
s,
|
|
1644
|
-
filePath,
|
|
1645
|
-
isBuild
|
|
1646
|
-
) || changed;
|
|
1647
|
-
}
|
|
1648
|
-
}
|
|
1649
|
-
if (hasStaticHandlerCode) {
|
|
1650
|
-
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1651
|
-
const bindings = getBindings(code, fnNames);
|
|
1652
|
-
if (isRscEnv) {
|
|
1653
|
-
changed = transformHandlerIds(
|
|
1654
|
-
STATIC_CONFIG,
|
|
1655
|
-
bindings,
|
|
1656
|
-
s,
|
|
1657
|
-
filePath,
|
|
1658
|
-
isBuild
|
|
1659
|
-
) || changed;
|
|
1660
|
-
} else {
|
|
1661
|
-
changed = stubHandlerExprs(STATIC_CONFIG, bindings, s, filePath, isBuild) || changed;
|
|
1662
|
-
}
|
|
1746
|
+
const finalHandlerConfigs = [
|
|
1747
|
+
hasPrerenderHandlerCode && PRERENDER_CONFIG,
|
|
1748
|
+
hasStaticHandlerCode && STATIC_CONFIG
|
|
1749
|
+
].filter((c) => !!c);
|
|
1750
|
+
for (const cfg of finalHandlerConfigs) {
|
|
1751
|
+
const bindings = getBindings(code, getFnNames(cfg.fnName));
|
|
1752
|
+
changed = (isRscEnv ? transformHandlerIds(cfg, bindings, s, filePath, isBuild) : stubHandlerExprs(cfg, bindings, s, filePath, isBuild)) || changed;
|
|
1663
1753
|
}
|
|
1664
1754
|
if (!changed) return;
|
|
1665
1755
|
return {
|
|
@@ -1675,10 +1765,11 @@ ${lazyImports.join(",\n")}
|
|
|
1675
1765
|
|
|
1676
1766
|
// src/vite/plugins/use-cache-transform.ts
|
|
1677
1767
|
import path5 from "node:path";
|
|
1678
|
-
import
|
|
1768
|
+
import MagicString4 from "magic-string";
|
|
1679
1769
|
var debug4 = createRangoDebugger(NS.transform);
|
|
1680
1770
|
var CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
1681
1771
|
var LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
1772
|
+
var USE_CACHE_DIRECTIVE_RE = /^use cache(:\s*[\w-]+)?$/;
|
|
1682
1773
|
function useCacheTransform() {
|
|
1683
1774
|
let projectRoot = "";
|
|
1684
1775
|
let isBuild = false;
|
|
@@ -1716,7 +1807,7 @@ function useCacheTransform() {
|
|
|
1716
1807
|
let ast;
|
|
1717
1808
|
try {
|
|
1718
1809
|
const { parseAst: parseAst4 } = await import("vite");
|
|
1719
|
-
ast = parseAst4(code);
|
|
1810
|
+
ast = parseAst4(code, { lang: "tsx" });
|
|
1720
1811
|
} catch {
|
|
1721
1812
|
return;
|
|
1722
1813
|
}
|
|
@@ -1772,7 +1863,7 @@ function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild, isLa
|
|
|
1772
1863
|
);
|
|
1773
1864
|
}
|
|
1774
1865
|
if (exportNames.length === 0) {
|
|
1775
|
-
const s = new
|
|
1866
|
+
const s = new MagicString4(code);
|
|
1776
1867
|
const directive2 = findFileLevelDirective(ast);
|
|
1777
1868
|
if (directive2) {
|
|
1778
1869
|
s.overwrite(
|
|
@@ -1807,7 +1898,7 @@ function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild, isLa
|
|
|
1807
1898
|
function transformFunctionLevelUseCache(code, ast, filePath, sourceId, isBuild, transformHoistInlineDirective) {
|
|
1808
1899
|
try {
|
|
1809
1900
|
const { output, names } = transformHoistInlineDirective(code, ast, {
|
|
1810
|
-
directive:
|
|
1901
|
+
directive: USE_CACHE_DIRECTIVE_RE,
|
|
1811
1902
|
runtime: (value, name, meta) => {
|
|
1812
1903
|
const funcId = isBuild ? hashId(filePath, name) : `${filePath}#${name}`;
|
|
1813
1904
|
const profileMatch = meta.directiveMatch[1];
|
|
@@ -1837,14 +1928,13 @@ function findFileLevelDirective(ast) {
|
|
|
1837
1928
|
}
|
|
1838
1929
|
return null;
|
|
1839
1930
|
}
|
|
1840
|
-
var VALID_DIRECTIVE_RE = /^use cache(:\s*[\w-]+)?$/;
|
|
1841
1931
|
var NEAR_MISS_RE = /^use cache:\s*.+$/;
|
|
1842
1932
|
function warnOnNearMissDirectives(ast, fileId, warn) {
|
|
1843
1933
|
const visit = (node) => {
|
|
1844
1934
|
if (!node || typeof node !== "object") return;
|
|
1845
1935
|
if (node.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string") {
|
|
1846
1936
|
const value = node.expression.value;
|
|
1847
|
-
if (value.startsWith("use cache") && NEAR_MISS_RE.test(value) && !
|
|
1937
|
+
if (value.startsWith("use cache") && NEAR_MISS_RE.test(value) && !USE_CACHE_DIRECTIVE_RE.test(value)) {
|
|
1848
1938
|
const profilePart = value.slice("use cache:".length).trim();
|
|
1849
1939
|
warn(
|
|
1850
1940
|
`[rango:use-cache] "${value}" in ${fileId} has an invalid profile name "${profilePart}". Profile names must match [a-zA-Z0-9_-]+. This directive will be ignored.`
|
|
@@ -1938,7 +2028,7 @@ import {
|
|
|
1938
2028
|
import { createElement, StrictMode } from "react";
|
|
1939
2029
|
import { hydrateRoot } from "react-dom/client";
|
|
1940
2030
|
import { rscStream } from "@rangojs/router/internal/deps/html-stream-client";
|
|
1941
|
-
import { initBrowserApp,
|
|
2031
|
+
import { initBrowserApp, Rango } from "@rangojs/router/browser";
|
|
1942
2032
|
|
|
1943
2033
|
async function initializeApp() {
|
|
1944
2034
|
const deps = {
|
|
@@ -1953,7 +2043,7 @@ async function initializeApp() {
|
|
|
1953
2043
|
|
|
1954
2044
|
hydrateRoot(
|
|
1955
2045
|
document,
|
|
1956
|
-
createElement(StrictMode, null, createElement(
|
|
2046
|
+
createElement(StrictMode, null, createElement(Rango))
|
|
1957
2047
|
);
|
|
1958
2048
|
}
|
|
1959
2049
|
|
|
@@ -2040,7 +2130,7 @@ import { resolve } from "node:path";
|
|
|
2040
2130
|
// package.json
|
|
2041
2131
|
var package_default = {
|
|
2042
2132
|
name: "@rangojs/router",
|
|
2043
|
-
version: "0.0.0-experimental.
|
|
2133
|
+
version: "0.0.0-experimental.d98a8e9d",
|
|
2044
2134
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
2045
2135
|
keywords: [
|
|
2046
2136
|
"react",
|
|
@@ -2166,6 +2256,31 @@ var package_default = {
|
|
|
2166
2256
|
"./host/testing": {
|
|
2167
2257
|
types: "./src/host/testing.ts",
|
|
2168
2258
|
default: "./src/host/testing.ts"
|
|
2259
|
+
},
|
|
2260
|
+
"./testing": {
|
|
2261
|
+
types: "./src/testing/index.ts",
|
|
2262
|
+
default: "./src/testing/index.ts"
|
|
2263
|
+
},
|
|
2264
|
+
"./testing/vitest": {
|
|
2265
|
+
types: "./src/testing/vitest.ts",
|
|
2266
|
+
default: "./dist/testing/vitest.js"
|
|
2267
|
+
},
|
|
2268
|
+
"./testing/dom": {
|
|
2269
|
+
types: "./src/testing/dom.entry.ts",
|
|
2270
|
+
default: "./src/testing/dom.entry.ts"
|
|
2271
|
+
},
|
|
2272
|
+
"./testing/e2e": {
|
|
2273
|
+
types: "./src/testing/e2e/index.ts",
|
|
2274
|
+
default: "./src/testing/e2e/index.ts"
|
|
2275
|
+
},
|
|
2276
|
+
"./testing/flight": {
|
|
2277
|
+
types: "./src/testing/flight.entry.ts",
|
|
2278
|
+
"react-server": "./src/testing/flight.entry.ts",
|
|
2279
|
+
default: "./src/testing/flight.entry.ts"
|
|
2280
|
+
},
|
|
2281
|
+
"./testing/flight-matchers": {
|
|
2282
|
+
types: "./src/testing/flight-matchers.ts",
|
|
2283
|
+
default: "./src/testing/flight-matchers.ts"
|
|
2169
2284
|
}
|
|
2170
2285
|
},
|
|
2171
2286
|
publishConfig: {
|
|
@@ -2173,47 +2288,66 @@ var package_default = {
|
|
|
2173
2288
|
tag: "experimental"
|
|
2174
2289
|
},
|
|
2175
2290
|
scripts: {
|
|
2176
|
-
build: "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
2291
|
+
build: "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm dlx esbuild src/testing/vitest.ts --bundle --format=esm --outfile=dist/testing/vitest.js --platform=node --packages=external && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
2177
2292
|
prepublishOnly: "pnpm build",
|
|
2178
|
-
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit",
|
|
2293
|
+
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit && tsc -p tsconfig.augment-check.json --noEmit",
|
|
2179
2294
|
test: "playwright test",
|
|
2180
2295
|
"test:ui": "playwright test --ui",
|
|
2296
|
+
"test:hmr-local": "playwright test --project=dev-warmup --project=hmr-routes --project=hmr-basename --project=hmr-prerender --no-deps --workers=1",
|
|
2181
2297
|
"test:unit": "vitest run",
|
|
2182
|
-
"test:unit:watch": "vitest"
|
|
2298
|
+
"test:unit:watch": "vitest",
|
|
2299
|
+
"test:unit:rsc": "vitest run --config vitest.rsc.config.ts"
|
|
2183
2300
|
},
|
|
2184
2301
|
dependencies: {
|
|
2185
2302
|
"@types/debug": "^4.1.12",
|
|
2186
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2303
|
+
"@vitejs/plugin-rsc": "^0.5.26",
|
|
2187
2304
|
debug: "^4.4.1",
|
|
2188
2305
|
"magic-string": "^0.30.17",
|
|
2189
2306
|
picomatch: "^4.0.3",
|
|
2190
|
-
"rsc-html-stream": "^0.0.7"
|
|
2307
|
+
"rsc-html-stream": "^0.0.7",
|
|
2308
|
+
tinyexec: "^0.3.2"
|
|
2191
2309
|
},
|
|
2192
2310
|
devDependencies: {
|
|
2193
2311
|
"@playwright/test": "^1.49.1",
|
|
2312
|
+
"@shared/e2e": "workspace:*",
|
|
2313
|
+
"@testing-library/dom": "^10.4.1",
|
|
2314
|
+
"@testing-library/react": "^16.3.2",
|
|
2194
2315
|
"@types/node": "^24.10.1",
|
|
2195
2316
|
"@types/react": "catalog:",
|
|
2196
2317
|
"@types/react-dom": "catalog:",
|
|
2197
2318
|
esbuild: "^0.27.0",
|
|
2319
|
+
"happy-dom": "^20.10.1",
|
|
2198
2320
|
jiti: "^2.6.1",
|
|
2199
2321
|
react: "catalog:",
|
|
2200
2322
|
"react-dom": "catalog:",
|
|
2201
|
-
tinyexec: "^0.3.2",
|
|
2202
2323
|
typescript: "^5.3.0",
|
|
2203
2324
|
vitest: "^4.0.0"
|
|
2204
2325
|
},
|
|
2205
2326
|
peerDependencies: {
|
|
2206
|
-
"@cloudflare/vite-plugin": "^1.
|
|
2207
|
-
"@
|
|
2208
|
-
react: "
|
|
2209
|
-
|
|
2327
|
+
"@cloudflare/vite-plugin": "^1.38.0",
|
|
2328
|
+
"@playwright/test": "^1.49.1",
|
|
2329
|
+
"@testing-library/react": ">=16",
|
|
2330
|
+
"@vitejs/plugin-rsc": "^0.5.26",
|
|
2331
|
+
react: ">=19.2.6 <20",
|
|
2332
|
+
"react-dom": ">=19.2.6 <20",
|
|
2333
|
+
vite: "^8.0.0",
|
|
2334
|
+
vitest: ">=3"
|
|
2210
2335
|
},
|
|
2211
2336
|
peerDependenciesMeta: {
|
|
2212
2337
|
"@cloudflare/vite-plugin": {
|
|
2213
2338
|
optional: true
|
|
2214
2339
|
},
|
|
2340
|
+
"@playwright/test": {
|
|
2341
|
+
optional: true
|
|
2342
|
+
},
|
|
2343
|
+
"@testing-library/react": {
|
|
2344
|
+
optional: true
|
|
2345
|
+
},
|
|
2215
2346
|
vite: {
|
|
2216
2347
|
optional: true
|
|
2348
|
+
},
|
|
2349
|
+
vitest: {
|
|
2350
|
+
optional: true
|
|
2217
2351
|
}
|
|
2218
2352
|
}
|
|
2219
2353
|
};
|
|
@@ -2399,7 +2533,7 @@ ${objectBody}
|
|
|
2399
2533
|
} as const;
|
|
2400
2534
|
|
|
2401
2535
|
declare global {
|
|
2402
|
-
namespace
|
|
2536
|
+
namespace Rango {
|
|
2403
2537
|
interface GeneratedRouteMap extends Readonly<typeof NamedRoutes> {}
|
|
2404
2538
|
}
|
|
2405
2539
|
}
|
|
@@ -2634,7 +2768,7 @@ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagno
|
|
|
2634
2768
|
const realPath = resolve2(filePath);
|
|
2635
2769
|
const key = variableName ? `${realPath}:${variableName}` : realPath;
|
|
2636
2770
|
if (visited.has(key)) {
|
|
2637
|
-
console.warn(`[
|
|
2771
|
+
console.warn(`[rango] Circular include detected, skipping: ${key}`);
|
|
2638
2772
|
return { routes: {}, searchSchemas: {} };
|
|
2639
2773
|
}
|
|
2640
2774
|
visited.add(key);
|
|
@@ -2695,6 +2829,7 @@ function countPublicRouteEntries(source) {
|
|
|
2695
2829
|
return count;
|
|
2696
2830
|
}
|
|
2697
2831
|
var ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
|
|
2832
|
+
var ROUTER_CALL_PATTERN_G = /\bcreateRouter\s*[<(]/g;
|
|
2698
2833
|
function isRoutableSourceFile(name) {
|
|
2699
2834
|
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
2700
2835
|
}
|
|
@@ -2704,7 +2839,7 @@ function findRouterFilesRecursive(dir, filter, results) {
|
|
|
2704
2839
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
2705
2840
|
} catch (err) {
|
|
2706
2841
|
console.warn(
|
|
2707
|
-
`[
|
|
2842
|
+
`[rango] Failed to scan directory ${dir}: ${err.message}`
|
|
2708
2843
|
);
|
|
2709
2844
|
return;
|
|
2710
2845
|
}
|
|
@@ -2722,7 +2857,7 @@ function findRouterFilesRecursive(dir, filter, results) {
|
|
|
2722
2857
|
if (filter && !filter(fullPath)) continue;
|
|
2723
2858
|
try {
|
|
2724
2859
|
const source = readFileSync2(fullPath, "utf-8");
|
|
2725
|
-
if (ROUTER_CALL_PATTERN.test(source)) {
|
|
2860
|
+
if (ROUTER_CALL_PATTERN.test(source) && firstCodeMatchIndex(source, ROUTER_CALL_PATTERN_G) >= 0) {
|
|
2726
2861
|
routerFilesInDir.push(fullPath);
|
|
2727
2862
|
}
|
|
2728
2863
|
} catch {
|
|
@@ -2760,7 +2895,7 @@ function findNestedRouterConflict(routerFiles) {
|
|
|
2760
2895
|
}
|
|
2761
2896
|
return null;
|
|
2762
2897
|
}
|
|
2763
|
-
function formatNestedRouterConflictError(conflict, prefix = "[
|
|
2898
|
+
function formatNestedRouterConflictError(conflict, prefix = "[rango]") {
|
|
2764
2899
|
return `${prefix} Nested router roots are not supported.
|
|
2765
2900
|
Router root: ${conflict.ancestor}
|
|
2766
2901
|
Nested router: ${conflict.nested}
|
|
@@ -2856,19 +2991,38 @@ function extractBasenameFromRouter(code) {
|
|
|
2856
2991
|
visit(sourceFile);
|
|
2857
2992
|
return result;
|
|
2858
2993
|
}
|
|
2859
|
-
function applyBasenameToRoutes(result,
|
|
2994
|
+
function applyBasenameToRoutes(result, basename2) {
|
|
2860
2995
|
const prefixed = {};
|
|
2861
2996
|
for (const [name, pattern] of Object.entries(result.routes)) {
|
|
2862
2997
|
if (pattern === "/") {
|
|
2863
|
-
prefixed[name] =
|
|
2864
|
-
} else if (
|
|
2865
|
-
prefixed[name] =
|
|
2998
|
+
prefixed[name] = basename2;
|
|
2999
|
+
} else if (basename2.endsWith("/") && pattern.startsWith("/")) {
|
|
3000
|
+
prefixed[name] = basename2 + pattern.slice(1);
|
|
2866
3001
|
} else {
|
|
2867
|
-
prefixed[name] =
|
|
3002
|
+
prefixed[name] = basename2 + pattern;
|
|
2868
3003
|
}
|
|
2869
3004
|
}
|
|
2870
3005
|
return { routes: prefixed, searchSchemas: result.searchSchemas };
|
|
2871
3006
|
}
|
|
3007
|
+
function genFileTsPath(sourceFile) {
|
|
3008
|
+
const base = pathBasename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
3009
|
+
return join(dirname2(sourceFile), `${base}.named-routes.gen.ts`);
|
|
3010
|
+
}
|
|
3011
|
+
function resolveSearchSchemas(publicRouteNames, runtimeSchemas, sourceFile) {
|
|
3012
|
+
if (runtimeSchemas && Object.keys(runtimeSchemas).length > 0) {
|
|
3013
|
+
return runtimeSchemas;
|
|
3014
|
+
}
|
|
3015
|
+
const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
|
|
3016
|
+
if (Object.keys(staticParsed.searchSchemas).length === 0) {
|
|
3017
|
+
return runtimeSchemas;
|
|
3018
|
+
}
|
|
3019
|
+
const filtered = {};
|
|
3020
|
+
for (const name of publicRouteNames) {
|
|
3021
|
+
const schema = staticParsed.searchSchemas[name];
|
|
3022
|
+
if (schema) filtered[name] = schema;
|
|
3023
|
+
}
|
|
3024
|
+
return Object.keys(filtered).length > 0 ? filtered : runtimeSchemas;
|
|
3025
|
+
}
|
|
2872
3026
|
function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
2873
3027
|
let routerSource;
|
|
2874
3028
|
try {
|
|
@@ -2881,7 +3035,7 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
|
2881
3035
|
return { routes: {}, searchSchemas: {} };
|
|
2882
3036
|
}
|
|
2883
3037
|
const rawBasename = extractBasenameFromRouter(routerSource);
|
|
2884
|
-
const
|
|
3038
|
+
const basename2 = rawBasename ? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "") : void 0;
|
|
2885
3039
|
let result;
|
|
2886
3040
|
if (extraction.kind === "inline") {
|
|
2887
3041
|
result = buildCombinedRouteMapWithSearch(
|
|
@@ -2906,8 +3060,8 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
|
2906
3060
|
result = buildCombinedRouteMapWithSearch(routerFilePath, extraction.name);
|
|
2907
3061
|
}
|
|
2908
3062
|
}
|
|
2909
|
-
if (
|
|
2910
|
-
result = applyBasenameToRoutes(result,
|
|
3063
|
+
if (basename2) {
|
|
3064
|
+
result = applyBasenameToRoutes(result, basename2);
|
|
2911
3065
|
}
|
|
2912
3066
|
return result;
|
|
2913
3067
|
}
|
|
@@ -2922,7 +3076,7 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
2922
3076
|
if (existsSync3(oldCombinedPath)) {
|
|
2923
3077
|
unlinkSync(oldCombinedPath);
|
|
2924
3078
|
console.log(
|
|
2925
|
-
`[
|
|
3079
|
+
`[rango] Removed stale combined route types: ${oldCombinedPath}`
|
|
2926
3080
|
);
|
|
2927
3081
|
}
|
|
2928
3082
|
} catch {
|
|
@@ -2944,18 +3098,12 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
2944
3098
|
}
|
|
2945
3099
|
if (!extractUrlsFromRouter(routerSource)) continue;
|
|
2946
3100
|
}
|
|
2947
|
-
const
|
|
2948
|
-
/\.(tsx?|jsx?)$/,
|
|
2949
|
-
""
|
|
2950
|
-
);
|
|
2951
|
-
const outPath = join(
|
|
2952
|
-
dirname2(routerFilePath),
|
|
2953
|
-
`${routerBasename}.named-routes.gen.ts`
|
|
2954
|
-
);
|
|
3101
|
+
const outPath = genFileTsPath(routerFilePath);
|
|
2955
3102
|
const existing = existsSync3(outPath) ? readFileSync2(outPath, "utf-8") : null;
|
|
2956
3103
|
if (Object.keys(result.routes).length === 0) {
|
|
2957
3104
|
if (!existing) {
|
|
2958
3105
|
const emptySource = generateRouteTypesSource({});
|
|
3106
|
+
opts?.onWrite?.(outPath, emptySource);
|
|
2959
3107
|
writeFileSync(outPath, emptySource);
|
|
2960
3108
|
}
|
|
2961
3109
|
continue;
|
|
@@ -2975,9 +3123,10 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
2975
3123
|
continue;
|
|
2976
3124
|
}
|
|
2977
3125
|
}
|
|
3126
|
+
opts?.onWrite?.(outPath, source);
|
|
2978
3127
|
writeFileSync(outPath, source);
|
|
2979
3128
|
console.log(
|
|
2980
|
-
`[
|
|
3129
|
+
`[rango] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`
|
|
2981
3130
|
);
|
|
2982
3131
|
}
|
|
2983
3132
|
}
|
|
@@ -2994,7 +3143,7 @@ function normalizeModuleId(id) {
|
|
|
2994
3143
|
function getClientModuleSignature(source) {
|
|
2995
3144
|
let program;
|
|
2996
3145
|
try {
|
|
2997
|
-
program = parseAst3(source, {
|
|
3146
|
+
program = parseAst3(source, { lang: "tsx" });
|
|
2998
3147
|
} catch {
|
|
2999
3148
|
return void 0;
|
|
3000
3149
|
}
|
|
@@ -3077,11 +3226,12 @@ function createVersionPlugin() {
|
|
|
3077
3226
|
let currentVersion = buildVersion;
|
|
3078
3227
|
let isDev = false;
|
|
3079
3228
|
let server = null;
|
|
3229
|
+
let resolvedCacheDir;
|
|
3080
3230
|
const clientModuleSignatures = /* @__PURE__ */ new Map();
|
|
3081
3231
|
let versionCounter = 0;
|
|
3082
3232
|
const bumpVersion = (reason) => {
|
|
3083
3233
|
currentVersion = Date.now().toString(16) + String(++versionCounter);
|
|
3084
|
-
console.log(`[
|
|
3234
|
+
console.log(`[rango] ${reason}, version updated: ${currentVersion}`);
|
|
3085
3235
|
const rscEnv = server?.environments?.rsc;
|
|
3086
3236
|
const versionMod = rscEnv?.moduleGraph?.getModuleById(
|
|
3087
3237
|
"\0" + VIRTUAL_IDS.version
|
|
@@ -3095,6 +3245,7 @@ function createVersionPlugin() {
|
|
|
3095
3245
|
enforce: "pre",
|
|
3096
3246
|
configResolved(config) {
|
|
3097
3247
|
isDev = config.command === "serve";
|
|
3248
|
+
resolvedCacheDir = config.cacheDir ? String(config.cacheDir).replace(/\\/g, "/") : void 0;
|
|
3098
3249
|
},
|
|
3099
3250
|
configureServer(devServer) {
|
|
3100
3251
|
server = devServer;
|
|
@@ -3136,6 +3287,7 @@ function createVersionPlugin() {
|
|
|
3136
3287
|
if (!isDev) return;
|
|
3137
3288
|
const isRscModule = this.environment?.name === "rsc";
|
|
3138
3289
|
if (!isRscModule) return;
|
|
3290
|
+
if (isViteDepCachePath(ctx.file, resolvedCacheDir)) return;
|
|
3139
3291
|
if (ctx.modules.length === 1 && ctx.modules[0].id === "\0" + VIRTUAL_IDS.version) {
|
|
3140
3292
|
return;
|
|
3141
3293
|
}
|
|
@@ -3165,6 +3317,17 @@ function createVersionPlugin() {
|
|
|
3165
3317
|
}
|
|
3166
3318
|
};
|
|
3167
3319
|
}
|
|
3320
|
+
function isViteDepCachePath(filePath, cacheDir) {
|
|
3321
|
+
if (!filePath) return false;
|
|
3322
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
3323
|
+
if (cacheDir) {
|
|
3324
|
+
const normalizedCacheDir = cacheDir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
3325
|
+
if (normalized === normalizedCacheDir || normalized.startsWith(normalizedCacheDir + "/")) {
|
|
3326
|
+
return true;
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
return /\/node_modules\/\.vite[^/]*\//.test(normalized) || normalized.includes("/.vite-isolated/");
|
|
3330
|
+
}
|
|
3168
3331
|
|
|
3169
3332
|
// src/vite/utils/shared-utils.ts
|
|
3170
3333
|
import * as Vite from "vite";
|
|
@@ -3193,22 +3356,18 @@ function patchRsdwClientDebugInfoRecovery(code) {
|
|
|
3193
3356
|
};
|
|
3194
3357
|
}
|
|
3195
3358
|
function performanceTracksOptimizeDepsPlugin() {
|
|
3359
|
+
const RSDW_CLIENT_RE = /react-server-dom-webpack-client\.browser\.(development|production)\.js$/;
|
|
3196
3360
|
return {
|
|
3197
3361
|
name: "@rangojs/router:performance-tracks-optimize-deps",
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
contents: patched.code,
|
|
3208
|
-
loader: "js"
|
|
3209
|
-
};
|
|
3210
|
-
}
|
|
3211
|
-
);
|
|
3362
|
+
// Vite 8 optimizes deps with Rolldown (Rollup-style plugin pipeline), so the
|
|
3363
|
+
// pre-bundled RSDW client is patched via load() rather than esbuild's onLoad.
|
|
3364
|
+
// Returning code overrides Rolldown's default filesystem read for the module.
|
|
3365
|
+
async load(id) {
|
|
3366
|
+
const cleanId = id.split("?")[0] ?? id;
|
|
3367
|
+
if (!RSDW_CLIENT_RE.test(cleanId)) return null;
|
|
3368
|
+
const code = await readFile(cleanId, "utf8");
|
|
3369
|
+
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
3370
|
+
return { code: patched.code };
|
|
3212
3371
|
}
|
|
3213
3372
|
};
|
|
3214
3373
|
}
|
|
@@ -3235,24 +3394,27 @@ function performanceTracksPlugin() {
|
|
|
3235
3394
|
}
|
|
3236
3395
|
|
|
3237
3396
|
// src/vite/utils/shared-utils.ts
|
|
3238
|
-
|
|
3397
|
+
function resolveRscEntryFromConfig(config) {
|
|
3398
|
+
const entries = config.environments?.["rsc"]?.optimizeDeps?.entries;
|
|
3399
|
+
if (typeof entries === "string") return entries;
|
|
3400
|
+
if (Array.isArray(entries) && entries.length > 0) return entries[0];
|
|
3401
|
+
return void 0;
|
|
3402
|
+
}
|
|
3403
|
+
var versionRolldownPlugin = {
|
|
3239
3404
|
name: "@rangojs/router-version",
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
loader: "js"
|
|
3250
|
-
})
|
|
3251
|
-
);
|
|
3405
|
+
resolveId(id) {
|
|
3406
|
+
if (id === VIRTUAL_IDS.version) return "\0" + VIRTUAL_IDS.version;
|
|
3407
|
+
return void 0;
|
|
3408
|
+
},
|
|
3409
|
+
load(id) {
|
|
3410
|
+
if (id === "\0" + VIRTUAL_IDS.version) {
|
|
3411
|
+
return getVirtualVersionContent("dev");
|
|
3412
|
+
}
|
|
3413
|
+
return void 0;
|
|
3252
3414
|
}
|
|
3253
3415
|
};
|
|
3254
|
-
var
|
|
3255
|
-
plugins: [
|
|
3416
|
+
var sharedRolldownOptions = {
|
|
3417
|
+
plugins: [versionRolldownPlugin, performanceTracksOptimizeDepsPlugin()]
|
|
3256
3418
|
};
|
|
3257
3419
|
function createVirtualEntriesPlugin(entries, routerPathRef) {
|
|
3258
3420
|
const virtualModules = {};
|
|
@@ -3294,8 +3456,29 @@ function createVirtualEntriesPlugin(entries, routerPathRef) {
|
|
|
3294
3456
|
}
|
|
3295
3457
|
};
|
|
3296
3458
|
}
|
|
3459
|
+
function isContentHashedAssetConflict(message) {
|
|
3460
|
+
if (!message) return false;
|
|
3461
|
+
const match = /The emitted file "?([^"\s]+)"? overwrites a previously emitted file/.exec(
|
|
3462
|
+
message
|
|
3463
|
+
);
|
|
3464
|
+
if (!match) return false;
|
|
3465
|
+
const fileName = match[1];
|
|
3466
|
+
const base = fileName.slice(fileName.lastIndexOf("/") + 1);
|
|
3467
|
+
const dot = base.lastIndexOf(".");
|
|
3468
|
+
if (dot <= 0) return false;
|
|
3469
|
+
const stem = base.slice(0, dot);
|
|
3470
|
+
const HASH_LEN = 8;
|
|
3471
|
+
if (stem.length < HASH_LEN + 1 || stem[stem.length - HASH_LEN - 1] !== "-") {
|
|
3472
|
+
return false;
|
|
3473
|
+
}
|
|
3474
|
+
const hash = stem.slice(-HASH_LEN);
|
|
3475
|
+
return /^[A-Za-z0-9_-]+$/.test(hash) && /[A-Z0-9]/.test(hash);
|
|
3476
|
+
}
|
|
3297
3477
|
function onwarn(warning, defaultHandler) {
|
|
3298
|
-
if (warning.code === "MODULE_LEVEL_DIRECTIVE" || warning.code === "SOURCEMAP_ERROR" || warning.code === "EMPTY_BUNDLE") {
|
|
3478
|
+
if (warning.code === "MODULE_LEVEL_DIRECTIVE" || warning.code === "SOURCEMAP_ERROR" || warning.code === "EMPTY_BUNDLE" || warning.code === "INEFFECTIVE_DYNAMIC_IMPORT") {
|
|
3479
|
+
return;
|
|
3480
|
+
}
|
|
3481
|
+
if (warning.code === "FILE_NAME_CONFLICT" && isContentHashedAssetConflict(warning.message)) {
|
|
3299
3482
|
return;
|
|
3300
3483
|
}
|
|
3301
3484
|
if (warning.message?.includes("Sourcemap is likely to be incorrect")) {
|
|
@@ -3314,12 +3497,138 @@ function getManualChunks(id) {
|
|
|
3314
3497
|
return "react";
|
|
3315
3498
|
}
|
|
3316
3499
|
const packageName = getPublishedPackageName();
|
|
3317
|
-
if (normalized.includes(`node_modules/${packageName}/`) ||
|
|
3500
|
+
if (normalized.includes(`node_modules/${packageName}/`) || /\/packages\/(rsc-router|rangojs-router)\/(src|dist)\//.test(normalized)) {
|
|
3318
3501
|
return "router";
|
|
3319
3502
|
}
|
|
3320
3503
|
return void 0;
|
|
3321
3504
|
}
|
|
3322
3505
|
|
|
3506
|
+
// src/vite/plugins/client-ref-hashing.ts
|
|
3507
|
+
import { relative } from "node:path";
|
|
3508
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
3509
|
+
var debug7 = createRangoDebugger(NS.transform);
|
|
3510
|
+
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3511
|
+
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
3512
|
+
var FS_PREFIX = "/@fs/";
|
|
3513
|
+
function hashRefKey(relativeId) {
|
|
3514
|
+
return createHash2("sha256").update(relativeId).digest("hex").slice(0, 12);
|
|
3515
|
+
}
|
|
3516
|
+
function computeProductionHash(projectRoot, refKey) {
|
|
3517
|
+
let toHash;
|
|
3518
|
+
if (refKey.startsWith(CLIENT_PKG_PROXY_PREFIX)) {
|
|
3519
|
+
toHash = refKey.slice(CLIENT_PKG_PROXY_PREFIX.length);
|
|
3520
|
+
} else if (refKey.startsWith(CLIENT_IN_SERVER_PKG_PROXY_PREFIX)) {
|
|
3521
|
+
const absPath = decodeURIComponent(
|
|
3522
|
+
refKey.slice(CLIENT_IN_SERVER_PKG_PROXY_PREFIX.length)
|
|
3523
|
+
);
|
|
3524
|
+
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3525
|
+
} else if (refKey.startsWith(FS_PREFIX)) {
|
|
3526
|
+
const absPath = refKey.slice(FS_PREFIX.length - 1);
|
|
3527
|
+
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3528
|
+
} else if (refKey.startsWith("/")) {
|
|
3529
|
+
toHash = refKey.slice(1);
|
|
3530
|
+
} else {
|
|
3531
|
+
return refKey;
|
|
3532
|
+
}
|
|
3533
|
+
return hashRefKey(toHash);
|
|
3534
|
+
}
|
|
3535
|
+
var REGISTER_CLIENT_REF_RE = /registerClientReference\(\s*(?:(?:\([^)]*\))|(?:\(\)[\s\S]*?\}))\s*,\s*"([^"]+)"\s*,\s*"[^"]+"\s*\)/g;
|
|
3536
|
+
function transformClientRefs(code, projectRoot) {
|
|
3537
|
+
if (!code.includes("registerClientReference")) return null;
|
|
3538
|
+
let hasReplacement = false;
|
|
3539
|
+
const result = code.replace(
|
|
3540
|
+
REGISTER_CLIENT_REF_RE,
|
|
3541
|
+
(match, refKey) => {
|
|
3542
|
+
const hash = computeProductionHash(projectRoot, refKey);
|
|
3543
|
+
if (hash === refKey) return match;
|
|
3544
|
+
hasReplacement = true;
|
|
3545
|
+
return match.replace(`"${refKey}"`, `"${hash}"`);
|
|
3546
|
+
}
|
|
3547
|
+
);
|
|
3548
|
+
return hasReplacement ? result : null;
|
|
3549
|
+
}
|
|
3550
|
+
function hashClientRefs(projectRoot) {
|
|
3551
|
+
const counter = createCounter(debug7, "hash-client-refs");
|
|
3552
|
+
return {
|
|
3553
|
+
name: "@rangojs/router:hash-client-refs",
|
|
3554
|
+
// Run after the RSC plugin's transform (default enforce is normal)
|
|
3555
|
+
enforce: "post",
|
|
3556
|
+
applyToEnvironment(env) {
|
|
3557
|
+
return env.name === "rsc";
|
|
3558
|
+
},
|
|
3559
|
+
buildEnd() {
|
|
3560
|
+
counter?.flush();
|
|
3561
|
+
},
|
|
3562
|
+
transform(code, id) {
|
|
3563
|
+
const start = counter ? performance.now() : 0;
|
|
3564
|
+
try {
|
|
3565
|
+
const result = transformClientRefs(code, projectRoot);
|
|
3566
|
+
if (result === null) return;
|
|
3567
|
+
return { code: result, map: null };
|
|
3568
|
+
} finally {
|
|
3569
|
+
counter?.record(id, performance.now() - start);
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3572
|
+
};
|
|
3573
|
+
}
|
|
3574
|
+
|
|
3575
|
+
// src/vite/utils/client-chunks.ts
|
|
3576
|
+
var debugChunks = createRangoDebugger(NS.chunks);
|
|
3577
|
+
function isSharedRuntime(meta) {
|
|
3578
|
+
return [meta.id, meta.normalizedId].some(
|
|
3579
|
+
(path6) => path6.includes("/node_modules/") || /\/@rangojs\/router\//.test(path6) || /\/packages\/(rangojs-router|rsc-router)\/(src|dist)\//.test(path6)
|
|
3580
|
+
);
|
|
3581
|
+
}
|
|
3582
|
+
function sanitizeGroup(name) {
|
|
3583
|
+
return name.replace(/[^a-zA-Z0-9_-]+/g, "_").replace(/^_+|_+$/g, "") || "app";
|
|
3584
|
+
}
|
|
3585
|
+
var ROUTE_ROOT_DIRS = /* @__PURE__ */ new Set([
|
|
3586
|
+
"routes",
|
|
3587
|
+
"route",
|
|
3588
|
+
"pages",
|
|
3589
|
+
"page",
|
|
3590
|
+
"app",
|
|
3591
|
+
"features",
|
|
3592
|
+
"feature",
|
|
3593
|
+
"views",
|
|
3594
|
+
"view",
|
|
3595
|
+
"handlers",
|
|
3596
|
+
"urls",
|
|
3597
|
+
"modules",
|
|
3598
|
+
"screens",
|
|
3599
|
+
"sections"
|
|
3600
|
+
]);
|
|
3601
|
+
function directoryClientChunks(meta, ctx) {
|
|
3602
|
+
if (isSharedRuntime(meta)) {
|
|
3603
|
+
return void 0;
|
|
3604
|
+
}
|
|
3605
|
+
if (ctx?.fallbackRefs.size && ctx.fallbackRefs.has(hashRefKey(meta.normalizedId))) {
|
|
3606
|
+
debugChunks?.("fallback %s -> app-fallback", meta.normalizedId);
|
|
3607
|
+
return "app-fallback";
|
|
3608
|
+
}
|
|
3609
|
+
const segments = meta.normalizedId.split("/").filter(Boolean);
|
|
3610
|
+
const dirCount = segments.length - 1;
|
|
3611
|
+
if (dirCount >= 1) {
|
|
3612
|
+
for (let i = 0; i < dirCount - 1; i++) {
|
|
3613
|
+
if (ROUTE_ROOT_DIRS.has(segments[i].toLowerCase())) {
|
|
3614
|
+
const group = `app-${sanitizeGroup(segments[i + 1])}`;
|
|
3615
|
+
debugChunks?.("split %s -> %s", meta.normalizedId, group);
|
|
3616
|
+
return group;
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
debugChunks?.(
|
|
3621
|
+
"shared %s (no route-root marker; inherits default grouping)",
|
|
3622
|
+
meta.normalizedId
|
|
3623
|
+
);
|
|
3624
|
+
return void 0;
|
|
3625
|
+
}
|
|
3626
|
+
function resolveClientChunks(option, ctx) {
|
|
3627
|
+
if (!option) return void 0;
|
|
3628
|
+
if (option === true) return (meta) => directoryClientChunks(meta, ctx);
|
|
3629
|
+
return option;
|
|
3630
|
+
}
|
|
3631
|
+
|
|
3323
3632
|
// src/vite/utils/banner.ts
|
|
3324
3633
|
var rangoVersion = package_default.version;
|
|
3325
3634
|
var _bannerPrinted = false;
|
|
@@ -3356,15 +3665,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3356
3665
|
enforce: "pre",
|
|
3357
3666
|
configResolved(config) {
|
|
3358
3667
|
let entryPath = rscEntryPath;
|
|
3359
|
-
if (!entryPath)
|
|
3360
|
-
const rscEnvConfig = config.environments?.["rsc"];
|
|
3361
|
-
const entries = rscEnvConfig?.optimizeDeps?.entries;
|
|
3362
|
-
if (typeof entries === "string") {
|
|
3363
|
-
entryPath = entries;
|
|
3364
|
-
} else if (Array.isArray(entries) && entries.length > 0) {
|
|
3365
|
-
entryPath = entries[0];
|
|
3366
|
-
}
|
|
3367
|
-
}
|
|
3668
|
+
if (!entryPath) entryPath = resolveRscEntryFromConfig(config);
|
|
3368
3669
|
if (entryPath) {
|
|
3369
3670
|
resolvedEntryPath = resolve4(config.root, entryPath);
|
|
3370
3671
|
}
|
|
@@ -3412,23 +3713,23 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3412
3713
|
}
|
|
3413
3714
|
|
|
3414
3715
|
// src/vite/plugins/cjs-to-esm.ts
|
|
3415
|
-
var
|
|
3716
|
+
var debug8 = createRangoDebugger(NS.transform);
|
|
3416
3717
|
function createCjsToEsmPlugin() {
|
|
3417
3718
|
return {
|
|
3418
3719
|
name: "@rangojs/router:cjs-to-esm",
|
|
3419
3720
|
enforce: "pre",
|
|
3420
3721
|
transform(code, id) {
|
|
3421
|
-
const cleanId = id.split("?")[0];
|
|
3422
|
-
if (cleanId.includes("vendor/react-server-dom/client.browser.js")
|
|
3722
|
+
const cleanId = id.split("?")[0].replaceAll("\\", "/");
|
|
3723
|
+
if (cleanId.includes("vendor/react-server-dom/client.browser.js")) {
|
|
3423
3724
|
const isProd = process.env.NODE_ENV === "production";
|
|
3424
3725
|
const cjsFile = isProd ? "./cjs/react-server-dom-webpack-client.browser.production.js" : "./cjs/react-server-dom-webpack-client.browser.development.js";
|
|
3425
|
-
|
|
3726
|
+
debug8?.("cjs-to-esm entry redirect %s", id);
|
|
3426
3727
|
return {
|
|
3427
3728
|
code: `export * from "${cjsFile}";`,
|
|
3428
3729
|
map: null
|
|
3429
3730
|
};
|
|
3430
3731
|
}
|
|
3431
|
-
if (
|
|
3732
|
+
if (cleanId.includes("vendor/react-server-dom/cjs/") && cleanId.includes("client.browser")) {
|
|
3432
3733
|
let transformed = code;
|
|
3433
3734
|
const licenseMatch = transformed.match(/^\/\*\*[\s\S]*?\*\//);
|
|
3434
3735
|
const license = licenseMatch ? licenseMatch[0] : "";
|
|
@@ -3458,7 +3759,7 @@ function createCjsToEsmPlugin() {
|
|
|
3458
3759
|
"export const $1 ="
|
|
3459
3760
|
);
|
|
3460
3761
|
transformed = license + "\n" + transformed;
|
|
3461
|
-
|
|
3762
|
+
debug8?.("cjs-to-esm body rewrite %s", id);
|
|
3462
3763
|
return {
|
|
3463
3764
|
code: transformed,
|
|
3464
3765
|
map: null
|
|
@@ -3547,7 +3848,7 @@ function createCloudflareProtocolStubPlugin() {
|
|
|
3547
3848
|
if (!code.includes(CF_PREFIX)) return null;
|
|
3548
3849
|
let ast;
|
|
3549
3850
|
try {
|
|
3550
|
-
ast = this.parse(code);
|
|
3851
|
+
ast = this.parse(code, { lang: "tsx" });
|
|
3551
3852
|
} catch {
|
|
3552
3853
|
return null;
|
|
3553
3854
|
}
|
|
@@ -3607,72 +3908,6 @@ function walk(node, visit) {
|
|
|
3607
3908
|
}
|
|
3608
3909
|
}
|
|
3609
3910
|
|
|
3610
|
-
// src/vite/plugins/client-ref-hashing.ts
|
|
3611
|
-
import { relative } from "node:path";
|
|
3612
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
3613
|
-
var debug8 = createRangoDebugger(NS.transform);
|
|
3614
|
-
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3615
|
-
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
3616
|
-
var FS_PREFIX = "/@fs/";
|
|
3617
|
-
function computeProductionHash(projectRoot, refKey) {
|
|
3618
|
-
let toHash;
|
|
3619
|
-
if (refKey.startsWith(CLIENT_PKG_PROXY_PREFIX)) {
|
|
3620
|
-
toHash = refKey.slice(CLIENT_PKG_PROXY_PREFIX.length);
|
|
3621
|
-
} else if (refKey.startsWith(CLIENT_IN_SERVER_PKG_PROXY_PREFIX)) {
|
|
3622
|
-
const absPath = decodeURIComponent(
|
|
3623
|
-
refKey.slice(CLIENT_IN_SERVER_PKG_PROXY_PREFIX.length)
|
|
3624
|
-
);
|
|
3625
|
-
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3626
|
-
} else if (refKey.startsWith(FS_PREFIX)) {
|
|
3627
|
-
const absPath = refKey.slice(FS_PREFIX.length - 1);
|
|
3628
|
-
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3629
|
-
} else if (refKey.startsWith("/")) {
|
|
3630
|
-
toHash = refKey.slice(1);
|
|
3631
|
-
} else {
|
|
3632
|
-
return refKey;
|
|
3633
|
-
}
|
|
3634
|
-
return createHash2("sha256").update(toHash).digest("hex").slice(0, 12);
|
|
3635
|
-
}
|
|
3636
|
-
var REGISTER_CLIENT_REF_RE = /registerClientReference\(\s*(?:(?:\([^)]*\))|(?:\(\)[\s\S]*?\}))\s*,\s*"([^"]+)"\s*,\s*"[^"]+"\s*\)/g;
|
|
3637
|
-
function transformClientRefs(code, projectRoot) {
|
|
3638
|
-
if (!code.includes("registerClientReference")) return null;
|
|
3639
|
-
let hasReplacement = false;
|
|
3640
|
-
const result = code.replace(
|
|
3641
|
-
REGISTER_CLIENT_REF_RE,
|
|
3642
|
-
(match, refKey) => {
|
|
3643
|
-
const hash = computeProductionHash(projectRoot, refKey);
|
|
3644
|
-
if (hash === refKey) return match;
|
|
3645
|
-
hasReplacement = true;
|
|
3646
|
-
return match.replace(`"${refKey}"`, `"${hash}"`);
|
|
3647
|
-
}
|
|
3648
|
-
);
|
|
3649
|
-
return hasReplacement ? result : null;
|
|
3650
|
-
}
|
|
3651
|
-
function hashClientRefs(projectRoot) {
|
|
3652
|
-
const counter = createCounter(debug8, "hash-client-refs");
|
|
3653
|
-
return {
|
|
3654
|
-
name: "@rangojs/router:hash-client-refs",
|
|
3655
|
-
// Run after the RSC plugin's transform (default enforce is normal)
|
|
3656
|
-
enforce: "post",
|
|
3657
|
-
applyToEnvironment(env) {
|
|
3658
|
-
return env.name === "rsc";
|
|
3659
|
-
},
|
|
3660
|
-
buildEnd() {
|
|
3661
|
-
counter?.flush();
|
|
3662
|
-
},
|
|
3663
|
-
transform(code, id) {
|
|
3664
|
-
const start = counter ? performance.now() : 0;
|
|
3665
|
-
try {
|
|
3666
|
-
const result = transformClientRefs(code, projectRoot);
|
|
3667
|
-
if (result === null) return;
|
|
3668
|
-
return { code: result, map: null };
|
|
3669
|
-
} finally {
|
|
3670
|
-
counter?.record(id, performance.now() - start);
|
|
3671
|
-
}
|
|
3672
|
-
}
|
|
3673
|
-
};
|
|
3674
|
-
}
|
|
3675
|
-
|
|
3676
3911
|
// src/vite/utils/bundle-analysis.ts
|
|
3677
3912
|
function findMatchingParenInBundle(code, openParenPos) {
|
|
3678
3913
|
let depth = 1;
|
|
@@ -3703,7 +3938,7 @@ function extractHandlerExportsFromChunk(chunkCode, handlerModules, fnName, detec
|
|
|
3703
3938
|
if (detectPassthrough) {
|
|
3704
3939
|
const eFnName = escapeRegExp(fnName);
|
|
3705
3940
|
const callStartRe = new RegExp(
|
|
3706
|
-
`const\\s+${eName}\\s*=\\s*${eFnName}\\s*(?:<[^>]*>)?\\s*\\(`
|
|
3941
|
+
`(?:const|let|var)\\s+${eName}\\s*=\\s*${eFnName}\\s*(?:<[^>]*>)?\\s*\\(`
|
|
3707
3942
|
);
|
|
3708
3943
|
const callStart = callStartRe.exec(chunkCode);
|
|
3709
3944
|
if (callStart) {
|
|
@@ -3728,7 +3963,7 @@ function evictHandlerCode(code, exports, fnName, brand) {
|
|
|
3728
3963
|
if (passthrough) continue;
|
|
3729
3964
|
const eName = escapeRegExp(name);
|
|
3730
3965
|
const callStartRe = new RegExp(
|
|
3731
|
-
`const\\s+${eName}\\s*=\\s*${eFnName}\\s*(?:<[^>]*>)?\\s*\\(`
|
|
3966
|
+
`(?:const|let|var)\\s+${eName}\\s*=\\s*${eFnName}\\s*(?:<[^>]*>)?\\s*\\(`
|
|
3732
3967
|
);
|
|
3733
3968
|
const startMatch = callStartRe.exec(modified);
|
|
3734
3969
|
if (!startMatch) continue;
|
|
@@ -3763,6 +3998,8 @@ function createDiscoveryState(entryPath, opts) {
|
|
|
3763
3998
|
projectRoot: "",
|
|
3764
3999
|
isBuildMode: false,
|
|
3765
4000
|
userResolveAlias: void 0,
|
|
4001
|
+
userRunnerConfig: void 0,
|
|
4002
|
+
userResolvePlugins: [],
|
|
3766
4003
|
scanFilter: void 0,
|
|
3767
4004
|
cachedRouterFiles: void 0,
|
|
3768
4005
|
opts,
|
|
@@ -3784,7 +4021,8 @@ function createDiscoveryState(entryPath, opts) {
|
|
|
3784
4021
|
devServerOrigin: null,
|
|
3785
4022
|
devServer: null,
|
|
3786
4023
|
selfWrittenGenFiles: /* @__PURE__ */ new Map(),
|
|
3787
|
-
SELF_WRITE_WINDOW_MS: 5e3
|
|
4024
|
+
SELF_WRITE_WINDOW_MS: 5e3,
|
|
4025
|
+
lastDiscoveryError: null
|
|
3788
4026
|
};
|
|
3789
4027
|
}
|
|
3790
4028
|
|
|
@@ -3822,11 +4060,14 @@ function checkSelfGenWrite(state, filePath, consume) {
|
|
|
3822
4060
|
}
|
|
3823
4061
|
}
|
|
3824
4062
|
|
|
3825
|
-
// src/
|
|
4063
|
+
// src/build/prefix-tree-utils.ts
|
|
3826
4064
|
function flattenLeafEntries(prefixTree, routeManifest, result) {
|
|
3827
|
-
function visit(node) {
|
|
4065
|
+
function visit(node, ancestorStaticPrefixes) {
|
|
3828
4066
|
const children = node.children || {};
|
|
3829
4067
|
if (Object.keys(children).length === 0 && node.routes && node.routes.length > 0) {
|
|
4068
|
+
if (ancestorStaticPrefixes.has(node.staticPrefix)) {
|
|
4069
|
+
return;
|
|
4070
|
+
}
|
|
3830
4071
|
const routes = {};
|
|
3831
4072
|
for (const name of node.routes) {
|
|
3832
4073
|
if (name in routeManifest) {
|
|
@@ -3835,13 +4076,15 @@ function flattenLeafEntries(prefixTree, routeManifest, result) {
|
|
|
3835
4076
|
}
|
|
3836
4077
|
result.push({ staticPrefix: node.staticPrefix, routes });
|
|
3837
4078
|
} else {
|
|
4079
|
+
const nextAncestors = new Set(ancestorStaticPrefixes);
|
|
4080
|
+
nextAncestors.add(node.staticPrefix);
|
|
3838
4081
|
for (const child of Object.values(children)) {
|
|
3839
|
-
visit(child);
|
|
4082
|
+
visit(child, nextAncestors);
|
|
3840
4083
|
}
|
|
3841
4084
|
}
|
|
3842
4085
|
}
|
|
3843
4086
|
for (const node of Object.values(prefixTree)) {
|
|
3844
|
-
visit(node);
|
|
4087
|
+
visit(node, /* @__PURE__ */ new Set());
|
|
3845
4088
|
}
|
|
3846
4089
|
}
|
|
3847
4090
|
function buildRouteToStaticPrefix(prefixTree, result) {
|
|
@@ -3858,6 +4101,8 @@ function buildRouteToStaticPrefix(prefixTree, result) {
|
|
|
3858
4101
|
visit(node);
|
|
3859
4102
|
}
|
|
3860
4103
|
}
|
|
4104
|
+
|
|
4105
|
+
// src/vite/utils/manifest-utils.ts
|
|
3861
4106
|
function jsonParseExpression(value) {
|
|
3862
4107
|
const json = JSON.stringify(value);
|
|
3863
4108
|
const escaped = json.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
@@ -4068,7 +4313,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4068
4313
|
const progressInterval = totalDynamic > 0 ? setInterval(() => {
|
|
4069
4314
|
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
4070
4315
|
console.log(
|
|
4071
|
-
`[
|
|
4316
|
+
`[rango] Resolving prerender params... ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
4072
4317
|
);
|
|
4073
4318
|
}, 5e3) : void 0;
|
|
4074
4319
|
try {
|
|
@@ -4105,7 +4350,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4105
4350
|
get env() {
|
|
4106
4351
|
if (buildEnv !== void 0) return buildEnv;
|
|
4107
4352
|
throw new Error(
|
|
4108
|
-
"[
|
|
4353
|
+
"[rango] ctx.env is not available during build-time getParams(). Configure buildEnv in your rango() plugin options to enable build-time env access."
|
|
4109
4354
|
);
|
|
4110
4355
|
}
|
|
4111
4356
|
};
|
|
@@ -4146,7 +4391,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4146
4391
|
resolvedRoutes++;
|
|
4147
4392
|
if (err.name === "Skip") {
|
|
4148
4393
|
console.log(
|
|
4149
|
-
`[
|
|
4394
|
+
`[rango] SKIP route "${routeName}" - ${err.message}`
|
|
4150
4395
|
);
|
|
4151
4396
|
notifyOnError(
|
|
4152
4397
|
registry,
|
|
@@ -4159,14 +4404,14 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4159
4404
|
continue;
|
|
4160
4405
|
}
|
|
4161
4406
|
console.error(
|
|
4162
|
-
`[
|
|
4407
|
+
`[rango] Failed to get params for prerender route "${routeName}": ${err.message}`
|
|
4163
4408
|
);
|
|
4164
4409
|
notifyOnError(registry, err, "prerender", routeName);
|
|
4165
4410
|
throw err;
|
|
4166
4411
|
}
|
|
4167
4412
|
} else {
|
|
4168
4413
|
console.warn(
|
|
4169
|
-
`[
|
|
4414
|
+
`[rango] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
4170
4415
|
);
|
|
4171
4416
|
}
|
|
4172
4417
|
}
|
|
@@ -4177,7 +4422,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4177
4422
|
clearInterval(progressInterval);
|
|
4178
4423
|
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
4179
4424
|
console.log(
|
|
4180
|
-
`[
|
|
4425
|
+
`[rango] Resolved prerender params: ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
4181
4426
|
);
|
|
4182
4427
|
}
|
|
4183
4428
|
}
|
|
@@ -4191,7 +4436,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4191
4436
|
const maxConcurrency = Math.max(...entries.map((e) => e.concurrency));
|
|
4192
4437
|
const concurrencyNote = maxConcurrency > 1 ? ` (concurrency: ${maxConcurrency})` : "";
|
|
4193
4438
|
console.log(
|
|
4194
|
-
`[
|
|
4439
|
+
`[rango] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
4195
4440
|
);
|
|
4196
4441
|
debug9?.(
|
|
4197
4442
|
"prerender loop: %d entries, max concurrency %d",
|
|
@@ -4224,7 +4469,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4224
4469
|
if (result.passthrough) {
|
|
4225
4470
|
const elapsed2 = (performance.now() - startUrl).toFixed(0);
|
|
4226
4471
|
console.log(
|
|
4227
|
-
`[
|
|
4472
|
+
`[rango] PASS ${entry.urlPath.padEnd(40)} (${elapsed2}ms) - live fallback`
|
|
4228
4473
|
);
|
|
4229
4474
|
doneCount++;
|
|
4230
4475
|
break;
|
|
@@ -4257,7 +4502,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4257
4502
|
}
|
|
4258
4503
|
const elapsed = (performance.now() - startUrl).toFixed(0);
|
|
4259
4504
|
console.log(
|
|
4260
|
-
`[
|
|
4505
|
+
`[rango] OK ${entry.urlPath.padEnd(40)} (${elapsed}ms)`
|
|
4261
4506
|
);
|
|
4262
4507
|
doneCount++;
|
|
4263
4508
|
break;
|
|
@@ -4265,7 +4510,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4265
4510
|
if (err.name === "Skip") {
|
|
4266
4511
|
const elapsed2 = (performance.now() - startUrl).toFixed(0);
|
|
4267
4512
|
console.log(
|
|
4268
|
-
`[
|
|
4513
|
+
`[rango] SKIP ${entry.urlPath.padEnd(40)} (${elapsed2}ms) - ${err.message}`
|
|
4269
4514
|
);
|
|
4270
4515
|
skipCount++;
|
|
4271
4516
|
notifyOnError(
|
|
@@ -4280,7 +4525,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4280
4525
|
}
|
|
4281
4526
|
const elapsed = (performance.now() - startUrl).toFixed(0);
|
|
4282
4527
|
console.error(
|
|
4283
|
-
`[
|
|
4528
|
+
`[rango] FAIL ${entry.urlPath.padEnd(40)} (${elapsed}ms) - ${err.message}`
|
|
4284
4529
|
);
|
|
4285
4530
|
notifyOnError(
|
|
4286
4531
|
registry,
|
|
@@ -4302,7 +4547,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4302
4547
|
const parts = [`${doneCount} done`];
|
|
4303
4548
|
if (skipCount > 0) parts.push(`${skipCount} skipped`);
|
|
4304
4549
|
console.log(
|
|
4305
|
-
`[
|
|
4550
|
+
`[rango] Pre-render complete: ${parts.join(", ")} (${totalElapsed}ms total)`
|
|
4306
4551
|
);
|
|
4307
4552
|
debug9?.(
|
|
4308
4553
|
"expandPrerenderRoutes done: %d done, %d skipped, %sms (overall %sms)",
|
|
@@ -4328,16 +4573,14 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
4328
4573
|
totalStaticCount += exportNames.length;
|
|
4329
4574
|
}
|
|
4330
4575
|
const startStatic = performance.now();
|
|
4331
|
-
console.log(
|
|
4332
|
-
`[rsc-router] Rendering ${totalStaticCount} static handler(s)...`
|
|
4333
|
-
);
|
|
4576
|
+
console.log(`[rango] Rendering ${totalStaticCount} static handler(s)...`);
|
|
4334
4577
|
for (const [moduleId, exportNames] of state.resolvedStaticModules) {
|
|
4335
4578
|
let mod;
|
|
4336
4579
|
try {
|
|
4337
4580
|
mod = await rscEnv.runner.import(moduleId);
|
|
4338
4581
|
} catch (err) {
|
|
4339
4582
|
console.error(
|
|
4340
|
-
`[
|
|
4583
|
+
`[rango] Failed to import static module ${moduleId}: ${err.message}`
|
|
4341
4584
|
);
|
|
4342
4585
|
notifyOnError(registry, err, "static");
|
|
4343
4586
|
throw err;
|
|
@@ -4367,9 +4610,7 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
4367
4610
|
exportValue
|
|
4368
4611
|
);
|
|
4369
4612
|
const elapsed = (performance.now() - startHandler).toFixed(0);
|
|
4370
|
-
console.log(
|
|
4371
|
-
`[rsc-router] OK ${name.padEnd(40)} (${elapsed}ms)`
|
|
4372
|
-
);
|
|
4613
|
+
console.log(`[rango] OK ${name.padEnd(40)} (${elapsed}ms)`);
|
|
4373
4614
|
staticDone++;
|
|
4374
4615
|
handled = true;
|
|
4375
4616
|
break;
|
|
@@ -4378,7 +4619,7 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
4378
4619
|
if (err.name === "Skip") {
|
|
4379
4620
|
const elapsed2 = (performance.now() - startHandler).toFixed(0);
|
|
4380
4621
|
console.log(
|
|
4381
|
-
`[
|
|
4622
|
+
`[rango] SKIP ${name.padEnd(40)} (${elapsed2}ms) - ${err.message}`
|
|
4382
4623
|
);
|
|
4383
4624
|
staticSkip++;
|
|
4384
4625
|
notifyOnError(registry, err, "static", void 0, void 0, true);
|
|
@@ -4387,16 +4628,14 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
4387
4628
|
}
|
|
4388
4629
|
const elapsed = (performance.now() - startHandler).toFixed(0);
|
|
4389
4630
|
console.error(
|
|
4390
|
-
`[
|
|
4631
|
+
`[rango] FAIL ${name.padEnd(40)} (${elapsed}ms) - ${err.message}`
|
|
4391
4632
|
);
|
|
4392
4633
|
notifyOnError(registry, err, "static");
|
|
4393
4634
|
throw err;
|
|
4394
4635
|
}
|
|
4395
4636
|
}
|
|
4396
4637
|
if (!handled) {
|
|
4397
|
-
console.warn(
|
|
4398
|
-
`[rsc-router] No router could render static handler "${name}"`
|
|
4399
|
-
);
|
|
4638
|
+
console.warn(`[rango] No router could render static handler "${name}"`);
|
|
4400
4639
|
}
|
|
4401
4640
|
}
|
|
4402
4641
|
}
|
|
@@ -4407,7 +4646,7 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
4407
4646
|
const staticParts = [`${staticDone} done`];
|
|
4408
4647
|
if (staticSkip > 0) staticParts.push(`${staticSkip} skipped`);
|
|
4409
4648
|
console.log(
|
|
4410
|
-
`[
|
|
4649
|
+
`[rango] Static render complete: ${staticParts.join(", ")} (${totalStaticElapsed}ms total)`
|
|
4411
4650
|
);
|
|
4412
4651
|
debug9?.(
|
|
4413
4652
|
"renderStaticHandlers done: %d done, %d skipped, %sms (overall %sms)",
|
|
@@ -4418,6 +4657,80 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
4418
4657
|
);
|
|
4419
4658
|
}
|
|
4420
4659
|
|
|
4660
|
+
// src/vite/discovery/discovery-errors.ts
|
|
4661
|
+
function indent(text, pad) {
|
|
4662
|
+
return text.split("\n").map((line) => line.length > 0 ? pad + line : line).join("\n");
|
|
4663
|
+
}
|
|
4664
|
+
async function invokeLazyMount(loader, context, errors) {
|
|
4665
|
+
try {
|
|
4666
|
+
await loader();
|
|
4667
|
+
} catch (error) {
|
|
4668
|
+
errors.push({ context, error });
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
function isLazyMount(route) {
|
|
4672
|
+
return !!route && route.kind === "lazy" && typeof route.handler === "function";
|
|
4673
|
+
}
|
|
4674
|
+
async function resolveHostRouterHandlers(hostRegistry) {
|
|
4675
|
+
const errors = [];
|
|
4676
|
+
for (const [hostId, entry] of hostRegistry) {
|
|
4677
|
+
for (const route of entry.routes) {
|
|
4678
|
+
if (isLazyMount(route)) {
|
|
4679
|
+
await invokeLazyMount(
|
|
4680
|
+
route.handler,
|
|
4681
|
+
`host "${hostId}" route handler`,
|
|
4682
|
+
errors
|
|
4683
|
+
);
|
|
4684
|
+
}
|
|
4685
|
+
}
|
|
4686
|
+
if (isLazyMount(entry.fallback)) {
|
|
4687
|
+
await invokeLazyMount(
|
|
4688
|
+
entry.fallback.handler,
|
|
4689
|
+
`host "${hostId}" fallback handler`,
|
|
4690
|
+
errors
|
|
4691
|
+
);
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
return errors;
|
|
4695
|
+
}
|
|
4696
|
+
function formatNoRoutersError(entryPath, errors) {
|
|
4697
|
+
const base = `[rango] No routers found in registry after importing ${entryPath}`;
|
|
4698
|
+
if (errors.length === 0) {
|
|
4699
|
+
return base;
|
|
4700
|
+
}
|
|
4701
|
+
const formatted = errors.map(({ context, error }) => {
|
|
4702
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
4703
|
+
const detail = err.stack ?? err.message;
|
|
4704
|
+
return ` - while resolving ${context}:
|
|
4705
|
+
${indent(detail, " ")}`;
|
|
4706
|
+
}).join("\n");
|
|
4707
|
+
return `${base}
|
|
4708
|
+
|
|
4709
|
+
${errors.length} error(s) were caught during host-router discovery and likely explain why no routers were registered:
|
|
4710
|
+
${formatted}`;
|
|
4711
|
+
}
|
|
4712
|
+
function toCause(errors) {
|
|
4713
|
+
if (errors.length === 0) return void 0;
|
|
4714
|
+
if (errors.length === 1) return errors[0].error;
|
|
4715
|
+
return new AggregateError(
|
|
4716
|
+
errors.map((e) => e.error),
|
|
4717
|
+
"Multiple host-router handlers failed during discovery"
|
|
4718
|
+
);
|
|
4719
|
+
}
|
|
4720
|
+
var DiscoveryError = class _DiscoveryError extends Error {
|
|
4721
|
+
constructor(entryPath, caught) {
|
|
4722
|
+
super(formatNoRoutersError(entryPath, caught));
|
|
4723
|
+
const cause = toCause(caught);
|
|
4724
|
+
if (cause !== void 0) {
|
|
4725
|
+
this.cause = cause;
|
|
4726
|
+
}
|
|
4727
|
+
this.name = "DiscoveryError";
|
|
4728
|
+
this.entryPath = entryPath;
|
|
4729
|
+
this.caught = caught;
|
|
4730
|
+
Object.setPrototypeOf(this, _DiscoveryError.prototype);
|
|
4731
|
+
}
|
|
4732
|
+
};
|
|
4733
|
+
|
|
4421
4734
|
// src/vite/discovery/discover-routers.ts
|
|
4422
4735
|
var debug10 = createRangoDebugger(NS.discovery);
|
|
4423
4736
|
async function discoverRouters(state, rscEnv) {
|
|
@@ -4434,27 +4747,17 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4434
4747
|
);
|
|
4435
4748
|
let registry = serverMod.RouterRegistry;
|
|
4436
4749
|
if (!registry || registry.size === 0) {
|
|
4750
|
+
const discoveryErrors = [];
|
|
4437
4751
|
try {
|
|
4438
4752
|
const hostRegistry = serverMod.HostRouterRegistry;
|
|
4439
4753
|
if (hostRegistry && hostRegistry.size > 0) {
|
|
4440
4754
|
console.log(
|
|
4441
|
-
`[
|
|
4755
|
+
`[rango] Found ${hostRegistry.size} host router(s), resolving lazy handlers...`
|
|
4442
4756
|
);
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
await route.handler();
|
|
4448
|
-
} catch {
|
|
4449
|
-
}
|
|
4450
|
-
}
|
|
4451
|
-
}
|
|
4452
|
-
if (entry.fallback && typeof entry.fallback.handler === "function") {
|
|
4453
|
-
try {
|
|
4454
|
-
await entry.fallback.handler();
|
|
4455
|
-
} catch {
|
|
4456
|
-
}
|
|
4457
|
-
}
|
|
4757
|
+
const handlerErrors = await resolveHostRouterHandlers(hostRegistry);
|
|
4758
|
+
discoveryErrors.push(...handlerErrors);
|
|
4759
|
+
for (const { context, error } of handlerErrors) {
|
|
4760
|
+
debug10?.("caught error while resolving %s: %O", context, error);
|
|
4458
4761
|
}
|
|
4459
4762
|
const freshServerMod = await rscEnv.runner.import(
|
|
4460
4763
|
"@rangojs/router/server"
|
|
@@ -4465,12 +4768,11 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4465
4768
|
registry = freshRegistry;
|
|
4466
4769
|
}
|
|
4467
4770
|
}
|
|
4468
|
-
} catch {
|
|
4771
|
+
} catch (error) {
|
|
4772
|
+
discoveryErrors.push({ context: "host-router discovery", error });
|
|
4469
4773
|
}
|
|
4470
4774
|
if (!registry || registry.size === 0) {
|
|
4471
|
-
throw new
|
|
4472
|
-
`[rsc-router] No routers found in registry after importing ${state.resolvedEntryPath}`
|
|
4473
|
-
);
|
|
4775
|
+
throw new DiscoveryError(state.resolvedEntryPath, discoveryErrors);
|
|
4474
4776
|
}
|
|
4475
4777
|
}
|
|
4476
4778
|
const buildMod = await timed(
|
|
@@ -4498,6 +4800,15 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4498
4800
|
let mergedRouteTrailingSlash = {};
|
|
4499
4801
|
let routerMountIndex = 0;
|
|
4500
4802
|
const allManifests = [];
|
|
4803
|
+
const clientChunkCtx = state.opts?.clientChunkCtx;
|
|
4804
|
+
const collectClientFallbackRef = clientChunkCtx ? (refKey) => clientChunkCtx.fallbackRefs.add(
|
|
4805
|
+
computeProductionHash(state.projectRoot, refKey)
|
|
4806
|
+
) : void 0;
|
|
4807
|
+
const collectFromBoundaryNode = (node) => {
|
|
4808
|
+
if (collectClientFallbackRef && buildMod.collectFallbackClientRefs) {
|
|
4809
|
+
buildMod.collectFallbackClientRefs(node, collectClientFallbackRef);
|
|
4810
|
+
}
|
|
4811
|
+
};
|
|
4501
4812
|
const manifestGenStart = debug10 ? performance.now() : 0;
|
|
4502
4813
|
for (const [id, router] of registry) {
|
|
4503
4814
|
if (!router.urlpatterns || !generateManifestFull) {
|
|
@@ -4506,10 +4817,18 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4506
4817
|
const manifest = generateManifestFull(
|
|
4507
4818
|
router.urlpatterns,
|
|
4508
4819
|
routerMountIndex,
|
|
4509
|
-
|
|
4820
|
+
{
|
|
4821
|
+
...router.__basename ? { urlPrefix: router.__basename } : {},
|
|
4822
|
+
...collectClientFallbackRef ? { collectClientFallbackRef } : {}
|
|
4823
|
+
}
|
|
4510
4824
|
);
|
|
4511
4825
|
routerMountIndex++;
|
|
4512
4826
|
allManifests.push({ id, manifest });
|
|
4827
|
+
if (collectClientFallbackRef) {
|
|
4828
|
+
collectFromBoundaryNode(router.__defaultErrorBoundary);
|
|
4829
|
+
collectFromBoundaryNode(router.__defaultNotFoundBoundary);
|
|
4830
|
+
collectFromBoundaryNode(router.__notFound);
|
|
4831
|
+
}
|
|
4513
4832
|
const routeCount = Object.keys(manifest.routeManifest).length;
|
|
4514
4833
|
const staticRoutes = Object.values(manifest.routeManifest).filter(
|
|
4515
4834
|
(p) => !p.includes(":") && !p.includes("*")
|
|
@@ -4560,7 +4879,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4560
4879
|
);
|
|
4561
4880
|
newPerRouterPrecomputedMap.set(id, routerPrecomputed);
|
|
4562
4881
|
console.log(
|
|
4563
|
-
`[
|
|
4882
|
+
`[rango] Router "${id}" -> ${routeCount} routes (${staticRoutes} static, ${dynamicRoutes} dynamic)`
|
|
4564
4883
|
);
|
|
4565
4884
|
}
|
|
4566
4885
|
if (registry.size > 1) {
|
|
@@ -4569,7 +4888,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4569
4888
|
);
|
|
4570
4889
|
if (autoIds.length > 1) {
|
|
4571
4890
|
console.warn(
|
|
4572
|
-
`[
|
|
4891
|
+
`[rango] WARNING: ${autoIds.length} routers use auto-generated IDs (${autoIds.join(", ")}). In multi-router setups, each createRouter() must have an explicit \`id\` option to ensure per-router manifest data is matched correctly at runtime. Example: createRouter({ id: "site", ... })`
|
|
4573
4892
|
);
|
|
4574
4893
|
}
|
|
4575
4894
|
}
|
|
@@ -4614,31 +4933,17 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4614
4933
|
newMergedRouteManifest,
|
|
4615
4934
|
mergedRouteAncestry,
|
|
4616
4935
|
routeToStaticPrefix,
|
|
4617
|
-
|
|
4618
|
-
prerenderRouteNames
|
|
4619
|
-
passthroughRouteNames
|
|
4620
|
-
|
|
4936
|
+
mergedRouteTrailingSlash,
|
|
4937
|
+
prerenderRouteNames,
|
|
4938
|
+
passthroughRouteNames,
|
|
4939
|
+
mergedResponseTypeRoutes
|
|
4621
4940
|
);
|
|
4941
|
+
const buildPerRouterTrie = buildMod.buildPerRouterTrie;
|
|
4622
4942
|
for (const { id, manifest } of allManifests) {
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
for (const name of Object.keys(manifest.routeManifest)) {
|
|
4627
|
-
perRouterStaticPrefix[name] = "";
|
|
4943
|
+
const perRouterTrie = buildPerRouterTrie ? buildPerRouterTrie(manifest) : null;
|
|
4944
|
+
if (perRouterTrie) {
|
|
4945
|
+
newPerRouterTrieMap.set(id, perRouterTrie);
|
|
4628
4946
|
}
|
|
4629
|
-
buildRouteToStaticPrefix(manifest.prefixTree, perRouterStaticPrefix);
|
|
4630
|
-
const perRouterPrerenderNames = manifest.prerenderRoutes ? new Set(manifest.prerenderRoutes) : void 0;
|
|
4631
|
-
const perRouterPassthroughNames = manifest.passthroughRoutes ? new Set(manifest.passthroughRoutes) : void 0;
|
|
4632
|
-
const perRouterTrie = buildRouteTrie(
|
|
4633
|
-
manifest.routeManifest,
|
|
4634
|
-
manifest._routeAncestry,
|
|
4635
|
-
perRouterStaticPrefix,
|
|
4636
|
-
manifest.routeTrailingSlash && Object.keys(manifest.routeTrailingSlash).length > 0 ? manifest.routeTrailingSlash : void 0,
|
|
4637
|
-
perRouterPrerenderNames && perRouterPrerenderNames.size > 0 ? perRouterPrerenderNames : void 0,
|
|
4638
|
-
perRouterPassthroughNames && perRouterPassthroughNames.size > 0 ? perRouterPassthroughNames : void 0,
|
|
4639
|
-
manifest.responseTypeRoutes && Object.keys(manifest.responseTypeRoutes).length > 0 ? manifest.responseTypeRoutes : void 0
|
|
4640
|
-
);
|
|
4641
|
-
newPerRouterTrieMap.set(id, perRouterTrie);
|
|
4642
4947
|
}
|
|
4643
4948
|
}
|
|
4644
4949
|
}
|
|
@@ -4659,7 +4964,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4659
4964
|
}
|
|
4660
4965
|
|
|
4661
4966
|
// src/vite/discovery/route-types-writer.ts
|
|
4662
|
-
import { dirname as dirname3,
|
|
4967
|
+
import { dirname as dirname3, join as join2, resolve as resolve6 } from "node:path";
|
|
4663
4968
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "node:fs";
|
|
4664
4969
|
function filterUserNamedRoutes(manifest) {
|
|
4665
4970
|
const filtered = {};
|
|
@@ -4670,39 +4975,20 @@ function filterUserNamedRoutes(manifest) {
|
|
|
4670
4975
|
}
|
|
4671
4976
|
return filtered;
|
|
4672
4977
|
}
|
|
4978
|
+
function writeGenFileIfChanged(state, outPath, source, opts) {
|
|
4979
|
+
const existing = existsSync5(outPath) ? readFileSync4(outPath, "utf-8") : null;
|
|
4980
|
+
if (existing === source) return;
|
|
4981
|
+
markSelfGenWrite(state, outPath, source);
|
|
4982
|
+
writeFileSync3(outPath, source);
|
|
4983
|
+
if (opts?.log) console.log(`[rango] Generated route types -> ${outPath}`);
|
|
4984
|
+
}
|
|
4673
4985
|
function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
4674
4986
|
const routerFiles = state.cachedRouterFiles ?? findRouterFiles(state.projectRoot, state.scanFilter);
|
|
4675
4987
|
state.cachedRouterFiles = routerFiles;
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
/\.(tsx?|jsx?)$/,
|
|
4681
|
-
""
|
|
4682
|
-
);
|
|
4683
|
-
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4684
|
-
try {
|
|
4685
|
-
preContent.set(outPath, readFileSync4(outPath, "utf-8"));
|
|
4686
|
-
} catch {
|
|
4687
|
-
}
|
|
4688
|
-
}
|
|
4689
|
-
writeCombinedRouteTypes(state.projectRoot, routerFiles, opts);
|
|
4690
|
-
for (const routerFilePath of routerFiles) {
|
|
4691
|
-
const routerDir = dirname3(routerFilePath);
|
|
4692
|
-
const routerBasename = basename(routerFilePath).replace(
|
|
4693
|
-
/\.(tsx?|jsx?)$/,
|
|
4694
|
-
""
|
|
4695
|
-
);
|
|
4696
|
-
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4697
|
-
if (!existsSync5(outPath)) continue;
|
|
4698
|
-
try {
|
|
4699
|
-
const content = readFileSync4(outPath, "utf-8");
|
|
4700
|
-
if (content !== preContent.get(outPath)) {
|
|
4701
|
-
markSelfGenWrite(state, outPath, content);
|
|
4702
|
-
}
|
|
4703
|
-
} catch {
|
|
4704
|
-
}
|
|
4705
|
-
}
|
|
4988
|
+
writeCombinedRouteTypes(state.projectRoot, routerFiles, {
|
|
4989
|
+
...opts,
|
|
4990
|
+
onWrite: (outPath, content) => markSelfGenWrite(state, outPath, content)
|
|
4991
|
+
});
|
|
4706
4992
|
}
|
|
4707
4993
|
function writeRouteTypesFiles(state) {
|
|
4708
4994
|
if (state.perRouterManifests.length === 0) return;
|
|
@@ -4714,7 +5000,7 @@ function writeRouteTypesFiles(state) {
|
|
|
4714
5000
|
if (existsSync5(oldCombinedPath)) {
|
|
4715
5001
|
unlinkSync2(oldCombinedPath);
|
|
4716
5002
|
console.log(
|
|
4717
|
-
`[
|
|
5003
|
+
`[rango] Removed stale combined route types: ${oldCombinedPath}`
|
|
4718
5004
|
);
|
|
4719
5005
|
}
|
|
4720
5006
|
} catch {
|
|
@@ -4728,39 +5014,23 @@ function writeRouteTypesFiles(state) {
|
|
|
4728
5014
|
if (!sourceFile) continue;
|
|
4729
5015
|
if (sourceFile.includes("node_modules")) {
|
|
4730
5016
|
throw new Error(
|
|
4731
|
-
`[
|
|
5017
|
+
`[rango] Router "${id}" has sourceFile inside node_modules: ${sourceFile}
|
|
4732
5018
|
This means createRouter() stack trace parsing matched a Vite internal frame.
|
|
4733
5019
|
Set an explicit \`id\` on createRouter() or check the call site.`
|
|
4734
5020
|
);
|
|
4735
5021
|
}
|
|
4736
|
-
const
|
|
4737
|
-
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4738
|
-
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
5022
|
+
const outPath = genFileTsPath(sourceFile);
|
|
4739
5023
|
const userRoutes = filterUserNamedRoutes(routeManifest);
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
for (const name of Object.keys(userRoutes)) {
|
|
4746
|
-
const schema = staticParsed.searchSchemas[name];
|
|
4747
|
-
if (schema) filtered[name] = schema;
|
|
4748
|
-
}
|
|
4749
|
-
if (Object.keys(filtered).length > 0) {
|
|
4750
|
-
effectiveSearchSchemas = filtered;
|
|
4751
|
-
}
|
|
4752
|
-
}
|
|
4753
|
-
}
|
|
5024
|
+
const effectiveSearchSchemas = resolveSearchSchemas(
|
|
5025
|
+
Object.keys(userRoutes),
|
|
5026
|
+
routeSearchSchemas,
|
|
5027
|
+
sourceFile
|
|
5028
|
+
);
|
|
4754
5029
|
const source = generateRouteTypesSource(
|
|
4755
5030
|
userRoutes,
|
|
4756
5031
|
effectiveSearchSchemas && Object.keys(effectiveSearchSchemas).length > 0 ? effectiveSearchSchemas : void 0
|
|
4757
5032
|
);
|
|
4758
|
-
|
|
4759
|
-
if (existing !== source) {
|
|
4760
|
-
markSelfGenWrite(state, outPath, source);
|
|
4761
|
-
writeFileSync3(outPath, source);
|
|
4762
|
-
console.log(`[rsc-router] Generated route types -> ${outPath}`);
|
|
4763
|
-
}
|
|
5033
|
+
writeGenFileIfChanged(state, outPath, source, { log: true });
|
|
4764
5034
|
}
|
|
4765
5035
|
}
|
|
4766
5036
|
function supplementGenFilesWithRuntimeRoutes(state) {
|
|
@@ -4798,23 +5068,17 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
4798
5068
|
}
|
|
4799
5069
|
}
|
|
4800
5070
|
}
|
|
4801
|
-
const
|
|
4802
|
-
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4803
|
-
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
5071
|
+
const outPath = genFileTsPath(sourceFile);
|
|
4804
5072
|
const source = generateRouteTypesSource(
|
|
4805
5073
|
mergedRoutes,
|
|
4806
5074
|
Object.keys(mergedSearchSchemas).length > 0 ? mergedSearchSchemas : void 0
|
|
4807
5075
|
);
|
|
4808
|
-
|
|
4809
|
-
if (existing !== source) {
|
|
4810
|
-
markSelfGenWrite(state, outPath, source);
|
|
4811
|
-
writeFileSync3(outPath, source);
|
|
4812
|
-
}
|
|
5076
|
+
writeGenFileIfChanged(state, outPath, source);
|
|
4813
5077
|
}
|
|
4814
5078
|
}
|
|
4815
5079
|
|
|
4816
5080
|
// src/vite/discovery/virtual-module-codegen.ts
|
|
4817
|
-
import { dirname as dirname4, basename
|
|
5081
|
+
import { dirname as dirname4, basename, join as join3 } from "node:path";
|
|
4818
5082
|
function generateRoutesManifestModule(state) {
|
|
4819
5083
|
const hasManifest = state.mergedRouteManifest && Object.keys(state.mergedRouteManifest).length > 0;
|
|
4820
5084
|
if (hasManifest) {
|
|
@@ -4825,7 +5089,7 @@ function generateRoutesManifestModule(state) {
|
|
|
4825
5089
|
for (const entry of state.perRouterManifests) {
|
|
4826
5090
|
if (entry.sourceFile) {
|
|
4827
5091
|
const routerDir = dirname4(entry.sourceFile);
|
|
4828
|
-
const routerBasename =
|
|
5092
|
+
const routerBasename = basename(entry.sourceFile).replace(
|
|
4829
5093
|
/\.(tsx?|jsx?)$/,
|
|
4830
5094
|
""
|
|
4831
5095
|
);
|
|
@@ -4846,7 +5110,7 @@ function generateRoutesManifestModule(state) {
|
|
|
4846
5110
|
}
|
|
4847
5111
|
}
|
|
4848
5112
|
const lines = [
|
|
4849
|
-
`import { setCachedManifest,
|
|
5113
|
+
`import { setCachedManifest, setRouterManifest, registerRouterManifestLoader, clearAllRouterData } from "@rangojs/router/server";`,
|
|
4850
5114
|
...genFileImports,
|
|
4851
5115
|
// Clear stale per-router cached data (manifest, trie, precomputed entries)
|
|
4852
5116
|
// before re-populating. In Cloudflare dev mode, program reloads re-evaluate
|
|
@@ -4882,18 +5146,6 @@ function generateRoutesManifestModule(state) {
|
|
|
4882
5146
|
);
|
|
4883
5147
|
}
|
|
4884
5148
|
}
|
|
4885
|
-
if (state.isBuildMode) {
|
|
4886
|
-
if (state.mergedPrecomputedEntries && state.mergedPrecomputedEntries.length > 0) {
|
|
4887
|
-
lines.push(
|
|
4888
|
-
`setPrecomputedEntries(${jsonParseExpression(state.mergedPrecomputedEntries)});`
|
|
4889
|
-
);
|
|
4890
|
-
}
|
|
4891
|
-
if (state.mergedRouteTrie) {
|
|
4892
|
-
lines.push(
|
|
4893
|
-
`setRouteTrie(${jsonParseExpression(state.mergedRouteTrie)});`
|
|
4894
|
-
);
|
|
4895
|
-
}
|
|
4896
|
-
}
|
|
4897
5149
|
for (const routerId of state.perRouterManifestDataMap.keys()) {
|
|
4898
5150
|
lines.push(
|
|
4899
5151
|
`registerRouterManifestLoader(${JSON.stringify(routerId)}, () => import(${JSON.stringify(VIRTUAL_ROUTES_MANIFEST_ID + "/" + routerId)}));`
|
|
@@ -4922,7 +5174,7 @@ function generatePerRouterModule(state, routerId) {
|
|
|
4922
5174
|
const lines = [];
|
|
4923
5175
|
if (routerEntry?.sourceFile) {
|
|
4924
5176
|
const routerDir = dirname4(routerEntry.sourceFile);
|
|
4925
|
-
const routerBasename =
|
|
5177
|
+
const routerBasename = basename(routerEntry.sourceFile).replace(
|
|
4926
5178
|
/\.(tsx?|jsx?)$/,
|
|
4927
5179
|
""
|
|
4928
5180
|
);
|
|
@@ -4993,12 +5245,12 @@ function postprocessBundle(state) {
|
|
|
4993
5245
|
writeFileSync4(chunkPath, result.code);
|
|
4994
5246
|
const savedKB = (result.savedBytes / 1024).toFixed(1);
|
|
4995
5247
|
console.log(
|
|
4996
|
-
`[
|
|
5248
|
+
`[rango] Evicted ${target.label} (${savedKB} KB saved): ${info.fileName}`
|
|
4997
5249
|
);
|
|
4998
5250
|
}
|
|
4999
5251
|
} catch (replaceErr) {
|
|
5000
5252
|
console.warn(
|
|
5001
|
-
`[
|
|
5253
|
+
`[rango] Failed to evict ${target.label}: ${replaceErr.message}`
|
|
5002
5254
|
);
|
|
5003
5255
|
}
|
|
5004
5256
|
}
|
|
@@ -5036,11 +5288,11 @@ function postprocessBundle(state) {
|
|
|
5036
5288
|
writeFileSync4(rscEntryPath, injection + rscCode);
|
|
5037
5289
|
const totalKB = (totalBytes / 1024).toFixed(1);
|
|
5038
5290
|
console.log(
|
|
5039
|
-
`[
|
|
5291
|
+
`[rango] Wrote prerender assets (${totalKB} KB total, ${Object.keys(state.prerenderManifestEntries).length} entries)`
|
|
5040
5292
|
);
|
|
5041
5293
|
} catch (err) {
|
|
5042
5294
|
throw new Error(
|
|
5043
|
-
`[
|
|
5295
|
+
`[rango] Failed to write prerender assets: ${err.message}`
|
|
5044
5296
|
);
|
|
5045
5297
|
}
|
|
5046
5298
|
}
|
|
@@ -5074,11 +5326,11 @@ function postprocessBundle(state) {
|
|
|
5074
5326
|
writeFileSync4(rscEntryPath, injection + rscCode);
|
|
5075
5327
|
const totalKB = (totalBytes / 1024).toFixed(1);
|
|
5076
5328
|
console.log(
|
|
5077
|
-
`[
|
|
5329
|
+
`[rango] Wrote static assets (${totalKB} KB total, ${Object.keys(state.staticManifestEntries).length} entries)`
|
|
5078
5330
|
);
|
|
5079
5331
|
} catch (err) {
|
|
5080
5332
|
throw new Error(
|
|
5081
|
-
`[
|
|
5333
|
+
`[rango] Failed to write static assets: ${err.message}`
|
|
5082
5334
|
);
|
|
5083
5335
|
}
|
|
5084
5336
|
}
|
|
@@ -5159,6 +5411,57 @@ function createDiscoveryGate(s, debug11) {
|
|
|
5159
5411
|
};
|
|
5160
5412
|
}
|
|
5161
5413
|
|
|
5414
|
+
// src/vite/utils/forward-user-plugins.ts
|
|
5415
|
+
function isDenied(name) {
|
|
5416
|
+
return name.startsWith("vite:") || name === "rsc" || name.startsWith("rsc:") || name.startsWith("@rangojs/router") || name.startsWith("@cloudflare/vite-plugin") || name.startsWith("vite-plugin-cloudflare");
|
|
5417
|
+
}
|
|
5418
|
+
function hasResolutionHooks(p) {
|
|
5419
|
+
return Boolean(p.resolveId || p.load);
|
|
5420
|
+
}
|
|
5421
|
+
function stripToResolutionHooks(p) {
|
|
5422
|
+
const stripped = { name: p.name };
|
|
5423
|
+
if (p.enforce) stripped.enforce = p.enforce;
|
|
5424
|
+
if (p.applyToEnvironment)
|
|
5425
|
+
stripped.applyToEnvironment = p.applyToEnvironment;
|
|
5426
|
+
if (p.resolveId) stripped.resolveId = p.resolveId;
|
|
5427
|
+
if (p.load) stripped.load = p.load;
|
|
5428
|
+
return stripped;
|
|
5429
|
+
}
|
|
5430
|
+
function selectForwardableResolvePlugins(plugins) {
|
|
5431
|
+
if (!plugins) return [];
|
|
5432
|
+
const forwarded = [];
|
|
5433
|
+
for (const p of plugins) {
|
|
5434
|
+
const name = p?.name;
|
|
5435
|
+
if (!name || isDenied(name)) continue;
|
|
5436
|
+
if (!hasResolutionHooks(p)) continue;
|
|
5437
|
+
forwarded.push(stripToResolutionHooks(p));
|
|
5438
|
+
}
|
|
5439
|
+
return forwarded;
|
|
5440
|
+
}
|
|
5441
|
+
function pickForwardedRunnerConfig(config) {
|
|
5442
|
+
const r = config.resolve ?? {};
|
|
5443
|
+
const resolve10 = {};
|
|
5444
|
+
if (r.alias !== void 0) resolve10.alias = r.alias;
|
|
5445
|
+
if (r.dedupe !== void 0) resolve10.dedupe = r.dedupe;
|
|
5446
|
+
if (r.conditions !== void 0) resolve10.conditions = r.conditions;
|
|
5447
|
+
if (r.mainFields !== void 0) resolve10.mainFields = r.mainFields;
|
|
5448
|
+
if (r.extensions !== void 0) resolve10.extensions = r.extensions;
|
|
5449
|
+
if (r.preserveSymlinks !== void 0)
|
|
5450
|
+
resolve10.preserveSymlinks = r.preserveSymlinks;
|
|
5451
|
+
if (r.tsconfigPaths !== void 0) resolve10.tsconfigPaths = r.tsconfigPaths;
|
|
5452
|
+
const userOxc = config.oxc;
|
|
5453
|
+
const userJsx = userOxc && typeof userOxc === "object" && typeof userOxc.jsx === "object" && userOxc.jsx !== null ? userOxc.jsx : {};
|
|
5454
|
+
const oxc = userOxc && typeof userOxc === "object" ? {
|
|
5455
|
+
...userOxc,
|
|
5456
|
+
jsx: { ...userJsx, runtime: "automatic", importSource: "react" }
|
|
5457
|
+
} : { jsx: { runtime: "automatic", importSource: "react" } };
|
|
5458
|
+
return {
|
|
5459
|
+
resolve: resolve10,
|
|
5460
|
+
define: config.define,
|
|
5461
|
+
oxc
|
|
5462
|
+
};
|
|
5463
|
+
}
|
|
5464
|
+
|
|
5162
5465
|
// src/vite/router-discovery.ts
|
|
5163
5466
|
var debugDiscovery = createRangoDebugger(NS.discovery);
|
|
5164
5467
|
var debugRoutes = createRangoDebugger(NS.routes);
|
|
@@ -5174,21 +5477,29 @@ function ensureCloudflareProtocolLoaderRegistered() {
|
|
|
5174
5477
|
);
|
|
5175
5478
|
} catch (err) {
|
|
5176
5479
|
console.warn(
|
|
5177
|
-
`[
|
|
5480
|
+
`[rango] Could not register Node ESM loader hook for cloudflare:* imports (${err?.message ?? err}). Falling back to Vite transform only.`
|
|
5178
5481
|
);
|
|
5179
5482
|
}
|
|
5180
5483
|
}
|
|
5181
5484
|
async function createTempRscServer(state, options = {}) {
|
|
5182
5485
|
ensureCloudflareProtocolLoaderRegistered();
|
|
5183
5486
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
5487
|
+
const runnerConfig = state.userRunnerConfig;
|
|
5488
|
+
const resolveConfig = runnerConfig?.resolve ?? {
|
|
5489
|
+
alias: state.userResolveAlias
|
|
5490
|
+
};
|
|
5491
|
+
const oxcConfig = runnerConfig?.oxc ?? {
|
|
5492
|
+
jsx: { runtime: "automatic", importSource: "react" }
|
|
5493
|
+
};
|
|
5184
5494
|
return createViteServer({
|
|
5185
5495
|
root: state.projectRoot,
|
|
5186
5496
|
configFile: false,
|
|
5187
5497
|
server: { middlewareMode: true },
|
|
5188
5498
|
appType: "custom",
|
|
5189
5499
|
logLevel: "silent",
|
|
5190
|
-
resolve:
|
|
5191
|
-
|
|
5500
|
+
resolve: resolveConfig,
|
|
5501
|
+
...runnerConfig?.define ? { define: runnerConfig.define } : {},
|
|
5502
|
+
oxc: oxcConfig,
|
|
5192
5503
|
...options.cacheDir && { cacheDir: options.cacheDir },
|
|
5193
5504
|
plugins: [
|
|
5194
5505
|
rsc({
|
|
@@ -5206,7 +5517,11 @@ async function createTempRscServer(state, options = {}) {
|
|
|
5206
5517
|
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
5207
5518
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
5208
5519
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : void 0),
|
|
5209
|
-
exposeRouterId()
|
|
5520
|
+
exposeRouterId(),
|
|
5521
|
+
// Forwarded user resolution plugins (e.g. vite-tsconfig-paths). Stripped
|
|
5522
|
+
// to resolveId/load and placed last so framework resolution runs first;
|
|
5523
|
+
// Vite re-sorts by `enforce`, so `enforce: "pre"` resolvers still lead.
|
|
5524
|
+
...state.userResolvePlugins
|
|
5210
5525
|
]
|
|
5211
5526
|
});
|
|
5212
5527
|
}
|
|
@@ -5215,7 +5530,7 @@ async function resolveBuildEnv(option, factoryCtx) {
|
|
|
5215
5530
|
if (option === "auto") {
|
|
5216
5531
|
if (factoryCtx.preset !== "cloudflare") {
|
|
5217
5532
|
throw new Error(
|
|
5218
|
-
'[
|
|
5533
|
+
'[rango] buildEnv: "auto" is only supported with preset: "cloudflare". Use a factory function or plain object for other presets.'
|
|
5219
5534
|
);
|
|
5220
5535
|
}
|
|
5221
5536
|
try {
|
|
@@ -5231,7 +5546,7 @@ async function resolveBuildEnv(option, factoryCtx) {
|
|
|
5231
5546
|
};
|
|
5232
5547
|
} catch (err) {
|
|
5233
5548
|
throw new Error(
|
|
5234
|
-
`[
|
|
5549
|
+
`[rango] buildEnv: "auto" requires wrangler to be installed.
|
|
5235
5550
|
Install it with: pnpm add -D wrangler
|
|
5236
5551
|
${err.message}`
|
|
5237
5552
|
);
|
|
@@ -5262,7 +5577,7 @@ async function releaseBuildEnv(s) {
|
|
|
5262
5577
|
try {
|
|
5263
5578
|
await s.buildEnvDispose();
|
|
5264
5579
|
} catch (err) {
|
|
5265
|
-
console.warn(`[
|
|
5580
|
+
console.warn(`[rango] buildEnv dispose failed: ${err.message}`);
|
|
5266
5581
|
}
|
|
5267
5582
|
s.buildEnvDispose = null;
|
|
5268
5583
|
}
|
|
@@ -5289,17 +5604,16 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
5289
5604
|
viteCommand = config.command;
|
|
5290
5605
|
viteMode = config.mode;
|
|
5291
5606
|
s.userResolveAlias = config.resolve.alias;
|
|
5607
|
+
s.userRunnerConfig = pickForwardedRunnerConfig(config);
|
|
5608
|
+
s.userResolvePlugins = selectForwardableResolvePlugins(
|
|
5609
|
+
config.plugins
|
|
5610
|
+
);
|
|
5292
5611
|
if (!s.resolvedEntryPath && opts?.routerPathRef?.path) {
|
|
5293
5612
|
s.resolvedEntryPath = opts.routerPathRef.path;
|
|
5294
5613
|
}
|
|
5295
5614
|
if (!s.resolvedEntryPath) {
|
|
5296
|
-
const
|
|
5297
|
-
|
|
5298
|
-
if (typeof entries === "string") {
|
|
5299
|
-
s.resolvedEntryPath = entries;
|
|
5300
|
-
} else if (Array.isArray(entries) && entries.length > 0) {
|
|
5301
|
-
s.resolvedEntryPath = entries[0];
|
|
5302
|
-
}
|
|
5615
|
+
const entry = resolveRscEntryFromConfig(config);
|
|
5616
|
+
if (entry) s.resolvedEntryPath = entry;
|
|
5303
5617
|
}
|
|
5304
5618
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
5305
5619
|
s.cachedRouterFiles = findRouterFiles(s.projectRoot, s.scanFilter);
|
|
@@ -5426,9 +5740,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
5426
5740
|
"getOrCreateTempServer: FAILED message=%s",
|
|
5427
5741
|
err.message
|
|
5428
5742
|
);
|
|
5429
|
-
console.warn(
|
|
5430
|
-
`[rsc-router] Failed to create temp runner: ${err.message}`
|
|
5431
|
-
);
|
|
5743
|
+
console.warn(`[rango] Failed to create temp runner: ${err.message}`);
|
|
5432
5744
|
}
|
|
5433
5745
|
return null;
|
|
5434
5746
|
}
|
|
@@ -5515,7 +5827,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
5515
5827
|
}
|
|
5516
5828
|
} catch (err) {
|
|
5517
5829
|
console.warn(
|
|
5518
|
-
`[
|
|
5830
|
+
`[rango] Cloudflare dev discovery failed: ${err.message}
|
|
5519
5831
|
${err.stack}`
|
|
5520
5832
|
);
|
|
5521
5833
|
}
|
|
@@ -5559,7 +5871,7 @@ ${err.stack}`
|
|
|
5559
5871
|
);
|
|
5560
5872
|
} catch (err) {
|
|
5561
5873
|
console.warn(
|
|
5562
|
-
`[
|
|
5874
|
+
`[rango] Router discovery failed: ${err.message}
|
|
5563
5875
|
${err.stack}`
|
|
5564
5876
|
);
|
|
5565
5877
|
} finally {
|
|
@@ -5592,20 +5904,15 @@ ${err.stack}`
|
|
|
5592
5904
|
if (s.mergedRouteTrie && serverMod.setRouteTrie) {
|
|
5593
5905
|
serverMod.setRouteTrie(s.mergedRouteTrie);
|
|
5594
5906
|
}
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
}
|
|
5605
|
-
if (serverMod.setRouterPrecomputedEntries) {
|
|
5606
|
-
for (const [routerId, entries] of s.perRouterPrecomputedMap) {
|
|
5607
|
-
serverMod.setRouterPrecomputedEntries(routerId, entries);
|
|
5608
|
-
}
|
|
5907
|
+
const perRouterSetters = [
|
|
5908
|
+
[s.perRouterManifestDataMap, "setRouterManifest"],
|
|
5909
|
+
[s.perRouterTrieMap, "setRouterTrie"],
|
|
5910
|
+
[s.perRouterPrecomputedMap, "setRouterPrecomputedEntries"]
|
|
5911
|
+
];
|
|
5912
|
+
for (const [map, fn] of perRouterSetters) {
|
|
5913
|
+
const setter = serverMod[fn];
|
|
5914
|
+
if (typeof setter !== "function") continue;
|
|
5915
|
+
for (const [routerId, value] of map) setter(routerId, value);
|
|
5609
5916
|
}
|
|
5610
5917
|
};
|
|
5611
5918
|
server.middlewares.use("/__rsc_prerender", async (req, res) => {
|
|
@@ -5639,7 +5946,7 @@ ${err.stack}`
|
|
|
5639
5946
|
registry = serverMod.RouterRegistry ?? null;
|
|
5640
5947
|
} catch (err) {
|
|
5641
5948
|
console.warn(
|
|
5642
|
-
`[
|
|
5949
|
+
`[rango] Dev prerender module refresh failed: ${err.message}`
|
|
5643
5950
|
);
|
|
5644
5951
|
res.statusCode = 500;
|
|
5645
5952
|
res.end(`Prerender handler error: ${err.message}`);
|
|
@@ -5697,7 +6004,7 @@ ${err.stack}`
|
|
|
5697
6004
|
return;
|
|
5698
6005
|
} catch (err) {
|
|
5699
6006
|
console.warn(
|
|
5700
|
-
`[
|
|
6007
|
+
`[rango] Dev prerender failed for ${pathname}: ${err.message}`
|
|
5701
6008
|
);
|
|
5702
6009
|
}
|
|
5703
6010
|
}
|
|
@@ -5768,9 +6075,25 @@ ${err.stack}`
|
|
|
5768
6075
|
() => writeRouteTypesFiles(s)
|
|
5769
6076
|
);
|
|
5770
6077
|
}
|
|
6078
|
+
if (s.lastDiscoveryError) {
|
|
6079
|
+
debugDiscovery?.(
|
|
6080
|
+
"hmr: cleared lastDiscoveryError (%s) after successful rediscovery",
|
|
6081
|
+
s.lastDiscoveryError.message
|
|
6082
|
+
);
|
|
6083
|
+
s.lastDiscoveryError = null;
|
|
6084
|
+
}
|
|
6085
|
+
if (rscEnv && !rscEnv.runner) forceCloudflareWorkerReload(rscEnv);
|
|
5771
6086
|
} catch (err) {
|
|
6087
|
+
s.lastDiscoveryError = {
|
|
6088
|
+
message: err?.message ?? String(err),
|
|
6089
|
+
at: Date.now()
|
|
6090
|
+
};
|
|
5772
6091
|
console.warn(
|
|
5773
|
-
`[
|
|
6092
|
+
`[rango] Runtime re-discovery failed: ${err.message}`
|
|
6093
|
+
);
|
|
6094
|
+
debugDiscovery?.(
|
|
6095
|
+
"hmr: lastDiscoveryError set (%s) \u2014 manifest preserved at last-good; recovery mode active (any in-scan source change will trigger rediscovery)",
|
|
6096
|
+
err?.message
|
|
5774
6097
|
);
|
|
5775
6098
|
} finally {
|
|
5776
6099
|
debugDiscovery?.(
|
|
@@ -5780,6 +6103,25 @@ ${err.stack}`
|
|
|
5780
6103
|
}
|
|
5781
6104
|
});
|
|
5782
6105
|
};
|
|
6106
|
+
const forceCloudflareWorkerReload = (rscEnv) => {
|
|
6107
|
+
if (!rscEnv?.hot) return;
|
|
6108
|
+
try {
|
|
6109
|
+
const graph = rscEnv.moduleGraph;
|
|
6110
|
+
if (graph?.invalidateAll) {
|
|
6111
|
+
graph.invalidateAll();
|
|
6112
|
+
debugDiscovery?.("hmr: invalidated workerd rsc module graph");
|
|
6113
|
+
}
|
|
6114
|
+
rscEnv.hot.send({ type: "full-reload" });
|
|
6115
|
+
debugDiscovery?.(
|
|
6116
|
+
"hmr: forced workerd rsc env reload (full-reload)"
|
|
6117
|
+
);
|
|
6118
|
+
} catch (err) {
|
|
6119
|
+
debugDiscovery?.(
|
|
6120
|
+
"hmr: workerd reload failed: %s",
|
|
6121
|
+
err?.message ?? err
|
|
6122
|
+
);
|
|
6123
|
+
}
|
|
6124
|
+
};
|
|
5783
6125
|
const scheduleRouteRegeneration = () => {
|
|
5784
6126
|
clearTimeout(routeChangeTimer);
|
|
5785
6127
|
routeChangeTimer = setTimeout(() => {
|
|
@@ -5799,9 +6141,7 @@ ${err.stack}`
|
|
|
5799
6141
|
}
|
|
5800
6142
|
}
|
|
5801
6143
|
} catch (err) {
|
|
5802
|
-
console.error(
|
|
5803
|
-
`[rsc-router] Route regeneration error: ${err.message}`
|
|
5804
|
-
);
|
|
6144
|
+
console.error(`[rango] Route regeneration error: ${err.message}`);
|
|
5805
6145
|
}
|
|
5806
6146
|
debugDiscovery?.(
|
|
5807
6147
|
"watcher: regenerated gen files (%sms)",
|
|
@@ -5810,7 +6150,7 @@ ${err.stack}`
|
|
|
5810
6150
|
if (s.perRouterManifests.length > 0) {
|
|
5811
6151
|
refreshRuntimeDiscovery().catch((err) => {
|
|
5812
6152
|
console.warn(
|
|
5813
|
-
`[
|
|
6153
|
+
`[rango] Runtime re-discovery error: ${err.message}`
|
|
5814
6154
|
);
|
|
5815
6155
|
resolveDiscoveryGate();
|
|
5816
6156
|
});
|
|
@@ -5819,23 +6159,56 @@ ${err.stack}`
|
|
|
5819
6159
|
};
|
|
5820
6160
|
const handleRouteFileChange = (filePath) => {
|
|
5821
6161
|
if (maybeHandleGeneratedRouteFileMutation(filePath)) return;
|
|
5822
|
-
if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx") && !filePath.endsWith(".js") && !filePath.endsWith(".jsx"))
|
|
6162
|
+
if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx") && !filePath.endsWith(".js") && !filePath.endsWith(".jsx")) {
|
|
6163
|
+
if (s.lastDiscoveryError) {
|
|
6164
|
+
debugDiscovery?.(
|
|
6165
|
+
"watcher: skip non-source %s [LASTERR %s]",
|
|
6166
|
+
filePath,
|
|
6167
|
+
s.lastDiscoveryError.message
|
|
6168
|
+
);
|
|
6169
|
+
}
|
|
5823
6170
|
return;
|
|
5824
|
-
|
|
6171
|
+
}
|
|
6172
|
+
if (s.scanFilter && !s.scanFilter(filePath)) {
|
|
6173
|
+
if (s.lastDiscoveryError) {
|
|
6174
|
+
debugDiscovery?.(
|
|
6175
|
+
"watcher: skip scan-filter %s [LASTERR %s]",
|
|
6176
|
+
filePath,
|
|
6177
|
+
s.lastDiscoveryError.message
|
|
6178
|
+
);
|
|
6179
|
+
}
|
|
6180
|
+
return;
|
|
6181
|
+
}
|
|
6182
|
+
const inRecoveryMode = !!s.lastDiscoveryError;
|
|
5825
6183
|
try {
|
|
5826
6184
|
const source = readFileSync6(filePath, "utf-8");
|
|
5827
6185
|
const trimmed = source.trimStart();
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
if (
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
6186
|
+
const isUseClient = trimmed.startsWith('"use client"') || trimmed.startsWith("'use client'");
|
|
6187
|
+
if (!inRecoveryMode && isUseClient) return;
|
|
6188
|
+
let hasUrls = source.includes("urls(");
|
|
6189
|
+
let hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
|
|
6190
|
+
if (hasUrls) hasUrls = firstCodeMatchIndex(source, /urls\(/g) >= 0;
|
|
6191
|
+
if (hasCreateRouter) {
|
|
6192
|
+
hasCreateRouter = firstCodeMatchIndex(source, /\bcreateRouter\s*[<(]/g) >= 0;
|
|
6193
|
+
}
|
|
6194
|
+
if (!inRecoveryMode && !hasUrls && !hasCreateRouter) return;
|
|
6195
|
+
if (inRecoveryMode) {
|
|
6196
|
+
debugDiscovery?.(
|
|
6197
|
+
"watcher: recovery rediscovery for %s (urls=%s, router=%s, useClient=%s) [LASTERR %s]",
|
|
6198
|
+
filePath,
|
|
6199
|
+
hasUrls,
|
|
6200
|
+
hasCreateRouter,
|
|
6201
|
+
isUseClient,
|
|
6202
|
+
s.lastDiscoveryError.message
|
|
6203
|
+
);
|
|
6204
|
+
} else {
|
|
6205
|
+
debugDiscovery?.(
|
|
6206
|
+
"watcher: %s matches (urls=%s, router=%s)",
|
|
6207
|
+
filePath,
|
|
6208
|
+
hasUrls,
|
|
6209
|
+
hasCreateRouter
|
|
6210
|
+
);
|
|
6211
|
+
}
|
|
5839
6212
|
if (hasCreateRouter) {
|
|
5840
6213
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
5841
6214
|
...s.cachedRouterFiles ?? [],
|
|
@@ -5853,7 +6226,15 @@ ${err.stack}`
|
|
|
5853
6226
|
gate.noteRouteEvent();
|
|
5854
6227
|
}
|
|
5855
6228
|
scheduleRouteRegeneration();
|
|
5856
|
-
} catch {
|
|
6229
|
+
} catch (readErr) {
|
|
6230
|
+
if (s.lastDiscoveryError) {
|
|
6231
|
+
debugDiscovery?.(
|
|
6232
|
+
"watcher: read error %s: %s [LASTERR %s]",
|
|
6233
|
+
filePath,
|
|
6234
|
+
readErr?.message,
|
|
6235
|
+
s.lastDiscoveryError.message
|
|
6236
|
+
);
|
|
6237
|
+
}
|
|
5857
6238
|
}
|
|
5858
6239
|
};
|
|
5859
6240
|
server.watcher.on("add", handleRouteFileChange);
|
|
@@ -5899,7 +6280,7 @@ ${err.stack}`
|
|
|
5899
6280
|
const rscEnv = tempServer.environments?.rsc;
|
|
5900
6281
|
if (!rscEnv?.runner) {
|
|
5901
6282
|
console.warn(
|
|
5902
|
-
"[
|
|
6283
|
+
"[rango] RSC environment runner not available during build, skipping manifest generation"
|
|
5903
6284
|
);
|
|
5904
6285
|
return;
|
|
5905
6286
|
}
|
|
@@ -5931,8 +6312,9 @@ ${err.stack}`
|
|
|
5931
6312
|
${err.stack}` : null
|
|
5932
6313
|
].filter(Boolean).join("\n");
|
|
5933
6314
|
throw new Error(
|
|
5934
|
-
`[
|
|
5935
|
-
${details}
|
|
6315
|
+
`[rango] Build-time router discovery failed:
|
|
6316
|
+
${details}`,
|
|
6317
|
+
{ cause: err }
|
|
5936
6318
|
);
|
|
5937
6319
|
} finally {
|
|
5938
6320
|
delete globalThis.__rscRouterDiscoveryActive;
|
|
@@ -5960,7 +6342,7 @@ ${details}`
|
|
|
5960
6342
|
// `consumeSelfGenWrite` inside `maybeHandleGeneratedRouteFileMutation`),
|
|
5961
6343
|
// AND vite's own HMR pipeline (which invalidates the gen file's
|
|
5962
6344
|
// importers and triggers a second workerd full reload — visible to the
|
|
5963
|
-
// user as a duplicate "[
|
|
6345
|
+
// user as a duplicate "[Rango] HMR: version changed" on the client).
|
|
5964
6346
|
//
|
|
5965
6347
|
// `peekSelfGenWrite` is the authoritative filter: its map only contains
|
|
5966
6348
|
// paths that `markSelfGenWrite` has registered, so it natively works
|
|
@@ -6120,6 +6502,10 @@ async function rango(options) {
|
|
|
6120
6502
|
const resolvedOptions = options ?? { preset: "node" };
|
|
6121
6503
|
const preset = resolvedOptions.preset ?? "node";
|
|
6122
6504
|
const showBanner = resolvedOptions.banner ?? true;
|
|
6505
|
+
const clientChunksOption = resolvedOptions.clientChunks ?? true;
|
|
6506
|
+
const useBuiltInClientChunks = clientChunksOption === true;
|
|
6507
|
+
const clientChunkCtx = useBuiltInClientChunks ? { fallbackRefs: /* @__PURE__ */ new Set() } : void 0;
|
|
6508
|
+
const clientChunks = resolveClientChunks(clientChunksOption, clientChunkCtx);
|
|
6123
6509
|
debugConfig?.("rango(%s) setup start", preset);
|
|
6124
6510
|
const plugins = [];
|
|
6125
6511
|
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
@@ -6155,10 +6541,18 @@ async function rango(options) {
|
|
|
6155
6541
|
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
6156
6542
|
optimizeDeps: {
|
|
6157
6543
|
exclude: excludeDeps,
|
|
6158
|
-
|
|
6544
|
+
rolldownOptions: sharedRolldownOptions
|
|
6159
6545
|
},
|
|
6160
6546
|
resolve: {
|
|
6161
|
-
alias: rangoAliases
|
|
6547
|
+
alias: rangoAliases,
|
|
6548
|
+
// Force a single React/React-DOM copy across all three RSC
|
|
6549
|
+
// environments. RSC requires exactly one react/react-dom instance
|
|
6550
|
+
// per environment runtime; consumer install topologies (pnpm
|
|
6551
|
+
// strict layout, experimental React pins, third-party "use client"
|
|
6552
|
+
// packages) can otherwise resolve duplicate copies, causing
|
|
6553
|
+
// "Invalid hook call" / lost context. Child environments inherit
|
|
6554
|
+
// this root dedupe, and Vite merges it with any consumer dedupe.
|
|
6555
|
+
dedupe: ["react", "react-dom"]
|
|
6162
6556
|
},
|
|
6163
6557
|
build: {
|
|
6164
6558
|
rollupOptions: { onwarn }
|
|
@@ -6167,6 +6561,14 @@ async function rango(options) {
|
|
|
6167
6561
|
client: {
|
|
6168
6562
|
build: {
|
|
6169
6563
|
rollupOptions: {
|
|
6564
|
+
// FILE_NAME_CONFLICT (and any other client-build warning) is
|
|
6565
|
+
// emitted by the CLIENT environment build, which consults THIS
|
|
6566
|
+
// env's onwarn -- Vite 8's environment builds do NOT propagate
|
|
6567
|
+
// the top-level build.rollupOptions.onwarn into the client env.
|
|
6568
|
+
// Wire it here so the suppression runs where the conflicts
|
|
6569
|
+
// originate (the top-level handler is invoked 0x for these; the
|
|
6570
|
+
// client-env handler is invoked for all of them).
|
|
6571
|
+
onwarn,
|
|
6170
6572
|
output: {
|
|
6171
6573
|
manualChunks: getManualChunks
|
|
6172
6574
|
}
|
|
@@ -6177,7 +6579,7 @@ async function rango(options) {
|
|
|
6177
6579
|
optimizeDeps: {
|
|
6178
6580
|
include: [nested("rsc-html-stream/client")],
|
|
6179
6581
|
exclude: excludeDeps,
|
|
6180
|
-
|
|
6582
|
+
rolldownOptions: sharedRolldownOptions
|
|
6181
6583
|
}
|
|
6182
6584
|
},
|
|
6183
6585
|
ssr: {
|
|
@@ -6185,10 +6587,6 @@ async function rango(options) {
|
|
|
6185
6587
|
build: {
|
|
6186
6588
|
outDir: "./dist/rsc/ssr"
|
|
6187
6589
|
},
|
|
6188
|
-
resolve: {
|
|
6189
|
-
// Ensure single React instance in SSR child environment
|
|
6190
|
-
dedupe: ["react", "react-dom"]
|
|
6191
|
-
},
|
|
6192
6590
|
// Pre-bundle SSR entry and React for proper module linking with childEnvironments
|
|
6193
6591
|
// All deps must be listed to avoid late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
6194
6592
|
optimizeDeps: {
|
|
@@ -6206,7 +6604,7 @@ async function rango(options) {
|
|
|
6206
6604
|
)
|
|
6207
6605
|
],
|
|
6208
6606
|
exclude: excludeDeps,
|
|
6209
|
-
|
|
6607
|
+
rolldownOptions: sharedRolldownOptions
|
|
6210
6608
|
}
|
|
6211
6609
|
},
|
|
6212
6610
|
rsc: {
|
|
@@ -6223,7 +6621,7 @@ async function rango(options) {
|
|
|
6223
6621
|
)
|
|
6224
6622
|
],
|
|
6225
6623
|
exclude: excludeDeps,
|
|
6226
|
-
|
|
6624
|
+
rolldownOptions: sharedRolldownOptions
|
|
6227
6625
|
}
|
|
6228
6626
|
}
|
|
6229
6627
|
}
|
|
@@ -6241,7 +6639,8 @@ async function rango(options) {
|
|
|
6241
6639
|
plugins.push(
|
|
6242
6640
|
rsc({
|
|
6243
6641
|
entries: finalEntries,
|
|
6244
|
-
serverHandler: false
|
|
6642
|
+
serverHandler: false,
|
|
6643
|
+
clientChunks
|
|
6245
6644
|
})
|
|
6246
6645
|
);
|
|
6247
6646
|
plugins.push(clientRefDedup());
|
|
@@ -6259,7 +6658,7 @@ async function rango(options) {
|
|
|
6259
6658
|
const list = candidates.map(
|
|
6260
6659
|
(f) => " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f)
|
|
6261
6660
|
).join("\n");
|
|
6262
|
-
throw new Error(`[
|
|
6661
|
+
throw new Error(`[rango] Multiple routers found:
|
|
6263
6662
|
${list}`);
|
|
6264
6663
|
}
|
|
6265
6664
|
}
|
|
@@ -6278,18 +6677,34 @@ ${list}`);
|
|
|
6278
6677
|
return {
|
|
6279
6678
|
optimizeDeps: {
|
|
6280
6679
|
exclude: excludeDeps,
|
|
6281
|
-
|
|
6680
|
+
rolldownOptions: sharedRolldownOptions
|
|
6282
6681
|
},
|
|
6283
6682
|
build: {
|
|
6284
6683
|
rollupOptions: { onwarn }
|
|
6285
6684
|
},
|
|
6286
6685
|
resolve: {
|
|
6287
|
-
alias: rangoAliases
|
|
6686
|
+
alias: rangoAliases,
|
|
6687
|
+
// Force a single React/React-DOM copy across all three RSC
|
|
6688
|
+
// environments. RSC requires exactly one react/react-dom instance
|
|
6689
|
+
// per environment runtime; consumer install topologies (pnpm
|
|
6690
|
+
// strict layout, experimental React pins, third-party "use client"
|
|
6691
|
+
// packages) can otherwise resolve duplicate copies, causing
|
|
6692
|
+
// "Invalid hook call" / lost context. Child environments inherit
|
|
6693
|
+
// this root dedupe, and Vite merges it with any consumer dedupe.
|
|
6694
|
+
dedupe: ["react", "react-dom"]
|
|
6288
6695
|
},
|
|
6289
6696
|
environments: {
|
|
6290
6697
|
client: {
|
|
6291
6698
|
build: {
|
|
6292
6699
|
rollupOptions: {
|
|
6700
|
+
// FILE_NAME_CONFLICT (and any other client-build warning) is
|
|
6701
|
+
// emitted by the CLIENT environment build, which consults THIS
|
|
6702
|
+
// env's onwarn -- Vite 8's environment builds do NOT propagate
|
|
6703
|
+
// the top-level build.rollupOptions.onwarn into the client env.
|
|
6704
|
+
// Wire it here so the suppression runs where the conflicts
|
|
6705
|
+
// originate (the top-level handler is invoked 0x for these; the
|
|
6706
|
+
// client-env handler is invoked for all of them).
|
|
6707
|
+
onwarn,
|
|
6293
6708
|
output: {
|
|
6294
6709
|
manualChunks: getManualChunks
|
|
6295
6710
|
}
|
|
@@ -6304,7 +6719,7 @@ ${list}`);
|
|
|
6304
6719
|
nested("rsc-html-stream/client")
|
|
6305
6720
|
],
|
|
6306
6721
|
exclude: excludeDeps,
|
|
6307
|
-
|
|
6722
|
+
rolldownOptions: sharedRolldownOptions,
|
|
6308
6723
|
entries: [VIRTUAL_IDS.browser]
|
|
6309
6724
|
}
|
|
6310
6725
|
},
|
|
@@ -6323,7 +6738,7 @@ ${list}`);
|
|
|
6323
6738
|
)
|
|
6324
6739
|
],
|
|
6325
6740
|
exclude: excludeDeps,
|
|
6326
|
-
|
|
6741
|
+
rolldownOptions: sharedRolldownOptions
|
|
6327
6742
|
}
|
|
6328
6743
|
},
|
|
6329
6744
|
rsc: {
|
|
@@ -6337,7 +6752,7 @@ ${list}`);
|
|
|
6337
6752
|
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
6338
6753
|
)
|
|
6339
6754
|
],
|
|
6340
|
-
|
|
6755
|
+
rolldownOptions: sharedRolldownOptions
|
|
6341
6756
|
}
|
|
6342
6757
|
}
|
|
6343
6758
|
}
|
|
@@ -6354,7 +6769,7 @@ ${list}`);
|
|
|
6354
6769
|
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
6355
6770
|
hasWarnedDuplicate = true;
|
|
6356
6771
|
console.warn(
|
|
6357
|
-
"[
|
|
6772
|
+
"[rango] Duplicate @vitejs/plugin-rsc detected. Remove rsc() from your vite config \u2014 rango() includes it automatically."
|
|
6358
6773
|
);
|
|
6359
6774
|
}
|
|
6360
6775
|
}
|
|
@@ -6363,7 +6778,8 @@ ${list}`);
|
|
|
6363
6778
|
plugins.push(performanceTracksPlugin());
|
|
6364
6779
|
plugins.push(
|
|
6365
6780
|
rsc({
|
|
6366
|
-
entries: finalEntries
|
|
6781
|
+
entries: finalEntries,
|
|
6782
|
+
clientChunks
|
|
6367
6783
|
})
|
|
6368
6784
|
);
|
|
6369
6785
|
plugins.push(clientRefDedup());
|
|
@@ -6402,7 +6818,8 @@ ${list}`);
|
|
|
6402
6818
|
routerPathRef: discoveryRouterRef,
|
|
6403
6819
|
enableBuildPrerender: prerenderEnabled,
|
|
6404
6820
|
buildEnv: options?.buildEnv,
|
|
6405
|
-
preset
|
|
6821
|
+
preset,
|
|
6822
|
+
clientChunkCtx
|
|
6406
6823
|
})
|
|
6407
6824
|
);
|
|
6408
6825
|
debugConfig?.(
|