@@ -9,9 +9,9 @@ process.env.ELEMENTS_ENV = 'cli';
99import yargs from 'yargs' ;
1010import { hideBin } from 'yargs/helpers' ;
1111import { performance } from 'perf_hooks' ;
12- import { type ManagedToolMethod , tools , ToolSupport , type Schema , isDebug , MAX_CONTEXT_TOKENS } from '@internals/tools' ;
12+ import { type ManagedToolMethod , tools , ToolSupport , type Schema } from '@internals/tools' ;
1313import { installNve } from './install.js' ;
14- import { banner , colors , getArgValue , progressBar , renderResult , runAsyncTool } from './utils.js' ;
14+ import { banner , colors , exitWithCompleteToolResult , exitWithToolError , getArgValue , runAsyncTool } from './utils.js' ;
1515import { notifyIfUpdateAvailable } from './update.js' ;
1616
1717export const VERSION = '0.0.0' ;
@@ -46,11 +46,6 @@ yargsInstance.middleware(argv => {
4646 }
4747} ) ;
4848
49- async function exitWithToolError ( result : unknown , message : string | undefined ) : Promise < never > {
50- console. error ( result === undefined ? colors . error ( message ?? 'unknown error' ) : await renderResult ( result ) ) ;
51- process . exit ( 1 ) ;
52- }
53-
5449yargsInstance . command (
5550 'install [source]' ,
5651 false ,
@@ -73,10 +68,10 @@ yargsInstance.command(
7368 async ( ) => {
7469 if ( process . argv . includes ( '--upgrade' ) ) {
7570 const upgradeTool = tools . find ( tool => tool . metadata . command === 'cli.upgrade' ) as ManagedToolMethod < unknown > ;
76- const { result, status, message } = await runAsyncTool ( { } , upgradeTool ) ;
71+ console . log ( colors . info ( 'Upgrading Elements CLI...' ) ) ;
72+ const { result, status, message } = await runAsyncTool ( { } , upgradeTool , { interactiveProgress : false } ) ;
7773 if ( status === 'complete' ) {
78- await renderResult ( result ) ;
79- process . exit ( 0 ) ;
74+ await exitWithCompleteToolResult ( { result } ) ;
8075 } else {
8176 await exitWithToolError ( result , message ) ;
8277 }
@@ -100,9 +95,12 @@ tools
10095 const optionalArgs = Object . keys ( properties ?? { } ) . filter (
10196 key => ! required ?. includes ( key ) || properties ?. [ key ] ?. default
10297 ) ;
98+ const hasVariadicArg = requiredArgs . some ( key => properties ?. [ key ] ?. type === 'array' ) ;
99+ const positionalArgs = requiredArgs . map ( key => ( properties ?. [ key ] ?. type === 'array' ? `<${ key } ..>` : `<${ key } >` ) ) ;
100+ const optionArgs = optionalArgs . map ( key => `[${ hasVariadicArg ? '--' : '' } ${ key } ]` ) ;
101+ const commandArgs = hasVariadicArg ? [ ...optionArgs , ...positionalArgs ] : [ ...positionalArgs , ...optionArgs ] ;
103102
104- const command =
105- `${ tool . metadata . command } ${ [ ...requiredArgs . map ( key => `<${ key } >` ) , ...optionalArgs . map ( key => `[${ key } ]` ) ] . join ( ' ' ) } ` . trim ( ) ;
103+ const command = `${ tool . metadata . command } ${ commandArgs . join ( ' ' ) } ` . trim ( ) ;
106104
107105 yargsInstance . command (
108106 command ,
@@ -113,7 +111,8 @@ tools
113111
114112 const argOptions = ( prop : Schema ) => ( {
115113 describe : prop . description ,
116- type : prop . type as 'string' | 'number' | 'boolean' ,
114+ type : ( prop . type === 'array' ? 'string' : prop . type ) as 'string' | 'number' | 'boolean' ,
115+ ...( prop . type === 'array' ? { array : true } : { } ) ,
117116 choices : prop . enum ?? undefined ,
118117 default : prop . default
119118 } ) ;
@@ -128,17 +127,13 @@ tools
128127 const end = performance . now ( ) ;
129128
130129 if ( status === 'complete' ) {
131- let formattedResult = await renderResult ( result ) ;
132- if ( isDebug ( ) ) {
133- const tokens = formattedResult . length / 4 ;
134- const pct = ( tokens / MAX_CONTEXT_TOKENS ) * 100 ;
135- formattedResult += `[debug]\n[command]: ${ tool . metadata . command } ` ;
136- formattedResult += `\n[execution time]: ${ ( ( end - start ) / 1000 ) . toFixed ( 2 ) } seconds` ;
137- formattedResult += `\n[token usage]: ${ progressBar ( pct ) } ${ tokens . toLocaleString ( ) } / ${ MAX_CONTEXT_TOKENS . toLocaleString ( ) } (${ ( 100 - pct ) . toFixed ( 1 ) } % remaining)` ;
138- }
139- console . log ( formattedResult ) ;
140- await notifyIfUpdateAvailable ( BUILD_SHA ) ;
141- process . exit ( 0 ) ;
130+ await exitWithCompleteToolResult ( {
131+ result,
132+ tool,
133+ start,
134+ end,
135+ notifyUpdate : ( ) => notifyIfUpdateAvailable ( BUILD_SHA )
136+ } ) ;
142137 } else {
143138 await exitWithToolError ( result , message ) ;
144139 }
@@ -155,13 +150,31 @@ tools
155150 const propertySchema = properties ?. [ argName ] ?? { } ;
156151 const v = await getArgValue ( argName , propertySchema ) ;
157152 argv [ argName ] = v ;
158- } else if ( properties ?. [ argName ] ?. type === 'array' && typeof argv [ argName ] === 'string' ) {
159- argv [ argName ] = ( argv [ argName ] as string )
160- . split ( ',' )
161- . map ( s => s . trim ( ) )
162- . filter ( Boolean ) ;
163153 }
164154 }
155+
156+ Object . entries ( properties ?? { } )
157+ . filter ( ( [ , property ] ) => property . type === 'array' )
158+ . forEach ( ( [ argName , property ] ) => {
159+ if ( argv [ argName ] === undefined ) return ;
160+ const values = ( Array . isArray ( argv [ argName ] ) ? argv [ argName ] : [ argv [ argName ] ] )
161+ . flatMap ( value => ( typeof value === 'string' ? value . split ( ',' ) : [ ] ) )
162+ . map ( value => value . trim ( ) )
163+ . filter ( Boolean ) ;
164+ if ( property . minItems !== undefined && values . length < property . minItems ) {
165+ console . error (
166+ colors . error ( `${ tool . metadata . command } accepts at least ${ property . minItems } ${ argName } .` )
167+ ) ;
168+ process . exit ( 1 ) ;
169+ }
170+ if ( property . maxItems !== undefined && values . length > property . maxItems ) {
171+ console . error (
172+ colors . error ( `${ tool . metadata . command } accepts at most ${ property . maxItems } ${ argName } .` )
173+ ) ;
174+ process . exit ( 1 ) ;
175+ }
176+ argv [ argName ] = values ;
177+ } ) ;
165178 }
166179 ]
167180 ) ;
0 commit comments