@vercel/build-utils 2.15.2-canary.0 → 2.15.2-canary.1

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.
@@ -7,6 +7,11 @@ export interface ScanParentDirsResult {
7
7
  * "yarn", "npm", or "pnpm" depending on the presence of lockfiles.
8
8
  */
9
9
  cliType: CliType;
10
+ /**
11
+ * The file path of found `package.json` file, or `undefined` if none was
12
+ * found.
13
+ */
14
+ packageJsonPath?: string;
10
15
  /**
11
16
  * The contents of found `package.json` file, when the `readPackageJson`
12
17
  * option is enabled.
@@ -56,7 +61,7 @@ export declare function getSpawnOptions(meta: Meta, nodeVersion: NodeVersion): S
56
61
  export declare function getNodeVersion(destPath: string, _nodeVersion?: string, config?: Config, meta?: Meta): Promise<NodeVersion>;
57
62
  export declare function scanParentDirs(destPath: string, readPackageJson?: boolean): Promise<ScanParentDirsResult>;
58
63
  export declare function walkParentDirs({ base, start, filename, }: WalkParentDirsProps): Promise<string | null>;
59
- export declare function runNpmInstall(destPath: string, args?: string[], spawnOpts?: SpawnOptions, meta?: Meta, nodeVersion?: NodeVersion): Promise<void>;
64
+ export declare function runNpmInstall(destPath: string, args?: string[], spawnOpts?: SpawnOptions, meta?: Meta, nodeVersion?: NodeVersion): Promise<boolean>;
60
65
  export declare function getEnvForPackageManager({ cliType, lockfileVersion, nodeVersion, env, }: {
61
66
  cliType: CliType;
62
67
  lockfileVersion: number | undefined;
@@ -7,12 +7,15 @@ exports.installDependencies = exports.getScriptName = exports.runPipInstall = ex
7
7
  const assert_1 = __importDefault(require("assert"));
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const path_1 = __importDefault(require("path"));
10
- const debug_1 = __importDefault(require("../debug"));
10
+ const async_sema_1 = __importDefault(require("async-sema"));
11
11
  const cross_spawn_1 = __importDefault(require("cross-spawn"));
12
12
  const util_1 = require("util");
13
+ const debug_1 = __importDefault(require("../debug"));
13
14
  const errors_1 = require("../errors");
14
15
  const node_version_1 = require("./node-version");
15
16
  const read_config_file_1 = require("./read-config-file");
17
+ // Only allow one `runNpmInstall()` invocation to run concurrently
18
+ const runNpmInstallSema = new async_sema_1.default(1);
16
19
  function spawnAsync(command, args, opts = {}) {
17
20
  return new Promise((resolve, reject) => {
18
21
  const stderrLogs = [];
@@ -151,11 +154,12 @@ async function scanParentDirs(destPath, readPackageJson = false) {
151
154
  assert_1.default(path_1.default.isAbsolute(destPath));
152
155
  let cliType = 'yarn';
153
156
  let packageJson;
157
+ let packageJsonPath;
154
158
  let currentDestPath = destPath;
155
159
  let lockfileVersion;
156
160
  // eslint-disable-next-line no-constant-condition
157
161
  while (true) {
158
- const packageJsonPath = path_1.default.join(currentDestPath, 'package.json');
162
+ packageJsonPath = path_1.default.join(currentDestPath, 'package.json');
159
163
  // eslint-disable-next-line no-await-in-loop
160
164
  if (await fs_extra_1.default.pathExists(packageJsonPath)) {
161
165
  // Only read the contents of the *first* `package.json` file found,
@@ -199,7 +203,7 @@ async function scanParentDirs(destPath, readPackageJson = false) {
199
203
  break;
200
204
  currentDestPath = newDestPath;
201
205
  }
202
- return { cliType, packageJson, lockfileVersion };
206
+ return { cliType, packageJson, lockfileVersion, packageJsonPath };
203
207
  }
204
208
  exports.scanParentDirs = scanParentDirs;
205
209
  async function walkParentDirs({ base, start, filename, }) {
@@ -217,46 +221,75 @@ async function walkParentDirs({ base, start, filename, }) {
217
221
  return null;
218
222
  }
219
223
  exports.walkParentDirs = walkParentDirs;
224
+ function isSet(v) {
225
+ var _a;
226
+ return ((_a = v === null || v === void 0 ? void 0 : v.constructor) === null || _a === void 0 ? void 0 : _a.name) === 'Set';
227
+ }
220
228
  async function runNpmInstall(destPath, args = [], spawnOpts, meta, nodeVersion) {
221
229
  if (meta === null || meta === void 0 ? void 0 : meta.isDev) {
222
230
  debug_1.default('Skipping dependency installation because dev mode is enabled');
223
- return;
231
+ return false;
224
232
  }
225
233
  assert_1.default(path_1.default.isAbsolute(destPath));
226
- debug_1.default(`Installing to ${destPath}`);
227
- const { cliType, lockfileVersion } = await scanParentDirs(destPath);
228
- const opts = { cwd: destPath, ...spawnOpts };
229
- const env = opts.env ? { ...opts.env } : { ...process.env };
230
- delete env.NODE_ENV;
231
- opts.env = getEnvForPackageManager({
232
- cliType,
233
- lockfileVersion,
234
- nodeVersion,
235
- env,
236
- });
237
- let commandArgs;
238
- if (cliType === 'npm') {
239
- opts.prettyCommand = 'npm install';
240
- commandArgs = args
241
- .filter(a => a !== '--prefer-offline')
242
- .concat(['install', '--no-audit', '--unsafe-perm']);
243
- }
244
- else if (cliType === 'pnpm') {
245
- // PNPM's install command is similar to NPM's but without the audit nonsense
246
- // @see options https://pnpm.io/cli/install
247
- opts.prettyCommand = 'pnpm install';
248
- commandArgs = args
249
- .filter(a => a !== '--prefer-offline')
250
- .concat(['install', '--unsafe-perm']);
251
- }
252
- else {
253
- opts.prettyCommand = 'yarn install';
254
- commandArgs = ['install', ...args];
234
+ try {
235
+ await runNpmInstallSema.acquire();
236
+ const { cliType, packageJsonPath, lockfileVersion } = await scanParentDirs(destPath);
237
+ // Only allow `runNpmInstall()` to run once per `package.json`
238
+ // when doing a default install (no additional args)
239
+ if (meta && packageJsonPath && args.length === 0) {
240
+ if (!isSet(meta.runNpmInstallSet)) {
241
+ meta.runNpmInstallSet = new Set();
242
+ }
243
+ if (isSet(meta.runNpmInstallSet)) {
244
+ if (meta.runNpmInstallSet.has(packageJsonPath)) {
245
+ return false;
246
+ }
247
+ else {
248
+ meta.runNpmInstallSet.add(packageJsonPath);
249
+ }
250
+ }
251
+ }
252
+ const installTime = Date.now();
253
+ console.log('Installing dependencies...');
254
+ debug_1.default(`Installing to ${destPath}`);
255
+ const opts = { cwd: destPath, ...spawnOpts };
256
+ const env = opts.env ? { ...opts.env } : { ...process.env };
257
+ delete env.NODE_ENV;
258
+ opts.env = getEnvForPackageManager({
259
+ cliType,
260
+ lockfileVersion,
261
+ nodeVersion,
262
+ env,
263
+ });
264
+ let commandArgs;
265
+ if (cliType === 'npm') {
266
+ opts.prettyCommand = 'npm install';
267
+ commandArgs = args
268
+ .filter(a => a !== '--prefer-offline')
269
+ .concat(['install', '--no-audit', '--unsafe-perm']);
270
+ }
271
+ else if (cliType === 'pnpm') {
272
+ // PNPM's install command is similar to NPM's but without the audit nonsense
273
+ // @see options https://pnpm.io/cli/install
274
+ opts.prettyCommand = 'pnpm install';
275
+ commandArgs = args
276
+ .filter(a => a !== '--prefer-offline')
277
+ .concat(['install', '--unsafe-perm']);
278
+ }
279
+ else {
280
+ opts.prettyCommand = 'yarn install';
281
+ commandArgs = ['install', ...args];
282
+ }
283
+ if (process.env.NPM_ONLY_PRODUCTION) {
284
+ commandArgs.push('--production');
285
+ }
286
+ await spawnAsync(cliType, commandArgs, opts);
287
+ debug_1.default(`Install complete [${Date.now() - installTime}ms]`);
288
+ return true;
255
289
  }
256
- if (process.env.NPM_ONLY_PRODUCTION) {
257
- commandArgs.push('--production');
290
+ finally {
291
+ runNpmInstallSema.release();
258
292
  }
259
- return spawnAsync(cliType, commandArgs, opts);
260
293
  }
261
294
  exports.runNpmInstall = runNpmInstall;
262
295
  function getEnvForPackageManager({ cliType, lockfileVersion, nodeVersion, env, }) {
package/dist/index.js CHANGED
@@ -34621,12 +34621,15 @@ exports.installDependencies = exports.getScriptName = exports.runPipInstall = ex
34621
34621
  const assert_1 = __importDefault(__webpack_require__(2357));
34622
34622
  const fs_extra_1 = __importDefault(__webpack_require__(5392));
34623
34623
  const path_1 = __importDefault(__webpack_require__(5622));
34624
- const debug_1 = __importDefault(__webpack_require__(1868));
34624
+ const async_sema_1 = __importDefault(__webpack_require__(5758));
34625
34625
  const cross_spawn_1 = __importDefault(__webpack_require__(7618));
34626
34626
  const util_1 = __webpack_require__(1669);
34627
+ const debug_1 = __importDefault(__webpack_require__(1868));
34627
34628
  const errors_1 = __webpack_require__(3983);
34628
34629
  const node_version_1 = __webpack_require__(7903);
34629
34630
  const read_config_file_1 = __webpack_require__(7792);
34631
+ // Only allow one `runNpmInstall()` invocation to run concurrently
34632
+ const runNpmInstallSema = new async_sema_1.default(1);
34630
34633
  function spawnAsync(command, args, opts = {}) {
34631
34634
  return new Promise((resolve, reject) => {
34632
34635
  const stderrLogs = [];
@@ -34765,11 +34768,12 @@ async function scanParentDirs(destPath, readPackageJson = false) {
34765
34768
  assert_1.default(path_1.default.isAbsolute(destPath));
34766
34769
  let cliType = 'yarn';
34767
34770
  let packageJson;
34771
+ let packageJsonPath;
34768
34772
  let currentDestPath = destPath;
34769
34773
  let lockfileVersion;
34770
34774
  // eslint-disable-next-line no-constant-condition
34771
34775
  while (true) {
34772
- const packageJsonPath = path_1.default.join(currentDestPath, 'package.json');
34776
+ packageJsonPath = path_1.default.join(currentDestPath, 'package.json');
34773
34777
  // eslint-disable-next-line no-await-in-loop
34774
34778
  if (await fs_extra_1.default.pathExists(packageJsonPath)) {
34775
34779
  // Only read the contents of the *first* `package.json` file found,
@@ -34813,7 +34817,7 @@ async function scanParentDirs(destPath, readPackageJson = false) {
34813
34817
  break;
34814
34818
  currentDestPath = newDestPath;
34815
34819
  }
34816
- return { cliType, packageJson, lockfileVersion };
34820
+ return { cliType, packageJson, lockfileVersion, packageJsonPath };
34817
34821
  }
34818
34822
  exports.scanParentDirs = scanParentDirs;
34819
34823
  async function walkParentDirs({ base, start, filename, }) {
@@ -34831,46 +34835,75 @@ async function walkParentDirs({ base, start, filename, }) {
34831
34835
  return null;
34832
34836
  }
34833
34837
  exports.walkParentDirs = walkParentDirs;
34838
+ function isSet(v) {
34839
+ var _a;
34840
+ return ((_a = v === null || v === void 0 ? void 0 : v.constructor) === null || _a === void 0 ? void 0 : _a.name) === 'Set';
34841
+ }
34834
34842
  async function runNpmInstall(destPath, args = [], spawnOpts, meta, nodeVersion) {
34835
34843
  if (meta === null || meta === void 0 ? void 0 : meta.isDev) {
34836
34844
  debug_1.default('Skipping dependency installation because dev mode is enabled');
34837
- return;
34845
+ return false;
34838
34846
  }
34839
34847
  assert_1.default(path_1.default.isAbsolute(destPath));
34840
- debug_1.default(`Installing to ${destPath}`);
34841
- const { cliType, lockfileVersion } = await scanParentDirs(destPath);
34842
- const opts = { cwd: destPath, ...spawnOpts };
34843
- const env = opts.env ? { ...opts.env } : { ...process.env };
34844
- delete env.NODE_ENV;
34845
- opts.env = getEnvForPackageManager({
34846
- cliType,
34847
- lockfileVersion,
34848
- nodeVersion,
34849
- env,
34850
- });
34851
- let commandArgs;
34852
- if (cliType === 'npm') {
34853
- opts.prettyCommand = 'npm install';
34854
- commandArgs = args
34855
- .filter(a => a !== '--prefer-offline')
34856
- .concat(['install', '--no-audit', '--unsafe-perm']);
34857
- }
34858
- else if (cliType === 'pnpm') {
34859
- // PNPM's install command is similar to NPM's but without the audit nonsense
34860
- // @see options https://pnpm.io/cli/install
34861
- opts.prettyCommand = 'pnpm install';
34862
- commandArgs = args
34863
- .filter(a => a !== '--prefer-offline')
34864
- .concat(['install', '--unsafe-perm']);
34865
- }
34866
- else {
34867
- opts.prettyCommand = 'yarn install';
34868
- commandArgs = ['install', ...args];
34848
+ try {
34849
+ await runNpmInstallSema.acquire();
34850
+ const { cliType, packageJsonPath, lockfileVersion } = await scanParentDirs(destPath);
34851
+ // Only allow `runNpmInstall()` to run once per `package.json`
34852
+ // when doing a default install (no additional args)
34853
+ if (meta && packageJsonPath && args.length === 0) {
34854
+ if (!isSet(meta.runNpmInstallSet)) {
34855
+ meta.runNpmInstallSet = new Set();
34856
+ }
34857
+ if (isSet(meta.runNpmInstallSet)) {
34858
+ if (meta.runNpmInstallSet.has(packageJsonPath)) {
34859
+ return false;
34860
+ }
34861
+ else {
34862
+ meta.runNpmInstallSet.add(packageJsonPath);
34863
+ }
34864
+ }
34865
+ }
34866
+ const installTime = Date.now();
34867
+ console.log('Installing dependencies...');
34868
+ debug_1.default(`Installing to ${destPath}`);
34869
+ const opts = { cwd: destPath, ...spawnOpts };
34870
+ const env = opts.env ? { ...opts.env } : { ...process.env };
34871
+ delete env.NODE_ENV;
34872
+ opts.env = getEnvForPackageManager({
34873
+ cliType,
34874
+ lockfileVersion,
34875
+ nodeVersion,
34876
+ env,
34877
+ });
34878
+ let commandArgs;
34879
+ if (cliType === 'npm') {
34880
+ opts.prettyCommand = 'npm install';
34881
+ commandArgs = args
34882
+ .filter(a => a !== '--prefer-offline')
34883
+ .concat(['install', '--no-audit', '--unsafe-perm']);
34884
+ }
34885
+ else if (cliType === 'pnpm') {
34886
+ // PNPM's install command is similar to NPM's but without the audit nonsense
34887
+ // @see options https://pnpm.io/cli/install
34888
+ opts.prettyCommand = 'pnpm install';
34889
+ commandArgs = args
34890
+ .filter(a => a !== '--prefer-offline')
34891
+ .concat(['install', '--unsafe-perm']);
34892
+ }
34893
+ else {
34894
+ opts.prettyCommand = 'yarn install';
34895
+ commandArgs = ['install', ...args];
34896
+ }
34897
+ if (process.env.NPM_ONLY_PRODUCTION) {
34898
+ commandArgs.push('--production');
34899
+ }
34900
+ await spawnAsync(cliType, commandArgs, opts);
34901
+ debug_1.default(`Install complete [${Date.now() - installTime}ms]`);
34902
+ return true;
34869
34903
  }
34870
- if (process.env.NPM_ONLY_PRODUCTION) {
34871
- commandArgs.push('--production');
34904
+ finally {
34905
+ runNpmInstallSema.release();
34872
34906
  }
34873
- return spawnAsync(cliType, commandArgs, opts);
34874
34907
  }
34875
34908
  exports.runNpmInstall = runNpmInstall;
34876
34909
  function getEnvForPackageManager({ cliType, lockfileVersion, nodeVersion, env, }) {
package/dist/types.d.ts CHANGED
@@ -313,7 +313,28 @@ export interface Images {
313
313
  minimumCacheTTL?: number;
314
314
  formats?: ImageFormat[];
315
315
  }
316
- export interface BuildResultV2 {
316
+ /**
317
+ * If a Builder ends up creating filesystem outputs conforming to
318
+ * the Build Output API, then the Builder should return this type.
319
+ */
320
+ export interface BuildResultBuildOutput {
321
+ /**
322
+ * Version number of the Build Output API that was created.
323
+ * Currently only `3` is a valid value.
324
+ * @example 3
325
+ */
326
+ buildOutputVersion: 3;
327
+ /**
328
+ * Filesystem path to the Build Output directory.
329
+ * @example "/path/to/.vercel/output"
330
+ */
331
+ buildOutputPath: string;
332
+ }
333
+ /**
334
+ * When a Builder implements `version: 2`, the `build()` function is expected
335
+ * to return this type.
336
+ */
337
+ export interface BuildResultV2Typical {
317
338
  routes?: any[];
318
339
  images?: Images;
319
340
  output: {
@@ -324,6 +345,7 @@ export interface BuildResultV2 {
324
345
  value: string;
325
346
  }>;
326
347
  }
348
+ export declare type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
327
349
  export interface BuildResultV3 {
328
350
  output: Lambda;
329
351
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/build-utils",
3
- "version": "2.15.2-canary.0",
3
+ "version": "2.15.2-canary.1",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",
@@ -49,5 +49,5 @@
49
49
  "typescript": "4.3.4",
50
50
  "yazl": "2.4.3"
51
51
  },
52
- "gitHead": "e7f524defba3bbf2db750dea3235e6699584c424"
52
+ "gitHead": "71b83d5587b549a1458697b50596a5534cb783d3"
53
53
  }