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

Commit

Permalink
feat: automatically detect workspace roots (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
nlf committed Jan 26, 2022
1 parent f8e5084 commit a3dc623
Show file tree
Hide file tree
Showing 5 changed files with 337 additions and 75 deletions.
68 changes: 56 additions & 12 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const walkUp = require('walk-up-path')
const ini = require('ini')
const nopt = require('nopt')
const mkdirp = require('mkdirp-infer-owner')
const mapWorkspaces = require('@npmcli/map-workspaces')
const rpj = require('read-package-json-fast')

/* istanbul ignore next */
const myUid = process.getuid && process.getuid()
Expand Down Expand Up @@ -543,23 +545,65 @@ class Config {
return
}

const cliWorkspaces = this[_get]('workspaces', 'cli')

for (const p of walkUp(this.cwd)) {
// walk up until we have a nm dir or a pj file
const hasAny = (await Promise.all([
stat(resolve(p, 'node_modules'))
.then(st => st.isDirectory())
.catch(() => false),
stat(resolve(p, 'package.json'))
.then(st => st.isFile())
.catch(() => false),
])).some(is => is)
if (hasAny) {
const hasNodeModules = await stat(resolve(p, 'node_modules'))
.then((st) => st.isDirectory())
.catch(() => false)

const hasPackageJson = await stat(resolve(p, 'package.json'))
.then((st) => st.isFile())
.catch(() => false)

if (!this.localPrefix && (hasNodeModules || hasPackageJson)) {
this.localPrefix = p
return

// if workspaces are disabled, return now
if (cliWorkspaces === false) {
return
}

// otherwise, continue the loop
continue
}

if (this.localPrefix && hasPackageJson) {
// if we already set localPrefix but this dir has a package.json
// then we need to see if `p` is a workspace root by reading its package.json
// however, if reading it fails then we should just move on
const pkg = await rpj(resolve(p, 'package.json')).catch(() => false)
if (!pkg) {
continue
}

const workspaces = await mapWorkspaces({ cwd: p, pkg })
for (const w of workspaces.values()) {
if (w === this.localPrefix) {
// see if there's a .npmrc file in the workspace, if so log a warning
const hasNpmrc = await stat(resolve(this.localPrefix, '.npmrc'))
.then((st) => st.isFile())
.catch(() => false)

if (hasNpmrc) {
this.log.warn(`ignoring workspace config at ${this.localPrefix}/.npmrc`)
}

// set the workspace in the default layer, which allows it to be overridden easily
const { data } = this.data.get('default')
data.workspace = [this.localPrefix]
this.localPrefix = p
this.log.info(`found workspace root at ${this.localPrefix}`)
// we found a root, so we return now
return
}
}
}
}

this.localPrefix = this.cwd
if (!this.localPrefix) {
this.localPrefix = this.cwd
}
}

loadUserConfig () {
Expand Down

0 comments on commit a3dc623

Please sign in to comment.