Skip to content

Commit 4e593aa

Browse files
committed
feat: [Command] example, examples
Signed-off-by: Lexus Drumgold <[email protected]>
1 parent 2e03da9 commit 4e593aa

File tree

14 files changed

+360
-0
lines changed

14 files changed

+360
-0
lines changed

README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
- [`Command#done([done])`](#commanddonedone)
5151
- [`Command#emit(event)`](#commandemitevent)
5252
- [`Command#emitOption(option, value, source[, flags])`](#commandemitoptionoption-value-source-flag)
53+
- [`Command#example(info[, prefix])`](#commandexampleinfo-prefix)
54+
- [`Command#examples([examples])`](#commandexamplesexamples)
5355
- [`Command#error(info)`](#commanderrorinfo)
5456
- [`Command#exit([e])`](#commandexite)
5557
- [`Command#exiter([exit])`](#commandexiterexit)
@@ -149,6 +151,8 @@
149151
- [`CommandSnapshot`](#commandsnapshot-1)
150152
- [`DefaultInfo`](#defaultinfo)
151153
- [`EmptyString`](#emptystring)
154+
- [`ExampleInfo`](#exampleinfo)
155+
- [`ExamplesData`](#examplesdata)
152156
- [`ExitCode`](#exitcode)
153157
- [`ExitProcess`](#exitprocess)
154158
- [`Exit`](#exit)
@@ -729,6 +733,46 @@ Display an error message and exit.
729733

730734
(`never`) Never, exits erroneously
731735

736+
#### `Command#example(info[, prefix])`
737+
738+
Add an example for the command.
739+
740+
> 👉 **Note**: This method can be called more than once to add multiple examples.
741+
742+
##### Overloads
743+
744+
- `example(info: ExampleInfo | string): this`
745+
- `example(info: string, prefix?: string | null | undefined): this`
746+
747+
##### Parameters
748+
749+
- `info` ([`ExampleInfo`](#exampleinfo) | `string`)
750+
— example info or text
751+
- `prefix` (`string` | `null` | `undefined`)
752+
— the example text prefix
753+
754+
##### Returns
755+
756+
([`this`](#commandinfo)) `this` command
757+
758+
#### `Command#examples([examples])`
759+
760+
Get or add examples for the command.
761+
762+
##### Overloads
763+
764+
- `examples(examples: ExamplesData | null | undefined): this`
765+
- `examples(): ExampleInfo[]`
766+
767+
##### Parameters
768+
769+
- `examples` ([`ExamplesData`](#examplesdata) | `null` | `undefined`)
770+
— example info, example text, or a list of such
771+
772+
##### Returns
773+
774+
([`ExampleInfo[]`](#exampleinfo) | [`this`](#commandinfo)) List of examples or `this` command
775+
732776
#### `Command#exit([e])`
733777

734778
Exit the process.
@@ -2029,6 +2073,8 @@ Command metadata (TypeScript interface).
20292073
— list of command aliases
20302074
- `arguments` ([`Argument[]`](#argumentinfo))
20312075
— list of command arguments
2076+
- `examples` ([`ExampleInfo[]`](#exampleinfo))
2077+
— list of command examples
20322078
- `helpOption` ([`Option`](#optioninfo) | `null` | `undefined`)
20332079
— the help option
20342080
- `options` ([`Map<string, Option>`](#optioninfo))
@@ -2097,6 +2143,25 @@ An empty string (TypeScript type).
20972143
type EmptyString = ''
20982144
```
20992145
2146+
### `ExampleInfo`
2147+
2148+
Command example info (TypeScript interface).
2149+
2150+
#### Properties
2151+
2152+
- `prefix?` (`string`, optional)
2153+
— the example text prefix
2154+
- `text` (`string`)
2155+
— the example text
2156+
2157+
### `ExamplesData`
2158+
2159+
Union of types used to configure command examples (TypeScript type).
2160+
2161+
```ts
2162+
type ExamplesData = ExampleInfo | List<ExampleInfo | string> | string
2163+
```
2164+
21002165
### `ExitCode`
21012166
21022167
Union of exit status code types (TypeScript type).

src/interfaces/__tests__/command.data.spec-d.mts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
Action,
99
ArgumentsData,
1010
Command,
11+
ExamplesData,
1112
Exit,
1213
HelpableInfo,
1314
HelpOptionData,
@@ -60,6 +61,12 @@ describe('unit-d:interfaces/CommandData', () => {
6061
.toEqualTypeOf<Nilable<Action<any>>>()
6162
})
6263

64+
it('should match [examples?: ExamplesData | null | undefined]', () => {
65+
expectTypeOf<TestSubject>()
66+
.toHaveProperty('examples')
67+
.toEqualTypeOf<Nilable<ExamplesData>>()
68+
})
69+
6370
it('should match [exit?: Exit | null | undefined]', () => {
6471
expectTypeOf<TestSubject>()
6572
.toHaveProperty('exit')

src/interfaces/__tests__/command.metadata.spec-d.mts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
Argument,
1212
Command,
1313
CommandInfo,
14+
ExampleInfo,
1415
Option,
1516
VersionOption
1617
} from '@flex-development/kronk'
@@ -37,6 +38,12 @@ describe('unit-d:interfaces/CommandMetadata', () => {
3738
.toEqualTypeOf<Argument[]>()
3839
})
3940

41+
it('should match [examples: ExampleInfo[]]', () => {
42+
expectTypeOf<TestSubject>()
43+
.toHaveProperty('examples')
44+
.toEqualTypeOf<ExampleInfo[]>()
45+
})
46+
4047
it('should match [helpCommand: Command | null | undefined]', () => {
4148
expectTypeOf<TestSubject>()
4249
.toHaveProperty('helpCommand')
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @file Type Tests - ExampleInfo
3+
* @module kronk/interfaces/tests/unit-d/ExampleInfo
4+
*/
5+
6+
import type TestSubject from '#interfaces/example.info'
7+
import type { Nilable } from '@flex-development/tutils'
8+
9+
describe('unit-d:interfaces/ExampleInfo', () => {
10+
it('should match [prefix?: string | null | undefined]', () => {
11+
expectTypeOf<TestSubject>()
12+
.toHaveProperty('prefix')
13+
.toEqualTypeOf<Nilable<string>>()
14+
})
15+
16+
it('should match [text: string]', () => {
17+
expectTypeOf<TestSubject>()
18+
.toHaveProperty('text')
19+
.toEqualTypeOf<string>()
20+
})
21+
})

src/interfaces/command.data.mts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
Action,
88
ArgumentsData,
99
Command,
10+
ExamplesData,
1011
Exit,
1112
HelpableInfo,
1213
HelpCommandData,
@@ -61,6 +62,13 @@ interface CommandData extends HelpableInfo {
6162
*/
6263
done?: Action<any> | null | undefined
6364

65+
/**
66+
* An example of the command, or a list of examples.
67+
*
68+
* @see {@linkcode ExamplesData}
69+
*/
70+
examples?: ExamplesData | null | undefined
71+
6472
/**
6573
* The callback to fire when the process is exited.
6674
*

src/interfaces/command.metadata.mts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
Argument,
88
Command,
99
CommandInfo,
10+
ExampleInfo,
1011
Option,
1112
VersionOption
1213
} from '@flex-development/kronk'
@@ -38,6 +39,15 @@ interface CommandMetadata extends Omit<CommandInfo, Skip> {
3839
*/
3940
arguments: Argument[]
4041

42+
/**
43+
* A list of command examples.
44+
*
45+
* @see {@linkcode ExampleInfo}
46+
*
47+
* @override
48+
*/
49+
examples: ExampleInfo[]
50+
4151
/**
4252
* The help subcommand.
4353
*

src/interfaces/example.info.mts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @file Interfaces - ExampleInfo
3+
* @module kronk/interfaces/ExampleInfo
4+
*/
5+
6+
/**
7+
* Command example info.
8+
*/
9+
interface ExampleInfo {
10+
/**
11+
* The example {@linkcode text} prefix.
12+
*/
13+
prefix?: string | null | undefined
14+
15+
/**
16+
* The example text.
17+
*/
18+
text: string
19+
}
20+
21+
export type { ExampleInfo as default }

src/interfaces/index.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export type { default as CommandInfo } from '#interfaces/command.info'
2121
export type { default as CommandMetadata } from '#interfaces/command.metadata'
2222
export type { default as CommandSnapshot } from '#interfaces/command.snapshot'
2323
export type { default as DefaultInfo } from '#interfaces/default.info'
24+
export type { default as ExampleInfo } from '#interfaces/example.info'
2425
export type { default as HelpableInfo } from '#interfaces/helpable.info'
2526
export type { default as KronkErrorCause } from '#interfaces/kronk-error.cause'
2627
export type { default as KronkErrorInfo } from '#interfaces/kronk-error.info'

src/lib/__snapshots__/command.snap

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ exports[`unit:lib/Command > #addOption > should throw on short flag conflict 1`]
5858
}
5959
`;
6060

61+
exports[`unit:lib/Command > #examples > should add examples and return \`this\` 1`] = `
62+
[
63+
{
64+
"prefix": undefined,
65+
"text": "bump -w 1.0.0",
66+
},
67+
{
68+
"prefix": "ch",
69+
"text": "--releases=0 --to=$(jq .version package.json -r) -sw",
70+
},
71+
]
72+
`;
73+
6174
exports[`unit:lib/Command > #helpCommand > should return help subcommand (0) 1`] = `
6275
Command {
6376
"info": {
@@ -67,6 +80,7 @@ Command {
6780
"hidden": false,
6881
"aliases": Set {},
6982
"arguments": [],
83+
"examples": [],
7084
"helpOption": Option {
7185
"info": {
7286
"description": "show help",
@@ -156,6 +170,7 @@ Command {
156170
"hidden": false,
157171
"aliases": Set {},
158172
"arguments": [],
173+
"examples": [],
159174
"helpCommand": [Circular],
160175
"helpOption": Option {
161176
"info": {

src/lib/__tests__/command.spec.mts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {
2424
Action,
2525
CommandInfo,
2626
CommandName,
27+
ExampleInfo,
2728
Exit,
2829
HelpCommandData,
2930
HelpOptionData,
@@ -313,6 +314,57 @@ describe('unit:lib/Command', () => {
313314
})
314315
})
315316

317+
describe('#example', () => {
318+
let subject: TestSubject
319+
320+
beforeEach(() => {
321+
subject = new TestSubject()
322+
})
323+
324+
it.each<[ExampleInfo | string, (string | null | undefined)?]>([
325+
['--to=0ea3bcf737edf29d0a0ad3dc7702f29615e16b29', 'ch'],
326+
[{ text: '-s' }]
327+
])('should add example and return `this` (%#)', (info, prefix) => {
328+
// Arrange
329+
const property: string = 'info.examples'
330+
331+
// Act
332+
const result = subject.example(info as never, prefix)
333+
334+
// Expect
335+
expect(result).to.eq(subject)
336+
expect(result).to.have.nested.property(property).satisfy(Array.isArray)
337+
expect(result).to.have.nested.property(property).be.of.length(1)
338+
})
339+
})
340+
341+
describe('#examples', () => {
342+
let subject: TestSubject
343+
344+
beforeEach(() => {
345+
subject = new TestSubject()
346+
})
347+
348+
it('should add examples and return `this`', () => {
349+
// Act
350+
const result = subject.examples([
351+
'bump -w 1.0.0',
352+
{
353+
prefix: 'ch',
354+
text: '--releases=0 --to=$(jq .version package.json -r) -sw'
355+
}
356+
])
357+
358+
// Expect
359+
expect(result).to.eq(subject)
360+
expect(subject.examples()).toMatchSnapshot()
361+
})
362+
363+
it('should return list of command examples', () => {
364+
expect(subject.examples()).to.satisfy(Array.isArray).and.be.empty
365+
})
366+
})
367+
316368
describe('#error', () => {
317369
let exit: MockInstance<TestSubject['exit']>
318370
let info: KronkError

0 commit comments

Comments
 (0)