@@ -8,13 +8,19 @@ const pacote = require('pacote')
8
8
const npa = require ( 'npm-package-arg' )
9
9
const npmFetch = require ( 'npm-registry-fetch' )
10
10
11
- const flatten = require ( './utils/config/flatten.js' )
12
11
const otplease = require ( './utils/otplease.js' )
13
12
const { getContents, logTar } = require ( './utils/tar.js' )
13
+ const getWorkspaces = require ( './workspaces/get-workspaces.js' )
14
+
15
+ // for historical reasons, publishConfig in package.json can contain ANY config
16
+ // keys that npm supports in .npmrc files and elsewhere. We *may* want to
17
+ // revisit this at some point, and have a minimal set that's a SemVer-major
18
+ // change that ought to get a RFC written on it.
19
+ const flatten = require ( './utils/config/flatten.js' )
14
20
15
- // this is the only case in the CLI where we use the old full slow
16
- // 'read-package-json' module, because we want to pull in all the
17
- // defaults and metadata, like git sha's and default scripts and all that.
21
+ // this is the only case in the CLI where we want to use the old full slow
22
+ // 'read-package-json' module, because we want to pull in all the defaults and
23
+ // metadata, like git sha's and default scripts and all that.
18
24
const readJson = util . promisify ( require ( 'read-package-json' ) )
19
25
20
26
const BaseCommand = require ( './base-command.js' )
@@ -30,7 +36,7 @@ class Publish extends BaseCommand {
30
36
31
37
/* istanbul ignore next - see test/lib/load-all-commands.js */
32
38
static get params ( ) {
33
- return [ 'tag' , 'access' , 'dry-run' ]
39
+ return [ 'tag' , 'access' , 'dry-run' , 'workspace' , 'workspaces' ]
34
40
}
35
41
36
42
/* istanbul ignore next - see test/lib/load-all-commands.js */
@@ -44,6 +50,10 @@ class Publish extends BaseCommand {
44
50
this . publish ( args ) . then ( ( ) => cb ( ) ) . catch ( cb )
45
51
}
46
52
53
+ execWorkspaces ( args , filters , cb ) {
54
+ this . publishWorkspaces ( args , filters ) . then ( ( ) => cb ( ) ) . catch ( cb )
55
+ }
56
+
47
57
async publish ( args ) {
48
58
if ( args . length === 0 )
49
59
args = [ '.' ]
@@ -56,6 +66,7 @@ class Publish extends BaseCommand {
56
66
const dryRun = this . npm . config . get ( 'dry-run' )
57
67
const json = this . npm . config . get ( 'json' )
58
68
const defaultTag = this . npm . config . get ( 'tag' )
69
+ const silent = log . level === 'silent'
59
70
60
71
if ( semver . validRange ( defaultTag ) )
61
72
throw new Error ( 'Tag name must not be a valid SemVer range: ' + defaultTag . trim ( ) )
@@ -68,7 +79,7 @@ class Publish extends BaseCommand {
68
79
let manifest = await this . getManifest ( spec , opts )
69
80
70
81
if ( manifest . publishConfig )
71
- Object . assign ( opts , this . publishConfigToOpts ( manifest . publishConfig ) )
82
+ flatten ( manifest . publishConfig , opts )
72
83
73
84
// only run scripts for directory type publishes
74
85
if ( spec . type === 'directory' ) {
@@ -77,7 +88,7 @@ class Publish extends BaseCommand {
77
88
path : spec . fetchSpec ,
78
89
stdio : 'inherit' ,
79
90
pkg : manifest ,
80
- banner : log . level !== ' silent' ,
91
+ banner : ! silent ,
81
92
} )
82
93
}
83
94
@@ -89,7 +100,7 @@ class Publish extends BaseCommand {
89
100
// note that publishConfig might have changed as well!
90
101
manifest = await this . getManifest ( spec , opts )
91
102
if ( manifest . publishConfig )
92
- Object . assign ( opts , this . publishConfigToOpts ( manifest . publishConfig ) )
103
+ flatten ( manifest . publishConfig , opts )
93
104
94
105
// note that logTar calls npmlog.notice(), so if we ARE in silent mode,
95
106
// this will do nothing, but we still want it in the debuglog if it fails.
@@ -114,44 +125,57 @@ class Publish extends BaseCommand {
114
125
path : spec . fetchSpec ,
115
126
stdio : 'inherit' ,
116
127
pkg : manifest ,
117
- banner : log . level !== ' silent' ,
128
+ banner : ! silent ,
118
129
} )
119
130
120
131
await runScript ( {
121
132
event : 'postpublish' ,
122
133
path : spec . fetchSpec ,
123
134
stdio : 'inherit' ,
124
135
pkg : manifest ,
125
- banner : log . level !== ' silent' ,
136
+ banner : ! silent ,
126
137
} )
127
138
}
128
139
129
- const silent = log . level === 'silent'
130
- if ( ! silent && json )
131
- this . npm . output ( JSON . stringify ( pkgContents , null , 2 ) )
132
- else if ( ! silent )
133
- this . npm . output ( `+ ${ pkgContents . id } ` )
140
+ if ( ! this . workspaces ) {
141
+ if ( ! silent && json )
142
+ this . npm . output ( JSON . stringify ( pkgContents , null , 2 ) )
143
+ else if ( ! silent )
144
+ this . npm . output ( `+ ${ pkgContents . id } ` )
145
+ }
134
146
135
147
return pkgContents
136
148
}
137
149
150
+ async publishWorkspaces ( args , filters ) {
151
+ // Suppresses JSON output in publish() so we can handle it here
152
+ this . workspaces = true
153
+
154
+ const results = { }
155
+ const json = this . npm . config . get ( 'json' )
156
+ const silent = log . level === 'silent'
157
+ const workspaces =
158
+ await getWorkspaces ( filters , { path : this . npm . localPrefix } )
159
+ for ( const [ name , workspace ] of workspaces . entries ( ) ) {
160
+ const pkgContents = await this . publish ( [ workspace ] )
161
+ // This needs to be in-line w/ the rest of the output that non-JSON
162
+ // publish generates
163
+ if ( ! silent && ! json )
164
+ this . npm . output ( `+ ${ pkgContents . id } ` )
165
+ else
166
+ results [ name ] = pkgContents
167
+ }
168
+
169
+ if ( ! silent && json )
170
+ this . npm . output ( JSON . stringify ( results , null , 2 ) )
171
+ }
172
+
138
173
// if it's a directory, read it from the file system
139
174
// otherwise, get the full metadata from whatever it is
140
175
getManifest ( spec , opts ) {
141
176
if ( spec . type === 'directory' )
142
177
return readJson ( `${ spec . fetchSpec } /package.json` )
143
178
return pacote . manifest ( spec , { ...opts , fullMetadata : true } )
144
179
}
145
-
146
- // for historical reasons, publishConfig in package.json can contain
147
- // ANY config keys that npm supports in .npmrc files and elsewhere.
148
- // We *may* want to revisit this at some point, and have a minimal set
149
- // that's a SemVer-major change that ought to get a RFC written on it.
150
- publishConfigToOpts ( publishConfig ) {
151
- // create a new object that inherits from the config stack
152
- // then squash the css-case into camelCase opts, like we do
153
- // this is Object.assign()'ed onto the base npm.flatOptions
154
- return flatten ( publishConfig , { } )
155
- }
156
180
}
157
181
module . exports = Publish
0 commit comments