cli-forge 0.12.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +1 -0
- package/dist/lib/internal-cli.d.ts +10 -10
- package/dist/lib/internal-cli.js +101 -4
- package/dist/lib/internal-cli.js.map +1 -1
- package/dist/lib/public-api.d.ts +92 -11
- package/dist/lib/public-api.js.map +1 -1
- package/package.json +7 -3
- package/src/lib/documentation.spec.ts +1 -0
- package/src/lib/internal-cli.spec.ts +6 -5
- package/src/lib/internal-cli.ts +140 -21
- package/src/lib/public-api.ts +140 -41
- package/src/lib/sdk.spec.ts +285 -0
- package/src/lib/test-harness.spec.ts +1 -0
- package/src/lib/utils.spec.ts +1 -0
- package/tsconfig.lib.json.tsbuildinfo +1 -1
package/src/lib/internal-cli.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
CLIHandlerContext,
|
|
18
18
|
Command,
|
|
19
19
|
ErrorHandler,
|
|
20
|
+
SDKCommand,
|
|
20
21
|
} from './public-api';
|
|
21
22
|
import { readOptionGroupsForCLI } from './cli-option-groups';
|
|
22
23
|
import { formatHelp } from './format-help';
|
|
@@ -170,22 +171,19 @@ export class InternalCLI<
|
|
|
170
171
|
return this;
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
command<TCommandArgs extends TArgs>(
|
|
174
|
-
cmd: Command<TArgs, TCommandArgs>
|
|
174
|
+
command<TCommandArgs extends TArgs, TCmdName extends string>(
|
|
175
|
+
cmd: Command<TArgs, TCommandArgs, TCmdName>
|
|
175
176
|
): CLI<
|
|
176
177
|
TArgs,
|
|
177
178
|
THandlerReturn,
|
|
178
|
-
TChildren &
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
>;
|
|
187
|
-
}
|
|
188
|
-
: {}),
|
|
179
|
+
TChildren & {
|
|
180
|
+
[key in TCmdName]: CLI<
|
|
181
|
+
TCommandArgs,
|
|
182
|
+
void,
|
|
183
|
+
{},
|
|
184
|
+
CLI<TArgs, THandlerReturn, TChildren, TParent>
|
|
185
|
+
>;
|
|
186
|
+
},
|
|
189
187
|
TParent
|
|
190
188
|
>;
|
|
191
189
|
command<
|
|
@@ -308,7 +306,7 @@ export class InternalCLI<
|
|
|
308
306
|
|
|
309
307
|
option<
|
|
310
308
|
TOption extends string,
|
|
311
|
-
const TOptionConfig extends OptionConfig<any, any, any
|
|
309
|
+
const TOptionConfig extends OptionConfig<any, any, any>
|
|
312
310
|
>(name: TOption, config: TOptionConfig) {
|
|
313
311
|
this.parser.option(name, config);
|
|
314
312
|
// Interface modifies the return type to reflect new params, cast is necessay.... I think 🤔
|
|
@@ -317,7 +315,7 @@ export class InternalCLI<
|
|
|
317
315
|
|
|
318
316
|
positional<
|
|
319
317
|
TOption extends string,
|
|
320
|
-
const TOptionConfig extends OptionConfig<any, any, any
|
|
318
|
+
const TOptionConfig extends OptionConfig<any, any, any>
|
|
321
319
|
>(name: TOption, config: TOptionConfig) {
|
|
322
320
|
this.parser.positional(name, config);
|
|
323
321
|
// Interface modifies the return type to reflect new params, cast is necessay.... I think 🤔
|
|
@@ -497,13 +495,15 @@ export class InternalCLI<
|
|
|
497
495
|
return this._parent as TParent;
|
|
498
496
|
}
|
|
499
497
|
|
|
500
|
-
getBuilder
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
| ((parser: CLI<T, any, any>) => CLI<TArgs, THandlerReturn, TChildren>)
|
|
498
|
+
getBuilder():
|
|
499
|
+
| (<TInit extends ParsedArgs, TInitHandlerReturn, TInitChildren, TInitParent>(
|
|
500
|
+
parser: CLI<TInit, TInitHandlerReturn, TInitChildren, TInitParent>
|
|
501
|
+
) => CLI<TInit & TArgs, TInitHandlerReturn, TInitChildren & TChildren, TInitParent>)
|
|
505
502
|
| undefined {
|
|
506
|
-
|
|
503
|
+
const builder = this.configuration?.builder;
|
|
504
|
+
if (!builder) return undefined;
|
|
505
|
+
// Return a composable builder that preserves input types
|
|
506
|
+
return ((parser: CLI<any, any, any, any>) => builder(parser)) as any;
|
|
507
507
|
}
|
|
508
508
|
|
|
509
509
|
getHandler():
|
|
@@ -523,6 +523,125 @@ export class InternalCLI<
|
|
|
523
523
|
) as THandlerReturn;
|
|
524
524
|
}
|
|
525
525
|
|
|
526
|
+
sdk(): SDKCommand<TArgs, THandlerReturn, TChildren> {
|
|
527
|
+
return this.buildSDKProxy(this) as SDKCommand<
|
|
528
|
+
TArgs,
|
|
529
|
+
THandlerReturn,
|
|
530
|
+
TChildren
|
|
531
|
+
>;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
private buildSDKProxy(targetCmd: InternalCLI<any, any, any, any>): unknown {
|
|
535
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
536
|
+
const self = this;
|
|
537
|
+
|
|
538
|
+
const invoke = async (
|
|
539
|
+
argsOrArgv?: Record<string, unknown> | string[]
|
|
540
|
+
): Promise<THandlerReturn & { $args?: TArgs }> => {
|
|
541
|
+
// Clone the target command to avoid mutating the original
|
|
542
|
+
const cmd = targetCmd.clone();
|
|
543
|
+
|
|
544
|
+
const handler = cmd._configuration?.handler;
|
|
545
|
+
if (!handler) {
|
|
546
|
+
throw new Error(`Command '${cmd.name}' has no handler`);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
let parsedArgs: any;
|
|
550
|
+
|
|
551
|
+
if (Array.isArray(argsOrArgv)) {
|
|
552
|
+
// String array: full pipeline (parse → validate → middleware)
|
|
553
|
+
// Run the builder first if present
|
|
554
|
+
if (cmd._configuration?.builder) {
|
|
555
|
+
cmd._configuration.builder(cmd as any);
|
|
556
|
+
}
|
|
557
|
+
parsedArgs = cmd.parser.parse(argsOrArgv);
|
|
558
|
+
} else {
|
|
559
|
+
// Object args: skip validation, apply defaults, run middleware
|
|
560
|
+
// Run the builder first to register options and get defaults
|
|
561
|
+
if (cmd._configuration?.builder) {
|
|
562
|
+
cmd._configuration.builder(cmd as any);
|
|
563
|
+
}
|
|
564
|
+
// Build defaults from configured options
|
|
565
|
+
const defaults: Record<string, unknown> = {};
|
|
566
|
+
for (const [key, config] of Object.entries(
|
|
567
|
+
cmd.parser.configuredOptions
|
|
568
|
+
)) {
|
|
569
|
+
if (config.default !== undefined) {
|
|
570
|
+
defaults[key] = config.default;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
parsedArgs = {
|
|
574
|
+
...defaults,
|
|
575
|
+
...argsOrArgv,
|
|
576
|
+
unmatched: [],
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// Collect and run middleware from the command chain
|
|
581
|
+
const middlewares = self.collectMiddlewareChain(targetCmd);
|
|
582
|
+
for (const mw of middlewares) {
|
|
583
|
+
const middlewareResult = await mw(parsedArgs);
|
|
584
|
+
if (
|
|
585
|
+
middlewareResult !== void 0 &&
|
|
586
|
+
typeof middlewareResult === 'object'
|
|
587
|
+
) {
|
|
588
|
+
parsedArgs = middlewareResult;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Execute handler
|
|
593
|
+
const context: CLIHandlerContext<any, any> = {
|
|
594
|
+
command: cmd as unknown as CLI<any, any, any, any>,
|
|
595
|
+
};
|
|
596
|
+
const result = await handler(parsedArgs, context);
|
|
597
|
+
|
|
598
|
+
// Try to attach $args to the result (fails silently for primitives)
|
|
599
|
+
if (result !== null && typeof result === 'object') {
|
|
600
|
+
try {
|
|
601
|
+
(result as any).$args = parsedArgs;
|
|
602
|
+
} catch {
|
|
603
|
+
// Cannot attach to frozen objects or primitives, return as-is
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return result as any as THandlerReturn & { $args?: TArgs };
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// Ensure builder has run to register all subcommands
|
|
611
|
+
if (targetCmd._configuration?.builder) {
|
|
612
|
+
targetCmd._configuration.builder(targetCmd as any);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Create proxy that is both callable and has child properties
|
|
616
|
+
return new Proxy(invoke, {
|
|
617
|
+
get(_, prop: string) {
|
|
618
|
+
// Handle special properties
|
|
619
|
+
if (prop === 'then' || prop === 'catch' || prop === 'finally') {
|
|
620
|
+
// Don't intercept Promise methods - this prevents issues with await
|
|
621
|
+
return undefined;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
const child = targetCmd.registeredCommands[prop];
|
|
625
|
+
if (child) {
|
|
626
|
+
return self.buildSDKProxy(child);
|
|
627
|
+
}
|
|
628
|
+
return undefined;
|
|
629
|
+
},
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
private collectMiddlewareChain(
|
|
634
|
+
cmd: InternalCLI<any, any, any, any>
|
|
635
|
+
): Array<(args: any) => unknown | Promise<unknown>> {
|
|
636
|
+
const chain: InternalCLI<any, any, any, any>[] = [];
|
|
637
|
+
let current: InternalCLI<any, any, any, any> | undefined = cmd;
|
|
638
|
+
while (current) {
|
|
639
|
+
chain.unshift(current);
|
|
640
|
+
current = current._parent;
|
|
641
|
+
}
|
|
642
|
+
return chain.flatMap((c) => c.registeredMiddleware);
|
|
643
|
+
}
|
|
644
|
+
|
|
526
645
|
enableInteractiveShell(): CLI<TArgs, THandlerReturn, TChildren, TParent> {
|
|
527
646
|
if (this.requiresCommand === 'EXPLICIT') {
|
|
528
647
|
throw new Error(
|
package/src/lib/public-api.ts
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
ResolveProperties,
|
|
14
14
|
WithOptional,
|
|
15
15
|
MakeUndefinedPropertiesOptional,
|
|
16
|
-
WithAdditionalProperties,
|
|
17
16
|
} from '@cli-forge/parser';
|
|
18
17
|
|
|
19
18
|
import { InternalCLI } from './internal-cli';
|
|
@@ -90,22 +89,19 @@ export interface CLI<
|
|
|
90
89
|
TChildren = {},
|
|
91
90
|
TParent = undefined
|
|
92
91
|
> {
|
|
93
|
-
command<TCommandArgs extends TArgs>(
|
|
94
|
-
cmd: Command<TArgs, TCommandArgs>
|
|
92
|
+
command<TCommandArgs extends TArgs, TCmdName extends string>(
|
|
93
|
+
cmd: Command<TArgs, TCommandArgs, TCmdName>
|
|
95
94
|
): CLI<
|
|
96
95
|
TArgs,
|
|
97
96
|
THandlerReturn,
|
|
98
|
-
TChildren &
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
>;
|
|
107
|
-
}
|
|
108
|
-
: {}),
|
|
97
|
+
TChildren & {
|
|
98
|
+
[key in TCmdName]: CLI<
|
|
99
|
+
TCommandArgs,
|
|
100
|
+
void,
|
|
101
|
+
{},
|
|
102
|
+
CLI<TArgs, THandlerReturn, TChildren, TParent>
|
|
103
|
+
>;
|
|
104
|
+
},
|
|
109
105
|
TParent
|
|
110
106
|
>;
|
|
111
107
|
|
|
@@ -127,7 +123,7 @@ export interface CLI<
|
|
|
127
123
|
TArgs,
|
|
128
124
|
TCommandArgs,
|
|
129
125
|
TChildHandlerReturn,
|
|
130
|
-
|
|
126
|
+
TChildren,
|
|
131
127
|
CLI<TArgs, THandlerReturn, TChildren, TParent>,
|
|
132
128
|
TChildChildren
|
|
133
129
|
>
|
|
@@ -436,22 +432,16 @@ export interface CLI<
|
|
|
436
432
|
option<
|
|
437
433
|
TOption extends string,
|
|
438
434
|
TCoerce,
|
|
439
|
-
const TProps extends Record<string, { type: string }
|
|
440
|
-
TAdditionalProps extends false | 'string' | 'number' | 'boolean' = false
|
|
435
|
+
const TProps extends Record<string, { type: string }>
|
|
441
436
|
>(
|
|
442
437
|
name: TOption,
|
|
443
|
-
config: ObjectOptionConfig<TCoerce, TProps
|
|
438
|
+
config: ObjectOptionConfig<TCoerce, TProps>
|
|
444
439
|
): CLI<
|
|
445
440
|
TArgs &
|
|
446
441
|
MakeUndefinedPropertiesOptional<{
|
|
447
442
|
[key in TOption]: WithOptional<
|
|
448
|
-
unknown extends TCoerce
|
|
449
|
-
|
|
450
|
-
ResolveProperties<TProps>,
|
|
451
|
-
TAdditionalProps
|
|
452
|
-
>
|
|
453
|
-
: TCoerce,
|
|
454
|
-
ObjectOptionConfig<TCoerce, TProps, TAdditionalProps>
|
|
443
|
+
unknown extends TCoerce ? ResolveProperties<TProps> : TCoerce,
|
|
444
|
+
ObjectOptionConfig<TCoerce, TProps>
|
|
455
445
|
>;
|
|
456
446
|
}>,
|
|
457
447
|
THandlerReturn,
|
|
@@ -525,7 +515,7 @@ export interface CLI<
|
|
|
525
515
|
// Generic fallback overload
|
|
526
516
|
option<
|
|
527
517
|
TOption extends string,
|
|
528
|
-
const TOptionConfig extends OptionConfig<any, any, any
|
|
518
|
+
const TOptionConfig extends OptionConfig<any, any, any>
|
|
529
519
|
>(
|
|
530
520
|
name: TOption,
|
|
531
521
|
config: TOptionConfig
|
|
@@ -552,22 +542,16 @@ export interface CLI<
|
|
|
552
542
|
positional<
|
|
553
543
|
TOption extends string,
|
|
554
544
|
TCoerce,
|
|
555
|
-
const TProps extends Record<string, { type: string }
|
|
556
|
-
TAdditionalProps extends false | 'string' | 'number' | 'boolean' = false
|
|
545
|
+
const TProps extends Record<string, { type: string }>
|
|
557
546
|
>(
|
|
558
547
|
name: TOption,
|
|
559
|
-
config: ObjectOptionConfig<TCoerce, TProps
|
|
548
|
+
config: ObjectOptionConfig<TCoerce, TProps>
|
|
560
549
|
): CLI<
|
|
561
550
|
TArgs &
|
|
562
551
|
MakeUndefinedPropertiesOptional<{
|
|
563
552
|
[key in TOption]: WithOptional<
|
|
564
|
-
unknown extends TCoerce
|
|
565
|
-
|
|
566
|
-
ResolveProperties<TProps>,
|
|
567
|
-
TAdditionalProps
|
|
568
|
-
>
|
|
569
|
-
: TCoerce,
|
|
570
|
-
ObjectOptionConfig<TCoerce, TProps, TAdditionalProps>
|
|
553
|
+
unknown extends TCoerce ? ResolveProperties<TProps> : TCoerce,
|
|
554
|
+
ObjectOptionConfig<TCoerce, TProps>
|
|
571
555
|
>;
|
|
572
556
|
}>,
|
|
573
557
|
THandlerReturn,
|
|
@@ -641,7 +625,7 @@ export interface CLI<
|
|
|
641
625
|
// Generic fallback overload
|
|
642
626
|
positional<
|
|
643
627
|
TOption extends string,
|
|
644
|
-
const TOptionConfig extends OptionConfig<any, any, any
|
|
628
|
+
const TOptionConfig extends OptionConfig<any, any, any>
|
|
645
629
|
>(
|
|
646
630
|
name: TOption,
|
|
647
631
|
config: TOptionConfig
|
|
@@ -778,10 +762,64 @@ export interface CLI<
|
|
|
778
762
|
*/
|
|
779
763
|
getParent(): TParent;
|
|
780
764
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
765
|
+
/**
|
|
766
|
+
* Returns a programmatic SDK for invoking this CLI and its subcommands.
|
|
767
|
+
* The SDK provides typed function calls instead of argv parsing.
|
|
768
|
+
*
|
|
769
|
+
* @example
|
|
770
|
+
* ```ts
|
|
771
|
+
* const myCLI = cli('my-app')
|
|
772
|
+
* .option('verbose', { type: 'boolean' })
|
|
773
|
+
* .command('build', {
|
|
774
|
+
* builder: (cmd) => cmd.option('watch', { type: 'boolean' }),
|
|
775
|
+
* handler: (args) => ({ success: true, files: ['a.js'] })
|
|
776
|
+
* });
|
|
777
|
+
*
|
|
778
|
+
* const sdk = myCLI.sdk();
|
|
779
|
+
*
|
|
780
|
+
* // Invoke root command (if it has a handler)
|
|
781
|
+
* await sdk({ verbose: true });
|
|
782
|
+
*
|
|
783
|
+
* // Invoke subcommand with typed args
|
|
784
|
+
* const result = await sdk.build({ watch: true });
|
|
785
|
+
* console.log(result.files); // ['a.js']
|
|
786
|
+
* console.log(result.$args.watch); // true
|
|
787
|
+
*
|
|
788
|
+
* // Use CLI-style args for -- support
|
|
789
|
+
* await sdk.build(['--watch', '--', 'extra-arg']);
|
|
790
|
+
* ```
|
|
791
|
+
*
|
|
792
|
+
* @returns An SDK object that is callable (if this command has a handler)
|
|
793
|
+
* and has properties for each subcommand.
|
|
794
|
+
*/
|
|
795
|
+
sdk(): SDKCommand<TArgs, THandlerReturn, TChildren>;
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Returns the builder function for this command as a composable builder.
|
|
799
|
+
* The returned function can be used with `chain` to compose multiple builders.
|
|
800
|
+
*
|
|
801
|
+
* @example
|
|
802
|
+
* ```ts
|
|
803
|
+
* const siblings = args.getParent().getChildren();
|
|
804
|
+
* const withBuildArgs = siblings.build.getBuilder()!;
|
|
805
|
+
* const withServeArgs = siblings.serve.getBuilder()!;
|
|
806
|
+
* return chain(args, withBuildArgs, withServeArgs);
|
|
807
|
+
* ```
|
|
808
|
+
*/
|
|
809
|
+
getBuilder():
|
|
810
|
+
| (<
|
|
811
|
+
TInit extends ParsedArgs,
|
|
812
|
+
TInitHandlerReturn,
|
|
813
|
+
TInitChildren,
|
|
814
|
+
TInitParent
|
|
815
|
+
>(
|
|
816
|
+
parser: CLI<TInit, TInitHandlerReturn, TInitChildren, TInitParent>
|
|
817
|
+
) => CLI<
|
|
818
|
+
TInit & TArgs,
|
|
819
|
+
TInitHandlerReturn,
|
|
820
|
+
TInitChildren & TChildren,
|
|
821
|
+
TInitParent
|
|
822
|
+
>)
|
|
785
823
|
| undefined;
|
|
786
824
|
getHandler():
|
|
787
825
|
| ((args: Omit<TArgs, keyof ParsedArgs>) => THandlerReturn)
|
|
@@ -910,6 +948,67 @@ export type MiddlewareFunction<TArgs extends ParsedArgs, TArgs2> = (
|
|
|
910
948
|
args: TArgs
|
|
911
949
|
) => TArgs2 | Promise<TArgs2>;
|
|
912
950
|
|
|
951
|
+
// ============================================================================
|
|
952
|
+
// SDK Types
|
|
953
|
+
// ============================================================================
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* Result type that conditionally includes $args.
|
|
957
|
+
* Only attaches $args when result is an object type.
|
|
958
|
+
* Uses `Awaited<T>` to handle async handlers that return `Promise<U>`.
|
|
959
|
+
*/
|
|
960
|
+
export type SDKResult<TArgs, THandlerReturn> =
|
|
961
|
+
Awaited<THandlerReturn> extends object
|
|
962
|
+
? Awaited<THandlerReturn> & { $args: TArgs }
|
|
963
|
+
: Awaited<THandlerReturn>;
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* The callable signature for a command with a handler.
|
|
967
|
+
* Supports both object-style args (typed, skips validation) and
|
|
968
|
+
* string array args (CLI-style, full validation pipeline).
|
|
969
|
+
*/
|
|
970
|
+
export type SDKInvokable<TArgs, THandlerReturn> = {
|
|
971
|
+
/**
|
|
972
|
+
* Invoke the command with typed object args.
|
|
973
|
+
* Skips validation (TypeScript handles it), applies defaults, runs middleware.
|
|
974
|
+
*/
|
|
975
|
+
(args?: Partial<Omit<TArgs, 'unmatched' | '--'>>): Promise<
|
|
976
|
+
SDKResult<TArgs, THandlerReturn>
|
|
977
|
+
>;
|
|
978
|
+
/**
|
|
979
|
+
* Invoke the command with CLI-style string args.
|
|
980
|
+
* Runs full pipeline: parse → validate → middleware → handler.
|
|
981
|
+
* Use this when you need to pass `--` extra args.
|
|
982
|
+
*/
|
|
983
|
+
(args: string[]): Promise<SDKResult<TArgs, THandlerReturn>>;
|
|
984
|
+
};
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Recursively builds SDK type from TChildren.
|
|
988
|
+
* Each child command becomes a property on the SDK object.
|
|
989
|
+
*/
|
|
990
|
+
export type SDKChildren<TChildren> = {
|
|
991
|
+
[K in keyof TChildren]: TChildren[K] extends CLI<
|
|
992
|
+
infer A,
|
|
993
|
+
infer R,
|
|
994
|
+
infer C,
|
|
995
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
996
|
+
infer _P
|
|
997
|
+
>
|
|
998
|
+
? SDKCommand<A, R, C>
|
|
999
|
+
: never;
|
|
1000
|
+
};
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* A single SDK command - callable if it has a handler, with nested children as properties.
|
|
1004
|
+
* Container commands (no handler) are not callable but still provide access to children.
|
|
1005
|
+
*/
|
|
1006
|
+
export type SDKCommand<TArgs, THandlerReturn, TChildren> =
|
|
1007
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
1008
|
+
// THandlerReturn extends void | undefined
|
|
1009
|
+
// ? SDKChildren<TChildren> // No handler = just children (not callable)
|
|
1010
|
+
SDKInvokable<TArgs, THandlerReturn> & SDKChildren<TChildren>;
|
|
1011
|
+
|
|
913
1012
|
/**
|
|
914
1013
|
* Constructs a CLI instance. See {@link CLI} for more information.
|
|
915
1014
|
* @param name Name for the top level CLI
|