@@ -2,17 +2,17 @@ const os = require('os')
22const path = require ( 'path' )
33const pacote = require ( 'pacote' )
44const table = require ( 'text-table' )
5- const color = require ( 'ansicolors ' )
5+ const color = require ( 'chalk ' )
66const styles = require ( 'ansistyles' )
77const npa = require ( 'npm-package-arg' )
88const pickManifest = require ( 'npm-pick-manifest' )
99
1010const Arborist = require ( '@npmcli/arborist' )
1111
1212const ansiTrim = require ( './utils/ansi-trim.js' )
13- const BaseCommand = require ( './base-command .js' )
13+ const ArboristWorkspaceCmd = require ( './workspaces/arborist-cmd .js' )
1414
15- class Outdated extends BaseCommand {
15+ class Outdated extends ArboristWorkspaceCmd {
1616 /* istanbul ignore next - see test/lib/load-all-commands.js */
1717 static get description ( ) {
1818 return 'Check for outdated packages'
@@ -36,6 +36,7 @@ class Outdated extends BaseCommand {
3636 'long' ,
3737 'parseable' ,
3838 'global' ,
39+ 'workspace' ,
3940 ]
4041 }
4142
@@ -58,6 +59,9 @@ class Outdated extends BaseCommand {
5859 this . list = [ ]
5960 this . tree = await arb . loadActual ( )
6061
62+ if ( this . workspaces && this . workspaces . length )
63+ this . filterSet = arb . workspaceDependencySet ( this . tree , this . workspaces )
64+
6165 if ( args . length !== 0 ) {
6266 // specific deps
6367 for ( let i = 0 ; i < args . length ; i ++ ) {
@@ -116,8 +120,14 @@ class Outdated extends BaseCommand {
116120 }
117121
118122 getEdges ( nodes , type ) {
119- if ( ! nodes )
120- return this . getEdgesOut ( this . tree )
123+ // when no nodes are provided then it should only read direct deps
124+ // from the root node and its workspaces direct dependencies
125+ if ( ! nodes ) {
126+ this . getEdgesOut ( this . tree )
127+ this . getWorkspacesEdges ( )
128+ return
129+ }
130+
121131 for ( const node of nodes ) {
122132 type === 'edgesOut'
123133 ? this . getEdgesOut ( node )
@@ -127,16 +137,45 @@ class Outdated extends BaseCommand {
127137
128138 getEdgesIn ( node ) {
129139 for ( const edge of node . edgesIn )
130- this . edges . add ( edge )
140+ this . trackEdge ( edge )
131141 }
132142
133143 getEdgesOut ( node ) {
144+ // TODO: normalize usage of edges and avoid looping through nodes here
134145 if ( this . npm . config . get ( 'global' ) ) {
135146 for ( const child of node . children . values ( ) )
136- this . edges . add ( child )
147+ this . trackEdge ( child )
137148 } else {
138149 for ( const edge of node . edgesOut . values ( ) )
139- this . edges . add ( edge )
150+ this . trackEdge ( edge )
151+ }
152+ }
153+
154+ trackEdge ( edge ) {
155+ const filteredOut =
156+ edge . from
157+ && this . filterSet
158+ && this . filterSet . size > 0
159+ && ! this . filterSet . has ( edge . from . target || edge . from )
160+
161+ if ( filteredOut )
162+ return
163+
164+ this . edges . add ( edge )
165+ }
166+
167+ getWorkspacesEdges ( node ) {
168+ if ( this . npm . config . get ( 'global' ) )
169+ return
170+
171+ for ( const edge of this . tree . edgesOut . values ( ) ) {
172+ const workspace = edge
173+ && edge . to
174+ && edge . to . target
175+ && edge . to . target . isWorkspace
176+
177+ if ( workspace )
178+ this . getEdgesOut ( edge . to . target )
140179 }
141180 }
142181
@@ -188,6 +227,10 @@ class Outdated extends BaseCommand {
188227 current !== wanted . version ||
189228 wanted . version !== latest . version
190229 ) {
230+ const dependent = edge . from ?
231+ this . maybeWorkspaceName ( edge . from )
232+ : 'global'
233+
191234 this . list . push ( {
192235 name : edge . name ,
193236 path,
@@ -196,7 +239,7 @@ class Outdated extends BaseCommand {
196239 location,
197240 wanted : wanted . version ,
198241 latest : latest . version ,
199- dependent : edge . from ? edge . from . name : 'global' ,
242+ dependent,
200243 homepage : packument . homepage ,
201244 } )
202245 }
@@ -212,6 +255,23 @@ class Outdated extends BaseCommand {
212255 }
213256 }
214257
258+ maybeWorkspaceName ( node ) {
259+ if ( ! node . isWorkspace )
260+ return node . name
261+
262+ const humanOutput =
263+ ! this . npm . config . get ( 'json' ) && ! this . npm . config . get ( 'parseable' )
264+
265+ const workspaceName =
266+ humanOutput
267+ ? node . pkgid
268+ : node . name
269+
270+ return this . npm . color && humanOutput
271+ ? color . green ( workspaceName )
272+ : workspaceName
273+ }
274+
215275 // formatting functions
216276 makePretty ( dep ) {
217277 const {
0 commit comments