@vercel/backends 0.8.30 → 0.8.33
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.d.mts +9 -2
- package/dist/index.mjs +235 -99
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -3,8 +3,15 @@ import { BuildOptions, BuildV2, DetectEntrypointFn, Files, PrepareCache, ShouldS
|
|
|
3
3
|
import { ParseArgsConfig } from "node:util";
|
|
4
4
|
|
|
5
5
|
//#region src/find-entrypoint.d.ts
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
type FindEntrypointOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* Project setting `outputDirectory`. When set, the search is exclusive to
|
|
9
|
+
* that directory, matching the wrapper builders.
|
|
10
|
+
*/
|
|
11
|
+
outputDirectory?: string;
|
|
12
|
+
};
|
|
13
|
+
declare const findEntrypoint: (cwd: string, options?: FindEntrypointOptions) => Promise<string | undefined>;
|
|
14
|
+
declare const findEntrypointOrThrow: (cwd: string, options?: FindEntrypointOptions) => Promise<string>;
|
|
8
15
|
/**
|
|
9
16
|
* Normalized entrypoint detector for Node services. Wraps {@link findEntrypoint}
|
|
10
17
|
* and returns the result in the shared {@link DetectedEntrypoint} shape consumed
|
package/dist/index.mjs
CHANGED
|
@@ -75,15 +75,64 @@ const diagnostics = createDiagnostics("node");
|
|
|
75
75
|
|
|
76
76
|
//#endregion
|
|
77
77
|
//#region src/find-entrypoint.ts
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Entrypoint detection modeled on the framework wrapper builders
|
|
80
|
+
* (`@vercel/express`, `@vercel/hono`, ... — see
|
|
81
|
+
* `packages/build-utils/src/generate-node-builder-functions.ts`), but
|
|
82
|
+
* deliberately a *permissive union* with this builder's historical behavior
|
|
83
|
+
* so that neither wrapper migrations nor existing `@vercel/backends` flag
|
|
84
|
+
* users start failing:
|
|
85
|
+
*
|
|
86
|
+
* 1. If `outputDirectory` is configured, search there first (wrapper
|
|
87
|
+
* preference) — but fall through to the source tree instead of erroring
|
|
88
|
+
* when nothing is found (historical backends behavior: `outputDirectory`
|
|
89
|
+
* never blocked detection).
|
|
90
|
+
* 2. Search well-known filenames in the project root, requiring the file to
|
|
91
|
+
* import the detected framework (wrapper behavior).
|
|
92
|
+
* 3. Fall back to `package.json#main` when it points at an existing file —
|
|
93
|
+
* without requiring a framework import (historical backends behavior;
|
|
94
|
+
* the wrappers additionally gate `main` on the import, but relaxing the
|
|
95
|
+
* gate only accepts more projects, never fewer).
|
|
96
|
+
*
|
|
97
|
+
* When no framework dependency is recognized, the framework-import gate is
|
|
98
|
+
* skipped and the first existing well-known file (or `main`) wins.
|
|
99
|
+
*/
|
|
100
|
+
const entrypointExtensions = [
|
|
101
|
+
"js",
|
|
102
|
+
"cjs",
|
|
103
|
+
"mjs",
|
|
104
|
+
"ts",
|
|
105
|
+
"cts",
|
|
106
|
+
"mts"
|
|
107
|
+
];
|
|
108
|
+
/**
|
|
109
|
+
* Wrapper builders search app/index/server (+src). Historical backends also
|
|
110
|
+
* searched main/src/main for every framework; keep them appended so
|
|
111
|
+
* existing users don't lose their entrypoint.
|
|
112
|
+
*/
|
|
113
|
+
const DEFAULT_FILENAMES = [
|
|
114
|
+
"app",
|
|
115
|
+
"index",
|
|
116
|
+
"server",
|
|
117
|
+
"src/app",
|
|
118
|
+
"src/index",
|
|
119
|
+
"src/server",
|
|
120
|
+
"main",
|
|
121
|
+
"src/main"
|
|
85
122
|
];
|
|
86
|
-
|
|
123
|
+
/** NestJS conventionally uses `src/main.ts`; its wrapper prefers `src/` first. */
|
|
124
|
+
const NESTJS_FILENAMES = [
|
|
125
|
+
"src/main",
|
|
126
|
+
"src/app",
|
|
127
|
+
"src/index",
|
|
128
|
+
"src/server",
|
|
129
|
+
"main",
|
|
130
|
+
"app",
|
|
131
|
+
"index",
|
|
132
|
+
"server"
|
|
133
|
+
];
|
|
134
|
+
/** Used when no framework dependency is recognized (historical backends order). */
|
|
135
|
+
const GENERIC_FILENAMES = [
|
|
87
136
|
"app",
|
|
88
137
|
"index",
|
|
89
138
|
"server",
|
|
@@ -93,62 +142,129 @@ const entrypointFilenames = [
|
|
|
93
142
|
"src/server",
|
|
94
143
|
"src/main"
|
|
95
144
|
];
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
145
|
+
/**
|
|
146
|
+
* `@nestjs/core` is listed first: Nest apps commonly also depend on `express`
|
|
147
|
+
* (via `@nestjs/platform-express`), and their entrypoints import
|
|
148
|
+
* `@nestjs/core`, not `express`.
|
|
149
|
+
*/
|
|
150
|
+
const FRAMEWORKS = [
|
|
151
|
+
{
|
|
152
|
+
dependency: "@nestjs/core",
|
|
153
|
+
name: "nestjs",
|
|
154
|
+
filenames: NESTJS_FILENAMES
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
dependency: "express",
|
|
158
|
+
name: "express",
|
|
159
|
+
filenames: DEFAULT_FILENAMES
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
dependency: "hono",
|
|
163
|
+
name: "hono",
|
|
164
|
+
filenames: DEFAULT_FILENAMES
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
dependency: "elysia",
|
|
168
|
+
name: "elysia",
|
|
169
|
+
filenames: DEFAULT_FILENAMES
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
dependency: "fastify",
|
|
173
|
+
name: "fastify",
|
|
174
|
+
filenames: DEFAULT_FILENAMES
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
dependency: "koa",
|
|
178
|
+
name: "koa",
|
|
179
|
+
filenames: DEFAULT_FILENAMES
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
dependency: "h3",
|
|
183
|
+
name: "h3",
|
|
184
|
+
filenames: DEFAULT_FILENAMES
|
|
185
|
+
}
|
|
103
186
|
];
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
const
|
|
187
|
+
const toCandidates = (filenames) => filenames.flatMap((filename) => entrypointExtensions.map((extension) => `${filename}.${extension}`));
|
|
188
|
+
const entrypointsForMessage = (filenames) => filenames.map((filename) => `- ${filename}.{${entrypointExtensions.join(",")}}`).join("\n");
|
|
189
|
+
const createFrameworkRegex = (dependency) => new RegExp(`(?:from|require|import)\\s*(?:\\(\\s*)?["']${dependency}["']\\s*(?:\\))?`, "g");
|
|
190
|
+
const pluralize = (word, count) => count === 1 ? word : `${word}s`;
|
|
191
|
+
/** Returns true/false for readable files, null when unreadable/missing. */
|
|
192
|
+
const matchesFramework = async (absolutePath, spec) => {
|
|
193
|
+
try {
|
|
194
|
+
return (await readFile(absolutePath, "utf-8")).match(createFrameworkRegex(spec.dependency)) !== null;
|
|
195
|
+
} catch {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const searchDirectory = async (dir, framework, filenames) => {
|
|
200
|
+
const existing = toCandidates(filenames).filter((candidate) => existsSync(join(dir, candidate)));
|
|
201
|
+
if (!framework) return {
|
|
202
|
+
entrypoint: existing[0],
|
|
203
|
+
entrypointsNotMatchingRegex: []
|
|
204
|
+
};
|
|
205
|
+
const matching = [];
|
|
206
|
+
const entrypointsNotMatchingRegex = [];
|
|
207
|
+
for (const candidate of existing) {
|
|
208
|
+
const matches = await matchesFramework(join(dir, candidate), framework);
|
|
209
|
+
if (matches === true) matching.push(candidate);
|
|
210
|
+
else if (matches === false) entrypointsNotMatchingRegex.push(candidate);
|
|
211
|
+
}
|
|
212
|
+
const entrypoint = matching[0];
|
|
213
|
+
if (matching.length > 1) console.warn(`Multiple entrypoints found: ${matching.join(", ")}. Using ${entrypoint}.`);
|
|
214
|
+
return {
|
|
215
|
+
entrypoint,
|
|
216
|
+
entrypointsNotMatchingRegex
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
const findMainEntrypoint = async (cwd, packageJsonObject) => {
|
|
220
|
+
const main = packageJsonObject && typeof packageJsonObject.main === "string" ? packageJsonObject.main.trim() : "";
|
|
221
|
+
if (!main) return void 0;
|
|
222
|
+
const abs = resolve(cwd, main);
|
|
223
|
+
const rel = relative(cwd, abs);
|
|
224
|
+
if (rel.startsWith("..") || rel === "") return void 0;
|
|
225
|
+
if (!existsSync(abs)) return void 0;
|
|
226
|
+
try {
|
|
227
|
+
await readFile(abs, "utf-8");
|
|
228
|
+
} catch {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
return rel.split(sep).join("/");
|
|
232
|
+
};
|
|
233
|
+
const resolveEntrypoint = async (cwd, options) => {
|
|
107
234
|
let packageJsonObject = null;
|
|
108
235
|
try {
|
|
109
236
|
const packageJson = await readFile(join(cwd, "package.json"), "utf-8");
|
|
110
237
|
packageJsonObject = JSON.parse(packageJson);
|
|
111
238
|
} catch (_) {}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
} catch {}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
let framework;
|
|
124
|
-
if (packageJsonObject) framework = frameworks.find((framework$1) => packageJsonObject.dependencies?.[framework$1]);
|
|
125
|
-
if (!framework) for (const entrypoint of entrypoints) {
|
|
126
|
-
const entrypointPath = join(cwd, entrypoint);
|
|
127
|
-
try {
|
|
128
|
-
await readFile(entrypointPath, "utf-8");
|
|
129
|
-
return entrypoint;
|
|
130
|
-
} catch (_) {}
|
|
131
|
-
}
|
|
132
|
-
const regex = framework ? createFrameworkRegex(framework) : void 0;
|
|
133
|
-
for (const entrypoint of entrypoints) {
|
|
134
|
-
const entrypointPath = join(cwd, entrypoint);
|
|
135
|
-
try {
|
|
136
|
-
const content = await readFile(entrypointPath, "utf-8");
|
|
137
|
-
if (regex) {
|
|
138
|
-
if (regex.test(content)) return entrypoint;
|
|
139
|
-
}
|
|
140
|
-
} catch (_) {}
|
|
239
|
+
const framework = packageJsonObject ? FRAMEWORKS.find((spec) => packageJsonObject.dependencies?.[spec.dependency]) : void 0;
|
|
240
|
+
const filenames = framework ? framework.filenames : GENERIC_FILENAMES;
|
|
241
|
+
const searchedForMessage = entrypointsForMessage(filenames);
|
|
242
|
+
const noMatchingImportError = (candidates) => /* @__PURE__ */ new Error(`No entrypoint found which imports ${framework.name}. Found possible ${pluralize("entrypoint", candidates.length)}: ${candidates.join(", ")}`);
|
|
243
|
+
const dir = options?.outputDirectory?.replace(/^\/+|\/+$/g, "");
|
|
244
|
+
if (dir) {
|
|
245
|
+
const { entrypoint: outputDirEntrypoint } = await searchDirectory(join(cwd, dir), framework, filenames);
|
|
246
|
+
if (outputDirEntrypoint) return { entrypoint: join(dir, outputDirEntrypoint).split(sep).join("/") };
|
|
141
247
|
}
|
|
248
|
+
const { entrypoint, entrypointsNotMatchingRegex } = await searchDirectory(cwd, framework, filenames);
|
|
249
|
+
if (entrypoint) return { entrypoint };
|
|
250
|
+
const mainEntrypoint = await findMainEntrypoint(cwd, packageJsonObject);
|
|
251
|
+
if (mainEntrypoint) return { entrypoint: mainEntrypoint };
|
|
252
|
+
if (framework && entrypointsNotMatchingRegex.length > 0) return { error: noMatchingImportError(entrypointsNotMatchingRegex) };
|
|
253
|
+
if (framework) return { error: /* @__PURE__ */ new Error(`No entrypoint found. Searched for:\n${searchedForMessage}`) };
|
|
254
|
+
return { error: /* @__PURE__ */ new Error(`No entrypoint found in "${cwd}". Set package.json "main" to a server file, or add one of: ${toCandidates(filenames).join(", ")}`) };
|
|
142
255
|
};
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
if (!entrypoint) throw new Error(`No entrypoint found in "${cwd}". Set package.json "main" to a server file, or add one of: ${entrypoints.join(", ")}`);
|
|
146
|
-
return entrypoint;
|
|
256
|
+
const findEntrypoint = async (cwd, options) => {
|
|
257
|
+
return (await resolveEntrypoint(cwd, options)).entrypoint;
|
|
147
258
|
};
|
|
148
|
-
const
|
|
259
|
+
const findEntrypointOrThrow = async (cwd, options) => {
|
|
260
|
+
const result = await resolveEntrypoint(cwd, options);
|
|
261
|
+
if (result.error) throw result.error;
|
|
262
|
+
return result.entrypoint;
|
|
263
|
+
};
|
|
264
|
+
const findEntrypointWithHintOrThrow = async (workPath, configured, options) => {
|
|
149
265
|
const explicit = configured && configured !== "package.json" ? configured : null;
|
|
150
266
|
if (explicit && existsSync(join(workPath, explicit))) return explicit;
|
|
151
|
-
return findEntrypointOrThrow(workPath);
|
|
267
|
+
return findEntrypointOrThrow(workPath, options);
|
|
152
268
|
};
|
|
153
269
|
/**
|
|
154
270
|
* Normalized entrypoint detector for Node services. Wraps {@link findEntrypoint}
|
|
@@ -807,22 +923,12 @@ const Colors = {
|
|
|
807
923
|
|
|
808
924
|
//#endregion
|
|
809
925
|
//#region src/typescript.ts
|
|
810
|
-
/**
|
|
811
|
-
* Typecheck via the TypeScript compiler API (`createProgram`, `getPreEmitDiagnostics`),
|
|
812
|
-
* not by spawning the `tsc` binary.
|
|
813
|
-
*
|
|
814
|
-
* We only want to validate the deployment entrypoint and its import graph, not every
|
|
815
|
-
* file matched by `tsconfig` `include`. The CLI cannot combine `--project` with explicit
|
|
816
|
-
* root files (TS5042), so expressing 'project options + entry-only roots' in one `tsc`
|
|
817
|
-
* call requires a generated tsconfig on disk. Writing beside the user's config is
|
|
818
|
-
* invasive; a temp config elsewhere often breaks `node_modules` / `@types` resolution
|
|
819
|
-
* relative to the real project. The API lets us reuse `parseJsonConfigFileContent` (same
|
|
820
|
-
* options as `-p`) with explicit `rootNames`, no files written, and a compiler host whose
|
|
821
|
-
* current directory stays `workPath`.
|
|
822
|
-
*
|
|
823
|
-
* The `typescript` package is resolved with `require` from the user's app (peer dependency), not bundled.
|
|
824
|
-
*/
|
|
825
926
|
const require_$1 = createRequire(import.meta.url);
|
|
927
|
+
const IGNORED_DIAGNOSTIC_CODES = new Set([
|
|
928
|
+
6059,
|
|
929
|
+
18002,
|
|
930
|
+
18003
|
|
931
|
+
]);
|
|
826
932
|
const typescript = (args) => {
|
|
827
933
|
const { span } = args;
|
|
828
934
|
return span.child("vc.builder.backends.tsCompile").trace(async () => {
|
|
@@ -832,7 +938,7 @@ const typescript = (args) => {
|
|
|
832
938
|
".mts",
|
|
833
939
|
".cts"
|
|
834
940
|
].includes(extension)) return;
|
|
835
|
-
const ts = resolveTypeScriptModule(args.workPath);
|
|
941
|
+
const ts = resolveTypeScriptModule(dirname(resolve(args.workPath, args.entrypoint)));
|
|
836
942
|
if (!ts) {
|
|
837
943
|
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck skipped ${Colors.gray("(TypeScript not found)")}`));
|
|
838
944
|
return null;
|
|
@@ -842,66 +948,95 @@ const typescript = (args) => {
|
|
|
842
948
|
};
|
|
843
949
|
async function doTypeCheck(args, ts) {
|
|
844
950
|
const entryAbsolute = resolve(args.workPath, args.entrypoint);
|
|
845
|
-
const tsconfig =
|
|
951
|
+
const tsconfig = findNearestTsconfig(dirname(entryAbsolute));
|
|
846
952
|
const formatDiagnostics = process.stdout.isTTY ? ts.formatDiagnosticsWithColorAndContext : ts.formatDiagnostics;
|
|
847
953
|
const diagnosticHost = {
|
|
848
954
|
getNewLine: () => ts.sys.newLine,
|
|
849
955
|
getCanonicalFileName: (fileName) => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
|
|
850
956
|
getCurrentDirectory: () => args.workPath
|
|
851
957
|
};
|
|
958
|
+
const filterIgnored = (diagnostics$1) => diagnostics$1.filter((d) => !IGNORED_DIAGNOSTIC_CODES.has(d.code));
|
|
959
|
+
const fail = (diagnostics$1) => {
|
|
960
|
+
const message = formatDiagnostics(diagnostics$1, diagnosticHost);
|
|
961
|
+
console.error("\nTypeScript type check failed:\n");
|
|
962
|
+
console.error(message);
|
|
963
|
+
throw new Error("TypeScript type check failed");
|
|
964
|
+
};
|
|
852
965
|
let options;
|
|
853
|
-
|
|
966
|
+
const rootNames = [entryAbsolute];
|
|
854
967
|
if (tsconfig) {
|
|
855
968
|
const configRead = ts.readConfigFile(tsconfig, ts.sys.readFile);
|
|
856
|
-
if (configRead.error)
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
const parsed = ts.parseJsonConfigFileContent(configRead.config, ts.sys, dirname(tsconfig), void 0, tsconfig);
|
|
863
|
-
parseDiagnostics = parsed.errors;
|
|
969
|
+
if (configRead.error) fail([configRead.error]);
|
|
970
|
+
const config = configRead.config ?? {};
|
|
971
|
+
const parsed = ts.parseJsonConfigFileContent(config, ts.sys, dirname(tsconfig), void 0, tsconfig);
|
|
972
|
+
const parseErrors = filterIgnored(parsed.errors).filter((d) => d.category === ts.DiagnosticCategory.Error);
|
|
973
|
+
if (parseErrors.length > 0) if (parsed.options.noEmitOnError) fail(parseErrors);
|
|
974
|
+
else console.error(formatDiagnostics(parseErrors, diagnosticHost));
|
|
864
975
|
options = {
|
|
865
976
|
...parsed.options,
|
|
866
977
|
noEmit: true,
|
|
867
978
|
skipLibCheck: true,
|
|
868
|
-
allowJs: true
|
|
869
|
-
esModuleInterop: true
|
|
979
|
+
allowJs: true
|
|
870
980
|
};
|
|
981
|
+
delete options.out;
|
|
982
|
+
delete options.outFile;
|
|
983
|
+
delete options.composite;
|
|
984
|
+
delete options.declarationDir;
|
|
985
|
+
delete options.declarationMap;
|
|
986
|
+
delete options.emitDeclarationOnly;
|
|
987
|
+
delete options.tsBuildInfoFile;
|
|
988
|
+
delete options.incremental;
|
|
989
|
+
if (options.target === void 0) options.target = defaultScriptTarget(ts, args.nodeVersionMajor);
|
|
990
|
+
if (options.esModuleInterop === void 0) options.esModuleInterop = true;
|
|
991
|
+
if (options.module === void 0 && options.moduleResolution === void 0) {
|
|
992
|
+
options.module = ts.ModuleKind.NodeNext;
|
|
993
|
+
options.moduleResolution = ts.ModuleResolutionKind.NodeNext;
|
|
994
|
+
options.strict = false;
|
|
995
|
+
}
|
|
996
|
+
for (const fileName of parsed.fileNames) if (/\.d\.(ts|mts|cts)$/.test(fileName) && fileName !== entryAbsolute) rootNames.push(fileName);
|
|
871
997
|
} else options = {
|
|
872
998
|
noEmit: true,
|
|
873
999
|
skipLibCheck: true,
|
|
874
1000
|
allowJs: true,
|
|
875
1001
|
esModuleInterop: true,
|
|
876
|
-
target: ts.
|
|
1002
|
+
target: defaultScriptTarget(ts, args.nodeVersionMajor),
|
|
877
1003
|
module: ts.ModuleKind.NodeNext,
|
|
878
|
-
moduleResolution: ts.ModuleResolutionKind.NodeNext
|
|
1004
|
+
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
1005
|
+
strict: false
|
|
879
1006
|
};
|
|
880
1007
|
const compilerHost = ts.createCompilerHost(options);
|
|
881
1008
|
compilerHost.getCurrentDirectory = () => args.workPath;
|
|
882
|
-
const program = ts.createProgram(
|
|
883
|
-
const errors =
|
|
1009
|
+
const program = ts.createProgram(rootNames, options, compilerHost);
|
|
1010
|
+
const errors = filterIgnored(ts.getPreEmitDiagnostics(program)).filter((d) => d.category === ts.DiagnosticCategory.Error);
|
|
884
1011
|
if (errors.length === 0) {
|
|
885
1012
|
console.log(Colors.gray(`${Colors.bold(Colors.cyan("✓"))} Typecheck complete`));
|
|
886
1013
|
return;
|
|
887
1014
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1015
|
+
fail(errors);
|
|
1016
|
+
}
|
|
1017
|
+
function defaultScriptTarget(ts, nodeVersionMajor = 16) {
|
|
1018
|
+
if (nodeVersionMajor >= 16) return ts.ScriptTarget.ES2021;
|
|
1019
|
+
if (nodeVersionMajor >= 14) return ts.ScriptTarget.ES2020;
|
|
1020
|
+
return ts.ScriptTarget.ES2019;
|
|
892
1021
|
}
|
|
893
|
-
function resolveTypeScriptModule(
|
|
1022
|
+
function resolveTypeScriptModule(startDir) {
|
|
894
1023
|
try {
|
|
895
|
-
|
|
1024
|
+
const ts = require_$1(require_$1.resolve("typescript", { paths: [startDir] }));
|
|
1025
|
+
console.log(`Using TypeScript ${ts.version} (local user-provided)`);
|
|
1026
|
+
return ts;
|
|
896
1027
|
} catch (_e) {
|
|
897
1028
|
return null;
|
|
898
1029
|
}
|
|
899
1030
|
}
|
|
900
|
-
const findNearestTsconfig =
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1031
|
+
const findNearestTsconfig = (startDir) => {
|
|
1032
|
+
let dir = resolve(startDir);
|
|
1033
|
+
for (;;) {
|
|
1034
|
+
const tsconfigPath = join(dir, "tsconfig.json");
|
|
1035
|
+
if (existsSync(tsconfigPath)) return tsconfigPath;
|
|
1036
|
+
const parent = dirname(dir);
|
|
1037
|
+
if (parent === dir) return;
|
|
1038
|
+
dir = parent;
|
|
1039
|
+
}
|
|
905
1040
|
};
|
|
906
1041
|
|
|
907
1042
|
//#endregion
|
|
@@ -2136,7 +2271,8 @@ const build = async (args) => {
|
|
|
2136
2271
|
span.setAttributes({ "builder.name": builderName });
|
|
2137
2272
|
const buildSpan = span.child("vc.builder.backends.build");
|
|
2138
2273
|
return buildSpan.trace(async () => {
|
|
2139
|
-
const
|
|
2274
|
+
const userBuildResult = await maybeDoBuildCommand(args, downloadResult);
|
|
2275
|
+
const entrypoint = await findEntrypointWithHintOrThrow(args.workPath, args.entrypoint, { outputDirectory: getOutputDirectorySetting(args.config) });
|
|
2140
2276
|
debug("Entrypoint", entrypoint);
|
|
2141
2277
|
args.entrypoint = entrypoint;
|
|
2142
2278
|
const serviceName = typeof args.config?.serviceName === "string" && args.config.serviceName !== "" ? args.config.serviceName : void 0;
|
|
@@ -2152,7 +2288,6 @@ const build = async (args) => {
|
|
|
2152
2288
|
entrypoint
|
|
2153
2289
|
});
|
|
2154
2290
|
const isCronService = cronEntries !== void 0;
|
|
2155
|
-
const userBuildResult = await maybeDoBuildCommand(args, downloadResult);
|
|
2156
2291
|
const preDeployCommand = args.config.preDeployCommand;
|
|
2157
2292
|
if (args.registerPreDeploy && typeof preDeployCommand === "string") {
|
|
2158
2293
|
const nodeBinPath = getNodeBinPaths({
|
|
@@ -2199,7 +2334,8 @@ const build = async (args) => {
|
|
|
2199
2334
|
} else typescriptPromise = typescript({
|
|
2200
2335
|
entrypoint,
|
|
2201
2336
|
workPath: args.workPath,
|
|
2202
|
-
span: buildSpan
|
|
2337
|
+
span: buildSpan,
|
|
2338
|
+
nodeVersionMajor: nodeVersion.major
|
|
2203
2339
|
});
|
|
2204
2340
|
const localBuildFiles = userBuildResult?.localBuildFiles.size > 0 ? userBuildResult?.localBuildFiles : rolldownResult.localBuildFiles;
|
|
2205
2341
|
const files = userBuildResult?.files || rolldownResult.files;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/backends",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.33",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"homepage": "https://vercel.com/docs",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"ts-morph": "12.0.0",
|
|
38
38
|
"tsx": "4.21.0",
|
|
39
39
|
"zod": "3.22.4",
|
|
40
|
-
"@vercel/
|
|
41
|
-
"@vercel/
|
|
40
|
+
"@vercel/static-config": "3.4.1",
|
|
41
|
+
"@vercel/build-utils": "14.0.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/express": "5.0.3",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"build": "tsdown",
|
|
57
57
|
"vitest-run": "vitest -c ../../vitest.config.mts",
|
|
58
58
|
"vitest": "tsdown && vitest",
|
|
59
|
-
"vitest-unit": "
|
|
59
|
+
"vitest-unit": "pnpm vitest-run --run test/unit.",
|
|
60
60
|
"type-check": "tsc --noEmit"
|
|
61
61
|
}
|
|
62
62
|
}
|