11import { z } from 'zod'
22import { isZodError , ParseError , ValidationError } from './error'
33import { defaultHelpConfig , HelpConfig , HelpGenerator } from './help'
4- import MassargOption , {
4+ import {
5+ MassargOption ,
56 MassargFlag ,
67 OptionConfig ,
78 TypedOptionConfig ,
89 MassargHelpFlag ,
910} from './option'
1011import { DeepRequired , setOrPush , deepMerge } from './utils'
11- import MassargExample , { ExampleConfig } from './example'
12+ import { MassargExample , ExampleConfig } from './example'
1213
1314export const CommandConfig = < RunArgs extends z . ZodType > ( args : RunArgs ) =>
1415 z . object ( {
@@ -26,8 +27,6 @@ export const CommandConfig = <RunArgs extends z.ZodType>(args: RunArgs) =>
2627 . function ( )
2728 . args ( args , z . any ( ) )
2829 . returns ( z . union ( [ z . promise ( z . void ( ) ) , z . void ( ) ] ) ) as z . ZodType < Runner < z . infer < RunArgs > > > ,
29- helpConfig : HelpConfig . optional ( ) ,
30- // argsHint: z.string().optional(),
3130 } )
3231
3332export type CommandConfig < T = unknown > = z . infer < ReturnType < typeof CommandConfig < z . ZodType < T > > > >
@@ -39,7 +38,15 @@ export type Runner<Args extends ArgsObject> = <A extends ArgsObject = Args>(
3938 instance : MassargCommand < A > ,
4039) => Promise < void > | void
4140
42- export default class MassargCommand < Args extends ArgsObject = ArgsObject > {
41+ /**
42+ * A command is a named function that can be invoked with a set of options.
43+ *
44+ * Commands can have sub-commands, which can have their own sub-commands, and so on.
45+ *
46+ * Options are not inherited by sub-commands, but their parsed values are passed down when
47+ * invoking a sub-command. This works recursively.
48+ */
49+ export class MassargCommand < Args extends ArgsObject = ArgsObject > {
4350 name : string
4451 description : string
4552 aliases : string [ ]
@@ -57,7 +64,7 @@ export default class MassargCommand<Args extends ArgsObject = ArgsObject> {
5764 this . description = options . description
5865 this . aliases = options . aliases ?? [ ]
5966 this . _run = options . run
60- this . _helpConfig = HelpConfig . required ( ) . parse ( defaultHelpConfig )
67+ this . _helpConfig = { }
6168 this . parent = parent
6269 }
6370
@@ -68,6 +75,15 @@ export default class MassargCommand<Args extends ArgsObject = ArgsObject> {
6875 return deepMerge ( defaultHelpConfig , this . _helpConfig ) as Required < HelpConfig >
6976 }
7077
78+ /**
79+ * Add a sub-command to this command.
80+ *
81+ * The sub-command will inherit all help configuration from the parent commands,
82+ * all the way up to the top-level command.
83+ *
84+ * While options are not inherited, they will be passed from any parent commands
85+ * to the sub-command when invoked.
86+ */
7187 command < A extends ArgsObject = Args > ( config : CommandConfig < A > ) : MassargCommand < Args >
7288 command < A extends ArgsObject = Args > ( config : MassargCommand < A > ) : MassargCommand < Args >
7389 command < A extends ArgsObject = Args > (
@@ -98,6 +114,17 @@ export default class MassargCommand<Args extends ArgsObject = ArgsObject> {
98114 }
99115 }
100116
117+ /**
118+ * Adds a flag to this command.
119+ *
120+ * A flag is an option that is either present or not. It can be used to toggle
121+ * a boolean value, or to indicate that a command should be run in a different
122+ * mode.
123+ *
124+ * A flag can be negated by prefixing it with `no-`. For example, `--no-verbose`,
125+ * or by prefixing the alias with `^` instead of `-`. This is configurable via the command's
126+ * configuration.
127+ */
101128 flag ( config : Omit < OptionConfig < boolean > , 'parse' | 'isDefault' > ) : MassargCommand < Args >
102129 flag ( config : MassargFlag ) : MassargCommand < Args >
103130 flag (
@@ -127,6 +154,19 @@ export default class MassargCommand<Args extends ArgsObject = ArgsObject> {
127154 }
128155 }
129156
157+ /**
158+ * Adds an option to this command.
159+ *
160+ * An option is a named value that can be passed to a command. It can be
161+ * required or optional, and can be of any type.
162+ *
163+ * You can specify a default value for an option, which will be used if the
164+ * option is not passed to the command.
165+ *
166+ * You can also specify a parse function, which will be used to parse the
167+ * value passed to the command. This is useful if you want to parse a string
168+ * into a more complex type, or if you want to validate the value.
169+ */
130170 option < T = string > ( config : MassargOption < T > ) : MassargCommand < Args >
131171 option < T = string > ( config : TypedOptionConfig < T > ) : MassargCommand < Args >
132172 option < T = string > ( config : TypedOptionConfig < T > | MassargOption < T > ) : MassargCommand < Args > {
@@ -165,11 +205,28 @@ export default class MassargCommand<Args extends ArgsObject = ArgsObject> {
165205 }
166206 }
167207
208+ /**
209+ * Adds an example to this command.
210+ *
211+ * An example is a description of how to use the command, with an example input and output.
212+ *
213+ * At least one of `description`, `input` or `output` must be provided, but neither alone is
214+ * required.
215+ */
168216 example ( config : ExampleConfig ) : MassargCommand < Args > {
169217 this . examples . push ( new MassargExample ( config ) )
170218 return this
171219 }
172220
221+ /**
222+ * Configure the help output for this (and all child) commands.
223+ *
224+ * You can automatically bind the help command to this command, and/or bind the help option
225+ * to this command.
226+ *
227+ * If you don't opt-in to this behavior with `bindCommand` or `bindOption`, you can still
228+ * access the help output via `this.helpString()` and `this.printHelp()`.
229+ */
173230 help ( config : HelpConfig ) : MassargCommand < Args > {
174231 this . _helpConfig = HelpConfig . parse ( config )
175232
@@ -182,11 +239,24 @@ export default class MassargCommand<Args extends ArgsObject = ArgsObject> {
182239 return this
183240 }
184241
242+ /**
243+ * Configure the main function for this command. This command will run when no sub-commands
244+ * are provided.
245+ *
246+ * If none is provided, help will be printed.
247+ */
185248 main < A extends ArgsObject = Args > ( run : Runner < A > ) : MassargCommand < Args > {
186249 this . _run = run
187250 return this
188251 }
189252
253+ /**
254+ * Parse the given arguments and run the command or sub-commands along with the given options
255+ * and flags.
256+ *
257+ * To parse the arguments without running any commands and only get the output args,
258+ * use `getArgs` instead.
259+ */
190260 parse ( argv : string [ ] , args ?: Partial < Args > , parent ?: MassargCommand < Args > ) : Promise < void > | void {
191261 this . getArgs ( argv , args , parent , true )
192262 }
@@ -209,6 +279,7 @@ export default class MassargCommand<Args extends ArgsObject = ArgsObject> {
209279 return res . argv
210280 }
211281
282+ /** Parse the given arguments and return the output args. */
212283 getArgs (
213284 argv : string [ ] ,
214285 __args ?: Partial < Args > ,
@@ -279,10 +350,16 @@ export default class MassargCommand<Args extends ArgsObject = ArgsObject> {
279350 }
280351 }
281352
353+ /**
354+ * Generate the help output for this command, and return it as a string.
355+ */
282356 helpString ( ) : string {
283357 return new HelpGenerator ( this ) . generate ( )
284358 }
285359
360+ /**
361+ * Print the help output for this command.
362+ */
286363 printHelp ( ) : void {
287364 console . log ( this . helpString ( ) )
288365 }
@@ -322,5 +399,3 @@ export class MassargHelpCommand<T extends ArgsObject = ArgsObject> extends Massa
322399 } )
323400 }
324401}
325-
326- export { MassargCommand }
0 commit comments