@rangojs/router 0.0.0-experimental.8874d8d2 → 0.0.0-experimental.89
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 +126 -38
- package/dist/bin/rango.js +138 -50
- package/dist/vite/index.js +1705 -701
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +19 -16
- package/skills/breadcrumbs/SKILL.md +3 -1
- package/skills/cache-guide/SKILL.md +32 -0
- package/skills/caching/SKILL.md +45 -4
- package/skills/handler-use/SKILL.md +362 -0
- package/skills/hooks/SKILL.md +28 -20
- 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 +88 -45
- 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 +110 -68
- package/skills/rango/SKILL.md +24 -22
- package/skills/response-routes/SKILL.md +8 -0
- package/skills/route/SKILL.md +55 -0
- package/skills/router-setup/SKILL.md +87 -2
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/typesafety/SKILL.md +13 -1
- package/src/__internal.ts +1 -1
- 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/navigation-bridge.ts +90 -16
- package/src/browser/navigation-client.ts +167 -59
- 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 +175 -15
- package/src/browser/prefetch/fetch.ts +180 -33
- 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 +81 -9
- 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 +168 -65
- 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 +49 -5
- package/src/build/generate-manifest.ts +6 -6
- package/src/build/generate-route-types.ts +3 -0
- package/src/build/route-trie.ts +50 -24
- 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.tsx +84 -230
- package/src/context-var.ts +72 -2
- package/src/debug.ts +2 -2
- package/src/handle.ts +40 -0
- package/src/index.rsc.ts +6 -1
- package/src/index.ts +49 -6
- package/src/outlet-context.ts +1 -1
- package/src/prerender/store.ts +5 -4
- 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 -0
- 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 +101 -25
- package/src/router/intercept-resolution.ts +11 -4
- package/src/router/lazy-includes.ts +10 -7
- package/src/router/loader-resolution.ts +159 -21
- package/src/router/logging.ts +5 -2
- package/src/router/manifest.ts +31 -16
- package/src/router/match-api.ts +127 -192
- 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 +104 -10
- package/src/router/metrics.ts +6 -1
- package/src/router/middleware-types.ts +8 -30
- package/src/router/middleware.ts +36 -10
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +60 -9
- package/src/router/prerender-match.ts +110 -10
- package/src/router/preview-match.ts +30 -102
- package/src/router/request-classification.ts +310 -0
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +6 -1
- package/src/router/router-interfaces.ts +36 -4
- package/src/router/router-options.ts +37 -11
- package/src/router/segment-resolution/fresh.ts +198 -20
- package/src/router/segment-resolution/helpers.ts +29 -24
- package/src/router/segment-resolution/loader-cache.ts +1 -0
- package/src/router/segment-resolution/revalidation.ts +437 -297
- package/src/router/segment-wrappers.ts +2 -0
- package/src/router/trie-matching.ts +10 -4
- package/src/router/types.ts +1 -0
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +60 -8
- package/src/rsc/handler.ts +478 -374
- package/src/rsc/helpers.ts +69 -41
- package/src/rsc/loader-fetch.ts +23 -3
- package/src/rsc/manifest-init.ts +5 -1
- package/src/rsc/progressive-enhancement.ts +16 -2
- package/src/rsc/response-route-handler.ts +14 -1
- package/src/rsc/rsc-rendering.ts +17 -1
- package/src/rsc/server-action.ts +10 -0
- package/src/rsc/ssr-setup.ts +2 -2
- package/src/rsc/types.ts +9 -1
- 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 +166 -17
- package/src/server/handle-store.ts +19 -0
- package/src/server/loader-registry.ts +9 -8
- package/src/server/request-context.ts +194 -60
- package/src/ssr/index.tsx +4 -0
- package/src/static-handler.ts +18 -6
- package/src/types/cache-types.ts +4 -4
- package/src/types/handler-context.ts +137 -65
- package/src/types/loader-types.ts +41 -15
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-entry.ts +19 -1
- package/src/types/segments.ts +2 -0
- 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/debug.ts +184 -0
- package/src/vite/discovery/bundle-postprocess.ts +30 -33
- package/src/vite/discovery/discover-routers.ts +36 -4
- package/src/vite/discovery/prerender-collection.ts +175 -74
- package/src/vite/discovery/state.ts +13 -6
- package/src/vite/index.ts +4 -0
- package/src/vite/plugin-types.ts +51 -79
- package/src/vite/plugins/cjs-to-esm.ts +5 -0
- package/src/vite/plugins/client-ref-dedup.ts +16 -0
- package/src/vite/plugins/client-ref-hashing.ts +16 -4
- 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 +53 -31
- 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-ids/router-transform.ts +20 -3
- package/src/vite/plugins/expose-internal-ids.ts +563 -316
- package/src/vite/plugins/performance-tracks.ts +96 -0
- package/src/vite/plugins/refresh-cmd.ts +88 -26
- package/src/vite/plugins/use-cache-transform.ts +56 -43
- package/src/vite/plugins/version-plugin.ts +13 -1
- package/src/vite/rango.ts +204 -217
- package/src/vite/router-discovery.ts +393 -67
- package/src/vite/utils/banner.ts +4 -4
- package/src/vite/utils/package-resolution.ts +41 -1
- package/src/vite/utils/prerender-utils.ts +37 -5
- package/src/vite/utils/shared-utils.ts +3 -2
package/dist/vite/index.js
CHANGED
|
@@ -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);
|
|
@@ -188,7 +191,99 @@ function escapeRegExp(input) {
|
|
|
188
191
|
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
189
192
|
}
|
|
190
193
|
|
|
194
|
+
// src/vite/debug.ts
|
|
195
|
+
import debugFactory from "debug";
|
|
196
|
+
var NS = {
|
|
197
|
+
config: "rango:config",
|
|
198
|
+
discovery: "rango:discovery",
|
|
199
|
+
routes: "rango:routes",
|
|
200
|
+
prerender: "rango:prerender",
|
|
201
|
+
build: "rango:build",
|
|
202
|
+
dev: "rango:dev",
|
|
203
|
+
transform: "rango:transform"
|
|
204
|
+
};
|
|
205
|
+
if (process.env.INTERNAL_RANGO_DEBUG) {
|
|
206
|
+
const existing = debugFactory.disable();
|
|
207
|
+
debugFactory.enable(existing ? `${existing},rango:*` : "rango:*");
|
|
208
|
+
}
|
|
209
|
+
function createRangoDebugger(namespace) {
|
|
210
|
+
const primary = debugFactory(namespace);
|
|
211
|
+
const shadow = debugFactory(`vite:${namespace}`);
|
|
212
|
+
if (primary.enabled) return primary;
|
|
213
|
+
if (shadow.enabled) return shadow;
|
|
214
|
+
return void 0;
|
|
215
|
+
}
|
|
216
|
+
async function timed(debug11, label, fn) {
|
|
217
|
+
if (!debug11) return await fn();
|
|
218
|
+
const start = performance.now();
|
|
219
|
+
try {
|
|
220
|
+
return await fn();
|
|
221
|
+
} finally {
|
|
222
|
+
debug11("%s (%sms)", label, (performance.now() - start).toFixed(1));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function timedSync(debug11, label, fn) {
|
|
226
|
+
if (!debug11) return fn();
|
|
227
|
+
const start = performance.now();
|
|
228
|
+
try {
|
|
229
|
+
return fn();
|
|
230
|
+
} finally {
|
|
231
|
+
debug11("%s (%sms)", label, (performance.now() - start).toFixed(1));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function createCounter(debug11, label) {
|
|
235
|
+
if (!debug11) return void 0;
|
|
236
|
+
let n = 0;
|
|
237
|
+
let totalMs = 0;
|
|
238
|
+
let slowestMs = 0;
|
|
239
|
+
let slowestFile = "";
|
|
240
|
+
const record = (file, ms) => {
|
|
241
|
+
n++;
|
|
242
|
+
totalMs += ms;
|
|
243
|
+
if (ms > slowestMs) {
|
|
244
|
+
slowestMs = ms;
|
|
245
|
+
slowestFile = file;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
return {
|
|
249
|
+
record,
|
|
250
|
+
time(file, fn) {
|
|
251
|
+
const start = performance.now();
|
|
252
|
+
let out;
|
|
253
|
+
try {
|
|
254
|
+
out = fn();
|
|
255
|
+
} catch (err) {
|
|
256
|
+
record(file, performance.now() - start);
|
|
257
|
+
throw err;
|
|
258
|
+
}
|
|
259
|
+
if (out && typeof out.then === "function") {
|
|
260
|
+
return out.finally(
|
|
261
|
+
() => record(file, performance.now() - start)
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
record(file, performance.now() - start);
|
|
265
|
+
return out;
|
|
266
|
+
},
|
|
267
|
+
flush() {
|
|
268
|
+
if (n === 0) return;
|
|
269
|
+
debug11(
|
|
270
|
+
"%s: %d files, %sms total, slowest %sms %s",
|
|
271
|
+
label,
|
|
272
|
+
n,
|
|
273
|
+
totalMs.toFixed(1),
|
|
274
|
+
slowestMs.toFixed(1),
|
|
275
|
+
slowestFile
|
|
276
|
+
);
|
|
277
|
+
n = 0;
|
|
278
|
+
totalMs = 0;
|
|
279
|
+
slowestMs = 0;
|
|
280
|
+
slowestFile = "";
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
191
285
|
// src/vite/plugins/expose-action-id.ts
|
|
286
|
+
var debug = createRangoDebugger(NS.transform);
|
|
192
287
|
function getRscPluginApi(config) {
|
|
193
288
|
let plugin = config.plugins.find((p) => p.name === "rsc:minimal");
|
|
194
289
|
if (!plugin) {
|
|
@@ -277,6 +372,8 @@ function exposeActionId() {
|
|
|
277
372
|
let isBuild = false;
|
|
278
373
|
let hashToFileMap;
|
|
279
374
|
let rscPluginApi;
|
|
375
|
+
const counterTransform = createCounter(debug, "expose-action-id transform");
|
|
376
|
+
const counterRender = createCounter(debug, "expose-action-id renderChunk");
|
|
280
377
|
return {
|
|
281
378
|
name: "@rangojs/router:expose-action-id",
|
|
282
379
|
// Run after all other plugins (including RSC plugin's transforms)
|
|
@@ -286,13 +383,17 @@ function exposeActionId() {
|
|
|
286
383
|
isBuild = config.command === "build";
|
|
287
384
|
rscPluginApi = getRscPluginApi(config);
|
|
288
385
|
},
|
|
386
|
+
buildEnd() {
|
|
387
|
+
counterTransform?.flush();
|
|
388
|
+
counterRender?.flush();
|
|
389
|
+
},
|
|
289
390
|
buildStart() {
|
|
290
391
|
if (!rscPluginApi) {
|
|
291
392
|
rscPluginApi = getRscPluginApi(config);
|
|
292
393
|
}
|
|
293
394
|
if (!rscPluginApi) {
|
|
294
395
|
throw new Error(
|
|
295
|
-
"[rsc-router] Could not find @vitejs/plugin-rsc. @rangojs/router requires the Vite RSC plugin
|
|
396
|
+
"[rsc-router] Could not find @vitejs/plugin-rsc. @rangojs/router requires the Vite RSC plugin, which is included automatically by rango()."
|
|
296
397
|
);
|
|
297
398
|
}
|
|
298
399
|
if (!isBuild) return;
|
|
@@ -322,28 +423,42 @@ function exposeActionId() {
|
|
|
322
423
|
if (id.includes("/node_modules/")) {
|
|
323
424
|
return;
|
|
324
425
|
}
|
|
325
|
-
|
|
426
|
+
const start = counterTransform ? performance.now() : 0;
|
|
427
|
+
try {
|
|
428
|
+
return transformServerReferences(code, id);
|
|
429
|
+
} finally {
|
|
430
|
+
counterTransform?.record(id, performance.now() - start);
|
|
431
|
+
}
|
|
326
432
|
},
|
|
327
433
|
// Build mode: renderChunk runs after all transforms and bundling complete
|
|
328
434
|
renderChunk(code, chunk) {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
code
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
435
|
+
const start = counterRender ? performance.now() : 0;
|
|
436
|
+
try {
|
|
437
|
+
const isRscEnv = this.environment?.name === "rsc";
|
|
438
|
+
const effectiveMap = isRscEnv ? hashToFileMap : void 0;
|
|
439
|
+
if (isRscEnv && hashToFileMap) {
|
|
440
|
+
const s = new MagicString(code);
|
|
441
|
+
const changed1 = applyServerReferenceWrapping(code, s, effectiveMap);
|
|
442
|
+
const changed2 = applyRegisterReferenceWrapping(
|
|
443
|
+
code,
|
|
444
|
+
s,
|
|
445
|
+
hashToFileMap
|
|
446
|
+
);
|
|
447
|
+
if (changed1 || changed2) {
|
|
448
|
+
return {
|
|
449
|
+
code: s.toString(),
|
|
450
|
+
map: s.generateMap({
|
|
451
|
+
source: chunk.fileName,
|
|
452
|
+
includeContent: true
|
|
453
|
+
})
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
343
457
|
}
|
|
344
|
-
return
|
|
458
|
+
return transformServerReferences(code, chunk.fileName, effectiveMap);
|
|
459
|
+
} finally {
|
|
460
|
+
counterRender?.record(chunk.fileName, performance.now() - start);
|
|
345
461
|
}
|
|
346
|
-
return transformServerReferences(code, chunk.fileName, effectiveMap);
|
|
347
462
|
}
|
|
348
463
|
};
|
|
349
464
|
}
|
|
@@ -910,9 +1025,7 @@ function generateWholeFileStubs(cfg, bindings, code, filePath, isBuild) {
|
|
|
910
1025
|
});
|
|
911
1026
|
return { code: stubs.join("\n") + "\n", map: null };
|
|
912
1027
|
}
|
|
913
|
-
function
|
|
914
|
-
if (bindings.length === 0) return null;
|
|
915
|
-
const s = new MagicString2(code);
|
|
1028
|
+
function stubHandlerExprs(cfg, bindings, s, filePath, isBuild) {
|
|
916
1029
|
let hasChanges = false;
|
|
917
1030
|
for (const binding of bindings) {
|
|
918
1031
|
const exportName = binding.exportNames[0];
|
|
@@ -924,15 +1037,7 @@ function generateExprStubs(cfg, bindings, code, filePath, sourceId, isBuild) {
|
|
|
924
1037
|
);
|
|
925
1038
|
hasChanges = true;
|
|
926
1039
|
}
|
|
927
|
-
|
|
928
|
-
return {
|
|
929
|
-
code: s.toString(),
|
|
930
|
-
map: s.generateMap({
|
|
931
|
-
source: sourceId,
|
|
932
|
-
includeContent: true,
|
|
933
|
-
hires: "boundary"
|
|
934
|
-
})
|
|
935
|
-
};
|
|
1040
|
+
return hasChanges;
|
|
936
1041
|
}
|
|
937
1042
|
function transformHandlerIds(cfg, bindings, s, filePath, isBuild) {
|
|
938
1043
|
let hasChanges = false;
|
|
@@ -960,6 +1065,7 @@ ${binding.localName}.$$id = "${handlerId}";`;
|
|
|
960
1065
|
import MagicString3 from "magic-string";
|
|
961
1066
|
import path3 from "node:path";
|
|
962
1067
|
import { createHash } from "node:crypto";
|
|
1068
|
+
var debug2 = createRangoDebugger(NS.transform);
|
|
963
1069
|
function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
964
1070
|
const pat = new RegExp(
|
|
965
1071
|
`\\b(?:${routerFnNames.map((n) => n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\s*(?:<[^>]*>)?\\s*\\(`,
|
|
@@ -1002,11 +1108,15 @@ function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
|
1002
1108
|
}
|
|
1003
1109
|
function exposeRouterId() {
|
|
1004
1110
|
let projectRoot = "";
|
|
1111
|
+
const counter = createCounter(debug2, "expose-router-id");
|
|
1005
1112
|
return {
|
|
1006
1113
|
name: "@rangojs/router:expose-router-id",
|
|
1007
1114
|
configResolved(config) {
|
|
1008
1115
|
projectRoot = config.root;
|
|
1009
1116
|
},
|
|
1117
|
+
buildEnd() {
|
|
1118
|
+
counter?.flush();
|
|
1119
|
+
},
|
|
1010
1120
|
transform(code, id) {
|
|
1011
1121
|
if (!code.includes("createRouter")) return null;
|
|
1012
1122
|
if (!/import\s*\{[^}]*\bcreateRouter\b[^}]*\}\s*from\s*["']@rangojs\/router(?:\/server)?["']/.test(
|
|
@@ -1015,14 +1125,25 @@ function exposeRouterId() {
|
|
|
1015
1125
|
return null;
|
|
1016
1126
|
}
|
|
1017
1127
|
if (id.includes("node_modules")) return null;
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
|
|
1128
|
+
const start = counter ? performance.now() : 0;
|
|
1129
|
+
try {
|
|
1130
|
+
const filePath = normalizePath(path3.relative(projectRoot, id));
|
|
1131
|
+
const routerFnNames = getImportedFnNames(code, "createRouter");
|
|
1132
|
+
return transformRouter(
|
|
1133
|
+
code,
|
|
1134
|
+
filePath,
|
|
1135
|
+
routerFnNames,
|
|
1136
|
+
normalizePath(id)
|
|
1137
|
+
);
|
|
1138
|
+
} finally {
|
|
1139
|
+
counter?.record(id, performance.now() - start);
|
|
1140
|
+
}
|
|
1021
1141
|
}
|
|
1022
1142
|
};
|
|
1023
1143
|
}
|
|
1024
1144
|
|
|
1025
1145
|
// src/vite/plugins/expose-internal-ids.ts
|
|
1146
|
+
var debug3 = createRangoDebugger(NS.transform);
|
|
1026
1147
|
var VIRTUAL_LOADER_MANIFEST = "virtual:rsc-router/loader-manifest";
|
|
1027
1148
|
var RESOLVED_VIRTUAL_LOADER_MANIFEST = "\0" + VIRTUAL_LOADER_MANIFEST;
|
|
1028
1149
|
var VIRTUAL_HANDLER_PREFIX = "virtual:handler-extract:";
|
|
@@ -1035,9 +1156,13 @@ function exposeInternalIds(options) {
|
|
|
1035
1156
|
const staticHandlerModules = /* @__PURE__ */ new Map();
|
|
1036
1157
|
const virtualHandlers = /* @__PURE__ */ new Map();
|
|
1037
1158
|
const unsupportedShapeWarnings = /* @__PURE__ */ new Set();
|
|
1159
|
+
const counter = createCounter(debug3, "expose-internal-ids");
|
|
1038
1160
|
return {
|
|
1039
1161
|
name: "@rangojs/router:expose-internal-ids",
|
|
1040
1162
|
enforce: "post",
|
|
1163
|
+
buildEnd() {
|
|
1164
|
+
counter?.flush();
|
|
1165
|
+
},
|
|
1041
1166
|
api: {
|
|
1042
1167
|
prerenderHandlerModules,
|
|
1043
1168
|
staticHandlerModules
|
|
@@ -1151,11 +1276,13 @@ ${lazyImports.join(",\n")}
|
|
|
1151
1276
|
// --------------- Unified transform ---------------
|
|
1152
1277
|
transform(code, id) {
|
|
1153
1278
|
if (id.includes("/node_modules/")) return;
|
|
1154
|
-
const
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
this.
|
|
1158
|
-
|
|
1279
|
+
const __t0 = counter ? performance.now() : 0;
|
|
1280
|
+
try {
|
|
1281
|
+
const filePath = normalizePath(path4.relative(projectRoot, id));
|
|
1282
|
+
const isRscEnv = this.environment?.name === "rsc";
|
|
1283
|
+
if (id.includes(".named-routes.gen.") && !isRscEnv && this.environment?.name === "client") {
|
|
1284
|
+
this.warn(
|
|
1285
|
+
`
|
|
1159
1286
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1160
1287
|
!! !!
|
|
1161
1288
|
!! WARNING: NamedRoutes imported in a CLIENT component! !!
|
|
@@ -1175,228 +1302,373 @@ ${lazyImports.join(",\n")}
|
|
|
1175
1302
|
!! !!
|
|
1176
1303
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1177
1304
|
`
|
|
1178
|
-
|
|
1179
|
-
}
|
|
1180
|
-
if (!code.includes("@rangojs/router")) return;
|
|
1181
|
-
const has = detectImports(code);
|
|
1182
|
-
const hasLoaderCode = has.loader && code.includes("createLoader");
|
|
1183
|
-
const hasHandleCode = has.handle && code.includes("createHandle");
|
|
1184
|
-
const hasLocationStateCode = has.locationState && code.includes("createLocationState");
|
|
1185
|
-
const hasPrerenderHandlerCode = has.prerenderHandler && code.includes("Prerender");
|
|
1186
|
-
const hasStaticHandlerCode = has.staticHandler && code.includes("Static");
|
|
1187
|
-
if (!hasLoaderCode && !hasHandleCode && !hasLocationStateCode && !hasPrerenderHandlerCode && !hasStaticHandlerCode) {
|
|
1188
|
-
return;
|
|
1189
|
-
}
|
|
1190
|
-
const _fnNamesCache = /* @__PURE__ */ new Map();
|
|
1191
|
-
const _bindingsCache = /* @__PURE__ */ new Map();
|
|
1192
|
-
let _cachedAst;
|
|
1193
|
-
let _astParseFailed = false;
|
|
1194
|
-
let _astCodeRef = code;
|
|
1195
|
-
const getFnNames = (canonicalName) => {
|
|
1196
|
-
let result = _fnNamesCache.get(canonicalName);
|
|
1197
|
-
if (!result) {
|
|
1198
|
-
result = getImportedFnNames(code, canonicalName);
|
|
1199
|
-
_fnNamesCache.set(canonicalName, result);
|
|
1305
|
+
);
|
|
1200
1306
|
}
|
|
1201
|
-
return
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1307
|
+
if (!code.includes("@rangojs/router")) return;
|
|
1308
|
+
const has = detectImports(code);
|
|
1309
|
+
const hasLoaderCode = has.loader && code.includes("createLoader");
|
|
1310
|
+
const hasHandleCode = has.handle && code.includes("createHandle");
|
|
1311
|
+
const hasLocationStateCode = has.locationState && code.includes("createLocationState");
|
|
1312
|
+
const hasPrerenderHandlerCode = has.prerenderHandler && code.includes("Prerender");
|
|
1313
|
+
const hasStaticHandlerCode = has.staticHandler && code.includes("Static");
|
|
1314
|
+
if (!hasLoaderCode && !hasHandleCode && !hasLocationStateCode && !hasPrerenderHandlerCode && !hasStaticHandlerCode) {
|
|
1315
|
+
return;
|
|
1208
1316
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1317
|
+
const _fnNamesCache = /* @__PURE__ */ new Map();
|
|
1318
|
+
const _bindingsCache = /* @__PURE__ */ new Map();
|
|
1319
|
+
let _cachedAst;
|
|
1320
|
+
let _astParseFailed = false;
|
|
1321
|
+
let _astCodeRef = code;
|
|
1322
|
+
const getFnNames = (canonicalName) => {
|
|
1323
|
+
let result = _fnNamesCache.get(canonicalName);
|
|
1324
|
+
if (!result) {
|
|
1325
|
+
result = getImportedFnNames(code, canonicalName);
|
|
1326
|
+
_fnNamesCache.set(canonicalName, result);
|
|
1327
|
+
}
|
|
1328
|
+
return result;
|
|
1329
|
+
};
|
|
1330
|
+
const lazyAst = () => {
|
|
1331
|
+
if (code !== _astCodeRef) {
|
|
1332
|
+
_cachedAst = void 0;
|
|
1333
|
+
_astParseFailed = false;
|
|
1334
|
+
_astCodeRef = code;
|
|
1335
|
+
}
|
|
1336
|
+
if (_cachedAst !== void 0 || _astParseFailed) return _cachedAst;
|
|
1337
|
+
try {
|
|
1338
|
+
_cachedAst = parseAst2(code, { jsx: true });
|
|
1339
|
+
} catch {
|
|
1340
|
+
_astParseFailed = true;
|
|
1341
|
+
}
|
|
1342
|
+
return _cachedAst;
|
|
1343
|
+
};
|
|
1344
|
+
const getBindings = (currentCode, fnNames) => {
|
|
1345
|
+
const key = fnNames.join("\0");
|
|
1346
|
+
let result = _bindingsCache.get(key);
|
|
1347
|
+
if (!result) {
|
|
1348
|
+
result = collectCreateExportBindings(
|
|
1349
|
+
currentCode,
|
|
1350
|
+
fnNames,
|
|
1351
|
+
lazyAst()
|
|
1352
|
+
);
|
|
1353
|
+
_bindingsCache.set(key, result);
|
|
1354
|
+
}
|
|
1355
|
+
return result;
|
|
1356
|
+
};
|
|
1357
|
+
for (const cfg of STRICT_CREATE_CONFIGS) {
|
|
1358
|
+
const hasCode = cfg.fnName === "createLoader" ? hasLoaderCode : cfg.fnName === "createHandle" ? hasHandleCode : hasLocationStateCode;
|
|
1359
|
+
if (!hasCode) continue;
|
|
1360
|
+
const fnNames = getFnNames(cfg.fnName);
|
|
1361
|
+
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1362
|
+
const supportedBindings = getBindings(code, fnNames).length;
|
|
1363
|
+
if (totalCalls <= supportedBindings) continue;
|
|
1364
|
+
const warnKey = `${id}::${cfg.fnName}`;
|
|
1365
|
+
if (unsupportedShapeWarnings.has(warnKey)) continue;
|
|
1366
|
+
unsupportedShapeWarnings.add(warnKey);
|
|
1367
|
+
this.warn(buildUnsupportedShapeWarning(filePath, cfg.fnName));
|
|
1214
1368
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1369
|
+
if (hasLoaderCode && isRscEnv) {
|
|
1370
|
+
const fnNames = getFnNames("createLoader");
|
|
1371
|
+
const bindings = getBindings(code, fnNames);
|
|
1372
|
+
for (const binding of bindings) {
|
|
1373
|
+
const exportName = binding.exportNames[0];
|
|
1374
|
+
const hashedId = hashId(filePath, exportName);
|
|
1375
|
+
loaderRegistry.set(hashedId, {
|
|
1376
|
+
filePath,
|
|
1377
|
+
exportName
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1223
1380
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1231
|
-
const supportedBindings = getBindings(code, fnNames).length;
|
|
1232
|
-
if (totalCalls <= supportedBindings) continue;
|
|
1233
|
-
const warnKey = `${id}::${cfg.fnName}`;
|
|
1234
|
-
if (unsupportedShapeWarnings.has(warnKey)) continue;
|
|
1235
|
-
unsupportedShapeWarnings.add(warnKey);
|
|
1236
|
-
this.warn(buildUnsupportedShapeWarning(filePath, cfg.fnName));
|
|
1237
|
-
}
|
|
1238
|
-
if (hasLoaderCode && isRscEnv) {
|
|
1239
|
-
const fnNames = getFnNames("createLoader");
|
|
1240
|
-
const bindings = getBindings(code, fnNames);
|
|
1241
|
-
for (const binding of bindings) {
|
|
1242
|
-
const exportName = binding.exportNames[0];
|
|
1243
|
-
const hashedId = hashId(filePath, exportName);
|
|
1244
|
-
loaderRegistry.set(hashedId, {
|
|
1381
|
+
if (hasLoaderCode && !isRscEnv) {
|
|
1382
|
+
const fnNames = getFnNames("createLoader");
|
|
1383
|
+
const bindings = getBindings(code, fnNames);
|
|
1384
|
+
const stubResult = generateClientLoaderStubs(
|
|
1385
|
+
bindings,
|
|
1386
|
+
code,
|
|
1245
1387
|
filePath,
|
|
1246
|
-
|
|
1247
|
-
|
|
1388
|
+
isBuild
|
|
1389
|
+
);
|
|
1390
|
+
if (stubResult) return stubResult;
|
|
1248
1391
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
}
|
|
1261
|
-
if (hasPrerenderHandlerCode && !isRscEnv) {
|
|
1262
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1263
|
-
const bindings = getBindings(code, fnNames);
|
|
1264
|
-
const wholeFile = generateWholeFileStubs(
|
|
1265
|
-
PRERENDER_CONFIG,
|
|
1266
|
-
bindings,
|
|
1267
|
-
code,
|
|
1268
|
-
filePath,
|
|
1269
|
-
isBuild
|
|
1270
|
-
);
|
|
1271
|
-
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
|
-
}
|
|
1282
|
-
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1283
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1284
|
-
const exportNames = getBindings(code, fnNames).map(
|
|
1285
|
-
(b) => b.exportNames[0]
|
|
1286
|
-
);
|
|
1287
|
-
if (exportNames.length > 0) {
|
|
1288
|
-
prerenderHandlerModules.set(id, exportNames);
|
|
1392
|
+
if (hasPrerenderHandlerCode && !isRscEnv) {
|
|
1393
|
+
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1394
|
+
const bindings = getBindings(code, fnNames);
|
|
1395
|
+
const wholeFile = generateWholeFileStubs(
|
|
1396
|
+
PRERENDER_CONFIG,
|
|
1397
|
+
bindings,
|
|
1398
|
+
code,
|
|
1399
|
+
filePath,
|
|
1400
|
+
isBuild
|
|
1401
|
+
);
|
|
1402
|
+
if (wholeFile) return wholeFile;
|
|
1289
1403
|
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
const
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
const
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1404
|
+
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1405
|
+
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1406
|
+
const exportNames = getBindings(code, fnNames).map(
|
|
1407
|
+
(b) => b.exportNames[0]
|
|
1408
|
+
);
|
|
1409
|
+
if (exportNames.length > 0) {
|
|
1410
|
+
prerenderHandlerModules.set(id, exportNames);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
let changed = false;
|
|
1414
|
+
const handlerConfigs = [
|
|
1415
|
+
hasStaticHandlerCode && STATIC_CONFIG,
|
|
1416
|
+
hasPrerenderHandlerCode && PRERENDER_CONFIG
|
|
1417
|
+
].filter((c) => !!c).map((cfg) => {
|
|
1418
|
+
const fnNames = getFnNames(cfg.fnName);
|
|
1419
|
+
return { cfg, fnNames };
|
|
1420
|
+
});
|
|
1421
|
+
for (const { cfg, fnNames } of handlerConfigs) {
|
|
1422
|
+
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1423
|
+
const supportedBindings = getBindings(code, fnNames).length;
|
|
1424
|
+
if (totalCalls > supportedBindings) {
|
|
1425
|
+
const iterS = new MagicString4(code);
|
|
1426
|
+
const result = transformInlineHandlers(
|
|
1427
|
+
cfg.fnName,
|
|
1428
|
+
VIRTUAL_HANDLER_PREFIX,
|
|
1429
|
+
iterS,
|
|
1430
|
+
code,
|
|
1431
|
+
filePath,
|
|
1432
|
+
virtualHandlers,
|
|
1433
|
+
id,
|
|
1434
|
+
parseAst2
|
|
1435
|
+
);
|
|
1436
|
+
if (result) {
|
|
1437
|
+
changed = true;
|
|
1438
|
+
code = iterS.toString();
|
|
1439
|
+
_bindingsCache.clear();
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
if (hasStaticHandlerCode && !isRscEnv) {
|
|
1444
|
+
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1445
|
+
const bindings = getBindings(code, fnNames);
|
|
1446
|
+
const wholeFile = generateWholeFileStubs(
|
|
1447
|
+
STATIC_CONFIG,
|
|
1448
|
+
bindings,
|
|
1308
1449
|
code,
|
|
1309
1450
|
filePath,
|
|
1310
|
-
|
|
1311
|
-
id,
|
|
1312
|
-
parseAst2
|
|
1451
|
+
isBuild
|
|
1313
1452
|
);
|
|
1314
|
-
if (
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1453
|
+
if (wholeFile) return wholeFile;
|
|
1454
|
+
}
|
|
1455
|
+
if (!isRscEnv && (hasPrerenderHandlerCode || hasStaticHandlerCode)) {
|
|
1456
|
+
const prerenderFnNames = hasPrerenderHandlerCode ? getFnNames(PRERENDER_CONFIG.fnName) : [];
|
|
1457
|
+
const staticFnNames = hasStaticHandlerCode ? getFnNames(STATIC_CONFIG.fnName) : [];
|
|
1458
|
+
const loaderFnNames = hasLoaderCode ? getFnNames("createLoader") : [];
|
|
1459
|
+
const handleFnNames = hasHandleCode ? getFnNames("createHandle") : [];
|
|
1460
|
+
const lsFnNames = hasLocationStateCode ? getFnNames("createLocationState") : [];
|
|
1461
|
+
const allBindings = [];
|
|
1462
|
+
for (const fnNames of [
|
|
1463
|
+
prerenderFnNames,
|
|
1464
|
+
staticFnNames,
|
|
1465
|
+
loaderFnNames,
|
|
1466
|
+
handleFnNames,
|
|
1467
|
+
lsFnNames
|
|
1468
|
+
]) {
|
|
1469
|
+
if (fnNames.length > 0) {
|
|
1470
|
+
allBindings.push(...getBindings(code, fnNames));
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
let canStubWholeFile = allBindings.length > 0 && isExportOnlyFile(code, allBindings);
|
|
1474
|
+
if (canStubWholeFile && (handleFnNames.length > 0 || lsFnNames.length > 0)) {
|
|
1475
|
+
const exportedLocals = new Set(allBindings.map((b) => b.localName));
|
|
1476
|
+
const strippedBindings = [];
|
|
1477
|
+
const localDeclPattern = /(?:^|;|\n)\s*(?:const|let|var|function)\s+(\w+)/g;
|
|
1478
|
+
let declMatch;
|
|
1479
|
+
while ((declMatch = localDeclPattern.exec(code)) !== null) {
|
|
1480
|
+
const name = declMatch[1];
|
|
1481
|
+
if (!exportedLocals.has(name) && !/^_c\d*$/.test(name)) {
|
|
1482
|
+
strippedBindings.push(name);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
const importPattern = /import\s*\{([^}]*)\}\s*from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1486
|
+
let importMatch;
|
|
1487
|
+
while ((importMatch = importPattern.exec(code)) !== null) {
|
|
1488
|
+
for (const spec of importMatch[1].split(",")) {
|
|
1489
|
+
const m = spec.trim().match(/^[A-Za-z_$][\w$]*(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
|
|
1490
|
+
if (m)
|
|
1491
|
+
strippedBindings.push(m[1] || m[0].trim().split(/\s/)[0]);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
const defaultImportPattern = /import\s+([A-Za-z_$][\w$]*)\s+from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1495
|
+
while ((importMatch = defaultImportPattern.exec(code)) !== null) {
|
|
1496
|
+
strippedBindings.push(importMatch[1]);
|
|
1497
|
+
}
|
|
1498
|
+
const nsImportPattern = /import\s+\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1499
|
+
while ((importMatch = nsImportPattern.exec(code)) !== null) {
|
|
1500
|
+
strippedBindings.push(importMatch[1]);
|
|
1501
|
+
}
|
|
1502
|
+
if (strippedBindings.length > 0) {
|
|
1503
|
+
const preservedBindings = allBindings.filter((b) => {
|
|
1504
|
+
const fc = code.slice(b.callExprStart, b.callOpenParenPos + 1);
|
|
1505
|
+
return handleFnNames.some((n) => fc.includes(n)) || lsFnNames.some((n) => fc.includes(n));
|
|
1506
|
+
});
|
|
1507
|
+
const strippedRe = new RegExp(
|
|
1508
|
+
`\\b(?:${strippedBindings.join("|")})\\b`
|
|
1509
|
+
);
|
|
1510
|
+
canStubWholeFile = !preservedBindings.some((b) => {
|
|
1511
|
+
const expr = code.slice(
|
|
1512
|
+
b.callExprStart,
|
|
1513
|
+
b.callCloseParenPos + 1
|
|
1514
|
+
);
|
|
1515
|
+
return strippedRe.test(expr);
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
if (canStubWholeFile) {
|
|
1520
|
+
const lines = [];
|
|
1521
|
+
const neededImports = [];
|
|
1522
|
+
if (handleFnNames.length > 0) neededImports.push("createHandle");
|
|
1523
|
+
if (lsFnNames.length > 0) neededImports.push("createLocationState");
|
|
1524
|
+
if (neededImports.length > 0) {
|
|
1525
|
+
lines.push(
|
|
1526
|
+
`import { ${neededImports.join(", ")} } from "@rangojs/router";`
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
for (const binding of allBindings) {
|
|
1530
|
+
const fnCall = code.slice(
|
|
1531
|
+
binding.callExprStart,
|
|
1532
|
+
binding.callOpenParenPos + 1
|
|
1533
|
+
);
|
|
1534
|
+
const isHandle = handleFnNames.some((n) => fnCall.includes(n));
|
|
1535
|
+
const isLocationState = lsFnNames.some((n) => fnCall.includes(n));
|
|
1536
|
+
const primaryName = binding.exportNames[0];
|
|
1537
|
+
const stubId = makeStubId(filePath, primaryName, isBuild);
|
|
1538
|
+
if (isHandle || isLocationState) {
|
|
1539
|
+
const rawArgs = code.slice(
|
|
1540
|
+
binding.callOpenParenPos + 1,
|
|
1541
|
+
binding.callCloseParenPos
|
|
1542
|
+
).replace(/\b_c\d*\s*=\s*/g, "");
|
|
1543
|
+
const canonicalName = isHandle ? "createHandle" : "createLocationState";
|
|
1544
|
+
const activeFnNames = isHandle ? handleFnNames : lsFnNames;
|
|
1545
|
+
let rawCallee = code.slice(
|
|
1546
|
+
binding.callExprStart,
|
|
1547
|
+
binding.callOpenParenPos
|
|
1548
|
+
);
|
|
1549
|
+
for (const alias of activeFnNames) {
|
|
1550
|
+
if (alias !== canonicalName && rawCallee.startsWith(alias)) {
|
|
1551
|
+
rawCallee = canonicalName + rawCallee.slice(alias.length);
|
|
1552
|
+
break;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
if (isHandle) {
|
|
1556
|
+
const idParam = binding.argCount === 0 ? `undefined, "${stubId}"` : `, "${stubId}"`;
|
|
1557
|
+
lines.push(
|
|
1558
|
+
`export const ${primaryName} = ${rawCallee}(${rawArgs}${idParam});`
|
|
1559
|
+
);
|
|
1560
|
+
lines.push(`${primaryName}.$$id = "${stubId}";`);
|
|
1561
|
+
} else {
|
|
1562
|
+
lines.push(
|
|
1563
|
+
`export const ${primaryName} = ${rawCallee}(${rawArgs});`
|
|
1564
|
+
);
|
|
1565
|
+
lines.push(
|
|
1566
|
+
`${primaryName}.__rsc_ls_key = "__rsc_ls_${stubId}";`
|
|
1567
|
+
);
|
|
1568
|
+
}
|
|
1569
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1570
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1571
|
+
}
|
|
1572
|
+
} else {
|
|
1573
|
+
let brand = "loader";
|
|
1574
|
+
if (prerenderFnNames.some((n) => fnCall.includes(n))) {
|
|
1575
|
+
brand = PRERENDER_CONFIG.brand;
|
|
1576
|
+
} else if (staticFnNames.some((n) => fnCall.includes(n))) {
|
|
1577
|
+
brand = STATIC_CONFIG.brand;
|
|
1578
|
+
}
|
|
1579
|
+
lines.push(
|
|
1580
|
+
`export const ${primaryName} = { __brand: "${brand}", $$id: "${stubId}" };`
|
|
1581
|
+
);
|
|
1582
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1583
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
return { code: lines.join("\n") + "\n", map: null };
|
|
1318
1588
|
}
|
|
1319
1589
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
filePath,
|
|
1329
|
-
isBuild
|
|
1330
|
-
);
|
|
1331
|
-
if (wholeFile) return wholeFile;
|
|
1332
|
-
const exprStubs = generateExprStubs(
|
|
1333
|
-
STATIC_CONFIG,
|
|
1334
|
-
bindings,
|
|
1335
|
-
code,
|
|
1336
|
-
filePath,
|
|
1337
|
-
id,
|
|
1338
|
-
isBuild
|
|
1339
|
-
);
|
|
1340
|
-
if (exprStubs) return exprStubs;
|
|
1341
|
-
}
|
|
1342
|
-
if (hasStaticHandlerCode && isRscEnv && isBuild) {
|
|
1343
|
-
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1344
|
-
const exportNames = getBindings(code, fnNames).map(
|
|
1345
|
-
(b) => b.exportNames[0]
|
|
1346
|
-
);
|
|
1347
|
-
if (exportNames.length > 0) {
|
|
1348
|
-
staticHandlerModules.set(id, exportNames);
|
|
1590
|
+
if (hasStaticHandlerCode && isRscEnv && isBuild) {
|
|
1591
|
+
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1592
|
+
const exportNames = getBindings(code, fnNames).map(
|
|
1593
|
+
(b) => b.exportNames[0]
|
|
1594
|
+
);
|
|
1595
|
+
if (exportNames.length > 0) {
|
|
1596
|
+
staticHandlerModules.set(id, exportNames);
|
|
1597
|
+
}
|
|
1349
1598
|
}
|
|
1599
|
+
const s = new MagicString4(code);
|
|
1600
|
+
if (hasLoaderCode) {
|
|
1601
|
+
const fnNames = getFnNames("createLoader");
|
|
1602
|
+
changed = transformLoaders(
|
|
1603
|
+
getBindings(code, fnNames),
|
|
1604
|
+
s,
|
|
1605
|
+
filePath,
|
|
1606
|
+
isBuild
|
|
1607
|
+
) || changed;
|
|
1608
|
+
}
|
|
1609
|
+
if (hasHandleCode) {
|
|
1610
|
+
const fnNames = getFnNames("createHandle");
|
|
1611
|
+
changed = transformHandles(
|
|
1612
|
+
getBindings(code, fnNames),
|
|
1613
|
+
s,
|
|
1614
|
+
code,
|
|
1615
|
+
filePath,
|
|
1616
|
+
isBuild
|
|
1617
|
+
) || changed;
|
|
1618
|
+
}
|
|
1619
|
+
if (hasLocationStateCode) {
|
|
1620
|
+
const fnNames = getFnNames("createLocationState");
|
|
1621
|
+
changed = transformLocationState(
|
|
1622
|
+
getBindings(code, fnNames),
|
|
1623
|
+
s,
|
|
1624
|
+
filePath,
|
|
1625
|
+
isBuild
|
|
1626
|
+
) || changed;
|
|
1627
|
+
}
|
|
1628
|
+
if (hasPrerenderHandlerCode) {
|
|
1629
|
+
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1630
|
+
const bindings = getBindings(code, fnNames);
|
|
1631
|
+
if (isRscEnv) {
|
|
1632
|
+
changed = transformHandlerIds(
|
|
1633
|
+
PRERENDER_CONFIG,
|
|
1634
|
+
bindings,
|
|
1635
|
+
s,
|
|
1636
|
+
filePath,
|
|
1637
|
+
isBuild
|
|
1638
|
+
) || changed;
|
|
1639
|
+
} else {
|
|
1640
|
+
changed = stubHandlerExprs(
|
|
1641
|
+
PRERENDER_CONFIG,
|
|
1642
|
+
bindings,
|
|
1643
|
+
s,
|
|
1644
|
+
filePath,
|
|
1645
|
+
isBuild
|
|
1646
|
+
) || changed;
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
if (hasStaticHandlerCode) {
|
|
1650
|
+
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1651
|
+
const bindings = getBindings(code, fnNames);
|
|
1652
|
+
if (isRscEnv) {
|
|
1653
|
+
changed = transformHandlerIds(
|
|
1654
|
+
STATIC_CONFIG,
|
|
1655
|
+
bindings,
|
|
1656
|
+
s,
|
|
1657
|
+
filePath,
|
|
1658
|
+
isBuild
|
|
1659
|
+
) || changed;
|
|
1660
|
+
} else {
|
|
1661
|
+
changed = stubHandlerExprs(STATIC_CONFIG, bindings, s, filePath, isBuild) || changed;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
if (!changed) return;
|
|
1665
|
+
return {
|
|
1666
|
+
code: s.toString(),
|
|
1667
|
+
map: s.generateMap({ source: id, includeContent: true })
|
|
1668
|
+
};
|
|
1669
|
+
} finally {
|
|
1670
|
+
counter?.record(id, performance.now() - __t0);
|
|
1350
1671
|
}
|
|
1351
|
-
const s = new MagicString4(code);
|
|
1352
|
-
if (hasLoaderCode) {
|
|
1353
|
-
const fnNames = getFnNames("createLoader");
|
|
1354
|
-
changed = transformLoaders(getBindings(code, fnNames), s, filePath, isBuild) || changed;
|
|
1355
|
-
}
|
|
1356
|
-
if (hasHandleCode) {
|
|
1357
|
-
const fnNames = getFnNames("createHandle");
|
|
1358
|
-
changed = transformHandles(
|
|
1359
|
-
getBindings(code, fnNames),
|
|
1360
|
-
s,
|
|
1361
|
-
code,
|
|
1362
|
-
filePath,
|
|
1363
|
-
isBuild
|
|
1364
|
-
) || changed;
|
|
1365
|
-
}
|
|
1366
|
-
if (hasLocationStateCode) {
|
|
1367
|
-
const fnNames = getFnNames("createLocationState");
|
|
1368
|
-
changed = transformLocationState(
|
|
1369
|
-
getBindings(code, fnNames),
|
|
1370
|
-
s,
|
|
1371
|
-
filePath,
|
|
1372
|
-
isBuild
|
|
1373
|
-
) || changed;
|
|
1374
|
-
}
|
|
1375
|
-
if (hasPrerenderHandlerCode && isRscEnv) {
|
|
1376
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1377
|
-
changed = transformHandlerIds(
|
|
1378
|
-
PRERENDER_CONFIG,
|
|
1379
|
-
getBindings(code, fnNames),
|
|
1380
|
-
s,
|
|
1381
|
-
filePath,
|
|
1382
|
-
isBuild
|
|
1383
|
-
) || changed;
|
|
1384
|
-
}
|
|
1385
|
-
if (hasStaticHandlerCode && isRscEnv) {
|
|
1386
|
-
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1387
|
-
changed = transformHandlerIds(
|
|
1388
|
-
STATIC_CONFIG,
|
|
1389
|
-
getBindings(code, fnNames),
|
|
1390
|
-
s,
|
|
1391
|
-
filePath,
|
|
1392
|
-
isBuild
|
|
1393
|
-
) || changed;
|
|
1394
|
-
}
|
|
1395
|
-
if (!changed) return;
|
|
1396
|
-
return {
|
|
1397
|
-
code: s.toString(),
|
|
1398
|
-
map: s.generateMap({ source: id, includeContent: true })
|
|
1399
|
-
};
|
|
1400
1672
|
}
|
|
1401
1673
|
};
|
|
1402
1674
|
}
|
|
@@ -1404,12 +1676,14 @@ ${lazyImports.join(",\n")}
|
|
|
1404
1676
|
// src/vite/plugins/use-cache-transform.ts
|
|
1405
1677
|
import path5 from "node:path";
|
|
1406
1678
|
import MagicString5 from "magic-string";
|
|
1679
|
+
var debug4 = createRangoDebugger(NS.transform);
|
|
1407
1680
|
var CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
1408
1681
|
var LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
1409
1682
|
function useCacheTransform() {
|
|
1410
1683
|
let projectRoot = "";
|
|
1411
1684
|
let isBuild = false;
|
|
1412
1685
|
let rscTransforms = null;
|
|
1686
|
+
const counter = createCounter(debug4, "use-cache");
|
|
1413
1687
|
return {
|
|
1414
1688
|
name: "@rangojs/router:use-cache",
|
|
1415
1689
|
enforce: "post",
|
|
@@ -1417,53 +1691,61 @@ function useCacheTransform() {
|
|
|
1417
1691
|
projectRoot = config.root;
|
|
1418
1692
|
isBuild = config.command === "build";
|
|
1419
1693
|
},
|
|
1694
|
+
buildEnd() {
|
|
1695
|
+
counter?.flush();
|
|
1696
|
+
},
|
|
1420
1697
|
async transform(code, id) {
|
|
1421
1698
|
if (this.environment?.name !== "rsc") return;
|
|
1422
1699
|
if (!code.includes("use cache")) return;
|
|
1423
1700
|
if (id.includes("/node_modules/") || id.startsWith("\0")) return;
|
|
1424
1701
|
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return;
|
|
1425
|
-
|
|
1702
|
+
const start = counter ? performance.now() : 0;
|
|
1703
|
+
try {
|
|
1704
|
+
if (!rscTransforms) {
|
|
1705
|
+
try {
|
|
1706
|
+
rscTransforms = await import("@vitejs/plugin-rsc/transforms");
|
|
1707
|
+
} catch {
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
const {
|
|
1712
|
+
hasDirective,
|
|
1713
|
+
transformWrapExport,
|
|
1714
|
+
transformHoistInlineDirective
|
|
1715
|
+
} = rscTransforms;
|
|
1716
|
+
let ast;
|
|
1426
1717
|
try {
|
|
1427
|
-
|
|
1718
|
+
const { parseAst: parseAst4 } = await import("vite");
|
|
1719
|
+
ast = parseAst4(code);
|
|
1428
1720
|
} catch {
|
|
1429
1721
|
return;
|
|
1430
1722
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
hasDirective,
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
1446
|
-
if (hasDirective(ast.body, "use cache")) {
|
|
1447
|
-
return transformFileLevelUseCache(
|
|
1723
|
+
const filePath = normalizePath(path5.relative(projectRoot, id));
|
|
1724
|
+
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
1725
|
+
if (hasDirective(ast.body, "use cache")) {
|
|
1726
|
+
return transformFileLevelUseCache(
|
|
1727
|
+
code,
|
|
1728
|
+
ast,
|
|
1729
|
+
filePath,
|
|
1730
|
+
id,
|
|
1731
|
+
isBuild,
|
|
1732
|
+
isLayoutOrTemplate,
|
|
1733
|
+
transformWrapExport
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
const functionResult = transformFunctionLevelUseCache(
|
|
1448
1737
|
code,
|
|
1449
1738
|
ast,
|
|
1450
1739
|
filePath,
|
|
1451
1740
|
id,
|
|
1452
1741
|
isBuild,
|
|
1453
|
-
|
|
1454
|
-
transformWrapExport
|
|
1742
|
+
transformHoistInlineDirective
|
|
1455
1743
|
);
|
|
1744
|
+
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1745
|
+
if (functionResult) return functionResult;
|
|
1746
|
+
} finally {
|
|
1747
|
+
counter?.record(id, performance.now() - start);
|
|
1456
1748
|
}
|
|
1457
|
-
const functionResult = transformFunctionLevelUseCache(
|
|
1458
|
-
code,
|
|
1459
|
-
ast,
|
|
1460
|
-
filePath,
|
|
1461
|
-
id,
|
|
1462
|
-
isBuild,
|
|
1463
|
-
transformHoistInlineDirective
|
|
1464
|
-
);
|
|
1465
|
-
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1466
|
-
if (functionResult) return functionResult;
|
|
1467
1749
|
}
|
|
1468
1750
|
};
|
|
1469
1751
|
}
|
|
@@ -1586,6 +1868,7 @@ function warnOnNearMissDirectives(ast, fileId, warn) {
|
|
|
1586
1868
|
}
|
|
1587
1869
|
|
|
1588
1870
|
// src/vite/plugins/client-ref-dedup.ts
|
|
1871
|
+
var debug5 = createRangoDebugger(NS.transform);
|
|
1589
1872
|
var CLIENT_IN_SERVER_PROXY_PREFIX = "virtual:vite-rsc/client-in-server-package-proxy/";
|
|
1590
1873
|
function extractPackageName(absolutePath) {
|
|
1591
1874
|
const marker = "/node_modules/";
|
|
@@ -1602,6 +1885,7 @@ function extractPackageName(absolutePath) {
|
|
|
1602
1885
|
}
|
|
1603
1886
|
function clientRefDedup() {
|
|
1604
1887
|
let clientExclude = [];
|
|
1888
|
+
const dedupedPackages = /* @__PURE__ */ new Set();
|
|
1605
1889
|
return {
|
|
1606
1890
|
name: "@rangojs/router:client-ref-dedup",
|
|
1607
1891
|
enforce: "pre",
|
|
@@ -1610,6 +1894,15 @@ function clientRefDedup() {
|
|
|
1610
1894
|
const clientEnv = config.environments?.["client"];
|
|
1611
1895
|
clientExclude = clientEnv?.optimizeDeps?.exclude ?? config.optimizeDeps?.exclude ?? [];
|
|
1612
1896
|
},
|
|
1897
|
+
buildEnd() {
|
|
1898
|
+
if (debug5 && dedupedPackages.size > 0) {
|
|
1899
|
+
debug5(
|
|
1900
|
+
"client-ref-dedup: redirected %d package(s) (%s)",
|
|
1901
|
+
dedupedPackages.size,
|
|
1902
|
+
[...dedupedPackages].join(",")
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1905
|
+
},
|
|
1613
1906
|
resolveId(source, importer, options) {
|
|
1614
1907
|
if (this.environment?.name !== "client") return;
|
|
1615
1908
|
if (!importer?.includes(CLIENT_IN_SERVER_PROXY_PREFIX)) return;
|
|
@@ -1618,6 +1911,7 @@ function clientRefDedup() {
|
|
|
1618
1911
|
const packageName = extractPackageName(source);
|
|
1619
1912
|
if (!packageName) return;
|
|
1620
1913
|
if (clientExclude.includes(packageName)) return;
|
|
1914
|
+
if (debug5) dedupedPackages.add(packageName);
|
|
1621
1915
|
return `\0rango:dedup/${packageName}`;
|
|
1622
1916
|
},
|
|
1623
1917
|
load(id) {
|
|
@@ -1740,12 +2034,13 @@ function getVirtualVersionContent(version) {
|
|
|
1740
2034
|
|
|
1741
2035
|
// src/vite/utils/package-resolution.ts
|
|
1742
2036
|
import { existsSync } from "node:fs";
|
|
2037
|
+
import { createRequire } from "node:module";
|
|
1743
2038
|
import { resolve } from "node:path";
|
|
1744
2039
|
|
|
1745
2040
|
// package.json
|
|
1746
2041
|
var package_default = {
|
|
1747
2042
|
name: "@rangojs/router",
|
|
1748
|
-
version: "0.0.0-experimental.
|
|
2043
|
+
version: "0.0.0-experimental.89",
|
|
1749
2044
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1750
2045
|
keywords: [
|
|
1751
2046
|
"react",
|
|
@@ -1878,22 +2173,24 @@ var package_default = {
|
|
|
1878
2173
|
tag: "experimental"
|
|
1879
2174
|
},
|
|
1880
2175
|
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",
|
|
2176
|
+
build: "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
1882
2177
|
prepublishOnly: "pnpm build",
|
|
1883
|
-
typecheck: "tsc --noEmit",
|
|
2178
|
+
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit",
|
|
1884
2179
|
test: "playwright test",
|
|
1885
2180
|
"test:ui": "playwright test --ui",
|
|
1886
2181
|
"test:unit": "vitest run",
|
|
1887
2182
|
"test:unit:watch": "vitest"
|
|
1888
2183
|
},
|
|
1889
2184
|
dependencies: {
|
|
1890
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2185
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
2186
|
+
debug: "^4.4.1",
|
|
1891
2187
|
"magic-string": "^0.30.17",
|
|
1892
2188
|
picomatch: "^4.0.3",
|
|
1893
2189
|
"rsc-html-stream": "^0.0.7"
|
|
1894
2190
|
},
|
|
1895
2191
|
devDependencies: {
|
|
1896
2192
|
"@playwright/test": "^1.49.1",
|
|
2193
|
+
"@types/debug": "^4.1.12",
|
|
1897
2194
|
"@types/node": "^24.10.1",
|
|
1898
2195
|
"@types/react": "catalog:",
|
|
1899
2196
|
"@types/react-dom": "catalog:",
|
|
@@ -1907,7 +2204,7 @@ var package_default = {
|
|
|
1907
2204
|
},
|
|
1908
2205
|
peerDependencies: {
|
|
1909
2206
|
"@cloudflare/vite-plugin": "^1.25.0",
|
|
1910
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2207
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
1911
2208
|
react: "^18.0.0 || ^19.0.0",
|
|
1912
2209
|
vite: "^7.3.0"
|
|
1913
2210
|
},
|
|
@@ -1922,6 +2219,7 @@ var package_default = {
|
|
|
1922
2219
|
};
|
|
1923
2220
|
|
|
1924
2221
|
// src/vite/utils/package-resolution.ts
|
|
2222
|
+
var require2 = createRequire(import.meta.url);
|
|
1925
2223
|
var VIRTUAL_PACKAGE_NAME = "@rangojs/router";
|
|
1926
2224
|
function getPublishedPackageName() {
|
|
1927
2225
|
return package_default.name;
|
|
@@ -1962,6 +2260,20 @@ function getPackageAliases() {
|
|
|
1962
2260
|
}
|
|
1963
2261
|
return aliases;
|
|
1964
2262
|
}
|
|
2263
|
+
function getVendorAliases() {
|
|
2264
|
+
const specs = [
|
|
2265
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
2266
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
2267
|
+
];
|
|
2268
|
+
const aliases = {};
|
|
2269
|
+
for (const spec of specs) {
|
|
2270
|
+
try {
|
|
2271
|
+
aliases[spec] = require2.resolve(spec);
|
|
2272
|
+
} catch {
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
return aliases;
|
|
2276
|
+
}
|
|
1965
2277
|
|
|
1966
2278
|
// src/build/route-types/param-extraction.ts
|
|
1967
2279
|
function extractParamsFromPattern(pattern) {
|
|
@@ -2095,31 +2407,7 @@ declare global {
|
|
|
2095
2407
|
}
|
|
2096
2408
|
|
|
2097
2409
|
// src/build/route-types/scan-filter.ts
|
|
2098
|
-
import { join, relative } from "node:path";
|
|
2099
2410
|
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
2411
|
|
|
2124
2412
|
// src/build/route-types/per-module-writer.ts
|
|
2125
2413
|
import ts4 from "typescript";
|
|
@@ -2341,7 +2629,7 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
|
|
|
2341
2629
|
}
|
|
2342
2630
|
return routeMap;
|
|
2343
2631
|
}
|
|
2344
|
-
function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut) {
|
|
2632
|
+
function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut, inlineBlock) {
|
|
2345
2633
|
visited = visited ?? /* @__PURE__ */ new Set();
|
|
2346
2634
|
const realPath = resolve2(filePath);
|
|
2347
2635
|
const key = variableName ? `${realPath}:${variableName}` : realPath;
|
|
@@ -2357,7 +2645,9 @@ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagno
|
|
|
2357
2645
|
return { routes: {}, searchSchemas: {} };
|
|
2358
2646
|
}
|
|
2359
2647
|
let block;
|
|
2360
|
-
if (
|
|
2648
|
+
if (inlineBlock) {
|
|
2649
|
+
block = inlineBlock;
|
|
2650
|
+
} else if (variableName) {
|
|
2361
2651
|
const extracted = extractUrlsBlockForVariable(source, variableName);
|
|
2362
2652
|
if (!extracted) return { routes: {}, searchSchemas: {} };
|
|
2363
2653
|
block = extracted;
|
|
@@ -2386,7 +2676,7 @@ import {
|
|
|
2386
2676
|
readdirSync
|
|
2387
2677
|
} from "node:fs";
|
|
2388
2678
|
import {
|
|
2389
|
-
join
|
|
2679
|
+
join,
|
|
2390
2680
|
dirname as dirname2,
|
|
2391
2681
|
resolve as resolve3,
|
|
2392
2682
|
sep,
|
|
@@ -2406,7 +2696,7 @@ function countPublicRouteEntries(source) {
|
|
|
2406
2696
|
}
|
|
2407
2697
|
var ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
|
|
2408
2698
|
function isRoutableSourceFile(name) {
|
|
2409
|
-
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.");
|
|
2699
|
+
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
2410
2700
|
}
|
|
2411
2701
|
function findRouterFilesRecursive(dir, filter, results) {
|
|
2412
2702
|
let entries;
|
|
@@ -2421,9 +2711,10 @@ function findRouterFilesRecursive(dir, filter, results) {
|
|
|
2421
2711
|
const childDirs = [];
|
|
2422
2712
|
const routerFilesInDir = [];
|
|
2423
2713
|
for (const entry of entries) {
|
|
2424
|
-
const fullPath =
|
|
2714
|
+
const fullPath = join(dir, entry.name);
|
|
2425
2715
|
if (entry.isDirectory()) {
|
|
2426
|
-
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
2716
|
+
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "coverage" || entry.name === "__tests__" || entry.name === "__mocks__" || entry.name.startsWith("."))
|
|
2717
|
+
continue;
|
|
2427
2718
|
childDirs.push(fullPath);
|
|
2428
2719
|
continue;
|
|
2429
2720
|
}
|
|
@@ -2475,7 +2766,7 @@ Router root: ${conflict.ancestor}
|
|
|
2475
2766
|
Nested router: ${conflict.nested}
|
|
2476
2767
|
Move the nested router into a sibling directory or configure it as a separate app root.`;
|
|
2477
2768
|
}
|
|
2478
|
-
function
|
|
2769
|
+
function extractUrlsFromRouter(code) {
|
|
2479
2770
|
const sourceFile = ts5.createSourceFile(
|
|
2480
2771
|
"router.tsx",
|
|
2481
2772
|
code,
|
|
@@ -2489,24 +2780,70 @@ function extractUrlsVariableFromRouter(code) {
|
|
|
2489
2780
|
const callee = node.expression;
|
|
2490
2781
|
return ts5.isIdentifier(callee) && callee.text === "createRouter";
|
|
2491
2782
|
}
|
|
2783
|
+
function isInlineBuilder(node) {
|
|
2784
|
+
return ts5.isArrowFunction(node) || ts5.isFunctionExpression(node);
|
|
2785
|
+
}
|
|
2786
|
+
function isRoutesOnCreateRouter(node) {
|
|
2787
|
+
if (!ts5.isPropertyAccessExpression(node.expression) || node.expression.name.text !== "routes")
|
|
2788
|
+
return false;
|
|
2789
|
+
let inner = node.expression.expression;
|
|
2790
|
+
while (ts5.isCallExpression(inner) && ts5.isPropertyAccessExpression(inner.expression)) {
|
|
2791
|
+
inner = inner.expression.expression;
|
|
2792
|
+
}
|
|
2793
|
+
return isCreateRouterCall(inner);
|
|
2794
|
+
}
|
|
2492
2795
|
function visit(node) {
|
|
2493
2796
|
if (result) return;
|
|
2494
|
-
if (ts5.isCallExpression(node) &&
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
}
|
|
2499
|
-
|
|
2500
|
-
result = node.arguments[0].text;
|
|
2501
|
-
return;
|
|
2797
|
+
if (ts5.isCallExpression(node) && node.arguments.length >= 1 && isRoutesOnCreateRouter(node)) {
|
|
2798
|
+
const arg = node.arguments[0];
|
|
2799
|
+
if (ts5.isIdentifier(arg)) {
|
|
2800
|
+
result = { kind: "variable", name: arg.text };
|
|
2801
|
+
} else if (isInlineBuilder(arg)) {
|
|
2802
|
+
result = { kind: "inline", block: arg.getText(sourceFile) };
|
|
2502
2803
|
}
|
|
2804
|
+
return;
|
|
2503
2805
|
}
|
|
2504
2806
|
if (isCreateRouterCall(node)) {
|
|
2505
2807
|
const callExpr = node;
|
|
2506
|
-
for (const
|
|
2808
|
+
for (const callArg of callExpr.arguments) {
|
|
2809
|
+
if (ts5.isObjectLiteralExpression(callArg)) {
|
|
2810
|
+
for (const prop of callArg.properties) {
|
|
2811
|
+
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "urls") {
|
|
2812
|
+
if (ts5.isIdentifier(prop.initializer)) {
|
|
2813
|
+
result = { kind: "variable", name: prop.initializer.text };
|
|
2814
|
+
} else if (isInlineBuilder(prop.initializer)) {
|
|
2815
|
+
result = {
|
|
2816
|
+
kind: "inline",
|
|
2817
|
+
block: prop.initializer.getText(sourceFile)
|
|
2818
|
+
};
|
|
2819
|
+
}
|
|
2820
|
+
return;
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
ts5.forEachChild(node, visit);
|
|
2827
|
+
}
|
|
2828
|
+
visit(sourceFile);
|
|
2829
|
+
return result;
|
|
2830
|
+
}
|
|
2831
|
+
function extractBasenameFromRouter(code) {
|
|
2832
|
+
const sourceFile = ts5.createSourceFile(
|
|
2833
|
+
"router.tsx",
|
|
2834
|
+
code,
|
|
2835
|
+
ts5.ScriptTarget.Latest,
|
|
2836
|
+
true,
|
|
2837
|
+
ts5.ScriptKind.TSX
|
|
2838
|
+
);
|
|
2839
|
+
let result;
|
|
2840
|
+
function visit(node) {
|
|
2841
|
+
if (result !== void 0) return;
|
|
2842
|
+
if (ts5.isCallExpression(node) && ts5.isIdentifier(node.expression) && node.expression.text === "createRouter") {
|
|
2843
|
+
for (const arg of node.arguments) {
|
|
2507
2844
|
if (ts5.isObjectLiteralExpression(arg)) {
|
|
2508
2845
|
for (const prop of arg.properties) {
|
|
2509
|
-
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "
|
|
2846
|
+
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "basename" && ts5.isStringLiteral(prop.initializer)) {
|
|
2510
2847
|
result = prop.initializer.text;
|
|
2511
2848
|
return;
|
|
2512
2849
|
}
|
|
@@ -2519,6 +2856,19 @@ function extractUrlsVariableFromRouter(code) {
|
|
|
2519
2856
|
visit(sourceFile);
|
|
2520
2857
|
return result;
|
|
2521
2858
|
}
|
|
2859
|
+
function applyBasenameToRoutes(result, basename3) {
|
|
2860
|
+
const prefixed = {};
|
|
2861
|
+
for (const [name, pattern] of Object.entries(result.routes)) {
|
|
2862
|
+
if (pattern === "/") {
|
|
2863
|
+
prefixed[name] = basename3;
|
|
2864
|
+
} else if (basename3.endsWith("/") && pattern.startsWith("/")) {
|
|
2865
|
+
prefixed[name] = basename3 + pattern.slice(1);
|
|
2866
|
+
} else {
|
|
2867
|
+
prefixed[name] = basename3 + pattern;
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
return { routes: prefixed, searchSchemas: result.searchSchemas };
|
|
2871
|
+
}
|
|
2522
2872
|
function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
2523
2873
|
let routerSource;
|
|
2524
2874
|
try {
|
|
@@ -2526,19 +2876,40 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
|
2526
2876
|
} catch {
|
|
2527
2877
|
return { routes: {}, searchSchemas: {} };
|
|
2528
2878
|
}
|
|
2529
|
-
const
|
|
2530
|
-
if (!
|
|
2879
|
+
const extraction = extractUrlsFromRouter(routerSource);
|
|
2880
|
+
if (!extraction) {
|
|
2531
2881
|
return { routes: {}, searchSchemas: {} };
|
|
2532
2882
|
}
|
|
2533
|
-
const
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2883
|
+
const rawBasename = extractBasenameFromRouter(routerSource);
|
|
2884
|
+
const basename3 = rawBasename ? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "") : void 0;
|
|
2885
|
+
let result;
|
|
2886
|
+
if (extraction.kind === "inline") {
|
|
2887
|
+
result = buildCombinedRouteMapWithSearch(
|
|
2888
|
+
routerFilePath,
|
|
2889
|
+
void 0,
|
|
2890
|
+
void 0,
|
|
2891
|
+
void 0,
|
|
2892
|
+
extraction.block
|
|
2893
|
+
);
|
|
2894
|
+
} else {
|
|
2895
|
+
const imported = resolveImportedVariable(routerSource, extraction.name);
|
|
2896
|
+
if (imported) {
|
|
2897
|
+
const targetFile = resolveImportPath(imported.specifier, routerFilePath);
|
|
2898
|
+
if (!targetFile) {
|
|
2899
|
+
return { routes: {}, searchSchemas: {} };
|
|
2900
|
+
}
|
|
2901
|
+
result = buildCombinedRouteMapWithSearch(
|
|
2902
|
+
targetFile,
|
|
2903
|
+
imported.exportedName
|
|
2904
|
+
);
|
|
2905
|
+
} else {
|
|
2906
|
+
result = buildCombinedRouteMapWithSearch(routerFilePath, extraction.name);
|
|
2538
2907
|
}
|
|
2539
|
-
return buildCombinedRouteMapWithSearch(targetFile, imported.exportedName);
|
|
2540
2908
|
}
|
|
2541
|
-
|
|
2909
|
+
if (basename3) {
|
|
2910
|
+
result = applyBasenameToRoutes(result, basename3);
|
|
2911
|
+
}
|
|
2912
|
+
return result;
|
|
2542
2913
|
}
|
|
2543
2914
|
function findRouterFiles(root, filter) {
|
|
2544
2915
|
const result = [];
|
|
@@ -2547,7 +2918,7 @@ function findRouterFiles(root, filter) {
|
|
|
2547
2918
|
}
|
|
2548
2919
|
function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
2549
2920
|
try {
|
|
2550
|
-
const oldCombinedPath =
|
|
2921
|
+
const oldCombinedPath = join(root, "src", "named-routes.gen.ts");
|
|
2551
2922
|
if (existsSync3(oldCombinedPath)) {
|
|
2552
2923
|
unlinkSync(oldCombinedPath);
|
|
2553
2924
|
console.log(
|
|
@@ -2563,31 +2934,21 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
2563
2934
|
throw new Error(formatNestedRouterConflictError(nestedRouterConflict));
|
|
2564
2935
|
}
|
|
2565
2936
|
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);
|
|
2937
|
+
const result = buildCombinedRouteMapForRouterFile(routerFilePath);
|
|
2938
|
+
if (Object.keys(result.routes).length === 0 && Object.keys(result.searchSchemas).length === 0) {
|
|
2939
|
+
let routerSource;
|
|
2940
|
+
try {
|
|
2941
|
+
routerSource = readFileSync2(routerFilePath, "utf-8");
|
|
2942
|
+
} catch {
|
|
2943
|
+
continue;
|
|
2944
|
+
}
|
|
2945
|
+
if (!extractUrlsFromRouter(routerSource)) continue;
|
|
2585
2946
|
}
|
|
2586
2947
|
const routerBasename = pathBasename(routerFilePath).replace(
|
|
2587
2948
|
/\.(tsx?|jsx?)$/,
|
|
2588
2949
|
""
|
|
2589
2950
|
);
|
|
2590
|
-
const outPath =
|
|
2951
|
+
const outPath = join(
|
|
2591
2952
|
dirname2(routerFilePath),
|
|
2592
2953
|
`${routerBasename}.named-routes.gen.ts`
|
|
2593
2954
|
);
|
|
@@ -2717,8 +3078,9 @@ function createVersionPlugin() {
|
|
|
2717
3078
|
let isDev = false;
|
|
2718
3079
|
let server = null;
|
|
2719
3080
|
const clientModuleSignatures = /* @__PURE__ */ new Map();
|
|
3081
|
+
let versionCounter = 0;
|
|
2720
3082
|
const bumpVersion = (reason) => {
|
|
2721
|
-
currentVersion = Date.now().toString(16);
|
|
3083
|
+
currentVersion = Date.now().toString(16) + String(++versionCounter);
|
|
2722
3084
|
console.log(`[rsc-router] ${reason}, version updated: ${currentVersion}`);
|
|
2723
3085
|
const rscEnv = server?.environments?.rsc;
|
|
2724
3086
|
const versionMod = rscEnv?.moduleGraph?.getModuleById(
|
|
@@ -2774,6 +3136,9 @@ function createVersionPlugin() {
|
|
|
2774
3136
|
if (!isDev) return;
|
|
2775
3137
|
const isRscModule = this.environment?.name === "rsc";
|
|
2776
3138
|
if (!isRscModule) return;
|
|
3139
|
+
if (ctx.modules.length === 1 && ctx.modules[0].id === "\0" + VIRTUAL_IDS.version) {
|
|
3140
|
+
return;
|
|
3141
|
+
}
|
|
2777
3142
|
if (isCodeModule(ctx.file)) {
|
|
2778
3143
|
const filePath = normalizeModuleId(ctx.file);
|
|
2779
3144
|
const previousSignature = clientModuleSignatures.get(filePath);
|
|
@@ -2803,6 +3168,73 @@ function createVersionPlugin() {
|
|
|
2803
3168
|
|
|
2804
3169
|
// src/vite/utils/shared-utils.ts
|
|
2805
3170
|
import * as Vite from "vite";
|
|
3171
|
+
|
|
3172
|
+
// src/vite/plugins/performance-tracks.ts
|
|
3173
|
+
import { readFile } from "node:fs/promises";
|
|
3174
|
+
var debug6 = createRangoDebugger(NS.transform);
|
|
3175
|
+
var RSDW_PATCH_RE = /((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
3176
|
+
function buildPatchReplacement(match, debugInfoVar) {
|
|
3177
|
+
return `${match}
|
|
3178
|
+
if (${debugInfoVar} && 0 === ${debugInfoVar}.length && "fulfilled" === root.status) {
|
|
3179
|
+
var _resolved = "function" === typeof resolveLazy ? resolveLazy(root.value) : root.value;
|
|
3180
|
+
if ("object" === typeof _resolved && null !== _resolved && isArrayImpl(_resolved._debugInfo)) {
|
|
3181
|
+
${debugInfoVar} = _resolved._debugInfo;
|
|
3182
|
+
}
|
|
3183
|
+
}`;
|
|
3184
|
+
}
|
|
3185
|
+
function patchRsdwClientDebugInfoRecovery(code) {
|
|
3186
|
+
const match = code.match(RSDW_PATCH_RE);
|
|
3187
|
+
if (!match) {
|
|
3188
|
+
return { code, debugInfoVar: null };
|
|
3189
|
+
}
|
|
3190
|
+
return {
|
|
3191
|
+
code: code.replace(match[1], buildPatchReplacement(match[1], match[2])),
|
|
3192
|
+
debugInfoVar: match[2]
|
|
3193
|
+
};
|
|
3194
|
+
}
|
|
3195
|
+
function performanceTracksOptimizeDepsPlugin() {
|
|
3196
|
+
return {
|
|
3197
|
+
name: "@rangojs/router:performance-tracks-optimize-deps",
|
|
3198
|
+
setup(build) {
|
|
3199
|
+
build.onLoad(
|
|
3200
|
+
{
|
|
3201
|
+
filter: /react-server-dom-webpack-client\.browser\.(development|production)\.js$/
|
|
3202
|
+
},
|
|
3203
|
+
async (args) => {
|
|
3204
|
+
const code = await readFile(args.path, "utf8");
|
|
3205
|
+
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
3206
|
+
return {
|
|
3207
|
+
contents: patched.code,
|
|
3208
|
+
loader: "js"
|
|
3209
|
+
};
|
|
3210
|
+
}
|
|
3211
|
+
);
|
|
3212
|
+
}
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3215
|
+
function performanceTracksPlugin() {
|
|
3216
|
+
const counter = createCounter(debug6, "performance-tracks");
|
|
3217
|
+
return {
|
|
3218
|
+
name: "@rangojs/router:performance-tracks",
|
|
3219
|
+
buildEnd() {
|
|
3220
|
+
counter?.flush();
|
|
3221
|
+
},
|
|
3222
|
+
transform(code, id) {
|
|
3223
|
+
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
3224
|
+
const start = counter ? performance.now() : 0;
|
|
3225
|
+
try {
|
|
3226
|
+
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
3227
|
+
if (!patched.debugInfoVar) return;
|
|
3228
|
+
debug6?.("patched RSDW client (var: %s)", patched.debugInfoVar);
|
|
3229
|
+
return patched.code;
|
|
3230
|
+
} finally {
|
|
3231
|
+
counter?.record(id, performance.now() - start);
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
};
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
// src/vite/utils/shared-utils.ts
|
|
2806
3238
|
var versionEsbuildPlugin = {
|
|
2807
3239
|
name: "@rangojs/router-version",
|
|
2808
3240
|
setup(build) {
|
|
@@ -2820,7 +3252,7 @@ var versionEsbuildPlugin = {
|
|
|
2820
3252
|
}
|
|
2821
3253
|
};
|
|
2822
3254
|
var sharedEsbuildOptions = {
|
|
2823
|
-
plugins: [versionEsbuildPlugin]
|
|
3255
|
+
plugins: [versionEsbuildPlugin, performanceTracksOptimizeDepsPlugin()]
|
|
2824
3256
|
};
|
|
2825
3257
|
function createVirtualEntriesPlugin(entries, routerPathRef) {
|
|
2826
3258
|
const virtualModules = {};
|
|
@@ -2903,11 +3335,11 @@ ${dim} \u2571${reset} ${bold}\u2554\u2550\u2557${reset}${dim} * \u2
|
|
|
2903
3335
|
${dim} ${reset}${bold}\u2551 \u2551${reset} ${bold}\u2554\u2550\u2557${reset}${dim} * \u2727. \u2571${reset}
|
|
2904
3336
|
${dim} ${reset}${bold}\u2554\u2557 \u2551 \u2551 \u2551 \u2551${reset}${dim} * \u2571${reset}
|
|
2905
3337
|
${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}
|
|
3338
|
+
${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
3339
|
${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
3340
|
${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\
|
|
3341
|
+
${dim} * ${reset}${bold}\u2551 \u2551${reset}${dim} * \u2727. \u2571${reset}
|
|
3342
|
+
${dim} ${reset}${bold}\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550${reset}${dim} \u2726 *${reset}
|
|
2911
3343
|
|
|
2912
3344
|
v${version} \xB7 ${preset} \xB7 ${mode}
|
|
2913
3345
|
`;
|
|
@@ -2968,6 +3400,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
2968
3400
|
}
|
|
2969
3401
|
|
|
2970
3402
|
// src/vite/plugins/cjs-to-esm.ts
|
|
3403
|
+
var debug7 = createRangoDebugger(NS.transform);
|
|
2971
3404
|
function createCjsToEsmPlugin() {
|
|
2972
3405
|
return {
|
|
2973
3406
|
name: "@rangojs/router:cjs-to-esm",
|
|
@@ -2977,6 +3410,7 @@ function createCjsToEsmPlugin() {
|
|
|
2977
3410
|
if (cleanId.includes("vendor/react-server-dom/client.browser.js") || cleanId.includes("vendor\\react-server-dom\\client.browser.js")) {
|
|
2978
3411
|
const isProd = process.env.NODE_ENV === "production";
|
|
2979
3412
|
const cjsFile = isProd ? "./cjs/react-server-dom-webpack-client.browser.production.js" : "./cjs/react-server-dom-webpack-client.browser.development.js";
|
|
3413
|
+
debug7?.("cjs-to-esm entry redirect %s", id);
|
|
2980
3414
|
return {
|
|
2981
3415
|
code: `export * from "${cjsFile}";`,
|
|
2982
3416
|
map: null
|
|
@@ -3012,6 +3446,7 @@ function createCjsToEsmPlugin() {
|
|
|
3012
3446
|
"export const $1 ="
|
|
3013
3447
|
);
|
|
3014
3448
|
transformed = license + "\n" + transformed;
|
|
3449
|
+
debug7?.("cjs-to-esm body rewrite %s", id);
|
|
3015
3450
|
return {
|
|
3016
3451
|
code: transformed,
|
|
3017
3452
|
map: null
|
|
@@ -3026,6 +3461,8 @@ function createCjsToEsmPlugin() {
|
|
|
3026
3461
|
import { createServer as createViteServer } from "vite";
|
|
3027
3462
|
import { resolve as resolve8 } from "node:path";
|
|
3028
3463
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
3464
|
+
import { createRequire as createRequire2, register } from "node:module";
|
|
3465
|
+
import { pathToFileURL } from "node:url";
|
|
3029
3466
|
|
|
3030
3467
|
// src/vite/plugins/virtual-stub-plugin.ts
|
|
3031
3468
|
function createVirtualStubPlugin() {
|
|
@@ -3051,9 +3488,117 @@ function createVirtualStubPlugin() {
|
|
|
3051
3488
|
};
|
|
3052
3489
|
}
|
|
3053
3490
|
|
|
3491
|
+
// src/vite/plugins/cloudflare-protocol-stub.ts
|
|
3492
|
+
var VIRTUAL_PREFIX = "virtual:rango-cloudflare-stub-";
|
|
3493
|
+
var NULL_PREFIX = "\0" + VIRTUAL_PREFIX;
|
|
3494
|
+
var CF_PREFIX = "cloudflare:";
|
|
3495
|
+
var BUILD_ENV_GLOBAL_KEY = "__rango_build_env__";
|
|
3496
|
+
var SOURCE_EXT_RE = /\.[mc]?[jt]sx?$/;
|
|
3497
|
+
var IMPORT_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
3498
|
+
"ImportDeclaration",
|
|
3499
|
+
"ImportExpression",
|
|
3500
|
+
"ExportNamedDeclaration",
|
|
3501
|
+
"ExportAllDeclaration"
|
|
3502
|
+
]);
|
|
3503
|
+
var STUBS = {
|
|
3504
|
+
"cloudflare:workers": `
|
|
3505
|
+
export class DurableObject { constructor(_ctx, _env) {} }
|
|
3506
|
+
export class WorkerEntrypoint { constructor(_ctx, _env) {} }
|
|
3507
|
+
export class WorkflowEntrypoint { constructor(_ctx, _env) {} }
|
|
3508
|
+
export class RpcTarget {}
|
|
3509
|
+
export const env = globalThis[${JSON.stringify(BUILD_ENV_GLOBAL_KEY)}] ?? {};
|
|
3510
|
+
export default {};
|
|
3511
|
+
`,
|
|
3512
|
+
"cloudflare:email": `
|
|
3513
|
+
export class EmailMessage { constructor(_from, _to, _raw) {} }
|
|
3514
|
+
export default {};
|
|
3515
|
+
`,
|
|
3516
|
+
"cloudflare:sockets": `
|
|
3517
|
+
export function connect() { return {}; }
|
|
3518
|
+
export default {};
|
|
3519
|
+
`,
|
|
3520
|
+
"cloudflare:workflows": `
|
|
3521
|
+
export class NonRetryableError extends Error {
|
|
3522
|
+
constructor(message, name) { super(message); this.name = name ?? "NonRetryableError"; }
|
|
3523
|
+
}
|
|
3524
|
+
export default {};
|
|
3525
|
+
`
|
|
3526
|
+
};
|
|
3527
|
+
var FALLBACK_STUB = `export default {};
|
|
3528
|
+
`;
|
|
3529
|
+
function createCloudflareProtocolStubPlugin() {
|
|
3530
|
+
return {
|
|
3531
|
+
name: "@rangojs/router:cloudflare-protocol-stub",
|
|
3532
|
+
transform(code, id) {
|
|
3533
|
+
const cleanId = id.split("?")[0] ?? id;
|
|
3534
|
+
if (!SOURCE_EXT_RE.test(cleanId)) return null;
|
|
3535
|
+
if (!code.includes(CF_PREFIX)) return null;
|
|
3536
|
+
let ast;
|
|
3537
|
+
try {
|
|
3538
|
+
ast = this.parse(code);
|
|
3539
|
+
} catch {
|
|
3540
|
+
return null;
|
|
3541
|
+
}
|
|
3542
|
+
const hits = [];
|
|
3543
|
+
walk(ast, (node) => {
|
|
3544
|
+
if (!IMPORT_NODE_TYPES.has(node.type)) return;
|
|
3545
|
+
const source = node.source;
|
|
3546
|
+
if (!source || source.type !== "Literal") return;
|
|
3547
|
+
if (typeof source.value !== "string") return;
|
|
3548
|
+
if (!source.value.startsWith(CF_PREFIX)) return;
|
|
3549
|
+
if (typeof source.start !== "number" || typeof source.end !== "number")
|
|
3550
|
+
return;
|
|
3551
|
+
hits.push({
|
|
3552
|
+
start: source.start,
|
|
3553
|
+
end: source.end,
|
|
3554
|
+
value: source.value
|
|
3555
|
+
});
|
|
3556
|
+
});
|
|
3557
|
+
if (hits.length === 0) return null;
|
|
3558
|
+
hits.sort((a, b) => b.start - a.start);
|
|
3559
|
+
let out = code;
|
|
3560
|
+
for (const hit of hits) {
|
|
3561
|
+
const submodule = hit.value.slice(CF_PREFIX.length);
|
|
3562
|
+
const quote = code[hit.start] === "'" ? "'" : '"';
|
|
3563
|
+
out = out.slice(0, hit.start) + quote + VIRTUAL_PREFIX + submodule + quote + out.slice(hit.end);
|
|
3564
|
+
}
|
|
3565
|
+
return { code: out, map: null };
|
|
3566
|
+
},
|
|
3567
|
+
resolveId(id) {
|
|
3568
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
3569
|
+
return "\0" + id;
|
|
3570
|
+
}
|
|
3571
|
+
return null;
|
|
3572
|
+
},
|
|
3573
|
+
load(id) {
|
|
3574
|
+
if (!id.startsWith(NULL_PREFIX)) return null;
|
|
3575
|
+
const submodule = id.slice(NULL_PREFIX.length);
|
|
3576
|
+
const specifier = CF_PREFIX + submodule;
|
|
3577
|
+
return STUBS[specifier] ?? FALLBACK_STUB;
|
|
3578
|
+
}
|
|
3579
|
+
};
|
|
3580
|
+
}
|
|
3581
|
+
function walk(node, visit) {
|
|
3582
|
+
if (!node || typeof node !== "object") return;
|
|
3583
|
+
if (Array.isArray(node)) {
|
|
3584
|
+
for (const child of node) walk(child, visit);
|
|
3585
|
+
return;
|
|
3586
|
+
}
|
|
3587
|
+
const n = node;
|
|
3588
|
+
if (typeof n.type !== "string") return;
|
|
3589
|
+
visit(n);
|
|
3590
|
+
for (const key in n) {
|
|
3591
|
+
if (key === "loc" || key === "start" || key === "end" || key === "range") {
|
|
3592
|
+
continue;
|
|
3593
|
+
}
|
|
3594
|
+
walk(n[key], visit);
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
|
|
3054
3598
|
// src/vite/plugins/client-ref-hashing.ts
|
|
3055
|
-
import { relative
|
|
3599
|
+
import { relative } from "node:path";
|
|
3056
3600
|
import { createHash as createHash2 } from "node:crypto";
|
|
3601
|
+
var debug8 = createRangoDebugger(NS.transform);
|
|
3057
3602
|
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3058
3603
|
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
3059
3604
|
var FS_PREFIX = "/@fs/";
|
|
@@ -3065,10 +3610,10 @@ function computeProductionHash(projectRoot, refKey) {
|
|
|
3065
3610
|
const absPath = decodeURIComponent(
|
|
3066
3611
|
refKey.slice(CLIENT_IN_SERVER_PKG_PROXY_PREFIX.length)
|
|
3067
3612
|
);
|
|
3068
|
-
toHash =
|
|
3613
|
+
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3069
3614
|
} else if (refKey.startsWith(FS_PREFIX)) {
|
|
3070
3615
|
const absPath = refKey.slice(FS_PREFIX.length - 1);
|
|
3071
|
-
toHash =
|
|
3616
|
+
toHash = relative(projectRoot, absPath).replaceAll("\\", "/");
|
|
3072
3617
|
} else if (refKey.startsWith("/")) {
|
|
3073
3618
|
toHash = refKey.slice(1);
|
|
3074
3619
|
} else {
|
|
@@ -3092,6 +3637,7 @@ function transformClientRefs(code, projectRoot) {
|
|
|
3092
3637
|
return hasReplacement ? result : null;
|
|
3093
3638
|
}
|
|
3094
3639
|
function hashClientRefs(projectRoot) {
|
|
3640
|
+
const counter = createCounter(debug8, "hash-client-refs");
|
|
3095
3641
|
return {
|
|
3096
3642
|
name: "@rangojs/router:hash-client-refs",
|
|
3097
3643
|
// Run after the RSC plugin's transform (default enforce is normal)
|
|
@@ -3099,10 +3645,18 @@ function hashClientRefs(projectRoot) {
|
|
|
3099
3645
|
applyToEnvironment(env) {
|
|
3100
3646
|
return env.name === "rsc";
|
|
3101
3647
|
},
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3648
|
+
buildEnd() {
|
|
3649
|
+
counter?.flush();
|
|
3650
|
+
},
|
|
3651
|
+
transform(code, id) {
|
|
3652
|
+
const start = counter ? performance.now() : 0;
|
|
3653
|
+
try {
|
|
3654
|
+
const result = transformClientRefs(code, projectRoot);
|
|
3655
|
+
if (result === null) return;
|
|
3656
|
+
return { code: result, map: null };
|
|
3657
|
+
} finally {
|
|
3658
|
+
counter?.record(id, performance.now() - start);
|
|
3659
|
+
}
|
|
3106
3660
|
}
|
|
3107
3661
|
};
|
|
3108
3662
|
}
|
|
@@ -3209,8 +3763,8 @@ function createDiscoveryState(entryPath, opts) {
|
|
|
3209
3763
|
perRouterManifestDataMap: /* @__PURE__ */ new Map(),
|
|
3210
3764
|
prerenderManifestEntries: null,
|
|
3211
3765
|
staticManifestEntries: null,
|
|
3212
|
-
|
|
3213
|
-
|
|
3766
|
+
handlerChunkInfoMap: /* @__PURE__ */ new Map(),
|
|
3767
|
+
staticHandlerChunkInfoMap: /* @__PURE__ */ new Map(),
|
|
3214
3768
|
rscEntryFileName: null,
|
|
3215
3769
|
resolvedPrerenderModules: void 0,
|
|
3216
3770
|
resolvedStaticModules: void 0,
|
|
@@ -3293,8 +3847,17 @@ function jsonParseExpression(value) {
|
|
|
3293
3847
|
}
|
|
3294
3848
|
|
|
3295
3849
|
// src/context-var.ts
|
|
3850
|
+
var NON_CACHEABLE_KEYS = /* @__PURE__ */ Symbol.for(
|
|
3851
|
+
"rango:non-cacheable-keys"
|
|
3852
|
+
);
|
|
3853
|
+
function getNonCacheableKeys(variables) {
|
|
3854
|
+
if (!variables[NON_CACHEABLE_KEYS]) {
|
|
3855
|
+
variables[NON_CACHEABLE_KEYS] = /* @__PURE__ */ new Set();
|
|
3856
|
+
}
|
|
3857
|
+
return variables[NON_CACHEABLE_KEYS];
|
|
3858
|
+
}
|
|
3296
3859
|
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
3297
|
-
function contextSet(variables, keyOrVar, value) {
|
|
3860
|
+
function contextSet(variables, keyOrVar, value, options) {
|
|
3298
3861
|
if (typeof keyOrVar === "string") {
|
|
3299
3862
|
if (FORBIDDEN_KEYS.has(keyOrVar)) {
|
|
3300
3863
|
throw new Error(
|
|
@@ -3302,8 +3865,14 @@ function contextSet(variables, keyOrVar, value) {
|
|
|
3302
3865
|
);
|
|
3303
3866
|
}
|
|
3304
3867
|
variables[keyOrVar] = value;
|
|
3868
|
+
if (options?.cache === false) {
|
|
3869
|
+
getNonCacheableKeys(variables).add(keyOrVar);
|
|
3870
|
+
}
|
|
3305
3871
|
} else {
|
|
3306
3872
|
variables[keyOrVar.key] = value;
|
|
3873
|
+
if (options?.cache === false) {
|
|
3874
|
+
getNonCacheableKeys(variables).add(keyOrVar.key);
|
|
3875
|
+
}
|
|
3307
3876
|
}
|
|
3308
3877
|
}
|
|
3309
3878
|
|
|
@@ -3326,13 +3895,31 @@ function encodePathParam(value) {
|
|
|
3326
3895
|
}
|
|
3327
3896
|
function substituteRouteParams(pattern, params, encode = encodeURIComponent) {
|
|
3328
3897
|
let result = pattern;
|
|
3898
|
+
let hadOmittedOptional = false;
|
|
3329
3899
|
for (const [key, value] of Object.entries(params)) {
|
|
3330
3900
|
const escaped = escapeRegExp2(key);
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3901
|
+
if (value === "") {
|
|
3902
|
+
result = result.replace(
|
|
3903
|
+
new RegExp(`:${escaped}(\\([^)]*\\))?(?!\\?)`),
|
|
3904
|
+
""
|
|
3905
|
+
);
|
|
3906
|
+
result = result.replace(`*${key}`, "");
|
|
3907
|
+
} else {
|
|
3908
|
+
result = result.replace(
|
|
3909
|
+
new RegExp(`:${escaped}(\\([^)]*\\))?\\??`),
|
|
3910
|
+
encode(value)
|
|
3911
|
+
);
|
|
3912
|
+
result = result.replace(`*${key}`, encode(value));
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3915
|
+
result = result.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?\?/g, () => {
|
|
3916
|
+
hadOmittedOptional = true;
|
|
3917
|
+
return "";
|
|
3918
|
+
});
|
|
3919
|
+
if (hadOmittedOptional) {
|
|
3920
|
+
const hadTrailingSlash = pattern.length > 1 && pattern.endsWith("/");
|
|
3921
|
+
result = result.replace(/\/\/+/g, "/").replace(/\/+$/, "") || "/";
|
|
3922
|
+
if (hadTrailingSlash && !result.endsWith("/")) result += "/";
|
|
3336
3923
|
}
|
|
3337
3924
|
return result;
|
|
3338
3925
|
}
|
|
@@ -3429,8 +4016,14 @@ function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
|
3429
4016
|
}
|
|
3430
4017
|
|
|
3431
4018
|
// src/vite/discovery/prerender-collection.ts
|
|
4019
|
+
var debug9 = createRangoDebugger(NS.prerender);
|
|
3432
4020
|
async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
3433
4021
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode) return;
|
|
4022
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
4023
|
+
debug9?.(
|
|
4024
|
+
"expandPrerenderRoutes: start (%d router manifest(s))",
|
|
4025
|
+
allManifests.length
|
|
4026
|
+
);
|
|
3434
4027
|
const entries = [];
|
|
3435
4028
|
const allRoutes = {};
|
|
3436
4029
|
for (const { manifest: m } of allManifests) {
|
|
@@ -3442,91 +4035,151 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3442
4035
|
if (!params) return pattern;
|
|
3443
4036
|
return substituteRouteParams(pattern, params);
|
|
3444
4037
|
};
|
|
4038
|
+
let resolvedRoutes = 0;
|
|
4039
|
+
let totalDynamic = 0;
|
|
3445
4040
|
for (const { manifest } of allManifests) {
|
|
3446
4041
|
if (!manifest.prerenderRoutes) continue;
|
|
3447
|
-
const defs = manifest._prerenderDefs || {};
|
|
3448
4042
|
for (const routeName of manifest.prerenderRoutes) {
|
|
3449
4043
|
const pattern = manifest.routeManifest[routeName];
|
|
3450
|
-
if (
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
4044
|
+
if (pattern && (pattern.includes(":") || pattern.includes("*"))) {
|
|
4045
|
+
totalDynamic++;
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
const paramsStart = performance.now();
|
|
4050
|
+
const progressInterval = totalDynamic > 0 ? setInterval(() => {
|
|
4051
|
+
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
4052
|
+
console.log(
|
|
4053
|
+
`[rsc-router] Resolving prerender params... ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
4054
|
+
);
|
|
4055
|
+
}, 5e3) : void 0;
|
|
4056
|
+
try {
|
|
4057
|
+
for (const { manifest } of allManifests) {
|
|
4058
|
+
if (!manifest.prerenderRoutes) continue;
|
|
4059
|
+
const defs = manifest._prerenderDefs || {};
|
|
4060
|
+
const passthroughSet = new Set(manifest.passthroughRoutes || []);
|
|
4061
|
+
for (const routeName of manifest.prerenderRoutes) {
|
|
4062
|
+
const pattern = manifest.routeManifest[routeName];
|
|
4063
|
+
if (!pattern) continue;
|
|
4064
|
+
const def = defs[routeName];
|
|
4065
|
+
const isPassthroughRoute = passthroughSet.has(routeName);
|
|
4066
|
+
const hasDynamic = pattern.includes(":") || pattern.includes("*");
|
|
4067
|
+
if (!hasDynamic) {
|
|
4068
|
+
entries.push({
|
|
4069
|
+
urlPath: pattern.replace(/\/$/, "") || "/",
|
|
4070
|
+
routeName,
|
|
4071
|
+
concurrency: 1,
|
|
4072
|
+
isPassthroughRoute
|
|
4073
|
+
});
|
|
4074
|
+
} else {
|
|
4075
|
+
if (def?.getParams) {
|
|
4076
|
+
const getParamsStart = debug9 ? performance.now() : 0;
|
|
4077
|
+
try {
|
|
4078
|
+
const buildVars = {};
|
|
4079
|
+
const buildEnv = state.resolvedBuildEnv;
|
|
4080
|
+
const getParamsCtx = {
|
|
4081
|
+
build: true,
|
|
4082
|
+
dev: !state.isBuildMode,
|
|
4083
|
+
set: ((keyOrVar, value) => {
|
|
4084
|
+
contextSet(buildVars, keyOrVar, value);
|
|
4085
|
+
}),
|
|
4086
|
+
reverse: getParamsReverse,
|
|
4087
|
+
get env() {
|
|
4088
|
+
if (buildEnv !== void 0) return buildEnv;
|
|
4089
|
+
throw new Error(
|
|
4090
|
+
"[rsc-router] ctx.env is not available during build-time getParams(). Configure buildEnv in your rango() plugin options to enable build-time env access."
|
|
4091
|
+
);
|
|
3485
4092
|
}
|
|
3486
|
-
}
|
|
3487
|
-
|
|
3488
|
-
|
|
4093
|
+
};
|
|
4094
|
+
const paramsList = await def.getParams(getParamsCtx);
|
|
4095
|
+
debug9?.(
|
|
4096
|
+
"getParams %s -> %d params (%sms)",
|
|
3489
4097
|
routeName,
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
isPassthroughRoute
|
|
3493
|
-
});
|
|
3494
|
-
}
|
|
3495
|
-
} catch (err) {
|
|
3496
|
-
if (err.name === "Skip") {
|
|
3497
|
-
console.log(
|
|
3498
|
-
`[rsc-router] SKIP route "${routeName}" - ${err.message}`
|
|
4098
|
+
paramsList.length,
|
|
4099
|
+
(performance.now() - getParamsStart).toFixed(1)
|
|
3499
4100
|
);
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
4101
|
+
const concurrency = def.options?.concurrency ?? 1;
|
|
4102
|
+
const hasBuildVars = Object.keys(buildVars).length > 0 || Object.getOwnPropertySymbols(buildVars).length > 0;
|
|
4103
|
+
for (const params of paramsList) {
|
|
4104
|
+
let url = substituteRouteParams(
|
|
4105
|
+
pattern,
|
|
4106
|
+
params,
|
|
4107
|
+
encodePathParam
|
|
4108
|
+
);
|
|
4109
|
+
if (url.includes("*")) {
|
|
4110
|
+
const wildcardValue = params["*"] ?? params.splat;
|
|
4111
|
+
if (wildcardValue !== void 0) {
|
|
4112
|
+
url = url.replace(
|
|
4113
|
+
/\*[^/]*$/,
|
|
4114
|
+
encodePathParam(wildcardValue)
|
|
4115
|
+
);
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
entries.push({
|
|
4119
|
+
urlPath: url.replace(/\/$/, "") || "/",
|
|
4120
|
+
routeName,
|
|
4121
|
+
concurrency,
|
|
4122
|
+
...hasBuildVars ? { buildVars } : {},
|
|
4123
|
+
isPassthroughRoute
|
|
4124
|
+
});
|
|
4125
|
+
}
|
|
4126
|
+
resolvedRoutes++;
|
|
4127
|
+
} catch (err) {
|
|
4128
|
+
resolvedRoutes++;
|
|
4129
|
+
if (err.name === "Skip") {
|
|
4130
|
+
console.log(
|
|
4131
|
+
`[rsc-router] SKIP route "${routeName}" - ${err.message}`
|
|
4132
|
+
);
|
|
4133
|
+
notifyOnError(
|
|
4134
|
+
registry,
|
|
4135
|
+
err,
|
|
4136
|
+
"prerender",
|
|
4137
|
+
routeName,
|
|
4138
|
+
void 0,
|
|
4139
|
+
true
|
|
4140
|
+
);
|
|
4141
|
+
continue;
|
|
4142
|
+
}
|
|
4143
|
+
console.error(
|
|
4144
|
+
`[rsc-router] Failed to get params for prerender route "${routeName}": ${err.message}`
|
|
3507
4145
|
);
|
|
3508
|
-
|
|
4146
|
+
notifyOnError(registry, err, "prerender", routeName);
|
|
4147
|
+
throw err;
|
|
3509
4148
|
}
|
|
3510
|
-
|
|
3511
|
-
|
|
4149
|
+
} else {
|
|
4150
|
+
console.warn(
|
|
4151
|
+
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3512
4152
|
);
|
|
3513
|
-
notifyOnError(registry, err, "prerender", routeName);
|
|
3514
|
-
throw err;
|
|
3515
4153
|
}
|
|
3516
|
-
} else {
|
|
3517
|
-
console.warn(
|
|
3518
|
-
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3519
|
-
);
|
|
3520
4154
|
}
|
|
3521
4155
|
}
|
|
3522
4156
|
}
|
|
4157
|
+
} finally {
|
|
4158
|
+
if (progressInterval) {
|
|
4159
|
+
clearInterval(progressInterval);
|
|
4160
|
+
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
4161
|
+
console.log(
|
|
4162
|
+
`[rsc-router] Resolved prerender params: ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
4163
|
+
);
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4166
|
+
if (entries.length === 0) {
|
|
4167
|
+
debug9?.(
|
|
4168
|
+
"no prerender entries (done in %sms)",
|
|
4169
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4170
|
+
);
|
|
4171
|
+
return;
|
|
3523
4172
|
}
|
|
3524
|
-
if (entries.length === 0) return;
|
|
3525
4173
|
const maxConcurrency = Math.max(...entries.map((e) => e.concurrency));
|
|
3526
4174
|
const concurrencyNote = maxConcurrency > 1 ? ` (concurrency: ${maxConcurrency})` : "";
|
|
3527
4175
|
console.log(
|
|
3528
4176
|
`[rsc-router] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
3529
4177
|
);
|
|
4178
|
+
debug9?.(
|
|
4179
|
+
"prerender loop: %d entries, max concurrency %d",
|
|
4180
|
+
entries.length,
|
|
4181
|
+
maxConcurrency
|
|
4182
|
+
);
|
|
3530
4183
|
const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
|
|
3531
4184
|
const manifestEntries = {};
|
|
3532
4185
|
let doneCount = 0;
|
|
@@ -3546,7 +4199,8 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3546
4199
|
entry.urlPath,
|
|
3547
4200
|
{},
|
|
3548
4201
|
entry.buildVars,
|
|
3549
|
-
entry.isPassthroughRoute
|
|
4202
|
+
entry.isPassthroughRoute,
|
|
4203
|
+
state.resolvedBuildEnv
|
|
3550
4204
|
);
|
|
3551
4205
|
if (!result) continue;
|
|
3552
4206
|
if (result.passthrough) {
|
|
@@ -3632,10 +4286,22 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3632
4286
|
console.log(
|
|
3633
4287
|
`[rsc-router] Pre-render complete: ${parts.join(", ")} (${totalElapsed}ms total)`
|
|
3634
4288
|
);
|
|
4289
|
+
debug9?.(
|
|
4290
|
+
"expandPrerenderRoutes done: %d done, %d skipped, %sms (overall %sms)",
|
|
4291
|
+
doneCount,
|
|
4292
|
+
skipCount,
|
|
4293
|
+
totalElapsed,
|
|
4294
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4295
|
+
);
|
|
3635
4296
|
}
|
|
3636
4297
|
async function renderStaticHandlers(state, rscEnv, registry) {
|
|
3637
4298
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
|
|
3638
4299
|
return;
|
|
4300
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
4301
|
+
debug9?.(
|
|
4302
|
+
"renderStaticHandlers: start (%d static module(s))",
|
|
4303
|
+
state.resolvedStaticModules.size
|
|
4304
|
+
);
|
|
3639
4305
|
const manifestEntries = {};
|
|
3640
4306
|
let staticDone = 0;
|
|
3641
4307
|
let staticSkip = 0;
|
|
@@ -3670,7 +4336,9 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3670
4336
|
const result = await routerInstance.renderStaticSegment(
|
|
3671
4337
|
def.handler,
|
|
3672
4338
|
def.$$id,
|
|
3673
|
-
def.$$routePrefix
|
|
4339
|
+
def.$$routePrefix,
|
|
4340
|
+
state.resolvedBuildEnv,
|
|
4341
|
+
!state.isBuildMode
|
|
3674
4342
|
);
|
|
3675
4343
|
if (result) {
|
|
3676
4344
|
const hasHandles = Object.keys(result.handles).length > 0;
|
|
@@ -3723,13 +4391,29 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3723
4391
|
console.log(
|
|
3724
4392
|
`[rsc-router] Static render complete: ${staticParts.join(", ")} (${totalStaticElapsed}ms total)`
|
|
3725
4393
|
);
|
|
4394
|
+
debug9?.(
|
|
4395
|
+
"renderStaticHandlers done: %d done, %d skipped, %sms (overall %sms)",
|
|
4396
|
+
staticDone,
|
|
4397
|
+
staticSkip,
|
|
4398
|
+
totalStaticElapsed,
|
|
4399
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4400
|
+
);
|
|
3726
4401
|
}
|
|
3727
4402
|
|
|
3728
4403
|
// src/vite/discovery/discover-routers.ts
|
|
4404
|
+
var debug10 = createRangoDebugger(NS.discovery);
|
|
3729
4405
|
async function discoverRouters(state, rscEnv) {
|
|
3730
4406
|
if (!state.resolvedEntryPath) return;
|
|
3731
|
-
await
|
|
3732
|
-
|
|
4407
|
+
await timed(
|
|
4408
|
+
debug10,
|
|
4409
|
+
"inner: import entry",
|
|
4410
|
+
() => rscEnv.runner.import(state.resolvedEntryPath)
|
|
4411
|
+
);
|
|
4412
|
+
const serverMod = await timed(
|
|
4413
|
+
debug10,
|
|
4414
|
+
"inner: import @rangojs/router/server",
|
|
4415
|
+
() => rscEnv.runner.import("@rangojs/router/server")
|
|
4416
|
+
);
|
|
3733
4417
|
let registry = serverMod.RouterRegistry;
|
|
3734
4418
|
if (!registry || registry.size === 0) {
|
|
3735
4419
|
try {
|
|
@@ -3771,8 +4455,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3771
4455
|
);
|
|
3772
4456
|
}
|
|
3773
4457
|
}
|
|
3774
|
-
const buildMod = await
|
|
4458
|
+
const buildMod = await timed(
|
|
4459
|
+
debug10,
|
|
4460
|
+
"inner: import @rangojs/router/build",
|
|
4461
|
+
() => rscEnv.runner.import("@rangojs/router/build")
|
|
4462
|
+
);
|
|
3775
4463
|
const generateManifestFull = buildMod.generateManifestFull;
|
|
4464
|
+
debug10?.("inner: found %d router(s) in registry", registry.size);
|
|
3776
4465
|
const nestedRouterConflict = findNestedRouterConflict(
|
|
3777
4466
|
[...registry.values()].map((router) => router.__sourceFile).filter(
|
|
3778
4467
|
(sourceFile) => typeof sourceFile === "string"
|
|
@@ -3791,11 +4480,16 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3791
4480
|
let mergedRouteTrailingSlash = {};
|
|
3792
4481
|
let routerMountIndex = 0;
|
|
3793
4482
|
const allManifests = [];
|
|
4483
|
+
const manifestGenStart = debug10 ? performance.now() : 0;
|
|
3794
4484
|
for (const [id, router] of registry) {
|
|
3795
4485
|
if (!router.urlpatterns || !generateManifestFull) {
|
|
3796
4486
|
continue;
|
|
3797
4487
|
}
|
|
3798
|
-
const manifest = generateManifestFull(
|
|
4488
|
+
const manifest = generateManifestFull(
|
|
4489
|
+
router.urlpatterns,
|
|
4490
|
+
routerMountIndex,
|
|
4491
|
+
router.__basename ? { urlPrefix: router.__basename } : void 0
|
|
4492
|
+
);
|
|
3799
4493
|
routerMountIndex++;
|
|
3800
4494
|
allManifests.push({ id, manifest });
|
|
3801
4495
|
const routeCount = Object.keys(manifest.routeManifest).length;
|
|
@@ -3861,7 +4555,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3861
4555
|
);
|
|
3862
4556
|
}
|
|
3863
4557
|
}
|
|
4558
|
+
debug10?.(
|
|
4559
|
+
"inner: generated manifests for %d router(s) (%sms)",
|
|
4560
|
+
allManifests.length,
|
|
4561
|
+
(performance.now() - manifestGenStart).toFixed(1)
|
|
4562
|
+
);
|
|
3864
4563
|
let newMergedRouteTrie = null;
|
|
4564
|
+
const trieStart = debug10 ? performance.now() : 0;
|
|
3865
4565
|
if (Object.keys(newMergedRouteManifest).length > 0) {
|
|
3866
4566
|
const buildRouteTrie = buildMod.buildRouteTrie;
|
|
3867
4567
|
if (buildRouteTrie && mergedRouteAncestry) {
|
|
@@ -3924,6 +4624,10 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3924
4624
|
}
|
|
3925
4625
|
}
|
|
3926
4626
|
}
|
|
4627
|
+
debug10?.(
|
|
4628
|
+
"inner: trie build done (%sms)",
|
|
4629
|
+
(performance.now() - trieStart).toFixed(1)
|
|
4630
|
+
);
|
|
3927
4631
|
state.mergedRouteManifest = newMergedRouteManifest;
|
|
3928
4632
|
state.mergedPrecomputedEntries = newMergedPrecomputedEntries;
|
|
3929
4633
|
state.perRouterManifests = newPerRouterManifests;
|
|
@@ -3937,7 +4641,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3937
4641
|
}
|
|
3938
4642
|
|
|
3939
4643
|
// src/vite/discovery/route-types-writer.ts
|
|
3940
|
-
import { dirname as dirname3, basename, join as
|
|
4644
|
+
import { dirname as dirname3, basename, join as join2, resolve as resolve6 } from "node:path";
|
|
3941
4645
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "node:fs";
|
|
3942
4646
|
function filterUserNamedRoutes(manifest) {
|
|
3943
4647
|
const filtered = {};
|
|
@@ -3958,7 +4662,7 @@ function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
|
3958
4662
|
/\.(tsx?|jsx?)$/,
|
|
3959
4663
|
""
|
|
3960
4664
|
);
|
|
3961
|
-
const outPath =
|
|
4665
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
3962
4666
|
try {
|
|
3963
4667
|
preContent.set(outPath, readFileSync4(outPath, "utf-8"));
|
|
3964
4668
|
} catch {
|
|
@@ -3971,7 +4675,7 @@ function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
|
3971
4675
|
/\.(tsx?|jsx?)$/,
|
|
3972
4676
|
""
|
|
3973
4677
|
);
|
|
3974
|
-
const outPath =
|
|
4678
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
3975
4679
|
if (!existsSync5(outPath)) continue;
|
|
3976
4680
|
try {
|
|
3977
4681
|
const content = readFileSync4(outPath, "utf-8");
|
|
@@ -3988,7 +4692,7 @@ function writeRouteTypesFiles(state) {
|
|
|
3988
4692
|
const entryDir = dirname3(
|
|
3989
4693
|
resolve6(state.projectRoot, state.resolvedEntryPath)
|
|
3990
4694
|
);
|
|
3991
|
-
const oldCombinedPath =
|
|
4695
|
+
const oldCombinedPath = join2(entryDir, "named-routes.gen.ts");
|
|
3992
4696
|
if (existsSync5(oldCombinedPath)) {
|
|
3993
4697
|
unlinkSync2(oldCombinedPath);
|
|
3994
4698
|
console.log(
|
|
@@ -4013,7 +4717,7 @@ Set an explicit \`id\` on createRouter() or check the call site.`
|
|
|
4013
4717
|
}
|
|
4014
4718
|
const routerDir = dirname3(sourceFile);
|
|
4015
4719
|
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4016
|
-
const outPath =
|
|
4720
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4017
4721
|
const userRoutes = filterUserNamedRoutes(routeManifest);
|
|
4018
4722
|
let effectiveSearchSchemas = routeSearchSchemas;
|
|
4019
4723
|
if ((!effectiveSearchSchemas || Object.keys(effectiveSearchSchemas).length === 0) && sourceFile) {
|
|
@@ -4078,7 +4782,7 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
4078
4782
|
}
|
|
4079
4783
|
const routerDir = dirname3(sourceFile);
|
|
4080
4784
|
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
4081
|
-
const outPath =
|
|
4785
|
+
const outPath = join2(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
4082
4786
|
const source = generateRouteTypesSource(
|
|
4083
4787
|
mergedRoutes,
|
|
4084
4788
|
Object.keys(mergedSearchSchemas).length > 0 ? mergedSearchSchemas : void 0
|
|
@@ -4092,7 +4796,7 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
4092
4796
|
}
|
|
4093
4797
|
|
|
4094
4798
|
// src/vite/discovery/virtual-module-codegen.ts
|
|
4095
|
-
import { dirname as dirname4, basename as basename2, join as
|
|
4799
|
+
import { dirname as dirname4, basename as basename2, join as join3 } from "node:path";
|
|
4096
4800
|
function generateRoutesManifestModule(state) {
|
|
4097
4801
|
const hasManifest = state.mergedRouteManifest && Object.keys(state.mergedRouteManifest).length > 0;
|
|
4098
4802
|
if (hasManifest) {
|
|
@@ -4107,7 +4811,7 @@ function generateRoutesManifestModule(state) {
|
|
|
4107
4811
|
/\.(tsx?|jsx?)$/,
|
|
4108
4812
|
""
|
|
4109
4813
|
);
|
|
4110
|
-
const genPath =
|
|
4814
|
+
const genPath = join3(
|
|
4111
4815
|
routerDir,
|
|
4112
4816
|
`${routerBasename}.named-routes.gen.js`
|
|
4113
4817
|
).replaceAll("\\", "/");
|
|
@@ -4204,7 +4908,7 @@ function generatePerRouterModule(state, routerId) {
|
|
|
4204
4908
|
/\.(tsx?|jsx?)$/,
|
|
4205
4909
|
""
|
|
4206
4910
|
);
|
|
4207
|
-
const genPath =
|
|
4911
|
+
const genPath = join3(
|
|
4208
4912
|
routerDir,
|
|
4209
4913
|
`${routerBasename}.named-routes.gen.js`
|
|
4210
4914
|
).replaceAll("\\", "/");
|
|
@@ -4244,48 +4948,45 @@ function postprocessBundle(state) {
|
|
|
4244
4948
|
);
|
|
4245
4949
|
const evictionTargets = [
|
|
4246
4950
|
{
|
|
4247
|
-
|
|
4951
|
+
infos: state.handlerChunkInfoMap.values(),
|
|
4248
4952
|
fnName: "Prerender",
|
|
4249
4953
|
brand: "prerenderHandler",
|
|
4250
4954
|
label: "handler code from RSC bundle"
|
|
4251
4955
|
},
|
|
4252
4956
|
{
|
|
4253
|
-
|
|
4957
|
+
infos: state.staticHandlerChunkInfoMap.values(),
|
|
4254
4958
|
fnName: "Static",
|
|
4255
4959
|
brand: "staticHandler",
|
|
4256
4960
|
label: "static handler code"
|
|
4257
4961
|
}
|
|
4258
4962
|
];
|
|
4259
4963
|
for (const target of evictionTargets) {
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4964
|
+
for (const info of target.infos) {
|
|
4965
|
+
const chunkPath = resolve7(state.projectRoot, "dist/rsc", info.fileName);
|
|
4966
|
+
try {
|
|
4967
|
+
const code = readFileSync5(chunkPath, "utf-8");
|
|
4968
|
+
const result = evictHandlerCode(
|
|
4969
|
+
code,
|
|
4970
|
+
info.exports,
|
|
4971
|
+
target.fnName,
|
|
4972
|
+
target.brand
|
|
4973
|
+
);
|
|
4974
|
+
if (result) {
|
|
4975
|
+
writeFileSync4(chunkPath, result.code);
|
|
4976
|
+
const savedKB = (result.savedBytes / 1024).toFixed(1);
|
|
4977
|
+
console.log(
|
|
4978
|
+
`[rsc-router] Evicted ${target.label} (${savedKB} KB saved): ${info.fileName}`
|
|
4979
|
+
);
|
|
4980
|
+
}
|
|
4981
|
+
} catch (replaceErr) {
|
|
4982
|
+
console.warn(
|
|
4983
|
+
`[rsc-router] Failed to evict ${target.label}: ${replaceErr.message}`
|
|
4279
4984
|
);
|
|
4280
4985
|
}
|
|
4281
|
-
} catch (replaceErr) {
|
|
4282
|
-
console.warn(
|
|
4283
|
-
`[rsc-router] Failed to evict ${target.label}: ${replaceErr.message}`
|
|
4284
|
-
);
|
|
4285
4986
|
}
|
|
4286
4987
|
}
|
|
4287
|
-
state.
|
|
4288
|
-
state.
|
|
4988
|
+
state.handlerChunkInfoMap.clear();
|
|
4989
|
+
state.staticHandlerChunkInfoMap.clear();
|
|
4289
4990
|
if (hasPrerenderData && existsSync6(rscEntryPath)) {
|
|
4290
4991
|
const rscCode = readFileSync5(rscEntryPath, "utf-8");
|
|
4291
4992
|
if (!rscCode.includes("__prerender-manifest.js")) {
|
|
@@ -4328,7 +5029,7 @@ function postprocessBundle(state) {
|
|
|
4328
5029
|
}
|
|
4329
5030
|
if (hasStaticData && existsSync6(rscEntryPath)) {
|
|
4330
5031
|
const rscCode = readFileSync5(rscEntryPath, "utf-8");
|
|
4331
|
-
if (!rscCode.includes("
|
|
5032
|
+
if (!rscCode.includes("__static-manifest.js")) {
|
|
4332
5033
|
try {
|
|
4333
5034
|
const manifestEntries = [];
|
|
4334
5035
|
let totalBytes = copyStagedBuildAssets(
|
|
@@ -4367,7 +5068,26 @@ function postprocessBundle(state) {
|
|
|
4367
5068
|
}
|
|
4368
5069
|
|
|
4369
5070
|
// src/vite/router-discovery.ts
|
|
5071
|
+
var debugDiscovery = createRangoDebugger(NS.discovery);
|
|
5072
|
+
var debugRoutes = createRangoDebugger(NS.routes);
|
|
5073
|
+
var debugBuild = createRangoDebugger(NS.build);
|
|
5074
|
+
var debugDev = createRangoDebugger(NS.dev);
|
|
5075
|
+
var loaderHookRegistered = false;
|
|
5076
|
+
function ensureCloudflareProtocolLoaderRegistered() {
|
|
5077
|
+
if (loaderHookRegistered) return;
|
|
5078
|
+
loaderHookRegistered = true;
|
|
5079
|
+
try {
|
|
5080
|
+
register(
|
|
5081
|
+
new URL("./plugins/cloudflare-protocol-loader-hook.mjs", import.meta.url)
|
|
5082
|
+
);
|
|
5083
|
+
} catch (err) {
|
|
5084
|
+
console.warn(
|
|
5085
|
+
`[rsc-router] Could not register Node ESM loader hook for cloudflare:* imports (${err?.message ?? err}). Falling back to Vite transform only.`
|
|
5086
|
+
);
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
4370
5089
|
async function createTempRscServer(state, options = {}) {
|
|
5090
|
+
ensureCloudflareProtocolLoaderRegistered();
|
|
4371
5091
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
4372
5092
|
return createViteServer({
|
|
4373
5093
|
root: state.projectRoot,
|
|
@@ -4390,6 +5110,7 @@ async function createTempRscServer(state, options = {}) {
|
|
|
4390
5110
|
...options.forceBuild ? [hashClientRefs(state.projectRoot)] : [],
|
|
4391
5111
|
createVersionPlugin(),
|
|
4392
5112
|
createVirtualStubPlugin(),
|
|
5113
|
+
createCloudflareProtocolStubPlugin(),
|
|
4393
5114
|
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
4394
5115
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
4395
5116
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : void 0),
|
|
@@ -4397,8 +5118,69 @@ async function createTempRscServer(state, options = {}) {
|
|
|
4397
5118
|
]
|
|
4398
5119
|
});
|
|
4399
5120
|
}
|
|
5121
|
+
async function resolveBuildEnv(option, factoryCtx) {
|
|
5122
|
+
if (!option) return null;
|
|
5123
|
+
if (option === "auto") {
|
|
5124
|
+
if (factoryCtx.preset !== "cloudflare") {
|
|
5125
|
+
throw new Error(
|
|
5126
|
+
'[rsc-router] buildEnv: "auto" is only supported with preset: "cloudflare". Use a factory function or plain object for other presets.'
|
|
5127
|
+
);
|
|
5128
|
+
}
|
|
5129
|
+
try {
|
|
5130
|
+
const userRequire = createRequire2(
|
|
5131
|
+
resolve8(factoryCtx.root, "package.json")
|
|
5132
|
+
);
|
|
5133
|
+
const wranglerPath = userRequire.resolve("wrangler");
|
|
5134
|
+
const { getPlatformProxy } = await import(pathToFileURL(wranglerPath).href);
|
|
5135
|
+
const proxy = await getPlatformProxy();
|
|
5136
|
+
return {
|
|
5137
|
+
env: proxy.env,
|
|
5138
|
+
dispose: proxy.dispose
|
|
5139
|
+
};
|
|
5140
|
+
} catch (err) {
|
|
5141
|
+
throw new Error(
|
|
5142
|
+
`[rsc-router] buildEnv: "auto" requires wrangler to be installed.
|
|
5143
|
+
Install it with: pnpm add -D wrangler
|
|
5144
|
+
${err.message}`
|
|
5145
|
+
);
|
|
5146
|
+
}
|
|
5147
|
+
}
|
|
5148
|
+
if (typeof option === "function") {
|
|
5149
|
+
return await option(factoryCtx);
|
|
5150
|
+
}
|
|
5151
|
+
return { env: option };
|
|
5152
|
+
}
|
|
5153
|
+
async function acquireBuildEnv(s, command, mode) {
|
|
5154
|
+
const option = s.opts?.buildEnv;
|
|
5155
|
+
if (!option) return false;
|
|
5156
|
+
const result = await resolveBuildEnv(option, {
|
|
5157
|
+
root: s.projectRoot,
|
|
5158
|
+
mode,
|
|
5159
|
+
command,
|
|
5160
|
+
preset: s.opts?.preset ?? "node"
|
|
5161
|
+
});
|
|
5162
|
+
if (!result) return false;
|
|
5163
|
+
s.resolvedBuildEnv = result.env;
|
|
5164
|
+
s.buildEnvDispose = result.dispose ?? null;
|
|
5165
|
+
globalThis[BUILD_ENV_GLOBAL_KEY] = result.env;
|
|
5166
|
+
return true;
|
|
5167
|
+
}
|
|
5168
|
+
async function releaseBuildEnv(s) {
|
|
5169
|
+
if (s.buildEnvDispose) {
|
|
5170
|
+
try {
|
|
5171
|
+
await s.buildEnvDispose();
|
|
5172
|
+
} catch (err) {
|
|
5173
|
+
console.warn(`[rsc-router] buildEnv dispose failed: ${err.message}`);
|
|
5174
|
+
}
|
|
5175
|
+
s.buildEnvDispose = null;
|
|
5176
|
+
}
|
|
5177
|
+
s.resolvedBuildEnv = void 0;
|
|
5178
|
+
delete globalThis[BUILD_ENV_GLOBAL_KEY];
|
|
5179
|
+
}
|
|
4400
5180
|
function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
4401
5181
|
const s = createDiscoveryState(entryPath, opts);
|
|
5182
|
+
let viteCommand = "build";
|
|
5183
|
+
let viteMode = "production";
|
|
4402
5184
|
return {
|
|
4403
5185
|
name: "@rangojs/router:discovery",
|
|
4404
5186
|
config() {
|
|
@@ -4407,31 +5189,13 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4407
5189
|
__RANGO_DEBUG__: JSON.stringify(!!process.env.INTERNAL_RANGO_DEBUG)
|
|
4408
5190
|
}
|
|
4409
5191
|
};
|
|
4410
|
-
if (opts?.enableBuildPrerender) {
|
|
4411
|
-
config.environments = {
|
|
4412
|
-
rsc: {
|
|
4413
|
-
build: {
|
|
4414
|
-
rollupOptions: {
|
|
4415
|
-
output: {
|
|
4416
|
-
manualChunks(id) {
|
|
4417
|
-
if (s.resolvedPrerenderModules?.has(id)) {
|
|
4418
|
-
return "__prerender-handlers";
|
|
4419
|
-
}
|
|
4420
|
-
if (s.resolvedStaticModules?.has(id)) {
|
|
4421
|
-
return "__static-handlers";
|
|
4422
|
-
}
|
|
4423
|
-
}
|
|
4424
|
-
}
|
|
4425
|
-
}
|
|
4426
|
-
}
|
|
4427
|
-
}
|
|
4428
|
-
};
|
|
4429
|
-
}
|
|
4430
5192
|
return config;
|
|
4431
5193
|
},
|
|
4432
5194
|
configResolved(config) {
|
|
4433
5195
|
s.projectRoot = config.root;
|
|
4434
5196
|
s.isBuildMode = config.command === "build";
|
|
5197
|
+
viteCommand = config.command;
|
|
5198
|
+
viteMode = config.mode;
|
|
4435
5199
|
s.userResolveAlias = config.resolve.alias;
|
|
4436
5200
|
if (!s.resolvedEntryPath && opts?.routerPathRef?.path) {
|
|
4437
5201
|
s.resolvedEntryPath = opts.routerPathRef.path;
|
|
@@ -4445,12 +5209,6 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4445
5209
|
s.resolvedEntryPath = entries[0];
|
|
4446
5210
|
}
|
|
4447
5211
|
}
|
|
4448
|
-
if (opts?.include || opts?.exclude) {
|
|
4449
|
-
s.scanFilter = createScanFilter(s.projectRoot, {
|
|
4450
|
-
include: opts.include,
|
|
4451
|
-
exclude: opts.exclude
|
|
4452
|
-
});
|
|
4453
|
-
}
|
|
4454
5212
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
4455
5213
|
s.cachedRouterFiles = findRouterFiles(s.projectRoot, s.scanFilter);
|
|
4456
5214
|
writeCombinedRouteTypesWithTracking(s, { preserveIfLarger: true });
|
|
@@ -4482,6 +5240,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4482
5240
|
});
|
|
4483
5241
|
prerenderTempServer = null;
|
|
4484
5242
|
}
|
|
5243
|
+
releaseBuildEnv(s).catch(() => {
|
|
5244
|
+
});
|
|
4485
5245
|
});
|
|
4486
5246
|
async function getOrCreateTempServer() {
|
|
4487
5247
|
if (prerenderNodeRegistry) {
|
|
@@ -4508,14 +5268,33 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4508
5268
|
return null;
|
|
4509
5269
|
}
|
|
4510
5270
|
const discover = async () => {
|
|
5271
|
+
const discoverStart = performance.now();
|
|
4511
5272
|
const rscEnv = server.environments?.rsc;
|
|
4512
5273
|
if (!rscEnv?.runner) {
|
|
5274
|
+
debugDiscovery?.("dev: no rsc runner (cloudflare path)");
|
|
4513
5275
|
s.devServerOrigin = getDevServerOrigin();
|
|
4514
5276
|
try {
|
|
4515
|
-
|
|
5277
|
+
await timed(
|
|
5278
|
+
debugDiscovery,
|
|
5279
|
+
"acquireBuildEnv",
|
|
5280
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5281
|
+
);
|
|
5282
|
+
const tempRscEnv = await timed(
|
|
5283
|
+
debugDiscovery,
|
|
5284
|
+
"getOrCreateTempServer",
|
|
5285
|
+
() => getOrCreateTempServer()
|
|
5286
|
+
);
|
|
4516
5287
|
if (tempRscEnv) {
|
|
4517
|
-
await
|
|
4518
|
-
|
|
5288
|
+
await timed(
|
|
5289
|
+
debugDiscovery,
|
|
5290
|
+
"discoverRouters (cloudflare)",
|
|
5291
|
+
() => discoverRouters(s, tempRscEnv)
|
|
5292
|
+
);
|
|
5293
|
+
timedSync(
|
|
5294
|
+
debugDiscovery,
|
|
5295
|
+
"writeRouteTypesFiles",
|
|
5296
|
+
() => writeRouteTypesFiles(s)
|
|
5297
|
+
);
|
|
4519
5298
|
}
|
|
4520
5299
|
} catch (err) {
|
|
4521
5300
|
console.warn(
|
|
@@ -4523,26 +5302,54 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4523
5302
|
${err.stack}`
|
|
4524
5303
|
);
|
|
4525
5304
|
}
|
|
5305
|
+
debugDiscovery?.(
|
|
5306
|
+
"dev discovery done (%sms)",
|
|
5307
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5308
|
+
);
|
|
4526
5309
|
resolveDiscovery();
|
|
4527
5310
|
return;
|
|
4528
5311
|
}
|
|
4529
5312
|
try {
|
|
4530
|
-
|
|
4531
|
-
|
|
5313
|
+
debugDiscovery?.("dev: node path start");
|
|
5314
|
+
await timed(
|
|
5315
|
+
debugDiscovery,
|
|
5316
|
+
"acquireBuildEnv",
|
|
5317
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5318
|
+
);
|
|
5319
|
+
const serverMod = await timed(
|
|
5320
|
+
debugDiscovery,
|
|
5321
|
+
"import @rangojs/router/server",
|
|
5322
|
+
() => rscEnv.runner.import("@rangojs/router/server")
|
|
4532
5323
|
);
|
|
4533
5324
|
if (serverMod?.setManifestReadyPromise) {
|
|
4534
5325
|
serverMod.setManifestReadyPromise(discoveryPromise);
|
|
4535
5326
|
}
|
|
4536
|
-
await
|
|
5327
|
+
await timed(
|
|
5328
|
+
debugDiscovery,
|
|
5329
|
+
"discoverRouters",
|
|
5330
|
+
() => discoverRouters(s, rscEnv)
|
|
5331
|
+
);
|
|
4537
5332
|
s.devServerOrigin = getDevServerOrigin();
|
|
4538
|
-
|
|
4539
|
-
|
|
5333
|
+
timedSync(
|
|
5334
|
+
debugDiscovery,
|
|
5335
|
+
"writeRouteTypesFiles",
|
|
5336
|
+
() => writeRouteTypesFiles(s)
|
|
5337
|
+
);
|
|
5338
|
+
await timed(
|
|
5339
|
+
debugDiscovery,
|
|
5340
|
+
"propagateDiscoveryState",
|
|
5341
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5342
|
+
);
|
|
4540
5343
|
} catch (err) {
|
|
4541
5344
|
console.warn(
|
|
4542
5345
|
`[rsc-router] Router discovery failed: ${err.message}
|
|
4543
5346
|
${err.stack}`
|
|
4544
5347
|
);
|
|
4545
5348
|
} finally {
|
|
5349
|
+
debugDiscovery?.(
|
|
5350
|
+
"dev discovery done (%sms)",
|
|
5351
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5352
|
+
);
|
|
4546
5353
|
resolveDiscovery();
|
|
4547
5354
|
}
|
|
4548
5355
|
};
|
|
@@ -4583,15 +5390,46 @@ ${err.stack}`
|
|
|
4583
5390
|
}
|
|
4584
5391
|
};
|
|
4585
5392
|
server.middlewares.use("/__rsc_prerender", async (req, res) => {
|
|
5393
|
+
const reqStart = debugDev ? performance.now() : 0;
|
|
5394
|
+
const logResult = (status, note) => {
|
|
5395
|
+
debugDev?.(
|
|
5396
|
+
"/__rsc_prerender %s -> %d %s (%sms)",
|
|
5397
|
+
req.url,
|
|
5398
|
+
status,
|
|
5399
|
+
note,
|
|
5400
|
+
(performance.now() - reqStart).toFixed(1)
|
|
5401
|
+
);
|
|
5402
|
+
};
|
|
4586
5403
|
if (s.discoveryDone) await s.discoveryDone;
|
|
4587
5404
|
const url = new URL(req.url || "/", "http://localhost");
|
|
4588
5405
|
const pathname = url.searchParams.get("pathname");
|
|
4589
5406
|
if (!pathname) {
|
|
4590
5407
|
res.statusCode = 400;
|
|
4591
5408
|
res.end("Missing pathname");
|
|
5409
|
+
logResult(400, "missing pathname");
|
|
4592
5410
|
return;
|
|
4593
5411
|
}
|
|
4594
|
-
|
|
5412
|
+
const rscEnv = server.environments?.rsc;
|
|
5413
|
+
let registry = null;
|
|
5414
|
+
if (rscEnv?.runner && s.resolvedEntryPath) {
|
|
5415
|
+
try {
|
|
5416
|
+
await rscEnv.runner.import(s.resolvedEntryPath);
|
|
5417
|
+
const serverMod = await rscEnv.runner.import(
|
|
5418
|
+
"@rangojs/router/server"
|
|
5419
|
+
);
|
|
5420
|
+
registry = serverMod.RouterRegistry ?? null;
|
|
5421
|
+
} catch (err) {
|
|
5422
|
+
console.warn(
|
|
5423
|
+
`[rsc-router] Dev prerender module refresh failed: ${err.message}`
|
|
5424
|
+
);
|
|
5425
|
+
res.statusCode = 500;
|
|
5426
|
+
res.end(`Prerender handler error: ${err.message}`);
|
|
5427
|
+
logResult(500, "module refresh failed");
|
|
5428
|
+
return;
|
|
5429
|
+
}
|
|
5430
|
+
} else {
|
|
5431
|
+
registry = mainRegistry;
|
|
5432
|
+
}
|
|
4595
5433
|
if (!registry) {
|
|
4596
5434
|
if (!prerenderNodeRegistry) {
|
|
4597
5435
|
await getOrCreateTempServer();
|
|
@@ -4601,6 +5439,7 @@ ${err.stack}`
|
|
|
4601
5439
|
if (!registry || registry.size === 0) {
|
|
4602
5440
|
res.statusCode = 503;
|
|
4603
5441
|
res.end("Prerender runner not available");
|
|
5442
|
+
logResult(503, "no registry");
|
|
4604
5443
|
return;
|
|
4605
5444
|
}
|
|
4606
5445
|
const wantIntercept = url.searchParams.get("intercept") === "1";
|
|
@@ -4613,7 +5452,10 @@ ${err.stack}`
|
|
|
4613
5452
|
pathname,
|
|
4614
5453
|
{},
|
|
4615
5454
|
void 0,
|
|
4616
|
-
wantPassthrough
|
|
5455
|
+
wantPassthrough,
|
|
5456
|
+
s.resolvedBuildEnv,
|
|
5457
|
+
true
|
|
5458
|
+
// devMode: check getParams for passthrough routes
|
|
4617
5459
|
);
|
|
4618
5460
|
if (!result) continue;
|
|
4619
5461
|
if (result.passthrough) continue;
|
|
@@ -4632,6 +5474,7 @@ ${err.stack}`
|
|
|
4632
5474
|
payload = { segments: result.segments, handles: result.handles };
|
|
4633
5475
|
}
|
|
4634
5476
|
res.end(JSON.stringify(payload));
|
|
5477
|
+
logResult(200, `match ${result.routeName}`);
|
|
4635
5478
|
return;
|
|
4636
5479
|
} catch (err) {
|
|
4637
5480
|
console.warn(
|
|
@@ -4641,6 +5484,7 @@ ${err.stack}`
|
|
|
4641
5484
|
}
|
|
4642
5485
|
res.statusCode = 404;
|
|
4643
5486
|
res.end("No prerender match");
|
|
5487
|
+
logResult(404, "no match");
|
|
4644
5488
|
});
|
|
4645
5489
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
4646
5490
|
const isGeneratedRouteFile = (filePath) => filePath.endsWith(".gen.ts") && (filePath.includes("named-routes.gen.ts") || filePath.includes("urls.gen.ts"));
|
|
@@ -4665,15 +5509,32 @@ ${err.stack}`
|
|
|
4665
5509
|
const rscEnv = server.environments?.rsc;
|
|
4666
5510
|
if (!rscEnv?.runner || runtimeRediscoveryInProgress) return;
|
|
4667
5511
|
runtimeRediscoveryInProgress = true;
|
|
5512
|
+
const hmrStart = performance.now();
|
|
4668
5513
|
try {
|
|
4669
|
-
await
|
|
4670
|
-
|
|
4671
|
-
|
|
5514
|
+
await timed(
|
|
5515
|
+
debugDiscovery,
|
|
5516
|
+
"hmr discoverRouters",
|
|
5517
|
+
() => discoverRouters(s, rscEnv)
|
|
5518
|
+
);
|
|
5519
|
+
timedSync(
|
|
5520
|
+
debugDiscovery,
|
|
5521
|
+
"hmr writeRouteTypesFiles",
|
|
5522
|
+
() => writeRouteTypesFiles(s)
|
|
5523
|
+
);
|
|
5524
|
+
await timed(
|
|
5525
|
+
debugDiscovery,
|
|
5526
|
+
"hmr propagateDiscoveryState",
|
|
5527
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5528
|
+
);
|
|
4672
5529
|
} catch (err) {
|
|
4673
5530
|
console.warn(
|
|
4674
5531
|
`[rsc-router] Runtime re-discovery failed: ${err.message}`
|
|
4675
5532
|
);
|
|
4676
5533
|
} finally {
|
|
5534
|
+
debugDiscovery?.(
|
|
5535
|
+
"hmr re-discovery done (%sms)",
|
|
5536
|
+
(performance.now() - hmrStart).toFixed(1)
|
|
5537
|
+
);
|
|
4677
5538
|
runtimeRediscoveryInProgress = false;
|
|
4678
5539
|
}
|
|
4679
5540
|
};
|
|
@@ -4681,6 +5542,7 @@ ${err.stack}`
|
|
|
4681
5542
|
clearTimeout(routeChangeTimer);
|
|
4682
5543
|
routeChangeTimer = setTimeout(() => {
|
|
4683
5544
|
routeChangeTimer = void 0;
|
|
5545
|
+
const regenStart = debugDiscovery ? performance.now() : 0;
|
|
4684
5546
|
try {
|
|
4685
5547
|
writeCombinedRouteTypesWithTracking(s);
|
|
4686
5548
|
if (s.perRouterManifests.length > 0) {
|
|
@@ -4691,6 +5553,10 @@ ${err.stack}`
|
|
|
4691
5553
|
`[rsc-router] Route regeneration error: ${err.message}`
|
|
4692
5554
|
);
|
|
4693
5555
|
}
|
|
5556
|
+
debugDiscovery?.(
|
|
5557
|
+
"watcher: regenerated gen files (%sms)",
|
|
5558
|
+
(performance.now() - regenStart).toFixed(1)
|
|
5559
|
+
);
|
|
4694
5560
|
if (s.perRouterManifests.length > 0) {
|
|
4695
5561
|
refreshRuntimeDiscovery().catch((err) => {
|
|
4696
5562
|
console.warn(
|
|
@@ -4713,6 +5579,12 @@ ${err.stack}`
|
|
|
4713
5579
|
const hasUrls = source.includes("urls(");
|
|
4714
5580
|
const hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
|
|
4715
5581
|
if (!hasUrls && !hasCreateRouter) return;
|
|
5582
|
+
debugDiscovery?.(
|
|
5583
|
+
"watcher: %s matches (urls=%s, router=%s)",
|
|
5584
|
+
filePath,
|
|
5585
|
+
hasUrls,
|
|
5586
|
+
hasCreateRouter
|
|
5587
|
+
);
|
|
4716
5588
|
if (hasCreateRouter) {
|
|
4717
5589
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
4718
5590
|
...s.cachedRouterFiles ?? [],
|
|
@@ -4745,14 +5617,31 @@ ${err.stack}`
|
|
|
4745
5617
|
// The manifest data is stored for the virtual module's load hook.
|
|
4746
5618
|
async buildStart() {
|
|
4747
5619
|
if (!s.isBuildMode) return;
|
|
4748
|
-
if (s.mergedRouteManifest !== null)
|
|
5620
|
+
if (s.mergedRouteManifest !== null) {
|
|
5621
|
+
debugDiscovery?.(
|
|
5622
|
+
"build: skip (already discovered, env=%s)",
|
|
5623
|
+
this.environment?.name ?? "?"
|
|
5624
|
+
);
|
|
5625
|
+
return;
|
|
5626
|
+
}
|
|
5627
|
+
const buildStartTime = performance.now();
|
|
5628
|
+
debugDiscovery?.("build: start (env=%s)", this.environment?.name ?? "?");
|
|
4749
5629
|
resetStagedBuildAssets(s.projectRoot);
|
|
4750
5630
|
s.prerenderManifestEntries = null;
|
|
4751
5631
|
s.staticManifestEntries = null;
|
|
5632
|
+
await timed(
|
|
5633
|
+
debugDiscovery,
|
|
5634
|
+
"build acquireBuildEnv",
|
|
5635
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5636
|
+
);
|
|
4752
5637
|
let tempServer = null;
|
|
4753
5638
|
globalThis.__rscRouterDiscoveryActive = true;
|
|
4754
5639
|
try {
|
|
4755
|
-
tempServer = await
|
|
5640
|
+
tempServer = await timed(
|
|
5641
|
+
debugDiscovery,
|
|
5642
|
+
"build createTempRscServer",
|
|
5643
|
+
() => createTempRscServer(s, { forceBuild: true })
|
|
5644
|
+
);
|
|
4756
5645
|
const rscEnv = tempServer.environments?.rsc;
|
|
4757
5646
|
if (!rscEnv?.runner) {
|
|
4758
5647
|
console.warn(
|
|
@@ -4766,8 +5655,16 @@ ${err.stack}`
|
|
|
4766
5655
|
if (tempIdsPlugin?.api?.staticHandlerModules) {
|
|
4767
5656
|
s.resolvedStaticModules = tempIdsPlugin.api.staticHandlerModules;
|
|
4768
5657
|
}
|
|
4769
|
-
await
|
|
4770
|
-
|
|
5658
|
+
await timed(
|
|
5659
|
+
debugDiscovery,
|
|
5660
|
+
"build discoverRouters",
|
|
5661
|
+
() => discoverRouters(s, rscEnv)
|
|
5662
|
+
);
|
|
5663
|
+
timedSync(
|
|
5664
|
+
debugDiscovery,
|
|
5665
|
+
"build writeRouteTypesFiles",
|
|
5666
|
+
() => writeRouteTypesFiles(s)
|
|
5667
|
+
);
|
|
4771
5668
|
} catch (err) {
|
|
4772
5669
|
const sourceFile = err.stack?.split("\n").find(
|
|
4773
5670
|
(line) => line.includes(s.projectRoot) && !line.includes("node_modules")
|
|
@@ -4786,8 +5683,17 @@ ${details}`
|
|
|
4786
5683
|
} finally {
|
|
4787
5684
|
delete globalThis.__rscRouterDiscoveryActive;
|
|
4788
5685
|
if (tempServer) {
|
|
4789
|
-
await
|
|
5686
|
+
await timed(
|
|
5687
|
+
debugDiscovery,
|
|
5688
|
+
"build tempServer.close",
|
|
5689
|
+
() => tempServer.close()
|
|
5690
|
+
);
|
|
4790
5691
|
}
|
|
5692
|
+
await releaseBuildEnv(s);
|
|
5693
|
+
debugDiscovery?.(
|
|
5694
|
+
"build discovery done (%sms)",
|
|
5695
|
+
(performance.now() - buildStartTime).toFixed(1)
|
|
5696
|
+
);
|
|
4791
5697
|
}
|
|
4792
5698
|
},
|
|
4793
5699
|
// Virtual module: provides the pre-generated route manifest as a JS module
|
|
@@ -4804,17 +5710,36 @@ ${details}`
|
|
|
4804
5710
|
async load(id) {
|
|
4805
5711
|
if (id === "\0" + VIRTUAL_ROUTES_MANIFEST_ID) {
|
|
4806
5712
|
if (s.discoveryDone) {
|
|
4807
|
-
await
|
|
5713
|
+
await timed(
|
|
5714
|
+
debugRoutes,
|
|
5715
|
+
"await discoveryDone (manifest)",
|
|
5716
|
+
() => s.discoveryDone
|
|
5717
|
+
);
|
|
4808
5718
|
}
|
|
4809
|
-
|
|
5719
|
+
const code = await timed(
|
|
5720
|
+
debugRoutes,
|
|
5721
|
+
"generateRoutesManifestModule",
|
|
5722
|
+
() => generateRoutesManifestModule(s)
|
|
5723
|
+
);
|
|
5724
|
+
debugRoutes?.("manifest module emitted (%d bytes)", code?.length ?? 0);
|
|
5725
|
+
return code;
|
|
4810
5726
|
}
|
|
4811
5727
|
const perRouterPrefix = "\0" + VIRTUAL_ROUTES_MANIFEST_ID + "/";
|
|
4812
5728
|
if (id.startsWith(perRouterPrefix)) {
|
|
4813
5729
|
if (s.discoveryDone) {
|
|
4814
|
-
await
|
|
5730
|
+
await timed(
|
|
5731
|
+
debugRoutes,
|
|
5732
|
+
"await discoveryDone (per-router)",
|
|
5733
|
+
() => s.discoveryDone
|
|
5734
|
+
);
|
|
4815
5735
|
}
|
|
4816
5736
|
const routerId = id.slice(perRouterPrefix.length);
|
|
4817
|
-
|
|
5737
|
+
const code = await timed(
|
|
5738
|
+
debugRoutes,
|
|
5739
|
+
`generatePerRouterModule ${routerId}`,
|
|
5740
|
+
() => generatePerRouterModule(s, routerId)
|
|
5741
|
+
);
|
|
5742
|
+
return code;
|
|
4818
5743
|
}
|
|
4819
5744
|
return null;
|
|
4820
5745
|
},
|
|
@@ -4822,28 +5747,44 @@ ${details}`
|
|
|
4822
5747
|
// Used by closeBundle for handler code eviction and prerender data injection.
|
|
4823
5748
|
generateBundle(_options, bundle) {
|
|
4824
5749
|
if (this.environment?.name !== "rsc") return;
|
|
5750
|
+
const genStart = debugBuild ? performance.now() : 0;
|
|
4825
5751
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
4826
5752
|
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
4827
5753
|
s.rscEntryFileName = fileName;
|
|
4828
5754
|
break;
|
|
4829
5755
|
}
|
|
4830
5756
|
}
|
|
4831
|
-
if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size)
|
|
5757
|
+
if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size) {
|
|
5758
|
+
debugBuild?.(
|
|
5759
|
+
"generateBundle (rsc): no handlers to scan (%sms)",
|
|
5760
|
+
(performance.now() - genStart).toFixed(1)
|
|
5761
|
+
);
|
|
4832
5762
|
return;
|
|
5763
|
+
}
|
|
5764
|
+
s.handlerChunkInfoMap.clear();
|
|
5765
|
+
s.staticHandlerChunkInfoMap.clear();
|
|
4833
5766
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
4834
5767
|
if (chunk.type !== "chunk") continue;
|
|
4835
|
-
if (
|
|
5768
|
+
if (s.resolvedPrerenderModules?.size) {
|
|
4836
5769
|
const handlers = extractHandlerExportsFromChunk(
|
|
4837
5770
|
chunk.code,
|
|
4838
5771
|
s.resolvedPrerenderModules,
|
|
4839
5772
|
"Prerender",
|
|
4840
|
-
|
|
5773
|
+
false
|
|
4841
5774
|
);
|
|
4842
5775
|
if (handlers.length > 0) {
|
|
4843
|
-
|
|
5776
|
+
const existing = s.handlerChunkInfoMap.get(fileName);
|
|
5777
|
+
if (existing) {
|
|
5778
|
+
existing.exports.push(...handlers);
|
|
5779
|
+
} else {
|
|
5780
|
+
s.handlerChunkInfoMap.set(fileName, {
|
|
5781
|
+
fileName,
|
|
5782
|
+
exports: handlers
|
|
5783
|
+
});
|
|
5784
|
+
}
|
|
4844
5785
|
}
|
|
4845
5786
|
}
|
|
4846
|
-
if (
|
|
5787
|
+
if (s.resolvedStaticModules?.size) {
|
|
4847
5788
|
const handlers = extractHandlerExportsFromChunk(
|
|
4848
5789
|
chunk.code,
|
|
4849
5790
|
s.resolvedStaticModules,
|
|
@@ -4851,10 +5792,25 @@ ${details}`
|
|
|
4851
5792
|
false
|
|
4852
5793
|
);
|
|
4853
5794
|
if (handlers.length > 0) {
|
|
4854
|
-
|
|
5795
|
+
const existing = s.staticHandlerChunkInfoMap.get(fileName);
|
|
5796
|
+
if (existing) {
|
|
5797
|
+
existing.exports.push(...handlers);
|
|
5798
|
+
} else {
|
|
5799
|
+
s.staticHandlerChunkInfoMap.set(fileName, {
|
|
5800
|
+
fileName,
|
|
5801
|
+
exports: handlers
|
|
5802
|
+
});
|
|
5803
|
+
}
|
|
4855
5804
|
}
|
|
4856
5805
|
}
|
|
4857
5806
|
}
|
|
5807
|
+
debugBuild?.(
|
|
5808
|
+
"generateBundle (rsc): scanned %d chunks, %d prerender chunk(s), %d static chunk(s) (%sms)",
|
|
5809
|
+
Object.keys(bundle).length,
|
|
5810
|
+
s.handlerChunkInfoMap.size,
|
|
5811
|
+
s.staticHandlerChunkInfoMap.size,
|
|
5812
|
+
(performance.now() - genStart).toFixed(1)
|
|
5813
|
+
);
|
|
4858
5814
|
},
|
|
4859
5815
|
// Build-time pre-rendering: evict handler code and inject collected prerender data.
|
|
4860
5816
|
// Collection now happens in-process during discoverRouters() via RSC runner.
|
|
@@ -4865,21 +5821,41 @@ ${details}`
|
|
|
4865
5821
|
async handler() {
|
|
4866
5822
|
if (!s.isBuildMode) return;
|
|
4867
5823
|
if (this.environment && this.environment.name !== "rsc") return;
|
|
4868
|
-
|
|
5824
|
+
timedSync(
|
|
5825
|
+
debugBuild,
|
|
5826
|
+
"closeBundle postprocessBundle",
|
|
5827
|
+
() => postprocessBundle(s)
|
|
5828
|
+
);
|
|
4869
5829
|
}
|
|
4870
5830
|
}
|
|
4871
5831
|
};
|
|
4872
5832
|
}
|
|
4873
5833
|
|
|
4874
5834
|
// src/vite/rango.ts
|
|
5835
|
+
var debugConfig = createRangoDebugger(NS.config);
|
|
4875
5836
|
async function rango(options) {
|
|
5837
|
+
const rangoStart = performance.now();
|
|
4876
5838
|
const resolvedOptions = options ?? { preset: "node" };
|
|
4877
5839
|
const preset = resolvedOptions.preset ?? "node";
|
|
4878
5840
|
const showBanner = resolvedOptions.banner ?? true;
|
|
5841
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
4879
5842
|
const plugins = [];
|
|
4880
|
-
const rangoAliases = getPackageAliases();
|
|
4881
|
-
const excludeDeps =
|
|
4882
|
-
|
|
5843
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
5844
|
+
const excludeDeps = [
|
|
5845
|
+
...getExcludeDeps(),
|
|
5846
|
+
// plugin-rsc itself injects these into the client env's
|
|
5847
|
+
// optimizeDeps.include, which overrides exclude for the dep's own
|
|
5848
|
+
// pre-bundle entry. What exclude still controls is how *other*
|
|
5849
|
+
// pre-bundled deps treat imports of these specs (external vs inlined)
|
|
5850
|
+
// via esbuildCjsExternalPlugin. The cjs-to-esm transform in
|
|
5851
|
+
// plugins/cjs-to-esm.ts is the fallback for strict-pnpm consumers,
|
|
5852
|
+
// where client.browser's bare include fails to resolve and Vite ends up
|
|
5853
|
+
// serving the raw CJS file at dev-serve time.
|
|
5854
|
+
"@vitejs/plugin-rsc/browser",
|
|
5855
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"
|
|
5856
|
+
];
|
|
5857
|
+
const pkg = getPublishedPackageName();
|
|
5858
|
+
const nested = (spec) => `${pkg} > ${spec}`;
|
|
4883
5859
|
const routerRef = { path: void 0 };
|
|
4884
5860
|
const prerenderEnabled = true;
|
|
4885
5861
|
if (preset === "cloudflare") {
|
|
@@ -4917,7 +5893,7 @@ async function rango(options) {
|
|
|
4917
5893
|
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
4918
5894
|
// Exclude rsc-router modules to ensure same Context instance
|
|
4919
5895
|
optimizeDeps: {
|
|
4920
|
-
include: ["rsc-html-stream/client"],
|
|
5896
|
+
include: [nested("rsc-html-stream/client")],
|
|
4921
5897
|
exclude: excludeDeps,
|
|
4922
5898
|
esbuildOptions: sharedEsbuildOptions
|
|
4923
5899
|
}
|
|
@@ -4942,8 +5918,10 @@ async function rango(options) {
|
|
|
4942
5918
|
"react-dom/static.edge",
|
|
4943
5919
|
"react/jsx-runtime",
|
|
4944
5920
|
"react/jsx-dev-runtime",
|
|
4945
|
-
"rsc-html-stream/server",
|
|
4946
|
-
|
|
5921
|
+
nested("rsc-html-stream/server"),
|
|
5922
|
+
nested(
|
|
5923
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5924
|
+
)
|
|
4947
5925
|
],
|
|
4948
5926
|
exclude: excludeDeps,
|
|
4949
5927
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -4958,7 +5936,9 @@ async function rango(options) {
|
|
|
4958
5936
|
"react",
|
|
4959
5937
|
"react/jsx-runtime",
|
|
4960
5938
|
"react/jsx-dev-runtime",
|
|
4961
|
-
|
|
5939
|
+
nested(
|
|
5940
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
5941
|
+
)
|
|
4962
5942
|
],
|
|
4963
5943
|
exclude: excludeDeps,
|
|
4964
5944
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -4975,6 +5955,7 @@ async function rango(options) {
|
|
|
4975
5955
|
}
|
|
4976
5956
|
});
|
|
4977
5957
|
plugins.push(createVirtualEntriesPlugin(finalEntries));
|
|
5958
|
+
plugins.push(performanceTracksPlugin());
|
|
4978
5959
|
plugins.push(
|
|
4979
5960
|
rsc({
|
|
4980
5961
|
entries: finalEntries,
|
|
@@ -4983,153 +5964,126 @@ async function rango(options) {
|
|
|
4983
5964
|
);
|
|
4984
5965
|
plugins.push(clientRefDedup());
|
|
4985
5966
|
} else {
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
const
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
routerRef.path = (abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs).replaceAll("\\", "/");
|
|
5002
|
-
} else if (candidates.length > 1) {
|
|
5003
|
-
const list = candidates.map(
|
|
5004
|
-
(f) => " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f)
|
|
5005
|
-
).join("\n");
|
|
5006
|
-
throw new Error(
|
|
5007
|
-
`[rsc-router] Multiple routers found. Specify \`router\` to choose one:
|
|
5008
|
-
${list}`
|
|
5009
|
-
);
|
|
5010
|
-
}
|
|
5967
|
+
plugins.push({
|
|
5968
|
+
name: "@rangojs/router:auto-discover",
|
|
5969
|
+
config(userConfig) {
|
|
5970
|
+
if (routerRef.path) return;
|
|
5971
|
+
const root = userConfig.root ? resolve9(process.cwd(), userConfig.root) : process.cwd();
|
|
5972
|
+
const candidates = findRouterFiles(root);
|
|
5973
|
+
if (candidates.length === 1) {
|
|
5974
|
+
const abs = candidates[0];
|
|
5975
|
+
routerRef.path = (abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs).replaceAll("\\", "/");
|
|
5976
|
+
} else if (candidates.length > 1) {
|
|
5977
|
+
const list = candidates.map(
|
|
5978
|
+
(f) => " - " + (f.startsWith(root) ? f.slice(root.length + 1) : f)
|
|
5979
|
+
).join("\n");
|
|
5980
|
+
throw new Error(`[rsc-router] Multiple routers found:
|
|
5981
|
+
${list}`);
|
|
5011
5982
|
}
|
|
5012
|
-
}
|
|
5013
|
-
}
|
|
5014
|
-
const
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
resolve: {
|
|
5043
|
-
alias: rangoAliases
|
|
5044
|
-
},
|
|
5045
|
-
environments: {
|
|
5046
|
-
client: {
|
|
5047
|
-
build: {
|
|
5048
|
-
rollupOptions: {
|
|
5049
|
-
output: {
|
|
5050
|
-
manualChunks: getManualChunks
|
|
5051
|
-
}
|
|
5052
|
-
}
|
|
5053
|
-
},
|
|
5054
|
-
// Always exclude rsc-router modules, conditionally add virtual entry
|
|
5055
|
-
optimizeDeps: {
|
|
5056
|
-
// Pre-bundle React and rsc-html-stream to prevent late discovery
|
|
5057
|
-
// triggering ERR_OUTDATED_OPTIMIZED_DEP on cold starts
|
|
5058
|
-
include: [
|
|
5059
|
-
"react",
|
|
5060
|
-
"react-dom",
|
|
5061
|
-
"react/jsx-runtime",
|
|
5062
|
-
"react/jsx-dev-runtime",
|
|
5063
|
-
"rsc-html-stream/client"
|
|
5064
|
-
],
|
|
5065
|
-
exclude: excludeDeps,
|
|
5066
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
5067
|
-
...useVirtualClient && {
|
|
5068
|
-
// Tell Vite to scan the virtual entry for dependencies
|
|
5069
|
-
entries: [VIRTUAL_IDS.browser]
|
|
5070
|
-
}
|
|
5071
|
-
}
|
|
5072
|
-
},
|
|
5073
|
-
...useVirtualSSR && {
|
|
5074
|
-
ssr: {
|
|
5075
|
-
optimizeDeps: {
|
|
5076
|
-
entries: [VIRTUAL_IDS.ssr],
|
|
5077
|
-
// Pre-bundle all SSR deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
5078
|
-
include: [
|
|
5079
|
-
"react",
|
|
5080
|
-
"react-dom",
|
|
5081
|
-
"react-dom/server.edge",
|
|
5082
|
-
"react-dom/static.edge",
|
|
5083
|
-
"react/jsx-runtime",
|
|
5084
|
-
"react/jsx-dev-runtime",
|
|
5085
|
-
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5086
|
-
],
|
|
5087
|
-
exclude: excludeDeps,
|
|
5088
|
-
esbuildOptions: sharedEsbuildOptions
|
|
5983
|
+
}
|
|
5984
|
+
});
|
|
5985
|
+
const finalEntries = {
|
|
5986
|
+
client: VIRTUAL_IDS.browser,
|
|
5987
|
+
ssr: VIRTUAL_IDS.ssr,
|
|
5988
|
+
rsc: VIRTUAL_IDS.rsc
|
|
5989
|
+
};
|
|
5990
|
+
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
5991
|
+
let hasWarnedDuplicate = false;
|
|
5992
|
+
plugins.push({
|
|
5993
|
+
name: "@rangojs/router:rsc-integration",
|
|
5994
|
+
enforce: "pre",
|
|
5995
|
+
config() {
|
|
5996
|
+
return {
|
|
5997
|
+
optimizeDeps: {
|
|
5998
|
+
exclude: excludeDeps,
|
|
5999
|
+
esbuildOptions: sharedEsbuildOptions
|
|
6000
|
+
},
|
|
6001
|
+
build: {
|
|
6002
|
+
rollupOptions: { onwarn }
|
|
6003
|
+
},
|
|
6004
|
+
resolve: {
|
|
6005
|
+
alias: rangoAliases
|
|
6006
|
+
},
|
|
6007
|
+
environments: {
|
|
6008
|
+
client: {
|
|
6009
|
+
build: {
|
|
6010
|
+
rollupOptions: {
|
|
6011
|
+
output: {
|
|
6012
|
+
manualChunks: getManualChunks
|
|
5089
6013
|
}
|
|
5090
6014
|
}
|
|
5091
6015
|
},
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
6016
|
+
optimizeDeps: {
|
|
6017
|
+
include: [
|
|
6018
|
+
"react",
|
|
6019
|
+
"react-dom",
|
|
6020
|
+
"react/jsx-runtime",
|
|
6021
|
+
"react/jsx-dev-runtime",
|
|
6022
|
+
nested("rsc-html-stream/client")
|
|
6023
|
+
],
|
|
6024
|
+
exclude: excludeDeps,
|
|
6025
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
6026
|
+
entries: [VIRTUAL_IDS.browser]
|
|
6027
|
+
}
|
|
6028
|
+
},
|
|
6029
|
+
ssr: {
|
|
6030
|
+
optimizeDeps: {
|
|
6031
|
+
entries: [VIRTUAL_IDS.ssr],
|
|
6032
|
+
include: [
|
|
6033
|
+
"react",
|
|
6034
|
+
"react-dom",
|
|
6035
|
+
"react-dom/server.edge",
|
|
6036
|
+
"react-dom/static.edge",
|
|
6037
|
+
"react/jsx-runtime",
|
|
6038
|
+
"react/jsx-dev-runtime",
|
|
6039
|
+
nested(
|
|
6040
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
6041
|
+
)
|
|
6042
|
+
],
|
|
6043
|
+
exclude: excludeDeps,
|
|
6044
|
+
esbuildOptions: sharedEsbuildOptions
|
|
6045
|
+
}
|
|
6046
|
+
},
|
|
6047
|
+
rsc: {
|
|
6048
|
+
optimizeDeps: {
|
|
6049
|
+
entries: [VIRTUAL_IDS.rsc],
|
|
6050
|
+
include: [
|
|
6051
|
+
"react",
|
|
6052
|
+
"react/jsx-runtime",
|
|
6053
|
+
"react/jsx-dev-runtime",
|
|
6054
|
+
nested(
|
|
6055
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
6056
|
+
)
|
|
6057
|
+
],
|
|
6058
|
+
esbuildOptions: sharedEsbuildOptions
|
|
5106
6059
|
}
|
|
5107
6060
|
}
|
|
5108
|
-
};
|
|
5109
|
-
},
|
|
5110
|
-
configResolved(config) {
|
|
5111
|
-
if (showBanner) {
|
|
5112
|
-
const mode = config.command === "serve" ? process.argv.includes("preview") ? "preview" : "dev" : "build";
|
|
5113
|
-
printBanner(mode, "node", rangoVersion);
|
|
5114
|
-
}
|
|
5115
|
-
const rscMinimalCount = config.plugins.filter(
|
|
5116
|
-
(p) => p.name === "rsc:minimal"
|
|
5117
|
-
).length;
|
|
5118
|
-
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
5119
|
-
hasWarnedDuplicate = true;
|
|
5120
|
-
console.warn(
|
|
5121
|
-
"[rsc-router] Duplicate @vitejs/plugin-rsc detected. Remove rsc() from your config or use rango({ rsc: false }) for manual configuration."
|
|
5122
|
-
);
|
|
5123
6061
|
}
|
|
6062
|
+
};
|
|
6063
|
+
},
|
|
6064
|
+
configResolved(config) {
|
|
6065
|
+
if (showBanner) {
|
|
6066
|
+
const mode = config.command === "serve" ? process.argv.includes("preview") ? "preview" : "dev" : "build";
|
|
6067
|
+
printBanner(mode, "node", rangoVersion);
|
|
5124
6068
|
}
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
6069
|
+
const rscMinimalCount = config.plugins.filter(
|
|
6070
|
+
(p) => p.name === "rsc:minimal"
|
|
6071
|
+
).length;
|
|
6072
|
+
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
6073
|
+
hasWarnedDuplicate = true;
|
|
6074
|
+
console.warn(
|
|
6075
|
+
"[rsc-router] Duplicate @vitejs/plugin-rsc detected. Remove rsc() from your vite config \u2014 rango() includes it automatically."
|
|
6076
|
+
);
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
});
|
|
6080
|
+
plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
|
|
6081
|
+
plugins.push(performanceTracksPlugin());
|
|
6082
|
+
plugins.push(
|
|
6083
|
+
rsc({
|
|
6084
|
+
entries: finalEntries
|
|
6085
|
+
})
|
|
6086
|
+
);
|
|
5133
6087
|
plugins.push(clientRefDedup());
|
|
5134
6088
|
}
|
|
5135
6089
|
plugins.push({
|
|
@@ -5157,20 +6111,24 @@ ${list}`
|
|
|
5157
6111
|
plugins.push(createVersionPlugin());
|
|
5158
6112
|
const discoveryEntryPath = preset !== "cloudflare" ? routerRef.path : void 0;
|
|
5159
6113
|
const discoveryRouterRef = preset !== "cloudflare" ? routerRef : void 0;
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
plugins.push(createVersionInjectorPlugin(injectorEntryPath));
|
|
6114
|
+
if (preset === "cloudflare") {
|
|
6115
|
+
plugins.push(createVersionInjectorPlugin(void 0));
|
|
5163
6116
|
}
|
|
5164
6117
|
plugins.push(createCjsToEsmPlugin());
|
|
5165
6118
|
plugins.push(
|
|
5166
6119
|
createRouterDiscoveryPlugin(discoveryEntryPath, {
|
|
5167
6120
|
routerPathRef: discoveryRouterRef,
|
|
5168
6121
|
enableBuildPrerender: prerenderEnabled,
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
exclude: resolvedOptions.exclude
|
|
6122
|
+
buildEnv: options?.buildEnv,
|
|
6123
|
+
preset
|
|
5172
6124
|
})
|
|
5173
6125
|
);
|
|
6126
|
+
debugConfig?.(
|
|
6127
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
6128
|
+
preset,
|
|
6129
|
+
plugins.length,
|
|
6130
|
+
(performance.now() - rangoStart).toFixed(1)
|
|
6131
|
+
);
|
|
5174
6132
|
return plugins;
|
|
5175
6133
|
}
|
|
5176
6134
|
|
|
@@ -5181,29 +6139,75 @@ function poke() {
|
|
|
5181
6139
|
apply: "serve",
|
|
5182
6140
|
configureServer(server) {
|
|
5183
6141
|
const stdin = process.stdin;
|
|
5184
|
-
const
|
|
6142
|
+
const debug11 = process.env.RANGO_POKE_DEBUG === "1";
|
|
6143
|
+
const triggerReload = (source) => {
|
|
6144
|
+
server.hot.send({ type: "full-reload", path: "*" });
|
|
6145
|
+
server.config.logger.info(` browser reload (${source})`, {
|
|
6146
|
+
timestamp: true
|
|
6147
|
+
});
|
|
6148
|
+
};
|
|
6149
|
+
const toBuffer = (chunk) => {
|
|
6150
|
+
return typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
6151
|
+
};
|
|
6152
|
+
const formatChunk = (chunk) => {
|
|
6153
|
+
const data = toBuffer(chunk);
|
|
6154
|
+
const hex = Array.from(data).map((byte) => `0x${byte.toString(16).padStart(2, "0")}`).join(" ");
|
|
6155
|
+
const ascii = Array.from(data).map((byte) => {
|
|
6156
|
+
if (byte >= 32 && byte <= 126) return String.fromCharCode(byte);
|
|
6157
|
+
if (byte === 10) return "\\n";
|
|
6158
|
+
if (byte === 13) return "\\r";
|
|
6159
|
+
if (byte === 9) return "\\t";
|
|
6160
|
+
return ".";
|
|
6161
|
+
}).join("");
|
|
6162
|
+
return `len=${data.length} hex=[${hex}] ascii="${ascii}"`;
|
|
6163
|
+
};
|
|
6164
|
+
const readCtrlR = (chunk) => {
|
|
6165
|
+
const data = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
6166
|
+
return data.length === 1 && data[0] === 18;
|
|
6167
|
+
};
|
|
6168
|
+
const readSubmittedCommands = (chunk) => {
|
|
6169
|
+
const text = toBuffer(chunk).toString("utf8").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
6170
|
+
if (!text.includes("\n")) return [];
|
|
6171
|
+
const lines = text.split("\n");
|
|
6172
|
+
lines.pop();
|
|
6173
|
+
return lines;
|
|
6174
|
+
};
|
|
6175
|
+
if (debug11) {
|
|
6176
|
+
server.config.logger.info(
|
|
6177
|
+
` poke debug enabled (isTTY=${stdin.isTTY ? "yes" : "no"}, isRaw=${stdin.isTTY ? stdin.isRaw ? "yes" : "no" : "n/a"})`,
|
|
6178
|
+
{ timestamp: true }
|
|
6179
|
+
);
|
|
6180
|
+
}
|
|
5185
6181
|
if (stdin.isTTY) {
|
|
5186
|
-
|
|
6182
|
+
server.config.logger.info(
|
|
6183
|
+
" poke ready: press e + enter to reload browser (ctrl+r also works when available)",
|
|
6184
|
+
{ timestamp: true }
|
|
6185
|
+
);
|
|
5187
6186
|
}
|
|
5188
6187
|
const onData = (data) => {
|
|
5189
|
-
if (
|
|
5190
|
-
|
|
5191
|
-
process.emit("SIGINT", "SIGINT");
|
|
5192
|
-
return;
|
|
5193
|
-
}
|
|
5194
|
-
if (data[0] === 18) {
|
|
5195
|
-
server.hot.send({ type: "full-reload", path: "*" });
|
|
5196
|
-
server.config.logger.info(" browser reload (ctrl+r)", {
|
|
6188
|
+
if (debug11) {
|
|
6189
|
+
server.config.logger.info(` poke stdin ${formatChunk(data)}`, {
|
|
5197
6190
|
timestamp: true
|
|
5198
6191
|
});
|
|
5199
6192
|
}
|
|
6193
|
+
if (readCtrlR(data)) {
|
|
6194
|
+
triggerReload("ctrl+r");
|
|
6195
|
+
return;
|
|
6196
|
+
}
|
|
6197
|
+
for (const command of readSubmittedCommands(data)) {
|
|
6198
|
+
if (command === "e") {
|
|
6199
|
+
triggerReload("e+enter");
|
|
6200
|
+
return;
|
|
6201
|
+
}
|
|
6202
|
+
if (command === "\x1Br") {
|
|
6203
|
+
triggerReload("option+r+enter");
|
|
6204
|
+
return;
|
|
6205
|
+
}
|
|
6206
|
+
}
|
|
5200
6207
|
};
|
|
5201
6208
|
stdin.on("data", onData);
|
|
5202
6209
|
server.httpServer?.on("close", () => {
|
|
5203
6210
|
stdin.off("data", onData);
|
|
5204
|
-
if (stdin.isTTY && previousRawMode !== null) {
|
|
5205
|
-
stdin.setRawMode(previousRawMode);
|
|
5206
|
-
}
|
|
5207
6211
|
});
|
|
5208
6212
|
}
|
|
5209
6213
|
};
|