@@ -8,86 +8,225 @@ import { Command } from "commander";
88import { runBuild } from "./commands/build" ;
99import { ALL_PACKAGES , CATEGORY_VM } from "./common/cli.constants" ;
1010import { startDeleteFlow } from "./commands/delete" ;
11- import { Options_Cli } from "./common/cli.types" ;
1211import {
13- log ,
14- mergeOptions ,
15- validateOptions ,
16- validatePackages ,
17- } from "./common/cli.utils" ;
12+ Options_Cli ,
13+ Options_Cli_Build ,
14+ Options_Cli_Delete ,
15+ Schema_Options_Cli_Build ,
16+ Schema_Options_Cli_Delete ,
17+ Schema_Options_Cli_Root ,
18+ } from "./common/cli.types" ;
19+ import { getPckgsTo , log } from "./common/cli.utils" ;
1820
1921class CompassCli {
2022 private program : Command ;
2123 private options : Options_Cli ;
2224
2325 constructor ( args : string [ ] ) {
24- this . program = this . createProgram ( ) ;
26+ this . program = this . _createProgram ( ) ;
2527 this . program . parse ( args ) ;
26- this . options = this . getCliOptions ( ) ;
28+ this . options = this . _getCliOptions ( ) ;
2729 }
2830
29- private createProgram ( ) : Command {
31+ public async run ( ) {
32+ const { force, user } = this . options ;
33+ const cmd = this . program . args [ 0 ] ;
34+
35+ switch ( true ) {
36+ case cmd === "build" : {
37+ await this . _validateBuild ( ) ;
38+ await runBuild ( this . options ) ;
39+ break ;
40+ }
41+ case cmd === "delete" : {
42+ this . _validateDelete ( ) ;
43+ await startDeleteFlow ( user as string , force ) ;
44+ break ;
45+ }
46+ default :
47+ this . _exitHelpfully ( "root" , `${ cmd as string } is not a supported cmd` ) ;
48+ }
49+ }
50+
51+ private _createProgram ( ) : Command {
3052 const program = new Command ( ) ;
31- program . option (
32- `-e, --environment [${ CATEGORY_VM . STAG } | ${ CATEGORY_VM . PROD } ]` ,
33- "specify environment"
34- ) ;
53+
3554 program . option ( "-f, --force" , "force operation, no cautionary prompts" ) ;
36- program . option (
37- "--user [id | email]" ,
38- "specify which user to run script for"
39- ) ;
4055
4156 program
4257 . command ( "build" )
4358 . description ( "build compass package" )
4459 . argument (
4560 `[${ ALL_PACKAGES . join ( " | " ) } ]` ,
46- "package to build (only provde 1 at a time )"
61+ "package to build (only provide 1 )"
4762 )
4863 . option (
4964 "-c, --clientId <clientId>" ,
5065 "google client id to inject into build"
66+ )
67+ . option (
68+ `-e, --environment [${ CATEGORY_VM . STAG } | ${ CATEGORY_VM . PROD } ]` ,
69+ "specify environment"
5170 ) ;
5271
5372 program
5473 . command ( "delete" )
55- . description ( "delete user data from compass database" ) ;
74+ . description ( "delete user data from compass database" )
75+ . option (
76+ "-u, --user [id | email]" ,
77+ "specify which user to run script for"
78+ ) ;
5679 return program ;
5780 }
5881
59- private getCliOptions ( ) : Options_Cli {
60- const options = mergeOptions ( this . program ) ;
61- const validOptions = validateOptions ( options ) ;
82+ private _exitHelpfully ( cmd : "root" | "build" | "delete" , msg ?: string ) {
83+ msg && log . error ( msg ) ;
6284
63- return validOptions ;
85+ if ( cmd === "root" ) {
86+ console . log ( this . program . helpInformation ( ) ) ;
87+ } else {
88+ const command = this . program . commands . find (
89+ ( c ) => c . name ( ) === cmd
90+ ) as Command ;
91+ console . log ( command . helpInformation ( ) ) ;
92+ }
93+
94+ process . exit ( 1 ) ;
6495 }
6596
66- public async run ( ) {
67- const { user, force } = this . options ;
68- const cmd = this . program . args [ 0 ] ;
97+ private _getBuildOptions ( ) {
98+ const buildOpts : Options_Cli_Build = { } ;
6999
70- switch ( true ) {
71- case cmd === "build" : {
72- await runBuild ( this . options ) ;
73- break ;
100+ const buildCmd = this . program . commands . find (
101+ ( cmd ) => cmd . name ( ) === "build"
102+ ) ;
103+ if ( buildCmd ) {
104+ const packages = this . program . args [ 1 ] ?. split ( "," ) ;
105+ if ( packages ) {
106+ buildOpts . packages = packages ;
74107 }
75- case cmd === "delete" : {
76- if ( ! user || typeof user !== "string" ) {
77- this . exitHelpfully ( "You must supply a user" ) ;
78- }
79- await startDeleteFlow ( user as string , force ) ;
80- break ;
108+
109+ const environment = buildCmd ?. opts ( ) [
110+ "environment"
111+ ] as Options_Cli_Build [ "environment" ] ;
112+ if ( environment ) {
113+ buildOpts . environment = environment ;
114+ }
115+
116+ const clientId = buildCmd ?. opts ( ) [
117+ "clientId"
118+ ] as Options_Cli_Build [ "clientId" ] ;
119+ if ( clientId ) {
120+ buildOpts . clientId = clientId ;
81121 }
82- default :
83- this . exitHelpfully ( "Unsupported cmd" ) ;
84122 }
123+ return buildOpts ;
85124 }
86125
87- private exitHelpfully ( msg ?: string ) {
88- msg && log . error ( msg ) ;
89- console . log ( this . program . helpInformation ( ) ) ;
90- process . exit ( 1 ) ;
126+ private _getCliOptions ( ) : Options_Cli {
127+ const options = this . _mergeOptions ( ) ;
128+ const validOptions = this . _validateOptions ( options ) ;
129+
130+ console . log ( "options" , options ) ;
131+ console . log ( "validOptions:" , validOptions ) ;
132+ return validOptions ;
133+ }
134+
135+ private _getDeleteOptions ( ) {
136+ const deleteOpts : Options_Cli_Delete = { } ;
137+
138+ const deleteCmd = this . program . commands . find (
139+ ( cmd ) => cmd . name ( ) === "delete"
140+ ) ;
141+ if ( deleteCmd ) {
142+ const user = deleteCmd ?. opts ( ) [ "user" ] as Options_Cli [ "user" ] ;
143+ if ( user ) {
144+ deleteOpts . user = user ;
145+ }
146+ }
147+
148+ return deleteOpts ;
149+ }
150+
151+ private _mergeOptions = ( ) : Options_Cli => {
152+ const _options = this . program . opts ( ) ;
153+ let options : Options_Cli = {
154+ ..._options ,
155+ force : _options [ "force" ] === true ,
156+ } ;
157+
158+ const buildOptions = this . _getBuildOptions ( ) ;
159+ if ( Object . keys ( buildOptions ) . length > 0 ) {
160+ options = {
161+ ...options ,
162+ ...buildOptions ,
163+ } ;
164+ }
165+
166+ const deleteOptions = this . _getDeleteOptions ( ) ;
167+ if ( Object . keys ( deleteOptions ) . length > 0 ) {
168+ options = {
169+ ...options ,
170+ ...deleteOptions ,
171+ } ;
172+ }
173+
174+ return options ;
175+ } ;
176+
177+ private async _validateBuild ( ) {
178+ if ( ! this . options . packages ) {
179+ this . options . packages = await getPckgsTo ( "build" ) ;
180+ }
181+
182+ const unsupportedPackages = this . options . packages . filter (
183+ ( pkg ) => ! ALL_PACKAGES . includes ( pkg )
184+ ) ;
185+ if ( unsupportedPackages . length > 0 ) {
186+ this . _exitHelpfully (
187+ "build" ,
188+ `One or more of these packages isn't supported: ${ unsupportedPackages . toString ( ) } `
189+ ) ;
190+ }
191+ }
192+
193+ private _validateDelete ( ) {
194+ const { user } = this . options ;
195+ if ( ! user || typeof user !== "string" ) {
196+ this . _exitHelpfully ( "delete" , "You must supply a user" ) ;
197+ }
198+ }
199+
200+ private _validateOptions ( options : Options_Cli ) {
201+ const { data : rootData , error : rootError } =
202+ Schema_Options_Cli_Root . safeParse ( options ) ;
203+ if ( rootError ) {
204+ this . _exitHelpfully (
205+ "root" ,
206+ `Invalid CLI options: ${ rootError . toString ( ) } `
207+ ) ;
208+ }
209+
210+ const { data : buildData , error : buildError } =
211+ Schema_Options_Cli_Build . safeParse ( options ) ;
212+ if ( buildError ) {
213+ this . _exitHelpfully (
214+ "build" ,
215+ `Invalid build options: ${ buildError . toString ( ) } `
216+ ) ;
217+ }
218+
219+ const { data : deleteData , error : deleteError } =
220+ Schema_Options_Cli_Delete . safeParse ( options ) ;
221+ if ( deleteError ) {
222+ this . _exitHelpfully (
223+ "delete" ,
224+ `Invalid delete options: ${ deleteError . toString ( ) } `
225+ ) ;
226+ }
227+
228+ const data : Options_Cli = { ...rootData , ...buildData , ...deleteData } ;
229+ return data ;
91230 }
92231}
93232
0 commit comments