Skip to content

Commit 8bf678e

Browse files
committed
docs: jsdoc updates
chore: small fixes
1 parent b11cdd3 commit 8bf678e

8 files changed

Lines changed: 260 additions & 41 deletions

File tree

src/command.ts

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { z } from 'zod'
22
import { isZodError, ParseError, ValidationError } from './error'
33
import { defaultHelpConfig, HelpConfig, HelpGenerator } from './help'
4-
import MassargOption, {
4+
import {
5+
MassargOption,
56
MassargFlag,
67
OptionConfig,
78
TypedOptionConfig,
89
MassargHelpFlag,
910
} from './option'
1011
import { DeepRequired, setOrPush, deepMerge } from './utils'
11-
import MassargExample, { ExampleConfig } from './example'
12+
import { MassargExample, ExampleConfig } from './example'
1213

1314
export 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

3332
export 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 }

src/error.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { z } from 'zod'
22

3+
/** This error is thrown when a validation fails. */
34
export class ValidationError extends Error {
5+
/** The path to the value that failed validation. */
46
path: string[]
7+
/** The error code. */
58
code: string
9+
/** The error message. */
610
message: string
711

812
constructor({ path, code, message }: { path: string[]; code: string; message: string }) {
@@ -14,10 +18,16 @@ export class ValidationError extends Error {
1418
this.name = 'ValidationError'
1519
}
1620
}
21+
22+
/** This error is thrown when a parse fails on an option value. */
1723
export class ParseError extends Error {
24+
/** The path to the value that failed parsing. */
1825
path: string[]
26+
/** The error code. */
1927
code: string
28+
/** The error message. */
2029
message: string
30+
/** The value that failed parsing. */
2131
received: unknown
2232

2333
constructor({

src/example.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,22 @@ import z from 'zod'
22
import { ValidationError } from './error'
33

44
export const ExampleConfig = z.object({
5+
/** Description of the example. This will appear as a title above the input/output line(s). */
56
description: z.string().optional(),
7+
/**
8+
* Input of the example. This will appear as a line below the description, with a `$` prefix.
9+
* The prefix can be changed using the `help()` function on the command.
10+
*/
611
input: z.string().optional(),
12+
/**
13+
* Output of the example. This will appear as a line below the input, with a `>` prefix.
14+
* The prefix can be changed using the `help()` function on the command.
15+
*/
716
output: z.string().optional(),
817
})
918
export type ExampleConfig = z.infer<typeof ExampleConfig>
1019

11-
export default class MassargExample {
20+
export class MassargExample {
1221
description: string | undefined
1322
input: string | undefined
1423
output: string | undefined
@@ -31,4 +40,3 @@ export default class MassargExample {
3140
this.output = config.output
3241
}
3342
}
34-
export { MassargExample }

0 commit comments

Comments
 (0)