@rangojs/router 0.0.0-experimental.20 → 0.0.0-experimental.20dbba0c
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/README.md +172 -50
- package/dist/bin/rango.js +138 -50
- package/dist/vite/index.js +1160 -508
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +17 -16
- package/skills/breadcrumbs/SKILL.md +252 -0
- package/skills/cache-guide/SKILL.md +32 -0
- package/skills/caching/SKILL.md +49 -8
- package/skills/document-cache/SKILL.md +2 -2
- package/skills/handler-use/SKILL.md +362 -0
- package/skills/hooks/SKILL.md +61 -51
- package/skills/host-router/SKILL.md +218 -0
- package/skills/intercept/SKILL.md +20 -0
- package/skills/layout/SKILL.md +22 -0
- package/skills/links/SKILL.md +91 -17
- package/skills/loader/SKILL.md +107 -24
- package/skills/middleware/SKILL.md +34 -3
- package/skills/migrate-nextjs/SKILL.md +560 -0
- package/skills/migrate-react-router/SKILL.md +765 -0
- package/skills/parallel/SKILL.md +185 -0
- package/skills/prerender/SKILL.md +112 -70
- package/skills/rango/SKILL.md +24 -23
- package/skills/response-routes/SKILL.md +8 -0
- package/skills/route/SKILL.md +58 -4
- package/skills/router-setup/SKILL.md +95 -5
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/typesafety/SKILL.md +38 -24
- package/src/__internal.ts +92 -0
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +5 -0
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +175 -17
- package/src/browser/navigation-client.ts +177 -44
- package/src/browser/navigation-store.ts +68 -9
- package/src/browser/navigation-transaction.ts +11 -9
- package/src/browser/partial-update.ts +113 -17
- package/src/browser/prefetch/cache.ts +275 -28
- package/src/browser/prefetch/fetch.ts +191 -46
- package/src/browser/prefetch/policy.ts +6 -0
- package/src/browser/prefetch/queue.ts +123 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +98 -14
- package/src/browser/react/NavigationProvider.tsx +89 -14
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/use-handle.ts +9 -58
- package/src/browser/react/use-navigation.ts +22 -2
- package/src/browser/react/use-params.ts +11 -1
- package/src/browser/react/use-router.ts +29 -9
- package/src/browser/rsc-router.tsx +177 -66
- package/src/browser/scroll-restoration.ts +41 -42
- package/src/browser/segment-reconciler.ts +36 -9
- package/src/browser/server-action-bridge.ts +8 -6
- package/src/browser/types.ts +73 -5
- package/src/build/generate-manifest.ts +6 -6
- package/src/build/generate-route-types.ts +3 -0
- package/src/build/route-trie.ts +67 -25
- package/src/build/route-types/include-resolution.ts +8 -1
- package/src/build/route-types/router-processing.ts +223 -74
- package/src/build/route-types/scan-filter.ts +8 -1
- package/src/cache/cache-runtime.ts +15 -11
- package/src/cache/cache-scope.ts +48 -7
- package/src/cache/cf/cf-cache-store.ts +455 -15
- 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/cache/taint.ts +55 -0
- package/src/client.rsc.tsx +2 -1
- package/src/client.tsx +85 -276
- package/src/context-var.ts +72 -2
- package/src/debug.ts +2 -2
- package/src/handle.ts +40 -0
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/host/index.ts +0 -3
- package/src/index.rsc.ts +9 -36
- package/src/index.ts +79 -70
- package/src/outlet-context.ts +1 -1
- package/src/prerender/store.ts +57 -15
- package/src/prerender.ts +138 -77
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +27 -2
- package/src/route-definition/dsl-helpers.ts +240 -40
- package/src/route-definition/helpers-types.ts +67 -19
- package/src/route-definition/index.ts +3 -3
- package/src/route-definition/redirect.ts +11 -3
- package/src/route-definition/resolve-handler-use.ts +155 -0
- package/src/route-map-builder.ts +7 -1
- package/src/route-types.ts +18 -0
- package/src/router/content-negotiation.ts +100 -1
- package/src/router/find-match.ts +4 -2
- package/src/router/handler-context.ts +129 -26
- package/src/router/intercept-resolution.ts +11 -4
- package/src/router/lazy-includes.ts +10 -7
- package/src/router/loader-resolution.ts +160 -22
- package/src/router/logging.ts +5 -2
- package/src/router/manifest.ts +31 -16
- package/src/router/match-api.ts +128 -193
- package/src/router/match-middleware/background-revalidation.ts +30 -2
- package/src/router/match-middleware/cache-lookup.ts +94 -17
- 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 +61 -5
- package/src/router/match-result.ts +103 -18
- package/src/router/metrics.ts +238 -13
- package/src/router/middleware-types.ts +48 -27
- package/src/router/middleware.ts +201 -86
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +77 -11
- package/src/router/prerender-match.ts +114 -10
- package/src/router/preview-match.ts +30 -102
- package/src/router/request-classification.ts +310 -0
- package/src/router/revalidation.ts +27 -7
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +6 -1
- package/src/router/router-interfaces.ts +50 -5
- package/src/router/router-options.ts +50 -19
- package/src/router/segment-resolution/fresh.ts +215 -19
- package/src/router/segment-resolution/helpers.ts +30 -25
- package/src/router/segment-resolution/loader-cache.ts +1 -0
- package/src/router/segment-resolution/revalidation.ts +454 -301
- package/src/router/segment-wrappers.ts +2 -0
- package/src/router/trie-matching.ts +30 -6
- package/src/router/types.ts +1 -0
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +89 -17
- package/src/rsc/handler.ts +563 -364
- package/src/rsc/helpers.ts +69 -41
- package/src/rsc/index.ts +0 -20
- package/src/rsc/loader-fetch.ts +23 -3
- package/src/rsc/manifest-init.ts +5 -1
- package/src/rsc/progressive-enhancement.ts +37 -10
- package/src/rsc/response-route-handler.ts +14 -1
- package/src/rsc/rsc-rendering.ts +47 -44
- package/src/rsc/server-action.ts +24 -10
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +11 -1
- package/src/search-params.ts +16 -13
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +109 -23
- package/src/server/context.ts +174 -19
- package/src/server/handle-store.ts +19 -0
- package/src/server/loader-registry.ts +9 -8
- package/src/server/request-context.ts +218 -65
- package/src/server.ts +6 -0
- package/src/ssr/index.tsx +4 -0
- package/src/static-handler.ts +18 -6
- package/src/theme/index.ts +4 -13
- package/src/types/cache-types.ts +4 -4
- package/src/types/handler-context.ts +140 -72
- package/src/types/loader-types.ts +41 -15
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-config.ts +17 -8
- package/src/types/route-entry.ts +19 -1
- package/src/types/segments.ts +2 -5
- package/src/urls/include-helper.ts +24 -14
- package/src/urls/path-helper-types.ts +39 -6
- package/src/urls/path-helper.ts +48 -13
- package/src/urls/pattern-types.ts +12 -0
- package/src/urls/response-types.ts +18 -16
- package/src/use-loader.tsx +77 -5
- package/src/vite/discovery/bundle-postprocess.ts +61 -89
- package/src/vite/discovery/discover-routers.ts +7 -4
- package/src/vite/discovery/prerender-collection.ts +162 -88
- package/src/vite/discovery/state.ts +17 -13
- package/src/vite/index.ts +8 -3
- package/src/vite/plugin-types.ts +51 -79
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
- package/src/vite/plugins/expose-action-id.ts +1 -3
- package/src/vite/plugins/expose-id-utils.ts +12 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +30 -0
- package/src/vite/plugins/expose-internal-ids.ts +257 -40
- package/src/vite/plugins/performance-tracks.ts +88 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/version-plugin.ts +13 -1
- package/src/vite/rango.ts +190 -217
- package/src/vite/router-discovery.ts +241 -45
- package/src/vite/utils/banner.ts +4 -4
- package/src/vite/utils/package-resolution.ts +34 -1
- package/src/vite/utils/prerender-utils.ts +97 -5
- package/src/vite/utils/shared-utils.ts +3 -2
- package/skills/testing/SKILL.md +0 -226
- package/src/route-definition/route-function.ts +0 -119
package/dist/vite/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/vite/rango.ts
|
|
2
2
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
3
|
-
import { resolve as
|
|
3
|
+
import { resolve as resolve9 } from "node:path";
|
|
4
4
|
|
|
5
5
|
// src/vite/plugins/expose-action-id.ts
|
|
6
6
|
import MagicString from "magic-string";
|
|
@@ -18,6 +18,9 @@ function hashId(filePath, exportName) {
|
|
|
18
18
|
const hash = crypto.createHash("sha256").update(input).digest("hex");
|
|
19
19
|
return `${hash.slice(0, 8)}#${exportName}`;
|
|
20
20
|
}
|
|
21
|
+
function makeStubId(filePath, exportName, isBuild) {
|
|
22
|
+
return isBuild ? hashId(filePath, exportName) : `${filePath}#${exportName}`;
|
|
23
|
+
}
|
|
21
24
|
function hashInlineId(filePath, lineNumber, index) {
|
|
22
25
|
const input = index !== void 0 && index > 0 ? `${filePath}:${lineNumber}:${index}` : `${filePath}:${lineNumber}`;
|
|
23
26
|
return crypto.createHash("sha256").update(input).digest("hex").slice(0, 8);
|
|
@@ -292,7 +295,7 @@ function exposeActionId() {
|
|
|
292
295
|
}
|
|
293
296
|
if (!rscPluginApi) {
|
|
294
297
|
throw new Error(
|
|
295
|
-
"[rsc-router] Could not find @vitejs/plugin-rsc. @rangojs/router requires the Vite RSC plugin
|
|
298
|
+
"[rsc-router] Could not find @vitejs/plugin-rsc. @rangojs/router requires the Vite RSC plugin, which is included automatically by rango()."
|
|
296
299
|
);
|
|
297
300
|
}
|
|
298
301
|
if (!isBuild) return;
|
|
@@ -910,9 +913,7 @@ function generateWholeFileStubs(cfg, bindings, code, filePath, isBuild) {
|
|
|
910
913
|
});
|
|
911
914
|
return { code: stubs.join("\n") + "\n", map: null };
|
|
912
915
|
}
|
|
913
|
-
function
|
|
914
|
-
if (bindings.length === 0) return null;
|
|
915
|
-
const s = new MagicString2(code);
|
|
916
|
+
function stubHandlerExprs(cfg, bindings, s, filePath, isBuild) {
|
|
916
917
|
let hasChanges = false;
|
|
917
918
|
for (const binding of bindings) {
|
|
918
919
|
const exportName = binding.exportNames[0];
|
|
@@ -924,15 +925,7 @@ function generateExprStubs(cfg, bindings, code, filePath, sourceId, isBuild) {
|
|
|
924
925
|
);
|
|
925
926
|
hasChanges = true;
|
|
926
927
|
}
|
|
927
|
-
|
|
928
|
-
return {
|
|
929
|
-
code: s.toString(),
|
|
930
|
-
map: s.generateMap({
|
|
931
|
-
source: sourceId,
|
|
932
|
-
includeContent: true,
|
|
933
|
-
hires: "boundary"
|
|
934
|
-
})
|
|
935
|
-
};
|
|
928
|
+
return hasChanges;
|
|
936
929
|
}
|
|
937
930
|
function transformHandlerIds(cfg, bindings, s, filePath, isBuild) {
|
|
938
931
|
let hasChanges = false;
|
|
@@ -1269,15 +1262,6 @@ ${lazyImports.join(",\n")}
|
|
|
1269
1262
|
isBuild
|
|
1270
1263
|
);
|
|
1271
1264
|
if (wholeFile) return wholeFile;
|
|
1272
|
-
const exprStubs = generateExprStubs(
|
|
1273
|
-
PRERENDER_CONFIG,
|
|
1274
|
-
bindings,
|
|
1275
|
-
code,
|
|
1276
|
-
filePath,
|
|
1277
|
-
id,
|
|
1278
|
-
isBuild
|
|
1279
|
-
);
|
|
1280
|
-
if (exprStubs) return exprStubs;
|
|
1281
1265
|
}
|
|
1282
1266
|
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1283
1267
|
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
@@ -1329,15 +1313,134 @@ ${lazyImports.join(",\n")}
|
|
|
1329
1313
|
isBuild
|
|
1330
1314
|
);
|
|
1331
1315
|
if (wholeFile) return wholeFile;
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1316
|
+
}
|
|
1317
|
+
if (!isRscEnv && (hasPrerenderHandlerCode || hasStaticHandlerCode)) {
|
|
1318
|
+
const prerenderFnNames = hasPrerenderHandlerCode ? getFnNames(PRERENDER_CONFIG.fnName) : [];
|
|
1319
|
+
const staticFnNames = hasStaticHandlerCode ? getFnNames(STATIC_CONFIG.fnName) : [];
|
|
1320
|
+
const loaderFnNames = hasLoaderCode ? getFnNames("createLoader") : [];
|
|
1321
|
+
const handleFnNames = hasHandleCode ? getFnNames("createHandle") : [];
|
|
1322
|
+
const lsFnNames = hasLocationStateCode ? getFnNames("createLocationState") : [];
|
|
1323
|
+
const allBindings = [];
|
|
1324
|
+
for (const fnNames of [
|
|
1325
|
+
prerenderFnNames,
|
|
1326
|
+
staticFnNames,
|
|
1327
|
+
loaderFnNames,
|
|
1328
|
+
handleFnNames,
|
|
1329
|
+
lsFnNames
|
|
1330
|
+
]) {
|
|
1331
|
+
if (fnNames.length > 0) {
|
|
1332
|
+
allBindings.push(...getBindings(code, fnNames));
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
let canStubWholeFile = allBindings.length > 0 && isExportOnlyFile(code, allBindings);
|
|
1336
|
+
if (canStubWholeFile && (handleFnNames.length > 0 || lsFnNames.length > 0)) {
|
|
1337
|
+
const exportedLocals = new Set(allBindings.map((b) => b.localName));
|
|
1338
|
+
const strippedBindings = [];
|
|
1339
|
+
const localDeclPattern = /(?:^|;|\n)\s*(?:const|let|var|function)\s+(\w+)/g;
|
|
1340
|
+
let declMatch;
|
|
1341
|
+
while ((declMatch = localDeclPattern.exec(code)) !== null) {
|
|
1342
|
+
const name = declMatch[1];
|
|
1343
|
+
if (!exportedLocals.has(name) && !/^_c\d*$/.test(name)) {
|
|
1344
|
+
strippedBindings.push(name);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
const importPattern = /import\s*\{([^}]*)\}\s*from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1348
|
+
let importMatch;
|
|
1349
|
+
while ((importMatch = importPattern.exec(code)) !== null) {
|
|
1350
|
+
for (const spec of importMatch[1].split(",")) {
|
|
1351
|
+
const m = spec.trim().match(/^[A-Za-z_$][\w$]*(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
|
|
1352
|
+
if (m) strippedBindings.push(m[1] || m[0].trim().split(/\s/)[0]);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
const defaultImportPattern = /import\s+([A-Za-z_$][\w$]*)\s+from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1356
|
+
while ((importMatch = defaultImportPattern.exec(code)) !== null) {
|
|
1357
|
+
strippedBindings.push(importMatch[1]);
|
|
1358
|
+
}
|
|
1359
|
+
const nsImportPattern = /import\s+\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1360
|
+
while ((importMatch = nsImportPattern.exec(code)) !== null) {
|
|
1361
|
+
strippedBindings.push(importMatch[1]);
|
|
1362
|
+
}
|
|
1363
|
+
if (strippedBindings.length > 0) {
|
|
1364
|
+
const preservedBindings = allBindings.filter((b) => {
|
|
1365
|
+
const fc = code.slice(b.callExprStart, b.callOpenParenPos + 1);
|
|
1366
|
+
return handleFnNames.some((n) => fc.includes(n)) || lsFnNames.some((n) => fc.includes(n));
|
|
1367
|
+
});
|
|
1368
|
+
const strippedRe = new RegExp(
|
|
1369
|
+
`\\b(?:${strippedBindings.join("|")})\\b`
|
|
1370
|
+
);
|
|
1371
|
+
canStubWholeFile = !preservedBindings.some((b) => {
|
|
1372
|
+
const expr = code.slice(b.callExprStart, b.callCloseParenPos + 1);
|
|
1373
|
+
return strippedRe.test(expr);
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
if (canStubWholeFile) {
|
|
1378
|
+
const lines = [];
|
|
1379
|
+
const neededImports = [];
|
|
1380
|
+
if (handleFnNames.length > 0) neededImports.push("createHandle");
|
|
1381
|
+
if (lsFnNames.length > 0) neededImports.push("createLocationState");
|
|
1382
|
+
if (neededImports.length > 0) {
|
|
1383
|
+
lines.push(
|
|
1384
|
+
`import { ${neededImports.join(", ")} } from "@rangojs/router";`
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
for (const binding of allBindings) {
|
|
1388
|
+
const fnCall = code.slice(
|
|
1389
|
+
binding.callExprStart,
|
|
1390
|
+
binding.callOpenParenPos + 1
|
|
1391
|
+
);
|
|
1392
|
+
const isHandle = handleFnNames.some((n) => fnCall.includes(n));
|
|
1393
|
+
const isLocationState = lsFnNames.some((n) => fnCall.includes(n));
|
|
1394
|
+
const primaryName = binding.exportNames[0];
|
|
1395
|
+
const stubId = makeStubId(filePath, primaryName, isBuild);
|
|
1396
|
+
if (isHandle || isLocationState) {
|
|
1397
|
+
const rawArgs = code.slice(binding.callOpenParenPos + 1, binding.callCloseParenPos).replace(/\b_c\d*\s*=\s*/g, "");
|
|
1398
|
+
const canonicalName = isHandle ? "createHandle" : "createLocationState";
|
|
1399
|
+
const activeFnNames = isHandle ? handleFnNames : lsFnNames;
|
|
1400
|
+
let rawCallee = code.slice(
|
|
1401
|
+
binding.callExprStart,
|
|
1402
|
+
binding.callOpenParenPos
|
|
1403
|
+
);
|
|
1404
|
+
for (const alias of activeFnNames) {
|
|
1405
|
+
if (alias !== canonicalName && rawCallee.startsWith(alias)) {
|
|
1406
|
+
rawCallee = canonicalName + rawCallee.slice(alias.length);
|
|
1407
|
+
break;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
if (isHandle) {
|
|
1411
|
+
const idParam = binding.argCount === 0 ? `undefined, "${stubId}"` : `, "${stubId}"`;
|
|
1412
|
+
lines.push(
|
|
1413
|
+
`export const ${primaryName} = ${rawCallee}(${rawArgs}${idParam});`
|
|
1414
|
+
);
|
|
1415
|
+
lines.push(`${primaryName}.$$id = "${stubId}";`);
|
|
1416
|
+
} else {
|
|
1417
|
+
lines.push(
|
|
1418
|
+
`export const ${primaryName} = ${rawCallee}(${rawArgs});`
|
|
1419
|
+
);
|
|
1420
|
+
lines.push(
|
|
1421
|
+
`${primaryName}.__rsc_ls_key = "__rsc_ls_${stubId}";`
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1425
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1426
|
+
}
|
|
1427
|
+
} else {
|
|
1428
|
+
let brand = "loader";
|
|
1429
|
+
if (prerenderFnNames.some((n) => fnCall.includes(n))) {
|
|
1430
|
+
brand = PRERENDER_CONFIG.brand;
|
|
1431
|
+
} else if (staticFnNames.some((n) => fnCall.includes(n))) {
|
|
1432
|
+
brand = STATIC_CONFIG.brand;
|
|
1433
|
+
}
|
|
1434
|
+
lines.push(
|
|
1435
|
+
`export const ${primaryName} = { __brand: "${brand}", $$id: "${stubId}" };`
|
|
1436
|
+
);
|
|
1437
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1438
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
return { code: lines.join("\n") + "\n", map: null };
|
|
1443
|
+
}
|
|
1341
1444
|
}
|
|
1342
1445
|
if (hasStaticHandlerCode && isRscEnv && isBuild) {
|
|
1343
1446
|
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
@@ -1372,25 +1475,41 @@ ${lazyImports.join(",\n")}
|
|
|
1372
1475
|
isBuild
|
|
1373
1476
|
) || changed;
|
|
1374
1477
|
}
|
|
1375
|
-
if (hasPrerenderHandlerCode
|
|
1478
|
+
if (hasPrerenderHandlerCode) {
|
|
1376
1479
|
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1480
|
+
const bindings = getBindings(code, fnNames);
|
|
1481
|
+
if (isRscEnv) {
|
|
1482
|
+
changed = transformHandlerIds(
|
|
1483
|
+
PRERENDER_CONFIG,
|
|
1484
|
+
bindings,
|
|
1485
|
+
s,
|
|
1486
|
+
filePath,
|
|
1487
|
+
isBuild
|
|
1488
|
+
) || changed;
|
|
1489
|
+
} else {
|
|
1490
|
+
changed = stubHandlerExprs(
|
|
1491
|
+
PRERENDER_CONFIG,
|
|
1492
|
+
bindings,
|
|
1493
|
+
s,
|
|
1494
|
+
filePath,
|
|
1495
|
+
isBuild
|
|
1496
|
+
) || changed;
|
|
1497
|
+
}
|
|
1384
1498
|
}
|
|
1385
|
-
if (hasStaticHandlerCode
|
|
1499
|
+
if (hasStaticHandlerCode) {
|
|
1386
1500
|
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1501
|
+
const bindings = getBindings(code, fnNames);
|
|
1502
|
+
if (isRscEnv) {
|
|
1503
|
+
changed = transformHandlerIds(
|
|
1504
|
+
STATIC_CONFIG,
|
|
1505
|
+
bindings,
|
|
1506
|
+
s,
|
|
1507
|
+
filePath,
|
|
1508
|
+
isBuild
|
|
1509
|
+
) || changed;
|
|
1510
|
+
} else {
|
|
1511
|
+
changed = stubHandlerExprs(STATIC_CONFIG, bindings, s, filePath, isBuild) || changed;
|
|
1512
|
+
}
|
|
1394
1513
|
}
|
|
1395
1514
|
if (!changed) return;
|
|
1396
1515
|
return {
|
|
@@ -1740,12 +1859,13 @@ function getVirtualVersionContent(version) {
|
|
|
1740
1859
|
|
|
1741
1860
|
// src/vite/utils/package-resolution.ts
|
|
1742
1861
|
import { existsSync } from "node:fs";
|
|
1862
|
+
import { createRequire } from "node:module";
|
|
1743
1863
|
import { resolve } from "node:path";
|
|
1744
1864
|
|
|
1745
1865
|
// package.json
|
|
1746
1866
|
var package_default = {
|
|
1747
1867
|
name: "@rangojs/router",
|
|
1748
|
-
version: "0.0.0-experimental.
|
|
1868
|
+
version: "0.0.0-experimental.20dbba0c",
|
|
1749
1869
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1750
1870
|
keywords: [
|
|
1751
1871
|
"react",
|
|
@@ -1878,16 +1998,16 @@ var package_default = {
|
|
|
1878
1998
|
tag: "experimental"
|
|
1879
1999
|
},
|
|
1880
2000
|
scripts: {
|
|
1881
|
-
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",
|
|
2001
|
+
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",
|
|
1882
2002
|
prepublishOnly: "pnpm build",
|
|
1883
|
-
typecheck: "tsc --noEmit",
|
|
2003
|
+
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit",
|
|
1884
2004
|
test: "playwright test",
|
|
1885
2005
|
"test:ui": "playwright test --ui",
|
|
1886
2006
|
"test:unit": "vitest run",
|
|
1887
2007
|
"test:unit:watch": "vitest"
|
|
1888
2008
|
},
|
|
1889
2009
|
dependencies: {
|
|
1890
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2010
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
1891
2011
|
"magic-string": "^0.30.17",
|
|
1892
2012
|
picomatch: "^4.0.3",
|
|
1893
2013
|
"rsc-html-stream": "^0.0.7"
|
|
@@ -1907,7 +2027,7 @@ var package_default = {
|
|
|
1907
2027
|
},
|
|
1908
2028
|
peerDependencies: {
|
|
1909
2029
|
"@cloudflare/vite-plugin": "^1.25.0",
|
|
1910
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2030
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
1911
2031
|
react: "^18.0.0 || ^19.0.0",
|
|
1912
2032
|
vite: "^7.3.0"
|
|
1913
2033
|
},
|
|
@@ -1922,6 +2042,7 @@ var package_default = {
|
|
|
1922
2042
|
};
|
|
1923
2043
|
|
|
1924
2044
|
// src/vite/utils/package-resolution.ts
|
|
2045
|
+
var require2 = createRequire(import.meta.url);
|
|
1925
2046
|
var VIRTUAL_PACKAGE_NAME = "@rangojs/router";
|
|
1926
2047
|
function getPublishedPackageName() {
|
|
1927
2048
|
return package_default.name;
|
|
@@ -1962,6 +2083,21 @@ function getPackageAliases() {
|
|
|
1962
2083
|
}
|
|
1963
2084
|
return aliases;
|
|
1964
2085
|
}
|
|
2086
|
+
function getVendorAliases() {
|
|
2087
|
+
const specs = [
|
|
2088
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
2089
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
2090
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"
|
|
2091
|
+
];
|
|
2092
|
+
const aliases = {};
|
|
2093
|
+
for (const spec of specs) {
|
|
2094
|
+
try {
|
|
2095
|
+
aliases[spec] = require2.resolve(spec);
|
|
2096
|
+
} catch {
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
return aliases;
|
|
2100
|
+
}
|
|
1965
2101
|
|
|
1966
2102
|
// src/build/route-types/param-extraction.ts
|
|
1967
2103
|
function extractParamsFromPattern(pattern) {
|
|
@@ -2095,31 +2231,7 @@ declare global {
|
|
|
2095
2231
|
}
|
|
2096
2232
|
|
|
2097
2233
|
// src/build/route-types/scan-filter.ts
|
|
2098
|
-
import { join, relative } from "node:path";
|
|
2099
2234
|
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
2235
|
|
|
2124
2236
|
// src/build/route-types/per-module-writer.ts
|
|
2125
2237
|
import ts4 from "typescript";
|
|
@@ -2341,7 +2453,7 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
|
|
|
2341
2453
|
}
|
|
2342
2454
|
return routeMap;
|
|
2343
2455
|
}
|
|
2344
|
-
function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut) {
|
|
2456
|
+
function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut, inlineBlock) {
|
|
2345
2457
|
visited = visited ?? /* @__PURE__ */ new Set();
|
|
2346
2458
|
const realPath = resolve2(filePath);
|
|
2347
2459
|
const key = variableName ? `${realPath}:${variableName}` : realPath;
|
|
@@ -2357,7 +2469,9 @@ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagno
|
|
|
2357
2469
|
return { routes: {}, searchSchemas: {} };
|
|
2358
2470
|
}
|
|
2359
2471
|
let block;
|
|
2360
|
-
if (
|
|
2472
|
+
if (inlineBlock) {
|
|
2473
|
+
block = inlineBlock;
|
|
2474
|
+
} else if (variableName) {
|
|
2361
2475
|
const extracted = extractUrlsBlockForVariable(source, variableName);
|
|
2362
2476
|
if (!extracted) return { routes: {}, searchSchemas: {} };
|
|
2363
2477
|
block = extracted;
|
|
@@ -2386,7 +2500,7 @@ import {
|
|
|
2386
2500
|
readdirSync
|
|
2387
2501
|
} from "node:fs";
|
|
2388
2502
|
import {
|
|
2389
|
-
join
|
|
2503
|
+
join,
|
|
2390
2504
|
dirname as dirname2,
|
|
2391
2505
|
resolve as resolve3,
|
|
2392
2506
|
sep,
|
|
@@ -2406,7 +2520,7 @@ function countPublicRouteEntries(source) {
|
|
|
2406
2520
|
}
|
|
2407
2521
|
var ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
|
|
2408
2522
|
function isRoutableSourceFile(name) {
|
|
2409
|
-
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.");
|
|
2523
|
+
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
2410
2524
|
}
|
|
2411
2525
|
function findRouterFilesRecursive(dir, filter, results) {
|
|
2412
2526
|
let entries;
|
|
@@ -2421,9 +2535,10 @@ function findRouterFilesRecursive(dir, filter, results) {
|
|
|
2421
2535
|
const childDirs = [];
|
|
2422
2536
|
const routerFilesInDir = [];
|
|
2423
2537
|
for (const entry of entries) {
|
|
2424
|
-
const fullPath =
|
|
2538
|
+
const fullPath = join(dir, entry.name);
|
|
2425
2539
|
if (entry.isDirectory()) {
|
|
2426
|
-
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
2540
|
+
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "coverage" || entry.name === "__tests__" || entry.name === "__mocks__" || entry.name.startsWith("."))
|
|
2541
|
+
continue;
|
|
2427
2542
|
childDirs.push(fullPath);
|
|
2428
2543
|
continue;
|
|
2429
2544
|
}
|
|
@@ -2475,7 +2590,7 @@ Router root: ${conflict.ancestor}
|
|
|
2475
2590
|
Nested router: ${conflict.nested}
|
|
2476
2591
|
Move the nested router into a sibling directory or configure it as a separate app root.`;
|
|
2477
2592
|
}
|
|
2478
|
-
function
|
|
2593
|
+
function extractUrlsFromRouter(code) {
|
|
2479
2594
|
const sourceFile = ts5.createSourceFile(
|
|
2480
2595
|
"router.tsx",
|
|
2481
2596
|
code,
|
|
@@ -2489,24 +2604,70 @@ function extractUrlsVariableFromRouter(code) {
|
|
|
2489
2604
|
const callee = node.expression;
|
|
2490
2605
|
return ts5.isIdentifier(callee) && callee.text === "createRouter";
|
|
2491
2606
|
}
|
|
2607
|
+
function isInlineBuilder(node) {
|
|
2608
|
+
return ts5.isArrowFunction(node) || ts5.isFunctionExpression(node);
|
|
2609
|
+
}
|
|
2610
|
+
function isRoutesOnCreateRouter(node) {
|
|
2611
|
+
if (!ts5.isPropertyAccessExpression(node.expression) || node.expression.name.text !== "routes")
|
|
2612
|
+
return false;
|
|
2613
|
+
let inner = node.expression.expression;
|
|
2614
|
+
while (ts5.isCallExpression(inner) && ts5.isPropertyAccessExpression(inner.expression)) {
|
|
2615
|
+
inner = inner.expression.expression;
|
|
2616
|
+
}
|
|
2617
|
+
return isCreateRouterCall(inner);
|
|
2618
|
+
}
|
|
2492
2619
|
function visit(node) {
|
|
2493
2620
|
if (result) return;
|
|
2494
|
-
if (ts5.isCallExpression(node) &&
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
}
|
|
2499
|
-
|
|
2500
|
-
result = node.arguments[0].text;
|
|
2501
|
-
return;
|
|
2621
|
+
if (ts5.isCallExpression(node) && node.arguments.length >= 1 && isRoutesOnCreateRouter(node)) {
|
|
2622
|
+
const arg = node.arguments[0];
|
|
2623
|
+
if (ts5.isIdentifier(arg)) {
|
|
2624
|
+
result = { kind: "variable", name: arg.text };
|
|
2625
|
+
} else if (isInlineBuilder(arg)) {
|
|
2626
|
+
result = { kind: "inline", block: arg.getText(sourceFile) };
|
|
2502
2627
|
}
|
|
2628
|
+
return;
|
|
2503
2629
|
}
|
|
2504
2630
|
if (isCreateRouterCall(node)) {
|
|
2505
2631
|
const callExpr = node;
|
|
2506
|
-
for (const
|
|
2632
|
+
for (const callArg of callExpr.arguments) {
|
|
2633
|
+
if (ts5.isObjectLiteralExpression(callArg)) {
|
|
2634
|
+
for (const prop of callArg.properties) {
|
|
2635
|
+
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "urls") {
|
|
2636
|
+
if (ts5.isIdentifier(prop.initializer)) {
|
|
2637
|
+
result = { kind: "variable", name: prop.initializer.text };
|
|
2638
|
+
} else if (isInlineBuilder(prop.initializer)) {
|
|
2639
|
+
result = {
|
|
2640
|
+
kind: "inline",
|
|
2641
|
+
block: prop.initializer.getText(sourceFile)
|
|
2642
|
+
};
|
|
2643
|
+
}
|
|
2644
|
+
return;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
ts5.forEachChild(node, visit);
|
|
2651
|
+
}
|
|
2652
|
+
visit(sourceFile);
|
|
2653
|
+
return result;
|
|
2654
|
+
}
|
|
2655
|
+
function extractBasenameFromRouter(code) {
|
|
2656
|
+
const sourceFile = ts5.createSourceFile(
|
|
2657
|
+
"router.tsx",
|
|
2658
|
+
code,
|
|
2659
|
+
ts5.ScriptTarget.Latest,
|
|
2660
|
+
true,
|
|
2661
|
+
ts5.ScriptKind.TSX
|
|
2662
|
+
);
|
|
2663
|
+
let result;
|
|
2664
|
+
function visit(node) {
|
|
2665
|
+
if (result !== void 0) return;
|
|
2666
|
+
if (ts5.isCallExpression(node) && ts5.isIdentifier(node.expression) && node.expression.text === "createRouter") {
|
|
2667
|
+
for (const arg of node.arguments) {
|
|
2507
2668
|
if (ts5.isObjectLiteralExpression(arg)) {
|
|
2508
2669
|
for (const prop of arg.properties) {
|
|
2509
|
-
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "
|
|
2670
|
+
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "basename" && ts5.isStringLiteral(prop.initializer)) {
|
|
2510
2671
|
result = prop.initializer.text;
|
|
2511
2672
|
return;
|
|
2512
2673
|
}
|
|
@@ -2519,6 +2680,19 @@ function extractUrlsVariableFromRouter(code) {
|
|
|
2519
2680
|
visit(sourceFile);
|
|
2520
2681
|
return result;
|
|
2521
2682
|
}
|
|
2683
|
+
function applyBasenameToRoutes(result, basename3) {
|
|
2684
|
+
const prefixed = {};
|
|
2685
|
+
for (const [name, pattern] of Object.entries(result.routes)) {
|
|
2686
|
+
if (pattern === "/") {
|
|
2687
|
+
prefixed[name] = basename3;
|
|
2688
|
+
} else if (basename3.endsWith("/") && pattern.startsWith("/")) {
|
|
2689
|
+
prefixed[name] = basename3 + pattern.slice(1);
|
|
2690
|
+
} else {
|
|
2691
|
+
prefixed[name] = basename3 + pattern;
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
return { routes: prefixed, searchSchemas: result.searchSchemas };
|
|
2695
|
+
}
|
|
2522
2696
|
function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
2523
2697
|
let routerSource;
|
|
2524
2698
|
try {
|
|
@@ -2526,19 +2700,40 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
|
2526
2700
|
} catch {
|
|
2527
2701
|
return { routes: {}, searchSchemas: {} };
|
|
2528
2702
|
}
|
|
2529
|
-
const
|
|
2530
|
-
if (!
|
|
2703
|
+
const extraction = extractUrlsFromRouter(routerSource);
|
|
2704
|
+
if (!extraction) {
|
|
2531
2705
|
return { routes: {}, searchSchemas: {} };
|
|
2532
2706
|
}
|
|
2533
|
-
const
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2707
|
+
const rawBasename = extractBasenameFromRouter(routerSource);
|
|
2708
|
+
const basename3 = rawBasename ? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "") : void 0;
|
|
2709
|
+
let result;
|
|
2710
|
+
if (extraction.kind === "inline") {
|
|
2711
|
+
result = buildCombinedRouteMapWithSearch(
|
|
2712
|
+
routerFilePath,
|
|
2713
|
+
void 0,
|
|
2714
|
+
void 0,
|
|
2715
|
+
void 0,
|
|
2716
|
+
extraction.block
|
|
2717
|
+
);
|
|
2718
|
+
} else {
|
|
2719
|
+
const imported = resolveImportedVariable(routerSource, extraction.name);
|
|
2720
|
+
if (imported) {
|
|
2721
|
+
const targetFile = resolveImportPath(imported.specifier, routerFilePath);
|
|
2722
|
+
if (!targetFile) {
|
|
2723
|
+
return { routes: {}, searchSchemas: {} };
|
|
2724
|
+
}
|
|
2725
|
+
result = buildCombinedRouteMapWithSearch(
|
|
2726
|
+
targetFile,
|
|
2727
|
+
imported.exportedName
|
|
2728
|
+
);
|
|
2729
|
+
} else {
|
|
2730
|
+
result = buildCombinedRouteMapWithSearch(routerFilePath, extraction.name);
|
|
2538
2731
|
}
|
|
2539
|
-
return buildCombinedRouteMapWithSearch(targetFile, imported.exportedName);
|
|
2540
2732
|
}
|
|
2541
|
-
|
|
2733
|
+
if (basename3) {
|
|
2734
|
+
result = applyBasenameToRoutes(result, basename3);
|
|
2735
|
+
}
|
|
2736
|
+
return result;
|
|
2542
2737
|
}
|
|
2543
2738
|
function findRouterFiles(root, filter) {
|
|
2544
2739
|
const result = [];
|
|
@@ -2547,7 +2742,7 @@ function findRouterFiles(root, filter) {
|
|
|
2547
2742
|
}
|
|
2548
2743
|
function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
2549
2744
|
try {
|
|
2550
|
-
const oldCombinedPath =
|
|
2745
|
+
const oldCombinedPath = join(root, "src", "named-routes.gen.ts");
|
|
2551
2746
|
if (existsSync3(oldCombinedPath)) {
|
|
2552
2747
|
unlinkSync(oldCombinedPath);
|
|
2553
2748
|
console.log(
|
|
@@ -2563,31 +2758,21 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
2563
2758
|
throw new Error(formatNestedRouterConflictError(nestedRouterConflict));
|
|
2564
2759
|
}
|
|
2565
2760
|
for (const routerFilePath of routerFilePaths) {
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
routerSource
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
const imported = resolveImportedVariable(routerSource, urlsVarName);
|
|
2576
|
-
if (imported) {
|
|
2577
|
-
const targetFile = resolveImportPath(imported.specifier, routerFilePath);
|
|
2578
|
-
if (!targetFile) continue;
|
|
2579
|
-
result = buildCombinedRouteMapWithSearch(
|
|
2580
|
-
targetFile,
|
|
2581
|
-
imported.exportedName
|
|
2582
|
-
);
|
|
2583
|
-
} else {
|
|
2584
|
-
result = buildCombinedRouteMapWithSearch(routerFilePath, urlsVarName);
|
|
2761
|
+
const result = buildCombinedRouteMapForRouterFile(routerFilePath);
|
|
2762
|
+
if (Object.keys(result.routes).length === 0 && Object.keys(result.searchSchemas).length === 0) {
|
|
2763
|
+
let routerSource;
|
|
2764
|
+
try {
|
|
2765
|
+
routerSource = readFileSync2(routerFilePath, "utf-8");
|
|
2766
|
+
} catch {
|
|
2767
|
+
continue;
|
|
2768
|
+
}
|
|
2769
|
+
if (!extractUrlsFromRouter(routerSource)) continue;
|
|
2585
2770
|
}
|
|
2586
2771
|
const routerBasename = pathBasename(routerFilePath).replace(
|
|
2587
2772
|
/\.(tsx?|jsx?)$/,
|
|
2588
2773
|
""
|
|
2589
2774
|
);
|
|
2590
|
-
const outPath =
|
|
2775
|
+
const outPath = join(
|
|
2591
2776
|
dirname2(routerFilePath),
|
|
2592
2777
|
`${routerBasename}.named-routes.gen.ts`
|
|
2593
2778
|
);
|
|
@@ -2717,8 +2902,9 @@ function createVersionPlugin() {
|
|
|
2717
2902
|
let isDev = false;
|
|
2718
2903
|
let server = null;
|
|
2719
2904
|
const clientModuleSignatures = /* @__PURE__ */ new Map();
|
|
2905
|
+
let versionCounter = 0;
|
|
2720
2906
|
const bumpVersion = (reason) => {
|
|
2721
|
-
currentVersion = Date.now().toString(16);
|
|
2907
|
+
currentVersion = Date.now().toString(16) + String(++versionCounter);
|
|
2722
2908
|
console.log(`[rsc-router] ${reason}, version updated: ${currentVersion}`);
|
|
2723
2909
|
const rscEnv = server?.environments?.rsc;
|
|
2724
2910
|
const versionMod = rscEnv?.moduleGraph?.getModuleById(
|
|
@@ -2774,6 +2960,9 @@ function createVersionPlugin() {
|
|
|
2774
2960
|
if (!isDev) return;
|
|
2775
2961
|
const isRscModule = this.environment?.name === "rsc";
|
|
2776
2962
|
if (!isRscModule) return;
|
|
2963
|
+
if (ctx.modules.length === 1 && ctx.modules[0].id === "\0" + VIRTUAL_IDS.version) {
|
|
2964
|
+
return;
|
|
2965
|
+
}
|
|
2777
2966
|
if (isCodeModule(ctx.file)) {
|
|
2778
2967
|
const filePath = normalizeModuleId(ctx.file);
|
|
2779
2968
|
const previousSignature = clientModuleSignatures.get(filePath);
|
|
@@ -2803,6 +2992,68 @@ function createVersionPlugin() {
|
|
|
2803
2992
|
|
|
2804
2993
|
// src/vite/utils/shared-utils.ts
|
|
2805
2994
|
import * as Vite from "vite";
|
|
2995
|
+
|
|
2996
|
+
// src/vite/plugins/performance-tracks.ts
|
|
2997
|
+
import { readFile } from "node:fs/promises";
|
|
2998
|
+
var RSDW_PATCH_RE = /((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
2999
|
+
function buildPatchReplacement(match, debugInfoVar) {
|
|
3000
|
+
return `${match}
|
|
3001
|
+
if (${debugInfoVar} && 0 === ${debugInfoVar}.length && "fulfilled" === root.status) {
|
|
3002
|
+
var _resolved = "function" === typeof resolveLazy ? resolveLazy(root.value) : root.value;
|
|
3003
|
+
if ("object" === typeof _resolved && null !== _resolved && isArrayImpl(_resolved._debugInfo)) {
|
|
3004
|
+
${debugInfoVar} = _resolved._debugInfo;
|
|
3005
|
+
}
|
|
3006
|
+
}`;
|
|
3007
|
+
}
|
|
3008
|
+
function patchRsdwClientDebugInfoRecovery(code) {
|
|
3009
|
+
const match = code.match(RSDW_PATCH_RE);
|
|
3010
|
+
if (!match) {
|
|
3011
|
+
return { code, debugInfoVar: null };
|
|
3012
|
+
}
|
|
3013
|
+
return {
|
|
3014
|
+
code: code.replace(match[1], buildPatchReplacement(match[1], match[2])),
|
|
3015
|
+
debugInfoVar: match[2]
|
|
3016
|
+
};
|
|
3017
|
+
}
|
|
3018
|
+
function performanceTracksOptimizeDepsPlugin() {
|
|
3019
|
+
return {
|
|
3020
|
+
name: "@rangojs/router:performance-tracks-optimize-deps",
|
|
3021
|
+
setup(build) {
|
|
3022
|
+
build.onLoad(
|
|
3023
|
+
{
|
|
3024
|
+
filter: /react-server-dom-webpack-client\.browser\.(development|production)\.js$/
|
|
3025
|
+
},
|
|
3026
|
+
async (args) => {
|
|
3027
|
+
const code = await readFile(args.path, "utf8");
|
|
3028
|
+
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
3029
|
+
return {
|
|
3030
|
+
contents: patched.code,
|
|
3031
|
+
loader: "js"
|
|
3032
|
+
};
|
|
3033
|
+
}
|
|
3034
|
+
);
|
|
3035
|
+
}
|
|
3036
|
+
};
|
|
3037
|
+
}
|
|
3038
|
+
function performanceTracksPlugin() {
|
|
3039
|
+
return {
|
|
3040
|
+
name: "@rangojs/router:performance-tracks",
|
|
3041
|
+
transform(code, id) {
|
|
3042
|
+
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
3043
|
+
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
3044
|
+
if (!patched.debugInfoVar) return;
|
|
3045
|
+
if (process.env.INTERNAL_RANGO_DEBUG)
|
|
3046
|
+
console.log(
|
|
3047
|
+
"[perf-tracks] patched RSDW client (var:",
|
|
3048
|
+
patched.debugInfoVar,
|
|
3049
|
+
")"
|
|
3050
|
+
);
|
|
3051
|
+
return patched.code;
|
|
3052
|
+
}
|
|
3053
|
+
};
|
|
3054
|
+
}
|
|
3055
|
+
|
|
3056
|
+
// src/vite/utils/shared-utils.ts
|
|
2806
3057
|
var versionEsbuildPlugin = {
|
|
2807
3058
|
name: "@rangojs/router-version",
|
|
2808
3059
|
setup(build) {
|
|
@@ -2820,7 +3071,7 @@ var versionEsbuildPlugin = {
|
|
|
2820
3071
|
}
|
|
2821
3072
|
};
|
|
2822
3073
|
var sharedEsbuildOptions = {
|
|
2823
|
-
plugins: [versionEsbuildPlugin]
|
|
3074
|
+
plugins: [versionEsbuildPlugin, performanceTracksOptimizeDepsPlugin()]
|
|
2824
3075
|
};
|
|
2825
3076
|
function createVirtualEntriesPlugin(entries, routerPathRef) {
|
|
2826
3077
|
const virtualModules = {};
|
|
@@ -2903,11 +3154,11 @@ ${dim} \u2571${reset} ${bold}\u2554\u2550\u2557${reset}${dim} * \u2
|
|
|
2903
3154
|
${dim} ${reset}${bold}\u2551 \u2551${reset} ${bold}\u2554\u2550\u2557${reset}${dim} * \u2727. \u2571${reset}
|
|
2904
3155
|
${dim} ${reset}${bold}\u2554\u2557 \u2551 \u2551 \u2551 \u2551${reset}${dim} * \u2571${reset}
|
|
2905
3156
|
${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}
|
|
3157
|
+
${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
3158
|
${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
3159
|
${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\
|
|
3160
|
+
${dim} * ${reset}${bold}\u2551 \u2551${reset}${dim} * \u2727. \u2571${reset}
|
|
3161
|
+
${dim} ${reset}${bold}\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550${reset}${dim} \u2726 *${reset}
|
|
2911
3162
|
|
|
2912
3163
|
v${version} \xB7 ${preset} \xB7 ${mode}
|
|
2913
3164
|
`;
|
|
@@ -3024,8 +3275,10 @@ function createCjsToEsmPlugin() {
|
|
|
3024
3275
|
|
|
3025
3276
|
// src/vite/router-discovery.ts
|
|
3026
3277
|
import { createServer as createViteServer } from "vite";
|
|
3027
|
-
import { resolve as
|
|
3278
|
+
import { resolve as resolve8 } from "node:path";
|
|
3028
3279
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
3280
|
+
import { createRequire as createRequire2, register } from "node:module";
|
|
3281
|
+
import { pathToFileURL } from "node:url";
|
|
3029
3282
|
|
|
3030
3283
|
// src/vite/plugins/virtual-stub-plugin.ts
|
|
3031
3284
|
function createVirtualStubPlugin() {
|
|
@@ -3051,8 +3304,115 @@ function createVirtualStubPlugin() {
|
|
|
3051
3304
|
};
|
|
3052
3305
|
}
|
|
3053
3306
|
|
|
3307
|
+
// src/vite/plugins/cloudflare-protocol-stub.ts
|
|
3308
|
+
var VIRTUAL_PREFIX = "virtual:rango-cloudflare-stub-";
|
|
3309
|
+
var NULL_PREFIX = "\0" + VIRTUAL_PREFIX;
|
|
3310
|
+
var CF_PREFIX = "cloudflare:";
|
|
3311
|
+
var BUILD_ENV_GLOBAL_KEY = "__rango_build_env__";
|
|
3312
|
+
var SOURCE_EXT_RE = /\.[mc]?[jt]sx?$/;
|
|
3313
|
+
var IMPORT_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
3314
|
+
"ImportDeclaration",
|
|
3315
|
+
"ImportExpression",
|
|
3316
|
+
"ExportNamedDeclaration",
|
|
3317
|
+
"ExportAllDeclaration"
|
|
3318
|
+
]);
|
|
3319
|
+
var STUBS = {
|
|
3320
|
+
"cloudflare:workers": `
|
|
3321
|
+
export class DurableObject { constructor(_ctx, _env) {} }
|
|
3322
|
+
export class WorkerEntrypoint { constructor(_ctx, _env) {} }
|
|
3323
|
+
export class WorkflowEntrypoint { constructor(_ctx, _env) {} }
|
|
3324
|
+
export class RpcTarget {}
|
|
3325
|
+
export const env = globalThis[${JSON.stringify(BUILD_ENV_GLOBAL_KEY)}] ?? {};
|
|
3326
|
+
export default {};
|
|
3327
|
+
`,
|
|
3328
|
+
"cloudflare:email": `
|
|
3329
|
+
export class EmailMessage { constructor(_from, _to, _raw) {} }
|
|
3330
|
+
export default {};
|
|
3331
|
+
`,
|
|
3332
|
+
"cloudflare:sockets": `
|
|
3333
|
+
export function connect() { return {}; }
|
|
3334
|
+
export default {};
|
|
3335
|
+
`,
|
|
3336
|
+
"cloudflare:workflows": `
|
|
3337
|
+
export class NonRetryableError extends Error {
|
|
3338
|
+
constructor(message, name) { super(message); this.name = name ?? "NonRetryableError"; }
|
|
3339
|
+
}
|
|
3340
|
+
export default {};
|
|
3341
|
+
`
|
|
3342
|
+
};
|
|
3343
|
+
var FALLBACK_STUB = `export default {};
|
|
3344
|
+
`;
|
|
3345
|
+
function createCloudflareProtocolStubPlugin() {
|
|
3346
|
+
return {
|
|
3347
|
+
name: "@rangojs/router:cloudflare-protocol-stub",
|
|
3348
|
+
transform(code, id) {
|
|
3349
|
+
const cleanId = id.split("?")[0] ?? id;
|
|
3350
|
+
if (!SOURCE_EXT_RE.test(cleanId)) return null;
|
|
3351
|
+
if (!code.includes(CF_PREFIX)) return null;
|
|
3352
|
+
let ast;
|
|
3353
|
+
try {
|
|
3354
|
+
ast = this.parse(code);
|
|
3355
|
+
} catch {
|
|
3356
|
+
return null;
|
|
3357
|
+
}
|
|
3358
|
+
const hits = [];
|
|
3359
|
+
walk(ast, (node) => {
|
|
3360
|
+
if (!IMPORT_NODE_TYPES.has(node.type)) return;
|
|
3361
|
+
const source = node.source;
|
|
3362
|
+
if (!source || source.type !== "Literal") return;
|
|
3363
|
+
if (typeof source.value !== "string") return;
|
|
3364
|
+
if (!source.value.startsWith(CF_PREFIX)) return;
|
|
3365
|
+
if (typeof source.start !== "number" || typeof source.end !== "number")
|
|
3366
|
+
return;
|
|
3367
|
+
hits.push({
|
|
3368
|
+
start: source.start,
|
|
3369
|
+
end: source.end,
|
|
3370
|
+
value: source.value
|
|
3371
|
+
});
|
|
3372
|
+
});
|
|
3373
|
+
if (hits.length === 0) return null;
|
|
3374
|
+
hits.sort((a, b) => b.start - a.start);
|
|
3375
|
+
let out = code;
|
|
3376
|
+
for (const hit of hits) {
|
|
3377
|
+
const submodule = hit.value.slice(CF_PREFIX.length);
|
|
3378
|
+
const quote = code[hit.start] === "'" ? "'" : '"';
|
|
3379
|
+
out = out.slice(0, hit.start) + quote + VIRTUAL_PREFIX + submodule + quote + out.slice(hit.end);
|
|
3380
|
+
}
|
|
3381
|
+
return { code: out, map: null };
|
|
3382
|
+
},
|
|
3383
|
+
resolveId(id) {
|
|
3384
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
3385
|
+
return "\0" + id;
|
|
3386
|
+
}
|
|
3387
|
+
return null;
|
|
3388
|
+
},
|
|
3389
|
+
load(id) {
|
|
3390
|
+
if (!id.startsWith(NULL_PREFIX)) return null;
|
|
3391
|
+
const submodule = id.slice(NULL_PREFIX.length);
|
|
3392
|
+
const specifier = CF_PREFIX + submodule;
|
|
3393
|
+
return STUBS[specifier] ?? FALLBACK_STUB;
|
|
3394
|
+
}
|
|
3395
|
+
};
|
|
3396
|
+
}
|
|
3397
|
+
function walk(node, visit) {
|
|
3398
|
+
if (!node || typeof node !== "object") return;
|
|
3399
|
+
if (Array.isArray(node)) {
|
|
3400
|
+
for (const child of node) walk(child, visit);
|
|
3401
|
+
return;
|
|
3402
|
+
}
|
|
3403
|
+
const n = node;
|
|
3404
|
+
if (typeof n.type !== "string") return;
|
|
3405
|
+
visit(n);
|
|
3406
|
+
for (const key in n) {
|
|
3407
|
+
if (key === "loc" || key === "start" || key === "end" || key === "range") {
|
|
3408
|
+
continue;
|
|
3409
|
+
}
|
|
3410
|
+
walk(n[key], visit);
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3054
3414
|
// src/vite/plugins/client-ref-hashing.ts
|
|
3055
|
-
import { relative
|
|
3415
|
+
import { relative } from "node:path";
|
|
3056
3416
|
import { createHash as createHash2 } from "node:crypto";
|
|
3057
3417
|
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3058
3418
|
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
@@ -3065,10 +3425,10 @@ function computeProductionHash(projectRoot, refKey) {
|
|
|
3065
3425
|
const absPath = decodeURIComponent(
|
|
3066
3426
|
refKey.slice(CLIENT_IN_SERVER_PKG_PROXY_PREFIX.length)
|
|
3067
3427
|
);
|
|
3068
|
-
toHash =
|
|
3428
|
+
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3069
3429
|
} else if (refKey.startsWith(FS_PREFIX)) {
|
|
3070
3430
|
const absPath = refKey.slice(FS_PREFIX.length - 1);
|
|
3071
|
-
toHash =
|
|
3431
|
+
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3072
3432
|
} else if (refKey.startsWith("/")) {
|
|
3073
3433
|
toHash = refKey.slice(1);
|
|
3074
3434
|
} else {
|
|
@@ -3207,10 +3567,10 @@ function createDiscoveryState(entryPath, opts) {
|
|
|
3207
3567
|
perRouterTrieMap: /* @__PURE__ */ new Map(),
|
|
3208
3568
|
perRouterPrecomputedMap: /* @__PURE__ */ new Map(),
|
|
3209
3569
|
perRouterManifestDataMap: /* @__PURE__ */ new Map(),
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3570
|
+
prerenderManifestEntries: null,
|
|
3571
|
+
staticManifestEntries: null,
|
|
3572
|
+
handlerChunkInfoMap: /* @__PURE__ */ new Map(),
|
|
3573
|
+
staticHandlerChunkInfoMap: /* @__PURE__ */ new Map(),
|
|
3214
3574
|
rscEntryFileName: null,
|
|
3215
3575
|
resolvedPrerenderModules: void 0,
|
|
3216
3576
|
resolvedStaticModules: void 0,
|
|
@@ -3293,8 +3653,17 @@ function jsonParseExpression(value) {
|
|
|
3293
3653
|
}
|
|
3294
3654
|
|
|
3295
3655
|
// src/context-var.ts
|
|
3656
|
+
var NON_CACHEABLE_KEYS = /* @__PURE__ */ Symbol.for(
|
|
3657
|
+
"rango:non-cacheable-keys"
|
|
3658
|
+
);
|
|
3659
|
+
function getNonCacheableKeys(variables) {
|
|
3660
|
+
if (!variables[NON_CACHEABLE_KEYS]) {
|
|
3661
|
+
variables[NON_CACHEABLE_KEYS] = /* @__PURE__ */ new Set();
|
|
3662
|
+
}
|
|
3663
|
+
return variables[NON_CACHEABLE_KEYS];
|
|
3664
|
+
}
|
|
3296
3665
|
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
3297
|
-
function contextSet(variables, keyOrVar, value) {
|
|
3666
|
+
function contextSet(variables, keyOrVar, value, options) {
|
|
3298
3667
|
if (typeof keyOrVar === "string") {
|
|
3299
3668
|
if (FORBIDDEN_KEYS.has(keyOrVar)) {
|
|
3300
3669
|
throw new Error(
|
|
@@ -3302,12 +3671,28 @@ function contextSet(variables, keyOrVar, value) {
|
|
|
3302
3671
|
);
|
|
3303
3672
|
}
|
|
3304
3673
|
variables[keyOrVar] = value;
|
|
3674
|
+
if (options?.cache === false) {
|
|
3675
|
+
getNonCacheableKeys(variables).add(keyOrVar);
|
|
3676
|
+
}
|
|
3305
3677
|
} else {
|
|
3306
3678
|
variables[keyOrVar.key] = value;
|
|
3679
|
+
if (options?.cache === false) {
|
|
3680
|
+
getNonCacheableKeys(variables).add(keyOrVar.key);
|
|
3681
|
+
}
|
|
3307
3682
|
}
|
|
3308
3683
|
}
|
|
3309
3684
|
|
|
3310
3685
|
// src/vite/utils/prerender-utils.ts
|
|
3686
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
3687
|
+
import {
|
|
3688
|
+
copyFileSync,
|
|
3689
|
+
existsSync as existsSync4,
|
|
3690
|
+
mkdirSync,
|
|
3691
|
+
rmSync,
|
|
3692
|
+
statSync,
|
|
3693
|
+
writeFileSync as writeFileSync2
|
|
3694
|
+
} from "node:fs";
|
|
3695
|
+
import { resolve as resolve5 } from "node:path";
|
|
3311
3696
|
function escapeRegExp2(str) {
|
|
3312
3697
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3313
3698
|
}
|
|
@@ -3316,13 +3701,31 @@ function encodePathParam(value) {
|
|
|
3316
3701
|
}
|
|
3317
3702
|
function substituteRouteParams(pattern, params, encode = encodeURIComponent) {
|
|
3318
3703
|
let result = pattern;
|
|
3704
|
+
let hadOmittedOptional = false;
|
|
3319
3705
|
for (const [key, value] of Object.entries(params)) {
|
|
3320
3706
|
const escaped = escapeRegExp2(key);
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3707
|
+
if (value === "") {
|
|
3708
|
+
result = result.replace(
|
|
3709
|
+
new RegExp(`:${escaped}(\\([^)]*\\))?(?!\\?)`),
|
|
3710
|
+
""
|
|
3711
|
+
);
|
|
3712
|
+
result = result.replace(`*${key}`, "");
|
|
3713
|
+
} else {
|
|
3714
|
+
result = result.replace(
|
|
3715
|
+
new RegExp(`:${escaped}(\\([^)]*\\))?\\??`),
|
|
3716
|
+
encode(value)
|
|
3717
|
+
);
|
|
3718
|
+
result = result.replace(`*${key}`, encode(value));
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
result = result.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?\?/g, () => {
|
|
3722
|
+
hadOmittedOptional = true;
|
|
3723
|
+
return "";
|
|
3724
|
+
});
|
|
3725
|
+
if (hadOmittedOptional) {
|
|
3726
|
+
const hadTrailingSlash = pattern.length > 1 && pattern.endsWith("/");
|
|
3727
|
+
result = result.replace(/\/\/+/g, "/").replace(/\/+$/, "") || "/";
|
|
3728
|
+
if (hadTrailingSlash && !result.endsWith("/")) result += "/";
|
|
3326
3729
|
}
|
|
3327
3730
|
return result;
|
|
3328
3731
|
}
|
|
@@ -3386,6 +3789,37 @@ function notifyOnError(registry, error, phase, routeKey, pathname, skipped) {
|
|
|
3386
3789
|
break;
|
|
3387
3790
|
}
|
|
3388
3791
|
}
|
|
3792
|
+
function getStagedAssetDir(projectRoot) {
|
|
3793
|
+
return resolve5(projectRoot, "node_modules/.rangojs-router-build/rsc-assets");
|
|
3794
|
+
}
|
|
3795
|
+
function resetStagedBuildAssets(projectRoot) {
|
|
3796
|
+
rmSync(getStagedAssetDir(projectRoot), { recursive: true, force: true });
|
|
3797
|
+
}
|
|
3798
|
+
function stageBuildAssetModule(projectRoot, prefix, exportValue) {
|
|
3799
|
+
const stagedDir = getStagedAssetDir(projectRoot);
|
|
3800
|
+
mkdirSync(stagedDir, { recursive: true });
|
|
3801
|
+
const contentHash = createHash4("sha256").update(exportValue).digest("hex").slice(0, 8);
|
|
3802
|
+
const fileName = `${prefix}-${contentHash}.js`;
|
|
3803
|
+
const filePath = resolve5(stagedDir, fileName);
|
|
3804
|
+
if (!existsSync4(filePath)) {
|
|
3805
|
+
writeFileSync2(filePath, `export default ${exportValue};
|
|
3806
|
+
`);
|
|
3807
|
+
}
|
|
3808
|
+
return fileName;
|
|
3809
|
+
}
|
|
3810
|
+
function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
3811
|
+
const stagedDir = getStagedAssetDir(projectRoot);
|
|
3812
|
+
const distAssetsDir = resolve5(projectRoot, "dist/rsc/assets");
|
|
3813
|
+
mkdirSync(distAssetsDir, { recursive: true });
|
|
3814
|
+
let totalBytes = 0;
|
|
3815
|
+
for (const fileName of new Set(fileNames)) {
|
|
3816
|
+
const stagedPath = resolve5(stagedDir, fileName);
|
|
3817
|
+
const distPath = resolve5(distAssetsDir, fileName);
|
|
3818
|
+
copyFileSync(stagedPath, distPath);
|
|
3819
|
+
totalBytes += statSync(stagedPath).size;
|
|
3820
|
+
}
|
|
3821
|
+
return totalBytes;
|
|
3822
|
+
}
|
|
3389
3823
|
|
|
3390
3824
|
// src/vite/discovery/prerender-collection.ts
|
|
3391
3825
|
async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
@@ -3401,84 +3835,126 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3401
3835
|
if (!params) return pattern;
|
|
3402
3836
|
return substituteRouteParams(pattern, params);
|
|
3403
3837
|
};
|
|
3838
|
+
let resolvedRoutes = 0;
|
|
3839
|
+
let totalDynamic = 0;
|
|
3404
3840
|
for (const { manifest } of allManifests) {
|
|
3405
3841
|
if (!manifest.prerenderRoutes) continue;
|
|
3406
|
-
const defs = manifest._prerenderDefs || {};
|
|
3407
3842
|
for (const routeName of manifest.prerenderRoutes) {
|
|
3408
3843
|
const pattern = manifest.routeManifest[routeName];
|
|
3409
|
-
if (
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3844
|
+
if (pattern && (pattern.includes(":") || pattern.includes("*"))) {
|
|
3845
|
+
totalDynamic++;
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
const paramsStart = performance.now();
|
|
3850
|
+
const progressInterval = totalDynamic > 0 ? setInterval(() => {
|
|
3851
|
+
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
3852
|
+
console.log(
|
|
3853
|
+
`[rsc-router] Resolving prerender params... ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
3854
|
+
);
|
|
3855
|
+
}, 5e3) : void 0;
|
|
3856
|
+
try {
|
|
3857
|
+
for (const { manifest } of allManifests) {
|
|
3858
|
+
if (!manifest.prerenderRoutes) continue;
|
|
3859
|
+
const defs = manifest._prerenderDefs || {};
|
|
3860
|
+
const passthroughSet = new Set(manifest.passthroughRoutes || []);
|
|
3861
|
+
for (const routeName of manifest.prerenderRoutes) {
|
|
3862
|
+
const pattern = manifest.routeManifest[routeName];
|
|
3863
|
+
if (!pattern) continue;
|
|
3864
|
+
const def = defs[routeName];
|
|
3865
|
+
const isPassthroughRoute = passthroughSet.has(routeName);
|
|
3866
|
+
const hasDynamic = pattern.includes(":") || pattern.includes("*");
|
|
3867
|
+
if (!hasDynamic) {
|
|
3868
|
+
entries.push({
|
|
3869
|
+
urlPath: pattern.replace(/\/$/, "") || "/",
|
|
3870
|
+
routeName,
|
|
3871
|
+
concurrency: 1,
|
|
3872
|
+
isPassthroughRoute
|
|
3873
|
+
});
|
|
3874
|
+
} else {
|
|
3875
|
+
if (def?.getParams) {
|
|
3876
|
+
try {
|
|
3877
|
+
const buildVars = {};
|
|
3878
|
+
const buildEnv = state.resolvedBuildEnv;
|
|
3879
|
+
const getParamsCtx = {
|
|
3880
|
+
build: true,
|
|
3881
|
+
dev: !state.isBuildMode,
|
|
3882
|
+
set: ((keyOrVar, value) => {
|
|
3883
|
+
contextSet(buildVars, keyOrVar, value);
|
|
3884
|
+
}),
|
|
3885
|
+
reverse: getParamsReverse,
|
|
3886
|
+
get env() {
|
|
3887
|
+
if (buildEnv !== void 0) return buildEnv;
|
|
3888
|
+
throw new Error(
|
|
3889
|
+
"[rsc-router] ctx.env is not available during build-time getParams(). Configure buildEnv in your rango() plugin options to enable build-time env access."
|
|
3890
|
+
);
|
|
3444
3891
|
}
|
|
3892
|
+
};
|
|
3893
|
+
const paramsList = await def.getParams(getParamsCtx);
|
|
3894
|
+
const concurrency = def.options?.concurrency ?? 1;
|
|
3895
|
+
const hasBuildVars = Object.keys(buildVars).length > 0 || Object.getOwnPropertySymbols(buildVars).length > 0;
|
|
3896
|
+
for (const params of paramsList) {
|
|
3897
|
+
let url = substituteRouteParams(
|
|
3898
|
+
pattern,
|
|
3899
|
+
params,
|
|
3900
|
+
encodePathParam
|
|
3901
|
+
);
|
|
3902
|
+
if (url.includes("*")) {
|
|
3903
|
+
const wildcardValue = params["*"] ?? params.splat;
|
|
3904
|
+
if (wildcardValue !== void 0) {
|
|
3905
|
+
url = url.replace(
|
|
3906
|
+
/\*[^/]*$/,
|
|
3907
|
+
encodePathParam(wildcardValue)
|
|
3908
|
+
);
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
entries.push({
|
|
3912
|
+
urlPath: url.replace(/\/$/, "") || "/",
|
|
3913
|
+
routeName,
|
|
3914
|
+
concurrency,
|
|
3915
|
+
...hasBuildVars ? { buildVars } : {},
|
|
3916
|
+
isPassthroughRoute
|
|
3917
|
+
});
|
|
3445
3918
|
}
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
true
|
|
3919
|
+
resolvedRoutes++;
|
|
3920
|
+
} catch (err) {
|
|
3921
|
+
resolvedRoutes++;
|
|
3922
|
+
if (err.name === "Skip") {
|
|
3923
|
+
console.log(
|
|
3924
|
+
`[rsc-router] SKIP route "${routeName}" - ${err.message}`
|
|
3925
|
+
);
|
|
3926
|
+
notifyOnError(
|
|
3927
|
+
registry,
|
|
3928
|
+
err,
|
|
3929
|
+
"prerender",
|
|
3930
|
+
routeName,
|
|
3931
|
+
void 0,
|
|
3932
|
+
true
|
|
3933
|
+
);
|
|
3934
|
+
continue;
|
|
3935
|
+
}
|
|
3936
|
+
console.error(
|
|
3937
|
+
`[rsc-router] Failed to get params for prerender route "${routeName}": ${err.message}`
|
|
3466
3938
|
);
|
|
3467
|
-
|
|
3939
|
+
notifyOnError(registry, err, "prerender", routeName);
|
|
3940
|
+
throw err;
|
|
3468
3941
|
}
|
|
3469
|
-
|
|
3470
|
-
|
|
3942
|
+
} else {
|
|
3943
|
+
console.warn(
|
|
3944
|
+
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3471
3945
|
);
|
|
3472
|
-
notifyOnError(registry, err, "prerender", routeName);
|
|
3473
|
-
throw err;
|
|
3474
3946
|
}
|
|
3475
|
-
} else {
|
|
3476
|
-
console.warn(
|
|
3477
|
-
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3478
|
-
);
|
|
3479
3947
|
}
|
|
3480
3948
|
}
|
|
3481
3949
|
}
|
|
3950
|
+
} finally {
|
|
3951
|
+
if (progressInterval) {
|
|
3952
|
+
clearInterval(progressInterval);
|
|
3953
|
+
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
3954
|
+
console.log(
|
|
3955
|
+
`[rsc-router] Resolved prerender params: ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
3956
|
+
);
|
|
3957
|
+
}
|
|
3482
3958
|
}
|
|
3483
3959
|
if (entries.length === 0) return;
|
|
3484
3960
|
const maxConcurrency = Math.max(...entries.map((e) => e.concurrency));
|
|
@@ -3487,7 +3963,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3487
3963
|
`[rsc-router] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
3488
3964
|
);
|
|
3489
3965
|
const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
|
|
3490
|
-
const
|
|
3966
|
+
const manifestEntries = {};
|
|
3491
3967
|
let doneCount = 0;
|
|
3492
3968
|
let skipCount = 0;
|
|
3493
3969
|
const startTotal = performance.now();
|
|
@@ -3505,7 +3981,8 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3505
3981
|
entry.urlPath,
|
|
3506
3982
|
{},
|
|
3507
3983
|
entry.buildVars,
|
|
3508
|
-
entry.isPassthroughRoute
|
|
3984
|
+
entry.isPassthroughRoute,
|
|
3985
|
+
state.resolvedBuildEnv
|
|
3509
3986
|
);
|
|
3510
3987
|
if (!result) continue;
|
|
3511
3988
|
if (result.passthrough) {
|
|
@@ -3517,18 +3994,30 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3517
3994
|
break;
|
|
3518
3995
|
}
|
|
3519
3996
|
const paramHash = hashParams(result.params || {});
|
|
3520
|
-
|
|
3997
|
+
const mainKey = `${result.routeName}/${paramHash}`;
|
|
3998
|
+
const mainValue = JSON.stringify({
|
|
3521
3999
|
segments: result.segments,
|
|
3522
4000
|
handles: result.handles
|
|
3523
|
-
};
|
|
4001
|
+
});
|
|
4002
|
+
manifestEntries[mainKey] = stageBuildAssetModule(
|
|
4003
|
+
state.projectRoot,
|
|
4004
|
+
"__pr",
|
|
4005
|
+
mainValue
|
|
4006
|
+
);
|
|
3524
4007
|
if (result.interceptSegments?.length) {
|
|
3525
|
-
|
|
4008
|
+
const interceptKey = `${result.routeName}/${paramHash}/i`;
|
|
4009
|
+
const interceptValue = JSON.stringify({
|
|
3526
4010
|
segments: [...result.segments, ...result.interceptSegments],
|
|
3527
4011
|
handles: {
|
|
3528
4012
|
...result.handles,
|
|
3529
4013
|
...result.interceptHandles || {}
|
|
3530
4014
|
}
|
|
3531
|
-
};
|
|
4015
|
+
});
|
|
4016
|
+
manifestEntries[interceptKey] = stageBuildAssetModule(
|
|
4017
|
+
state.projectRoot,
|
|
4018
|
+
"__pr",
|
|
4019
|
+
interceptValue
|
|
4020
|
+
);
|
|
3532
4021
|
}
|
|
3533
4022
|
const elapsed = (performance.now() - startUrl).toFixed(0);
|
|
3534
4023
|
console.log(
|
|
@@ -3572,7 +4061,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3572
4061
|
}
|
|
3573
4062
|
const totalElapsed = (performance.now() - startTotal).toFixed(0);
|
|
3574
4063
|
if (doneCount > 0) {
|
|
3575
|
-
state.
|
|
4064
|
+
state.prerenderManifestEntries = manifestEntries;
|
|
3576
4065
|
}
|
|
3577
4066
|
const parts = [`${doneCount} done`];
|
|
3578
4067
|
if (skipCount > 0) parts.push(`${skipCount} skipped`);
|
|
@@ -3583,7 +4072,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3583
4072
|
async function renderStaticHandlers(state, rscEnv, registry) {
|
|
3584
4073
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
|
|
3585
4074
|
return;
|
|
3586
|
-
const
|
|
4075
|
+
const manifestEntries = {};
|
|
3587
4076
|
let staticDone = 0;
|
|
3588
4077
|
let staticSkip = 0;
|
|
3589
4078
|
let totalStaticCount = 0;
|
|
@@ -3617,10 +4106,18 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3617
4106
|
const result = await routerInstance.renderStaticSegment(
|
|
3618
4107
|
def.handler,
|
|
3619
4108
|
def.$$id,
|
|
3620
|
-
def.$$routePrefix
|
|
4109
|
+
def.$$routePrefix,
|
|
4110
|
+
state.resolvedBuildEnv,
|
|
4111
|
+
!state.isBuildMode
|
|
3621
4112
|
);
|
|
3622
4113
|
if (result) {
|
|
3623
|
-
|
|
4114
|
+
const hasHandles = Object.keys(result.handles).length > 0;
|
|
4115
|
+
const exportValue = hasHandles ? JSON.stringify(result) : JSON.stringify(result.encoded);
|
|
4116
|
+
manifestEntries[def.$$id] = stageBuildAssetModule(
|
|
4117
|
+
state.projectRoot,
|
|
4118
|
+
"__st",
|
|
4119
|
+
exportValue
|
|
4120
|
+
);
|
|
3624
4121
|
const elapsed = (performance.now() - startHandler).toFixed(0);
|
|
3625
4122
|
console.log(
|
|
3626
4123
|
`[rsc-router] OK ${name.padEnd(40)} (${elapsed}ms)`
|
|
@@ -3657,7 +4154,7 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3657
4154
|
}
|
|
3658
4155
|
const totalStaticElapsed = (performance.now() - startStatic).toFixed(0);
|
|
3659
4156
|
if (staticDone > 0) {
|
|
3660
|
-
state.
|
|
4157
|
+
state.staticManifestEntries = manifestEntries;
|
|
3661
4158
|
}
|
|
3662
4159
|
const staticParts = [`${staticDone} done`];
|
|
3663
4160
|
if (staticSkip > 0) staticParts.push(`${staticSkip} skipped`);
|
|
@@ -3674,8 +4171,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3674
4171
|
let registry = serverMod.RouterRegistry;
|
|
3675
4172
|
if (!registry || registry.size === 0) {
|
|
3676
4173
|
try {
|
|
3677
|
-
const
|
|
3678
|
-
const hostRegistry = hostMod.HostRouterRegistry;
|
|
4174
|
+
const hostRegistry = serverMod.HostRouterRegistry;
|
|
3679
4175
|
if (hostRegistry && hostRegistry.size > 0) {
|
|
3680
4176
|
console.log(
|
|
3681
4177
|
`[rsc-router] Found ${hostRegistry.size} host router(s), resolving lazy handlers...`
|
|
@@ -3737,7 +4233,11 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3737
4233
|
if (!router.urlpatterns || !generateManifestFull) {
|
|
3738
4234
|
continue;
|
|
3739
4235
|
}
|
|
3740
|
-
const manifest = generateManifestFull(
|
|
4236
|
+
const manifest = generateManifestFull(
|
|
4237
|
+
router.urlpatterns,
|
|
4238
|
+
routerMountIndex,
|
|
4239
|
+
router.__basename ? { urlPrefix: router.__basename } : void 0
|
|
4240
|
+
);
|
|
3741
4241
|
routerMountIndex++;
|
|
3742
4242
|
allManifests.push({ id, manifest });
|
|
3743
4243
|
const routeCount = Object.keys(manifest.routeManifest).length;
|
|
@@ -3879,8 +4379,8 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3879
4379
|
}
|
|
3880
4380
|
|
|
3881
4381
|
// src/vite/discovery/route-types-writer.ts
|
|
3882
|
-
import { dirname as dirname3, basename, join as
|
|
3883
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
4382
|
+
import { dirname as dirname3, basename, join as join2, resolve as resolve6 } from "node:path";
|
|
4383
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "node:fs";
|
|
3884
4384
|
function filterUserNamedRoutes(manifest) {
|
|
3885
4385
|
const filtered = {};
|
|
3886
4386
|
for (const [name, pattern] of Object.entries(manifest)) {
|
|
@@ -3900,7 +4400,7 @@ function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
|
3900
4400
|
/\.(tsx?|jsx?)$/,
|
|
3901
4401
|
""
|
|
3902
4402
|
);
|
|
3903
|
-
const outPath =
|
|
4403
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
3904
4404
|
try {
|
|
3905
4405
|
preContent.set(outPath, readFileSync4(outPath, "utf-8"));
|
|
3906
4406
|
} catch {
|
|
@@ -3913,8 +4413,8 @@ function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
|
3913
4413
|
/\.(tsx?|jsx?)$/,
|
|
3914
4414
|
""
|
|
3915
4415
|
);
|
|
3916
|
-
const outPath =
|
|
3917
|
-
if (!
|
|
4416
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4417
|
+
if (!existsSync5(outPath)) continue;
|
|
3918
4418
|
try {
|
|
3919
4419
|
const content = readFileSync4(outPath, "utf-8");
|
|
3920
4420
|
if (content !== preContent.get(outPath)) {
|
|
@@ -3928,10 +4428,10 @@ function writeRouteTypesFiles(state) {
|
|
|
3928
4428
|
if (state.perRouterManifests.length === 0) return;
|
|
3929
4429
|
try {
|
|
3930
4430
|
const entryDir = dirname3(
|
|
3931
|
-
|
|
4431
|
+
resolve6(state.projectRoot, state.resolvedEntryPath)
|
|
3932
4432
|
);
|
|
3933
|
-
const oldCombinedPath =
|
|
3934
|
-
if (
|
|
4433
|
+
const oldCombinedPath = join2(entryDir, "named-routes.gen.ts");
|
|
4434
|
+
if (existsSync5(oldCombinedPath)) {
|
|
3935
4435
|
unlinkSync2(oldCombinedPath);
|
|
3936
4436
|
console.log(
|
|
3937
4437
|
`[rsc-router] Removed stale combined route types: ${oldCombinedPath}`
|
|
@@ -3955,7 +4455,7 @@ Set an explicit \`id\` on createRouter() or check the call site.`
|
|
|
3955
4455
|
}
|
|
3956
4456
|
const routerDir = dirname3(sourceFile);
|
|
3957
4457
|
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
3958
|
-
const outPath =
|
|
4458
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
3959
4459
|
const userRoutes = filterUserNamedRoutes(routeManifest);
|
|
3960
4460
|
let effectiveSearchSchemas = routeSearchSchemas;
|
|
3961
4461
|
if ((!effectiveSearchSchemas || Object.keys(effectiveSearchSchemas).length === 0) && sourceFile) {
|
|
@@ -3975,10 +4475,10 @@ Set an explicit \`id\` on createRouter() or check the call site.`
|
|
|
3975
4475
|
userRoutes,
|
|
3976
4476
|
effectiveSearchSchemas && Object.keys(effectiveSearchSchemas).length > 0 ? effectiveSearchSchemas : void 0
|
|
3977
4477
|
);
|
|
3978
|
-
const existing =
|
|
4478
|
+
const existing = existsSync5(outPath) ? readFileSync4(outPath, "utf-8") : null;
|
|
3979
4479
|
if (existing !== source) {
|
|
3980
4480
|
markSelfGenWrite(state, outPath, source);
|
|
3981
|
-
|
|
4481
|
+
writeFileSync3(outPath, source);
|
|
3982
4482
|
console.log(`[rsc-router] Generated route types -> ${outPath}`);
|
|
3983
4483
|
}
|
|
3984
4484
|
}
|
|
@@ -4020,21 +4520,21 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
4020
4520
|
}
|
|
4021
4521
|
const routerDir = dirname3(sourceFile);
|
|
4022
4522
|
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4023
|
-
const outPath =
|
|
4523
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4024
4524
|
const source = generateRouteTypesSource(
|
|
4025
4525
|
mergedRoutes,
|
|
4026
4526
|
Object.keys(mergedSearchSchemas).length > 0 ? mergedSearchSchemas : void 0
|
|
4027
4527
|
);
|
|
4028
|
-
const existing =
|
|
4528
|
+
const existing = existsSync5(outPath) ? readFileSync4(outPath, "utf-8") : null;
|
|
4029
4529
|
if (existing !== source) {
|
|
4030
4530
|
markSelfGenWrite(state, outPath, source);
|
|
4031
|
-
|
|
4531
|
+
writeFileSync3(outPath, source);
|
|
4032
4532
|
}
|
|
4033
4533
|
}
|
|
4034
4534
|
}
|
|
4035
4535
|
|
|
4036
4536
|
// src/vite/discovery/virtual-module-codegen.ts
|
|
4037
|
-
import { dirname as dirname4, basename as basename2, join as
|
|
4537
|
+
import { dirname as dirname4, basename as basename2, join as join3 } from "node:path";
|
|
4038
4538
|
function generateRoutesManifestModule(state) {
|
|
4039
4539
|
const hasManifest = state.mergedRouteManifest && Object.keys(state.mergedRouteManifest).length > 0;
|
|
4040
4540
|
if (hasManifest) {
|
|
@@ -4049,7 +4549,7 @@ function generateRoutesManifestModule(state) {
|
|
|
4049
4549
|
/\.(tsx?|jsx?)$/,
|
|
4050
4550
|
""
|
|
4051
4551
|
);
|
|
4052
|
-
const genPath =
|
|
4552
|
+
const genPath = join3(
|
|
4053
4553
|
routerDir,
|
|
4054
4554
|
`${routerBasename}.named-routes.gen.js`
|
|
4055
4555
|
).replaceAll("\\", "/");
|
|
@@ -4146,7 +4646,7 @@ function generatePerRouterModule(state, routerId) {
|
|
|
4146
4646
|
/\.(tsx?|jsx?)$/,
|
|
4147
4647
|
""
|
|
4148
4648
|
);
|
|
4149
|
-
const genPath =
|
|
4649
|
+
const genPath = join3(
|
|
4150
4650
|
routerDir,
|
|
4151
4651
|
`${routerBasename}.named-routes.gen.js`
|
|
4152
4652
|
).replaceAll("\\", "/");
|
|
@@ -4173,100 +4673,90 @@ function generatePerRouterModule(state, routerId) {
|
|
|
4173
4673
|
}
|
|
4174
4674
|
|
|
4175
4675
|
// src/vite/discovery/bundle-postprocess.ts
|
|
4176
|
-
import { resolve as
|
|
4177
|
-
import {
|
|
4178
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync } from "node:fs";
|
|
4676
|
+
import { resolve as resolve7 } from "node:path";
|
|
4677
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6 } from "node:fs";
|
|
4179
4678
|
function postprocessBundle(state) {
|
|
4180
|
-
const hasPrerenderData = state.
|
|
4181
|
-
const hasStaticData = state.
|
|
4679
|
+
const hasPrerenderData = state.prerenderManifestEntries && Object.keys(state.prerenderManifestEntries).length > 0;
|
|
4680
|
+
const hasStaticData = state.staticManifestEntries && Object.keys(state.staticManifestEntries).length > 0;
|
|
4182
4681
|
if (!hasPrerenderData && !hasStaticData) return;
|
|
4183
|
-
const rscEntryPath =
|
|
4682
|
+
const rscEntryPath = resolve7(
|
|
4184
4683
|
state.projectRoot,
|
|
4185
4684
|
"dist/rsc",
|
|
4186
4685
|
state.rscEntryFileName ?? "index.js"
|
|
4187
4686
|
);
|
|
4188
4687
|
const evictionTargets = [
|
|
4189
4688
|
{
|
|
4190
|
-
|
|
4689
|
+
infos: state.handlerChunkInfoMap.values(),
|
|
4191
4690
|
fnName: "Prerender",
|
|
4192
4691
|
brand: "prerenderHandler",
|
|
4193
4692
|
label: "handler code from RSC bundle"
|
|
4194
4693
|
},
|
|
4195
4694
|
{
|
|
4196
|
-
|
|
4695
|
+
infos: state.staticHandlerChunkInfoMap.values(),
|
|
4197
4696
|
fnName: "Static",
|
|
4198
4697
|
brand: "staticHandler",
|
|
4199
4698
|
label: "static handler code"
|
|
4200
4699
|
}
|
|
4201
4700
|
];
|
|
4202
4701
|
for (const target of evictionTargets) {
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4702
|
+
for (const info of target.infos) {
|
|
4703
|
+
const chunkPath = resolve7(state.projectRoot, "dist/rsc", info.fileName);
|
|
4704
|
+
try {
|
|
4705
|
+
const code = readFileSync5(chunkPath, "utf-8");
|
|
4706
|
+
const result = evictHandlerCode(
|
|
4707
|
+
code,
|
|
4708
|
+
info.exports,
|
|
4709
|
+
target.fnName,
|
|
4710
|
+
target.brand
|
|
4711
|
+
);
|
|
4712
|
+
if (result) {
|
|
4713
|
+
writeFileSync4(chunkPath, result.code);
|
|
4714
|
+
const savedKB = (result.savedBytes / 1024).toFixed(1);
|
|
4715
|
+
console.log(
|
|
4716
|
+
`[rsc-router] Evicted ${target.label} (${savedKB} KB saved): ${info.fileName}`
|
|
4717
|
+
);
|
|
4718
|
+
}
|
|
4719
|
+
} catch (replaceErr) {
|
|
4720
|
+
console.warn(
|
|
4721
|
+
`[rsc-router] Failed to evict ${target.label}: ${replaceErr.message}`
|
|
4222
4722
|
);
|
|
4223
4723
|
}
|
|
4224
|
-
} catch (replaceErr) {
|
|
4225
|
-
console.warn(
|
|
4226
|
-
`[rsc-router] Failed to evict ${target.label}: ${replaceErr.message}`
|
|
4227
|
-
);
|
|
4228
4724
|
}
|
|
4229
4725
|
}
|
|
4230
|
-
state.
|
|
4231
|
-
state.
|
|
4232
|
-
if (hasPrerenderData &&
|
|
4726
|
+
state.handlerChunkInfoMap.clear();
|
|
4727
|
+
state.staticHandlerChunkInfoMap.clear();
|
|
4728
|
+
if (hasPrerenderData && existsSync6(rscEntryPath)) {
|
|
4233
4729
|
const rscCode = readFileSync5(rscEntryPath, "utf-8");
|
|
4234
4730
|
if (!rscCode.includes("__prerender-manifest.js")) {
|
|
4235
4731
|
try {
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4732
|
+
let totalBytes = copyStagedBuildAssets(
|
|
4733
|
+
state.projectRoot,
|
|
4734
|
+
Object.values(state.prerenderManifestEntries)
|
|
4735
|
+
);
|
|
4736
|
+
const manifestMap = {};
|
|
4737
|
+
for (const [key, assetFileName] of Object.entries(
|
|
4738
|
+
state.prerenderManifestEntries
|
|
4242
4739
|
)) {
|
|
4243
|
-
|
|
4244
|
-
const contentHash = createHash4("sha256").update(entryJson).digest("hex").slice(0, 8);
|
|
4245
|
-
const assetFileName = `__pr-${contentHash}.js`;
|
|
4246
|
-
const assetPath = resolve6(assetsDir, assetFileName);
|
|
4247
|
-
const assetCode = `export default ${entryJson};
|
|
4248
|
-
`;
|
|
4249
|
-
writeFileSync3(assetPath, assetCode);
|
|
4250
|
-
totalBytes += Buffer.byteLength(assetCode);
|
|
4251
|
-
manifestEntries.push(
|
|
4252
|
-
`${JSON.stringify(key)}:()=>import("./assets/${assetFileName}")`
|
|
4253
|
-
);
|
|
4740
|
+
manifestMap[key] = `./assets/${assetFileName}`;
|
|
4254
4741
|
}
|
|
4255
|
-
const manifestCode =
|
|
4256
|
-
|
|
4257
|
-
|
|
4742
|
+
const manifestCode = [
|
|
4743
|
+
`const m=JSON.parse('${JSON.stringify(manifestMap).replace(/'/g, "\\'")}');`,
|
|
4744
|
+
`export function loadPrerenderAsset(s){return import(s)}`,
|
|
4745
|
+
`export default m;`,
|
|
4746
|
+
""
|
|
4747
|
+
].join("\n");
|
|
4748
|
+
const manifestPath = resolve7(
|
|
4258
4749
|
state.projectRoot,
|
|
4259
4750
|
"dist/rsc/__prerender-manifest.js"
|
|
4260
4751
|
);
|
|
4261
|
-
|
|
4752
|
+
writeFileSync4(manifestPath, manifestCode);
|
|
4262
4753
|
totalBytes += Buffer.byteLength(manifestCode);
|
|
4263
|
-
const injection = `
|
|
4264
|
-
globalThis.__PRERENDER_MANIFEST = __pm;
|
|
4754
|
+
const injection = `globalThis.__loadPrerenderManifestModule = () => import("./__prerender-manifest.js");
|
|
4265
4755
|
`;
|
|
4266
|
-
|
|
4756
|
+
writeFileSync4(rscEntryPath, injection + rscCode);
|
|
4267
4757
|
const totalKB = (totalBytes / 1024).toFixed(1);
|
|
4268
4758
|
console.log(
|
|
4269
|
-
`[rsc-router] Wrote prerender assets (${totalKB} KB total, ${Object.keys(state.
|
|
4759
|
+
`[rsc-router] Wrote prerender assets (${totalKB} KB total, ${Object.keys(state.prerenderManifestEntries).length} entries)`
|
|
4270
4760
|
);
|
|
4271
4761
|
} catch (err) {
|
|
4272
4762
|
throw new Error(
|
|
@@ -4275,44 +4765,36 @@ globalThis.__PRERENDER_MANIFEST = __pm;
|
|
|
4275
4765
|
}
|
|
4276
4766
|
}
|
|
4277
4767
|
}
|
|
4278
|
-
if (hasStaticData &&
|
|
4768
|
+
if (hasStaticData && existsSync6(rscEntryPath)) {
|
|
4279
4769
|
const rscCode = readFileSync5(rscEntryPath, "utf-8");
|
|
4280
|
-
if (!rscCode.includes("
|
|
4770
|
+
if (!rscCode.includes("__static-manifest.js")) {
|
|
4281
4771
|
try {
|
|
4282
|
-
const assetsDir = resolve6(state.projectRoot, "dist/rsc/assets");
|
|
4283
|
-
mkdirSync(assetsDir, { recursive: true });
|
|
4284
4772
|
const manifestEntries = [];
|
|
4285
|
-
let totalBytes =
|
|
4286
|
-
|
|
4287
|
-
state.
|
|
4773
|
+
let totalBytes = copyStagedBuildAssets(
|
|
4774
|
+
state.projectRoot,
|
|
4775
|
+
Object.values(state.staticManifestEntries)
|
|
4776
|
+
);
|
|
4777
|
+
for (const [handlerId, assetFileName] of Object.entries(
|
|
4778
|
+
state.staticManifestEntries
|
|
4288
4779
|
)) {
|
|
4289
|
-
const hasHandles = Object.keys(handles).length > 0;
|
|
4290
|
-
const exportValue = hasHandles ? JSON.stringify({ encoded, handles }) : JSON.stringify(encoded);
|
|
4291
|
-
const contentHash = createHash4("sha256").update(exportValue).digest("hex").slice(0, 8);
|
|
4292
|
-
const assetFileName = `__st-${contentHash}.js`;
|
|
4293
|
-
const assetPath = resolve6(assetsDir, assetFileName);
|
|
4294
|
-
const assetCode = `export default ${exportValue};
|
|
4295
|
-
`;
|
|
4296
|
-
writeFileSync3(assetPath, assetCode);
|
|
4297
|
-
totalBytes += Buffer.byteLength(assetCode);
|
|
4298
4780
|
manifestEntries.push(
|
|
4299
4781
|
`${JSON.stringify(handlerId)}:()=>import("./assets/${assetFileName}")`
|
|
4300
4782
|
);
|
|
4301
4783
|
}
|
|
4302
4784
|
const manifestCode = `const m={${manifestEntries.join(",")}};globalThis.__STATIC_MANIFEST=m;export default m;
|
|
4303
4785
|
`;
|
|
4304
|
-
const manifestPath =
|
|
4786
|
+
const manifestPath = resolve7(
|
|
4305
4787
|
state.projectRoot,
|
|
4306
4788
|
"dist/rsc/__static-manifest.js"
|
|
4307
4789
|
);
|
|
4308
|
-
|
|
4790
|
+
writeFileSync4(manifestPath, manifestCode);
|
|
4309
4791
|
totalBytes += Buffer.byteLength(manifestCode);
|
|
4310
4792
|
const injection = `import "./__static-manifest.js";
|
|
4311
4793
|
`;
|
|
4312
|
-
|
|
4794
|
+
writeFileSync4(rscEntryPath, injection + rscCode);
|
|
4313
4795
|
const totalKB = (totalBytes / 1024).toFixed(1);
|
|
4314
4796
|
console.log(
|
|
4315
|
-
`[rsc-router] Wrote static assets (${totalKB} KB total, ${Object.keys(state.
|
|
4797
|
+
`[rsc-router] Wrote static assets (${totalKB} KB total, ${Object.keys(state.staticManifestEntries).length} entries)`
|
|
4316
4798
|
);
|
|
4317
4799
|
} catch (err) {
|
|
4318
4800
|
throw new Error(
|
|
@@ -4324,7 +4806,22 @@ globalThis.__PRERENDER_MANIFEST = __pm;
|
|
|
4324
4806
|
}
|
|
4325
4807
|
|
|
4326
4808
|
// src/vite/router-discovery.ts
|
|
4809
|
+
var loaderHookRegistered = false;
|
|
4810
|
+
function ensureCloudflareProtocolLoaderRegistered() {
|
|
4811
|
+
if (loaderHookRegistered) return;
|
|
4812
|
+
loaderHookRegistered = true;
|
|
4813
|
+
try {
|
|
4814
|
+
register(
|
|
4815
|
+
new URL("./plugins/cloudflare-protocol-loader-hook.mjs", import.meta.url)
|
|
4816
|
+
);
|
|
4817
|
+
} catch (err) {
|
|
4818
|
+
console.warn(
|
|
4819
|
+
`[rsc-router] Could not register Node ESM loader hook for cloudflare:* imports (${err?.message ?? err}). Falling back to Vite transform only.`
|
|
4820
|
+
);
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4327
4823
|
async function createTempRscServer(state, options = {}) {
|
|
4824
|
+
ensureCloudflareProtocolLoaderRegistered();
|
|
4328
4825
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
4329
4826
|
return createViteServer({
|
|
4330
4827
|
root: state.projectRoot,
|
|
@@ -4347,6 +4844,7 @@ async function createTempRscServer(state, options = {}) {
|
|
|
4347
4844
|
...options.forceBuild ? [hashClientRefs(state.projectRoot)] : [],
|
|
4348
4845
|
createVersionPlugin(),
|
|
4349
4846
|
createVirtualStubPlugin(),
|
|
4847
|
+
createCloudflareProtocolStubPlugin(),
|
|
4350
4848
|
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
4351
4849
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
4352
4850
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : void 0),
|
|
@@ -4354,8 +4852,69 @@ async function createTempRscServer(state, options = {}) {
|
|
|
4354
4852
|
]
|
|
4355
4853
|
});
|
|
4356
4854
|
}
|
|
4855
|
+
async function resolveBuildEnv(option, factoryCtx) {
|
|
4856
|
+
if (!option) return null;
|
|
4857
|
+
if (option === "auto") {
|
|
4858
|
+
if (factoryCtx.preset !== "cloudflare") {
|
|
4859
|
+
throw new Error(
|
|
4860
|
+
'[rsc-router] buildEnv: "auto" is only supported with preset: "cloudflare". Use a factory function or plain object for other presets.'
|
|
4861
|
+
);
|
|
4862
|
+
}
|
|
4863
|
+
try {
|
|
4864
|
+
const userRequire = createRequire2(
|
|
4865
|
+
resolve8(factoryCtx.root, "package.json")
|
|
4866
|
+
);
|
|
4867
|
+
const wranglerPath = userRequire.resolve("wrangler");
|
|
4868
|
+
const { getPlatformProxy } = await import(pathToFileURL(wranglerPath).href);
|
|
4869
|
+
const proxy = await getPlatformProxy();
|
|
4870
|
+
return {
|
|
4871
|
+
env: proxy.env,
|
|
4872
|
+
dispose: proxy.dispose
|
|
4873
|
+
};
|
|
4874
|
+
} catch (err) {
|
|
4875
|
+
throw new Error(
|
|
4876
|
+
`[rsc-router] buildEnv: "auto" requires wrangler to be installed.
|
|
4877
|
+
Install it with: pnpm add -D wrangler
|
|
4878
|
+
${err.message}`
|
|
4879
|
+
);
|
|
4880
|
+
}
|
|
4881
|
+
}
|
|
4882
|
+
if (typeof option === "function") {
|
|
4883
|
+
return await option(factoryCtx);
|
|
4884
|
+
}
|
|
4885
|
+
return { env: option };
|
|
4886
|
+
}
|
|
4887
|
+
async function acquireBuildEnv(s, command, mode) {
|
|
4888
|
+
const option = s.opts?.buildEnv;
|
|
4889
|
+
if (!option) return false;
|
|
4890
|
+
const result = await resolveBuildEnv(option, {
|
|
4891
|
+
root: s.projectRoot,
|
|
4892
|
+
mode,
|
|
4893
|
+
command,
|
|
4894
|
+
preset: s.opts?.preset ?? "node"
|
|
4895
|
+
});
|
|
4896
|
+
if (!result) return false;
|
|
4897
|
+
s.resolvedBuildEnv = result.env;
|
|
4898
|
+
s.buildEnvDispose = result.dispose ?? null;
|
|
4899
|
+
globalThis[BUILD_ENV_GLOBAL_KEY] = result.env;
|
|
4900
|
+
return true;
|
|
4901
|
+
}
|
|
4902
|
+
async function releaseBuildEnv(s) {
|
|
4903
|
+
if (s.buildEnvDispose) {
|
|
4904
|
+
try {
|
|
4905
|
+
await s.buildEnvDispose();
|
|
4906
|
+
} catch (err) {
|
|
4907
|
+
console.warn(`[rsc-router] buildEnv dispose failed: ${err.message}`);
|
|
4908
|
+
}
|
|
4909
|
+
s.buildEnvDispose = null;
|
|
4910
|
+
}
|
|
4911
|
+
s.resolvedBuildEnv = void 0;
|
|
4912
|
+
delete globalThis[BUILD_ENV_GLOBAL_KEY];
|
|
4913
|
+
}
|
|
4357
4914
|
function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
4358
4915
|
const s = createDiscoveryState(entryPath, opts);
|
|
4916
|
+
let viteCommand = "build";
|
|
4917
|
+
let viteMode = "production";
|
|
4359
4918
|
return {
|
|
4360
4919
|
name: "@rangojs/router:discovery",
|
|
4361
4920
|
config() {
|
|
@@ -4364,31 +4923,13 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4364
4923
|
__RANGO_DEBUG__: JSON.stringify(!!process.env.INTERNAL_RANGO_DEBUG)
|
|
4365
4924
|
}
|
|
4366
4925
|
};
|
|
4367
|
-
if (opts?.enableBuildPrerender) {
|
|
4368
|
-
config.environments = {
|
|
4369
|
-
rsc: {
|
|
4370
|
-
build: {
|
|
4371
|
-
rollupOptions: {
|
|
4372
|
-
output: {
|
|
4373
|
-
manualChunks(id) {
|
|
4374
|
-
if (s.resolvedPrerenderModules?.has(id)) {
|
|
4375
|
-
return "__prerender-handlers";
|
|
4376
|
-
}
|
|
4377
|
-
if (s.resolvedStaticModules?.has(id)) {
|
|
4378
|
-
return "__static-handlers";
|
|
4379
|
-
}
|
|
4380
|
-
}
|
|
4381
|
-
}
|
|
4382
|
-
}
|
|
4383
|
-
}
|
|
4384
|
-
}
|
|
4385
|
-
};
|
|
4386
|
-
}
|
|
4387
4926
|
return config;
|
|
4388
4927
|
},
|
|
4389
4928
|
configResolved(config) {
|
|
4390
4929
|
s.projectRoot = config.root;
|
|
4391
4930
|
s.isBuildMode = config.command === "build";
|
|
4931
|
+
viteCommand = config.command;
|
|
4932
|
+
viteMode = config.mode;
|
|
4392
4933
|
s.userResolveAlias = config.resolve.alias;
|
|
4393
4934
|
if (!s.resolvedEntryPath && opts?.routerPathRef?.path) {
|
|
4394
4935
|
s.resolvedEntryPath = opts.routerPathRef.path;
|
|
@@ -4402,12 +4943,6 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4402
4943
|
s.resolvedEntryPath = entries[0];
|
|
4403
4944
|
}
|
|
4404
4945
|
}
|
|
4405
|
-
if (opts?.include || opts?.exclude) {
|
|
4406
|
-
s.scanFilter = createScanFilter(s.projectRoot, {
|
|
4407
|
-
include: opts.include,
|
|
4408
|
-
exclude: opts.exclude
|
|
4409
|
-
});
|
|
4410
|
-
}
|
|
4411
4946
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
4412
4947
|
s.cachedRouterFiles = findRouterFiles(s.projectRoot, s.scanFilter);
|
|
4413
4948
|
writeCombinedRouteTypesWithTracking(s, { preserveIfLarger: true });
|
|
@@ -4427,8 +4962,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4427
4962
|
if (globalThis.__rscRouterDiscoveryActive) return;
|
|
4428
4963
|
s.devServer = server;
|
|
4429
4964
|
let resolveDiscovery;
|
|
4430
|
-
const discoveryPromise = new Promise((
|
|
4431
|
-
resolveDiscovery =
|
|
4965
|
+
const discoveryPromise = new Promise((resolve10) => {
|
|
4966
|
+
resolveDiscovery = resolve10;
|
|
4432
4967
|
});
|
|
4433
4968
|
const getDevServerOrigin = () => server.resolvedUrls?.local?.[0]?.replace(/\/$/, "") || `http://localhost:${server.config.server.port || 5173}`;
|
|
4434
4969
|
let prerenderTempServer = null;
|
|
@@ -4439,6 +4974,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4439
4974
|
});
|
|
4440
4975
|
prerenderTempServer = null;
|
|
4441
4976
|
}
|
|
4977
|
+
releaseBuildEnv(s).catch(() => {
|
|
4978
|
+
});
|
|
4442
4979
|
});
|
|
4443
4980
|
async function getOrCreateTempServer() {
|
|
4444
4981
|
if (prerenderNodeRegistry) {
|
|
@@ -4469,6 +5006,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4469
5006
|
if (!rscEnv?.runner) {
|
|
4470
5007
|
s.devServerOrigin = getDevServerOrigin();
|
|
4471
5008
|
try {
|
|
5009
|
+
await acquireBuildEnv(s, viteCommand, viteMode);
|
|
4472
5010
|
const tempRscEnv = await getOrCreateTempServer();
|
|
4473
5011
|
if (tempRscEnv) {
|
|
4474
5012
|
await discoverRouters(s, tempRscEnv);
|
|
@@ -4484,6 +5022,7 @@ ${err.stack}`
|
|
|
4484
5022
|
return;
|
|
4485
5023
|
}
|
|
4486
5024
|
try {
|
|
5025
|
+
await acquireBuildEnv(s, viteCommand, viteMode);
|
|
4487
5026
|
const serverMod = await rscEnv.runner.import(
|
|
4488
5027
|
"@rangojs/router/server"
|
|
4489
5028
|
);
|
|
@@ -4503,8 +5042,8 @@ ${err.stack}`
|
|
|
4503
5042
|
resolveDiscovery();
|
|
4504
5043
|
}
|
|
4505
5044
|
};
|
|
4506
|
-
s.discoveryDone = new Promise((
|
|
4507
|
-
setTimeout(() => discover().then(
|
|
5045
|
+
s.discoveryDone = new Promise((resolve10) => {
|
|
5046
|
+
setTimeout(() => discover().then(resolve10, resolve10), 0);
|
|
4508
5047
|
});
|
|
4509
5048
|
let mainRegistry = null;
|
|
4510
5049
|
const propagateDiscoveryState = async (rscEnv) => {
|
|
@@ -4548,7 +5087,26 @@ ${err.stack}`
|
|
|
4548
5087
|
res.end("Missing pathname");
|
|
4549
5088
|
return;
|
|
4550
5089
|
}
|
|
4551
|
-
|
|
5090
|
+
const rscEnv = server.environments?.rsc;
|
|
5091
|
+
let registry = null;
|
|
5092
|
+
if (rscEnv?.runner && s.resolvedEntryPath) {
|
|
5093
|
+
try {
|
|
5094
|
+
await rscEnv.runner.import(s.resolvedEntryPath);
|
|
5095
|
+
const serverMod = await rscEnv.runner.import(
|
|
5096
|
+
"@rangojs/router/server"
|
|
5097
|
+
);
|
|
5098
|
+
registry = serverMod.RouterRegistry ?? null;
|
|
5099
|
+
} catch (err) {
|
|
5100
|
+
console.warn(
|
|
5101
|
+
`[rsc-router] Dev prerender module refresh failed: ${err.message}`
|
|
5102
|
+
);
|
|
5103
|
+
res.statusCode = 500;
|
|
5104
|
+
res.end(`Prerender handler error: ${err.message}`);
|
|
5105
|
+
return;
|
|
5106
|
+
}
|
|
5107
|
+
} else {
|
|
5108
|
+
registry = mainRegistry;
|
|
5109
|
+
}
|
|
4552
5110
|
if (!registry) {
|
|
4553
5111
|
if (!prerenderNodeRegistry) {
|
|
4554
5112
|
await getOrCreateTempServer();
|
|
@@ -4570,7 +5128,10 @@ ${err.stack}`
|
|
|
4570
5128
|
pathname,
|
|
4571
5129
|
{},
|
|
4572
5130
|
void 0,
|
|
4573
|
-
wantPassthrough
|
|
5131
|
+
wantPassthrough,
|
|
5132
|
+
s.resolvedBuildEnv,
|
|
5133
|
+
true
|
|
5134
|
+
// devMode: check getParams for passthrough routes
|
|
4574
5135
|
);
|
|
4575
5136
|
if (!result) continue;
|
|
4576
5137
|
if (result.passthrough) continue;
|
|
@@ -4673,7 +5234,7 @@ ${err.stack}`
|
|
|
4673
5234
|
if (hasCreateRouter) {
|
|
4674
5235
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
4675
5236
|
...s.cachedRouterFiles ?? [],
|
|
4676
|
-
|
|
5237
|
+
resolve8(filePath)
|
|
4677
5238
|
]);
|
|
4678
5239
|
if (nestedRouterConflict) {
|
|
4679
5240
|
server.config.logger.error(
|
|
@@ -4703,6 +5264,10 @@ ${err.stack}`
|
|
|
4703
5264
|
async buildStart() {
|
|
4704
5265
|
if (!s.isBuildMode) return;
|
|
4705
5266
|
if (s.mergedRouteManifest !== null) return;
|
|
5267
|
+
resetStagedBuildAssets(s.projectRoot);
|
|
5268
|
+
s.prerenderManifestEntries = null;
|
|
5269
|
+
s.staticManifestEntries = null;
|
|
5270
|
+
await acquireBuildEnv(s, viteCommand, viteMode);
|
|
4706
5271
|
let tempServer = null;
|
|
4707
5272
|
globalThis.__rscRouterDiscoveryActive = true;
|
|
4708
5273
|
try {
|
|
@@ -4742,6 +5307,7 @@ ${details}`
|
|
|
4742
5307
|
if (tempServer) {
|
|
4743
5308
|
await tempServer.close();
|
|
4744
5309
|
}
|
|
5310
|
+
await releaseBuildEnv(s);
|
|
4745
5311
|
}
|
|
4746
5312
|
},
|
|
4747
5313
|
// Virtual module: provides the pre-generated route manifest as a JS module
|
|
@@ -4784,20 +5350,30 @@ ${details}`
|
|
|
4784
5350
|
}
|
|
4785
5351
|
if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size)
|
|
4786
5352
|
return;
|
|
5353
|
+
s.handlerChunkInfoMap.clear();
|
|
5354
|
+
s.staticHandlerChunkInfoMap.clear();
|
|
4787
5355
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
4788
5356
|
if (chunk.type !== "chunk") continue;
|
|
4789
|
-
if (
|
|
5357
|
+
if (s.resolvedPrerenderModules?.size) {
|
|
4790
5358
|
const handlers = extractHandlerExportsFromChunk(
|
|
4791
5359
|
chunk.code,
|
|
4792
5360
|
s.resolvedPrerenderModules,
|
|
4793
5361
|
"Prerender",
|
|
4794
|
-
|
|
5362
|
+
false
|
|
4795
5363
|
);
|
|
4796
5364
|
if (handlers.length > 0) {
|
|
4797
|
-
|
|
5365
|
+
const existing = s.handlerChunkInfoMap.get(fileName);
|
|
5366
|
+
if (existing) {
|
|
5367
|
+
existing.exports.push(...handlers);
|
|
5368
|
+
} else {
|
|
5369
|
+
s.handlerChunkInfoMap.set(fileName, {
|
|
5370
|
+
fileName,
|
|
5371
|
+
exports: handlers
|
|
5372
|
+
});
|
|
5373
|
+
}
|
|
4798
5374
|
}
|
|
4799
5375
|
}
|
|
4800
|
-
if (
|
|
5376
|
+
if (s.resolvedStaticModules?.size) {
|
|
4801
5377
|
const handlers = extractHandlerExportsFromChunk(
|
|
4802
5378
|
chunk.code,
|
|
4803
5379
|
s.resolvedStaticModules,
|
|
@@ -4805,7 +5381,15 @@ ${details}`
|
|
|
4805
5381
|
false
|
|
4806
5382
|
);
|
|
4807
5383
|
if (handlers.length > 0) {
|
|
4808
|
-
|
|
5384
|
+
const existing = s.staticHandlerChunkInfoMap.get(fileName);
|
|
5385
|
+
if (existing) {
|
|
5386
|
+
existing.exports.push(...handlers);
|
|
5387
|
+
} else {
|
|
5388
|
+
s.staticHandlerChunkInfoMap.set(fileName, {
|
|
5389
|
+
fileName,
|
|
5390
|
+
exports: handlers
|
|
5391
|
+
});
|
|
5392
|
+
}
|
|
4809
5393
|
}
|
|
4810
5394
|
}
|
|
4811
5395
|
}
|
|
@@ -4831,9 +5415,19 @@ async function rango(options) {
|
|
|
4831
5415
|
const preset = resolvedOptions.preset ?? "node";
|
|
4832
5416
|
const showBanner = resolvedOptions.banner ?? true;
|
|
4833
5417
|
const plugins = [];
|
|
4834
|
-
const rangoAliases = getPackageAliases();
|
|
4835
|
-
const excludeDeps =
|
|
4836
|
-
|
|
5418
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
5419
|
+
const excludeDeps = [
|
|
5420
|
+
...getExcludeDeps(),
|
|
5421
|
+
// The public browser entry re-exports the RSDW browser client.
|
|
5422
|
+
// Excluding both keeps Vite from freezing the unpatched bundle into
|
|
5423
|
+
// .vite/deps before our source transforms run.
|
|
5424
|
+
"@vitejs/plugin-rsc/browser",
|
|
5425
|
+
// Keep the browser RSDW client out of Vite's dep optimizer so our
|
|
5426
|
+
// cjs-to-esm transform can patch the real file.
|
|
5427
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"
|
|
5428
|
+
];
|
|
5429
|
+
const pkg = getPublishedPackageName();
|
|
5430
|
+
const nested = (spec) => `${pkg} > ${spec}`;
|
|
4837
5431
|
const routerRef = { path: void 0 };
|
|
4838
5432
|
const prerenderEnabled = true;
|
|
4839
5433
|
if (preset === "cloudflare") {
|
|
@@ -4871,7 +5465,7 @@ async function rango(options) {
|
|
|
4871
5465
|
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
4872
5466
|
// Exclude rsc-router modules to ensure same Context instance
|
|
4873
5467
|
optimizeDeps: {
|
|
4874
|
-
include: ["rsc-html-stream/client"],
|
|
5468
|
+
include: [nested("rsc-html-stream/client")],
|
|
4875
5469
|
exclude: excludeDeps,
|
|
4876
5470
|
esbuildOptions: sharedEsbuildOptions
|
|
4877
5471
|
}
|
|
@@ -4896,8 +5490,10 @@ async function rango(options) {
|
|
|
4896
5490
|
"react-dom/static.edge",
|
|
4897
5491
|
"react/jsx-runtime",
|
|
4898
5492
|
"react/jsx-dev-runtime",
|
|
4899
|
-
"rsc-html-stream/server",
|
|
4900
|
-
|
|
5493
|
+
nested("rsc-html-stream/server"),
|
|
5494
|
+
nested(
|
|
5495
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5496
|
+
)
|
|
4901
5497
|
],
|
|
4902
5498
|
exclude: excludeDeps,
|
|
4903
5499
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -4912,7 +5508,9 @@ async function rango(options) {
|
|
|
4912
5508
|
"react",
|
|
4913
5509
|
"react/jsx-runtime",
|
|
4914
5510
|
"react/jsx-dev-runtime",
|
|
4915
|
-
|
|
5511
|
+
nested(
|
|
5512
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
5513
|
+
)
|
|
4916
5514
|
],
|
|
4917
5515
|
exclude: excludeDeps,
|
|
4918
5516
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -4929,6 +5527,7 @@ async function rango(options) {
|
|
|
4929
5527
|
}
|
|
4930
5528
|
});
|
|
4931
5529
|
plugins.push(createVirtualEntriesPlugin(finalEntries));
|
|
5530
|
+
plugins.push(performanceTracksPlugin());
|
|
4932
5531
|
plugins.push(
|
|
4933
5532
|
rsc({
|
|
4934
5533
|
entries: finalEntries,
|
|
@@ -4937,153 +5536,126 @@ async function rango(options) {
|
|
|
4937
5536
|
);
|
|
4938
5537
|
plugins.push(clientRefDedup());
|
|
4939
5538
|
} else {
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
const
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
routerRef.path = (abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs).replaceAll("\\", "/");
|
|
4956
|
-
} else if (candidates.length > 1) {
|
|
4957
|
-
const list = candidates.map(
|
|
4958
|
-
(f) => " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f)
|
|
4959
|
-
).join("\n");
|
|
4960
|
-
throw new Error(
|
|
4961
|
-
`[rsc-router] Multiple routers found. Specify \`router\` to choose one:
|
|
4962
|
-
${list}`
|
|
4963
|
-
);
|
|
4964
|
-
}
|
|
5539
|
+
plugins.push({
|
|
5540
|
+
name: "@rangojs/router:auto-discover",
|
|
5541
|
+
config(userConfig) {
|
|
5542
|
+
if (routerRef.path) return;
|
|
5543
|
+
const root = userConfig.root ? resolve9(process.cwd(), userConfig.root) : process.cwd();
|
|
5544
|
+
const candidates = findRouterFiles(root);
|
|
5545
|
+
if (candidates.length === 1) {
|
|
5546
|
+
const abs = candidates[0];
|
|
5547
|
+
routerRef.path = (abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs).replaceAll("\\", "/");
|
|
5548
|
+
} else if (candidates.length > 1) {
|
|
5549
|
+
const list = candidates.map(
|
|
5550
|
+
(f) => " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f)
|
|
5551
|
+
).join("\n");
|
|
5552
|
+
throw new Error(`[rsc-router] Multiple routers found:
|
|
5553
|
+
${list}`);
|
|
4965
5554
|
}
|
|
4966
|
-
}
|
|
4967
|
-
}
|
|
4968
|
-
const
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
resolve: {
|
|
4997
|
-
alias: rangoAliases
|
|
4998
|
-
},
|
|
4999
|
-
environments: {
|
|
5000
|
-
client: {
|
|
5001
|
-
build: {
|
|
5002
|
-
rollupOptions: {
|
|
5003
|
-
output: {
|
|
5004
|
-
manualChunks: getManualChunks
|
|
5005
|
-
}
|
|
5006
|
-
}
|
|
5007
|
-
},
|
|
5008
|
-
// Always exclude rsc-router modules, conditionally add virtual entry
|
|
5009
|
-
optimizeDeps: {
|
|
5010
|
-
// Pre-bundle React and rsc-html-stream to prevent late discovery
|
|
5011
|
-
// triggering ERR_OUTDATED_OPTIMIZED_DEP on cold starts
|
|
5012
|
-
include: [
|
|
5013
|
-
"react",
|
|
5014
|
-
"react-dom",
|
|
5015
|
-
"react/jsx-runtime",
|
|
5016
|
-
"react/jsx-dev-runtime",
|
|
5017
|
-
"rsc-html-stream/client"
|
|
5018
|
-
],
|
|
5019
|
-
exclude: excludeDeps,
|
|
5020
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
5021
|
-
...useVirtualClient && {
|
|
5022
|
-
// Tell Vite to scan the virtual entry for dependencies
|
|
5023
|
-
entries: [VIRTUAL_IDS.browser]
|
|
5024
|
-
}
|
|
5025
|
-
}
|
|
5026
|
-
},
|
|
5027
|
-
...useVirtualSSR && {
|
|
5028
|
-
ssr: {
|
|
5029
|
-
optimizeDeps: {
|
|
5030
|
-
entries: [VIRTUAL_IDS.ssr],
|
|
5031
|
-
// Pre-bundle all SSR deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
5032
|
-
include: [
|
|
5033
|
-
"react",
|
|
5034
|
-
"react-dom",
|
|
5035
|
-
"react-dom/server.edge",
|
|
5036
|
-
"react-dom/static.edge",
|
|
5037
|
-
"react/jsx-runtime",
|
|
5038
|
-
"react/jsx-dev-runtime",
|
|
5039
|
-
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5040
|
-
],
|
|
5041
|
-
exclude: excludeDeps,
|
|
5042
|
-
esbuildOptions: sharedEsbuildOptions
|
|
5555
|
+
}
|
|
5556
|
+
});
|
|
5557
|
+
const finalEntries = {
|
|
5558
|
+
client: VIRTUAL_IDS.browser,
|
|
5559
|
+
ssr: VIRTUAL_IDS.ssr,
|
|
5560
|
+
rsc: VIRTUAL_IDS.rsc
|
|
5561
|
+
};
|
|
5562
|
+
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
5563
|
+
let hasWarnedDuplicate = false;
|
|
5564
|
+
plugins.push({
|
|
5565
|
+
name: "@rangojs/router:rsc-integration",
|
|
5566
|
+
enforce: "pre",
|
|
5567
|
+
config() {
|
|
5568
|
+
return {
|
|
5569
|
+
optimizeDeps: {
|
|
5570
|
+
exclude: excludeDeps,
|
|
5571
|
+
esbuildOptions: sharedEsbuildOptions
|
|
5572
|
+
},
|
|
5573
|
+
build: {
|
|
5574
|
+
rollupOptions: { onwarn }
|
|
5575
|
+
},
|
|
5576
|
+
resolve: {
|
|
5577
|
+
alias: rangoAliases
|
|
5578
|
+
},
|
|
5579
|
+
environments: {
|
|
5580
|
+
client: {
|
|
5581
|
+
build: {
|
|
5582
|
+
rollupOptions: {
|
|
5583
|
+
output: {
|
|
5584
|
+
manualChunks: getManualChunks
|
|
5043
5585
|
}
|
|
5044
5586
|
}
|
|
5045
5587
|
},
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5588
|
+
optimizeDeps: {
|
|
5589
|
+
include: [
|
|
5590
|
+
"react",
|
|
5591
|
+
"react-dom",
|
|
5592
|
+
"react/jsx-runtime",
|
|
5593
|
+
"react/jsx-dev-runtime",
|
|
5594
|
+
nested("rsc-html-stream/client")
|
|
5595
|
+
],
|
|
5596
|
+
exclude: excludeDeps,
|
|
5597
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
5598
|
+
entries: [VIRTUAL_IDS.browser]
|
|
5599
|
+
}
|
|
5600
|
+
},
|
|
5601
|
+
ssr: {
|
|
5602
|
+
optimizeDeps: {
|
|
5603
|
+
entries: [VIRTUAL_IDS.ssr],
|
|
5604
|
+
include: [
|
|
5605
|
+
"react",
|
|
5606
|
+
"react-dom",
|
|
5607
|
+
"react-dom/server.edge",
|
|
5608
|
+
"react-dom/static.edge",
|
|
5609
|
+
"react/jsx-runtime",
|
|
5610
|
+
"react/jsx-dev-runtime",
|
|
5611
|
+
nested(
|
|
5612
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5613
|
+
)
|
|
5614
|
+
],
|
|
5615
|
+
exclude: excludeDeps,
|
|
5616
|
+
esbuildOptions: sharedEsbuildOptions
|
|
5617
|
+
}
|
|
5618
|
+
},
|
|
5619
|
+
rsc: {
|
|
5620
|
+
optimizeDeps: {
|
|
5621
|
+
entries: [VIRTUAL_IDS.rsc],
|
|
5622
|
+
include: [
|
|
5623
|
+
"react",
|
|
5624
|
+
"react/jsx-runtime",
|
|
5625
|
+
"react/jsx-dev-runtime",
|
|
5626
|
+
nested(
|
|
5627
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
5628
|
+
)
|
|
5629
|
+
],
|
|
5630
|
+
esbuildOptions: sharedEsbuildOptions
|
|
5060
5631
|
}
|
|
5061
5632
|
}
|
|
5062
|
-
};
|
|
5063
|
-
},
|
|
5064
|
-
configResolved(config) {
|
|
5065
|
-
if (showBanner) {
|
|
5066
|
-
const mode = config.command === "serve" ? process.argv.includes("preview") ? "preview" : "dev" : "build";
|
|
5067
|
-
printBanner(mode, "node", rangoVersion);
|
|
5068
|
-
}
|
|
5069
|
-
const rscMinimalCount = config.plugins.filter(
|
|
5070
|
-
(p) => p.name === "rsc:minimal"
|
|
5071
|
-
).length;
|
|
5072
|
-
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
5073
|
-
hasWarnedDuplicate = true;
|
|
5074
|
-
console.warn(
|
|
5075
|
-
"[rsc-router] Duplicate @vitejs/plugin-rsc detected. Remove rsc() from your config or use rango({ rsc: false }) for manual configuration."
|
|
5076
|
-
);
|
|
5077
5633
|
}
|
|
5634
|
+
};
|
|
5635
|
+
},
|
|
5636
|
+
configResolved(config) {
|
|
5637
|
+
if (showBanner) {
|
|
5638
|
+
const mode = config.command === "serve" ? process.argv.includes("preview") ? "preview" : "dev" : "build";
|
|
5639
|
+
printBanner(mode, "node", rangoVersion);
|
|
5078
5640
|
}
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5641
|
+
const rscMinimalCount = config.plugins.filter(
|
|
5642
|
+
(p) => p.name === "rsc:minimal"
|
|
5643
|
+
).length;
|
|
5644
|
+
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
5645
|
+
hasWarnedDuplicate = true;
|
|
5646
|
+
console.warn(
|
|
5647
|
+
"[rsc-router] Duplicate @vitejs/plugin-rsc detected. Remove rsc() from your vite config \u2014 rango() includes it automatically."
|
|
5648
|
+
);
|
|
5649
|
+
}
|
|
5650
|
+
}
|
|
5651
|
+
});
|
|
5652
|
+
plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
|
|
5653
|
+
plugins.push(performanceTracksPlugin());
|
|
5654
|
+
plugins.push(
|
|
5655
|
+
rsc({
|
|
5656
|
+
entries: finalEntries
|
|
5657
|
+
})
|
|
5658
|
+
);
|
|
5087
5659
|
plugins.push(clientRefDedup());
|
|
5088
5660
|
}
|
|
5089
5661
|
plugins.push({
|
|
@@ -5111,22 +5683,102 @@ ${list}`
|
|
|
5111
5683
|
plugins.push(createVersionPlugin());
|
|
5112
5684
|
const discoveryEntryPath = preset !== "cloudflare" ? routerRef.path : void 0;
|
|
5113
5685
|
const discoveryRouterRef = preset !== "cloudflare" ? routerRef : void 0;
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
plugins.push(createVersionInjectorPlugin(injectorEntryPath));
|
|
5686
|
+
if (preset === "cloudflare") {
|
|
5687
|
+
plugins.push(createVersionInjectorPlugin(void 0));
|
|
5117
5688
|
}
|
|
5118
5689
|
plugins.push(createCjsToEsmPlugin());
|
|
5119
5690
|
plugins.push(
|
|
5120
5691
|
createRouterDiscoveryPlugin(discoveryEntryPath, {
|
|
5121
5692
|
routerPathRef: discoveryRouterRef,
|
|
5122
5693
|
enableBuildPrerender: prerenderEnabled,
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
exclude: resolvedOptions.exclude
|
|
5694
|
+
buildEnv: options?.buildEnv,
|
|
5695
|
+
preset
|
|
5126
5696
|
})
|
|
5127
5697
|
);
|
|
5128
5698
|
return plugins;
|
|
5129
5699
|
}
|
|
5700
|
+
|
|
5701
|
+
// src/vite/plugins/refresh-cmd.ts
|
|
5702
|
+
function poke() {
|
|
5703
|
+
return {
|
|
5704
|
+
name: "vite-plugin-poke",
|
|
5705
|
+
apply: "serve",
|
|
5706
|
+
configureServer(server) {
|
|
5707
|
+
const stdin = process.stdin;
|
|
5708
|
+
const debug = process.env.RANGO_POKE_DEBUG === "1";
|
|
5709
|
+
const triggerReload = (source) => {
|
|
5710
|
+
server.hot.send({ type: "full-reload", path: "*" });
|
|
5711
|
+
server.config.logger.info(` browser reload (${source})`, {
|
|
5712
|
+
timestamp: true
|
|
5713
|
+
});
|
|
5714
|
+
};
|
|
5715
|
+
const toBuffer = (chunk) => {
|
|
5716
|
+
return typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
5717
|
+
};
|
|
5718
|
+
const formatChunk = (chunk) => {
|
|
5719
|
+
const data = toBuffer(chunk);
|
|
5720
|
+
const hex = Array.from(data).map((byte) => `0x${byte.toString(16).padStart(2, "0")}`).join(" ");
|
|
5721
|
+
const ascii = Array.from(data).map((byte) => {
|
|
5722
|
+
if (byte >= 32 && byte <= 126) return String.fromCharCode(byte);
|
|
5723
|
+
if (byte === 10) return "\\n";
|
|
5724
|
+
if (byte === 13) return "\\r";
|
|
5725
|
+
if (byte === 9) return "\\t";
|
|
5726
|
+
return ".";
|
|
5727
|
+
}).join("");
|
|
5728
|
+
return `len=${data.length} hex=[${hex}] ascii="${ascii}"`;
|
|
5729
|
+
};
|
|
5730
|
+
const readCtrlR = (chunk) => {
|
|
5731
|
+
const data = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
5732
|
+
return data.length === 1 && data[0] === 18;
|
|
5733
|
+
};
|
|
5734
|
+
const readSubmittedCommands = (chunk) => {
|
|
5735
|
+
const text = toBuffer(chunk).toString("utf8").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
5736
|
+
if (!text.includes("\n")) return [];
|
|
5737
|
+
const lines = text.split("\n");
|
|
5738
|
+
lines.pop();
|
|
5739
|
+
return lines;
|
|
5740
|
+
};
|
|
5741
|
+
if (debug) {
|
|
5742
|
+
server.config.logger.info(
|
|
5743
|
+
` poke debug enabled (isTTY=${stdin.isTTY ? "yes" : "no"}, isRaw=${stdin.isTTY ? stdin.isRaw ? "yes" : "no" : "n/a"})`,
|
|
5744
|
+
{ timestamp: true }
|
|
5745
|
+
);
|
|
5746
|
+
}
|
|
5747
|
+
if (stdin.isTTY) {
|
|
5748
|
+
server.config.logger.info(
|
|
5749
|
+
" poke ready: press e + enter to reload browser (ctrl+r also works when available)",
|
|
5750
|
+
{ timestamp: true }
|
|
5751
|
+
);
|
|
5752
|
+
}
|
|
5753
|
+
const onData = (data) => {
|
|
5754
|
+
if (debug) {
|
|
5755
|
+
server.config.logger.info(` poke stdin ${formatChunk(data)}`, {
|
|
5756
|
+
timestamp: true
|
|
5757
|
+
});
|
|
5758
|
+
}
|
|
5759
|
+
if (readCtrlR(data)) {
|
|
5760
|
+
triggerReload("ctrl+r");
|
|
5761
|
+
return;
|
|
5762
|
+
}
|
|
5763
|
+
for (const command of readSubmittedCommands(data)) {
|
|
5764
|
+
if (command === "e") {
|
|
5765
|
+
triggerReload("e+enter");
|
|
5766
|
+
return;
|
|
5767
|
+
}
|
|
5768
|
+
if (command === "\x1Br") {
|
|
5769
|
+
triggerReload("option+r+enter");
|
|
5770
|
+
return;
|
|
5771
|
+
}
|
|
5772
|
+
}
|
|
5773
|
+
};
|
|
5774
|
+
stdin.on("data", onData);
|
|
5775
|
+
server.httpServer?.on("close", () => {
|
|
5776
|
+
stdin.off("data", onData);
|
|
5777
|
+
});
|
|
5778
|
+
}
|
|
5779
|
+
};
|
|
5780
|
+
}
|
|
5130
5781
|
export {
|
|
5782
|
+
poke,
|
|
5131
5783
|
rango
|
|
5132
5784
|
};
|