@vercel/build-utils 5.0.3 → 5.0.6

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.
@@ -189,62 +189,44 @@ async function getNodeVersion(destPath, _nodeVersion, config = {}, meta = {}) {
189
189
  exports.getNodeVersion = getNodeVersion;
190
190
  async function scanParentDirs(destPath, readPackageJson = false) {
191
191
  assert_1.default(path_1.default.isAbsolute(destPath));
192
- let cliType = 'yarn';
193
- let packageJson;
194
- let packageJsonPath;
195
- let currentDestPath = destPath;
192
+ const pkgJsonPath = await walkParentDirs({
193
+ base: '/',
194
+ start: destPath,
195
+ filename: 'package.json',
196
+ });
197
+ const packageJson = readPackageJson && pkgJsonPath
198
+ ? JSON.parse(await fs_extra_1.default.readFile(pkgJsonPath, 'utf8'))
199
+ : undefined;
200
+ const [yarnLockPath, npmLockPath, pnpmLockPath] = await walkParentDirsMulti({
201
+ base: '/',
202
+ start: destPath,
203
+ filenames: ['yarn.lock', 'package-lock.json', 'pnpm-lock.yaml'],
204
+ });
196
205
  let lockfileVersion;
197
- // eslint-disable-next-line no-constant-condition
198
- while (true) {
199
- packageJsonPath = path_1.default.join(currentDestPath, 'package.json');
200
- // eslint-disable-next-line no-await-in-loop
201
- if (await fs_extra_1.default.pathExists(packageJsonPath)) {
202
- // Only read the contents of the *first* `package.json` file found,
203
- // since that's the one related to this installation.
204
- if (readPackageJson && !packageJson) {
205
- // eslint-disable-next-line no-await-in-loop
206
- packageJson = JSON.parse(await fs_extra_1.default.readFile(packageJsonPath, 'utf8'));
207
- }
208
- // eslint-disable-next-line no-await-in-loop
209
- const [packageLockJson, hasYarnLock, pnpmLockYaml] = await Promise.all([
210
- fs_extra_1.default
211
- .readJson(path_1.default.join(currentDestPath, 'package-lock.json'))
212
- .catch(error => {
213
- // If the file doesn't exist, fail gracefully otherwise error
214
- if (error.code === 'ENOENT') {
215
- return null;
216
- }
217
- throw error;
218
- }),
219
- fs_extra_1.default.pathExists(path_1.default.join(currentDestPath, 'yarn.lock')),
220
- read_config_file_1.readConfigFile(path_1.default.join(currentDestPath, 'pnpm-lock.yaml')),
221
- ]);
222
- // Priority order is Yarn > pnpm > npm
223
- // - find highest priority lock file and use that
224
- if (hasYarnLock) {
225
- cliType = 'yarn';
226
- }
227
- else if (pnpmLockYaml) {
228
- cliType = 'pnpm';
229
- // just ensure that it is read as a number and not a string
230
- lockfileVersion = Number(pnpmLockYaml.lockfileVersion);
231
- }
232
- else if (packageLockJson) {
233
- cliType = 'npm';
234
- lockfileVersion = packageLockJson.lockfileVersion;
235
- }
236
- // Only stop iterating if a lockfile was found, because it's possible
237
- // that the lockfile is in a higher path than where the `package.json`
238
- // file was found.
239
- if (packageLockJson || hasYarnLock || pnpmLockYaml) {
240
- break;
241
- }
242
- }
243
- const newDestPath = path_1.default.dirname(currentDestPath);
244
- if (currentDestPath === newDestPath)
245
- break;
246
- currentDestPath = newDestPath;
206
+ let cliType = 'yarn';
207
+ const [hasYarnLock, packageLockJson, pnpmLockYaml] = await Promise.all([
208
+ Boolean(yarnLockPath),
209
+ npmLockPath
210
+ ? read_config_file_1.readConfigFile(npmLockPath)
211
+ : null,
212
+ pnpmLockPath
213
+ ? read_config_file_1.readConfigFile(pnpmLockPath)
214
+ : null,
215
+ ]);
216
+ // Priority order is Yarn > pnpm > npm
217
+ if (hasYarnLock) {
218
+ cliType = 'yarn';
247
219
  }
220
+ else if (pnpmLockYaml) {
221
+ cliType = 'pnpm';
222
+ // just ensure that it is read as a number and not a string
223
+ lockfileVersion = Number(pnpmLockYaml.lockfileVersion);
224
+ }
225
+ else if (packageLockJson) {
226
+ cliType = 'npm';
227
+ lockfileVersion = packageLockJson.lockfileVersion;
228
+ }
229
+ const packageJsonPath = pkgJsonPath || undefined;
248
230
  return { cliType, packageJson, lockfileVersion, packageJsonPath };
249
231
  }
250
232
  exports.scanParentDirs = scanParentDirs;
@@ -259,10 +241,31 @@ async function walkParentDirs({ base, start, filename, }) {
259
241
  return fullPath;
260
242
  }
261
243
  parent = path_1.default.dirname(current);
244
+ if (parent === current) {
245
+ // Reached root directory of the filesystem
246
+ break;
247
+ }
262
248
  }
263
249
  return null;
264
250
  }
265
251
  exports.walkParentDirs = walkParentDirs;
252
+ async function walkParentDirsMulti({ base, start, filenames, }) {
253
+ let parent = '';
254
+ for (let current = start; base.length <= current.length; current = parent) {
255
+ const fullPaths = filenames.map(f => path_1.default.join(current, f));
256
+ const existResults = await Promise.all(fullPaths.map(f => fs_extra_1.default.pathExists(f)));
257
+ const foundOneOrMore = existResults.some(b => b);
258
+ if (foundOneOrMore) {
259
+ return fullPaths.map((f, i) => (existResults[i] ? f : undefined));
260
+ }
261
+ parent = path_1.default.dirname(current);
262
+ if (parent === current) {
263
+ // Reached root directory of the filesystem
264
+ break;
265
+ }
266
+ }
267
+ return [];
268
+ }
266
269
  function isSet(v) {
267
270
  return v?.constructor?.name === 'Set';
268
271
  }