@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.
@@ -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) => { var _a; return Boolean(b.config && b.config.zeroConfig && ((_a = b.src) === null || _a === void 0 ? void 0 : _a.startsWith('api/'))); })
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 => { var _a; return b.config && b.config.zeroConfig && ((_a = b.src) === null || _a === void 0 ? void 0 : _a.startsWith('api/')); });
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
- ((_a = builder.config) === null || _a === void 0 ? void 0 : _a.zeroConfig) === true) {
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((_a = slugToFramework.get(framework || '')) === null || _a === void 0 ? void 0 : _a.ignoreRuntimes);
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
- var _a, _b;
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 = ((_a = frontendBuilder === null || frontendBuilder === void 0 ? void 0 : frontendBuilder.config) === null || _a === void 0 ? void 0 : _a.framework) || '';
691
- const isNextjs = framework === 'nextjs' || _1.isOfficialRuntime('next', frontendBuilder === null || frontendBuilder === void 0 ? void 0 : frontendBuilder.use);
692
- const ignoreRuntimes = (_b = slugToFramework.get(framework)) === null || _b === void 0 ? void 0 : _b.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 === null || pkg === void 0 ? void 0 : pkg.dependencies, pkg === null || pkg === void 0 ? void 0 : pkg.devDependencies);
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 ((vercelConfig === null || vercelConfig === void 0 ? void 0 : vercelConfig.builds) && vercelConfig.builds.length > 0) {
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((vercelConfig === null || vercelConfig === void 0 ? void 0 : vercelConfig.functions) || {}).some(fn => !!fn.runtime)) {
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 === null || projectSettings === void 0 ? void 0 : projectSettings.outputDirectory) {
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 = (frontendBuilder === null || frontendBuilder === void 0 ? void 0 : frontendBuilder.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,6 @@
1
+ /// <reference types="node" />
2
+ import fs from 'fs';
3
+ import { DetectorFilesystem } from '../detectors/filesystem';
4
+ declare type GlobFs = typeof fs;
5
+ export declare function getGlobFs(_fs: DetectorFilesystem): GlobFs;
6
+ export {};
@@ -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 && nodeVersion !== node && !meta.isDev) {
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
- var _a;
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 === null || meta === void 0 ? void 0 : meta.isDev) {
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
- ((nodeVersion === null || nodeVersion === void 0 ? void 0 : nodeVersion.major) || 0) < 16) {
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: (spawnOpts === null || spawnOpts === void 0 ? void 0 : spawnOpts.env) || {},
345
+ env: spawnOpts?.env || {},
335
346
  });
336
- debug_1.default(`Running with $PATH:`, (env === null || env === void 0 ? void 0 : env.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 === null || spawnOpts === void 0 ? void 0 : spawnOpts.env,
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 === null || pkg === void 0 ? void 0 : pkg.scripts) {
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';