@@ -11,16 +11,13 @@ import { concatMap, map, tap, toArray } from 'rxjs/operators';
11
11
import { WorkspaceLoader } from '../models/workspace-loader' ;
12
12
13
13
14
- export interface GenericTargetTargetSpecifier {
15
- target : string ;
16
- configuration ?: string ;
17
- }
18
-
19
14
export abstract class ArchitectCommand < T = any > extends Command < T > {
20
15
private _host = new NodeJsSyncHost ( ) ;
21
16
private _architect : Architect ;
22
17
private _workspace : experimental . workspace . Workspace ;
23
18
private _logger = createConsoleLogger ( ) ;
19
+ // If this command supports running multiple targets.
20
+ protected multiTarget = false ;
24
21
25
22
readonly Options : Option [ ] = [ {
26
23
name : 'configuration' ,
@@ -46,7 +43,7 @@ export abstract class ArchitectCommand<T = any> extends Command<T> {
46
43
const [ project , target ] = options . target . split ( ':' ) ;
47
44
targetSpec = { project, target } ;
48
45
} else if ( this . target ) {
49
- const projects = this . getAllProjectsForTargetName ( this . target ) ;
46
+ const projects = this . getProjectNamesByTarget ( this . target ) ;
50
47
51
48
if ( projects . length === 1 ) {
52
49
// If there is a single target, use it to parse overrides.
@@ -70,12 +67,12 @@ export abstract class ArchitectCommand<T = any> extends Command<T> {
70
67
) ;
71
68
} )
72
69
) . toPromise ( )
73
- . then ( ( ) => { } ) ;
70
+ . then ( ( ) => { } ) ;
74
71
}
75
72
76
73
public validate ( options : any ) {
77
74
if ( ! options . project && this . target ) {
78
- const projectNames = this . getAllProjectsForTargetName ( this . target ) ;
75
+ const projectNames = this . getProjectNamesByTarget ( this . target ) ;
79
76
const overrides = { ...options } ;
80
77
delete overrides . project ;
81
78
delete overrides . configuration ;
@@ -164,7 +161,7 @@ export abstract class ArchitectCommand<T = any> extends Command<T> {
164
161
if ( ! targetSpec . project && this . target ) {
165
162
// This runs each target sequentially.
166
163
// Running them in parallel would jumble the log messages.
167
- return await from ( this . getAllProjectsForTargetName ( this . target ) ) . pipe (
164
+ return await from ( this . getProjectNamesByTarget ( this . target ) ) . pipe (
168
165
concatMap ( project => runSingleTarget ( { ...targetSpec , project } ) ) ,
169
166
toArray ( ) ,
170
167
) . toPromise ( ) . then ( results => results . every ( res => res === 0 ) ? 0 : 1 ) ;
@@ -197,10 +194,28 @@ export abstract class ArchitectCommand<T = any> extends Command<T> {
197
194
}
198
195
}
199
196
200
- private getAllProjectsForTargetName ( targetName : string ) {
201
- return this . _workspace . listProjectNames ( ) . map ( projectName =>
197
+ private getProjectNamesByTarget ( targetName : string ) : string [ ] {
198
+ const allProjectsForTargetName = this . _workspace . listProjectNames ( ) . map ( projectName =>
202
199
this . _architect . listProjectTargets ( projectName ) . includes ( targetName ) ? projectName : null
203
200
) . filter ( x => ! ! x ) ;
201
+
202
+ if ( this . multiTarget ) {
203
+ // For multi target commands, we always list all projects that have the target.
204
+ return allProjectsForTargetName ;
205
+ } else {
206
+ // For single target commands, we try try the default project project first,
207
+ // then the full list if it has a single project, then error out.
208
+ const maybeDefaultProject = this . _workspace . getDefaultProjectName ( ) ;
209
+ if ( maybeDefaultProject && allProjectsForTargetName . includes ( maybeDefaultProject ) ) {
210
+ return [ maybeDefaultProject ] ;
211
+ }
212
+
213
+ if ( allProjectsForTargetName . length === 1 ) {
214
+ return allProjectsForTargetName ;
215
+ }
216
+
217
+ throw new Error ( `Could not determine a single project for the '${ targetName } target.` ) ;
218
+ }
204
219
}
205
220
206
221
private _loadWorkspaceAndArchitect ( ) {
0 commit comments