11'use strict' ;
22
3+ /**
4+ * @typedef {import('./cache') } Cache
5+ * @typedef {import('./cli') } Cli
6+ * @typedef {import('./events') } AsyncEvents
7+ * @typedef {import('bluebird') } Bluebird
8+ * @typedef {Object } Debugger
9+ * @property {(formatter: any, ...args: any[]) => void } __call - Debug function that logs messages
10+ * @property {() => Debugger } contract - Returns a new debugger instance with the same namespace
11+ * @property {() => Debugger } replace - Returns a new debugger instance replacing the current one
12+ * @property {(name: string) => Debugger & {(formatter: any, ...args: any[]): void} } extend - Creates a new debugger with an extended namespace
13+ * @property {string } color - ANSI color code for console output
14+ * @property {number } diff - Time difference for timing operations
15+ * @property {boolean } enabled - Whether debug output is enabled
16+ * @property {(...args: any[]) => any } log - Raw logging function
17+ * @property {string } namespace - Debug namespace identifier
18+ * @property {() => void | boolean } destroy - Cleanup function for debugger instance
19+ */
20+
21+ /**
22+ * @typedef {Object } LandoConfig
23+ * @property {string|number } logLevelConsole - Log level for console output
24+ * @property {string } userAgent - User agent string
25+ * @property {string } channel - Update channel
26+ * @property {Object } cli - CLI configuration
27+ * @property {string } pluginConfigFile - Path to plugin config file
28+ * @property {Object } pluginConfig - Plugin configuration
29+ * @property {boolean } isInteractive - Whether running in interactive mode
30+ * @property {string } caCert - Path to CA certificate
31+ * @property {string } caKey - Path to CA private key
32+ * @property {string } userConfRoot - Path to user config directory
33+ * @property {Array<{path: string, type: string, dir?: string}> } pluginDirs - Plugin directories
34+ * @property {string[] } preLandoFiles - Pre-lando configuration files
35+ * @property {string } landoFile - Main lando configuration file
36+ * @property {string[] } postLandoFiles - Post-lando configuration files
37+ * @property {Object } setup - Setup configuration
38+ */
39+
40+ /**
41+ * @typedef {Object } DebugShim
42+ * @property {(...args: any[]) => void } debug - Debug logging function
43+ * @property {() => any } contract - Contract function
44+ * @property {() => any } replace - Replace function
45+ * @property {(name: string) => any } extend - Extend function
46+ * @property {string } [color] - Color property
47+ * @property {boolean } [diff] - Diff property
48+ * @property {boolean } [enabled] - Enabled property
49+ * @property {Function } [log] - Log function
50+ */
51+
52+ /**
53+ * @typedef {Object } LandoOptions
54+ * @property {string } [logLevelConsole] - Log level for console output
55+ * @property {string } [userConfRoot] - Path to user config directory
56+ * @property {string } [envPrefix] - Environment variable prefix
57+ * @property {Object[] } [configSources] - Config source definitions
58+ * @property {string[] } [pluginDirs] - Directories to scan for plugins
59+ * @property {string } [mode='cli'] - Operating mode
60+ */
61+
62+ /**
63+ * @typedef {Object } SetupResults
64+ * @property {Array<Error> } errors - Setup errors
65+ * @property {Array<Object> } results - Setup results
66+ * @property {boolean } restart - Whether restart is needed
67+ * @property {number } total - Total number of operations
68+ */
69+
70+ /**
71+ * @typedef {Object } PluginStatus
72+ * @property {string } description - Plugin description
73+ * @property {string } state - Current state (INSTALLED|NOT INSTALLED|CANNOT INSTALL)
74+ * @property {string } version - Plugin version
75+ * @property {string } [comment] - Additional status details
76+ */
77+
78+ /**
79+ * @typedef {Object } TaskResults
80+ * @property {Object } data - Raw task data
81+ * @property {Array<Error> } errors - Task errors
82+ * @property {Array<Object> } results - Task results
83+ * @property {number } total - Total number of tasks processed
84+ * @property {number } [skipped] - Number of skipped tasks
85+ * @property {number } [ran] - Number of tasks that ran
86+ */
87+
88+ /**
89+ * @typedef {Object } TaskRunnerOptions
90+ * @property {string } [renderer='simple'] - Progress renderer to use
91+ * @property {Object } [rendererOptions] - Options for the renderer
92+ * @property {boolean } [concurrent] - Whether to run tasks concurrently
93+ * @property {boolean } [exitOnError] - Whether to exit on first error
94+ * @property {string } [debug] - Debug renderer to use
95+ * @property {string } [fallbackRenderer] - Fallback renderer if primary fails
96+ * @property {boolean } [rendererForce] - Force use of specified renderer
97+ */
98+
99+ /**
100+ * @typedef {Object } UpdateManagerOptions
101+ * @property {string } [agent] - User agent string
102+ * @property {string } [channel] - Update channel
103+ * @property {Object } [cli] - CLI configuration
104+ * @property {Object } [config] - Plugin configuration
105+ * @property {any } [debug] - Debug logger
106+ */
107+
3108const _ = require ( 'lodash' ) ;
4109const fs = require ( 'fs' ) ;
5110const glob = require ( 'glob' ) ;
@@ -170,63 +275,78 @@ const bootstrapRouter = async (level, lando) => {
170275} ;
171276
172277/**
173- * The class to instantiate a new Lando
278+ * The Lando class provides core functionality for the Lando framework
174279 *
175- * Generally you will not need to do this unless you are using Lando to build your own
176- * interface.
280+ * Generally you will not need to instantiate this directly unless you are using Lando
281+ * to build your own interface.
177282 *
178283 * Check out `./bin/lando.js` in this repository for an example of how we instantiate
179284 * `lando` for usage in a CLI.
180285 *
181286 * @since 3.0.0
287+ * @class
182288 * @name Lando
183- * @param {Object } [options] Options to initialize a Lando object with
184- * @return {Lando } An initialized Lando instance
185- * @example
186- * // Get a new lando instance
187- * const Lando = require('lando');
188- * const lando = new Lando({
189- * logLevelConsole: LOGLEVELCONSOLE,
190- * userConfRoot: USERCONFROOT,
191- * envPrefix: ENVPREFIX,
192- * configSources: configSources,
193- * pluginDirs: [USERCONFROOT],
194- * mode: 'cli'
195- * });
289+ * @module Lando
290+ * @alias lando
291+ * @property {Object } BOOTSTRAP_LEVELS Bootstrap level constants {config: 1, tasks: 2, engine: 3, app: 4}
292+ * @property {LandoConfig } config The complete Lando configuration object
293+ * @property {Bluebird } Promise A Promise implementation
294+ * @property {Array } tasks Array of registered Lando tasks
295+ * @property {Cache } cache Cache manager instance
296+ * @property {Object } log Winston logger instance
297+ * @property {Object } metrics Metrics tracking system
298+ * @property {Object } error Error handler instance
299+ * @property {AsyncEvents } events Event emitter for async events
300+ * @property {Object } user User configuration
301+ * @property {Object } updates Update manager instance
302+ * @property {boolean } debuggy Whether debug mode is enabled
303+ * @property {Object } engine Docker engine interface
304+ * @property {Object } shell Shell command executor
305+ * @property {Object } scanUrls URL scanning utility
306+ * @property {Object } utils Collection of utility functions
307+ * @property {Object } factory Service/recipe factory
308+ * @property {Object } yaml YAML parser/writer utility
196309 */
197- module . exports = class Lando {
310+ class Lando {
311+ /**
312+ * Creates a new Lando instance
313+ * @param {LandoOptions } [options] Options to initialize a Lando object with
314+ */
198315 constructor ( options = { } ) {
199316 const getPluginConfig = require ( '../utils/get-plugin-config' ) ;
200317
201318 this . BOOTSTRAP_LEVELS = BOOTSTRAP_LEVELS ;
319+ /** @type {LandoConfig } */
202320 this . config = require ( '../utils/build-config' ) ( options ) ;
321+ /** @type {Bluebird } */
203322 this . Promise = require ( './promise' ) ;
204323 this . tasks = [ ] ;
205324 const AsyncEvents = require ( './events' ) ;
206325 const Log = require ( './logger' ) ;
207326 const ErrorHandler = require ( './error' ) ;
208327 const UpdateManager = require ( './updates' ) ;
209328 this . cache = require ( '../utils/setup-cache' ) ( this . log , this . config ) ;
210- this . log = new Log ( this . config ) ;
329+ this . log = new Log ( { logLevelConsole : String ( this . config . logLevelConsole ) } ) ;
211330 this . metrics = require ( '../utils/setup-metrics' ) ( this . log , this . config ) ;
212331 this . error = new ErrorHandler ( this . log , this . metrics ) ,
213332 this . events = new AsyncEvents ( this . log ) ;
214333 this . user = require ( './user' ) ;
215334
216335 // updater is more complex now
217- this . updates = new UpdateManager ( {
336+ /** @type {UpdateManagerOptions } */
337+ const updateOpts = {
218338 agent : this . config . userAgent ,
219339 channel : this . config . channel ,
220340 cli : _ . get ( this , 'config.cli' ) ,
221341 config : getPluginConfig ( this . config . pluginConfigFile , this . config . pluginConfig ) ,
222342 debug : require ( '../utils/debug-shim' ) ( this . log ) ,
223- } ) ;
343+ } ;
344+ this . updates = new UpdateManager ( updateOpts ) ;
224345
225346 // helper just to determine whether we are "debuggy" or not
226- this . debuggy = this . config . logLevelConsole > 2
227- || this . config . logLevelConsole === 'verbose'
228- || this . config . logLevelConsole === 'debug'
229- || this . config . logLevelConsole === 'silly' ;
347+ this . debuggy = this . config . logLevelConsole === 'verbose' ||
348+ this . config . logLevelConsole === 'debug' ||
349+ this . config . logLevelConsole === 'silly' ;
230350 }
231351
232352 /**
@@ -265,11 +385,8 @@ module.exports = class Lando {
265385 * @fires post_bootstrap_tasks
266386 * @fires post_bootstrap_engine
267387 * @fires post_bootstrap_app
268- * @param {String } [level=app] Level with which to bootstrap Lando
269- * @return {Promise } A Promise
270- * @example
271- * // Bootstrap lando at default level and then exit
272- * lando.bootstrap().then(() => process.exit(0))l
388+ * @param {string } [level='app'] Level with which to bootstrap Lando
389+ * @return {Promise<Lando> } A Promise that resolves with the bootstrapped Lando instance
273390 */
274391 bootstrap ( level = 'app' ) {
275392 // Log that we've begun
@@ -397,6 +514,20 @@ module.exports = class Lando {
397514 . then ( ( ) => this ) ;
398515 }
399516
517+ /**
518+ * Generates an SSL certificate for a domain
519+ *
520+ * @param {string } name - Name to use for the certificate files
521+ * @param {Object } [options] - Certificate generation options
522+ * @param {string } [options.caCert] - Path to CA certificate
523+ * @param {string } [options.caKey] - Path to CA private key
524+ * @param {string[] } [options.domains=[]] - Additional domains for the cert
525+ * @param {string } [options.organization='Lando System'] - Organization name
526+ * @param {number } [options.validity=365] - Certificate validity in days
527+ * @return {Promise<Object> } Object containing paths to generated cert and key
528+ * @property {string } certPath - Path to generated certificate
529+ * @property {string } keyPath - Path to generated private key
530+ */
400531 async generateCert ( name , {
401532 caCert = this . config . caCert ,
402533 caKey = this . config . caKey ,
@@ -436,15 +567,15 @@ module.exports = class Lando {
436567 }
437568
438569 /**
439- * Gets a fully instantiated App instance.
570+ * Gets a fully instantiated App instance
440571 *
441- * Lando will also scan parent directories if no app is found in `startFrom`
572+ * Lando will scan parent directories if no app is found in the starting directory.
442573 *
443574 * @since 3.0.0
444575 * @alias lando.getApp
445- * @param {String } [startFrom=process.cwd()] The directory to start looking for an app
446- * @param {Boolean } [warn=true] Show a warning if we can't find an app
447- * @return {App } Returns an instantiated App instandce.
576+ * @param {string } [startFrom=process.cwd()] - The directory to start looking for an app
577+ * @param {boolean } [warn=true] - Whether to show a warning if no app is found
578+ * @return {App|undefined } Returns an instantiated App instance or undefined if no app found
448579 * @example
449580 * const app = lando.getApp('/path/to/my/app')
450581 */
@@ -472,6 +603,12 @@ module.exports = class Lando {
472603 return new App ( config . name , _ . merge ( { } , config , { files : landoFiles } ) , this ) ;
473604 }
474605
606+ /**
607+ * Gets installation status for plugins
608+ * @param {Object } [options] - Plugin installation options
609+ * @param {Object } [options.plugins] - Plugin definitions to check
610+ * @return {Promise<PluginStatus[]> } Array of plugin status objects
611+ */
475612 async getInstallPluginsStatus ( options = this . config . setup ) {
476613 const getPluginConfig = require ( '../utils/get-plugin-config' ) ;
477614 const Plugin = require ( '../components/plugin' ) ;
@@ -481,7 +618,8 @@ module.exports = class Lando {
481618 Plugin . debug = require ( '../utils/debug-shim' ) ( this . log ) ;
482619
483620 // attempt to compute the destination to install the plugin
484- const { dir} = this . config . pluginDirs . find ( dir => dir . type === require ( '../utils/get-plugin-type' ) ( ) ) ;
621+ const pluginDir = this . config . pluginDirs . find ( dir => dir . type === require ( '../utils/get-plugin-type' ) ( ) ) ;
622+ const dir = pluginDir ?. dir ;
485623
486624 // event that lets plugins modify the status check
487625 await this . events . emit ( 'pre-install-plugins' , options ) ;
@@ -517,6 +655,12 @@ module.exports = class Lando {
517655 return results ;
518656 }
519657
658+ /**
659+ * Installs Lando plugins
660+ * @param {Object } [options] - Plugin installation options
661+ * @param {Object } [options.plugins] - Plugin definitions to install
662+ * @return {Promise<TaskResults> } Installation results
663+ */
520664 async installPlugins ( options = this . config . setup ) {
521665 const getPluginConfig = require ( '../utils/get-plugin-config' ) ;
522666 const Plugin = require ( '../components/plugin' ) ;
@@ -559,7 +703,12 @@ module.exports = class Lando {
559703 return { data, errors, results, total} ;
560704 }
561705
562- // run tasks
706+ /**
707+ * Runs a series of tasks with progress reporting
708+ * @param {Array } tasks - Tasks to run
709+ * @param {TaskRunnerOptions } [options] - Task runner options
710+ * @return {Promise<TaskResults> } Task results
711+ */
563712 async runTasks ( tasks , options = { } ) {
564713 // some defaults
565714 const defaults = { rendererOptions : { log : this . log . debug } } ;
@@ -570,7 +719,7 @@ module.exports = class Lando {
570719 }
571720
572721 // set to the debug renderer if we are in debug mode
573- if ( this . config . logLevelConsole > 3
722+ if ( ( typeof this . config . logLevelConsole === 'number' && this . config . logLevelConsole > 3 )
574723 || this . config . logLevelConsole === 'debug'
575724 || this . config . logLevelConsole === 'silly' ) {
576725 options . renderer = options . debug || 'debug' ;
@@ -582,15 +731,27 @@ module.exports = class Lando {
582731 return await require ( '../utils/run-tasks' ) ( tasks , _ . merge ( defaults , options ) ) ;
583732 }
584733
585- // this lets us reload plugins mid-process as though we were bootstrapping lando freshly
734+ /**
735+ * Reloads plugins as if bootstrapping fresh
736+ *
737+ * @return {Promise<void> }
738+ */
586739 async reloadPlugins ( ) {
587740 // if we dont do this we have at least double added setup tasks/plugins
588741 this . events . removeAllListeners ( ) ;
589742 // reload plugins
590743 return await bootstrapConfig ( this ) ;
591744 }
592745
593- // setup
746+ /**
747+ * Runs setup tasks and plugin installation
748+ * @param {Object } [options] - Setup options
749+ * @param {Array } [options.tasks=[]] - Setup tasks to run
750+ * @param {Object } [options.plugins={}] - Plugins to install
751+ * @param {boolean } [options.installPlugins] - Whether to install plugins
752+ * @param {boolean } [options.installTasks] - Whether to run setup tasks
753+ * @return {Promise<SetupResults> } Setup results
754+ */
594755 async setup ( options = this . config . setup ) {
595756 // merge needed defaults into options
596757 options = _ . merge ( { tasks : [ ] , plugins : { } } , options ) ;
@@ -655,6 +816,18 @@ module.exports = class Lando {
655816 return data ;
656817 }
657818
819+ /**
820+ * Gets status of setup tasks
821+ *
822+ * @param {Object } [options] - Setup options
823+ * @param {Array } [options.tasks] - Tasks to check status for
824+ * @return {Promise<Array<Object>> } Array of task status objects
825+ * @property {string } version - Task version
826+ * @property {string } description - Task description
827+ * @property {string } state - Current state
828+ * @property {string } [comment] - Additional status details
829+ * @property {boolean } restart - Whether task requires restart
830+ */
658831 async getSetupStatus ( options = this . config . setup ) {
659832 // pre setup event to mutate the setup tasks
660833 await this . events . emit ( 'pre-setup' , options ) ;
@@ -690,4 +863,6 @@ module.exports = class Lando {
690863
691864 return results ;
692865 }
693- } ;
866+ }
867+
868+ module . exports = Lando ;
0 commit comments