@rangojs/router 0.0.0-experimental.ede38110 → 0.0.0-experimental.f2d1a2f1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -20
- package/dist/vite/index.js +353 -49
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +5 -3
- package/skills/breadcrumbs/SKILL.md +3 -1
- package/skills/hooks/SKILL.md +28 -20
- package/skills/links/SKILL.md +88 -16
- package/skills/loader/SKILL.md +35 -2
- package/skills/migrate-react-router/SKILL.md +1 -0
- package/skills/response-routes/SKILL.md +8 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/typesafety/SKILL.md +3 -1
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/navigation-bridge.ts +51 -2
- package/src/browser/navigation-client.ts +33 -10
- package/src/browser/navigation-store.ts +25 -1
- package/src/browser/partial-update.ts +20 -1
- package/src/browser/prefetch/cache.ts +124 -26
- package/src/browser/prefetch/fetch.ts +114 -38
- package/src/browser/prefetch/queue.ts +36 -5
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +18 -13
- package/src/browser/react/NavigationProvider.tsx +50 -11
- package/src/browser/react/use-navigation.ts +30 -11
- package/src/browser/react/use-params.ts +11 -1
- package/src/browser/react/use-router.ts +8 -1
- package/src/browser/rsc-router.tsx +34 -6
- package/src/browser/types.ts +13 -0
- package/src/cache/cf/cf-cache-store.ts +5 -7
- package/src/index.rsc.ts +3 -0
- package/src/index.ts +3 -0
- package/src/outlet-context.ts +1 -1
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +3 -2
- package/src/route-definition/dsl-helpers.ts +16 -3
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/router/handler-context.ts +20 -3
- package/src/router/lazy-includes.ts +1 -1
- package/src/router/loader-resolution.ts +3 -0
- package/src/router/match-api.ts +3 -3
- package/src/router/middleware-types.ts +2 -22
- package/src/router/middleware.ts +32 -4
- package/src/router/pattern-matching.ts +60 -9
- package/src/router/trie-matching.ts +10 -4
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +1 -2
- package/src/rsc/handler.ts +8 -4
- package/src/rsc/helpers.ts +69 -41
- package/src/rsc/progressive-enhancement.ts +2 -0
- package/src/rsc/response-route-handler.ts +14 -1
- package/src/rsc/rsc-rendering.ts +7 -0
- package/src/rsc/server-action.ts +2 -0
- package/src/server/request-context.ts +10 -42
- package/src/types/handler-context.ts +2 -34
- package/src/types/loader-types.ts +5 -6
- package/src/types/request-scope.ts +126 -0
- package/src/urls/response-types.ts +2 -10
- package/src/vite/debug.ts +86 -0
- 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/performance-tracks.ts +4 -6
- package/src/vite/rango.ts +49 -14
- package/src/vite/router-discovery.ts +161 -23
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/package-resolution.ts +41 -1
package/dist/vite/index.js
CHANGED
|
@@ -1859,12 +1859,13 @@ function getVirtualVersionContent(version) {
|
|
|
1859
1859
|
|
|
1860
1860
|
// src/vite/utils/package-resolution.ts
|
|
1861
1861
|
import { existsSync } from "node:fs";
|
|
1862
|
+
import { createRequire } from "node:module";
|
|
1862
1863
|
import { resolve } from "node:path";
|
|
1863
1864
|
|
|
1864
1865
|
// package.json
|
|
1865
1866
|
var package_default = {
|
|
1866
1867
|
name: "@rangojs/router",
|
|
1867
|
-
version: "0.0.0-experimental.
|
|
1868
|
+
version: "0.0.0-experimental.f2d1a2f1",
|
|
1868
1869
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1869
1870
|
keywords: [
|
|
1870
1871
|
"react",
|
|
@@ -1997,9 +1998,9 @@ var package_default = {
|
|
|
1997
1998
|
tag: "experimental"
|
|
1998
1999
|
},
|
|
1999
2000
|
scripts: {
|
|
2000
|
-
build: "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
2001
|
+
build: "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
2001
2002
|
prepublishOnly: "pnpm build",
|
|
2002
|
-
typecheck: "tsc --noEmit",
|
|
2003
|
+
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit",
|
|
2003
2004
|
test: "playwright test",
|
|
2004
2005
|
"test:ui": "playwright test --ui",
|
|
2005
2006
|
"test:unit": "vitest run",
|
|
@@ -2007,12 +2008,14 @@ var package_default = {
|
|
|
2007
2008
|
},
|
|
2008
2009
|
dependencies: {
|
|
2009
2010
|
"@vitejs/plugin-rsc": "^0.5.23",
|
|
2011
|
+
debug: "^4.4.1",
|
|
2010
2012
|
"magic-string": "^0.30.17",
|
|
2011
2013
|
picomatch: "^4.0.3",
|
|
2012
2014
|
"rsc-html-stream": "^0.0.7"
|
|
2013
2015
|
},
|
|
2014
2016
|
devDependencies: {
|
|
2015
2017
|
"@playwright/test": "^1.49.1",
|
|
2018
|
+
"@types/debug": "^4.1.12",
|
|
2016
2019
|
"@types/node": "^24.10.1",
|
|
2017
2020
|
"@types/react": "catalog:",
|
|
2018
2021
|
"@types/react-dom": "catalog:",
|
|
@@ -2041,6 +2044,7 @@ var package_default = {
|
|
|
2041
2044
|
};
|
|
2042
2045
|
|
|
2043
2046
|
// src/vite/utils/package-resolution.ts
|
|
2047
|
+
var require2 = createRequire(import.meta.url);
|
|
2044
2048
|
var VIRTUAL_PACKAGE_NAME = "@rangojs/router";
|
|
2045
2049
|
function getPublishedPackageName() {
|
|
2046
2050
|
return package_default.name;
|
|
@@ -2081,6 +2085,20 @@ function getPackageAliases() {
|
|
|
2081
2085
|
}
|
|
2082
2086
|
return aliases;
|
|
2083
2087
|
}
|
|
2088
|
+
function getVendorAliases() {
|
|
2089
|
+
const specs = [
|
|
2090
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
2091
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
2092
|
+
];
|
|
2093
|
+
const aliases = {};
|
|
2094
|
+
for (const spec of specs) {
|
|
2095
|
+
try {
|
|
2096
|
+
aliases[spec] = require2.resolve(spec);
|
|
2097
|
+
} catch {
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
return aliases;
|
|
2101
|
+
}
|
|
2084
2102
|
|
|
2085
2103
|
// src/build/route-types/param-extraction.ts
|
|
2086
2104
|
function extractParamsFromPattern(pattern) {
|
|
@@ -2978,6 +2996,41 @@ import * as Vite from "vite";
|
|
|
2978
2996
|
|
|
2979
2997
|
// src/vite/plugins/performance-tracks.ts
|
|
2980
2998
|
import { readFile } from "node:fs/promises";
|
|
2999
|
+
|
|
3000
|
+
// src/vite/debug.ts
|
|
3001
|
+
import debugFactory from "debug";
|
|
3002
|
+
if (process.env.INTERNAL_RANGO_DEBUG) {
|
|
3003
|
+
const existing = debugFactory.disable();
|
|
3004
|
+
debugFactory.enable(existing ? `${existing},rango:*` : "rango:*");
|
|
3005
|
+
}
|
|
3006
|
+
function createRangoDebugger(namespace) {
|
|
3007
|
+
const primary = debugFactory(namespace);
|
|
3008
|
+
const shadow = debugFactory(`vite:${namespace}`);
|
|
3009
|
+
if (primary.enabled) return primary;
|
|
3010
|
+
if (shadow.enabled) return shadow;
|
|
3011
|
+
return void 0;
|
|
3012
|
+
}
|
|
3013
|
+
async function timed(debug2, label, fn) {
|
|
3014
|
+
if (!debug2) return await fn();
|
|
3015
|
+
const start = performance.now();
|
|
3016
|
+
try {
|
|
3017
|
+
return await fn();
|
|
3018
|
+
} finally {
|
|
3019
|
+
debug2("%s (%sms)", label, (performance.now() - start).toFixed(1));
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
function timedSync(debug2, label, fn) {
|
|
3023
|
+
if (!debug2) return fn();
|
|
3024
|
+
const start = performance.now();
|
|
3025
|
+
try {
|
|
3026
|
+
return fn();
|
|
3027
|
+
} finally {
|
|
3028
|
+
debug2("%s (%sms)", label, (performance.now() - start).toFixed(1));
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
// src/vite/plugins/performance-tracks.ts
|
|
3033
|
+
var debug = createRangoDebugger("rango:transform");
|
|
2981
3034
|
var RSDW_PATCH_RE = /((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
2982
3035
|
function buildPatchReplacement(match, debugInfoVar) {
|
|
2983
3036
|
return `${match}
|
|
@@ -3025,12 +3078,7 @@ function performanceTracksPlugin() {
|
|
|
3025
3078
|
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
3026
3079
|
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
3027
3080
|
if (!patched.debugInfoVar) return;
|
|
3028
|
-
|
|
3029
|
-
console.log(
|
|
3030
|
-
"[perf-tracks] patched RSDW client (var:",
|
|
3031
|
-
patched.debugInfoVar,
|
|
3032
|
-
")"
|
|
3033
|
-
);
|
|
3081
|
+
debug?.("patched RSDW client (var: %s)", patched.debugInfoVar);
|
|
3034
3082
|
return patched.code;
|
|
3035
3083
|
}
|
|
3036
3084
|
};
|
|
@@ -3260,7 +3308,7 @@ function createCjsToEsmPlugin() {
|
|
|
3260
3308
|
import { createServer as createViteServer } from "vite";
|
|
3261
3309
|
import { resolve as resolve8 } from "node:path";
|
|
3262
3310
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
3263
|
-
import { createRequire } from "node:module";
|
|
3311
|
+
import { createRequire as createRequire2, register } from "node:module";
|
|
3264
3312
|
import { pathToFileURL } from "node:url";
|
|
3265
3313
|
|
|
3266
3314
|
// src/vite/plugins/virtual-stub-plugin.ts
|
|
@@ -3287,6 +3335,113 @@ function createVirtualStubPlugin() {
|
|
|
3287
3335
|
};
|
|
3288
3336
|
}
|
|
3289
3337
|
|
|
3338
|
+
// src/vite/plugins/cloudflare-protocol-stub.ts
|
|
3339
|
+
var VIRTUAL_PREFIX = "virtual:rango-cloudflare-stub-";
|
|
3340
|
+
var NULL_PREFIX = "\0" + VIRTUAL_PREFIX;
|
|
3341
|
+
var CF_PREFIX = "cloudflare:";
|
|
3342
|
+
var BUILD_ENV_GLOBAL_KEY = "__rango_build_env__";
|
|
3343
|
+
var SOURCE_EXT_RE = /\.[mc]?[jt]sx?$/;
|
|
3344
|
+
var IMPORT_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
3345
|
+
"ImportDeclaration",
|
|
3346
|
+
"ImportExpression",
|
|
3347
|
+
"ExportNamedDeclaration",
|
|
3348
|
+
"ExportAllDeclaration"
|
|
3349
|
+
]);
|
|
3350
|
+
var STUBS = {
|
|
3351
|
+
"cloudflare:workers": `
|
|
3352
|
+
export class DurableObject { constructor(_ctx, _env) {} }
|
|
3353
|
+
export class WorkerEntrypoint { constructor(_ctx, _env) {} }
|
|
3354
|
+
export class WorkflowEntrypoint { constructor(_ctx, _env) {} }
|
|
3355
|
+
export class RpcTarget {}
|
|
3356
|
+
export const env = globalThis[${JSON.stringify(BUILD_ENV_GLOBAL_KEY)}] ?? {};
|
|
3357
|
+
export default {};
|
|
3358
|
+
`,
|
|
3359
|
+
"cloudflare:email": `
|
|
3360
|
+
export class EmailMessage { constructor(_from, _to, _raw) {} }
|
|
3361
|
+
export default {};
|
|
3362
|
+
`,
|
|
3363
|
+
"cloudflare:sockets": `
|
|
3364
|
+
export function connect() { return {}; }
|
|
3365
|
+
export default {};
|
|
3366
|
+
`,
|
|
3367
|
+
"cloudflare:workflows": `
|
|
3368
|
+
export class NonRetryableError extends Error {
|
|
3369
|
+
constructor(message, name) { super(message); this.name = name ?? "NonRetryableError"; }
|
|
3370
|
+
}
|
|
3371
|
+
export default {};
|
|
3372
|
+
`
|
|
3373
|
+
};
|
|
3374
|
+
var FALLBACK_STUB = `export default {};
|
|
3375
|
+
`;
|
|
3376
|
+
function createCloudflareProtocolStubPlugin() {
|
|
3377
|
+
return {
|
|
3378
|
+
name: "@rangojs/router:cloudflare-protocol-stub",
|
|
3379
|
+
transform(code, id) {
|
|
3380
|
+
const cleanId = id.split("?")[0] ?? id;
|
|
3381
|
+
if (!SOURCE_EXT_RE.test(cleanId)) return null;
|
|
3382
|
+
if (!code.includes(CF_PREFIX)) return null;
|
|
3383
|
+
let ast;
|
|
3384
|
+
try {
|
|
3385
|
+
ast = this.parse(code);
|
|
3386
|
+
} catch {
|
|
3387
|
+
return null;
|
|
3388
|
+
}
|
|
3389
|
+
const hits = [];
|
|
3390
|
+
walk(ast, (node) => {
|
|
3391
|
+
if (!IMPORT_NODE_TYPES.has(node.type)) return;
|
|
3392
|
+
const source = node.source;
|
|
3393
|
+
if (!source || source.type !== "Literal") return;
|
|
3394
|
+
if (typeof source.value !== "string") return;
|
|
3395
|
+
if (!source.value.startsWith(CF_PREFIX)) return;
|
|
3396
|
+
if (typeof source.start !== "number" || typeof source.end !== "number")
|
|
3397
|
+
return;
|
|
3398
|
+
hits.push({
|
|
3399
|
+
start: source.start,
|
|
3400
|
+
end: source.end,
|
|
3401
|
+
value: source.value
|
|
3402
|
+
});
|
|
3403
|
+
});
|
|
3404
|
+
if (hits.length === 0) return null;
|
|
3405
|
+
hits.sort((a, b) => b.start - a.start);
|
|
3406
|
+
let out = code;
|
|
3407
|
+
for (const hit of hits) {
|
|
3408
|
+
const submodule = hit.value.slice(CF_PREFIX.length);
|
|
3409
|
+
const quote = code[hit.start] === "'" ? "'" : '"';
|
|
3410
|
+
out = out.slice(0, hit.start) + quote + VIRTUAL_PREFIX + submodule + quote + out.slice(hit.end);
|
|
3411
|
+
}
|
|
3412
|
+
return { code: out, map: null };
|
|
3413
|
+
},
|
|
3414
|
+
resolveId(id) {
|
|
3415
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
3416
|
+
return "\0" + id;
|
|
3417
|
+
}
|
|
3418
|
+
return null;
|
|
3419
|
+
},
|
|
3420
|
+
load(id) {
|
|
3421
|
+
if (!id.startsWith(NULL_PREFIX)) return null;
|
|
3422
|
+
const submodule = id.slice(NULL_PREFIX.length);
|
|
3423
|
+
const specifier = CF_PREFIX + submodule;
|
|
3424
|
+
return STUBS[specifier] ?? FALLBACK_STUB;
|
|
3425
|
+
}
|
|
3426
|
+
};
|
|
3427
|
+
}
|
|
3428
|
+
function walk(node, visit) {
|
|
3429
|
+
if (!node || typeof node !== "object") return;
|
|
3430
|
+
if (Array.isArray(node)) {
|
|
3431
|
+
for (const child of node) walk(child, visit);
|
|
3432
|
+
return;
|
|
3433
|
+
}
|
|
3434
|
+
const n = node;
|
|
3435
|
+
if (typeof n.type !== "string") return;
|
|
3436
|
+
visit(n);
|
|
3437
|
+
for (const key in n) {
|
|
3438
|
+
if (key === "loc" || key === "start" || key === "end" || key === "range") {
|
|
3439
|
+
continue;
|
|
3440
|
+
}
|
|
3441
|
+
walk(n[key], visit);
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
|
|
3290
3445
|
// src/vite/plugins/client-ref-hashing.ts
|
|
3291
3446
|
import { relative } from "node:path";
|
|
3292
3447
|
import { createHash as createHash2 } from "node:crypto";
|
|
@@ -4682,7 +4837,24 @@ function postprocessBundle(state) {
|
|
|
4682
4837
|
}
|
|
4683
4838
|
|
|
4684
4839
|
// src/vite/router-discovery.ts
|
|
4840
|
+
var debugDiscovery = createRangoDebugger("rango:discovery");
|
|
4841
|
+
var debugRoutes = createRangoDebugger("rango:routes");
|
|
4842
|
+
var loaderHookRegistered = false;
|
|
4843
|
+
function ensureCloudflareProtocolLoaderRegistered() {
|
|
4844
|
+
if (loaderHookRegistered) return;
|
|
4845
|
+
loaderHookRegistered = true;
|
|
4846
|
+
try {
|
|
4847
|
+
register(
|
|
4848
|
+
new URL("./plugins/cloudflare-protocol-loader-hook.mjs", import.meta.url)
|
|
4849
|
+
);
|
|
4850
|
+
} catch (err) {
|
|
4851
|
+
console.warn(
|
|
4852
|
+
`[rsc-router] Could not register Node ESM loader hook for cloudflare:* imports (${err?.message ?? err}). Falling back to Vite transform only.`
|
|
4853
|
+
);
|
|
4854
|
+
}
|
|
4855
|
+
}
|
|
4685
4856
|
async function createTempRscServer(state, options = {}) {
|
|
4857
|
+
ensureCloudflareProtocolLoaderRegistered();
|
|
4686
4858
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
4687
4859
|
return createViteServer({
|
|
4688
4860
|
root: state.projectRoot,
|
|
@@ -4705,6 +4877,7 @@ async function createTempRscServer(state, options = {}) {
|
|
|
4705
4877
|
...options.forceBuild ? [hashClientRefs(state.projectRoot)] : [],
|
|
4706
4878
|
createVersionPlugin(),
|
|
4707
4879
|
createVirtualStubPlugin(),
|
|
4880
|
+
createCloudflareProtocolStubPlugin(),
|
|
4708
4881
|
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
4709
4882
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
4710
4883
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : void 0),
|
|
@@ -4721,7 +4894,7 @@ async function resolveBuildEnv(option, factoryCtx) {
|
|
|
4721
4894
|
);
|
|
4722
4895
|
}
|
|
4723
4896
|
try {
|
|
4724
|
-
const userRequire =
|
|
4897
|
+
const userRequire = createRequire2(
|
|
4725
4898
|
resolve8(factoryCtx.root, "package.json")
|
|
4726
4899
|
);
|
|
4727
4900
|
const wranglerPath = userRequire.resolve("wrangler");
|
|
@@ -4756,6 +4929,7 @@ async function acquireBuildEnv(s, command, mode) {
|
|
|
4756
4929
|
if (!result) return false;
|
|
4757
4930
|
s.resolvedBuildEnv = result.env;
|
|
4758
4931
|
s.buildEnvDispose = result.dispose ?? null;
|
|
4932
|
+
globalThis[BUILD_ENV_GLOBAL_KEY] = result.env;
|
|
4759
4933
|
return true;
|
|
4760
4934
|
}
|
|
4761
4935
|
async function releaseBuildEnv(s) {
|
|
@@ -4768,6 +4942,7 @@ async function releaseBuildEnv(s) {
|
|
|
4768
4942
|
s.buildEnvDispose = null;
|
|
4769
4943
|
}
|
|
4770
4944
|
s.resolvedBuildEnv = void 0;
|
|
4945
|
+
delete globalThis[BUILD_ENV_GLOBAL_KEY];
|
|
4771
4946
|
}
|
|
4772
4947
|
function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
4773
4948
|
const s = createDiscoveryState(entryPath, opts);
|
|
@@ -4860,15 +5035,33 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4860
5035
|
return null;
|
|
4861
5036
|
}
|
|
4862
5037
|
const discover = async () => {
|
|
5038
|
+
const discoverStart = performance.now();
|
|
4863
5039
|
const rscEnv = server.environments?.rsc;
|
|
4864
5040
|
if (!rscEnv?.runner) {
|
|
5041
|
+
debugDiscovery?.("dev: no rsc runner (cloudflare path)");
|
|
4865
5042
|
s.devServerOrigin = getDevServerOrigin();
|
|
4866
5043
|
try {
|
|
4867
|
-
await
|
|
4868
|
-
|
|
5044
|
+
await timed(
|
|
5045
|
+
debugDiscovery,
|
|
5046
|
+
"acquireBuildEnv",
|
|
5047
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5048
|
+
);
|
|
5049
|
+
const tempRscEnv = await timed(
|
|
5050
|
+
debugDiscovery,
|
|
5051
|
+
"getOrCreateTempServer",
|
|
5052
|
+
() => getOrCreateTempServer()
|
|
5053
|
+
);
|
|
4869
5054
|
if (tempRscEnv) {
|
|
4870
|
-
await
|
|
4871
|
-
|
|
5055
|
+
await timed(
|
|
5056
|
+
debugDiscovery,
|
|
5057
|
+
"discoverRouters (cloudflare)",
|
|
5058
|
+
() => discoverRouters(s, tempRscEnv)
|
|
5059
|
+
);
|
|
5060
|
+
timedSync(
|
|
5061
|
+
debugDiscovery,
|
|
5062
|
+
"writeRouteTypesFiles",
|
|
5063
|
+
() => writeRouteTypesFiles(s)
|
|
5064
|
+
);
|
|
4872
5065
|
}
|
|
4873
5066
|
} catch (err) {
|
|
4874
5067
|
console.warn(
|
|
@@ -4876,27 +5069,54 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4876
5069
|
${err.stack}`
|
|
4877
5070
|
);
|
|
4878
5071
|
}
|
|
5072
|
+
debugDiscovery?.(
|
|
5073
|
+
"dev discovery done (%sms)",
|
|
5074
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5075
|
+
);
|
|
4879
5076
|
resolveDiscovery();
|
|
4880
5077
|
return;
|
|
4881
5078
|
}
|
|
4882
5079
|
try {
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
5080
|
+
debugDiscovery?.("dev: node path start");
|
|
5081
|
+
await timed(
|
|
5082
|
+
debugDiscovery,
|
|
5083
|
+
"acquireBuildEnv",
|
|
5084
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5085
|
+
);
|
|
5086
|
+
const serverMod = await timed(
|
|
5087
|
+
debugDiscovery,
|
|
5088
|
+
"import @rangojs/router/server",
|
|
5089
|
+
() => rscEnv.runner.import("@rangojs/router/server")
|
|
4886
5090
|
);
|
|
4887
5091
|
if (serverMod?.setManifestReadyPromise) {
|
|
4888
5092
|
serverMod.setManifestReadyPromise(discoveryPromise);
|
|
4889
5093
|
}
|
|
4890
|
-
await
|
|
5094
|
+
await timed(
|
|
5095
|
+
debugDiscovery,
|
|
5096
|
+
"discoverRouters",
|
|
5097
|
+
() => discoverRouters(s, rscEnv)
|
|
5098
|
+
);
|
|
4891
5099
|
s.devServerOrigin = getDevServerOrigin();
|
|
4892
|
-
|
|
4893
|
-
|
|
5100
|
+
timedSync(
|
|
5101
|
+
debugDiscovery,
|
|
5102
|
+
"writeRouteTypesFiles",
|
|
5103
|
+
() => writeRouteTypesFiles(s)
|
|
5104
|
+
);
|
|
5105
|
+
await timed(
|
|
5106
|
+
debugDiscovery,
|
|
5107
|
+
"propagateDiscoveryState",
|
|
5108
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5109
|
+
);
|
|
4894
5110
|
} catch (err) {
|
|
4895
5111
|
console.warn(
|
|
4896
5112
|
`[rsc-router] Router discovery failed: ${err.message}
|
|
4897
5113
|
${err.stack}`
|
|
4898
5114
|
);
|
|
4899
5115
|
} finally {
|
|
5116
|
+
debugDiscovery?.(
|
|
5117
|
+
"dev discovery done (%sms)",
|
|
5118
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5119
|
+
);
|
|
4900
5120
|
resolveDiscovery();
|
|
4901
5121
|
}
|
|
4902
5122
|
};
|
|
@@ -5041,15 +5261,32 @@ ${err.stack}`
|
|
|
5041
5261
|
const rscEnv = server.environments?.rsc;
|
|
5042
5262
|
if (!rscEnv?.runner || runtimeRediscoveryInProgress) return;
|
|
5043
5263
|
runtimeRediscoveryInProgress = true;
|
|
5264
|
+
const hmrStart = performance.now();
|
|
5044
5265
|
try {
|
|
5045
|
-
await
|
|
5046
|
-
|
|
5047
|
-
|
|
5266
|
+
await timed(
|
|
5267
|
+
debugDiscovery,
|
|
5268
|
+
"hmr discoverRouters",
|
|
5269
|
+
() => discoverRouters(s, rscEnv)
|
|
5270
|
+
);
|
|
5271
|
+
timedSync(
|
|
5272
|
+
debugDiscovery,
|
|
5273
|
+
"hmr writeRouteTypesFiles",
|
|
5274
|
+
() => writeRouteTypesFiles(s)
|
|
5275
|
+
);
|
|
5276
|
+
await timed(
|
|
5277
|
+
debugDiscovery,
|
|
5278
|
+
"hmr propagateDiscoveryState",
|
|
5279
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5280
|
+
);
|
|
5048
5281
|
} catch (err) {
|
|
5049
5282
|
console.warn(
|
|
5050
5283
|
`[rsc-router] Runtime re-discovery failed: ${err.message}`
|
|
5051
5284
|
);
|
|
5052
5285
|
} finally {
|
|
5286
|
+
debugDiscovery?.(
|
|
5287
|
+
"hmr re-discovery done (%sms)",
|
|
5288
|
+
(performance.now() - hmrStart).toFixed(1)
|
|
5289
|
+
);
|
|
5053
5290
|
runtimeRediscoveryInProgress = false;
|
|
5054
5291
|
}
|
|
5055
5292
|
};
|
|
@@ -5122,14 +5359,24 @@ ${err.stack}`
|
|
|
5122
5359
|
async buildStart() {
|
|
5123
5360
|
if (!s.isBuildMode) return;
|
|
5124
5361
|
if (s.mergedRouteManifest !== null) return;
|
|
5362
|
+
const buildStartTime = performance.now();
|
|
5363
|
+
debugDiscovery?.("build: start");
|
|
5125
5364
|
resetStagedBuildAssets(s.projectRoot);
|
|
5126
5365
|
s.prerenderManifestEntries = null;
|
|
5127
5366
|
s.staticManifestEntries = null;
|
|
5128
|
-
await
|
|
5367
|
+
await timed(
|
|
5368
|
+
debugDiscovery,
|
|
5369
|
+
"build acquireBuildEnv",
|
|
5370
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5371
|
+
);
|
|
5129
5372
|
let tempServer = null;
|
|
5130
5373
|
globalThis.__rscRouterDiscoveryActive = true;
|
|
5131
5374
|
try {
|
|
5132
|
-
tempServer = await
|
|
5375
|
+
tempServer = await timed(
|
|
5376
|
+
debugDiscovery,
|
|
5377
|
+
"build createTempRscServer",
|
|
5378
|
+
() => createTempRscServer(s, { forceBuild: true })
|
|
5379
|
+
);
|
|
5133
5380
|
const rscEnv = tempServer.environments?.rsc;
|
|
5134
5381
|
if (!rscEnv?.runner) {
|
|
5135
5382
|
console.warn(
|
|
@@ -5143,8 +5390,16 @@ ${err.stack}`
|
|
|
5143
5390
|
if (tempIdsPlugin?.api?.staticHandlerModules) {
|
|
5144
5391
|
s.resolvedStaticModules = tempIdsPlugin.api.staticHandlerModules;
|
|
5145
5392
|
}
|
|
5146
|
-
await
|
|
5147
|
-
|
|
5393
|
+
await timed(
|
|
5394
|
+
debugDiscovery,
|
|
5395
|
+
"build discoverRouters",
|
|
5396
|
+
() => discoverRouters(s, rscEnv)
|
|
5397
|
+
);
|
|
5398
|
+
timedSync(
|
|
5399
|
+
debugDiscovery,
|
|
5400
|
+
"build writeRouteTypesFiles",
|
|
5401
|
+
() => writeRouteTypesFiles(s)
|
|
5402
|
+
);
|
|
5148
5403
|
} catch (err) {
|
|
5149
5404
|
const sourceFile = err.stack?.split("\n").find(
|
|
5150
5405
|
(line) => line.includes(s.projectRoot) && !line.includes("node_modules")
|
|
@@ -5163,9 +5418,17 @@ ${details}`
|
|
|
5163
5418
|
} finally {
|
|
5164
5419
|
delete globalThis.__rscRouterDiscoveryActive;
|
|
5165
5420
|
if (tempServer) {
|
|
5166
|
-
await
|
|
5421
|
+
await timed(
|
|
5422
|
+
debugDiscovery,
|
|
5423
|
+
"build tempServer.close",
|
|
5424
|
+
() => tempServer.close()
|
|
5425
|
+
);
|
|
5167
5426
|
}
|
|
5168
5427
|
await releaseBuildEnv(s);
|
|
5428
|
+
debugDiscovery?.(
|
|
5429
|
+
"build discovery done (%sms)",
|
|
5430
|
+
(performance.now() - buildStartTime).toFixed(1)
|
|
5431
|
+
);
|
|
5169
5432
|
}
|
|
5170
5433
|
},
|
|
5171
5434
|
// Virtual module: provides the pre-generated route manifest as a JS module
|
|
@@ -5182,17 +5445,36 @@ ${details}`
|
|
|
5182
5445
|
async load(id) {
|
|
5183
5446
|
if (id === "\0" + VIRTUAL_ROUTES_MANIFEST_ID) {
|
|
5184
5447
|
if (s.discoveryDone) {
|
|
5185
|
-
await
|
|
5448
|
+
await timed(
|
|
5449
|
+
debugRoutes,
|
|
5450
|
+
"await discoveryDone (manifest)",
|
|
5451
|
+
() => Promise.resolve(s.discoveryDone)
|
|
5452
|
+
);
|
|
5186
5453
|
}
|
|
5187
|
-
|
|
5454
|
+
const code = await timed(
|
|
5455
|
+
debugRoutes,
|
|
5456
|
+
"generateRoutesManifestModule",
|
|
5457
|
+
() => generateRoutesManifestModule(s)
|
|
5458
|
+
);
|
|
5459
|
+
debugRoutes?.("manifest module emitted (%d bytes)", code?.length ?? 0);
|
|
5460
|
+
return code;
|
|
5188
5461
|
}
|
|
5189
5462
|
const perRouterPrefix = "\0" + VIRTUAL_ROUTES_MANIFEST_ID + "/";
|
|
5190
5463
|
if (id.startsWith(perRouterPrefix)) {
|
|
5191
5464
|
if (s.discoveryDone) {
|
|
5192
|
-
await
|
|
5465
|
+
await timed(
|
|
5466
|
+
debugRoutes,
|
|
5467
|
+
"await discoveryDone (per-router)",
|
|
5468
|
+
() => Promise.resolve(s.discoveryDone)
|
|
5469
|
+
);
|
|
5193
5470
|
}
|
|
5194
5471
|
const routerId = id.slice(perRouterPrefix.length);
|
|
5195
|
-
|
|
5472
|
+
const code = await timed(
|
|
5473
|
+
debugRoutes,
|
|
5474
|
+
`generatePerRouterModule ${routerId}`,
|
|
5475
|
+
() => generatePerRouterModule(s, routerId)
|
|
5476
|
+
);
|
|
5477
|
+
return code;
|
|
5196
5478
|
}
|
|
5197
5479
|
return null;
|
|
5198
5480
|
},
|
|
@@ -5268,22 +5550,30 @@ ${details}`
|
|
|
5268
5550
|
}
|
|
5269
5551
|
|
|
5270
5552
|
// src/vite/rango.ts
|
|
5553
|
+
var debugConfig = createRangoDebugger("rango:config");
|
|
5271
5554
|
async function rango(options) {
|
|
5555
|
+
const rangoStart = performance.now();
|
|
5272
5556
|
const resolvedOptions = options ?? { preset: "node" };
|
|
5273
5557
|
const preset = resolvedOptions.preset ?? "node";
|
|
5274
5558
|
const showBanner = resolvedOptions.banner ?? true;
|
|
5559
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
5275
5560
|
const plugins = [];
|
|
5276
|
-
const rangoAliases = getPackageAliases();
|
|
5561
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
5277
5562
|
const excludeDeps = [
|
|
5278
5563
|
...getExcludeDeps(),
|
|
5279
|
-
//
|
|
5280
|
-
//
|
|
5281
|
-
// .
|
|
5564
|
+
// plugin-rsc itself injects these into the client env's
|
|
5565
|
+
// optimizeDeps.include, which overrides exclude for the dep's own
|
|
5566
|
+
// pre-bundle entry. What exclude still controls is how *other*
|
|
5567
|
+
// pre-bundled deps treat imports of these specs (external vs inlined)
|
|
5568
|
+
// via esbuildCjsExternalPlugin. The cjs-to-esm transform in
|
|
5569
|
+
// plugins/cjs-to-esm.ts is the fallback for strict-pnpm consumers,
|
|
5570
|
+
// where client.browser's bare include fails to resolve and Vite ends up
|
|
5571
|
+
// serving the raw CJS file at dev-serve time.
|
|
5282
5572
|
"@vitejs/plugin-rsc/browser",
|
|
5283
|
-
// Keep the browser RSDW client out of Vite's dep optimizer so our
|
|
5284
|
-
// cjs-to-esm transform can patch the real file.
|
|
5285
5573
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"
|
|
5286
5574
|
];
|
|
5575
|
+
const pkg = getPublishedPackageName();
|
|
5576
|
+
const nested = (spec) => `${pkg} > ${spec}`;
|
|
5287
5577
|
const routerRef = { path: void 0 };
|
|
5288
5578
|
const prerenderEnabled = true;
|
|
5289
5579
|
if (preset === "cloudflare") {
|
|
@@ -5321,7 +5611,7 @@ async function rango(options) {
|
|
|
5321
5611
|
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
5322
5612
|
// Exclude rsc-router modules to ensure same Context instance
|
|
5323
5613
|
optimizeDeps: {
|
|
5324
|
-
include: ["rsc-html-stream/client"],
|
|
5614
|
+
include: [nested("rsc-html-stream/client")],
|
|
5325
5615
|
exclude: excludeDeps,
|
|
5326
5616
|
esbuildOptions: sharedEsbuildOptions
|
|
5327
5617
|
}
|
|
@@ -5346,8 +5636,10 @@ async function rango(options) {
|
|
|
5346
5636
|
"react-dom/static.edge",
|
|
5347
5637
|
"react/jsx-runtime",
|
|
5348
5638
|
"react/jsx-dev-runtime",
|
|
5349
|
-
"rsc-html-stream/server",
|
|
5350
|
-
|
|
5639
|
+
nested("rsc-html-stream/server"),
|
|
5640
|
+
nested(
|
|
5641
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5642
|
+
)
|
|
5351
5643
|
],
|
|
5352
5644
|
exclude: excludeDeps,
|
|
5353
5645
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5362,7 +5654,9 @@ async function rango(options) {
|
|
|
5362
5654
|
"react",
|
|
5363
5655
|
"react/jsx-runtime",
|
|
5364
5656
|
"react/jsx-dev-runtime",
|
|
5365
|
-
|
|
5657
|
+
nested(
|
|
5658
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
5659
|
+
)
|
|
5366
5660
|
],
|
|
5367
5661
|
exclude: excludeDeps,
|
|
5368
5662
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5443,7 +5737,7 @@ ${list}`);
|
|
|
5443
5737
|
"react-dom",
|
|
5444
5738
|
"react/jsx-runtime",
|
|
5445
5739
|
"react/jsx-dev-runtime",
|
|
5446
|
-
"rsc-html-stream/client"
|
|
5740
|
+
nested("rsc-html-stream/client")
|
|
5447
5741
|
],
|
|
5448
5742
|
exclude: excludeDeps,
|
|
5449
5743
|
esbuildOptions: sharedEsbuildOptions,
|
|
@@ -5460,7 +5754,9 @@ ${list}`);
|
|
|
5460
5754
|
"react-dom/static.edge",
|
|
5461
5755
|
"react/jsx-runtime",
|
|
5462
5756
|
"react/jsx-dev-runtime",
|
|
5463
|
-
|
|
5757
|
+
nested(
|
|
5758
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5759
|
+
)
|
|
5464
5760
|
],
|
|
5465
5761
|
exclude: excludeDeps,
|
|
5466
5762
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5473,7 +5769,9 @@ ${list}`);
|
|
|
5473
5769
|
"react",
|
|
5474
5770
|
"react/jsx-runtime",
|
|
5475
5771
|
"react/jsx-dev-runtime",
|
|
5476
|
-
|
|
5772
|
+
nested(
|
|
5773
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
5774
|
+
)
|
|
5477
5775
|
],
|
|
5478
5776
|
esbuildOptions: sharedEsbuildOptions
|
|
5479
5777
|
}
|
|
@@ -5543,6 +5841,12 @@ ${list}`);
|
|
|
5543
5841
|
preset
|
|
5544
5842
|
})
|
|
5545
5843
|
);
|
|
5844
|
+
debugConfig?.(
|
|
5845
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
5846
|
+
preset,
|
|
5847
|
+
plugins.length,
|
|
5848
|
+
(performance.now() - rangoStart).toFixed(1)
|
|
5849
|
+
);
|
|
5546
5850
|
return plugins;
|
|
5547
5851
|
}
|
|
5548
5852
|
|
|
@@ -5553,7 +5857,7 @@ function poke() {
|
|
|
5553
5857
|
apply: "serve",
|
|
5554
5858
|
configureServer(server) {
|
|
5555
5859
|
const stdin = process.stdin;
|
|
5556
|
-
const
|
|
5860
|
+
const debug2 = process.env.RANGO_POKE_DEBUG === "1";
|
|
5557
5861
|
const triggerReload = (source) => {
|
|
5558
5862
|
server.hot.send({ type: "full-reload", path: "*" });
|
|
5559
5863
|
server.config.logger.info(` browser reload (${source})`, {
|
|
@@ -5586,7 +5890,7 @@ function poke() {
|
|
|
5586
5890
|
lines.pop();
|
|
5587
5891
|
return lines;
|
|
5588
5892
|
};
|
|
5589
|
-
if (
|
|
5893
|
+
if (debug2) {
|
|
5590
5894
|
server.config.logger.info(
|
|
5591
5895
|
` poke debug enabled (isTTY=${stdin.isTTY ? "yes" : "no"}, isRaw=${stdin.isTTY ? stdin.isRaw ? "yes" : "no" : "n/a"})`,
|
|
5592
5896
|
{ timestamp: true }
|
|
@@ -5599,7 +5903,7 @@ function poke() {
|
|
|
5599
5903
|
);
|
|
5600
5904
|
}
|
|
5601
5905
|
const onData = (data) => {
|
|
5602
|
-
if (
|
|
5906
|
+
if (debug2) {
|
|
5603
5907
|
server.config.logger.info(` poke stdin ${formatChunk(data)}`, {
|
|
5604
5908
|
timestamp: true
|
|
5605
5909
|
});
|