@@ -11,6 +11,80 @@ const EOL = os.EOL;
1111const formatters = require ( './formatters' ) ;
1212const getSysDataPath = require ( '../utils/get-system-data-dir' ) ;
1313
14+ /**
15+ * @typedef {import('chalk').Chalk } Chalk
16+ * @typedef {import('inquirer') } Inquirer
17+ * @typedef {import('yargs') } YargsInstance
18+ * @typedef {import('yargs').Arguments } Arguments
19+ * @typedef {import('yargs').CommandModule } CommandModule
20+ * @typedef {import('yargs').Options } Options
21+ * @typedef {import('yargs').ParserConfigurationOptions } ParserConfigurationOptions
22+ * @typedef {import('yargs').BuilderCallback } BuilderCallback
23+ */
24+
25+ /**
26+ * @typedef {Object } GlobalOptions
27+ * @property {Object } channel - Channel option configuration
28+ * @property {string } channel.describe - Option description
29+ * @property {string[] } channel.choices - Valid channel choices
30+ * @property {boolean } channel.global - Whether option is global
31+ * @property {string } channel.type - Option type
32+ * @property {Object } clear - Clear option configuration
33+ * @property {string } clear.describe - Option description
34+ * @property {boolean } clear.global - Whether option is global
35+ * @property {string } clear.type - Option type
36+ * @property {Object } debug - Debug option configuration
37+ * @property {string } debug.describe - Option description
38+ * @property {boolean } debug.global - Whether option is global
39+ * @property {string } debug.type - Option type
40+ * @property {Object } experimental - Experimental option configuration
41+ * @property {string } experimental.describe - Option description
42+ * @property {boolean } experimental.global - Whether option is global
43+ * @property {boolean } experimental.hidden - Whether option is hidden
44+ * @property {string } experimental.type - Option type
45+ * @property {Object } help - Help option configuration
46+ * @property {string } help.describe - Option description
47+ * @property {string } help.type - Option type
48+ * @property {Object } lando - Lando option configuration
49+ * @property {boolean } lando.hidden - Whether option is hidden
50+ * @property {string } lando.type - Option type
51+ * @property {Object } verbose - Verbose option configuration
52+ * @property {string } verbose.alias - Option alias
53+ * @property {string } verbose.describe - Option description
54+ * @property {string } verbose.type - Option type
55+ */
56+
57+ /**
58+ * @typedef {Object } TaskConfig
59+ * @property {string } [command] - Command name
60+ * @property {string } [describe] - Command description
61+ * @property {Array<string|Array> } [examples] - Command examples
62+ * @property {string } [file] - Path to task file
63+ * @property {Options } [options] - Command options
64+ * @property {Object } [positionals] - Command positional arguments
65+ * @property {Function|Object } [run] - Command run function
66+ * @property {string } [level='app'] - Command level
67+ * @property {string } [usage] - Command usage
68+ */
69+
70+ /**
71+ * @typedef {Object } CliConfig
72+ * @property {string } [prefix='LANDO'] - Environment variable prefix
73+ * @property {string } [logLevel='warn'] - Default log level
74+ * @property {string } [userConfRoot='~/.lando'] - Path to user config directory
75+ * @property {string } [coreBase='../'] - Path to Lando core base directory
76+ * @property {Function } [debug=require('debug')('@lando/cli')] - Debug function
77+ */
78+
79+ /**
80+ * @typedef {Object } ErrorHandler
81+ * @property {(error: Error & {verbose?: number}, reportErrors?: boolean) => Promise<number> } handle - Handles an error and returns exit code
82+ */
83+
84+ /**
85+ * @typedef {Error & {verbose?: number} } LandoError
86+ */
87+
1488// Global options
1589const globalOptions = {
1690 channel : {
@@ -50,17 +124,42 @@ const globalOptions = {
50124 } ,
51125} ;
52126
53- /*
54- * Construct the CLI
127+ /**
128+ * The CLI class provides command line interface functionality for Lando
129+ *
130+ * This class handles command line argument parsing, task management, and user interaction
131+ * for the Lando CLI. It integrates with the core Lando system to provide a complete
132+ * command line interface.
133+ *
134+ * @since 3.0.0
135+ * @class
136+ * @memberof module:Lando
137+ * @property {string } prefix - Environment variable prefix for CLI
138+ * @property {string } logLevel - Default log level
139+ * @property {string } userConfRoot - Path to user config directory
140+ * @property {string } coreBase - Path to Lando core base directory
141+ * @property {Function } debug - Debug logging function
142+ * @property {Chalk } chalk - Chalk instance for terminal coloring
143+ * @property {Arguments } argv Parsed CLI arguments
144+ * @property {Function } checkPerms Checks if Lando is running with sudo
145+ * @property {Function } clearTaskCaches Clears the Lando task caches
146+ * @property {Function } confirm Creates a confirmation prompt configuration
147+ * @property {Function } defaultConfig Returns default configuration for CLI bootstrap
148+ * @property {Function } formatData Formats data for CLI output
149+ * @property {Function } formatOptions Gets CLI options formatting
55150 */
56- module . exports = class Cli {
57- constructor (
151+ class Cli {
152+ /**
153+ * Creates a new CLI instance
154+ * @param {CliConfig } config - CLI configuration options
155+ */
156+ constructor ( {
58157 prefix = 'LANDO' ,
59158 logLevel = 'warn' ,
60159 userConfRoot = path . join ( os . homedir ( ) , '.lando' ) ,
61160 coreBase = path . resolve ( __dirname , '..' ) ,
62161 debug = require ( 'debug' ) ( '@lando/cli' ) ,
63- ) {
162+ } = { } ) {
64163 this . prefix = prefix ;
65164 this . logLevel = logLevel ;
66165 this . userConfRoot = userConfRoot ;
@@ -74,7 +173,7 @@ module.exports = class Cli {
74173 *
75174 * @since 3.0.0
76175 * @alias lando.cli.argv
77- * @return {Object } Yarg parsed options
176+ * @return {Arguments } Yargs parsed command line arguments
78177 * @example
79178 * const argv = lando.cli.argv();
80179 * @todo make this static and then fix all call sites
@@ -84,29 +183,35 @@ module.exports = class Cli {
84183 }
85184
86185 /**
87- * Checks to see if lando is running with sudo. If it is it
88- * will exit the process with a stern warning
186+ * Checks if Lando is running with sudo and exits if true
89187 *
90188 * @since 3.0.0
91189 * @alias lando.cli.checkPerms
92190 * @example
93191 * lando.cli.checkPerms()
192+ * @throws {Error } If Lando is running with sudo
94193 */
95194 checkPerms ( ) {
96195 const sudoBlock = require ( 'sudo-block' ) ;
97196 sudoBlock ( this . makeArt ( 'sudoRun' ) ) ;
98197 }
99198
100- /*
101- * Toggle the secret toggle
199+ /**
200+ * Clears the Lando task caches
201+ * @private
102202 */
103203 clearTaskCaches ( ) {
104- if ( fs . existsSync ( process . landoTaskCacheFile ) ) fs . unlinkSync ( process . landoTaskCacheFile ) ;
105- if ( fs . existsSync ( process . landoAppCacheFile ) ) fs . unlinkSync ( process . landoAppCacheFile ) ;
204+ const taskCacheFile = process . env . LANDO_TASK_CACHE_FILE ;
205+ const appCacheFile = process . env . LANDO_APP_CACHE_FILE ;
206+ if ( taskCacheFile && fs . existsSync ( taskCacheFile ) ) fs . unlinkSync ( taskCacheFile ) ;
207+ if ( appCacheFile && fs . existsSync ( appCacheFile ) ) fs . unlinkSync ( appCacheFile ) ;
106208 }
107209
108- /*
109- * Confirm question
210+ /**
211+ * Creates a confirmation prompt configuration
212+ *
213+ * @param {string } [message='Are you sure?'] Prompt message
214+ * @return {Object } Inquirer prompt configuration
110215 */
111216 confirm ( message = 'Are you sure?' ) {
112217 return {
@@ -123,13 +228,12 @@ module.exports = class Cli {
123228 }
124229
125230 /**
126- * Returns a config object with some good default settings for bootstrapping
127- * lando as a command line interface
231+ * Returns default configuration for CLI bootstrap
128232 *
129233 * @since 3.5.0
130234 * @alias lando.cli.defaultConfig
131235 * @param {Object } [appConfig={}] Optional raw landofile
132- * @return {Object } Config that can be used in a Lando CLI bootstrap
236+ * @return {Object } CLI bootstrap configuration
133237 * @example
134238 * const config = lando.cli.defaultConfig();
135239 * // Kick off our bootstrap
@@ -218,44 +322,70 @@ module.exports = class Cli {
218322 return config ;
219323 }
220324
221- /*
222- * Format data
325+ /**
326+ * Formats data for CLI output
327+ *
328+ * @param {* } data Data to format
329+ * @param {Object } [options] Format options
330+ * @param {string } [options.path=''] Path to data property
331+ * @param {string } [options.format='default'] Output format
332+ * @param {Array } [options.filter=[]] Properties to filter
333+ * @param {Object } [opts={}] Additional formatting options
334+ * @return {string } Formatted output
223335 */
224336 formatData ( data , { path = '' , format = 'default' , filter = [ ] } = { } , opts = { } ) {
225337 return formatters . formatData ( data , { path, format, filter} , opts ) ;
226338 }
227339
228- /*
229- * FormatOptios
340+ /**
341+ * Gets CLI options formatting
342+ *
343+ * @param {Array } [omit=[]] Options to omit
344+ * @return {Object } Formatted options
230345 */
231346 formatOptions ( omit = [ ] ) {
232347 return formatters . formatOptions ( omit ) ;
233348 }
234349
350+ /**
351+ * Gets Inquirer instance for prompts
352+ *
353+ * @return {Inquirer } Inquirer instance
354+ */
235355 getInquirer ( ) {
236356 return require ( 'inquirer' ) ;
237357 }
238358
359+ /**
360+ * Gets oclif UX instance
361+ *
362+ * @return {Object } oclif UX instance
363+ */
239364 getUX ( ) {
240365 return require ( '@oclif/core' ) . ux ;
241366 }
242367
368+ /**
369+ * Checks if debug mode is enabled
370+ *
371+ * @return {number } Debug level
372+ */
243373 isDebug ( ) {
244374 const { debug, verbose} = this . argv ( ) ;
245375 return debug ? 1 + verbose : 0 + verbose ;
246376 }
247377
248378 /**
249- * Cli wrapper for error handler
379+ * Handles CLI errors
250380 *
251381 * @since 3.0.0
252382 * @alias lando.cli.handleError
253- * @param {Error } error The error
254- * @param {Function } handler The error handler function
255- * @param {Integer } verbose [verbose=this.argv().verbose] The verbosity level
256- * @param {Object } lando The Lando object
257- * @param {Boolean } yes [yes=this.argv().yes] The auto yes value
258- * @return {Integer } The exit codes
383+ * @param {LandoError } error Error object
384+ * @param {ErrorHandler } handler Error handler
385+ * @param {number } [verbose=this.argv().verbose] Verbosity level
386+ * @param {Object } [ lando={}] Lando instance
387+ * @param {boolean } [yes=this.argv().yes] Auto-confirm prompts
388+ * @return {Promise<number> } Exit code
259389 */
260390 handleError ( error , handler , verbose = this . argv ( ) . verbose , lando = { } , yes = this . argv ( ) . yes ) {
261391 // Set the verbosity
@@ -289,8 +419,13 @@ module.exports = class Cli {
289419 . then ( ( ) => handler . handle ( error , lando . cache . get ( 'report_errors' ) ) . then ( code => process . exit ( code ) ) ) ;
290420 }
291421
292- /*
293- * Init
422+ /**
423+ * Initializes the CLI with tasks and configuration
424+ *
425+ * @param {YargsInstance } yargs Yargs instance
426+ * @param {Array<CommandModule> } tasks CLI tasks
427+ * @param {Object } config Lando configuration
428+ * @param {Object } [userConfig={}] User configuration
294429 */
295430 init ( yargs , tasks , config , userConfig = { } ) {
296431 // if we have LANDO_ENTRYPOINT_NAME
@@ -351,15 +486,14 @@ module.exports = class Cli {
351486 yargs . argv ;
352487 }
353488
354-
355489 /**
356- * Returns some cli " art"
490+ * Generates CLI art
357491 *
358492 * @since 3.0.0
359493 * @alias lando.cli.makeArt
360- * @param {String } [ func='start'] The art func you want to call
361- * @param {Object } [opts] Func options
362- * @return {String } Usually a printable string
494+ * @param {string } func Art function to call
495+ * @param {Object } [opts] Function options
496+ * @return {string } Generated art
363497 * @example
364498 * console.log(lando.cli.makeArt('secretToggle', true);
365499 */
@@ -368,18 +502,18 @@ module.exports = class Cli {
368502 }
369503
370504 /**
371- * Parses a lando task object into something that can be used by the [yargs](http://yargs.js.org/docs/) CLI.
505+ * Parses a Lando task into Yargs command format
372506 *
373507 * A lando task object is an abstraction on top of yargs that also contains some
374508 * metadata about how to interactively ask questions on both a CLI and GUI.
375509 *
376510 * @since 3.5.0
377511 * @alias lando.cli.parseToYargs
378- * @see [yargs docs](http://yargs.js.org/docs/)
379- * @see [inquirer docs](https://github.com/sboudrias/Inquirer.js)
380- * @param { Object } task A Lando task object (@see add for definition)
381- * @param { Object } [config={}] The landofile
382- * @return { Object } A yargs command object
512+ * @param { TaskConfig } task - Lando task configuration
513+ * @param { Object } [config={}] - Lando configuration
514+ * @return { CommandModule } Yargs command object
515+ * @see { @link http://yargs.js.org/docs/|Yargs }
516+ * @see { @link https://github.com/sboudrias/Inquirer.js|Inquirer.js }
383517 * @example
384518 * // Add a task to the yargs CLI
385519 * yargs.command(lando.tasks.parseToYargs(task));
@@ -502,12 +636,23 @@ module.exports = class Cli {
502636 } } ;
503637 }
504638
639+ /**
640+ * Prettifies data for CLI output
641+ *
642+ * @param {* } data Data to prettify
643+ * @param {Object } [options] Prettify options
644+ * @param {string } [options.arraySeparator=', '] Separator for arrays
645+ * @return {string } Prettified output
646+ */
505647 prettify ( data , { arraySeparator = ', ' } = { } ) {
506648 return require ( '../utils/prettify' ) ( data , { arraySeparator} ) ;
507649 }
508650
509- /*
510- * Run the CLI
651+ /**
652+ * Runs the CLI
653+ *
654+ * @param {Array<CommandModule> } [tasks=[]] CLI tasks
655+ * @param {Object } [config={}] Lando configuration
511656 */
512657 run ( tasks = [ ] , config = { } ) {
513658 const yargonaut = require ( 'yargonaut' ) ;
@@ -551,8 +696,11 @@ module.exports = class Cli {
551696 this . init ( yargs , tasks , config , userConfig ) ;
552697 }
553698
554- /*
555- * Toggle a toggle
699+ /**
700+ * Updates user configuration
701+ *
702+ * @param {Object } [data={}] Configuration updates
703+ * @return {Object } Updated configuration
556704 */
557705 updateUserConfig ( data = { } ) {
558706 const Yaml = require ( `../lib/yaml` ) ;
@@ -562,4 +710,6 @@ module.exports = class Cli {
562710 const file = yaml . dump ( configFile , _ . assign ( { } , config , data ) ) ;
563711 return yaml . load ( file ) ;
564712 }
565- } ;
713+ }
714+
715+ module . exports = Cli ;
0 commit comments