@vercel/backends 0.0.62 → 0.0.63
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/dist/index.mjs +149 -182
- package/dist/rolldown/index.mjs +14 -4
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import { builtinModules, createRequire } from "node:module";
|
|
2
|
-
import { delimiter, dirname,
|
|
2
|
+
import { delimiter, dirname, join } from "path";
|
|
3
3
|
import { FileBlob, FileFsRef, NodejsLambda, Span, debug, defaultCachePathGlob, download, execCommand, getEnvForPackageManager, getLambdaOptionsFromFunction, getNodeBinPaths, getNodeVersion, glob, isBackendFramework, isBunVersion, isExperimentalBackendsWithoutIntrospectionEnabled, runNpmInstall, runPackageJsonScript, scanParentDirs } from "@vercel/build-utils";
|
|
4
4
|
import { createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { lstat, readFile, rm, stat } from "node:fs/promises";
|
|
6
|
-
import { basename, dirname as dirname$1, extname
|
|
6
|
+
import { basename, dirname as dirname$1, extname, isAbsolute, join as join$1, relative, resolve, sep } from "node:path";
|
|
7
7
|
import { build as build$2 } from "rolldown";
|
|
8
8
|
import { exports } from "resolve.exports";
|
|
9
9
|
import { isNativeError } from "node:util/types";
|
|
10
|
-
import { nodeFileTrace as nodeFileTrace$1, resolve } from "@vercel/nft";
|
|
10
|
+
import { nodeFileTrace as nodeFileTrace$1, resolve as resolve$1 } from "@vercel/nft";
|
|
11
11
|
import { transform } from "oxc-transform";
|
|
12
|
-
import { createRequire as createRequire$1 } from "module";
|
|
13
|
-
import { spawn } from "child_process";
|
|
14
|
-
import { existsSync as existsSync$1 } from "fs";
|
|
15
12
|
import execa from "execa";
|
|
16
13
|
import { readFile as readFile$1, writeFile } from "fs/promises";
|
|
17
|
-
import { spawn
|
|
14
|
+
import { spawn } from "node:child_process";
|
|
18
15
|
import { tmpdir } from "node:os";
|
|
19
16
|
import { z } from "zod";
|
|
20
17
|
|
|
@@ -46,7 +43,7 @@ async function downloadInstallAndBundle(args) {
|
|
|
46
43
|
spawnEnv
|
|
47
44
|
};
|
|
48
45
|
}
|
|
49
|
-
async function maybeExecBuildCommand(args, { spawnEnv
|
|
46
|
+
async function maybeExecBuildCommand(args, { spawnEnv }) {
|
|
50
47
|
const projectBuildCommand = args.config.projectSettings?.buildCommand;
|
|
51
48
|
if (projectBuildCommand) {
|
|
52
49
|
const nodeBinPath = getNodeBinPaths({
|
|
@@ -61,7 +58,7 @@ async function maybeExecBuildCommand(args, { spawnEnv, entrypointFsDirname }) {
|
|
|
61
58
|
cwd: args.workPath
|
|
62
59
|
});
|
|
63
60
|
}
|
|
64
|
-
return runPackageJsonScript(
|
|
61
|
+
return runPackageJsonScript(args.workPath, ["build"], { env: spawnEnv }, args.config.projectSettings?.createdAt);
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
//#endregion
|
|
@@ -93,7 +90,7 @@ const plugin = (args) => {
|
|
|
93
90
|
* Determine if a resolved module is CommonJS based on package.json exports
|
|
94
91
|
*/
|
|
95
92
|
const isCommonJS = async (bareImport, resolvedPath, resolvedInfo) => {
|
|
96
|
-
const ext = extname
|
|
93
|
+
const ext = extname(resolvedPath);
|
|
97
94
|
if (ext === ".cjs") return true;
|
|
98
95
|
if (ext === ".mjs") return false;
|
|
99
96
|
if (ext === ".js" || ext === ".ts") {
|
|
@@ -231,7 +228,7 @@ const nodeFileTrace = async (args) => {
|
|
|
231
228
|
ts: true,
|
|
232
229
|
mixedModules: true,
|
|
233
230
|
async resolve(id, parent, job, cjsResolve) {
|
|
234
|
-
return resolve(id, parent, job, cjsResolve);
|
|
231
|
+
return resolve$1(id, parent, job, cjsResolve);
|
|
235
232
|
},
|
|
236
233
|
async readFile(fsPath) {
|
|
237
234
|
try {
|
|
@@ -276,7 +273,7 @@ var __dirname = typeof __dirname !== 'undefined' ? __dirname : __dirname_(__file
|
|
|
276
273
|
const rolldown$1 = async (args) => {
|
|
277
274
|
const entrypointPath = join$1(args.workPath, args.entrypoint);
|
|
278
275
|
const outputDir = join$1(args.workPath, args.out);
|
|
279
|
-
const extension = extname
|
|
276
|
+
const extension = extname(args.entrypoint);
|
|
280
277
|
const extensionMap = {
|
|
281
278
|
".ts": {
|
|
282
279
|
format: "auto",
|
|
@@ -407,9 +404,24 @@ const Colors = {
|
|
|
407
404
|
};
|
|
408
405
|
|
|
409
406
|
//#endregion
|
|
410
|
-
//#region src/
|
|
411
|
-
|
|
412
|
-
|
|
407
|
+
//#region src/typescript.ts
|
|
408
|
+
/**
|
|
409
|
+
* Typecheck via the TypeScript compiler API (`createProgram`, `getPreEmitDiagnostics`),
|
|
410
|
+
* not by spawning the `tsc` binary.
|
|
411
|
+
*
|
|
412
|
+
* We only want to validate the deployment entrypoint and its import graph, not every
|
|
413
|
+
* file matched by `tsconfig` `include`. The CLI cannot combine `--project` with explicit
|
|
414
|
+
* root files (TS5042), so expressing 'project options + entry-only roots' in one `tsc`
|
|
415
|
+
* call requires a generated tsconfig on disk. Writing beside the user's config is
|
|
416
|
+
* invasive; a temp config elsewhere often breaks `node_modules` / `@types` resolution
|
|
417
|
+
* relative to the real project. The API lets us reuse `parseJsonConfigFileContent` (same
|
|
418
|
+
* options as `-p`) with explicit `rootNames`, no files written, and a compiler host whose
|
|
419
|
+
* current directory stays `workPath`.
|
|
420
|
+
*
|
|
421
|
+
* The `typescript` package is resolved with `require` from the user's app (peer dependency), not bundled.
|
|
422
|
+
*/
|
|
423
|
+
const require_ = createRequire(import.meta.url);
|
|
424
|
+
const typescript = (args) => {
|
|
413
425
|
const { span } = args;
|
|
414
426
|
return span.child("vc.builder.backends.tsCompile").trace(async () => {
|
|
415
427
|
const extension = extname(args.entrypoint);
|
|
@@ -418,79 +430,76 @@ const typescript$1 = (args) => {
|
|
|
418
430
|
".mts",
|
|
419
431
|
".cts"
|
|
420
432
|
].includes(extension)) return;
|
|
421
|
-
const
|
|
422
|
-
if (!
|
|
433
|
+
const ts = resolveTypeScriptModule(args.workPath);
|
|
434
|
+
if (!ts) {
|
|
423
435
|
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck skipped ${Colors.gray("(TypeScript not found)")}`));
|
|
424
436
|
return null;
|
|
425
437
|
}
|
|
426
|
-
return doTypeCheck
|
|
438
|
+
return doTypeCheck(args, ts);
|
|
427
439
|
});
|
|
428
440
|
};
|
|
429
|
-
async function doTypeCheck
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
reject(err);
|
|
479
|
-
});
|
|
480
|
-
});
|
|
441
|
+
async function doTypeCheck(args, ts) {
|
|
442
|
+
const entryAbsolute = resolve(args.workPath, args.entrypoint);
|
|
443
|
+
const tsconfig = await findNearestTsconfig(args.workPath);
|
|
444
|
+
const formatDiagnostics = process.stdout.isTTY ? ts.formatDiagnosticsWithColorAndContext : ts.formatDiagnostics;
|
|
445
|
+
const diagnosticHost = {
|
|
446
|
+
getNewLine: () => ts.sys.newLine,
|
|
447
|
+
getCanonicalFileName: (fileName) => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
|
|
448
|
+
getCurrentDirectory: () => args.workPath
|
|
449
|
+
};
|
|
450
|
+
let options;
|
|
451
|
+
let parseDiagnostics = [];
|
|
452
|
+
if (tsconfig) {
|
|
453
|
+
const configRead = ts.readConfigFile(tsconfig, ts.sys.readFile);
|
|
454
|
+
if (configRead.error) {
|
|
455
|
+
const message = formatDiagnostics([configRead.error], diagnosticHost);
|
|
456
|
+
console.error("\nTypeScript type check failed:\n");
|
|
457
|
+
console.error(message);
|
|
458
|
+
throw new Error("TypeScript type check failed");
|
|
459
|
+
}
|
|
460
|
+
const parsed = ts.parseJsonConfigFileContent(configRead.config, ts.sys, dirname$1(tsconfig), void 0, tsconfig);
|
|
461
|
+
parseDiagnostics = parsed.errors;
|
|
462
|
+
options = {
|
|
463
|
+
...parsed.options,
|
|
464
|
+
noEmit: true,
|
|
465
|
+
skipLibCheck: true,
|
|
466
|
+
allowJs: true,
|
|
467
|
+
esModuleInterop: true
|
|
468
|
+
};
|
|
469
|
+
} else options = {
|
|
470
|
+
noEmit: true,
|
|
471
|
+
skipLibCheck: true,
|
|
472
|
+
allowJs: true,
|
|
473
|
+
esModuleInterop: true,
|
|
474
|
+
target: ts.ScriptTarget.ES2022,
|
|
475
|
+
module: ts.ModuleKind.NodeNext,
|
|
476
|
+
moduleResolution: ts.ModuleResolutionKind.NodeNext
|
|
477
|
+
};
|
|
478
|
+
const compilerHost = ts.createCompilerHost(options);
|
|
479
|
+
compilerHost.getCurrentDirectory = () => args.workPath;
|
|
480
|
+
const program = ts.createProgram([entryAbsolute], options, compilerHost);
|
|
481
|
+
const errors = [...parseDiagnostics, ...ts.getPreEmitDiagnostics(program)].filter((d) => d.category === ts.DiagnosticCategory.Error);
|
|
482
|
+
if (errors.length === 0) {
|
|
483
|
+
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck complete`));
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
const output = formatDiagnostics(errors, diagnosticHost);
|
|
487
|
+
console.error("\nTypeScript type check failed:\n");
|
|
488
|
+
console.error(output);
|
|
489
|
+
throw new Error("TypeScript type check failed");
|
|
481
490
|
}
|
|
482
|
-
|
|
491
|
+
function resolveTypeScriptModule(workPath) {
|
|
483
492
|
try {
|
|
484
|
-
return require_
|
|
493
|
+
return require_(require_.resolve("typescript", { paths: [workPath] }));
|
|
485
494
|
} catch (_e) {
|
|
486
495
|
return null;
|
|
487
496
|
}
|
|
488
|
-
}
|
|
489
|
-
const findNearestTsconfig
|
|
490
|
-
const tsconfigPath = join(workPath, "tsconfig.json");
|
|
491
|
-
if (existsSync
|
|
497
|
+
}
|
|
498
|
+
const findNearestTsconfig = async (workPath) => {
|
|
499
|
+
const tsconfigPath = join$1(workPath, "tsconfig.json");
|
|
500
|
+
if (existsSync(tsconfigPath)) return tsconfigPath;
|
|
492
501
|
if (workPath === "/") return;
|
|
493
|
-
return findNearestTsconfig$1(
|
|
502
|
+
return findNearestTsconfig(join$1(workPath, ".."));
|
|
494
503
|
};
|
|
495
504
|
|
|
496
505
|
//#endregion
|
|
@@ -524,12 +533,24 @@ const entrypointExtensions = [
|
|
|
524
533
|
const entrypoints = entrypointFilenames.flatMap((filename) => entrypointExtensions.map((extension) => `${filename}.${extension}`));
|
|
525
534
|
const createFrameworkRegex = (framework) => new RegExp(`(?:from|require|import)\\s*(?:\\(\\s*)?["']${framework}["']\\s*(?:\\))?`, "g");
|
|
526
535
|
const findEntrypoint = async (cwd) => {
|
|
527
|
-
let
|
|
536
|
+
let packageJsonObject = null;
|
|
528
537
|
try {
|
|
529
538
|
const packageJson = await readFile(join$1(cwd, "package.json"), "utf-8");
|
|
530
|
-
|
|
531
|
-
framework = frameworks.find((framework$1) => packageJsonObject.dependencies?.[framework$1]);
|
|
539
|
+
packageJsonObject = JSON.parse(packageJson);
|
|
532
540
|
} catch (_) {}
|
|
541
|
+
if (packageJsonObject) {
|
|
542
|
+
const main = typeof packageJsonObject.main === "string" ? packageJsonObject.main.trim() : "";
|
|
543
|
+
if (main) {
|
|
544
|
+
const abs = resolve(cwd, main);
|
|
545
|
+
const rel = relative(cwd, abs);
|
|
546
|
+
if (!rel.startsWith("..") && rel !== "") try {
|
|
547
|
+
await readFile(abs, "utf-8");
|
|
548
|
+
return rel.split(sep).join("/");
|
|
549
|
+
} catch {}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
let framework;
|
|
553
|
+
if (packageJsonObject) framework = frameworks.find((framework$1) => packageJsonObject.dependencies?.[framework$1]);
|
|
533
554
|
if (!framework) for (const entrypoint of entrypoints) {
|
|
534
555
|
const entrypointPath = join$1(cwd, entrypoint);
|
|
535
556
|
try {
|
|
@@ -550,7 +571,7 @@ const findEntrypoint = async (cwd) => {
|
|
|
550
571
|
};
|
|
551
572
|
const findEntrypointOrThrow = async (cwd) => {
|
|
552
573
|
const entrypoint = await findEntrypoint(cwd);
|
|
553
|
-
if (!entrypoint) throw new Error(`No entrypoint found in "${cwd}".
|
|
574
|
+
if (!entrypoint) throw new Error(`No entrypoint found in "${cwd}". Set package.json "main" to a server file, or add one of: ${entrypoints.join(", ")}`);
|
|
554
575
|
return entrypoint;
|
|
555
576
|
};
|
|
556
577
|
|
|
@@ -564,7 +585,7 @@ const getBuildSummary = async (outputDir) => {
|
|
|
564
585
|
const build$1 = async (args) => {
|
|
565
586
|
const entrypoint = args.entrypoint || await findEntrypointOrThrow(args.workPath);
|
|
566
587
|
const span = args.span ?? new Span({ name: "cervel-build" });
|
|
567
|
-
const [, rolldownResult] = await Promise.all([typescript
|
|
588
|
+
const [, rolldownResult] = await Promise.all([typescript({
|
|
568
589
|
entrypoint,
|
|
569
590
|
workPath: args.workPath,
|
|
570
591
|
span
|
|
@@ -625,7 +646,7 @@ const srvxOptions = {
|
|
|
625
646
|
//#endregion
|
|
626
647
|
//#region src/rolldown/resolve-format.ts
|
|
627
648
|
const resolveEntrypointAndFormat = async (args) => {
|
|
628
|
-
const extension = extname
|
|
649
|
+
const extension = extname(args.entrypoint);
|
|
629
650
|
const extensionMap = {
|
|
630
651
|
".ts": {
|
|
631
652
|
format: "auto",
|
|
@@ -678,7 +699,7 @@ const resolveEntrypointAndFormat = async (args) => {
|
|
|
678
699
|
async function applyServiceVcInit(args) {
|
|
679
700
|
const { format, extension } = await resolveShimFormat(args);
|
|
680
701
|
const handlerDir = dirname$1(args.handler);
|
|
681
|
-
const vcInitName = `${basename(args.handler, extname
|
|
702
|
+
const vcInitName = `${basename(args.handler, extname(args.handler))}.__vc_service_vc_init${extension}`;
|
|
682
703
|
const vcInitHandler = handlerDir === "." ? vcInitName : join$1(handlerDir, vcInitName);
|
|
683
704
|
const handlerImportPath = `./${basename(args.handler)}`;
|
|
684
705
|
const vcInitSource = format === "esm" ? createEsmServiceVcInit(handlerImportPath) : createCjsServiceVcInit(handlerImportPath);
|
|
@@ -700,7 +721,7 @@ async function resolveShimFormat(args) {
|
|
|
700
721
|
});
|
|
701
722
|
return {
|
|
702
723
|
format,
|
|
703
|
-
extension: extname
|
|
724
|
+
extension: extname(args.handler) || (format === "esm" ? ".mjs" : ".cjs")
|
|
704
725
|
};
|
|
705
726
|
}
|
|
706
727
|
const sharedShimPrelude = String.raw`
|
|
@@ -840,7 +861,7 @@ const nft = async (args) => {
|
|
|
840
861
|
const nftSpan = args.span.child("vc.builder.backends.nft");
|
|
841
862
|
const runNft = async () => {
|
|
842
863
|
const ignorePatterns = [...args.ignoreNodeModules ? ["**/node_modules/**"] : [], ...args.ignore ? Array.isArray(args.ignore) ? args.ignore : [args.ignore] : []];
|
|
843
|
-
const nftResult = await nodeFileTrace$1(Array.from(args.localBuildFiles), {
|
|
864
|
+
const nftResult = await nodeFileTrace$1(Array.from(args.localBuildFiles).filter((p) => existsSync(p)), {
|
|
844
865
|
base: args.repoRootPath,
|
|
845
866
|
processCwd: args.workPath,
|
|
846
867
|
ts: true,
|
|
@@ -860,7 +881,13 @@ const nft = async (args) => {
|
|
|
860
881
|
});
|
|
861
882
|
for (const file of nftResult.fileList) {
|
|
862
883
|
const absolutePath = join$1(args.repoRootPath, file);
|
|
863
|
-
|
|
884
|
+
let stats;
|
|
885
|
+
try {
|
|
886
|
+
stats = await lstat(absolutePath);
|
|
887
|
+
} catch (error) {
|
|
888
|
+
if (isNativeError(error) && "code" in error && error.code === "ENOENT") continue;
|
|
889
|
+
throw error;
|
|
890
|
+
}
|
|
864
891
|
const outputPath = file;
|
|
865
892
|
if (args.localBuildFiles.has(join$1(args.repoRootPath, outputPath))) continue;
|
|
866
893
|
if (stats.isSymbolicLink() || stats.isFile()) if (args.ignoreNodeModules) {
|
|
@@ -912,7 +939,7 @@ const rolldown = async (args) => {
|
|
|
912
939
|
}
|
|
913
940
|
};
|
|
914
941
|
const isCommonJS = async (bareImport, resolvedPath, resolvedInfo) => {
|
|
915
|
-
const ext = extname
|
|
942
|
+
const ext = extname(resolvedPath);
|
|
916
943
|
if (ext === ".cjs") return true;
|
|
917
944
|
if (ext === ".mjs") return false;
|
|
918
945
|
if (ext === ".js" || ext === ".ts") {
|
|
@@ -974,8 +1001,12 @@ const rolldown = async (args) => {
|
|
|
974
1001
|
id,
|
|
975
1002
|
external: true
|
|
976
1003
|
};
|
|
977
|
-
if (resolved?.id && isLocalImport(resolved.id))
|
|
978
|
-
|
|
1004
|
+
if (resolved?.id && isLocalImport(resolved.id)) {
|
|
1005
|
+
if (existsSync(resolved.id)) localBuildFiles.add(resolved.id);
|
|
1006
|
+
} else if (!resolved && !(isBareImport(id) && importer)) {
|
|
1007
|
+
const candidate = join$1(args.workPath, id);
|
|
1008
|
+
if (existsSync(candidate)) localBuildFiles.add(candidate);
|
|
1009
|
+
}
|
|
979
1010
|
if (importer?.startsWith(CJS_SHIM_PREFIX) && isBareImport(id)) return {
|
|
980
1011
|
id,
|
|
981
1012
|
external: true
|
|
@@ -1132,7 +1163,7 @@ const introspection = async (args) => {
|
|
|
1132
1163
|
const tempFilePath = join$1(outputTempDir, "output.txt");
|
|
1133
1164
|
const writeStream = createWriteStream(tempFilePath);
|
|
1134
1165
|
let streamClosed = false;
|
|
1135
|
-
const child = spawn
|
|
1166
|
+
const child = spawn("node", [
|
|
1136
1167
|
"-r",
|
|
1137
1168
|
rolldownCjsLoaderPath,
|
|
1138
1169
|
"--import",
|
|
@@ -1272,6 +1303,20 @@ const introspection = async (args) => {
|
|
|
1272
1303
|
|
|
1273
1304
|
//#endregion
|
|
1274
1305
|
//#region src/build.ts
|
|
1306
|
+
/**
|
|
1307
|
+
* `outputDirectory` is usually the same project setting the static builder uses
|
|
1308
|
+
* (Vite/Webpack/etc. client output). We only reuse it for the Node lambda when we
|
|
1309
|
+
* find a known server entry file under that folder; otherwise we bundle from
|
|
1310
|
+
* source with rolldown. Errors here are swallowed so static-only output trees do
|
|
1311
|
+
* not fail the build.
|
|
1312
|
+
*/
|
|
1313
|
+
async function findEntrypointInOutputDir(dir) {
|
|
1314
|
+
try {
|
|
1315
|
+
return await findEntrypoint(dir);
|
|
1316
|
+
} catch {
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1275
1320
|
const maybeDoBuildCommand = async (args, downloadResult) => {
|
|
1276
1321
|
const buildCommandResult = await maybeExecBuildCommand(args, downloadResult);
|
|
1277
1322
|
const outputSetting = args.config.outputDirectory;
|
|
@@ -1279,7 +1324,7 @@ const maybeDoBuildCommand = async (args, downloadResult) => {
|
|
|
1279
1324
|
let entrypoint;
|
|
1280
1325
|
if (buildCommandResult && outputSetting) if (outputSetting) {
|
|
1281
1326
|
const _outputDir = join$1(args.workPath, outputSetting);
|
|
1282
|
-
const _entrypoint = await
|
|
1327
|
+
const _entrypoint = await findEntrypointInOutputDir(_outputDir);
|
|
1283
1328
|
if (_entrypoint) {
|
|
1284
1329
|
outputDir = _outputDir;
|
|
1285
1330
|
entrypoint = _entrypoint;
|
|
@@ -1291,7 +1336,7 @@ const maybeDoBuildCommand = async (args, downloadResult) => {
|
|
|
1291
1336
|
]) {
|
|
1292
1337
|
const _outputDir = join$1(args.workPath, outputDirectory);
|
|
1293
1338
|
if (existsSync(_outputDir)) {
|
|
1294
|
-
const _entrypoint = await
|
|
1339
|
+
const _entrypoint = await findEntrypointInOutputDir(_outputDir);
|
|
1295
1340
|
if (_entrypoint) {
|
|
1296
1341
|
outputDir = _outputDir;
|
|
1297
1342
|
entrypoint = _entrypoint;
|
|
@@ -1313,93 +1358,6 @@ const maybeDoBuildCommand = async (args, downloadResult) => {
|
|
|
1313
1358
|
};
|
|
1314
1359
|
};
|
|
1315
1360
|
|
|
1316
|
-
//#endregion
|
|
1317
|
-
//#region src/typescript.ts
|
|
1318
|
-
const require_ = createRequire(import.meta.url);
|
|
1319
|
-
const typescript = (args) => {
|
|
1320
|
-
const { span } = args;
|
|
1321
|
-
return span.child("vc.builder.backends.tsCompile").trace(async () => {
|
|
1322
|
-
const extension = extname$1(args.entrypoint);
|
|
1323
|
-
if (![
|
|
1324
|
-
".ts",
|
|
1325
|
-
".mts",
|
|
1326
|
-
".cts"
|
|
1327
|
-
].includes(extension)) return;
|
|
1328
|
-
const tscPath = resolveTscPath(args);
|
|
1329
|
-
if (!tscPath) {
|
|
1330
|
-
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck skipped ${Colors.gray("(TypeScript not found)")}`));
|
|
1331
|
-
return null;
|
|
1332
|
-
}
|
|
1333
|
-
return doTypeCheck(args, tscPath);
|
|
1334
|
-
});
|
|
1335
|
-
};
|
|
1336
|
-
async function doTypeCheck(args, tscPath) {
|
|
1337
|
-
let stdout = "";
|
|
1338
|
-
let stderr = "";
|
|
1339
|
-
/**
|
|
1340
|
-
* This might be subject to change.
|
|
1341
|
-
* - if no tscPath, skip typecheck
|
|
1342
|
-
* - if tsconfig, provide the tsconfig path
|
|
1343
|
-
* - else provide the entrypoint path
|
|
1344
|
-
*/
|
|
1345
|
-
const tscArgs = [
|
|
1346
|
-
tscPath,
|
|
1347
|
-
"--noEmit",
|
|
1348
|
-
"--pretty",
|
|
1349
|
-
"--allowJs",
|
|
1350
|
-
"--esModuleInterop",
|
|
1351
|
-
"--skipLibCheck"
|
|
1352
|
-
];
|
|
1353
|
-
const tsconfig = await findNearestTsconfig(args.workPath);
|
|
1354
|
-
if (tsconfig) tscArgs.push("--project", tsconfig);
|
|
1355
|
-
else tscArgs.push(args.entrypoint);
|
|
1356
|
-
const child = spawn$1(process.execPath, tscArgs, {
|
|
1357
|
-
cwd: args.workPath,
|
|
1358
|
-
stdio: [
|
|
1359
|
-
"ignore",
|
|
1360
|
-
"pipe",
|
|
1361
|
-
"pipe"
|
|
1362
|
-
]
|
|
1363
|
-
});
|
|
1364
|
-
child.stdout?.on("data", (data) => {
|
|
1365
|
-
stdout += data.toString();
|
|
1366
|
-
});
|
|
1367
|
-
child.stderr?.on("data", (data) => {
|
|
1368
|
-
stderr += data.toString();
|
|
1369
|
-
});
|
|
1370
|
-
await new Promise((resolve$1, reject) => {
|
|
1371
|
-
child.on("close", (code) => {
|
|
1372
|
-
if (code === 0) {
|
|
1373
|
-
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck complete`));
|
|
1374
|
-
resolve$1();
|
|
1375
|
-
} else {
|
|
1376
|
-
const output = stdout || stderr;
|
|
1377
|
-
if (output) {
|
|
1378
|
-
console.error("\nTypeScript type check failed:\n");
|
|
1379
|
-
console.error(output);
|
|
1380
|
-
}
|
|
1381
|
-
reject(/* @__PURE__ */ new Error("TypeScript type check failed"));
|
|
1382
|
-
}
|
|
1383
|
-
});
|
|
1384
|
-
child.on("error", (err) => {
|
|
1385
|
-
reject(err);
|
|
1386
|
-
});
|
|
1387
|
-
});
|
|
1388
|
-
}
|
|
1389
|
-
const resolveTscPath = (args) => {
|
|
1390
|
-
try {
|
|
1391
|
-
return require_.resolve("typescript/bin/tsc", { paths: [args.workPath] });
|
|
1392
|
-
} catch (_e) {
|
|
1393
|
-
return null;
|
|
1394
|
-
}
|
|
1395
|
-
};
|
|
1396
|
-
const findNearestTsconfig = async (workPath) => {
|
|
1397
|
-
const tsconfigPath = join$1(workPath, "tsconfig.json");
|
|
1398
|
-
if (existsSync(tsconfigPath)) return tsconfigPath;
|
|
1399
|
-
if (workPath === "/") return;
|
|
1400
|
-
return findNearestTsconfig(join$1(workPath, ".."));
|
|
1401
|
-
};
|
|
1402
|
-
|
|
1403
1361
|
//#endregion
|
|
1404
1362
|
//#region src/introspection/index.ts
|
|
1405
1363
|
const require = createRequire(import.meta.url);
|
|
@@ -1429,7 +1387,7 @@ const introspectApp = async (args) => {
|
|
|
1429
1387
|
await new Promise((resolvePromise) => {
|
|
1430
1388
|
try {
|
|
1431
1389
|
debug("Spawning introspection process");
|
|
1432
|
-
const child = spawn
|
|
1390
|
+
const child = spawn("node", [
|
|
1433
1391
|
"-r",
|
|
1434
1392
|
cjsLoaderPath,
|
|
1435
1393
|
"--import",
|
|
@@ -1589,6 +1547,11 @@ const getFramework = (args) => {
|
|
|
1589
1547
|
//#endregion
|
|
1590
1548
|
//#region src/index.ts
|
|
1591
1549
|
const version = 2;
|
|
1550
|
+
/** Non-empty Build Command from project settings / vercel.json (not the default `build` script). */
|
|
1551
|
+
function hasExplicitBuildCommand(config) {
|
|
1552
|
+
const cmd = config.buildCommand ?? config.projectSettings?.buildCommand;
|
|
1553
|
+
return typeof cmd === "string" && cmd.trim().length > 0;
|
|
1554
|
+
}
|
|
1592
1555
|
const build = async (args) => {
|
|
1593
1556
|
const downloadResult = await downloadInstallAndBundle(args);
|
|
1594
1557
|
const nodeVersion = await getNodeVersion(args.workPath, void 0, args.config, args.meta);
|
|
@@ -1621,7 +1584,11 @@ const build = async (args) => {
|
|
|
1621
1584
|
additionalFolders: [],
|
|
1622
1585
|
additionalDeps: []
|
|
1623
1586
|
});
|
|
1624
|
-
|
|
1587
|
+
let typescriptPromise;
|
|
1588
|
+
if (hasExplicitBuildCommand(args.config)) {
|
|
1589
|
+
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck skipped ${Colors.gray("(Build Command is configured)")}`));
|
|
1590
|
+
typescriptPromise = Promise.resolve();
|
|
1591
|
+
} else typescriptPromise = typescript({
|
|
1625
1592
|
entrypoint,
|
|
1626
1593
|
workPath: args.workPath,
|
|
1627
1594
|
span: buildSpan
|
package/dist/rolldown/index.mjs
CHANGED
|
@@ -94,7 +94,7 @@ const nft = async (args) => {
|
|
|
94
94
|
const nftSpan = args.span.child("vc.builder.backends.nft");
|
|
95
95
|
const runNft = async () => {
|
|
96
96
|
const ignorePatterns = [...args.ignoreNodeModules ? ["**/node_modules/**"] : [], ...args.ignore ? Array.isArray(args.ignore) ? args.ignore : [args.ignore] : []];
|
|
97
|
-
const nftResult = await nodeFileTrace(Array.from(args.localBuildFiles), {
|
|
97
|
+
const nftResult = await nodeFileTrace(Array.from(args.localBuildFiles).filter((p) => existsSync(p)), {
|
|
98
98
|
base: args.repoRootPath,
|
|
99
99
|
processCwd: args.workPath,
|
|
100
100
|
ts: true,
|
|
@@ -114,7 +114,13 @@ const nft = async (args) => {
|
|
|
114
114
|
});
|
|
115
115
|
for (const file of nftResult.fileList) {
|
|
116
116
|
const absolutePath = join(args.repoRootPath, file);
|
|
117
|
-
|
|
117
|
+
let stats;
|
|
118
|
+
try {
|
|
119
|
+
stats = await lstat(absolutePath);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (isNativeError(error) && "code" in error && error.code === "ENOENT") continue;
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
118
124
|
const outputPath = file;
|
|
119
125
|
if (args.localBuildFiles.has(join(args.repoRootPath, outputPath))) continue;
|
|
120
126
|
if (stats.isSymbolicLink() || stats.isFile()) if (args.ignoreNodeModules) {
|
|
@@ -228,8 +234,12 @@ const rolldown = async (args) => {
|
|
|
228
234
|
id,
|
|
229
235
|
external: true
|
|
230
236
|
};
|
|
231
|
-
if (resolved?.id && isLocalImport(resolved.id))
|
|
232
|
-
|
|
237
|
+
if (resolved?.id && isLocalImport(resolved.id)) {
|
|
238
|
+
if (existsSync(resolved.id)) localBuildFiles.add(resolved.id);
|
|
239
|
+
} else if (!resolved && !(isBareImport(id) && importer)) {
|
|
240
|
+
const candidate = join(args.workPath, id);
|
|
241
|
+
if (existsSync(candidate)) localBuildFiles.add(candidate);
|
|
242
|
+
}
|
|
233
243
|
if (importer?.startsWith(CJS_SHIM_PREFIX) && isBareImport(id)) return {
|
|
234
244
|
id,
|
|
235
245
|
external: true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/backends",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.63",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"homepage": "https://vercel.com/docs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"srvx": "0.8.9",
|
|
35
35
|
"tsx": "4.21.0",
|
|
36
36
|
"zod": "3.22.4",
|
|
37
|
-
"@vercel/build-utils": "13.17.
|
|
37
|
+
"@vercel/build-utils": "13.17.1"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"typescript": "^4.0.0 || ^5.0.0"
|