Skip to content
This repository was archived by the owner on Nov 3, 2022. It is now read-only.

Commit f884edc

Browse files
committed
feat: automatically detect workspace roots
1 parent f8e5084 commit f884edc

5 files changed

Lines changed: 325 additions & 75 deletions

File tree

lib/index.js

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ const walkUp = require('walk-up-path')
33
const ini = require('ini')
44
const nopt = require('nopt')
55
const mkdirp = require('mkdirp-infer-owner')
6+
const mapWorkspaces = require('@npmcli/map-workspaces')
7+
const rpj = require('read-package-json-fast')
68

79
/* istanbul ignore next */
810
const myUid = process.getuid && process.getuid()
@@ -543,23 +545,64 @@ class Config {
543545
return
544546
}
545547

548+
const cliWorkspaces = this[_get]('workspaces', 'cli')
549+
546550
for (const p of walkUp(this.cwd)) {
547-
// walk up until we have a nm dir or a pj file
548-
const hasAny = (await Promise.all([
549-
stat(resolve(p, 'node_modules'))
550-
.then(st => st.isDirectory())
551-
.catch(() => false),
552-
stat(resolve(p, 'package.json'))
553-
.then(st => st.isFile())
554-
.catch(() => false),
555-
])).some(is => is)
556-
if (hasAny) {
551+
const hasNodeModules = await stat(resolve(p, 'node_modules'))
552+
.then((st) => st.isDirectory())
553+
.catch(() => false)
554+
555+
const hasPackageJson = await stat(resolve(p, 'package.json'))
556+
.then((st) => st.isFile())
557+
.catch(() => false)
558+
559+
if (!this.localPrefix && (hasNodeModules || hasPackageJson)) {
557560
this.localPrefix = p
558-
return
561+
562+
// if workspaces are disabled, return now
563+
if (cliWorkspaces === false) {
564+
return
565+
}
566+
567+
// otherwise, continue the loop
568+
continue
569+
}
570+
571+
if (this.localPrefix && hasPackageJson) {
572+
// if we already set localPrefix but this dir has a package.json
573+
// then we need to see if `p` is a workspace root by reading its package.json
574+
// however, if reading it fails then we should just move on
575+
const pkg = await rpj(resolve(p, 'package.json')).catch(() => false)
576+
if (!pkg) {
577+
continue
578+
}
579+
580+
const workspaces = await mapWorkspaces({ cwd: p, pkg })
581+
for (const w of workspaces.values()) {
582+
if (w === this.localPrefix) {
583+
// see if there's a .npmrc file in the workspace, if so log a warning
584+
const hasNpmrc = await stat(resolve(this.localPrefix, '.npmrc'))
585+
.then((st) => st.isFile())
586+
.catch(() => false)
587+
588+
if (hasNpmrc) {
589+
this.log.warn(`ignoring workspace config at ${this.localPrefix}/.npmrc`)
590+
}
591+
592+
// set the workspace in the default layer, which allows it to be overridden easily
593+
const { data } = this.data.get('default')
594+
data.workspace = [this.localPrefix]
595+
this.localPrefix = p
596+
// we found a root, so we return now
597+
return
598+
}
599+
}
559600
}
560601
}
561602

562-
this.localPrefix = this.cwd
603+
if (!this.localPrefix) {
604+
this.localPrefix = this.cwd
605+
}
563606
}
564607

565608
loadUserConfig () {

0 commit comments

Comments
 (0)