@rangojs/router 0.0.0-experimental.138 → 0.0.0-experimental.139
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 +273 -924
- package/dist/bin/rango.js +28 -14
- package/dist/vite/index.js +472 -77
- package/package.json +33 -19
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/host-router/SKILL.md +45 -3
- package/skills/layout/SKILL.md +26 -9
- package/skills/middleware/SKILL.md +6 -2
- package/skills/observability/SKILL.md +23 -1
- package/skills/parallel/SKILL.md +11 -3
- package/skills/rango/SKILL.md +71 -23
- package/skills/route/SKILL.md +19 -3
- package/skills/router-setup/SKILL.md +1 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/vercel/SKILL.md +128 -0
- package/src/build/generate-route-types.ts +1 -0
- package/src/build/route-types/router-processing.ts +77 -27
- package/src/cache/index.ts +12 -0
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +948 -0
- package/src/host/errors.ts +15 -0
- package/src/host/index.ts +1 -0
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/discovery/state.ts +1 -1
- package/src/vite/index.ts +2 -0
- package/src/vite/plugin-types.ts +84 -2
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/virtual-entries.ts +72 -0
- package/src/vite/rango.ts +128 -21
- package/src/vite/utils/shared-utils.ts +52 -2
package/dist/vite/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/vite/rango.ts
|
|
2
|
-
import { readFileSync as readFileSync7 } from "node:fs";
|
|
3
|
-
import { resolve as
|
|
2
|
+
import { readFileSync as readFileSync7, existsSync as existsSync8 } from "node:fs";
|
|
3
|
+
import { resolve as resolve11 } from "node:path";
|
|
4
4
|
|
|
5
5
|
// src/vite/plugins/expose-action-id.ts
|
|
6
6
|
import MagicString from "magic-string";
|
|
@@ -2279,6 +2279,77 @@ export default function handler(request, env) {
|
|
|
2279
2279
|
}
|
|
2280
2280
|
`.trim();
|
|
2281
2281
|
}
|
|
2282
|
+
function getVirtualEntryRSCHost(hostEntryPath) {
|
|
2283
|
+
return `
|
|
2284
|
+
import * as __hostEntry from "${hostEntryPath}";
|
|
2285
|
+
import { isNoRouteMatchError } from "@rangojs/router/host";
|
|
2286
|
+
|
|
2287
|
+
// Register every sub-app's fetchable loaders + route manifests at startup, same
|
|
2288
|
+
// as the single-router entry. Discovery's host fallback populates these for all
|
|
2289
|
+
// mounted sub-apps, so the aggregate manifests cover the whole host tree.
|
|
2290
|
+
import "virtual:rsc-router/loader-manifest";
|
|
2291
|
+
import "virtual:rsc-router/routes-manifest";
|
|
2292
|
+
|
|
2293
|
+
// The host entry module must export the HostRouter instance (createHostRouter()),
|
|
2294
|
+
// as a default export or a named \`hostRouter\`/\`router\` export. A Cloudflare-style
|
|
2295
|
+
// \`export default { fetch }\` object is not a HostRouter and is rejected (on first
|
|
2296
|
+
// request; see the lazy resolution below).
|
|
2297
|
+
// We require BOTH .match() and .host(): a regular createRouter() also exposes
|
|
2298
|
+
// .match(), so matching on .match() alone would accept an ordinary router and then
|
|
2299
|
+
// return its MatchResult (not a Response) at runtime. .host() is unique to a
|
|
2300
|
+
// HostRouter, so it disambiguates a mistaken \`hostRouter\` path.
|
|
2301
|
+
// Exports are read dynamically (m[name]) so Rollup does not emit IMPORT_IS_UNDEFINED
|
|
2302
|
+
// warnings for the named exports a default-only host module legitimately omits.
|
|
2303
|
+
const __resolveHostRouter = (m) => {
|
|
2304
|
+
for (const name of ["default", "hostRouter", "router"]) {
|
|
2305
|
+
const candidate = m[name];
|
|
2306
|
+
if (
|
|
2307
|
+
candidate &&
|
|
2308
|
+
typeof candidate.match === "function" &&
|
|
2309
|
+
typeof candidate.host === "function"
|
|
2310
|
+
)
|
|
2311
|
+
return candidate;
|
|
2312
|
+
}
|
|
2313
|
+
return undefined;
|
|
2314
|
+
};
|
|
2315
|
+
|
|
2316
|
+
// Resolve + validate the HostRouter lazily on first request, mirroring the
|
|
2317
|
+
// single-router entry's \`_handler\`. During HMR the host module can re-evaluate
|
|
2318
|
+
// before its createHostRouter() export has resolved; validating at module-
|
|
2319
|
+
// evaluation time would then throw a spurious "must export a HostRouter" error
|
|
2320
|
+
// overlay for a perfectly valid app. Resolving on first request lets the live
|
|
2321
|
+
// binding settle first.
|
|
2322
|
+
let _hostRouter;
|
|
2323
|
+
|
|
2324
|
+
// input = { env, ctx } from the launcher / node server. The host router threads
|
|
2325
|
+
// it unchanged to each matched sub-app's handler and cache factory.
|
|
2326
|
+
// On node/vercel rango owns this entry, so there is no user worker to translate
|
|
2327
|
+
// an unmatched host into a response: catch NoRouteMatchError and return 404
|
|
2328
|
+
// (parity with the documented Cloudflare catch). Other errors propagate.
|
|
2329
|
+
export default async function handler(request, input) {
|
|
2330
|
+
if (!_hostRouter) {
|
|
2331
|
+
_hostRouter = __resolveHostRouter(__hostEntry);
|
|
2332
|
+
if (!_hostRouter) {
|
|
2333
|
+
throw new Error(
|
|
2334
|
+
"[rango] The host entry (${hostEntryPath}) must export a HostRouter instance (createHostRouter()) for the node/vercel preset: a default export, or a named 'hostRouter'/'router' export. An ordinary createRouter() is not a host router (it has no .host()), and a Cloudflare-style 'export default { fetch }' object is not supported on this preset."
|
|
2335
|
+
);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
try {
|
|
2339
|
+
return await _hostRouter.match(request, input);
|
|
2340
|
+
} catch (err) {
|
|
2341
|
+
// isNoRouteMatchError also matches by name: a workspace with a duplicated
|
|
2342
|
+
// @rangojs/router copy can throw a NoRouteMatchError whose prototype differs
|
|
2343
|
+
// from this module's import, so a bare instanceof would turn an
|
|
2344
|
+
// unmatched-host 404 into a 500.
|
|
2345
|
+
if (isNoRouteMatchError(err)) {
|
|
2346
|
+
return new Response("Not Found", { status: 404 });
|
|
2347
|
+
}
|
|
2348
|
+
throw err;
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
`.trim();
|
|
2352
|
+
}
|
|
2282
2353
|
var VIRTUAL_IDS = {
|
|
2283
2354
|
browser: "virtual:rsc-router/entry.browser.js",
|
|
2284
2355
|
ssr: "virtual:rsc-router/entry.ssr.js",
|
|
@@ -2297,7 +2368,7 @@ import { resolve } from "node:path";
|
|
|
2297
2368
|
// package.json
|
|
2298
2369
|
var package_default = {
|
|
2299
2370
|
name: "@rangojs/router",
|
|
2300
|
-
version: "0.0.0-experimental.
|
|
2371
|
+
version: "0.0.0-experimental.139",
|
|
2301
2372
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
2302
2373
|
keywords: [
|
|
2303
2374
|
"react",
|
|
@@ -2412,6 +2483,11 @@ var package_default = {
|
|
|
2412
2483
|
"react-server": "./src/cloudflare/index.ts",
|
|
2413
2484
|
default: "./src/cloudflare/index.ts"
|
|
2414
2485
|
},
|
|
2486
|
+
"./vercel": {
|
|
2487
|
+
types: "./src/vercel/index.ts",
|
|
2488
|
+
"react-server": "./src/vercel/index.ts",
|
|
2489
|
+
default: "./src/vercel/index.ts"
|
|
2490
|
+
},
|
|
2415
2491
|
"./theme": {
|
|
2416
2492
|
types: "./src/theme/index.ts",
|
|
2417
2493
|
default: "./src/theme/index.ts"
|
|
@@ -2477,9 +2553,11 @@ var package_default = {
|
|
|
2477
2553
|
"magic-string": "^0.30.17",
|
|
2478
2554
|
picomatch: "^4.0.4",
|
|
2479
2555
|
"rsc-html-stream": "^0.0.7",
|
|
2556
|
+
srvx: "^0.11.15",
|
|
2480
2557
|
tinyexec: "^0.3.2"
|
|
2481
2558
|
},
|
|
2482
2559
|
devDependencies: {
|
|
2560
|
+
"@opentelemetry/api": "^1.9.0",
|
|
2483
2561
|
"@playwright/test": "^1.49.1",
|
|
2484
2562
|
"@shared/e2e": "workspace:*",
|
|
2485
2563
|
"@testing-library/dom": "^10.4.1",
|
|
@@ -2497,8 +2575,10 @@ var package_default = {
|
|
|
2497
2575
|
},
|
|
2498
2576
|
peerDependencies: {
|
|
2499
2577
|
"@cloudflare/vite-plugin": "^1.42.1",
|
|
2578
|
+
"@opentelemetry/api": "^1.9.0",
|
|
2500
2579
|
"@playwright/test": "^1.49.1",
|
|
2501
2580
|
"@testing-library/react": ">=16",
|
|
2581
|
+
"@vercel/functions": "^3.0.0",
|
|
2502
2582
|
"@vitejs/plugin-rsc": "^0.5.27",
|
|
2503
2583
|
react: ">=19.2.6 <20",
|
|
2504
2584
|
"react-dom": ">=19.2.6 <20",
|
|
@@ -2509,12 +2589,18 @@ var package_default = {
|
|
|
2509
2589
|
"@cloudflare/vite-plugin": {
|
|
2510
2590
|
optional: true
|
|
2511
2591
|
},
|
|
2592
|
+
"@opentelemetry/api": {
|
|
2593
|
+
optional: true
|
|
2594
|
+
},
|
|
2512
2595
|
"@playwright/test": {
|
|
2513
2596
|
optional: true
|
|
2514
2597
|
},
|
|
2515
2598
|
"@testing-library/react": {
|
|
2516
2599
|
optional: true
|
|
2517
2600
|
},
|
|
2601
|
+
"@vercel/functions": {
|
|
2602
|
+
optional: true
|
|
2603
|
+
},
|
|
2518
2604
|
vite: {
|
|
2519
2605
|
optional: true
|
|
2520
2606
|
},
|
|
@@ -3270,7 +3356,10 @@ var ROUTER_CALL_PATTERN_G = /\bcreateRouter\s*[<(]/g;
|
|
|
3270
3356
|
function isRoutableSourceFile(name) {
|
|
3271
3357
|
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
3272
3358
|
}
|
|
3273
|
-
function
|
|
3359
|
+
function isExcludedScanDir(name) {
|
|
3360
|
+
return name === "node_modules" || name === "dist" || name === "coverage" || name === "__tests__" || name === "__mocks__" || name.startsWith(".");
|
|
3361
|
+
}
|
|
3362
|
+
function findCallSiteFilesRecursive(dir, pattern, patternG, stopAtMatchDir, filter, results) {
|
|
3274
3363
|
let entries;
|
|
3275
3364
|
try {
|
|
3276
3365
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
@@ -3281,32 +3370,36 @@ function findRouterFilesRecursive(dir, filter, results) {
|
|
|
3281
3370
|
return;
|
|
3282
3371
|
}
|
|
3283
3372
|
const childDirs = [];
|
|
3284
|
-
const
|
|
3373
|
+
const matchesInDir = [];
|
|
3285
3374
|
for (const entry of entries) {
|
|
3286
3375
|
const fullPath = join2(dir, entry.name);
|
|
3287
3376
|
if (entry.isDirectory()) {
|
|
3288
|
-
if (entry.name
|
|
3289
|
-
continue;
|
|
3290
|
-
childDirs.push(fullPath);
|
|
3377
|
+
if (!isExcludedScanDir(entry.name)) childDirs.push(fullPath);
|
|
3291
3378
|
continue;
|
|
3292
3379
|
}
|
|
3293
3380
|
if (!isRoutableSourceFile(entry.name)) continue;
|
|
3294
3381
|
if (filter && !filter(fullPath)) continue;
|
|
3295
3382
|
try {
|
|
3296
3383
|
const source = readFileSync2(fullPath, "utf-8");
|
|
3297
|
-
if (
|
|
3298
|
-
|
|
3384
|
+
if (pattern.test(source) && firstCodeMatchIndex(source, patternG) >= 0) {
|
|
3385
|
+
matchesInDir.push(fullPath);
|
|
3299
3386
|
}
|
|
3300
3387
|
} catch {
|
|
3301
3388
|
continue;
|
|
3302
3389
|
}
|
|
3303
3390
|
}
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3391
|
+
results.push(...matchesInDir);
|
|
3392
|
+
if (!stopAtMatchDir || matchesInDir.length === 0) {
|
|
3393
|
+
for (const childDir of childDirs) {
|
|
3394
|
+
findCallSiteFilesRecursive(
|
|
3395
|
+
childDir,
|
|
3396
|
+
pattern,
|
|
3397
|
+
patternG,
|
|
3398
|
+
stopAtMatchDir,
|
|
3399
|
+
filter,
|
|
3400
|
+
results
|
|
3401
|
+
);
|
|
3402
|
+
}
|
|
3310
3403
|
}
|
|
3311
3404
|
}
|
|
3312
3405
|
function findNestedRouterConflict(routerFiles) {
|
|
@@ -3504,7 +3597,28 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
|
3504
3597
|
}
|
|
3505
3598
|
function findRouterFiles(root, filter) {
|
|
3506
3599
|
const result = [];
|
|
3507
|
-
|
|
3600
|
+
findCallSiteFilesRecursive(
|
|
3601
|
+
root,
|
|
3602
|
+
ROUTER_CALL_PATTERN,
|
|
3603
|
+
ROUTER_CALL_PATTERN_G,
|
|
3604
|
+
true,
|
|
3605
|
+
filter,
|
|
3606
|
+
result
|
|
3607
|
+
);
|
|
3608
|
+
return result;
|
|
3609
|
+
}
|
|
3610
|
+
var HOST_ROUTER_CALL_PATTERN = /\bcreateHostRouter\s*[<(]/;
|
|
3611
|
+
var HOST_ROUTER_CALL_PATTERN_G = /\bcreateHostRouter\s*[<(]/g;
|
|
3612
|
+
function findHostRouterFiles(root, filter) {
|
|
3613
|
+
const result = [];
|
|
3614
|
+
findCallSiteFilesRecursive(
|
|
3615
|
+
root,
|
|
3616
|
+
HOST_ROUTER_CALL_PATTERN,
|
|
3617
|
+
HOST_ROUTER_CALL_PATTERN_G,
|
|
3618
|
+
false,
|
|
3619
|
+
filter,
|
|
3620
|
+
result
|
|
3621
|
+
);
|
|
3508
3622
|
return result;
|
|
3509
3623
|
}
|
|
3510
3624
|
function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
@@ -3778,6 +3892,7 @@ function isViteDepCachePath(filePath, cacheDir) {
|
|
|
3778
3892
|
|
|
3779
3893
|
// src/vite/utils/shared-utils.ts
|
|
3780
3894
|
import * as Vite from "vite";
|
|
3895
|
+
import { isAbsolute, resolve as resolve4 } from "node:path";
|
|
3781
3896
|
|
|
3782
3897
|
// src/vite/plugins/performance-tracks.ts
|
|
3783
3898
|
import { readFile } from "node:fs/promises";
|
|
@@ -3860,6 +3975,21 @@ var versionRolldownPlugin = {
|
|
|
3860
3975
|
var sharedRolldownOptions = {
|
|
3861
3976
|
plugins: [versionRolldownPlugin, performanceTracksOptimizeDepsPlugin()]
|
|
3862
3977
|
};
|
|
3978
|
+
function normalizeHostRouterEntry(rawInput, root, exists) {
|
|
3979
|
+
const raw = rawInput.replaceAll("\\", "/");
|
|
3980
|
+
const isRelative = raw.startsWith("./") || raw.startsWith("../");
|
|
3981
|
+
const isRooted = raw.startsWith("/") || isAbsolute(rawInput);
|
|
3982
|
+
if (isRooted) return raw;
|
|
3983
|
+
if (isRelative) {
|
|
3984
|
+
if (!exists(resolve4(root, raw))) {
|
|
3985
|
+
throw new Error(
|
|
3986
|
+
`[rango] hostRouter entry not found: "${rawInput}" (resolved under ${root}). Point it at your createHostRouter() module, e.g. rango({ hostRouter: "./src/worker.rsc.tsx" }).`
|
|
3987
|
+
);
|
|
3988
|
+
}
|
|
3989
|
+
return raw;
|
|
3990
|
+
}
|
|
3991
|
+
return exists(resolve4(root, raw)) ? "./" + raw : raw;
|
|
3992
|
+
}
|
|
3863
3993
|
function createVirtualEntriesPlugin(entries, routerPathRef) {
|
|
3864
3994
|
const virtualModules = {};
|
|
3865
3995
|
if (entries.client === VIRTUAL_IDS.browser) {
|
|
@@ -3893,7 +4023,7 @@ function createVirtualEntriesPlugin(entries, routerPathRef) {
|
|
|
3893
4023
|
if (virtualId === VIRTUAL_IDS.rsc && routerPathRef?.path) {
|
|
3894
4024
|
const raw = routerPathRef.path.startsWith(".") ? "/" + routerPathRef.path.slice(2) : routerPathRef.path;
|
|
3895
4025
|
const absoluteRouterPath = raw.replaceAll("\\", "/");
|
|
3896
|
-
return getVirtualEntryRSC(absoluteRouterPath);
|
|
4026
|
+
return routerPathRef.kind === "host" ? getVirtualEntryRSCHost(absoluteRouterPath) : getVirtualEntryRSC(absoluteRouterPath);
|
|
3897
4027
|
}
|
|
3898
4028
|
}
|
|
3899
4029
|
return null;
|
|
@@ -4072,6 +4202,221 @@ function resolveClientChunks(option, ctx) {
|
|
|
4072
4202
|
return option;
|
|
4073
4203
|
}
|
|
4074
4204
|
|
|
4205
|
+
// src/vite/plugins/vercel-output.ts
|
|
4206
|
+
import { rm, mkdir, cp, writeFile } from "node:fs/promises";
|
|
4207
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
4208
|
+
import { resolve as resolve5, join as join3 } from "node:path";
|
|
4209
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
4210
|
+
import { pathToFileURL } from "node:url";
|
|
4211
|
+
var LAUNCHER_SOURCE = `import { toNodeHandler } from "srvx/node";
|
|
4212
|
+
import { waitUntil } from "@vercel/functions";
|
|
4213
|
+
import rscHandler from "./rsc/index.js";
|
|
4214
|
+
|
|
4215
|
+
// The Vercel Node launcher invokes a Node (req, res) handler, not a Web fetch
|
|
4216
|
+
// handler. srvx's toNodeHandler bridges the Rango Web fetch handler and pipes
|
|
4217
|
+
// the streamed Response to the Node response (set supportsResponseStreaming).
|
|
4218
|
+
const onVercel = Boolean(process.env.VERCEL);
|
|
4219
|
+
|
|
4220
|
+
const fetchHandler = (request) =>
|
|
4221
|
+
rscHandler(request, {
|
|
4222
|
+
env: process.env,
|
|
4223
|
+
// Forward Vercel's waitUntil so cache writes / revalidation run off the
|
|
4224
|
+
// response path. Omitted off-platform so those writes settle inline.
|
|
4225
|
+
ctx: onVercel ? { waitUntil } : undefined,
|
|
4226
|
+
});
|
|
4227
|
+
|
|
4228
|
+
export default toNodeHandler(fetchHandler);
|
|
4229
|
+
`;
|
|
4230
|
+
function assertVercelNodeRuntime(runtime) {
|
|
4231
|
+
if (runtime != null && !runtime.startsWith("nodejs")) {
|
|
4232
|
+
throw new Error(
|
|
4233
|
+
`[rango] preset "vercel": runtime "${runtime}" is not supported. This preset emits a Node serverless function; use a "nodejs*" runtime (default "nodejs22.x"). The Edge runtime is not supported.`
|
|
4234
|
+
);
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
function assertValidVercelFunctionName(functionName) {
|
|
4238
|
+
if (!/^[A-Za-z0-9._-]+$/.test(functionName)) {
|
|
4239
|
+
throw new Error(
|
|
4240
|
+
`[rango] preset "vercel": invalid functionName ${JSON.stringify(
|
|
4241
|
+
functionName
|
|
4242
|
+
)}. Use letters, digits, ".", "_" or "-" only (it becomes the .func directory and the routing dest).`
|
|
4243
|
+
);
|
|
4244
|
+
}
|
|
4245
|
+
}
|
|
4246
|
+
function buildVercelVcConfig(vercel) {
|
|
4247
|
+
const vcConfig = {
|
|
4248
|
+
runtime: vercel.runtime ?? "nodejs22.x",
|
|
4249
|
+
handler: "index.mjs",
|
|
4250
|
+
launcherType: "Nodejs",
|
|
4251
|
+
shouldAddHelpers: false,
|
|
4252
|
+
supportsResponseStreaming: true,
|
|
4253
|
+
maxDuration: vercel.maxDuration ?? 30
|
|
4254
|
+
};
|
|
4255
|
+
if (vercel.memory != null) vcConfig.memory = vercel.memory;
|
|
4256
|
+
if (vercel.regions != null) vcConfig.regions = vercel.regions;
|
|
4257
|
+
return vcConfig;
|
|
4258
|
+
}
|
|
4259
|
+
function buildVercelOutputConfig(functionName, assetsDir) {
|
|
4260
|
+
const assetsPrefix = assetsDir.replace(/^\/+|\/+$/g, "");
|
|
4261
|
+
const assetHeaderRoute = assetsPrefix ? [
|
|
4262
|
+
{
|
|
4263
|
+
src: `/${escapeRegExp(assetsPrefix)}/(.*)`,
|
|
4264
|
+
headers: { "cache-control": "public, max-age=31536000, immutable" },
|
|
4265
|
+
continue: true
|
|
4266
|
+
}
|
|
4267
|
+
] : [];
|
|
4268
|
+
return {
|
|
4269
|
+
version: 3,
|
|
4270
|
+
routes: [
|
|
4271
|
+
...assetHeaderRoute,
|
|
4272
|
+
{ handle: "filesystem" },
|
|
4273
|
+
{ src: "/(.*)", dest: `/${functionName}` }
|
|
4274
|
+
]
|
|
4275
|
+
};
|
|
4276
|
+
}
|
|
4277
|
+
async function assemble(root, options, assetsDir, publicDir) {
|
|
4278
|
+
const vercel = options.vercel ?? {};
|
|
4279
|
+
assertVercelNodeRuntime(vercel.runtime);
|
|
4280
|
+
const assetsPrefix = assetsDir.replace(/^\/+|\/+$/g, "");
|
|
4281
|
+
if (publicDir && assetsPrefix && existsSync4(join3(publicDir, assetsPrefix))) {
|
|
4282
|
+
console.warn(
|
|
4283
|
+
`[rango] preset "vercel": ${join3(publicDir, assetsPrefix)} exists. Files under public/${assetsPrefix}/ share the /${assetsPrefix}/ URL prefix with hashed build assets and will be served with a one-year immutable cache-control header. Move un-hashed public files out of "${assetsPrefix}/".`
|
|
4284
|
+
);
|
|
4285
|
+
}
|
|
4286
|
+
const dist = join3(root, "dist");
|
|
4287
|
+
for (const dir of ["client", "rsc", "ssr"]) {
|
|
4288
|
+
if (!existsSync4(join3(dist, dir))) {
|
|
4289
|
+
throw new Error(
|
|
4290
|
+
`[rango] preset "vercel": missing dist/${dir}. Run the production build first.`
|
|
4291
|
+
);
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
const functionName = vercel.functionName ?? "index";
|
|
4295
|
+
assertValidVercelFunctionName(functionName);
|
|
4296
|
+
const out = join3(root, ".vercel", "output");
|
|
4297
|
+
const funcDir = join3(out, "functions", `${functionName}.func`);
|
|
4298
|
+
await rm(out, { recursive: true, force: true });
|
|
4299
|
+
await mkdir(funcDir, { recursive: true });
|
|
4300
|
+
await cp(join3(dist, "client"), join3(out, "static"), { recursive: true });
|
|
4301
|
+
await cp(join3(dist, "rsc"), join3(funcDir, "rsc"), { recursive: true });
|
|
4302
|
+
await cp(join3(dist, "ssr"), join3(funcDir, "ssr"), { recursive: true });
|
|
4303
|
+
if (existsSync4(join3(dist, "static"))) {
|
|
4304
|
+
await cp(join3(dist, "static"), join3(funcDir, "static"), {
|
|
4305
|
+
recursive: true
|
|
4306
|
+
});
|
|
4307
|
+
}
|
|
4308
|
+
const rangoRequire = createRequire2(import.meta.url);
|
|
4309
|
+
let srvxNodePath;
|
|
4310
|
+
try {
|
|
4311
|
+
srvxNodePath = rangoRequire.resolve("srvx/node");
|
|
4312
|
+
} catch {
|
|
4313
|
+
throw new Error(
|
|
4314
|
+
'[rango] preset "vercel" requires "srvx" (a dependency of @rangojs/router). Reinstall dependencies.'
|
|
4315
|
+
);
|
|
4316
|
+
}
|
|
4317
|
+
const appRequire = createRequire2(join3(root, "package.json"));
|
|
4318
|
+
const resolveEsbuildPath = () => {
|
|
4319
|
+
try {
|
|
4320
|
+
const viteRequire = createRequire2(appRequire.resolve("vite"));
|
|
4321
|
+
return viteRequire.resolve("esbuild");
|
|
4322
|
+
} catch {
|
|
4323
|
+
}
|
|
4324
|
+
try {
|
|
4325
|
+
return appRequire.resolve("esbuild");
|
|
4326
|
+
} catch {
|
|
4327
|
+
}
|
|
4328
|
+
return rangoRequire.resolve("esbuild");
|
|
4329
|
+
};
|
|
4330
|
+
let esbuildModule;
|
|
4331
|
+
try {
|
|
4332
|
+
esbuildModule = await import(pathToFileURL(resolveEsbuildPath()).href);
|
|
4333
|
+
} catch {
|
|
4334
|
+
throw new Error(
|
|
4335
|
+
'[rango] preset "vercel" requires "esbuild" to bundle the function launcher. It ships with Vite; reinstall dependencies (or add esbuild to your app dependencies).'
|
|
4336
|
+
);
|
|
4337
|
+
}
|
|
4338
|
+
const esbuildBuild = esbuildModule.build ?? esbuildModule.default?.build;
|
|
4339
|
+
if (typeof esbuildBuild !== "function") {
|
|
4340
|
+
throw new Error('[rango] preset "vercel": could not load esbuild.build.');
|
|
4341
|
+
}
|
|
4342
|
+
try {
|
|
4343
|
+
await esbuildBuild({
|
|
4344
|
+
stdin: {
|
|
4345
|
+
contents: LAUNCHER_SOURCE,
|
|
4346
|
+
resolveDir: root,
|
|
4347
|
+
sourcefile: "func-entry.mjs",
|
|
4348
|
+
loader: "js"
|
|
4349
|
+
},
|
|
4350
|
+
outfile: join3(funcDir, "index.mjs"),
|
|
4351
|
+
bundle: true,
|
|
4352
|
+
format: "esm",
|
|
4353
|
+
platform: "node",
|
|
4354
|
+
target: "node18",
|
|
4355
|
+
alias: { "srvx/node": srvxNodePath },
|
|
4356
|
+
plugins: [
|
|
4357
|
+
{
|
|
4358
|
+
name: "external-rsc-entry",
|
|
4359
|
+
setup(b) {
|
|
4360
|
+
b.onResolve({ filter: /^\.\/rsc\/index\.js$/ }, () => ({
|
|
4361
|
+
path: "./rsc/index.js",
|
|
4362
|
+
external: true
|
|
4363
|
+
}));
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4366
|
+
]
|
|
4367
|
+
});
|
|
4368
|
+
} catch (error) {
|
|
4369
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4370
|
+
if (/@vercel\/functions/.test(message)) {
|
|
4371
|
+
throw new Error(
|
|
4372
|
+
'[rango] preset "vercel": could not resolve "@vercel/functions". Add it to your app dependencies (it also backs VercelCacheStore).\n' + message
|
|
4373
|
+
);
|
|
4374
|
+
}
|
|
4375
|
+
throw error;
|
|
4376
|
+
}
|
|
4377
|
+
await writeFile(
|
|
4378
|
+
join3(funcDir, "package.json"),
|
|
4379
|
+
JSON.stringify({ type: "module" }, null, 2) + "\n"
|
|
4380
|
+
);
|
|
4381
|
+
await writeFile(
|
|
4382
|
+
join3(funcDir, ".vc-config.json"),
|
|
4383
|
+
JSON.stringify(buildVercelVcConfig(vercel), null, 2) + "\n"
|
|
4384
|
+
);
|
|
4385
|
+
await writeFile(
|
|
4386
|
+
join3(out, "config.json"),
|
|
4387
|
+
JSON.stringify(buildVercelOutputConfig(functionName, assetsDir), null, 2) + "\n"
|
|
4388
|
+
);
|
|
4389
|
+
console.log(
|
|
4390
|
+
`[rango] assembled .vercel/output (function: ${functionName}.func)`
|
|
4391
|
+
);
|
|
4392
|
+
}
|
|
4393
|
+
function createVercelOutputPlugin(options) {
|
|
4394
|
+
let root = process.cwd();
|
|
4395
|
+
let isBuild = false;
|
|
4396
|
+
let assetsDir = "assets";
|
|
4397
|
+
let publicDir = "";
|
|
4398
|
+
return {
|
|
4399
|
+
name: "@rangojs/router:vercel-output",
|
|
4400
|
+
configResolved(config) {
|
|
4401
|
+
root = resolve5(config.root);
|
|
4402
|
+
isBuild = config.command === "build";
|
|
4403
|
+
assetsDir = config.environments?.client?.build?.assetsDir ?? config.build?.assetsDir ?? "assets";
|
|
4404
|
+
publicDir = config.publicDir || "";
|
|
4405
|
+
},
|
|
4406
|
+
// buildApp runs once after the whole multi-environment build (rsc, client,
|
|
4407
|
+
// ssr), so dist/ is complete here. closeBundle is unusable for this: it
|
|
4408
|
+
// fires per environment, and twice for ssr (the server-reference scan and
|
|
4409
|
+
// the real build), so it would run before dist/client exists.
|
|
4410
|
+
buildApp: {
|
|
4411
|
+
order: "post",
|
|
4412
|
+
async handler() {
|
|
4413
|
+
if (!isBuild) return;
|
|
4414
|
+
await assemble(root, options, assetsDir, publicDir);
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
};
|
|
4418
|
+
}
|
|
4419
|
+
|
|
4075
4420
|
// src/vite/utils/banner.ts
|
|
4076
4421
|
var rangoVersion = package_default.version;
|
|
4077
4422
|
var _bannerPrinted = false;
|
|
@@ -4099,7 +4444,7 @@ ${dim} ${reset}${bold}\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550$
|
|
|
4099
4444
|
}
|
|
4100
4445
|
|
|
4101
4446
|
// src/vite/plugins/version-injector.ts
|
|
4102
|
-
import { resolve as
|
|
4447
|
+
import { resolve as resolve6 } from "node:path";
|
|
4103
4448
|
import * as Vite2 from "vite";
|
|
4104
4449
|
function createVersionInjectorPlugin(rscEntryPath) {
|
|
4105
4450
|
let resolvedEntryPath = "";
|
|
@@ -4110,7 +4455,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
4110
4455
|
let entryPath = rscEntryPath;
|
|
4111
4456
|
if (!entryPath) entryPath = resolveRscEntryFromConfig(config);
|
|
4112
4457
|
if (entryPath) {
|
|
4113
|
-
resolvedEntryPath =
|
|
4458
|
+
resolvedEntryPath = resolve6(config.root, entryPath);
|
|
4114
4459
|
}
|
|
4115
4460
|
},
|
|
4116
4461
|
transform(code, id) {
|
|
@@ -4219,10 +4564,10 @@ function createCjsToEsmPlugin() {
|
|
|
4219
4564
|
|
|
4220
4565
|
// src/vite/router-discovery.ts
|
|
4221
4566
|
import { createServer as createViteServer } from "vite";
|
|
4222
|
-
import { resolve as
|
|
4567
|
+
import { resolve as resolve10 } from "node:path";
|
|
4223
4568
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
4224
|
-
import { createRequire as
|
|
4225
|
-
import { pathToFileURL } from "node:url";
|
|
4569
|
+
import { createRequire as createRequire3, register } from "node:module";
|
|
4570
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
4226
4571
|
|
|
4227
4572
|
// src/vite/inject-client-debug.ts
|
|
4228
4573
|
function injectClientDebugFlag(id) {
|
|
@@ -4860,13 +5205,13 @@ function contextSet(variables, keyOrVar, value, options) {
|
|
|
4860
5205
|
import { createHash as createHash4 } from "node:crypto";
|
|
4861
5206
|
import {
|
|
4862
5207
|
copyFileSync,
|
|
4863
|
-
existsSync as
|
|
5208
|
+
existsSync as existsSync5,
|
|
4864
5209
|
mkdirSync,
|
|
4865
5210
|
rmSync,
|
|
4866
5211
|
statSync,
|
|
4867
5212
|
writeFileSync as writeFileSync2
|
|
4868
5213
|
} from "node:fs";
|
|
4869
|
-
import { resolve as
|
|
5214
|
+
import { resolve as resolve7 } from "node:path";
|
|
4870
5215
|
function encodePathParam(value) {
|
|
4871
5216
|
return String(value).split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
4872
5217
|
}
|
|
@@ -4989,7 +5334,7 @@ function resolvePrerenderError(registry, error, onError, label, elapsed, phase,
|
|
|
4989
5334
|
throw error;
|
|
4990
5335
|
}
|
|
4991
5336
|
function getStagedAssetDir(projectRoot) {
|
|
4992
|
-
return
|
|
5337
|
+
return resolve7(projectRoot, "node_modules/.rangojs-router-build/rsc-assets");
|
|
4993
5338
|
}
|
|
4994
5339
|
function resetStagedBuildAssets(projectRoot) {
|
|
4995
5340
|
rmSync(getStagedAssetDir(projectRoot), { recursive: true, force: true });
|
|
@@ -4999,8 +5344,8 @@ function stageBuildAssetModule(projectRoot, prefix, exportValue) {
|
|
|
4999
5344
|
mkdirSync(stagedDir, { recursive: true });
|
|
5000
5345
|
const contentHash = createHash4("sha256").update(exportValue).digest("hex").slice(0, 8);
|
|
5001
5346
|
const fileName = `${prefix}-${contentHash}.js`;
|
|
5002
|
-
const filePath =
|
|
5003
|
-
if (!
|
|
5347
|
+
const filePath = resolve7(stagedDir, fileName);
|
|
5348
|
+
if (!existsSync5(filePath)) {
|
|
5004
5349
|
writeFileSync2(filePath, `export default ${exportValue};
|
|
5005
5350
|
`);
|
|
5006
5351
|
}
|
|
@@ -5008,12 +5353,12 @@ function stageBuildAssetModule(projectRoot, prefix, exportValue) {
|
|
|
5008
5353
|
}
|
|
5009
5354
|
function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
5010
5355
|
const stagedDir = getStagedAssetDir(projectRoot);
|
|
5011
|
-
const distAssetsDir =
|
|
5356
|
+
const distAssetsDir = resolve7(projectRoot, "dist/rsc/assets");
|
|
5012
5357
|
mkdirSync(distAssetsDir, { recursive: true });
|
|
5013
5358
|
let totalBytes = 0;
|
|
5014
5359
|
for (const fileName of new Set(fileNames)) {
|
|
5015
|
-
const stagedPath =
|
|
5016
|
-
const distPath =
|
|
5360
|
+
const stagedPath = resolve7(stagedDir, fileName);
|
|
5361
|
+
const distPath = resolve7(distAssetsDir, fileName);
|
|
5017
5362
|
copyFileSync(stagedPath, distPath);
|
|
5018
5363
|
totalBytes += statSync(stagedPath).size;
|
|
5019
5364
|
}
|
|
@@ -5682,8 +6027,8 @@ async function discoverRouters(state, rscEnv) {
|
|
|
5682
6027
|
}
|
|
5683
6028
|
|
|
5684
6029
|
// src/vite/discovery/route-types-writer.ts
|
|
5685
|
-
import { dirname as dirname3, join as
|
|
5686
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as
|
|
6030
|
+
import { dirname as dirname3, join as join4, resolve as resolve8 } from "node:path";
|
|
6031
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync6, unlinkSync as unlinkSync2 } from "node:fs";
|
|
5687
6032
|
function filterUserNamedRoutes(manifest) {
|
|
5688
6033
|
const filtered = {};
|
|
5689
6034
|
for (const [name, pattern] of Object.entries(manifest)) {
|
|
@@ -5694,7 +6039,7 @@ function filterUserNamedRoutes(manifest) {
|
|
|
5694
6039
|
return filtered;
|
|
5695
6040
|
}
|
|
5696
6041
|
function writeGenFileIfChanged(state, outPath, source, opts) {
|
|
5697
|
-
const existing =
|
|
6042
|
+
const existing = existsSync6(outPath) ? readFileSync4(outPath, "utf-8") : null;
|
|
5698
6043
|
if (existing === source) return;
|
|
5699
6044
|
markSelfGenWrite(state, outPath, source);
|
|
5700
6045
|
writeFileSync3(outPath, source);
|
|
@@ -5712,10 +6057,10 @@ function writeRouteTypesFiles(state) {
|
|
|
5712
6057
|
if (state.perRouterManifests.length === 0) return;
|
|
5713
6058
|
try {
|
|
5714
6059
|
const entryDir = dirname3(
|
|
5715
|
-
|
|
6060
|
+
resolve8(state.projectRoot, state.resolvedEntryPath)
|
|
5716
6061
|
);
|
|
5717
|
-
const oldCombinedPath =
|
|
5718
|
-
if (
|
|
6062
|
+
const oldCombinedPath = join4(entryDir, "named-routes.gen.ts");
|
|
6063
|
+
if (existsSync6(oldCombinedPath)) {
|
|
5719
6064
|
unlinkSync2(oldCombinedPath);
|
|
5720
6065
|
console.log(
|
|
5721
6066
|
`[rango] Removed stale combined route types: ${oldCombinedPath}`
|
|
@@ -5796,7 +6141,7 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
5796
6141
|
}
|
|
5797
6142
|
|
|
5798
6143
|
// src/vite/discovery/virtual-module-codegen.ts
|
|
5799
|
-
import { dirname as dirname4, basename, join as
|
|
6144
|
+
import { dirname as dirname4, basename, join as join5 } from "node:path";
|
|
5800
6145
|
function generateRoutesManifestModule(state) {
|
|
5801
6146
|
const hasManifest = state.mergedRouteManifest && Object.keys(state.mergedRouteManifest).length > 0;
|
|
5802
6147
|
if (hasManifest) {
|
|
@@ -5811,7 +6156,7 @@ function generateRoutesManifestModule(state) {
|
|
|
5811
6156
|
/\.(tsx?|jsx?)$/,
|
|
5812
6157
|
""
|
|
5813
6158
|
);
|
|
5814
|
-
const genPath =
|
|
6159
|
+
const genPath = join5(
|
|
5815
6160
|
routerDir,
|
|
5816
6161
|
`${routerBasename}.named-routes.gen.js`
|
|
5817
6162
|
).replaceAll("\\", "/");
|
|
@@ -5896,7 +6241,7 @@ function generatePerRouterModule(state, routerId) {
|
|
|
5896
6241
|
/\.(tsx?|jsx?)$/,
|
|
5897
6242
|
""
|
|
5898
6243
|
);
|
|
5899
|
-
const genPath =
|
|
6244
|
+
const genPath = join5(
|
|
5900
6245
|
routerDir,
|
|
5901
6246
|
`${routerBasename}.named-routes.gen.js`
|
|
5902
6247
|
).replaceAll("\\", "/");
|
|
@@ -5923,13 +6268,13 @@ function generatePerRouterModule(state, routerId) {
|
|
|
5923
6268
|
}
|
|
5924
6269
|
|
|
5925
6270
|
// src/vite/discovery/bundle-postprocess.ts
|
|
5926
|
-
import { resolve as
|
|
5927
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as
|
|
6271
|
+
import { resolve as resolve9 } from "node:path";
|
|
6272
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync7 } from "node:fs";
|
|
5928
6273
|
function postprocessBundle(state) {
|
|
5929
6274
|
const hasPrerenderData = state.prerenderManifestEntries && Object.keys(state.prerenderManifestEntries).length > 0;
|
|
5930
6275
|
const hasStaticData = state.staticManifestEntries && Object.keys(state.staticManifestEntries).length > 0;
|
|
5931
6276
|
if (!hasPrerenderData && !hasStaticData) return;
|
|
5932
|
-
const rscEntryPath =
|
|
6277
|
+
const rscEntryPath = resolve9(
|
|
5933
6278
|
state.projectRoot,
|
|
5934
6279
|
"dist/rsc",
|
|
5935
6280
|
state.rscEntryFileName ?? "index.js"
|
|
@@ -5950,7 +6295,7 @@ function postprocessBundle(state) {
|
|
|
5950
6295
|
];
|
|
5951
6296
|
for (const target of evictionTargets) {
|
|
5952
6297
|
for (const info of target.infos) {
|
|
5953
|
-
const chunkPath =
|
|
6298
|
+
const chunkPath = resolve9(state.projectRoot, "dist/rsc", info.fileName);
|
|
5954
6299
|
try {
|
|
5955
6300
|
const code = readFileSync5(chunkPath, "utf-8");
|
|
5956
6301
|
const result = evictHandlerCode(
|
|
@@ -5975,7 +6320,7 @@ function postprocessBundle(state) {
|
|
|
5975
6320
|
}
|
|
5976
6321
|
state.handlerChunkInfoMap.clear();
|
|
5977
6322
|
state.staticHandlerChunkInfoMap.clear();
|
|
5978
|
-
if (hasPrerenderData &&
|
|
6323
|
+
if (hasPrerenderData && existsSync7(rscEntryPath)) {
|
|
5979
6324
|
const rscCode = readFileSync5(rscEntryPath, "utf-8");
|
|
5980
6325
|
if (!rscCode.includes("__prerender-manifest.js")) {
|
|
5981
6326
|
try {
|
|
@@ -5995,7 +6340,7 @@ function postprocessBundle(state) {
|
|
|
5995
6340
|
`export default m;`,
|
|
5996
6341
|
""
|
|
5997
6342
|
].join("\n");
|
|
5998
|
-
const manifestPath =
|
|
6343
|
+
const manifestPath = resolve9(
|
|
5999
6344
|
state.projectRoot,
|
|
6000
6345
|
"dist/rsc/__prerender-manifest.js"
|
|
6001
6346
|
);
|
|
@@ -6015,7 +6360,7 @@ function postprocessBundle(state) {
|
|
|
6015
6360
|
}
|
|
6016
6361
|
}
|
|
6017
6362
|
}
|
|
6018
|
-
if (hasStaticData &&
|
|
6363
|
+
if (hasStaticData && existsSync7(rscEntryPath)) {
|
|
6019
6364
|
const rscCode = readFileSync5(rscEntryPath, "utf-8");
|
|
6020
6365
|
if (!rscCode.includes("__static-manifest.js")) {
|
|
6021
6366
|
try {
|
|
@@ -6033,7 +6378,7 @@ function postprocessBundle(state) {
|
|
|
6033
6378
|
}
|
|
6034
6379
|
const manifestCode = `const m={${manifestEntries.join(",")}};globalThis.__STATIC_MANIFEST=m;export default m;
|
|
6035
6380
|
`;
|
|
6036
|
-
const manifestPath =
|
|
6381
|
+
const manifestPath = resolve9(
|
|
6037
6382
|
state.projectRoot,
|
|
6038
6383
|
"dist/rsc/__static-manifest.js"
|
|
6039
6384
|
);
|
|
@@ -6065,8 +6410,8 @@ function createDiscoveryGate(s, debug11) {
|
|
|
6065
6410
|
let pendingEvents = false;
|
|
6066
6411
|
const beginGate = () => {
|
|
6067
6412
|
if (gatePending) return;
|
|
6068
|
-
s.discoveryDone = new Promise((
|
|
6069
|
-
gateResolver =
|
|
6413
|
+
s.discoveryDone = new Promise((resolve12) => {
|
|
6414
|
+
gateResolver = resolve12;
|
|
6070
6415
|
});
|
|
6071
6416
|
gatePending = true;
|
|
6072
6417
|
};
|
|
@@ -6158,15 +6503,15 @@ function selectForwardableResolvePlugins(plugins) {
|
|
|
6158
6503
|
}
|
|
6159
6504
|
function pickForwardedRunnerConfig(config) {
|
|
6160
6505
|
const r = config.resolve ?? {};
|
|
6161
|
-
const
|
|
6162
|
-
if (r.alias !== void 0)
|
|
6163
|
-
if (r.dedupe !== void 0)
|
|
6164
|
-
if (r.conditions !== void 0)
|
|
6165
|
-
if (r.mainFields !== void 0)
|
|
6166
|
-
if (r.extensions !== void 0)
|
|
6506
|
+
const resolve12 = {};
|
|
6507
|
+
if (r.alias !== void 0) resolve12.alias = r.alias;
|
|
6508
|
+
if (r.dedupe !== void 0) resolve12.dedupe = r.dedupe;
|
|
6509
|
+
if (r.conditions !== void 0) resolve12.conditions = r.conditions;
|
|
6510
|
+
if (r.mainFields !== void 0) resolve12.mainFields = r.mainFields;
|
|
6511
|
+
if (r.extensions !== void 0) resolve12.extensions = r.extensions;
|
|
6167
6512
|
if (r.preserveSymlinks !== void 0)
|
|
6168
|
-
|
|
6169
|
-
if (r.tsconfigPaths !== void 0)
|
|
6513
|
+
resolve12.preserveSymlinks = r.preserveSymlinks;
|
|
6514
|
+
if (r.tsconfigPaths !== void 0) resolve12.tsconfigPaths = r.tsconfigPaths;
|
|
6170
6515
|
const userOxc = config.oxc;
|
|
6171
6516
|
const userJsx = userOxc && typeof userOxc === "object" && typeof userOxc.jsx === "object" && userOxc.jsx !== null ? userOxc.jsx : {};
|
|
6172
6517
|
const oxc = userOxc && typeof userOxc === "object" ? {
|
|
@@ -6174,7 +6519,7 @@ function pickForwardedRunnerConfig(config) {
|
|
|
6174
6519
|
jsx: { ...userJsx, runtime: "automatic", importSource: "react" }
|
|
6175
6520
|
} : { jsx: { runtime: "automatic", importSource: "react" } };
|
|
6176
6521
|
return {
|
|
6177
|
-
resolve:
|
|
6522
|
+
resolve: resolve12,
|
|
6178
6523
|
define: config.define,
|
|
6179
6524
|
oxc
|
|
6180
6525
|
};
|
|
@@ -6252,11 +6597,11 @@ async function resolveBuildEnv(option, factoryCtx) {
|
|
|
6252
6597
|
);
|
|
6253
6598
|
}
|
|
6254
6599
|
try {
|
|
6255
|
-
const userRequire =
|
|
6256
|
-
|
|
6600
|
+
const userRequire = createRequire3(
|
|
6601
|
+
resolve10(factoryCtx.root, "package.json")
|
|
6257
6602
|
);
|
|
6258
6603
|
const wranglerPath = userRequire.resolve("wrangler");
|
|
6259
|
-
const { getPlatformProxy } = await import(
|
|
6604
|
+
const { getPlatformProxy } = await import(pathToFileURL2(wranglerPath).href);
|
|
6260
6605
|
const proxy = await getPlatformProxy();
|
|
6261
6606
|
return {
|
|
6262
6607
|
env: proxy.env,
|
|
@@ -6353,8 +6698,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
6353
6698
|
if (globalThis.__rscRouterDiscoveryActive) return;
|
|
6354
6699
|
s.devServer = server;
|
|
6355
6700
|
let resolveDiscovery;
|
|
6356
|
-
const discoveryPromise = new Promise((
|
|
6357
|
-
resolveDiscovery =
|
|
6701
|
+
const discoveryPromise = new Promise((resolve12) => {
|
|
6702
|
+
resolveDiscovery = resolve12;
|
|
6358
6703
|
});
|
|
6359
6704
|
const gate = createDiscoveryGate(s, debugDiscovery);
|
|
6360
6705
|
const beginDiscoveryGate = gate.beginGate;
|
|
@@ -6936,7 +7281,7 @@ ${err.stack}`
|
|
|
6936
7281
|
if (hasCreateRouter) {
|
|
6937
7282
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
6938
7283
|
...s.cachedRouterFiles ?? [],
|
|
6939
|
-
|
|
7284
|
+
resolve10(filePath)
|
|
6940
7285
|
]);
|
|
6941
7286
|
if (nestedRouterConflict) {
|
|
6942
7287
|
server.config.logger.error(
|
|
@@ -7248,7 +7593,11 @@ async function rango(options) {
|
|
|
7248
7593
|
];
|
|
7249
7594
|
const pkg = getPublishedPackageName();
|
|
7250
7595
|
const nested = (spec) => `${pkg} > ${spec}`;
|
|
7251
|
-
const routerRef = {
|
|
7596
|
+
const routerRef = {
|
|
7597
|
+
path: void 0,
|
|
7598
|
+
kind: "router"
|
|
7599
|
+
};
|
|
7600
|
+
const explicitHostRouter = preset !== "cloudflare" ? resolvedOptions.hostRouter : void 0;
|
|
7252
7601
|
const prerenderEnabled = true;
|
|
7253
7602
|
if (preset === "cloudflare") {
|
|
7254
7603
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
@@ -7356,17 +7705,49 @@ async function rango(options) {
|
|
|
7356
7705
|
name: "@rangojs/router:auto-discover",
|
|
7357
7706
|
config(userConfig) {
|
|
7358
7707
|
if (routerRef.path) return;
|
|
7359
|
-
const root = userConfig.root ?
|
|
7708
|
+
const root = userConfig.root ? resolve11(process.cwd(), userConfig.root) : process.cwd();
|
|
7709
|
+
const toRootRelative = (abs) => (abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs).replaceAll("\\", "/");
|
|
7710
|
+
const bulletList = (files) => files.map((f) => " - " + toRootRelative(f)).join("\n");
|
|
7711
|
+
if (explicitHostRouter) {
|
|
7712
|
+
routerRef.path = normalizeHostRouterEntry(
|
|
7713
|
+
explicitHostRouter,
|
|
7714
|
+
root,
|
|
7715
|
+
existsSync8
|
|
7716
|
+
);
|
|
7717
|
+
routerRef.kind = "host";
|
|
7718
|
+
return;
|
|
7719
|
+
}
|
|
7720
|
+
const hostCandidates = findHostRouterFiles(root);
|
|
7721
|
+
if (hostCandidates.length === 1) {
|
|
7722
|
+
const hostPath = toRootRelative(hostCandidates[0]);
|
|
7723
|
+
console.info(
|
|
7724
|
+
`[rango] Serving host router entry ${hostPath} (auto-detected). Set the \`hostRouter\` option to override.`
|
|
7725
|
+
);
|
|
7726
|
+
routerRef.path = hostPath;
|
|
7727
|
+
routerRef.kind = "host";
|
|
7728
|
+
return;
|
|
7729
|
+
}
|
|
7730
|
+
if (hostCandidates.length > 1) {
|
|
7731
|
+
throw new Error(
|
|
7732
|
+
`[rango] Multiple host routers found:
|
|
7733
|
+
${bulletList(hostCandidates)}
|
|
7734
|
+
|
|
7735
|
+
Set the \`hostRouter\` option to the entry to serve, e.g. rango({ preset: "${preset}", hostRouter: "./src/worker.rsc.tsx" }).`
|
|
7736
|
+
);
|
|
7737
|
+
}
|
|
7360
7738
|
const candidates = findRouterFiles(root);
|
|
7361
7739
|
if (candidates.length === 1) {
|
|
7362
|
-
|
|
7363
|
-
routerRef.
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
${
|
|
7740
|
+
routerRef.path = toRootRelative(candidates[0]);
|
|
7741
|
+
routerRef.kind = "router";
|
|
7742
|
+
return;
|
|
7743
|
+
}
|
|
7744
|
+
if (candidates.length > 1) {
|
|
7745
|
+
throw new Error(
|
|
7746
|
+
`[rango] Multiple routers found:
|
|
7747
|
+
${bulletList(candidates)}
|
|
7748
|
+
|
|
7749
|
+
If this is a multi-app host router, export a createHostRouter() instance and set the \`hostRouter\` option (e.g. rango({ preset: "${preset}", hostRouter: "./src/worker.rsc.tsx" })), or use preset: "cloudflare" where you own the worker entry.`
|
|
7750
|
+
);
|
|
7370
7751
|
}
|
|
7371
7752
|
}
|
|
7372
7753
|
});
|
|
@@ -7380,8 +7761,11 @@ ${list}`);
|
|
|
7380
7761
|
plugins.push({
|
|
7381
7762
|
name: "@rangojs/router:rsc-integration",
|
|
7382
7763
|
enforce: "pre",
|
|
7383
|
-
config() {
|
|
7764
|
+
config(_userConfig, configEnv) {
|
|
7765
|
+
const vercelDefine = preset === "vercel" && configEnv.command === "build" ? { "process.env.NODE_ENV": JSON.stringify("production") } : void 0;
|
|
7766
|
+
const vercelServerEnv = preset === "vercel" && configEnv.command === "build" ? { resolve: { noExternal: true } } : void 0;
|
|
7384
7767
|
return {
|
|
7768
|
+
...vercelDefine ? { define: vercelDefine } : {},
|
|
7385
7769
|
optimizeDeps: {
|
|
7386
7770
|
exclude: excludeDeps,
|
|
7387
7771
|
rolldownOptions: sharedRolldownOptions
|
|
@@ -7424,6 +7808,7 @@ ${list}`);
|
|
|
7424
7808
|
}
|
|
7425
7809
|
},
|
|
7426
7810
|
ssr: {
|
|
7811
|
+
...vercelServerEnv ?? {},
|
|
7427
7812
|
optimizeDeps: {
|
|
7428
7813
|
entries: [VIRTUAL_IDS.ssr],
|
|
7429
7814
|
include: [
|
|
@@ -7442,6 +7827,7 @@ ${list}`);
|
|
|
7442
7827
|
}
|
|
7443
7828
|
},
|
|
7444
7829
|
rsc: {
|
|
7830
|
+
...vercelServerEnv ?? {},
|
|
7445
7831
|
optimizeDeps: {
|
|
7446
7832
|
entries: [VIRTUAL_IDS.rsc],
|
|
7447
7833
|
include: [
|
|
@@ -7467,7 +7853,11 @@ ${list}`);
|
|
|
7467
7853
|
configResolved(config) {
|
|
7468
7854
|
if (showBanner) {
|
|
7469
7855
|
const mode = config.command === "serve" ? process.argv.includes("preview") ? "preview" : "dev" : "build";
|
|
7470
|
-
printBanner(
|
|
7856
|
+
printBanner(
|
|
7857
|
+
mode,
|
|
7858
|
+
preset === "vercel" ? "vercel" : "node",
|
|
7859
|
+
rangoVersion
|
|
7860
|
+
);
|
|
7471
7861
|
}
|
|
7472
7862
|
const rscMinimalCount = config.plugins.filter(
|
|
7473
7863
|
(p) => p.name === "rsc:minimal"
|
|
@@ -7529,6 +7919,11 @@ ${list}`);
|
|
|
7529
7919
|
clientChunkCtx
|
|
7530
7920
|
})
|
|
7531
7921
|
);
|
|
7922
|
+
if (preset === "vercel") {
|
|
7923
|
+
plugins.push(
|
|
7924
|
+
createVercelOutputPlugin(resolvedOptions)
|
|
7925
|
+
);
|
|
7926
|
+
}
|
|
7532
7927
|
debugConfig?.(
|
|
7533
7928
|
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
7534
7929
|
preset,
|