cli-forge 1.2.2 → 1.3.0
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/dist/bin/commands/generate-documentation.js +1 -13
- package/dist/bin/commands/generate-documentation.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/internal-cli.d.ts +33 -2
- package/dist/lib/internal-cli.js +90 -4
- package/dist/lib/internal-cli.js.map +1 -1
- package/dist/lib/prompt-types.d.ts +44 -0
- package/dist/lib/prompt-types.js +3 -0
- package/dist/lib/prompt-types.js.map +1 -0
- package/dist/lib/public-api.d.ts +45 -12
- package/dist/lib/public-api.js.map +1 -1
- package/dist/lib/resolve-prompts.d.ts +13 -0
- package/dist/lib/resolve-prompts.js +121 -0
- package/dist/lib/resolve-prompts.js.map +1 -0
- package/dist/lib/test-harness.js +1 -1
- package/dist/lib/test-harness.js.map +1 -1
- package/dist/prompt-providers/clack.d.ts +29 -0
- package/dist/prompt-providers/clack.js +136 -0
- package/dist/prompt-providers/clack.js.map +1 -0
- package/package.json +11 -2
- package/src/bin/commands/generate-documentation.ts +1 -13
- package/src/index.ts +1 -0
- package/src/lib/composable-builder.ts +3 -3
- package/src/lib/internal-cli.spec.ts +300 -0
- package/src/lib/internal-cli.ts +117 -9
- package/src/lib/prompt-types.ts +48 -0
- package/src/lib/public-api.ts +31 -19
- package/src/lib/resolve-prompts.spec.ts +311 -0
- package/src/lib/resolve-prompts.ts +156 -0
- package/src/lib/test-harness.ts +1 -1
- package/src/prompt-providers/clack.spec.ts +376 -0
- package/src/prompt-providers/clack.ts +169 -0
- package/tsconfig.lib.json.tsbuildinfo +1 -1
- package/typedoc.json +10 -0
- package/.eslintrc.json +0 -36
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolvePrompts = resolvePrompts;
|
|
4
|
+
/**
|
|
5
|
+
* Collects options that need prompting, matches them to providers,
|
|
6
|
+
* executes prompts, and returns the prompted values.
|
|
7
|
+
*/
|
|
8
|
+
async function resolvePrompts(opts) {
|
|
9
|
+
const { configuredOptions, configuredImplies, promptConfigs, providers, currentArgs, } = opts;
|
|
10
|
+
// Step 1: Collect promptable options
|
|
11
|
+
const promptableOptions = [];
|
|
12
|
+
for (const [name, config] of Object.entries(configuredOptions)) {
|
|
13
|
+
// Skip internal options
|
|
14
|
+
if (name === 'help' ||
|
|
15
|
+
name === 'version' ||
|
|
16
|
+
name === 'unmatched' ||
|
|
17
|
+
name === '--') {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
// Already has a value — skip unless prompt is explicitly true/string
|
|
21
|
+
const hasValue = currentArgs[name] !== undefined;
|
|
22
|
+
const promptSetting = promptConfigs.get(name);
|
|
23
|
+
let resolved;
|
|
24
|
+
if (typeof promptSetting === 'function') {
|
|
25
|
+
resolved = promptSetting(currentArgs);
|
|
26
|
+
// Callback: null/undefined treated as false
|
|
27
|
+
if (resolved === null || resolved === undefined) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (promptSetting !== undefined) {
|
|
32
|
+
// Static value
|
|
33
|
+
resolved = promptSetting;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Not specified: prompt only if required and missing value
|
|
37
|
+
if (hasValue)
|
|
38
|
+
continue;
|
|
39
|
+
const isRequired = config.required === true;
|
|
40
|
+
const isImplied = isOptionImplied(name, configuredImplies, currentArgs);
|
|
41
|
+
if (!isRequired && !isImplied)
|
|
42
|
+
continue;
|
|
43
|
+
if (providers.length === 0)
|
|
44
|
+
continue; // No providers, let validation handle it
|
|
45
|
+
resolved = true; // Will prompt
|
|
46
|
+
}
|
|
47
|
+
if (resolved === false)
|
|
48
|
+
continue;
|
|
49
|
+
if (hasValue && resolved !== true && typeof resolved !== 'string')
|
|
50
|
+
continue;
|
|
51
|
+
promptableOptions.push({
|
|
52
|
+
name,
|
|
53
|
+
config: {
|
|
54
|
+
...config,
|
|
55
|
+
prompt: resolved === true ? true : resolved ?? undefined,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (promptableOptions.length === 0) {
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
// Step 2: Match options to providers
|
|
63
|
+
const filteredProviders = providers.filter((p) => p.filter);
|
|
64
|
+
const fallbackProviders = providers.filter((p) => !p.filter);
|
|
65
|
+
const providerGroups = new Map();
|
|
66
|
+
const unmatchedOptions = [];
|
|
67
|
+
for (const option of promptableOptions) {
|
|
68
|
+
let matched = false;
|
|
69
|
+
for (const provider of filteredProviders) {
|
|
70
|
+
if (provider.filter(option.name, option.config)) {
|
|
71
|
+
if (!providerGroups.has(provider)) {
|
|
72
|
+
providerGroups.set(provider, []);
|
|
73
|
+
}
|
|
74
|
+
providerGroups.get(provider).push(option);
|
|
75
|
+
matched = true;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!matched) {
|
|
80
|
+
unmatchedOptions.push(option);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Assign unmatched options to first fallback provider
|
|
84
|
+
if (unmatchedOptions.length > 0) {
|
|
85
|
+
if (fallbackProviders.length === 0) {
|
|
86
|
+
const names = unmatchedOptions.map((o) => `'${o.name}'`).join(', ');
|
|
87
|
+
throw new Error(`Option(s) ${names} require prompting but no prompt provider is available`);
|
|
88
|
+
}
|
|
89
|
+
const fallback = fallbackProviders[0];
|
|
90
|
+
if (!providerGroups.has(fallback)) {
|
|
91
|
+
providerGroups.set(fallback, []);
|
|
92
|
+
}
|
|
93
|
+
providerGroups.get(fallback).push(...unmatchedOptions);
|
|
94
|
+
}
|
|
95
|
+
// Step 3: Execute prompts
|
|
96
|
+
const results = {};
|
|
97
|
+
for (const [provider, options] of providerGroups) {
|
|
98
|
+
if (provider.promptBatch) {
|
|
99
|
+
const batchResults = await provider.promptBatch(options);
|
|
100
|
+
Object.assign(results, batchResults);
|
|
101
|
+
}
|
|
102
|
+
else if (provider.prompt) {
|
|
103
|
+
for (const option of options) {
|
|
104
|
+
results[option.name] = await provider.prompt(option);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return results;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check if an option is implied by another option that has been set.
|
|
112
|
+
*/
|
|
113
|
+
function isOptionImplied(name, configuredImplies, currentArgs) {
|
|
114
|
+
for (const [trigger, implied] of Object.entries(configuredImplies)) {
|
|
115
|
+
if (implied.has(name) && currentArgs[trigger] !== undefined) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=resolve-prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-prompts.js","sourceRoot":"","sources":["../../src/lib/resolve-prompts.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/test-harness.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-harness.js","sourceRoot":"","sources":["../../src/lib/test-harness.ts"],"names":[],"mappings":";;;AACA,iDAA6C;AA8B7C;;;GAGG;AACH,MAAa,WAAW;IACd,GAAG,CAAiB;IAE5B,YAAY,GAAW;QACrB,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"test-harness.js","sourceRoot":"","sources":["../../src/lib/test-harness.ts"],"names":[],"mappings":";;;AACA,iDAA6C;AA8B7C;;;GAGG;AACH,MAAa,WAAW;IACd,GAAG,CAAiB;IAE5B,YAAY,GAAW;QACrB,IAAI,0BAAW,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;YACf,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAc;QACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,OAAO;YACL,IAAI,EAAE,IAAI;YACV,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY;SACpC,CAAC;IACJ,CAAC;CACF;AAtBD,kCAsBC;AAED,SAAS,WAAW,CAAC,GAAgB;IACnC,IAAI,GAAG,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC;QAC/B,GAAG,CAAC,aAAa,CAAC,OAAO,GAAG,GAAG,EAAE;YAC/B,6BAA6B;QAC/B,CAAC,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,kBAAkB,EAAE,CAAC;QAC7C,WAAW,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Readable, Writable } from 'node:stream';
|
|
2
|
+
import type { PromptProvider } from '../lib/prompt-types';
|
|
3
|
+
/**
|
|
4
|
+
* Options for {@link createClackPromptProvider}.
|
|
5
|
+
*/
|
|
6
|
+
export interface ClackPromptProviderOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Custom input stream to read from instead of `process.stdin`.
|
|
9
|
+
* Useful for testing — pass a `Readable` with `isTTY = true` and
|
|
10
|
+
* a no-op `setRawMode` to emulate a terminal.
|
|
11
|
+
*/
|
|
12
|
+
input?: Readable;
|
|
13
|
+
/**
|
|
14
|
+
* Custom output stream to write to instead of `process.stdout`.
|
|
15
|
+
*/
|
|
16
|
+
output?: Writable;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a prompt provider backed by @clack/prompts.
|
|
20
|
+
* Requires `@clack/prompts` as a peer dependency.
|
|
21
|
+
*
|
|
22
|
+
* The provider uses dynamic imports so that `@clack/prompts` is only
|
|
23
|
+
* loaded when prompting actually occurs.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createClackPromptProvider(providerOptions?: ClackPromptProviderOptions): PromptProvider;
|
|
26
|
+
/**
|
|
27
|
+
* Default clack prompt provider, uses stdin/stdout
|
|
28
|
+
*/
|
|
29
|
+
export declare const ClackPromptProvider: PromptProvider;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClackPromptProvider = void 0;
|
|
4
|
+
exports.createClackPromptProvider = createClackPromptProvider;
|
|
5
|
+
/**
|
|
6
|
+
* Creates a prompt provider backed by @clack/prompts.
|
|
7
|
+
* Requires `@clack/prompts` as a peer dependency.
|
|
8
|
+
*
|
|
9
|
+
* The provider uses dynamic imports so that `@clack/prompts` is only
|
|
10
|
+
* loaded when prompting actually occurs.
|
|
11
|
+
*/
|
|
12
|
+
function createClackPromptProvider(providerOptions) {
|
|
13
|
+
// Build the common stream options once; spread into every prompt call.
|
|
14
|
+
const streamOpts = {};
|
|
15
|
+
if (providerOptions?.input)
|
|
16
|
+
streamOpts.input = providerOptions.input;
|
|
17
|
+
if (providerOptions?.output)
|
|
18
|
+
streamOpts.output = providerOptions.output;
|
|
19
|
+
return {
|
|
20
|
+
async promptBatch(options) {
|
|
21
|
+
const clack = await import('@clack/prompts');
|
|
22
|
+
const results = {};
|
|
23
|
+
for (const option of options) {
|
|
24
|
+
const message = getLabel(option);
|
|
25
|
+
const defaultValue = getDefault(option.config);
|
|
26
|
+
let value;
|
|
27
|
+
if (option.config.type === 'boolean') {
|
|
28
|
+
value = await clack.confirm({
|
|
29
|
+
...streamOpts,
|
|
30
|
+
message,
|
|
31
|
+
initialValue: typeof defaultValue === 'boolean' ? defaultValue : undefined,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
else if (hasChoices(option.config)) {
|
|
35
|
+
const choices = getChoices(option.config);
|
|
36
|
+
if (option.config.type === 'array') {
|
|
37
|
+
value = await clack.multiselect({
|
|
38
|
+
...streamOpts,
|
|
39
|
+
message,
|
|
40
|
+
options: choices.map((c) => ({ value: c, label: String(c) })),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
value = await clack.select({
|
|
45
|
+
...streamOpts,
|
|
46
|
+
message,
|
|
47
|
+
options: choices.map((c) => ({ value: c, label: String(c) })),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else if (option.config.type === 'number') {
|
|
52
|
+
const raw = await clack.text({
|
|
53
|
+
...streamOpts,
|
|
54
|
+
message,
|
|
55
|
+
placeholder: defaultValue !== undefined ? String(defaultValue) : undefined,
|
|
56
|
+
defaultValue: defaultValue !== undefined ? String(defaultValue) : undefined,
|
|
57
|
+
validate: (val) => {
|
|
58
|
+
if (val && isNaN(Number(val))) {
|
|
59
|
+
return 'Please enter a valid number';
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
if (clack.isCancel(raw)) {
|
|
65
|
+
clack.cancel('Operation cancelled.');
|
|
66
|
+
throw new Error('Prompt cancelled by user');
|
|
67
|
+
}
|
|
68
|
+
value = raw !== undefined && raw !== '' ? Number(raw) : defaultValue;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// string, array without choices
|
|
72
|
+
value = await clack.text({
|
|
73
|
+
...streamOpts,
|
|
74
|
+
message,
|
|
75
|
+
placeholder: defaultValue !== undefined ? String(defaultValue) : undefined,
|
|
76
|
+
defaultValue: defaultValue !== undefined ? String(defaultValue) : undefined,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// clack returns a Symbol when the user cancels (Ctrl+C)
|
|
80
|
+
if (clack.isCancel(value)) {
|
|
81
|
+
clack.cancel('Operation cancelled.');
|
|
82
|
+
throw new Error('Prompt cancelled by user');
|
|
83
|
+
}
|
|
84
|
+
results[option.name] = value;
|
|
85
|
+
}
|
|
86
|
+
return results;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Default clack prompt provider, uses stdin/stdout
|
|
92
|
+
*/
|
|
93
|
+
exports.ClackPromptProvider = createClackPromptProvider();
|
|
94
|
+
/**
|
|
95
|
+
* Determine the label to show for a prompt option.
|
|
96
|
+
* Priority: prompt string > description > option name.
|
|
97
|
+
*/
|
|
98
|
+
function getLabel(option) {
|
|
99
|
+
if (typeof option.config.prompt === 'string') {
|
|
100
|
+
return option.config.prompt;
|
|
101
|
+
}
|
|
102
|
+
return option.config.description ?? option.name;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Extract the default value from an option config.
|
|
106
|
+
* Handles the three forms:
|
|
107
|
+
* - Primitive value directly
|
|
108
|
+
* - `{ value: T; description: string }` object
|
|
109
|
+
* - `{ factory: () => T; description: string }` object
|
|
110
|
+
*/
|
|
111
|
+
function getDefault(config) {
|
|
112
|
+
if (config.default === undefined)
|
|
113
|
+
return undefined;
|
|
114
|
+
if (typeof config.default === 'object' && config.default !== null) {
|
|
115
|
+
if ('factory' in config.default) {
|
|
116
|
+
return config.default.factory();
|
|
117
|
+
}
|
|
118
|
+
if ('value' in config.default) {
|
|
119
|
+
return config.default.value;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return config.default;
|
|
123
|
+
}
|
|
124
|
+
function hasChoices(config) {
|
|
125
|
+
return ('choices' in config &&
|
|
126
|
+
config['choices'] !== undefined);
|
|
127
|
+
}
|
|
128
|
+
function getChoices(config) {
|
|
129
|
+
const cfg = config;
|
|
130
|
+
const choices = cfg['choices'];
|
|
131
|
+
if (typeof choices === 'function') {
|
|
132
|
+
return choices();
|
|
133
|
+
}
|
|
134
|
+
return choices ?? [];
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=clack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clack.js","sourceRoot":"","sources":["../../src/prompt-providers/clack.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cli-forge",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"tslib": "^2.3.0",
|
|
6
|
-
"@cli-forge/parser": "1.
|
|
6
|
+
"@cli-forge/parser": "1.3.0"
|
|
7
7
|
},
|
|
8
8
|
"peerDependencies": {
|
|
9
|
+
"@clack/prompts": "*",
|
|
9
10
|
"markdown-factory": "^0.2.0",
|
|
10
11
|
"tsx": "^4.19.0",
|
|
11
12
|
"zod": "^4.1.13"
|
|
12
13
|
},
|
|
13
14
|
"peerDependenciesMeta": {
|
|
15
|
+
"@clack/prompts": {
|
|
16
|
+
"optional": true
|
|
17
|
+
},
|
|
14
18
|
"markdown-factory": {
|
|
15
19
|
"optional": true,
|
|
16
20
|
"dev": true
|
|
@@ -53,6 +57,11 @@
|
|
|
53
57
|
"require": "./dist/middleware/*.js",
|
|
54
58
|
"types": "./dist/middleware/*.d.ts"
|
|
55
59
|
},
|
|
60
|
+
"./prompt-providers/clack": {
|
|
61
|
+
"require": "./dist/prompt-providers/clack.js",
|
|
62
|
+
"types": "./dist/prompt-providers/clack.d.ts",
|
|
63
|
+
"import": "./dist/prompt-providers/clack.js"
|
|
64
|
+
},
|
|
56
65
|
"./package.json": "./package.json"
|
|
57
66
|
},
|
|
58
67
|
"publishConfig": {
|
|
@@ -386,19 +386,7 @@ async function importMarkdownFactory(): Promise<mdfactory> {
|
|
|
386
386
|
}
|
|
387
387
|
|
|
388
388
|
function isCLI(obj: unknown): obj is InternalCLI {
|
|
389
|
-
|
|
390
|
-
return true;
|
|
391
|
-
}
|
|
392
|
-
if (typeof obj !== 'object' || !obj) {
|
|
393
|
-
return false;
|
|
394
|
-
}
|
|
395
|
-
if (!('constructor' in obj)) {
|
|
396
|
-
return false;
|
|
397
|
-
}
|
|
398
|
-
if (!('name' in obj.constructor)) {
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
401
|
-
return obj.constructor.name === InternalCLI.name;
|
|
389
|
+
return InternalCLI.isInternalCLI(obj);
|
|
402
390
|
}
|
|
403
391
|
|
|
404
392
|
function getExamplesFragment(
|
package/src/index.ts
CHANGED
|
@@ -9,5 +9,6 @@ export type {
|
|
|
9
9
|
ExtractChildren,
|
|
10
10
|
} from './lib/composable-builder';
|
|
11
11
|
export type { ArgumentsOf } from './lib/utils';
|
|
12
|
+
export type { PromptConfig, PromptOptionConfig, PromptOption, PromptProvider } from './lib/prompt-types';
|
|
12
13
|
export { ConfigurationProviders } from './lib/configuration-providers';
|
|
13
14
|
export type { LocalizationDictionary, LocalizationFunction } from '@cli-forge/parser';
|
|
@@ -19,7 +19,7 @@ export type ExtractArgs<T> = T extends CLI<infer A, any, any, any> ? A : never;
|
|
|
19
19
|
*/
|
|
20
20
|
export type ComposableBuilder<
|
|
21
21
|
TArgs2 extends ParsedArgs,
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
23
23
|
TAddedChildren = {}
|
|
24
24
|
> = <TInit extends ParsedArgs, THandlerReturn, TChildren, TParent>(
|
|
25
25
|
init: CLI<TInit, THandlerReturn, TChildren, TParent>
|
|
@@ -39,11 +39,11 @@ export type ComposableBuilder<
|
|
|
39
39
|
*/
|
|
40
40
|
export function makeComposableBuilder<
|
|
41
41
|
TArgs2 extends ParsedArgs,
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
43
43
|
TChildren2 = {}
|
|
44
44
|
>(
|
|
45
45
|
fn: (
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
47
47
|
init: CLI<ParsedArgs, any, {}, any>
|
|
48
48
|
) => CLI<TArgs2, any, TChildren2, any>
|
|
49
49
|
) {
|