@vercel/build-utils 4.2.0 → 5.0.1-canary.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.
@@ -44,6 +44,12 @@ export interface SpawnOptionsExtended extends SpawnOptions {
44
44
  * Pretty formatted command that is being spawned for logging purposes.
45
45
  */
46
46
  prettyCommand?: string;
47
+ /**
48
+ * Returns instead of throwing an error when the process exits with a
49
+ * non-0 exit code. When relevant, the returned object will include
50
+ * the error code, stdout and stderr.
51
+ */
52
+ ignoreNon0Exit?: boolean;
47
53
  }
48
54
  export declare function spawnAsync(command: string, args: string[], opts?: SpawnOptionsExtended): Promise<void>;
49
55
  export declare function execAsync(command: string, args: string[], opts?: SpawnOptionsExtended): Promise<{
@@ -53,7 +59,7 @@ export declare function execAsync(command: string, args: string[], opts?: SpawnO
53
59
  }>;
54
60
  export declare function spawnCommand(command: string, options?: SpawnOptions): import("child_process").ChildProcess;
55
61
  export declare function execCommand(command: string, options?: SpawnOptions): Promise<boolean>;
56
- export declare function getNodeBinPath({ cwd }: {
62
+ export declare function getNodeBinPath({ cwd, }: {
57
63
  cwd: string;
58
64
  }): Promise<string>;
59
65
  export declare function runShellScript(fsPath: string, args?: string[], spawnOpts?: SpawnOptions): Promise<boolean>;
@@ -27,7 +27,7 @@ function spawnAsync(command, args, opts = {}) {
27
27
  }
28
28
  child.on('error', reject);
29
29
  child.on('close', (code, signal) => {
30
- if (code === 0) {
30
+ if (code === 0 || opts.ignoreNon0Exit) {
31
31
  return resolve();
32
32
  }
33
33
  const cmd = opts.prettyCommand
@@ -57,20 +57,20 @@ function execAsync(command, args, opts = {}) {
57
57
  });
58
58
  child.on('error', reject);
59
59
  child.on('close', (code, signal) => {
60
- if (code !== 0) {
61
- const cmd = opts.prettyCommand
62
- ? `Command "${opts.prettyCommand}"`
63
- : 'Command';
64
- return reject(new errors_1.NowBuildError({
65
- code: `BUILD_UTILS_EXEC_${code || signal}`,
66
- message: `${cmd} exited with ${code || signal}`,
67
- }));
60
+ if (code === 0 || opts.ignoreNon0Exit) {
61
+ return resolve({
62
+ code,
63
+ stdout: Buffer.concat(stdoutList).toString(),
64
+ stderr: Buffer.concat(stderrList).toString(),
65
+ });
68
66
  }
69
- return resolve({
70
- code,
71
- stdout: Buffer.concat(stdoutList).toString(),
72
- stderr: Buffer.concat(stderrList).toString(),
73
- });
67
+ const cmd = opts.prettyCommand
68
+ ? `Command "${opts.prettyCommand}"`
69
+ : 'Command';
70
+ return reject(new errors_1.NowBuildError({
71
+ code: `BUILD_UTILS_EXEC_${code || signal}`,
72
+ message: `${cmd} exited with ${code || signal}`,
73
+ }));
74
74
  });
75
75
  });
76
76
  }
@@ -94,9 +94,22 @@ async function execCommand(command, options = {}) {
94
94
  return true;
95
95
  }
96
96
  exports.execCommand = execCommand;
97
- async function getNodeBinPath({ cwd }) {
98
- const { stdout } = await execAsync('npm', ['bin'], { cwd });
99
- return stdout.trim();
97
+ async function getNodeBinPath({ cwd, }) {
98
+ const { code, stdout, stderr } = await execAsync('npm', ['bin'], {
99
+ cwd,
100
+ prettyCommand: 'npm bin',
101
+ // in some rare cases, we saw `npm bin` exit with a non-0 code, but still
102
+ // output the right bin path, so we ignore the exit code
103
+ ignoreNon0Exit: true,
104
+ });
105
+ const nodeBinPath = stdout.trim();
106
+ if (path_1.default.isAbsolute(nodeBinPath)) {
107
+ return nodeBinPath;
108
+ }
109
+ throw new errors_1.NowBuildError({
110
+ code: `BUILD_UTILS_GET_NODE_BIN_PATH`,
111
+ message: `Running \`npm bin\` failed to return a valid bin path (code=${code}, stdout=${stdout}, stderr=${stderr})`,
112
+ });
100
113
  }
101
114
  exports.getNodeBinPath = getNodeBinPath;
102
115
  async function chmodPlusX(fsPath) {
@@ -125,8 +138,20 @@ function getSpawnOptions(meta, nodeVersion) {
125
138
  env: { ...process.env },
126
139
  };
127
140
  if (!meta.isDev) {
128
- // Ensure that the selected Node version is at the beginning of the `$PATH`
129
- opts.env.PATH = `/node${nodeVersion.major}/bin${path_1.default.delimiter}${opts.env.PATH || process.env.PATH}`;
141
+ let found = false;
142
+ const oldPath = opts.env.PATH || process.env.PATH || '';
143
+ const pathSegments = oldPath.split(path_1.default.delimiter).map(segment => {
144
+ if (/^\/node[0-9]+\/bin/.test(segment)) {
145
+ found = true;
146
+ return `/node${nodeVersion.major}/bin`;
147
+ }
148
+ return segment;
149
+ });
150
+ if (!found) {
151
+ // If we didn't find & replace, prepend at beginning of PATH
152
+ pathSegments.unshift(`/node${nodeVersion.major}/bin`);
153
+ }
154
+ opts.env.PATH = pathSegments.filter(Boolean).join(path_1.default.delimiter);
130
155
  }
131
156
  return opts;
132
157
  }
@@ -310,19 +335,28 @@ async function runNpmInstall(destPath, args = [], spawnOpts, meta, nodeVersion)
310
335
  exports.runNpmInstall = runNpmInstall;
311
336
  function getEnvForPackageManager({ cliType, lockfileVersion, nodeVersion, env, }) {
312
337
  const newEnv = { ...env };
338
+ const oldPath = env.PATH + '';
339
+ const npm7 = '/node16/bin-npm7';
340
+ const pnpm7 = '/pnpm7/node_modules/.bin';
341
+ const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
313
342
  if (cliType === 'npm') {
314
343
  if (typeof lockfileVersion === 'number' &&
315
344
  lockfileVersion >= 2 &&
316
- (nodeVersion?.major || 0) < 16) {
345
+ (nodeVersion?.major || 0) < 16 &&
346
+ !oldPath.includes(npm7) &&
347
+ !corepackEnabled) {
317
348
  // Ensure that npm 7 is at the beginning of the `$PATH`
318
- newEnv.PATH = `/node16/bin-npm7${path_1.default.delimiter}${env.PATH}`;
319
- console.log('Detected `package-lock.json` generated by npm 7...');
349
+ newEnv.PATH = `${npm7}${path_1.default.delimiter}${oldPath}`;
350
+ console.log('Detected `package-lock.json` generated by npm 7+...');
320
351
  }
321
352
  }
322
353
  else if (cliType === 'pnpm') {
323
- if (typeof lockfileVersion === 'number' && lockfileVersion === 5.4) {
354
+ if (typeof lockfileVersion === 'number' &&
355
+ lockfileVersion === 5.4 &&
356
+ !oldPath.includes(pnpm7) &&
357
+ !corepackEnabled) {
324
358
  // Ensure that pnpm 7 is at the beginning of the `$PATH`
325
- newEnv.PATH = `/pnpm7/node_modules/.bin${path_1.default.delimiter}${env.PATH}`;
359
+ newEnv.PATH = `${pnpm7}${path_1.default.delimiter}${oldPath}`;
326
360
  console.log('Detected `pnpm-lock.yaml` generated by pnpm 7...');
327
361
  }
328
362
  }
package/dist/index.d.ts CHANGED
@@ -16,23 +16,9 @@ import getIgnoreFilter from './get-ignore-filter';
16
16
  import { getPlatformEnv } from './get-platform-env';
17
17
  export { FileBlob, FileFsRef, FileRef, Lambda, NodejsLambda, createLambda, Prerender, download, DownloadedFiles, getWriteableDirectory, glob, GlobOptions, rename, execAsync, spawnAsync, getScriptName, installDependencies, runPackageJsonScript, execCommand, spawnCommand, walkParentDirs, getNodeBinPath, runNpmInstall, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, getEnvForPackageManager, getNodeVersion, getLatestNodeVersion, getDiscontinuedNodeVersions, getSpawnOptions, getPlatformEnv, streamToBuffer, debug, isSymbolicLink, getLambdaOptionsFromFunction, scanParentDirs, getIgnoreFilter, };
18
18
  export { EdgeFunction } from './edge-function';
19
- export { detectBuilders, detectOutputDirectory, detectApiDirectory, detectApiExtensions, } from './detect-builders';
20
- export { detectFileSystemAPI } from './detect-file-system-api';
21
- export { detectFramework } from './detect-framework';
22
- export { getProjectPaths } from './get-project-paths';
23
- export { DetectorFilesystem } from './detectors/filesystem';
24
19
  export { readConfigFile } from './fs/read-config-file';
25
20
  export { normalizePath } from './fs/normalize-path';
26
21
  export * from './should-serve';
27
22
  export * from './schemas';
28
23
  export * from './types';
29
24
  export * from './errors';
30
- /**
31
- * Helper function to support both `@vercel` and legacy `@now` official Runtimes.
32
- */
33
- export declare const isOfficialRuntime: (desired: string, name?: string | undefined) => boolean;
34
- export declare const isStaticRuntime: (name?: string | undefined) => boolean;
35
- export { workspaceManagers } from './workspaces/workspace-managers';
36
- export { getWorkspaces, GetWorkspaceOptions, Workspace, WorkspaceType, } from './workspaces/get-workspaces';
37
- export { getWorkspacePackagePaths, GetWorkspacePackagePathsOptions, } from './workspaces/get-workspace-package-paths';
38
- export { monorepoManagers } from './monorepos/monorepo-managers';