@rangojs/router 0.0.0-experimental.cb54cbba → 0.0.0-experimental.debug-cache-2383ca26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/dist/bin/rango.js +8 -3
- package/dist/vite/index.js +139 -200
- package/package.json +15 -14
- package/skills/caching/SKILL.md +37 -4
- package/skills/parallel/SKILL.md +126 -0
- package/src/browser/event-controller.ts +5 -0
- package/src/browser/navigation-bridge.ts +1 -3
- package/src/browser/navigation-client.ts +60 -27
- package/src/browser/navigation-transaction.ts +11 -9
- package/src/browser/partial-update.ts +50 -9
- package/src/browser/prefetch/cache.ts +57 -5
- package/src/browser/prefetch/fetch.ts +30 -21
- package/src/browser/prefetch/queue.ts +53 -13
- package/src/browser/react/Link.tsx +9 -1
- package/src/browser/react/NavigationProvider.tsx +27 -0
- package/src/browser/rsc-router.tsx +109 -57
- package/src/browser/scroll-restoration.ts +31 -34
- package/src/browser/segment-reconciler.ts +6 -1
- package/src/browser/types.ts +9 -0
- package/src/build/route-types/router-processing.ts +12 -2
- package/src/cache/cache-runtime.ts +15 -11
- package/src/cache/cache-scope.ts +43 -3
- package/src/cache/cf/cf-cache-store.ts +453 -11
- package/src/cache/cf/index.ts +5 -1
- package/src/cache/document-cache.ts +17 -7
- package/src/cache/index.ts +1 -0
- package/src/debug.ts +2 -2
- package/src/route-definition/dsl-helpers.ts +32 -7
- package/src/route-definition/redirect.ts +2 -2
- package/src/route-map-builder.ts +7 -1
- package/src/router/find-match.ts +4 -2
- package/src/router/intercept-resolution.ts +2 -0
- package/src/router/lazy-includes.ts +4 -1
- package/src/router/logging.ts +5 -2
- package/src/router/manifest.ts +9 -3
- package/src/router/match-middleware/background-revalidation.ts +30 -2
- package/src/router/match-middleware/cache-lookup.ts +66 -9
- package/src/router/match-middleware/cache-store.ts +53 -10
- package/src/router/match-middleware/intercept-resolution.ts +9 -7
- package/src/router/match-middleware/segment-resolution.ts +8 -5
- package/src/router/match-result.ts +22 -6
- package/src/router/metrics.ts +6 -1
- package/src/router/middleware.ts +2 -1
- package/src/router/router-context.ts +6 -1
- package/src/router/segment-resolution/fresh.ts +122 -15
- package/src/router/segment-resolution/loader-cache.ts +1 -0
- package/src/router/segment-resolution/revalidation.ts +347 -290
- package/src/router/segment-wrappers.ts +2 -0
- package/src/router.ts +5 -1
- package/src/segment-system.tsx +140 -4
- package/src/server/context.ts +90 -13
- package/src/server/request-context.ts +10 -4
- package/src/ssr/index.tsx +1 -0
- package/src/types/handler-context.ts +103 -17
- package/src/types/route-entry.ts +7 -0
- package/src/types/segments.ts +2 -0
- package/src/urls/path-helper.ts +1 -1
- package/src/vite/discovery/state.ts +0 -2
- package/src/vite/plugin-types.ts +0 -83
- package/src/vite/plugins/expose-action-id.ts +1 -3
- package/src/vite/plugins/version-plugin.ts +13 -1
- package/src/vite/rango.ts +144 -209
- package/src/vite/router-discovery.ts +0 -8
- package/src/vite/utils/banner.ts +3 -3
package/AGENTS.md
CHANGED
|
@@ -3,3 +3,7 @@
|
|
|
3
3
|
A file-system based React Server Components router.
|
|
4
4
|
|
|
5
5
|
Run `/rango` to understand the API. Detailed guides for each feature are in the `skills/` directory (e.g. `node_modules/@rangojs/router/skills/loader`, `skills/caching`, `skills/middleware`, etc.).
|
|
6
|
+
|
|
7
|
+
## Development rules
|
|
8
|
+
|
|
9
|
+
- Always commit generated files (e.g. `*.gen.ts`) alongside the source changes that produced them.
|
package/dist/bin/rango.js
CHANGED
|
@@ -601,7 +601,7 @@ function countPublicRouteEntries(source) {
|
|
|
601
601
|
return count;
|
|
602
602
|
}
|
|
603
603
|
function isRoutableSourceFile(name) {
|
|
604
|
-
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.");
|
|
604
|
+
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
605
605
|
}
|
|
606
606
|
function findRouterFilesRecursive(dir, filter, results) {
|
|
607
607
|
let entries;
|
|
@@ -618,7 +618,8 @@ function findRouterFilesRecursive(dir, filter, results) {
|
|
|
618
618
|
for (const entry of entries) {
|
|
619
619
|
const fullPath = join2(dir, entry.name);
|
|
620
620
|
if (entry.isDirectory()) {
|
|
621
|
-
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
621
|
+
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "coverage" || entry.name === "__tests__" || entry.name === "__mocks__" || entry.name.startsWith("."))
|
|
622
|
+
continue;
|
|
622
623
|
childDirs.push(fullPath);
|
|
623
624
|
continue;
|
|
624
625
|
}
|
|
@@ -1062,8 +1063,9 @@ function createVersionPlugin() {
|
|
|
1062
1063
|
let isDev = false;
|
|
1063
1064
|
let server = null;
|
|
1064
1065
|
const clientModuleSignatures = /* @__PURE__ */ new Map();
|
|
1066
|
+
let versionCounter = 0;
|
|
1065
1067
|
const bumpVersion = (reason) => {
|
|
1066
|
-
currentVersion = Date.now().toString(16);
|
|
1068
|
+
currentVersion = Date.now().toString(16) + String(++versionCounter);
|
|
1067
1069
|
console.log(`[rsc-router] ${reason}, version updated: ${currentVersion}`);
|
|
1068
1070
|
const rscEnv = server?.environments?.rsc;
|
|
1069
1071
|
const versionMod = rscEnv?.moduleGraph?.getModuleById(
|
|
@@ -1119,6 +1121,9 @@ function createVersionPlugin() {
|
|
|
1119
1121
|
if (!isDev) return;
|
|
1120
1122
|
const isRscModule = this.environment?.name === "rsc";
|
|
1121
1123
|
if (!isRscModule) return;
|
|
1124
|
+
if (ctx.modules.length === 1 && ctx.modules[0].id === "\0" + VIRTUAL_IDS.version) {
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1122
1127
|
if (isCodeModule(ctx.file)) {
|
|
1123
1128
|
const filePath = normalizeModuleId(ctx.file);
|
|
1124
1129
|
const previousSignature = clientModuleSignatures.get(filePath);
|
package/dist/vite/index.js
CHANGED
|
@@ -292,7 +292,7 @@ function exposeActionId() {
|
|
|
292
292
|
}
|
|
293
293
|
if (!rscPluginApi) {
|
|
294
294
|
throw new Error(
|
|
295
|
-
"[rsc-router] Could not find @vitejs/plugin-rsc. @rangojs/router requires the Vite RSC plugin
|
|
295
|
+
"[rsc-router] Could not find @vitejs/plugin-rsc. @rangojs/router requires the Vite RSC plugin, which is included automatically by rango()."
|
|
296
296
|
);
|
|
297
297
|
}
|
|
298
298
|
if (!isBuild) return;
|
|
@@ -1745,7 +1745,7 @@ import { resolve } from "node:path";
|
|
|
1745
1745
|
// package.json
|
|
1746
1746
|
var package_default = {
|
|
1747
1747
|
name: "@rangojs/router",
|
|
1748
|
-
version: "0.0.0-experimental.
|
|
1748
|
+
version: "0.0.0-experimental.debug-cache-2383ca26",
|
|
1749
1749
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1750
1750
|
keywords: [
|
|
1751
1751
|
"react",
|
|
@@ -2095,31 +2095,7 @@ declare global {
|
|
|
2095
2095
|
}
|
|
2096
2096
|
|
|
2097
2097
|
// src/build/route-types/scan-filter.ts
|
|
2098
|
-
import { join, relative } from "node:path";
|
|
2099
2098
|
import picomatch from "picomatch";
|
|
2100
|
-
var DEFAULT_EXCLUDE_PATTERNS = [
|
|
2101
|
-
"**/__tests__/**",
|
|
2102
|
-
"**/__mocks__/**",
|
|
2103
|
-
"**/dist/**",
|
|
2104
|
-
"**/coverage/**",
|
|
2105
|
-
"**/*.test.{ts,tsx,js,jsx}",
|
|
2106
|
-
"**/*.spec.{ts,tsx,js,jsx}"
|
|
2107
|
-
];
|
|
2108
|
-
function createScanFilter(root, opts) {
|
|
2109
|
-
const { include, exclude } = opts;
|
|
2110
|
-
const hasInclude = include && include.length > 0;
|
|
2111
|
-
const hasCustomExclude = exclude !== void 0;
|
|
2112
|
-
if (!hasInclude && !hasCustomExclude) return void 0;
|
|
2113
|
-
const effectiveExclude = exclude ?? DEFAULT_EXCLUDE_PATTERNS;
|
|
2114
|
-
const includeMatcher = hasInclude ? picomatch(include) : null;
|
|
2115
|
-
const excludeMatcher = effectiveExclude.length > 0 ? picomatch(effectiveExclude) : null;
|
|
2116
|
-
return (absolutePath) => {
|
|
2117
|
-
const rel = relative(root, absolutePath);
|
|
2118
|
-
if (excludeMatcher && excludeMatcher(rel)) return false;
|
|
2119
|
-
if (includeMatcher) return includeMatcher(rel);
|
|
2120
|
-
return true;
|
|
2121
|
-
};
|
|
2122
|
-
}
|
|
2123
2099
|
|
|
2124
2100
|
// src/build/route-types/per-module-writer.ts
|
|
2125
2101
|
import ts4 from "typescript";
|
|
@@ -2386,7 +2362,7 @@ import {
|
|
|
2386
2362
|
readdirSync
|
|
2387
2363
|
} from "node:fs";
|
|
2388
2364
|
import {
|
|
2389
|
-
join
|
|
2365
|
+
join,
|
|
2390
2366
|
dirname as dirname2,
|
|
2391
2367
|
resolve as resolve3,
|
|
2392
2368
|
sep,
|
|
@@ -2406,7 +2382,7 @@ function countPublicRouteEntries(source) {
|
|
|
2406
2382
|
}
|
|
2407
2383
|
var ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
|
|
2408
2384
|
function isRoutableSourceFile(name) {
|
|
2409
|
-
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.");
|
|
2385
|
+
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
2410
2386
|
}
|
|
2411
2387
|
function findRouterFilesRecursive(dir, filter, results) {
|
|
2412
2388
|
let entries;
|
|
@@ -2421,9 +2397,10 @@ function findRouterFilesRecursive(dir, filter, results) {
|
|
|
2421
2397
|
const childDirs = [];
|
|
2422
2398
|
const routerFilesInDir = [];
|
|
2423
2399
|
for (const entry of entries) {
|
|
2424
|
-
const fullPath =
|
|
2400
|
+
const fullPath = join(dir, entry.name);
|
|
2425
2401
|
if (entry.isDirectory()) {
|
|
2426
|
-
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
2402
|
+
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "coverage" || entry.name === "__tests__" || entry.name === "__mocks__" || entry.name.startsWith("."))
|
|
2403
|
+
continue;
|
|
2427
2404
|
childDirs.push(fullPath);
|
|
2428
2405
|
continue;
|
|
2429
2406
|
}
|
|
@@ -2547,7 +2524,7 @@ function findRouterFiles(root, filter) {
|
|
|
2547
2524
|
}
|
|
2548
2525
|
function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
2549
2526
|
try {
|
|
2550
|
-
const oldCombinedPath =
|
|
2527
|
+
const oldCombinedPath = join(root, "src", "named-routes.gen.ts");
|
|
2551
2528
|
if (existsSync3(oldCombinedPath)) {
|
|
2552
2529
|
unlinkSync(oldCombinedPath);
|
|
2553
2530
|
console.log(
|
|
@@ -2587,7 +2564,7 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
2587
2564
|
/\.(tsx?|jsx?)$/,
|
|
2588
2565
|
""
|
|
2589
2566
|
);
|
|
2590
|
-
const outPath =
|
|
2567
|
+
const outPath = join(
|
|
2591
2568
|
dirname2(routerFilePath),
|
|
2592
2569
|
`${routerBasename}.named-routes.gen.ts`
|
|
2593
2570
|
);
|
|
@@ -2717,8 +2694,9 @@ function createVersionPlugin() {
|
|
|
2717
2694
|
let isDev = false;
|
|
2718
2695
|
let server = null;
|
|
2719
2696
|
const clientModuleSignatures = /* @__PURE__ */ new Map();
|
|
2697
|
+
let versionCounter = 0;
|
|
2720
2698
|
const bumpVersion = (reason) => {
|
|
2721
|
-
currentVersion = Date.now().toString(16);
|
|
2699
|
+
currentVersion = Date.now().toString(16) + String(++versionCounter);
|
|
2722
2700
|
console.log(`[rsc-router] ${reason}, version updated: ${currentVersion}`);
|
|
2723
2701
|
const rscEnv = server?.environments?.rsc;
|
|
2724
2702
|
const versionMod = rscEnv?.moduleGraph?.getModuleById(
|
|
@@ -2774,6 +2752,9 @@ function createVersionPlugin() {
|
|
|
2774
2752
|
if (!isDev) return;
|
|
2775
2753
|
const isRscModule = this.environment?.name === "rsc";
|
|
2776
2754
|
if (!isRscModule) return;
|
|
2755
|
+
if (ctx.modules.length === 1 && ctx.modules[0].id === "\0" + VIRTUAL_IDS.version) {
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2777
2758
|
if (isCodeModule(ctx.file)) {
|
|
2778
2759
|
const filePath = normalizeModuleId(ctx.file);
|
|
2779
2760
|
const previousSignature = clientModuleSignatures.get(filePath);
|
|
@@ -2903,11 +2884,11 @@ ${dim} \u2571${reset} ${bold}\u2554\u2550\u2557${reset}${dim} * \u2
|
|
|
2903
2884
|
${dim} ${reset}${bold}\u2551 \u2551${reset} ${bold}\u2554\u2550\u2557${reset}${dim} * \u2727. \u2571${reset}
|
|
2904
2885
|
${dim} ${reset}${bold}\u2554\u2557 \u2551 \u2551 \u2551 \u2551${reset}${dim} * \u2571${reset}
|
|
2905
2886
|
${dim} ${reset}${bold}\u2551\u2551 \u2551 \u2551 \u2551 \u2551 \u2566\u2550\u2557\u2554\u2550\u2557\u2554\u2557\u2554\u2554\u2550\u2557\u2554\u2550\u2557${reset}${dim} \u2727 \u2726${reset}
|
|
2906
|
-
${dim}
|
|
2887
|
+
${dim} ${reset}${bold}\u2551\u2551 \u2551 \u2560\u2550\u255D \u2551 \u2560\u2566\u255D\u2560\u2550\u2563\u2551\u2551\u2551\u2551 \u2566\u2551 \u2551${reset}${dim} * \u2727${reset}
|
|
2907
2888
|
${dim} ${reset}${bold}\u2551\u255A\u2550\u255D \u2554\u2550\u2550\u2550\u255D \u2569\u255A\u2550\u2569 \u2569\u255D\u255A\u255D\u255A\u2550\u255D\u255A\u2550\u255D${reset}${dim} \u2726 . *${reset}
|
|
2908
2889
|
${dim} ${reset}${bold}\u255A\u2550\u2550\u2557 \u2551${reset}${dim} * RSC Wrangler \u2727 \u2726${reset}
|
|
2909
|
-
${dim} * ${reset}${bold}\u2551 \
|
|
2910
|
-
${bold}\u2550\u2550\u2550\
|
|
2890
|
+
${dim} * ${reset}${bold}\u2551 \u2551${reset}${dim} * \u2727. \u2571${reset}
|
|
2891
|
+
${dim} ${reset}${bold}\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550${reset}${dim} \u2726 *${reset}
|
|
2911
2892
|
|
|
2912
2893
|
v${version} \xB7 ${preset} \xB7 ${mode}
|
|
2913
2894
|
`;
|
|
@@ -3052,7 +3033,7 @@ function createVirtualStubPlugin() {
|
|
|
3052
3033
|
}
|
|
3053
3034
|
|
|
3054
3035
|
// src/vite/plugins/client-ref-hashing.ts
|
|
3055
|
-
import { relative
|
|
3036
|
+
import { relative } from "node:path";
|
|
3056
3037
|
import { createHash as createHash2 } from "node:crypto";
|
|
3057
3038
|
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3058
3039
|
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
@@ -3065,10 +3046,10 @@ function computeProductionHash(projectRoot, refKey) {
|
|
|
3065
3046
|
const absPath = decodeURIComponent(
|
|
3066
3047
|
refKey.slice(CLIENT_IN_SERVER_PKG_PROXY_PREFIX.length)
|
|
3067
3048
|
);
|
|
3068
|
-
toHash =
|
|
3049
|
+
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3069
3050
|
} else if (refKey.startsWith(FS_PREFIX)) {
|
|
3070
3051
|
const absPath = refKey.slice(FS_PREFIX.length - 1);
|
|
3071
|
-
toHash =
|
|
3052
|
+
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3072
3053
|
} else if (refKey.startsWith("/")) {
|
|
3073
3054
|
toHash = refKey.slice(1);
|
|
3074
3055
|
} else {
|
|
@@ -3937,7 +3918,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3937
3918
|
}
|
|
3938
3919
|
|
|
3939
3920
|
// src/vite/discovery/route-types-writer.ts
|
|
3940
|
-
import { dirname as dirname3, basename, join as
|
|
3921
|
+
import { dirname as dirname3, basename, join as join2, resolve as resolve6 } from "node:path";
|
|
3941
3922
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "node:fs";
|
|
3942
3923
|
function filterUserNamedRoutes(manifest) {
|
|
3943
3924
|
const filtered = {};
|
|
@@ -3958,7 +3939,7 @@ function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
|
3958
3939
|
/\.(tsx?|jsx?)$/,
|
|
3959
3940
|
""
|
|
3960
3941
|
);
|
|
3961
|
-
const outPath =
|
|
3942
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
3962
3943
|
try {
|
|
3963
3944
|
preContent.set(outPath, readFileSync4(outPath, "utf-8"));
|
|
3964
3945
|
} catch {
|
|
@@ -3971,7 +3952,7 @@ function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
|
3971
3952
|
/\.(tsx?|jsx?)$/,
|
|
3972
3953
|
""
|
|
3973
3954
|
);
|
|
3974
|
-
const outPath =
|
|
3955
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
3975
3956
|
if (!existsSync5(outPath)) continue;
|
|
3976
3957
|
try {
|
|
3977
3958
|
const content = readFileSync4(outPath, "utf-8");
|
|
@@ -3988,7 +3969,7 @@ function writeRouteTypesFiles(state) {
|
|
|
3988
3969
|
const entryDir = dirname3(
|
|
3989
3970
|
resolve6(state.projectRoot, state.resolvedEntryPath)
|
|
3990
3971
|
);
|
|
3991
|
-
const oldCombinedPath =
|
|
3972
|
+
const oldCombinedPath = join2(entryDir, "named-routes.gen.ts");
|
|
3992
3973
|
if (existsSync5(oldCombinedPath)) {
|
|
3993
3974
|
unlinkSync2(oldCombinedPath);
|
|
3994
3975
|
console.log(
|
|
@@ -4013,7 +3994,7 @@ Set an explicit \`id\` on createRouter() or check the call site.`
|
|
|
4013
3994
|
}
|
|
4014
3995
|
const routerDir = dirname3(sourceFile);
|
|
4015
3996
|
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4016
|
-
const outPath =
|
|
3997
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4017
3998
|
const userRoutes = filterUserNamedRoutes(routeManifest);
|
|
4018
3999
|
let effectiveSearchSchemas = routeSearchSchemas;
|
|
4019
4000
|
if ((!effectiveSearchSchemas || Object.keys(effectiveSearchSchemas).length === 0) && sourceFile) {
|
|
@@ -4078,7 +4059,7 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
4078
4059
|
}
|
|
4079
4060
|
const routerDir = dirname3(sourceFile);
|
|
4080
4061
|
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4081
|
-
const outPath =
|
|
4062
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4082
4063
|
const source = generateRouteTypesSource(
|
|
4083
4064
|
mergedRoutes,
|
|
4084
4065
|
Object.keys(mergedSearchSchemas).length > 0 ? mergedSearchSchemas : void 0
|
|
@@ -4092,7 +4073,7 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
4092
4073
|
}
|
|
4093
4074
|
|
|
4094
4075
|
// src/vite/discovery/virtual-module-codegen.ts
|
|
4095
|
-
import { dirname as dirname4, basename as basename2, join as
|
|
4076
|
+
import { dirname as dirname4, basename as basename2, join as join3 } from "node:path";
|
|
4096
4077
|
function generateRoutesManifestModule(state) {
|
|
4097
4078
|
const hasManifest = state.mergedRouteManifest && Object.keys(state.mergedRouteManifest).length > 0;
|
|
4098
4079
|
if (hasManifest) {
|
|
@@ -4107,7 +4088,7 @@ function generateRoutesManifestModule(state) {
|
|
|
4107
4088
|
/\.(tsx?|jsx?)$/,
|
|
4108
4089
|
""
|
|
4109
4090
|
);
|
|
4110
|
-
const genPath =
|
|
4091
|
+
const genPath = join3(
|
|
4111
4092
|
routerDir,
|
|
4112
4093
|
`${routerBasename}.named-routes.gen.js`
|
|
4113
4094
|
).replaceAll("\\", "/");
|
|
@@ -4204,7 +4185,7 @@ function generatePerRouterModule(state, routerId) {
|
|
|
4204
4185
|
/\.(tsx?|jsx?)$/,
|
|
4205
4186
|
""
|
|
4206
4187
|
);
|
|
4207
|
-
const genPath =
|
|
4188
|
+
const genPath = join3(
|
|
4208
4189
|
routerDir,
|
|
4209
4190
|
`${routerBasename}.named-routes.gen.js`
|
|
4210
4191
|
).replaceAll("\\", "/");
|
|
@@ -4445,12 +4426,6 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4445
4426
|
s.resolvedEntryPath = entries[0];
|
|
4446
4427
|
}
|
|
4447
4428
|
}
|
|
4448
|
-
if (opts?.include || opts?.exclude) {
|
|
4449
|
-
s.scanFilter = createScanFilter(s.projectRoot, {
|
|
4450
|
-
include: opts.include,
|
|
4451
|
-
exclude: opts.exclude
|
|
4452
|
-
});
|
|
4453
|
-
}
|
|
4454
4429
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
4455
4430
|
s.cachedRouterFiles = findRouterFiles(s.projectRoot, s.scanFilter);
|
|
4456
4431
|
writeCombinedRouteTypesWithTracking(s, { preserveIfLarger: true });
|
|
@@ -4879,7 +4854,6 @@ async function rango(options) {
|
|
|
4879
4854
|
const plugins = [];
|
|
4880
4855
|
const rangoAliases = getPackageAliases();
|
|
4881
4856
|
const excludeDeps = getExcludeDeps();
|
|
4882
|
-
let rscEntryPath = null;
|
|
4883
4857
|
const routerRef = { path: void 0 };
|
|
4884
4858
|
const prerenderEnabled = true;
|
|
4885
4859
|
if (preset === "cloudflare") {
|
|
@@ -4983,153 +4957,121 @@ async function rango(options) {
|
|
|
4983
4957
|
);
|
|
4984
4958
|
plugins.push(clientRefDedup());
|
|
4985
4959
|
} else {
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
const
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
routerRef.path = (abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs).replaceAll("\\", "/");
|
|
5002
|
-
} else if (candidates.length > 1) {
|
|
5003
|
-
const list = candidates.map(
|
|
5004
|
-
(f) => " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f)
|
|
5005
|
-
).join("\n");
|
|
5006
|
-
throw new Error(
|
|
5007
|
-
`[rsc-router] Multiple routers found. Specify \`router\` to choose one:
|
|
5008
|
-
${list}`
|
|
5009
|
-
);
|
|
5010
|
-
}
|
|
4960
|
+
plugins.push({
|
|
4961
|
+
name: "@rangojs/router:auto-discover",
|
|
4962
|
+
config(userConfig) {
|
|
4963
|
+
if (routerRef.path) return;
|
|
4964
|
+
const root = userConfig.root ? resolve9(process.cwd(), userConfig.root) : process.cwd();
|
|
4965
|
+
const candidates = findRouterFiles(root);
|
|
4966
|
+
if (candidates.length === 1) {
|
|
4967
|
+
const abs = candidates[0];
|
|
4968
|
+
routerRef.path = (abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs).replaceAll("\\", "/");
|
|
4969
|
+
} else if (candidates.length > 1) {
|
|
4970
|
+
const list = candidates.map(
|
|
4971
|
+
(f) => " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f)
|
|
4972
|
+
).join("\n");
|
|
4973
|
+
throw new Error(`[rsc-router] Multiple routers found:
|
|
4974
|
+
${list}`);
|
|
5011
4975
|
}
|
|
5012
|
-
}
|
|
5013
|
-
}
|
|
5014
|
-
const
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
resolve: {
|
|
5043
|
-
alias: rangoAliases
|
|
5044
|
-
},
|
|
5045
|
-
environments: {
|
|
5046
|
-
client: {
|
|
5047
|
-
build: {
|
|
5048
|
-
rollupOptions: {
|
|
5049
|
-
output: {
|
|
5050
|
-
manualChunks: getManualChunks
|
|
5051
|
-
}
|
|
5052
|
-
}
|
|
5053
|
-
},
|
|
5054
|
-
// Always exclude rsc-router modules, conditionally add virtual entry
|
|
5055
|
-
optimizeDeps: {
|
|
5056
|
-
// Pre-bundle React and rsc-html-stream to prevent late discovery
|
|
5057
|
-
// triggering ERR_OUTDATED_OPTIMIZED_DEP on cold starts
|
|
5058
|
-
include: [
|
|
5059
|
-
"react",
|
|
5060
|
-
"react-dom",
|
|
5061
|
-
"react/jsx-runtime",
|
|
5062
|
-
"react/jsx-dev-runtime",
|
|
5063
|
-
"rsc-html-stream/client"
|
|
5064
|
-
],
|
|
5065
|
-
exclude: excludeDeps,
|
|
5066
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
5067
|
-
...useVirtualClient && {
|
|
5068
|
-
// Tell Vite to scan the virtual entry for dependencies
|
|
5069
|
-
entries: [VIRTUAL_IDS.browser]
|
|
5070
|
-
}
|
|
5071
|
-
}
|
|
5072
|
-
},
|
|
5073
|
-
...useVirtualSSR && {
|
|
5074
|
-
ssr: {
|
|
5075
|
-
optimizeDeps: {
|
|
5076
|
-
entries: [VIRTUAL_IDS.ssr],
|
|
5077
|
-
// Pre-bundle all SSR deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
5078
|
-
include: [
|
|
5079
|
-
"react",
|
|
5080
|
-
"react-dom",
|
|
5081
|
-
"react-dom/server.edge",
|
|
5082
|
-
"react-dom/static.edge",
|
|
5083
|
-
"react/jsx-runtime",
|
|
5084
|
-
"react/jsx-dev-runtime",
|
|
5085
|
-
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5086
|
-
],
|
|
5087
|
-
exclude: excludeDeps,
|
|
5088
|
-
esbuildOptions: sharedEsbuildOptions
|
|
4976
|
+
}
|
|
4977
|
+
});
|
|
4978
|
+
const finalEntries = {
|
|
4979
|
+
client: VIRTUAL_IDS.browser,
|
|
4980
|
+
ssr: VIRTUAL_IDS.ssr,
|
|
4981
|
+
rsc: VIRTUAL_IDS.rsc
|
|
4982
|
+
};
|
|
4983
|
+
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
4984
|
+
let hasWarnedDuplicate = false;
|
|
4985
|
+
plugins.push({
|
|
4986
|
+
name: "@rangojs/router:rsc-integration",
|
|
4987
|
+
enforce: "pre",
|
|
4988
|
+
config() {
|
|
4989
|
+
return {
|
|
4990
|
+
optimizeDeps: {
|
|
4991
|
+
exclude: excludeDeps,
|
|
4992
|
+
esbuildOptions: sharedEsbuildOptions
|
|
4993
|
+
},
|
|
4994
|
+
build: {
|
|
4995
|
+
rollupOptions: { onwarn }
|
|
4996
|
+
},
|
|
4997
|
+
resolve: {
|
|
4998
|
+
alias: rangoAliases
|
|
4999
|
+
},
|
|
5000
|
+
environments: {
|
|
5001
|
+
client: {
|
|
5002
|
+
build: {
|
|
5003
|
+
rollupOptions: {
|
|
5004
|
+
output: {
|
|
5005
|
+
manualChunks: getManualChunks
|
|
5089
5006
|
}
|
|
5090
5007
|
}
|
|
5091
5008
|
},
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5009
|
+
optimizeDeps: {
|
|
5010
|
+
include: [
|
|
5011
|
+
"react",
|
|
5012
|
+
"react-dom",
|
|
5013
|
+
"react/jsx-runtime",
|
|
5014
|
+
"react/jsx-dev-runtime",
|
|
5015
|
+
"rsc-html-stream/client"
|
|
5016
|
+
],
|
|
5017
|
+
exclude: excludeDeps,
|
|
5018
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
5019
|
+
entries: [VIRTUAL_IDS.browser]
|
|
5020
|
+
}
|
|
5021
|
+
},
|
|
5022
|
+
ssr: {
|
|
5023
|
+
optimizeDeps: {
|
|
5024
|
+
entries: [VIRTUAL_IDS.ssr],
|
|
5025
|
+
include: [
|
|
5026
|
+
"react",
|
|
5027
|
+
"react-dom",
|
|
5028
|
+
"react-dom/server.edge",
|
|
5029
|
+
"react-dom/static.edge",
|
|
5030
|
+
"react/jsx-runtime",
|
|
5031
|
+
"react/jsx-dev-runtime",
|
|
5032
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5033
|
+
],
|
|
5034
|
+
exclude: excludeDeps,
|
|
5035
|
+
esbuildOptions: sharedEsbuildOptions
|
|
5036
|
+
}
|
|
5037
|
+
},
|
|
5038
|
+
rsc: {
|
|
5039
|
+
optimizeDeps: {
|
|
5040
|
+
entries: [VIRTUAL_IDS.rsc],
|
|
5041
|
+
include: [
|
|
5042
|
+
"react",
|
|
5043
|
+
"react/jsx-runtime",
|
|
5044
|
+
"react/jsx-dev-runtime",
|
|
5045
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
5046
|
+
],
|
|
5047
|
+
esbuildOptions: sharedEsbuildOptions
|
|
5106
5048
|
}
|
|
5107
5049
|
}
|
|
5108
|
-
};
|
|
5109
|
-
},
|
|
5110
|
-
configResolved(config) {
|
|
5111
|
-
if (showBanner) {
|
|
5112
|
-
const mode = config.command === "serve" ? process.argv.includes("preview") ? "preview" : "dev" : "build";
|
|
5113
|
-
printBanner(mode, "node", rangoVersion);
|
|
5114
|
-
}
|
|
5115
|
-
const rscMinimalCount = config.plugins.filter(
|
|
5116
|
-
(p) => p.name === "rsc:minimal"
|
|
5117
|
-
).length;
|
|
5118
|
-
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
5119
|
-
hasWarnedDuplicate = true;
|
|
5120
|
-
console.warn(
|
|
5121
|
-
"[rsc-router] Duplicate @vitejs/plugin-rsc detected. Remove rsc() from your config or use rango({ rsc: false }) for manual configuration."
|
|
5122
|
-
);
|
|
5123
5050
|
}
|
|
5051
|
+
};
|
|
5052
|
+
},
|
|
5053
|
+
configResolved(config) {
|
|
5054
|
+
if (showBanner) {
|
|
5055
|
+
const mode = config.command === "serve" ? process.argv.includes("preview") ? "preview" : "dev" : "build";
|
|
5056
|
+
printBanner(mode, "node", rangoVersion);
|
|
5124
5057
|
}
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5058
|
+
const rscMinimalCount = config.plugins.filter(
|
|
5059
|
+
(p) => p.name === "rsc:minimal"
|
|
5060
|
+
).length;
|
|
5061
|
+
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
5062
|
+
hasWarnedDuplicate = true;
|
|
5063
|
+
console.warn(
|
|
5064
|
+
"[rsc-router] Duplicate @vitejs/plugin-rsc detected. Remove rsc() from your vite config \u2014 rango() includes it automatically."
|
|
5065
|
+
);
|
|
5066
|
+
}
|
|
5067
|
+
}
|
|
5068
|
+
});
|
|
5069
|
+
plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
|
|
5070
|
+
plugins.push(
|
|
5071
|
+
rsc({
|
|
5072
|
+
entries: finalEntries
|
|
5073
|
+
})
|
|
5074
|
+
);
|
|
5133
5075
|
plugins.push(clientRefDedup());
|
|
5134
5076
|
}
|
|
5135
5077
|
plugins.push({
|
|
@@ -5157,18 +5099,15 @@ ${list}`
|
|
|
5157
5099
|
plugins.push(createVersionPlugin());
|
|
5158
5100
|
const discoveryEntryPath = preset !== "cloudflare" ? routerRef.path : void 0;
|
|
5159
5101
|
const discoveryRouterRef = preset !== "cloudflare" ? routerRef : void 0;
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
plugins.push(createVersionInjectorPlugin(injectorEntryPath));
|
|
5102
|
+
if (preset === "cloudflare") {
|
|
5103
|
+
plugins.push(createVersionInjectorPlugin(void 0));
|
|
5163
5104
|
}
|
|
5164
5105
|
plugins.push(createCjsToEsmPlugin());
|
|
5165
5106
|
plugins.push(
|
|
5166
5107
|
createRouterDiscoveryPlugin(discoveryEntryPath, {
|
|
5167
5108
|
routerPathRef: discoveryRouterRef,
|
|
5168
5109
|
enableBuildPrerender: prerenderEnabled,
|
|
5169
|
-
staticRouteTypesGeneration: resolvedOptions.staticRouteTypesGeneration
|
|
5170
|
-
include: resolvedOptions.include,
|
|
5171
|
-
exclude: resolvedOptions.exclude
|
|
5110
|
+
staticRouteTypesGeneration: resolvedOptions.staticRouteTypesGeneration
|
|
5172
5111
|
})
|
|
5173
5112
|
);
|
|
5174
5113
|
return plugins;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rangojs/router",
|
|
3
|
-
"version": "0.0.0-experimental.
|
|
3
|
+
"version": "0.0.0-experimental.debug-cache-2383ca26",
|
|
4
4
|
"description": "Django-inspired RSC router with composable URL patterns",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -132,6 +132,15 @@
|
|
|
132
132
|
"access": "public",
|
|
133
133
|
"tag": "experimental"
|
|
134
134
|
},
|
|
135
|
+
"scripts": {
|
|
136
|
+
"build": "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.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",
|
|
137
|
+
"prepublishOnly": "pnpm build",
|
|
138
|
+
"typecheck": "tsc --noEmit",
|
|
139
|
+
"test": "playwright test",
|
|
140
|
+
"test:ui": "playwright test --ui",
|
|
141
|
+
"test:unit": "vitest run",
|
|
142
|
+
"test:unit:watch": "vitest"
|
|
143
|
+
},
|
|
135
144
|
"dependencies": {
|
|
136
145
|
"@vitejs/plugin-rsc": "^0.5.14",
|
|
137
146
|
"magic-string": "^0.30.17",
|
|
@@ -141,12 +150,12 @@
|
|
|
141
150
|
"devDependencies": {
|
|
142
151
|
"@playwright/test": "^1.49.1",
|
|
143
152
|
"@types/node": "^24.10.1",
|
|
144
|
-
"@types/react": "
|
|
145
|
-
"@types/react-dom": "
|
|
153
|
+
"@types/react": "catalog:",
|
|
154
|
+
"@types/react-dom": "catalog:",
|
|
146
155
|
"esbuild": "^0.27.0",
|
|
147
156
|
"jiti": "^2.6.1",
|
|
148
|
-
"react": "
|
|
149
|
-
"react-dom": "
|
|
157
|
+
"react": "catalog:",
|
|
158
|
+
"react-dom": "catalog:",
|
|
150
159
|
"tinyexec": "^0.3.2",
|
|
151
160
|
"typescript": "^5.3.0",
|
|
152
161
|
"vitest": "^4.0.0"
|
|
@@ -164,13 +173,5 @@
|
|
|
164
173
|
"vite": {
|
|
165
174
|
"optional": true
|
|
166
175
|
}
|
|
167
|
-
},
|
|
168
|
-
"scripts": {
|
|
169
|
-
"build": "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.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",
|
|
170
|
-
"typecheck": "tsc --noEmit",
|
|
171
|
-
"test": "playwright test",
|
|
172
|
-
"test:ui": "playwright test --ui",
|
|
173
|
-
"test:unit": "vitest run",
|
|
174
|
-
"test:unit:watch": "vitest"
|
|
175
176
|
}
|
|
176
|
-
}
|
|
177
|
+
}
|