@rangojs/router 0.0.0-experimental.110 → 0.0.0-experimental.112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rango.js +41 -37
- package/dist/vite/index.js +144 -191
- package/package.json +17 -14
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/rango/SKILL.md +20 -0
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/event-controller.ts +42 -66
- package/src/browser/navigation-bridge.ts +4 -0
- package/src/browser/navigation-client.ts +12 -15
- package/src/browser/navigation-store.ts +7 -8
- package/src/browser/navigation-transaction.ts +7 -21
- package/src/browser/partial-update.ts +8 -16
- package/src/browser/react/NavigationProvider.tsx +29 -40
- package/src/browser/react/use-params.ts +3 -4
- package/src/browser/response-adapter.ts +25 -0
- package/src/browser/rsc-router.tsx +16 -2
- package/src/browser/server-action-bridge.ts +23 -30
- package/src/browser/types.ts +2 -0
- package/src/build/generate-manifest.ts +29 -31
- package/src/build/generate-route-types.ts +2 -0
- package/src/build/route-types/router-processing.ts +37 -9
- package/src/build/runtime-discovery.ts +9 -20
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +29 -0
- package/src/index.rsc.ts +1 -0
- package/src/index.ts +1 -0
- package/src/response-utils.ts +9 -0
- package/src/route-content-wrapper.tsx +6 -28
- package/src/route-definition/dsl-helpers.ts +231 -259
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-types.ts +19 -41
- package/src/router/content-negotiation.ts +15 -2
- package/src/router/intercept-resolution.ts +4 -18
- package/src/router/match-result.ts +32 -30
- package/src/router/middleware.ts +46 -78
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +4 -28
- package/src/rsc/handler.ts +20 -65
- package/src/rsc/helpers.ts +3 -2
- package/src/rsc/origin-guard.ts +28 -10
- package/src/rsc/response-route-handler.ts +32 -52
- 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/segment-system.tsx +5 -39
- package/src/server/context.ts +76 -35
- package/src/urls/include-helper.ts +10 -53
- package/src/urls/index.ts +0 -3
- package/src/urls/path-helper.ts +17 -52
- package/src/urls/pattern-types.ts +2 -19
- package/src/urls/response-types.ts +20 -19
- package/src/urls/type-extraction.ts +20 -115
- package/src/urls/urls-function.ts +1 -5
- package/src/vite/discovery/discover-routers.ts +10 -22
- package/src/vite/discovery/route-types-writer.ts +38 -82
- package/src/vite/plugins/cjs-to-esm.ts +3 -7
- 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 +34 -62
- package/src/vite/plugins/version-injector.ts +2 -12
- package/src/vite/router-discovery.ts +71 -26
- package/src/vite/utils/shared-utils.ts +13 -1
- package/src/browser/action-response-classifier.ts +0 -99
package/dist/vite/index.js
CHANGED
|
@@ -465,7 +465,7 @@ function exposeActionId() {
|
|
|
465
465
|
|
|
466
466
|
// src/vite/plugins/expose-internal-ids.ts
|
|
467
467
|
import { parseAst as parseAst2 } from "vite";
|
|
468
|
-
import
|
|
468
|
+
import MagicString3 from "magic-string";
|
|
469
469
|
import path4 from "node:path";
|
|
470
470
|
|
|
471
471
|
// src/vite/utils/ast-handler-extract.ts
|
|
@@ -960,7 +960,7 @@ function generateClientLoaderStubs(bindings, code, filePath, isBuild) {
|
|
|
960
960
|
const lines = [];
|
|
961
961
|
for (const binding of bindings) {
|
|
962
962
|
for (const name of binding.exportNames) {
|
|
963
|
-
const loaderId =
|
|
963
|
+
const loaderId = makeStubId(filePath, name, isBuild);
|
|
964
964
|
lines.push(
|
|
965
965
|
`export const ${name} = { __brand: "loader", $$id: "${loaderId}" };`
|
|
966
966
|
);
|
|
@@ -972,7 +972,7 @@ function transformLoaders(bindings, s, filePath, isBuild) {
|
|
|
972
972
|
let hasChanges = false;
|
|
973
973
|
for (const binding of bindings) {
|
|
974
974
|
const exportName = binding.exportNames[0];
|
|
975
|
-
const loaderId =
|
|
975
|
+
const loaderId = makeStubId(filePath, exportName, isBuild);
|
|
976
976
|
const paramInjection = binding.argCount === 1 ? `, undefined, "${loaderId}"` : `, "${loaderId}"`;
|
|
977
977
|
s.appendLeft(binding.callCloseParenPos, paramInjection);
|
|
978
978
|
const propInjection = `
|
|
@@ -984,7 +984,6 @@ ${binding.localName}.$$id = "${loaderId}";`;
|
|
|
984
984
|
}
|
|
985
985
|
|
|
986
986
|
// src/vite/plugins/expose-ids/handler-transform.ts
|
|
987
|
-
import MagicString2 from "magic-string";
|
|
988
987
|
function analyzeCreateHandleArgs(code, startPos, endPos) {
|
|
989
988
|
const content = code.slice(startPos, endPos).trim();
|
|
990
989
|
return { hasArgs: content.length > 0 };
|
|
@@ -998,7 +997,7 @@ function transformHandles(bindings, s, code, filePath, isBuild) {
|
|
|
998
997
|
binding.callOpenParenPos + 1,
|
|
999
998
|
binding.callCloseParenPos
|
|
1000
999
|
);
|
|
1001
|
-
const handleId =
|
|
1000
|
+
const handleId = makeStubId(filePath, exportName, isBuild);
|
|
1002
1001
|
let paramInjection;
|
|
1003
1002
|
if (!args.hasArgs) {
|
|
1004
1003
|
paramInjection = `undefined, "${handleId}"`;
|
|
@@ -1017,7 +1016,7 @@ function transformLocationState(bindings, s, filePath, isBuild) {
|
|
|
1017
1016
|
let hasChanges = false;
|
|
1018
1017
|
for (const binding of bindings) {
|
|
1019
1018
|
const exportName = binding.exportNames[0];
|
|
1020
|
-
const stateKey =
|
|
1019
|
+
const stateKey = makeStubId(filePath, exportName, isBuild);
|
|
1021
1020
|
const propInjection = `
|
|
1022
1021
|
${binding.localName}.__rsc_ls_key = "__rsc_ls_${stateKey}";`;
|
|
1023
1022
|
s.appendRight(binding.statementEnd, propInjection);
|
|
@@ -1029,7 +1028,7 @@ function generateWholeFileStubs(cfg, bindings, code, filePath, isBuild) {
|
|
|
1029
1028
|
if (!isExportOnlyFile(code, bindings)) return null;
|
|
1030
1029
|
const exportNames = bindings.flatMap((b) => b.exportNames);
|
|
1031
1030
|
const stubs = exportNames.map((name) => {
|
|
1032
|
-
const handlerId =
|
|
1031
|
+
const handlerId = makeStubId(filePath, name, isBuild);
|
|
1033
1032
|
return `export const ${name} = { __brand: "${cfg.brand}", $$id: "${handlerId}" };`;
|
|
1034
1033
|
});
|
|
1035
1034
|
return { code: stubs.join("\n") + "\n", map: null };
|
|
@@ -1038,7 +1037,7 @@ function stubHandlerExprs(cfg, bindings, s, filePath, isBuild) {
|
|
|
1038
1037
|
let hasChanges = false;
|
|
1039
1038
|
for (const binding of bindings) {
|
|
1040
1039
|
const exportName = binding.exportNames[0];
|
|
1041
|
-
const handlerId =
|
|
1040
|
+
const handlerId = makeStubId(filePath, exportName, isBuild);
|
|
1042
1041
|
s.overwrite(
|
|
1043
1042
|
binding.callExprStart,
|
|
1044
1043
|
binding.callCloseParenPos + 1,
|
|
@@ -1052,7 +1051,7 @@ function transformHandlerIds(cfg, bindings, s, filePath, isBuild) {
|
|
|
1052
1051
|
let hasChanges = false;
|
|
1053
1052
|
for (const binding of bindings) {
|
|
1054
1053
|
const exportName = binding.exportNames[0];
|
|
1055
|
-
const handlerId =
|
|
1054
|
+
const handlerId = makeStubId(filePath, exportName, isBuild);
|
|
1056
1055
|
let paramInjection;
|
|
1057
1056
|
if (binding.argCount === 0) {
|
|
1058
1057
|
paramInjection = `undefined, "${handlerId}"`;
|
|
@@ -1071,7 +1070,7 @@ ${binding.localName}.$$id = "${handlerId}";`;
|
|
|
1071
1070
|
}
|
|
1072
1071
|
|
|
1073
1072
|
// src/vite/plugins/expose-ids/router-transform.ts
|
|
1074
|
-
import
|
|
1073
|
+
import MagicString2 from "magic-string";
|
|
1075
1074
|
import path3 from "node:path";
|
|
1076
1075
|
import { createHash } from "node:crypto";
|
|
1077
1076
|
var debug2 = createRangoDebugger(NS.transform);
|
|
@@ -1081,10 +1080,10 @@ function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
|
1081
1080
|
"g"
|
|
1082
1081
|
);
|
|
1083
1082
|
let match;
|
|
1084
|
-
const s = new
|
|
1083
|
+
const s = new MagicString2(code);
|
|
1085
1084
|
let changed = false;
|
|
1086
|
-
const
|
|
1087
|
-
const routeNamesImport = `./${
|
|
1085
|
+
const basename2 = path3.basename(filePath).replace(/\.(tsx?|jsx?)$/, "");
|
|
1086
|
+
const routeNamesImport = `./${basename2}.named-routes.gen.js`;
|
|
1088
1087
|
const routeNamesVar = `__rsc_rn`;
|
|
1089
1088
|
while ((match = pat.exec(code)) !== null) {
|
|
1090
1089
|
const callStart = match.index;
|
|
@@ -1410,15 +1409,6 @@ ${lazyImports.join(",\n")}
|
|
|
1410
1409
|
);
|
|
1411
1410
|
if (wholeFile) return wholeFile;
|
|
1412
1411
|
}
|
|
1413
|
-
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1414
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1415
|
-
const exportNames = getBindings(code, fnNames).map(
|
|
1416
|
-
(b) => b.exportNames[0]
|
|
1417
|
-
);
|
|
1418
|
-
if (exportNames.length > 0) {
|
|
1419
|
-
prerenderHandlerModules.set(id, exportNames);
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
1412
|
let changed = false;
|
|
1423
1413
|
const handlerConfigs = [
|
|
1424
1414
|
hasStaticHandlerCode && STATIC_CONFIG,
|
|
@@ -1431,7 +1421,7 @@ ${lazyImports.join(",\n")}
|
|
|
1431
1421
|
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1432
1422
|
const supportedBindings = getBindings(code, fnNames).length;
|
|
1433
1423
|
if (totalCalls > supportedBindings) {
|
|
1434
|
-
const iterS = new
|
|
1424
|
+
const iterS = new MagicString3(code);
|
|
1435
1425
|
const result = transformInlineHandlers(
|
|
1436
1426
|
cfg.fnName,
|
|
1437
1427
|
VIRTUAL_HANDLER_PREFIX,
|
|
@@ -1596,16 +1586,24 @@ ${lazyImports.join(",\n")}
|
|
|
1596
1586
|
return { code: lines.join("\n") + "\n", map: null };
|
|
1597
1587
|
}
|
|
1598
1588
|
}
|
|
1599
|
-
if (
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1589
|
+
if (isRscEnv && isBuild) {
|
|
1590
|
+
const trackTypes = [
|
|
1591
|
+
[
|
|
1592
|
+
hasPrerenderHandlerCode,
|
|
1593
|
+
PRERENDER_CONFIG,
|
|
1594
|
+
prerenderHandlerModules
|
|
1595
|
+
],
|
|
1596
|
+
[hasStaticHandlerCode, STATIC_CONFIG, staticHandlerModules]
|
|
1597
|
+
];
|
|
1598
|
+
for (const [has2, cfg, trackMap] of trackTypes) {
|
|
1599
|
+
if (!has2) continue;
|
|
1600
|
+
const exportNames = getBindings(code, getFnNames(cfg.fnName)).map(
|
|
1601
|
+
(b) => b.exportNames[0]
|
|
1602
|
+
);
|
|
1603
|
+
if (exportNames.length > 0) trackMap.set(id, exportNames);
|
|
1606
1604
|
}
|
|
1607
1605
|
}
|
|
1608
|
-
const s = new
|
|
1606
|
+
const s = new MagicString3(code);
|
|
1609
1607
|
if (hasLoaderCode) {
|
|
1610
1608
|
const fnNames = getFnNames("createLoader");
|
|
1611
1609
|
changed = transformLoaders(
|
|
@@ -1634,41 +1632,13 @@ ${lazyImports.join(",\n")}
|
|
|
1634
1632
|
isBuild
|
|
1635
1633
|
) || changed;
|
|
1636
1634
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
s,
|
|
1645
|
-
filePath,
|
|
1646
|
-
isBuild
|
|
1647
|
-
) || changed;
|
|
1648
|
-
} else {
|
|
1649
|
-
changed = stubHandlerExprs(
|
|
1650
|
-
PRERENDER_CONFIG,
|
|
1651
|
-
bindings,
|
|
1652
|
-
s,
|
|
1653
|
-
filePath,
|
|
1654
|
-
isBuild
|
|
1655
|
-
) || changed;
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
if (hasStaticHandlerCode) {
|
|
1659
|
-
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1660
|
-
const bindings = getBindings(code, fnNames);
|
|
1661
|
-
if (isRscEnv) {
|
|
1662
|
-
changed = transformHandlerIds(
|
|
1663
|
-
STATIC_CONFIG,
|
|
1664
|
-
bindings,
|
|
1665
|
-
s,
|
|
1666
|
-
filePath,
|
|
1667
|
-
isBuild
|
|
1668
|
-
) || changed;
|
|
1669
|
-
} else {
|
|
1670
|
-
changed = stubHandlerExprs(STATIC_CONFIG, bindings, s, filePath, isBuild) || changed;
|
|
1671
|
-
}
|
|
1635
|
+
const finalHandlerConfigs = [
|
|
1636
|
+
hasPrerenderHandlerCode && PRERENDER_CONFIG,
|
|
1637
|
+
hasStaticHandlerCode && STATIC_CONFIG
|
|
1638
|
+
].filter((c) => !!c);
|
|
1639
|
+
for (const cfg of finalHandlerConfigs) {
|
|
1640
|
+
const bindings = getBindings(code, getFnNames(cfg.fnName));
|
|
1641
|
+
changed = (isRscEnv ? transformHandlerIds(cfg, bindings, s, filePath, isBuild) : stubHandlerExprs(cfg, bindings, s, filePath, isBuild)) || changed;
|
|
1672
1642
|
}
|
|
1673
1643
|
if (!changed) return;
|
|
1674
1644
|
return {
|
|
@@ -1684,7 +1654,7 @@ ${lazyImports.join(",\n")}
|
|
|
1684
1654
|
|
|
1685
1655
|
// src/vite/plugins/use-cache-transform.ts
|
|
1686
1656
|
import path5 from "node:path";
|
|
1687
|
-
import
|
|
1657
|
+
import MagicString4 from "magic-string";
|
|
1688
1658
|
var debug4 = createRangoDebugger(NS.transform);
|
|
1689
1659
|
var CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
1690
1660
|
var LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
@@ -1781,7 +1751,7 @@ function transformFileLevelUseCache(code, ast, filePath, sourceId, isBuild, isLa
|
|
|
1781
1751
|
);
|
|
1782
1752
|
}
|
|
1783
1753
|
if (exportNames.length === 0) {
|
|
1784
|
-
const s = new
|
|
1754
|
+
const s = new MagicString4(code);
|
|
1785
1755
|
const directive2 = findFileLevelDirective(ast);
|
|
1786
1756
|
if (directive2) {
|
|
1787
1757
|
s.overwrite(
|
|
@@ -2049,7 +2019,7 @@ import { resolve } from "node:path";
|
|
|
2049
2019
|
// package.json
|
|
2050
2020
|
var package_default = {
|
|
2051
2021
|
name: "@rangojs/router",
|
|
2052
|
-
version: "0.0.0-experimental.
|
|
2022
|
+
version: "0.0.0-experimental.112",
|
|
2053
2023
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
2054
2024
|
keywords: [
|
|
2055
2025
|
"react",
|
|
@@ -2187,6 +2157,7 @@ var package_default = {
|
|
|
2187
2157
|
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit && tsc -p tsconfig.augment-check.json --noEmit",
|
|
2188
2158
|
test: "playwright test",
|
|
2189
2159
|
"test:ui": "playwright test --ui",
|
|
2160
|
+
"test:hmr-local": "playwright test --project=dev-warmup --project=hmr-routes --project=hmr-basename --project=hmr-prerender --no-deps --workers=1",
|
|
2190
2161
|
"test:unit": "vitest run",
|
|
2191
2162
|
"test:unit:watch": "vitest"
|
|
2192
2163
|
},
|
|
@@ -2200,6 +2171,7 @@ var package_default = {
|
|
|
2200
2171
|
},
|
|
2201
2172
|
devDependencies: {
|
|
2202
2173
|
"@playwright/test": "^1.49.1",
|
|
2174
|
+
"@shared/e2e": "workspace:*",
|
|
2203
2175
|
"@types/node": "^24.10.1",
|
|
2204
2176
|
"@types/react": "catalog:",
|
|
2205
2177
|
"@types/react-dom": "catalog:",
|
|
@@ -2866,19 +2838,38 @@ function extractBasenameFromRouter(code) {
|
|
|
2866
2838
|
visit(sourceFile);
|
|
2867
2839
|
return result;
|
|
2868
2840
|
}
|
|
2869
|
-
function applyBasenameToRoutes(result,
|
|
2841
|
+
function applyBasenameToRoutes(result, basename2) {
|
|
2870
2842
|
const prefixed = {};
|
|
2871
2843
|
for (const [name, pattern] of Object.entries(result.routes)) {
|
|
2872
2844
|
if (pattern === "/") {
|
|
2873
|
-
prefixed[name] =
|
|
2874
|
-
} else if (
|
|
2875
|
-
prefixed[name] =
|
|
2845
|
+
prefixed[name] = basename2;
|
|
2846
|
+
} else if (basename2.endsWith("/") && pattern.startsWith("/")) {
|
|
2847
|
+
prefixed[name] = basename2 + pattern.slice(1);
|
|
2876
2848
|
} else {
|
|
2877
|
-
prefixed[name] =
|
|
2849
|
+
prefixed[name] = basename2 + pattern;
|
|
2878
2850
|
}
|
|
2879
2851
|
}
|
|
2880
2852
|
return { routes: prefixed, searchSchemas: result.searchSchemas };
|
|
2881
2853
|
}
|
|
2854
|
+
function genFileTsPath(sourceFile) {
|
|
2855
|
+
const base = pathBasename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
2856
|
+
return join(dirname2(sourceFile), `${base}.named-routes.gen.ts`);
|
|
2857
|
+
}
|
|
2858
|
+
function resolveSearchSchemas(publicRouteNames, runtimeSchemas, sourceFile) {
|
|
2859
|
+
if (runtimeSchemas && Object.keys(runtimeSchemas).length > 0) {
|
|
2860
|
+
return runtimeSchemas;
|
|
2861
|
+
}
|
|
2862
|
+
const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
|
|
2863
|
+
if (Object.keys(staticParsed.searchSchemas).length === 0) {
|
|
2864
|
+
return runtimeSchemas;
|
|
2865
|
+
}
|
|
2866
|
+
const filtered = {};
|
|
2867
|
+
for (const name of publicRouteNames) {
|
|
2868
|
+
const schema = staticParsed.searchSchemas[name];
|
|
2869
|
+
if (schema) filtered[name] = schema;
|
|
2870
|
+
}
|
|
2871
|
+
return Object.keys(filtered).length > 0 ? filtered : runtimeSchemas;
|
|
2872
|
+
}
|
|
2882
2873
|
function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
2883
2874
|
let routerSource;
|
|
2884
2875
|
try {
|
|
@@ -2891,7 +2882,7 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
|
2891
2882
|
return { routes: {}, searchSchemas: {} };
|
|
2892
2883
|
}
|
|
2893
2884
|
const rawBasename = extractBasenameFromRouter(routerSource);
|
|
2894
|
-
const
|
|
2885
|
+
const basename2 = rawBasename ? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "") : void 0;
|
|
2895
2886
|
let result;
|
|
2896
2887
|
if (extraction.kind === "inline") {
|
|
2897
2888
|
result = buildCombinedRouteMapWithSearch(
|
|
@@ -2916,8 +2907,8 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
|
2916
2907
|
result = buildCombinedRouteMapWithSearch(routerFilePath, extraction.name);
|
|
2917
2908
|
}
|
|
2918
2909
|
}
|
|
2919
|
-
if (
|
|
2920
|
-
result = applyBasenameToRoutes(result,
|
|
2910
|
+
if (basename2) {
|
|
2911
|
+
result = applyBasenameToRoutes(result, basename2);
|
|
2921
2912
|
}
|
|
2922
2913
|
return result;
|
|
2923
2914
|
}
|
|
@@ -2954,18 +2945,12 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
2954
2945
|
}
|
|
2955
2946
|
if (!extractUrlsFromRouter(routerSource)) continue;
|
|
2956
2947
|
}
|
|
2957
|
-
const
|
|
2958
|
-
/\.(tsx?|jsx?)$/,
|
|
2959
|
-
""
|
|
2960
|
-
);
|
|
2961
|
-
const outPath = join(
|
|
2962
|
-
dirname2(routerFilePath),
|
|
2963
|
-
`${routerBasename}.named-routes.gen.ts`
|
|
2964
|
-
);
|
|
2948
|
+
const outPath = genFileTsPath(routerFilePath);
|
|
2965
2949
|
const existing = existsSync3(outPath) ? readFileSync2(outPath, "utf-8") : null;
|
|
2966
2950
|
if (Object.keys(result.routes).length === 0) {
|
|
2967
2951
|
if (!existing) {
|
|
2968
2952
|
const emptySource = generateRouteTypesSource({});
|
|
2953
|
+
opts?.onWrite?.(outPath, emptySource);
|
|
2969
2954
|
writeFileSync(outPath, emptySource);
|
|
2970
2955
|
}
|
|
2971
2956
|
continue;
|
|
@@ -2985,6 +2970,7 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
2985
2970
|
continue;
|
|
2986
2971
|
}
|
|
2987
2972
|
}
|
|
2973
|
+
opts?.onWrite?.(outPath, source);
|
|
2988
2974
|
writeFileSync(outPath, source);
|
|
2989
2975
|
console.log(
|
|
2990
2976
|
`[rango] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`
|
|
@@ -3255,6 +3241,12 @@ function performanceTracksPlugin() {
|
|
|
3255
3241
|
}
|
|
3256
3242
|
|
|
3257
3243
|
// src/vite/utils/shared-utils.ts
|
|
3244
|
+
function resolveRscEntryFromConfig(config) {
|
|
3245
|
+
const entries = config.environments?.["rsc"]?.optimizeDeps?.entries;
|
|
3246
|
+
if (typeof entries === "string") return entries;
|
|
3247
|
+
if (Array.isArray(entries) && entries.length > 0) return entries[0];
|
|
3248
|
+
return void 0;
|
|
3249
|
+
}
|
|
3258
3250
|
var versionRolldownPlugin = {
|
|
3259
3251
|
name: "@rangojs/router-version",
|
|
3260
3252
|
resolveId(id) {
|
|
@@ -3373,15 +3365,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3373
3365
|
enforce: "pre",
|
|
3374
3366
|
configResolved(config) {
|
|
3375
3367
|
let entryPath = rscEntryPath;
|
|
3376
|
-
if (!entryPath)
|
|
3377
|
-
const rscEnvConfig = config.environments?.["rsc"];
|
|
3378
|
-
const entries = rscEnvConfig?.optimizeDeps?.entries;
|
|
3379
|
-
if (typeof entries === "string") {
|
|
3380
|
-
entryPath = entries;
|
|
3381
|
-
} else if (Array.isArray(entries) && entries.length > 0) {
|
|
3382
|
-
entryPath = entries[0];
|
|
3383
|
-
}
|
|
3384
|
-
}
|
|
3368
|
+
if (!entryPath) entryPath = resolveRscEntryFromConfig(config);
|
|
3385
3369
|
if (entryPath) {
|
|
3386
3370
|
resolvedEntryPath = resolve4(config.root, entryPath);
|
|
3387
3371
|
}
|
|
@@ -3435,8 +3419,8 @@ function createCjsToEsmPlugin() {
|
|
|
3435
3419
|
name: "@rangojs/router:cjs-to-esm",
|
|
3436
3420
|
enforce: "pre",
|
|
3437
3421
|
transform(code, id) {
|
|
3438
|
-
const cleanId = id.split("?")[0];
|
|
3439
|
-
if (cleanId.includes("vendor/react-server-dom/client.browser.js")
|
|
3422
|
+
const cleanId = id.split("?")[0].replaceAll("\\", "/");
|
|
3423
|
+
if (cleanId.includes("vendor/react-server-dom/client.browser.js")) {
|
|
3440
3424
|
const isProd = process.env.NODE_ENV === "production";
|
|
3441
3425
|
const cjsFile = isProd ? "./cjs/react-server-dom-webpack-client.browser.production.js" : "./cjs/react-server-dom-webpack-client.browser.development.js";
|
|
3442
3426
|
debug7?.("cjs-to-esm entry redirect %s", id);
|
|
@@ -3445,7 +3429,7 @@ function createCjsToEsmPlugin() {
|
|
|
3445
3429
|
map: null
|
|
3446
3430
|
};
|
|
3447
3431
|
}
|
|
3448
|
-
if (
|
|
3432
|
+
if (cleanId.includes("vendor/react-server-dom/cjs/") && cleanId.includes("client.browser")) {
|
|
3449
3433
|
let transformed = code;
|
|
3450
3434
|
const licenseMatch = transformed.match(/^\/\*\*[\s\S]*?\*\//);
|
|
3451
3435
|
const license = licenseMatch ? licenseMatch[0] : "";
|
|
@@ -4696,10 +4680,10 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4696
4680
|
newMergedRouteManifest,
|
|
4697
4681
|
mergedRouteAncestry,
|
|
4698
4682
|
routeToStaticPrefix,
|
|
4699
|
-
|
|
4700
|
-
prerenderRouteNames
|
|
4701
|
-
passthroughRouteNames
|
|
4702
|
-
|
|
4683
|
+
mergedRouteTrailingSlash,
|
|
4684
|
+
prerenderRouteNames,
|
|
4685
|
+
passthroughRouteNames,
|
|
4686
|
+
mergedResponseTypeRoutes
|
|
4703
4687
|
);
|
|
4704
4688
|
for (const { id, manifest } of allManifests) {
|
|
4705
4689
|
if (!manifest._routeAncestry || Object.keys(manifest._routeAncestry).length === 0)
|
|
@@ -4715,10 +4699,10 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4715
4699
|
manifest.routeManifest,
|
|
4716
4700
|
manifest._routeAncestry,
|
|
4717
4701
|
perRouterStaticPrefix,
|
|
4718
|
-
manifest.routeTrailingSlash
|
|
4719
|
-
perRouterPrerenderNames
|
|
4720
|
-
perRouterPassthroughNames
|
|
4721
|
-
manifest.responseTypeRoutes
|
|
4702
|
+
manifest.routeTrailingSlash,
|
|
4703
|
+
perRouterPrerenderNames,
|
|
4704
|
+
perRouterPassthroughNames,
|
|
4705
|
+
manifest.responseTypeRoutes
|
|
4722
4706
|
);
|
|
4723
4707
|
newPerRouterTrieMap.set(id, perRouterTrie);
|
|
4724
4708
|
}
|
|
@@ -4741,7 +4725,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4741
4725
|
}
|
|
4742
4726
|
|
|
4743
4727
|
// src/vite/discovery/route-types-writer.ts
|
|
4744
|
-
import { dirname as dirname3,
|
|
4728
|
+
import { dirname as dirname3, join as join2, resolve as resolve6 } from "node:path";
|
|
4745
4729
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "node:fs";
|
|
4746
4730
|
function filterUserNamedRoutes(manifest) {
|
|
4747
4731
|
const filtered = {};
|
|
@@ -4752,39 +4736,20 @@ function filterUserNamedRoutes(manifest) {
|
|
|
4752
4736
|
}
|
|
4753
4737
|
return filtered;
|
|
4754
4738
|
}
|
|
4739
|
+
function writeGenFileIfChanged(state, outPath, source, opts) {
|
|
4740
|
+
const existing = existsSync5(outPath) ? readFileSync4(outPath, "utf-8") : null;
|
|
4741
|
+
if (existing === source) return;
|
|
4742
|
+
markSelfGenWrite(state, outPath, source);
|
|
4743
|
+
writeFileSync3(outPath, source);
|
|
4744
|
+
if (opts?.log) console.log(`[rango] Generated route types -> ${outPath}`);
|
|
4745
|
+
}
|
|
4755
4746
|
function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
4756
4747
|
const routerFiles = state.cachedRouterFiles ?? findRouterFiles(state.projectRoot, state.scanFilter);
|
|
4757
4748
|
state.cachedRouterFiles = routerFiles;
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
/\.(tsx?|jsx?)$/,
|
|
4763
|
-
""
|
|
4764
|
-
);
|
|
4765
|
-
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4766
|
-
try {
|
|
4767
|
-
preContent.set(outPath, readFileSync4(outPath, "utf-8"));
|
|
4768
|
-
} catch {
|
|
4769
|
-
}
|
|
4770
|
-
}
|
|
4771
|
-
writeCombinedRouteTypes(state.projectRoot, routerFiles, opts);
|
|
4772
|
-
for (const routerFilePath of routerFiles) {
|
|
4773
|
-
const routerDir = dirname3(routerFilePath);
|
|
4774
|
-
const routerBasename = basename(routerFilePath).replace(
|
|
4775
|
-
/\.(tsx?|jsx?)$/,
|
|
4776
|
-
""
|
|
4777
|
-
);
|
|
4778
|
-
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4779
|
-
if (!existsSync5(outPath)) continue;
|
|
4780
|
-
try {
|
|
4781
|
-
const content = readFileSync4(outPath, "utf-8");
|
|
4782
|
-
if (content !== preContent.get(outPath)) {
|
|
4783
|
-
markSelfGenWrite(state, outPath, content);
|
|
4784
|
-
}
|
|
4785
|
-
} catch {
|
|
4786
|
-
}
|
|
4787
|
-
}
|
|
4749
|
+
writeCombinedRouteTypes(state.projectRoot, routerFiles, {
|
|
4750
|
+
...opts,
|
|
4751
|
+
onWrite: (outPath, content) => markSelfGenWrite(state, outPath, content)
|
|
4752
|
+
});
|
|
4788
4753
|
}
|
|
4789
4754
|
function writeRouteTypesFiles(state) {
|
|
4790
4755
|
if (state.perRouterManifests.length === 0) return;
|
|
@@ -4815,34 +4780,18 @@ This means createRouter() stack trace parsing matched a Vite internal frame.
|
|
|
4815
4780
|
Set an explicit \`id\` on createRouter() or check the call site.`
|
|
4816
4781
|
);
|
|
4817
4782
|
}
|
|
4818
|
-
const
|
|
4819
|
-
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4820
|
-
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4783
|
+
const outPath = genFileTsPath(sourceFile);
|
|
4821
4784
|
const userRoutes = filterUserNamedRoutes(routeManifest);
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
for (const name of Object.keys(userRoutes)) {
|
|
4828
|
-
const schema = staticParsed.searchSchemas[name];
|
|
4829
|
-
if (schema) filtered[name] = schema;
|
|
4830
|
-
}
|
|
4831
|
-
if (Object.keys(filtered).length > 0) {
|
|
4832
|
-
effectiveSearchSchemas = filtered;
|
|
4833
|
-
}
|
|
4834
|
-
}
|
|
4835
|
-
}
|
|
4785
|
+
const effectiveSearchSchemas = resolveSearchSchemas(
|
|
4786
|
+
Object.keys(userRoutes),
|
|
4787
|
+
routeSearchSchemas,
|
|
4788
|
+
sourceFile
|
|
4789
|
+
);
|
|
4836
4790
|
const source = generateRouteTypesSource(
|
|
4837
4791
|
userRoutes,
|
|
4838
4792
|
effectiveSearchSchemas && Object.keys(effectiveSearchSchemas).length > 0 ? effectiveSearchSchemas : void 0
|
|
4839
4793
|
);
|
|
4840
|
-
|
|
4841
|
-
if (existing !== source) {
|
|
4842
|
-
markSelfGenWrite(state, outPath, source);
|
|
4843
|
-
writeFileSync3(outPath, source);
|
|
4844
|
-
console.log(`[rango] Generated route types -> ${outPath}`);
|
|
4845
|
-
}
|
|
4794
|
+
writeGenFileIfChanged(state, outPath, source, { log: true });
|
|
4846
4795
|
}
|
|
4847
4796
|
}
|
|
4848
4797
|
function supplementGenFilesWithRuntimeRoutes(state) {
|
|
@@ -4880,23 +4829,17 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
4880
4829
|
}
|
|
4881
4830
|
}
|
|
4882
4831
|
}
|
|
4883
|
-
const
|
|
4884
|
-
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4885
|
-
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4832
|
+
const outPath = genFileTsPath(sourceFile);
|
|
4886
4833
|
const source = generateRouteTypesSource(
|
|
4887
4834
|
mergedRoutes,
|
|
4888
4835
|
Object.keys(mergedSearchSchemas).length > 0 ? mergedSearchSchemas : void 0
|
|
4889
4836
|
);
|
|
4890
|
-
|
|
4891
|
-
if (existing !== source) {
|
|
4892
|
-
markSelfGenWrite(state, outPath, source);
|
|
4893
|
-
writeFileSync3(outPath, source);
|
|
4894
|
-
}
|
|
4837
|
+
writeGenFileIfChanged(state, outPath, source);
|
|
4895
4838
|
}
|
|
4896
4839
|
}
|
|
4897
4840
|
|
|
4898
4841
|
// src/vite/discovery/virtual-module-codegen.ts
|
|
4899
|
-
import { dirname as dirname4, basename
|
|
4842
|
+
import { dirname as dirname4, basename, join as join3 } from "node:path";
|
|
4900
4843
|
function generateRoutesManifestModule(state) {
|
|
4901
4844
|
const hasManifest = state.mergedRouteManifest && Object.keys(state.mergedRouteManifest).length > 0;
|
|
4902
4845
|
if (hasManifest) {
|
|
@@ -4907,7 +4850,7 @@ function generateRoutesManifestModule(state) {
|
|
|
4907
4850
|
for (const entry of state.perRouterManifests) {
|
|
4908
4851
|
if (entry.sourceFile) {
|
|
4909
4852
|
const routerDir = dirname4(entry.sourceFile);
|
|
4910
|
-
const routerBasename =
|
|
4853
|
+
const routerBasename = basename(entry.sourceFile).replace(
|
|
4911
4854
|
/\.(tsx?|jsx?)$/,
|
|
4912
4855
|
""
|
|
4913
4856
|
);
|
|
@@ -4992,7 +4935,7 @@ function generatePerRouterModule(state, routerId) {
|
|
|
4992
4935
|
const lines = [];
|
|
4993
4936
|
if (routerEntry?.sourceFile) {
|
|
4994
4937
|
const routerDir = dirname4(routerEntry.sourceFile);
|
|
4995
|
-
const routerBasename =
|
|
4938
|
+
const routerBasename = basename(routerEntry.sourceFile).replace(
|
|
4996
4939
|
/\.(tsx?|jsx?)$/,
|
|
4997
4940
|
""
|
|
4998
4941
|
);
|
|
@@ -5430,13 +5373,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
5430
5373
|
s.resolvedEntryPath = opts.routerPathRef.path;
|
|
5431
5374
|
}
|
|
5432
5375
|
if (!s.resolvedEntryPath) {
|
|
5433
|
-
const
|
|
5434
|
-
|
|
5435
|
-
if (typeof entries === "string") {
|
|
5436
|
-
s.resolvedEntryPath = entries;
|
|
5437
|
-
} else if (Array.isArray(entries) && entries.length > 0) {
|
|
5438
|
-
s.resolvedEntryPath = entries[0];
|
|
5439
|
-
}
|
|
5376
|
+
const entry = resolveRscEntryFromConfig(config);
|
|
5377
|
+
if (entry) s.resolvedEntryPath = entry;
|
|
5440
5378
|
}
|
|
5441
5379
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
5442
5380
|
s.cachedRouterFiles = findRouterFiles(s.projectRoot, s.scanFilter);
|
|
@@ -5727,20 +5665,15 @@ ${err.stack}`
|
|
|
5727
5665
|
if (s.mergedRouteTrie && serverMod.setRouteTrie) {
|
|
5728
5666
|
serverMod.setRouteTrie(s.mergedRouteTrie);
|
|
5729
5667
|
}
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
}
|
|
5740
|
-
if (serverMod.setRouterPrecomputedEntries) {
|
|
5741
|
-
for (const [routerId, entries] of s.perRouterPrecomputedMap) {
|
|
5742
|
-
serverMod.setRouterPrecomputedEntries(routerId, entries);
|
|
5743
|
-
}
|
|
5668
|
+
const perRouterSetters = [
|
|
5669
|
+
[s.perRouterManifestDataMap, "setRouterManifest"],
|
|
5670
|
+
[s.perRouterTrieMap, "setRouterTrie"],
|
|
5671
|
+
[s.perRouterPrecomputedMap, "setRouterPrecomputedEntries"]
|
|
5672
|
+
];
|
|
5673
|
+
for (const [map, fn] of perRouterSetters) {
|
|
5674
|
+
const setter = serverMod[fn];
|
|
5675
|
+
if (typeof setter !== "function") continue;
|
|
5676
|
+
for (const [routerId, value] of map) setter(routerId, value);
|
|
5744
5677
|
}
|
|
5745
5678
|
};
|
|
5746
5679
|
server.middlewares.use("/__rsc_prerender", async (req, res) => {
|
|
@@ -5910,6 +5843,7 @@ ${err.stack}`
|
|
|
5910
5843
|
);
|
|
5911
5844
|
s.lastDiscoveryError = null;
|
|
5912
5845
|
}
|
|
5846
|
+
if (rscEnv && !rscEnv.runner) forceCloudflareWorkerReload(rscEnv);
|
|
5913
5847
|
} catch (err) {
|
|
5914
5848
|
s.lastDiscoveryError = {
|
|
5915
5849
|
message: err?.message ?? String(err),
|
|
@@ -5930,6 +5864,25 @@ ${err.stack}`
|
|
|
5930
5864
|
}
|
|
5931
5865
|
});
|
|
5932
5866
|
};
|
|
5867
|
+
const forceCloudflareWorkerReload = (rscEnv) => {
|
|
5868
|
+
if (!rscEnv?.hot) return;
|
|
5869
|
+
try {
|
|
5870
|
+
const graph = rscEnv.moduleGraph;
|
|
5871
|
+
if (graph?.invalidateAll) {
|
|
5872
|
+
graph.invalidateAll();
|
|
5873
|
+
debugDiscovery?.("hmr: invalidated workerd rsc module graph");
|
|
5874
|
+
}
|
|
5875
|
+
rscEnv.hot.send({ type: "full-reload" });
|
|
5876
|
+
debugDiscovery?.(
|
|
5877
|
+
"hmr: forced workerd rsc env reload (full-reload)"
|
|
5878
|
+
);
|
|
5879
|
+
} catch (err) {
|
|
5880
|
+
debugDiscovery?.(
|
|
5881
|
+
"hmr: workerd reload failed: %s",
|
|
5882
|
+
err?.message ?? err
|
|
5883
|
+
);
|
|
5884
|
+
}
|
|
5885
|
+
};
|
|
5933
5886
|
const scheduleRouteRegeneration = () => {
|
|
5934
5887
|
clearTimeout(routeChangeTimer);
|
|
5935
5888
|
routeChangeTimer = setTimeout(() => {
|