@@ -3,33 +3,34 @@ import colors from 'colors';
33import { Command , CommanderError , Option } from 'commander' ;
44import * as actions from './actions' ;
55import { CliError } from './cli-error' ;
6- import { getVersion } from './utils/version-utils' ;
6+ import { telemetry } from './telemetry' ;
7+ import { checkNewVersion , getVersion } from './utils/version-utils' ;
78
89const generateAction = async ( options : Parameters < typeof actions . generate > [ 0 ] ) : Promise < void > => {
9- await actions . generate ( options ) ;
10+ await telemetry . trackCommand ( 'generate' , ( ) => actions . generate ( options ) ) ;
1011} ;
1112
12- const migrateAction = async ( command : string , options : any ) : Promise < void > => {
13- await actions . migrate ( command , options ) ;
13+ const migrateAction = async ( subCommand : string , options : any ) : Promise < void > => {
14+ await telemetry . trackCommand ( `migrate ${ subCommand } ` , ( ) => actions . migrate ( subCommand , options ) ) ;
1415} ;
1516
16- const dbAction = async ( command : string , options : any ) : Promise < void > => {
17- await actions . db ( command , options ) ;
17+ const dbAction = async ( subCommand : string , options : any ) : Promise < void > => {
18+ await telemetry . trackCommand ( `db ${ subCommand } ` , ( ) => actions . db ( subCommand , options ) ) ;
1819} ;
1920
2021const infoAction = async ( projectPath : string ) : Promise < void > => {
21- await actions . info ( projectPath ) ;
22+ await telemetry . trackCommand ( 'info' , ( ) => actions . info ( projectPath ) ) ;
2223} ;
2324
2425const initAction = async ( projectPath : string ) : Promise < void > => {
25- await actions . init ( projectPath ) ;
26+ await telemetry . trackCommand ( 'init' , ( ) => actions . init ( projectPath ) ) ;
2627} ;
2728
2829const checkAction = async ( options : Parameters < typeof actions . check > [ 0 ] ) : Promise < void > => {
29- await actions . check ( options ) ;
30+ await telemetry . trackCommand ( 'check' , ( ) => actions . check ( options ) ) ;
3031} ;
3132
32- export function createProgram ( ) {
33+ function createProgram ( ) {
3334 const program = new Command ( 'zen' ) ;
3435
3536 program . version ( getVersion ( ) ! , '-v --version' , 'display CLI version' ) ;
@@ -50,10 +51,13 @@ export function createProgram() {
5051 `schema file (with extension ${ schemaExtensions } ). Defaults to "zenstack/schema.zmodel" unless specified in package.json.` ,
5152 ) ;
5253
54+ const noVersionCheckOption = new Option ( '--no-version-check' , 'do not check for new version' ) ;
55+
5356 program
5457 . command ( 'generate' )
5558 . description ( 'Run code generation plugins.' )
5659 . addOption ( schemaOption )
60+ . addOption ( noVersionCheckOption )
5761 . addOption ( new Option ( '-o, --output <path>' , 'default output directory for code generation' ) )
5862 . addOption ( new Option ( '--silent' , 'suppress all output except errors' ) . default ( false ) )
5963 . action ( generateAction ) ;
@@ -64,6 +68,7 @@ export function createProgram() {
6468 migrateCommand
6569 . command ( 'dev' )
6670 . addOption ( schemaOption )
71+ . addOption ( noVersionCheckOption )
6772 . addOption ( new Option ( '-n, --name <name>' , 'migration name' ) )
6873 . addOption ( new Option ( '--create-only' , 'only create migration, do not apply' ) )
6974 . addOption ( migrationsOption )
@@ -75,26 +80,30 @@ export function createProgram() {
7580 . addOption ( schemaOption )
7681 . addOption ( new Option ( '--force' , 'skip the confirmation prompt' ) )
7782 . addOption ( migrationsOption )
83+ . addOption ( noVersionCheckOption )
7884 . description ( 'Reset your database and apply all migrations, all data will be lost.' )
7985 . action ( ( options ) => migrateAction ( 'reset' , options ) ) ;
8086
8187 migrateCommand
8288 . command ( 'deploy' )
8389 . addOption ( schemaOption )
90+ . addOption ( noVersionCheckOption )
8491 . addOption ( migrationsOption )
8592 . description ( 'Deploy your pending migrations to your production/staging database.' )
8693 . action ( ( options ) => migrateAction ( 'deploy' , options ) ) ;
8794
8895 migrateCommand
8996 . command ( 'status' )
9097 . addOption ( schemaOption )
98+ . addOption ( noVersionCheckOption )
9199 . addOption ( migrationsOption )
92100 . description ( 'Check the status of your database migrations.' )
93101 . action ( ( options ) => migrateAction ( 'status' , options ) ) ;
94102
95103 migrateCommand
96104 . command ( 'resolve' )
97105 . addOption ( schemaOption )
106+ . addOption ( noVersionCheckOption )
98107 . addOption ( migrationsOption )
99108 . addOption ( new Option ( '--applied <migration>' , 'record a specific migration as applied' ) )
100109 . addOption ( new Option ( '--rolled-back <migration>' , 'record a specific migration as rolled back' ) )
@@ -107,6 +116,7 @@ export function createProgram() {
107116 . command ( 'push' )
108117 . description ( 'Push the state from your schema to your database.' )
109118 . addOption ( schemaOption )
119+ . addOption ( noVersionCheckOption )
110120 . addOption ( new Option ( '--accept-data-loss' , 'ignore data loss warnings' ) )
111121 . addOption ( new Option ( '--force-reset' , 'force a reset of the database before push' ) )
112122 . action ( ( options ) => dbAction ( 'push' , options ) ) ;
@@ -115,35 +125,64 @@ export function createProgram() {
115125 . command ( 'info' )
116126 . description ( 'Get information of installed ZenStack packages.' )
117127 . argument ( '[path]' , 'project path' , '.' )
128+ . addOption ( noVersionCheckOption )
118129 . action ( infoAction ) ;
119130
120131 program
121132 . command ( 'init' )
122133 . description ( 'Initialize an existing project for ZenStack.' )
123134 . argument ( '[path]' , 'project path' , '.' )
135+ . addOption ( noVersionCheckOption )
124136 . action ( initAction ) ;
125137
126138 program
127139 . command ( 'check' )
128140 . description ( 'Check a ZModel schema for syntax or semantic errors.' )
129141 . addOption ( schemaOption )
142+ . addOption ( noVersionCheckOption )
130143 . action ( checkAction ) ;
131144
145+ program . hook ( 'preAction' , async ( _thisCommand , actionCommand ) => {
146+ if ( actionCommand . getOptionValue ( 'versionCheck' ) !== false ) {
147+ await checkNewVersion ( ) ;
148+ }
149+ } ) ;
150+
132151 return program ;
133152}
134153
135- const program = createProgram ( ) ;
154+ async function main ( ) {
155+ let exitCode = 0 ;
156+
157+ const program = createProgram ( ) ;
158+ program . exitOverride ( ) ;
159+
160+ try {
161+ await telemetry . trackCli ( async ( ) => {
162+ await program . parseAsync ( ) ;
163+ } ) ;
164+ } catch ( e ) {
165+ if ( e instanceof CommanderError ) {
166+ // ignore
167+ exitCode = e . exitCode ;
168+ } else if ( e instanceof CliError ) {
169+ // log
170+ console . error ( colors . red ( e . message ) ) ;
171+ exitCode = 1 ;
172+ } else {
173+ console . error ( colors . red ( `Unhandled error: ${ e } ` ) ) ;
174+ exitCode = 1 ;
175+ }
176+ }
136177
137- program . parseAsync ( ) . catch ( ( err ) => {
138- if ( err instanceof CliError ) {
139- console . error ( colors . red ( err . message ) ) ;
140- process . exit ( 1 ) ;
141- } else if ( err instanceof CommanderError ) {
142- // errors are already reported, just exit
143- process . exit ( err . exitCode ) ;
178+ if ( telemetry . isTracking ) {
179+ // give telemetry a chance to send events before exit
180+ setTimeout ( ( ) => {
181+ process . exit ( exitCode ) ;
182+ } , 200 ) ;
144183 } else {
145- console . error ( colors . red ( 'An unexpected error occurred:' ) ) ;
146- console . error ( err ) ;
147- process . exit ( 1 ) ;
184+ process . exit ( exitCode ) ;
148185 }
149- } ) ;
186+ }
187+
188+ main ( ) ;
0 commit comments