@@ -3,6 +3,8 @@ const walkUp = require('walk-up-path')
33const ini = require ( 'ini' )
44const nopt = require ( 'nopt' )
55const 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 */
810const 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