@vercel/build-utils 3.1.1 → 4.1.0
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/detect-builders.js +8 -11
- package/dist/detect-file-system-api.js +5 -5
- package/dist/fs/get-glob-fs.d.ts +6 -0
- package/dist/fs/get-glob-fs.js +71 -0
- package/dist/fs/run-user-scripts.js +21 -10
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1443 -178
- package/dist/lambda.js +1 -1
- package/dist/types.d.ts +4 -3
- package/dist/workspaces/get-workspace-package-paths.d.ts +11 -0
- package/dist/workspaces/get-workspace-package-paths.js +62 -0
- package/package.json +5 -5
package/dist/detect-builders.js
CHANGED
@@ -18,7 +18,7 @@ function sortFiles(fileA, fileB) {
|
|
18
18
|
exports.sortFiles = sortFiles;
|
19
19
|
function detectApiExtensions(builders) {
|
20
20
|
return new Set(builders
|
21
|
-
.filter((b) =>
|
21
|
+
.filter((b) => Boolean(b.config && b.config.zeroConfig && b.src?.startsWith('api/')))
|
22
22
|
.map(b => path_1.extname(b.src))
|
23
23
|
.filter(Boolean));
|
24
24
|
}
|
@@ -26,18 +26,17 @@ exports.detectApiExtensions = detectApiExtensions;
|
|
26
26
|
function detectApiDirectory(builders) {
|
27
27
|
// TODO: We eventually want to save the api directory to
|
28
28
|
// builder.config.apiDirectory so it is only detected once
|
29
|
-
const found = builders.some(b =>
|
29
|
+
const found = builders.some(b => b.config && b.config.zeroConfig && b.src?.startsWith('api/'));
|
30
30
|
return found ? 'api' : null;
|
31
31
|
}
|
32
32
|
exports.detectApiDirectory = detectApiDirectory;
|
33
33
|
// TODO: Replace this function with `config.outputDirectory`
|
34
34
|
function getPublicBuilder(builders) {
|
35
|
-
var _a;
|
36
35
|
for (const builder of builders) {
|
37
36
|
if (typeof builder.src === 'string' &&
|
38
37
|
_1.isOfficialRuntime('static', builder.use) &&
|
39
38
|
/^.*\/\*\*\/\*$/.test(builder.src) &&
|
40
|
-
|
39
|
+
builder.config?.zeroConfig === true) {
|
41
40
|
return builder;
|
42
41
|
}
|
43
42
|
}
|
@@ -51,7 +50,6 @@ function detectOutputDirectory(builders) {
|
|
51
50
|
}
|
52
51
|
exports.detectOutputDirectory = detectOutputDirectory;
|
53
52
|
async function detectBuilders(files, pkg, options = {}) {
|
54
|
-
var _a;
|
55
53
|
const errors = [];
|
56
54
|
const warnings = [];
|
57
55
|
const apiBuilders = [];
|
@@ -81,7 +79,7 @@ async function detectBuilders(files, pkg, options = {}) {
|
|
81
79
|
const absolutePathCache = new Map();
|
82
80
|
const { projectSettings = {} } = options;
|
83
81
|
const { buildCommand, outputDirectory, framework } = projectSettings;
|
84
|
-
const ignoreRuntimes = new Set(
|
82
|
+
const ignoreRuntimes = new Set(slugToFramework.get(framework || '')?.ignoreRuntimes);
|
85
83
|
const withTag = options.tag ? `@${options.tag}` : '';
|
86
84
|
const apiMatches = getApiMatches()
|
87
85
|
.filter(b => !ignoreRuntimes.has(b.use))
|
@@ -676,8 +674,7 @@ function createRouteFromPath(filePath, featHandleMiss, cleanUrls) {
|
|
676
674
|
return { route, isDynamic };
|
677
675
|
}
|
678
676
|
function getRouteResult(pkg, apiRoutes, dynamicRoutes, outputDirectory, apiBuilders, frontendBuilder, options) {
|
679
|
-
|
680
|
-
const deps = Object.assign({}, pkg === null || pkg === void 0 ? void 0 : pkg.dependencies, pkg === null || pkg === void 0 ? void 0 : pkg.devDependencies);
|
677
|
+
const deps = Object.assign({}, pkg?.dependencies, pkg?.devDependencies);
|
681
678
|
const defaultRoutes = [];
|
682
679
|
const redirectRoutes = [];
|
683
680
|
const rewriteRoutes = [];
|
@@ -687,9 +684,9 @@ function getRouteResult(pkg, apiRoutes, dynamicRoutes, outputDirectory, apiBuild
|
|
687
684
|
redirectRoutes: [],
|
688
685
|
rewriteRoutes: [],
|
689
686
|
};
|
690
|
-
const framework =
|
691
|
-
const isNextjs = framework === 'nextjs' || _1.isOfficialRuntime('next', frontendBuilder
|
692
|
-
const ignoreRuntimes =
|
687
|
+
const framework = frontendBuilder?.config?.framework || '';
|
688
|
+
const isNextjs = framework === 'nextjs' || _1.isOfficialRuntime('next', frontendBuilder?.use);
|
689
|
+
const ignoreRuntimes = slugToFramework.get(framework)?.ignoreRuntimes;
|
693
690
|
if (apiRoutes && apiRoutes.length > 0) {
|
694
691
|
if (options.featHandleMiss) {
|
695
692
|
// Exclude extension names if the corresponding plugin is not found in package.json
|
@@ -14,7 +14,7 @@ const enableFileSystemApiFrameworks = new Set(['solidstart']);
|
|
14
14
|
*/
|
15
15
|
async function detectFileSystemAPI({ files, projectSettings, builders, vercelConfig, pkg, tag, enableFlag = false, }) {
|
16
16
|
const framework = projectSettings.framework || '';
|
17
|
-
const deps = Object.assign({}, pkg
|
17
|
+
const deps = Object.assign({}, pkg?.dependencies, pkg?.devDependencies);
|
18
18
|
const plugins = Object.keys(deps).filter(dep => dep.startsWith('vercel-plugin-'));
|
19
19
|
const hasDotOutput = Object.keys(files).some(file => file.startsWith('.output/'));
|
20
20
|
const hasMiddleware = Boolean(files['_middleware.js'] || files['_middleware.ts']);
|
@@ -30,14 +30,14 @@ async function detectFileSystemAPI({ files, projectSettings, builders, vercelCon
|
|
30
30
|
if (!isEnabled) {
|
31
31
|
return { metadata, fsApiBuilder: null, reason: 'Flag not enabled.' };
|
32
32
|
}
|
33
|
-
if (
|
33
|
+
if (vercelConfig?.builds && vercelConfig.builds.length > 0) {
|
34
34
|
return {
|
35
35
|
metadata,
|
36
36
|
fsApiBuilder: null,
|
37
37
|
reason: 'Detected `builds` in vercel.json. Please remove it in favor of CLI plugins.',
|
38
38
|
};
|
39
39
|
}
|
40
|
-
if (Object.values(
|
40
|
+
if (Object.values(vercelConfig?.functions || {}).some(fn => !!fn.runtime)) {
|
41
41
|
return {
|
42
42
|
metadata,
|
43
43
|
fsApiBuilder: null,
|
@@ -107,7 +107,7 @@ async function detectFileSystemAPI({ files, projectSettings, builders, vercelCon
|
|
107
107
|
// Use the old pipeline if a custom output directory was specified for Next.js
|
108
108
|
// because `vercel build` cannot ensure that the directory will be in the same
|
109
109
|
// location as `.output`, which can break imports (not just nft.json files).
|
110
|
-
if (projectSettings
|
110
|
+
if (projectSettings?.outputDirectory) {
|
111
111
|
return {
|
112
112
|
metadata,
|
113
113
|
fsApiBuilder: null,
|
@@ -154,7 +154,7 @@ async function detectFileSystemAPI({ files, projectSettings, builders, vercelCon
|
|
154
154
|
const frontendBuilder = builders.find(({ use }) => _1.isOfficialRuntime('next', use) ||
|
155
155
|
_1.isOfficialRuntime('static', use) ||
|
156
156
|
_1.isOfficialRuntime('static-build', use));
|
157
|
-
const config =
|
157
|
+
const config = frontendBuilder?.config || {};
|
158
158
|
const withTag = tag ? `@${tag}` : '';
|
159
159
|
const fsApiBuilder = {
|
160
160
|
use: `@vercelruntimes/file-system-api${withTag}`,
|
@@ -0,0 +1,71 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.getGlobFs = void 0;
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
8
|
+
function normalizePath(path) {
|
9
|
+
// on windows, this will return a path like
|
10
|
+
// D:/c/package.json
|
11
|
+
// since we abstract the filesystem, we need to remove windows specific info from the path
|
12
|
+
// and let the FS decide how to process the path
|
13
|
+
// D:/c/package.json => /c/package.json
|
14
|
+
return path.replace(/^[a-zA-Z]:/, '');
|
15
|
+
}
|
16
|
+
function getGlobFs(_fs) {
|
17
|
+
const readdir = (path, callback) => {
|
18
|
+
_fs
|
19
|
+
.readdir(normalizePath(String(path)))
|
20
|
+
.then(stats => callback(null, stats.map(stat => stat.name)))
|
21
|
+
.catch(err => callback(err, []));
|
22
|
+
};
|
23
|
+
const stat = (path, callback) => {
|
24
|
+
_fs
|
25
|
+
.isFile(normalizePath(String(path)))
|
26
|
+
.then(isPathAFile => {
|
27
|
+
callback(null, {
|
28
|
+
ino: 0,
|
29
|
+
mode: 0,
|
30
|
+
nlink: 0,
|
31
|
+
uid: 0,
|
32
|
+
gid: 0,
|
33
|
+
rdev: 0,
|
34
|
+
size: 0,
|
35
|
+
blksize: 0,
|
36
|
+
blocks: 0,
|
37
|
+
atimeMs: 0,
|
38
|
+
mtimeMs: 0,
|
39
|
+
ctimeMs: 0,
|
40
|
+
birthtimeMs: 0,
|
41
|
+
atime: new Date(),
|
42
|
+
mtime: new Date(),
|
43
|
+
ctime: new Date(),
|
44
|
+
birthtime: new Date(),
|
45
|
+
dev: 0,
|
46
|
+
isBlockDevice: () => false,
|
47
|
+
isCharacterDevice: () => false,
|
48
|
+
isDirectory: () => !isPathAFile,
|
49
|
+
isFIFO: () => false,
|
50
|
+
isFile: () => isPathAFile,
|
51
|
+
isSocket: () => false,
|
52
|
+
isSymbolicLink: () => false,
|
53
|
+
});
|
54
|
+
})
|
55
|
+
.catch(err => callback(err, null));
|
56
|
+
};
|
57
|
+
return new Proxy(fs_1.default, {
|
58
|
+
get(_target, prop) {
|
59
|
+
switch (prop) {
|
60
|
+
case 'readdir':
|
61
|
+
return readdir;
|
62
|
+
case 'lstat':
|
63
|
+
case 'stat':
|
64
|
+
return stat;
|
65
|
+
default:
|
66
|
+
throw new Error('Not Implemented');
|
67
|
+
}
|
68
|
+
},
|
69
|
+
});
|
70
|
+
}
|
71
|
+
exports.getGlobFs = getGlobFs;
|
@@ -9,6 +9,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
10
10
|
const async_sema_1 = __importDefault(require("async-sema"));
|
11
11
|
const cross_spawn_1 = __importDefault(require("cross-spawn"));
|
12
|
+
const semver_1 = require("semver");
|
12
13
|
const util_1 = require("util");
|
13
14
|
const debug_1 = __importDefault(require("../debug"));
|
14
15
|
const errors_1 = require("../errors");
|
@@ -131,9 +132,9 @@ function getSpawnOptions(meta, nodeVersion) {
|
|
131
132
|
}
|
132
133
|
exports.getSpawnOptions = getSpawnOptions;
|
133
134
|
async function getNodeVersion(destPath, _nodeVersion, config = {}, meta = {}) {
|
135
|
+
const latest = node_version_1.getLatestNodeVersion();
|
134
136
|
if (meta && meta.isDev) {
|
135
137
|
// Use the system-installed version of `node` in PATH for `vercel dev`
|
136
|
-
const latest = node_version_1.getLatestNodeVersion();
|
137
138
|
return { ...latest, runtime: 'nodejs' };
|
138
139
|
}
|
139
140
|
const { packageJson } = await scanParentDirs(destPath, true);
|
@@ -141,9 +142,20 @@ async function getNodeVersion(destPath, _nodeVersion, config = {}, meta = {}) {
|
|
141
142
|
let isAuto = true;
|
142
143
|
if (packageJson && packageJson.engines && packageJson.engines.node) {
|
143
144
|
const { node } = packageJson.engines;
|
144
|
-
if (nodeVersion &&
|
145
|
+
if (nodeVersion &&
|
146
|
+
semver_1.validRange(node) &&
|
147
|
+
!semver_1.intersects(nodeVersion, node) &&
|
148
|
+
!meta.isDev) {
|
145
149
|
console.warn(`Warning: Due to "engines": { "node": "${node}" } in your \`package.json\` file, the Node.js Version defined in your Project Settings ("${nodeVersion}") will not apply. Learn More: http://vercel.link/node-version`);
|
146
150
|
}
|
151
|
+
else if (semver_1.coerce(node)?.raw === node && !meta.isDev) {
|
152
|
+
console.warn(`Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` with major.minor.patch, but only major Node.js Version can be selected. Learn More: http://vercel.link/node-version`);
|
153
|
+
}
|
154
|
+
else if (semver_1.validRange(node) &&
|
155
|
+
semver_1.intersects(`${latest.major + 1}.x`, node) &&
|
156
|
+
!meta.isDev) {
|
157
|
+
console.warn(`Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` that will automatically upgrade when a new major Node.js Version is released. Learn More: http://vercel.link/node-version`);
|
158
|
+
}
|
147
159
|
nodeVersion = node;
|
148
160
|
isAuto = false;
|
149
161
|
}
|
@@ -227,11 +239,10 @@ async function walkParentDirs({ base, start, filename, }) {
|
|
227
239
|
}
|
228
240
|
exports.walkParentDirs = walkParentDirs;
|
229
241
|
function isSet(v) {
|
230
|
-
|
231
|
-
return ((_a = v === null || v === void 0 ? void 0 : v.constructor) === null || _a === void 0 ? void 0 : _a.name) === 'Set';
|
242
|
+
return v?.constructor?.name === 'Set';
|
232
243
|
}
|
233
244
|
async function runNpmInstall(destPath, args = [], spawnOpts, meta, nodeVersion) {
|
234
|
-
if (meta
|
245
|
+
if (meta?.isDev) {
|
235
246
|
debug_1.default('Skipping dependency installation because dev mode is enabled');
|
236
247
|
return false;
|
237
248
|
}
|
@@ -302,7 +313,7 @@ function getEnvForPackageManager({ cliType, lockfileVersion, nodeVersion, env, }
|
|
302
313
|
if (cliType === 'npm') {
|
303
314
|
if (typeof lockfileVersion === 'number' &&
|
304
315
|
lockfileVersion >= 2 &&
|
305
|
-
(
|
316
|
+
(nodeVersion?.major || 0) < 16) {
|
306
317
|
// Ensure that npm 7 is at the beginning of the `$PATH`
|
307
318
|
newEnv.PATH = `/node16/bin-npm7${path_1.default.delimiter}${env.PATH}`;
|
308
319
|
console.log('Detected `package-lock.json` generated by npm 7...');
|
@@ -331,9 +342,9 @@ async function runCustomInstallCommand({ destPath, installCommand, nodeVersion,
|
|
331
342
|
cliType,
|
332
343
|
lockfileVersion,
|
333
344
|
nodeVersion,
|
334
|
-
env:
|
345
|
+
env: spawnOpts?.env || {},
|
335
346
|
});
|
336
|
-
debug_1.default(`Running with $PATH:`,
|
347
|
+
debug_1.default(`Running with $PATH:`, env?.PATH || '');
|
337
348
|
await execCommand(installCommand, {
|
338
349
|
...spawnOpts,
|
339
350
|
env,
|
@@ -358,7 +369,7 @@ async function runPackageJsonScript(destPath, scriptNames, spawnOpts) {
|
|
358
369
|
nodeVersion: undefined,
|
359
370
|
env: {
|
360
371
|
...process.env,
|
361
|
-
...spawnOpts
|
372
|
+
...spawnOpts?.env,
|
362
373
|
},
|
363
374
|
}),
|
364
375
|
};
|
@@ -398,7 +409,7 @@ async function runPipInstall(destPath, args = [], spawnOpts, meta) {
|
|
398
409
|
}
|
399
410
|
exports.runPipInstall = runPipInstall;
|
400
411
|
function getScriptName(pkg, possibleNames) {
|
401
|
-
if (pkg
|
412
|
+
if (pkg?.scripts) {
|
402
413
|
for (const name of possibleNames) {
|
403
414
|
if (name in pkg.scripts) {
|
404
415
|
return name;
|
package/dist/index.d.ts
CHANGED
@@ -32,5 +32,6 @@ export * from './errors';
|
|
32
32
|
export declare const isOfficialRuntime: (desired: string, name?: string | undefined) => boolean;
|
33
33
|
export declare const isStaticRuntime: (name?: string | undefined) => boolean;
|
34
34
|
export { workspaceManagers } from './workspaces/workspace-managers';
|
35
|
-
export { getWorkspaces } from './workspaces/get-workspaces';
|
35
|
+
export { getWorkspaces, GetWorkspaceOptions, Workspace, WorkspaceType, } from './workspaces/get-workspaces';
|
36
|
+
export { getWorkspacePackagePaths, GetWorkspacePackagePathsOptions, } from './workspaces/get-workspace-package-paths';
|
36
37
|
export { monorepoManagers } from './monorepos/monorepo-managers';
|