@@ -12,6 +12,7 @@ import { isCommandPreRun } from '../../guards';
1212import { FatalException } from '../errors' ;
1313import { validators } from '../validators' ;
1414import { minimistOptionsToArray , validateInputs } from './utils' ;
15+ import { Logger } from '../utils/logger' ;
1516
1617export class Command implements ICommand {
1718 public env : IonicEnvironment ;
@@ -31,10 +32,21 @@ export class Command implements ICommand {
3132 }
3233 }
3334
34- async runcmd ( pargv : string [ ] ) : Promise < void > {
35+ async runcmd ( pargv : string [ ] , opts : { showLogs ?: boolean } = { } ) : Promise < void > {
36+ const env = { ...this . env } ;
37+
38+ if ( typeof opts . showLogs === 'undefined' ) {
39+ opts . showLogs = true ;
40+ }
41+
42+ if ( ! opts . showLogs ) {
43+ const DevNull = require ( 'dev-null' ) ; // TODO
44+ env . log = new Logger ( { level : this . env . log . level , stream : new DevNull ( ) , prefix : this . env . log . prefix } ) ;
45+ }
46+
3547 await this . runwrap ( async ( ) => {
36- this . env . log . msg ( `> ${ chalk . green ( [ this . env . namespace . name , ...pargv ] . map ( a => a . includes ( ' ' ) ? `"${ a } "` : a ) . join ( ' ' ) ) } ` ) ;
37- return this . env . namespace . runCommand ( this . env , pargv ) ;
48+ env . log . msg ( `> ${ chalk . green ( [ env . namespace . name , ...pargv ] . map ( a => a . includes ( ' ' ) ? `"${ a } "` : a ) . join ( ' ' ) ) } ` ) ;
49+ return this . env . namespace . runCommand ( env , pargv ) ;
3850 } , { exit0 : false } ) ;
3951 }
4052
@@ -75,56 +87,67 @@ export class Command implements ICommand {
7587 }
7688 }
7789
78- await Promise . all ( [
79- ( async ( ) => {
80- // TODO: get telemetry for commands that aborted above
81- if ( config . telemetry !== false ) {
82- let cmdInputs : CommandLineInputs = [ ] ;
90+ const runPromise = ( async ( ) => {
91+ await this . runwrap ( ( ) => this . run ( inputs , options ) ) ;
92+ } ) ( ) ;
8393
84- if ( this . metadata . name === 'help' ) {
85- cmdInputs = inputs ;
86- } else {
87- cmdInputs = this . getCleanInputsForTelemetry ( inputs , options ) ;
88- }
94+ const telemetryPromise = ( async ( ) => {
95+ if ( config . telemetry !== false ) {
96+ let cmdInputs : CommandLineInputs = [ ] ;
8997
90- await this . env . telemetry . sendCommand ( `ionic ${ this . metadata . fullName } ` , cmdInputs ) ;
98+ if ( this . metadata . name === 'login' || this . metadata . name === 'logout' ) {
99+ await runPromise ;
100+ } else if ( this . metadata . name === 'help' ) {
101+ cmdInputs = inputs ;
102+ } else {
103+ cmdInputs = await this . getCleanInputsForTelemetry ( inputs , options ) ;
91104 }
92- } ) ( ) ,
93- ( async ( ) => {
94- await this . runwrap ( ( ) => this . run ( inputs , options ) ) ;
95- } ) ( )
96- ] ) ;
105+
106+ await this . env . telemetry . sendCommand ( `ionic ${ this . metadata . fullName } ` , cmdInputs ) ;
107+ }
108+ } ) ( ) ;
109+
110+ await Promise . all ( [ runPromise , telemetryPromise ] ) ;
97111 }
98112
99113 exit ( msg : string , code : number = 1 ) : FatalException {
100114 return new FatalException ( msg , code ) ;
101115 }
102116
103- getCleanInputsForTelemetry ( inputs : CommandLineInputs , options : CommandLineOptions ) {
104- if ( this . metadata . inputs ) {
105- const mdi = this . metadata . inputs ;
106- inputs = inputs
107- . filter ( ( input , i ) => {
108- return mdi [ i ] && ! mdi [ i ] . private ;
117+ async getCleanInputsForTelemetry ( inputs : CommandLineInputs , options : CommandLineOptions ) : Promise < string [ ] > {
118+ const initialOptions : CommandLineOptions = { _ : [ ] } ;
119+
120+ const filteredInputs = inputs . filter ( ( input , i ) => ! this . metadata . inputs || ( this . metadata . inputs [ i ] && ! this . metadata . inputs [ i ] . private ) ) ;
121+ const filteredOptions = Object . keys ( options )
122+ . filter ( optionName => {
123+ const metadataOption = this . metadata . options && this . metadata . options . find ( ( o ) => {
124+ return o . name === optionName || ( typeof o . aliases !== 'undefined' && o . aliases . includes ( optionName ) ) ;
109125 } ) ;
110- }
111126
112- if ( this . metadata . options ) {
113- const mdo = this . metadata . options ;
114- options = Object . keys ( options )
115- . filter ( optionName => {
116- const metadataOptionFound = mdo . find ( ( mdOption ) => (
117- mdOption . name === optionName || ( mdOption . aliases || [ ] ) . includes ( optionName )
118- ) ) ;
119- return metadataOptionFound ? ! metadataOptionFound . private : true ;
120- } )
121- . reduce ( ( allOptions , optionName ) => {
122- allOptions [ optionName ] = options [ optionName ] ;
123- return allOptions ;
124- } , < CommandLineOptions > { } ) ;
125- }
127+ if ( metadataOption && metadataOption . aliases && metadataOption . aliases . includes ( optionName ) ) {
128+ return false ; // exclude aliases
129+ }
130+
131+ if ( ! metadataOption ) {
132+ return true ; // include unknown options
133+ }
134+
135+ if ( metadataOption . private ) {
136+ return false ; // exclude private options
137+ }
138+
139+ if ( typeof metadataOption . default !== 'undefined' && metadataOption . default === options [ optionName ] ) {
140+ return false ; // exclude options that match their default value (means it wasn't supplied by user)
141+ }
142+
143+ return true ;
144+ } )
145+ . reduce ( ( allOptions , optionName ) => {
146+ allOptions [ optionName ] = options [ optionName ] ;
147+ return allOptions ;
148+ } , initialOptions ) ;
126149
127- let optionInputs = minimistOptionsToArray ( options ) ;
128- return inputs . concat ( optionInputs ) ;
150+ const optionInputs = minimistOptionsToArray ( filteredOptions , { useDoubleQuotes : true } ) ;
151+ return filteredInputs . concat ( optionInputs ) ;
129152 }
130153}
0 commit comments