@boneskull/bargs 2.0.0 → 3.0.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/README.md +305 -299
- package/dist/bargs.cjs +465 -135
- package/dist/bargs.cjs.map +1 -1
- package/dist/bargs.d.cts +35 -17
- package/dist/bargs.d.cts.map +1 -1
- package/dist/bargs.d.ts +35 -17
- package/dist/bargs.d.ts.map +1 -1
- package/dist/bargs.js +463 -135
- package/dist/bargs.js.map +1 -1
- package/dist/help.cjs +1 -2
- package/dist/help.cjs.map +1 -1
- package/dist/help.d.cts +20 -3
- package/dist/help.d.cts.map +1 -1
- package/dist/help.d.ts +20 -3
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +1 -2
- package/dist/help.js.map +1 -1
- package/dist/index.cjs +27 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -79
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +15 -79
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -30
- package/dist/index.js.map +1 -1
- package/dist/opt.cjs +148 -122
- package/dist/opt.cjs.map +1 -1
- package/dist/opt.d.cts +87 -113
- package/dist/opt.d.cts.map +1 -1
- package/dist/opt.d.ts +87 -113
- package/dist/opt.d.ts.map +1 -1
- package/dist/opt.js +147 -121
- package/dist/opt.js.map +1 -1
- package/dist/parser.cjs +3 -230
- package/dist/parser.cjs.map +1 -1
- package/dist/parser.d.cts +3 -51
- package/dist/parser.d.cts.map +1 -1
- package/dist/parser.d.ts +3 -51
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +2 -223
- package/dist/parser.js.map +1 -1
- package/dist/types.cjs +1 -3
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +111 -233
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +111 -233
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -3
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/dist/validate.cjs +0 -463
- package/dist/validate.cjs.map +0 -1
- package/dist/validate.d.cts +0 -28
- package/dist/validate.d.cts.map +0 -1
- package/dist/validate.d.ts +0 -28
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js +0 -459
- package/dist/validate.js.map +0 -1
package/dist/bargs.js
CHANGED
|
@@ -1,175 +1,503 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Core bargs
|
|
2
|
+
* Core bargs API using parser combinator pattern.
|
|
3
3
|
*
|
|
4
|
-
* Provides `bargs()`
|
|
5
|
-
*
|
|
6
|
-
* `--version` flags, argument parsing, and handler invocation. Supports both
|
|
7
|
-
* simple CLIs with options/positionals and command-based CLIs with
|
|
8
|
-
* subcommands.
|
|
4
|
+
* Provides `bargs.create()` for building CLIs with a fluent API, plus
|
|
5
|
+
* combinator functions like `pipe()`, `map()`, and `handle()`.
|
|
9
6
|
*
|
|
10
7
|
* @packageDocumentation
|
|
11
8
|
*/
|
|
12
|
-
import { HelpError } from "./errors.js";
|
|
9
|
+
import { BargsError, HelpError } from "./errors.js";
|
|
13
10
|
import { generateCommandHelp, generateHelp } from "./help.js";
|
|
14
|
-
import {
|
|
11
|
+
import { parseSimple } from "./parser.js";
|
|
15
12
|
import { defaultTheme, getTheme } from "./theme.js";
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
export function handle(parserOrFn, maybeFn) {
|
|
14
|
+
// Direct form: handle(parser, fn) returns Command
|
|
15
|
+
// Check for Parser first since CallableParser is also a function
|
|
16
|
+
if (isParser(parserOrFn)) {
|
|
17
|
+
const parser = parserOrFn;
|
|
18
|
+
const parserWithTransform = parser;
|
|
19
|
+
const fn = maybeFn;
|
|
20
|
+
const cmd = {
|
|
21
|
+
__brand: 'Command',
|
|
22
|
+
__optionsSchema: parser.__optionsSchema,
|
|
23
|
+
__positionalsSchema: parser.__positionalsSchema,
|
|
24
|
+
handler: fn,
|
|
25
|
+
};
|
|
26
|
+
// Preserve transforms from the parser
|
|
27
|
+
if (parserWithTransform.__transform) {
|
|
28
|
+
cmd.__transform = parserWithTransform.__transform;
|
|
29
|
+
}
|
|
30
|
+
return cmd;
|
|
31
|
+
}
|
|
32
|
+
// Curried form: handle(fn) returns (parser) => Command
|
|
33
|
+
const fn = parserOrFn;
|
|
34
|
+
return (parser) => {
|
|
35
|
+
const parserWithTransform = parser;
|
|
36
|
+
const cmd = {
|
|
37
|
+
__brand: 'Command',
|
|
38
|
+
__optionsSchema: parser.__optionsSchema,
|
|
39
|
+
__positionalsSchema: parser.__positionalsSchema,
|
|
40
|
+
handler: fn,
|
|
41
|
+
};
|
|
42
|
+
// Preserve transforms from the parser
|
|
43
|
+
if (parserWithTransform.__transform) {
|
|
44
|
+
cmd.__transform = parserWithTransform.__transform;
|
|
45
|
+
}
|
|
46
|
+
return cmd;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function map(parserOrFn, maybeFn) {
|
|
50
|
+
// Direct form: map(parser, fn) returns Parser
|
|
51
|
+
// Check for Parser first since CallableParser is also a function
|
|
52
|
+
if (isParser(parserOrFn)) {
|
|
53
|
+
const parser = parserOrFn;
|
|
54
|
+
const fn = maybeFn;
|
|
55
|
+
return {
|
|
56
|
+
...parser,
|
|
57
|
+
__brand: 'Parser',
|
|
58
|
+
__positionals: [],
|
|
59
|
+
__transform: fn,
|
|
60
|
+
__values: {},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Curried form: map(fn) returns (parser) => Parser
|
|
64
|
+
const fn = parserOrFn;
|
|
65
|
+
return (parser) => {
|
|
66
|
+
return {
|
|
67
|
+
...parser,
|
|
68
|
+
__brand: 'Parser',
|
|
69
|
+
__positionals: [],
|
|
70
|
+
__transform: fn,
|
|
71
|
+
__values: {},
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function merge(...parsers) {
|
|
76
|
+
if (parsers.length === 0) {
|
|
77
|
+
throw new BargsError('merge() requires at least one parser');
|
|
27
78
|
}
|
|
28
|
-
|
|
29
|
-
|
|
79
|
+
// Start with the first parser and fold the rest in
|
|
80
|
+
let result = parsers[0];
|
|
81
|
+
for (let i = 1; i < parsers.length; i++) {
|
|
82
|
+
const next = parsers[i];
|
|
83
|
+
// Merge options schemas
|
|
84
|
+
const mergedOptions = {
|
|
85
|
+
...result.__optionsSchema,
|
|
86
|
+
...next.__optionsSchema,
|
|
87
|
+
};
|
|
88
|
+
// Merge positionals schemas
|
|
89
|
+
const mergedPositionals = [
|
|
90
|
+
...result.__positionalsSchema,
|
|
91
|
+
...next.__positionalsSchema,
|
|
92
|
+
];
|
|
93
|
+
const resultWithTransform = result;
|
|
94
|
+
const nextWithTransform = next;
|
|
95
|
+
let mergedTransform;
|
|
96
|
+
if (resultWithTransform.__transform && nextWithTransform.__transform) {
|
|
97
|
+
// Chain transforms
|
|
98
|
+
const t1 = resultWithTransform.__transform;
|
|
99
|
+
const t2 = nextWithTransform.__transform;
|
|
100
|
+
mergedTransform = (r) => {
|
|
101
|
+
const r1 = t1(r);
|
|
102
|
+
if (r1 instanceof Promise) {
|
|
103
|
+
return r1.then(t2);
|
|
104
|
+
}
|
|
105
|
+
return t2(r1);
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
mergedTransform =
|
|
110
|
+
nextWithTransform.__transform ?? resultWithTransform.__transform;
|
|
111
|
+
}
|
|
112
|
+
result = {
|
|
113
|
+
__brand: 'Parser',
|
|
114
|
+
__optionsSchema: mergedOptions,
|
|
115
|
+
__positionals: [],
|
|
116
|
+
__positionalsSchema: mergedPositionals,
|
|
117
|
+
__values: {},
|
|
118
|
+
};
|
|
119
|
+
if (mergedTransform) {
|
|
120
|
+
result.__transform =
|
|
121
|
+
mergedTransform;
|
|
122
|
+
}
|
|
30
123
|
}
|
|
31
|
-
|
|
32
|
-
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
127
|
+
// CLI BUILDER
|
|
128
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
129
|
+
/**
|
|
130
|
+
* Create a new CLI.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
*
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const cli = await bargs
|
|
136
|
+
* .create('my-app', { version: '1.0.0' })
|
|
137
|
+
* .globals(
|
|
138
|
+
* map(opt.options({ verbose: opt.boolean() }), ({ values }) => ({
|
|
139
|
+
* values: { ...values, ts: Date.now() },
|
|
140
|
+
* positionals: [] as const,
|
|
141
|
+
* })),
|
|
142
|
+
* )
|
|
143
|
+
* .command(
|
|
144
|
+
* 'greet',
|
|
145
|
+
* pos.positionals(pos.string({ name: 'name', required: true })),
|
|
146
|
+
* ({ positionals }) => console.log(`Hello, ${positionals[0]}!`),
|
|
147
|
+
* )
|
|
148
|
+
* .parseAsync();
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
const create = (name, options = {}) => {
|
|
152
|
+
const theme = options.theme ? getTheme(options.theme) : defaultTheme;
|
|
153
|
+
return createCliBuilder({
|
|
154
|
+
commands: new Map(),
|
|
155
|
+
name,
|
|
156
|
+
options,
|
|
157
|
+
theme,
|
|
158
|
+
});
|
|
33
159
|
};
|
|
34
160
|
/**
|
|
35
|
-
* Check if
|
|
161
|
+
* Check if something is a Command (has __brand: 'Command').
|
|
36
162
|
*/
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
163
|
+
const isCommand = (x) => {
|
|
164
|
+
if (x === null || x === undefined) {
|
|
39
165
|
return false;
|
|
40
166
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
// Check if any option has 'V' as an alias
|
|
45
|
-
return Object.values(options).some((opt) => opt.aliases?.includes('V'));
|
|
167
|
+
const obj = x;
|
|
168
|
+
return '__brand' in obj && obj.__brand === 'Command';
|
|
46
169
|
};
|
|
47
170
|
/**
|
|
48
|
-
*
|
|
171
|
+
* Create a CLI builder.
|
|
49
172
|
*/
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
173
|
+
const createCliBuilder = (state) => {
|
|
174
|
+
return {
|
|
175
|
+
// Overloaded command(): accepts either (name, Command, desc?) or (name, Parser, handler, desc?)
|
|
176
|
+
command(name, cmdOrParser, handlerOrDesc, maybeDesc) {
|
|
177
|
+
let cmd;
|
|
178
|
+
let description;
|
|
179
|
+
if (isCommand(cmdOrParser)) {
|
|
180
|
+
// Form 1: command(name, Command, description?)
|
|
181
|
+
cmd = cmdOrParser;
|
|
182
|
+
description = handlerOrDesc;
|
|
183
|
+
}
|
|
184
|
+
else if (isParser(cmdOrParser)) {
|
|
185
|
+
// Form 2: command(name, Parser, handler, description?)
|
|
186
|
+
const parser = cmdOrParser;
|
|
187
|
+
const handler = handlerOrDesc;
|
|
188
|
+
description = maybeDesc;
|
|
189
|
+
// Create Command from Parser + handler
|
|
190
|
+
const parserWithTransform = parser;
|
|
191
|
+
const newCmd = {
|
|
192
|
+
__brand: 'Command',
|
|
193
|
+
__optionsSchema: parser.__optionsSchema,
|
|
194
|
+
__positionalsSchema: parser.__positionalsSchema,
|
|
195
|
+
handler,
|
|
196
|
+
};
|
|
197
|
+
// Preserve transforms from the parser
|
|
198
|
+
if (parserWithTransform.__transform) {
|
|
199
|
+
newCmd.__transform = parserWithTransform.__transform;
|
|
200
|
+
}
|
|
201
|
+
cmd = newCmd;
|
|
61
202
|
}
|
|
62
203
|
else {
|
|
63
|
-
|
|
204
|
+
throw new Error('command() requires a Command or Parser as second argument');
|
|
205
|
+
}
|
|
206
|
+
state.commands.set(name, { cmd, description });
|
|
207
|
+
return this;
|
|
208
|
+
},
|
|
209
|
+
// Overloaded defaultCommand(): accepts name, Command, or (Parser, handler)
|
|
210
|
+
defaultCommand(nameOrCmdOrParser, maybeHandler) {
|
|
211
|
+
// Form 1: defaultCommand(name) - just set the name
|
|
212
|
+
if (typeof nameOrCmdOrParser === 'string') {
|
|
213
|
+
return createCliBuilder({
|
|
214
|
+
...state,
|
|
215
|
+
defaultCommandName: nameOrCmdOrParser,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
// Generate a unique name for the default command
|
|
219
|
+
const defaultName = '__default__';
|
|
220
|
+
if (isCommand(nameOrCmdOrParser)) {
|
|
221
|
+
// Form 2: defaultCommand(Command)
|
|
222
|
+
state.commands.set(defaultName, {
|
|
223
|
+
cmd: nameOrCmdOrParser,
|
|
224
|
+
description: undefined,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
else if (isParser(nameOrCmdOrParser)) {
|
|
228
|
+
// Form 3: defaultCommand(Parser, handler)
|
|
229
|
+
const parser = nameOrCmdOrParser;
|
|
230
|
+
const handler = maybeHandler;
|
|
231
|
+
const parserWithTransform = parser;
|
|
232
|
+
const newCmd = {
|
|
233
|
+
__brand: 'Command',
|
|
234
|
+
__optionsSchema: parser.__optionsSchema,
|
|
235
|
+
__positionalsSchema: parser.__positionalsSchema,
|
|
236
|
+
handler,
|
|
237
|
+
};
|
|
238
|
+
// Preserve transforms from the parser
|
|
239
|
+
if (parserWithTransform.__transform) {
|
|
240
|
+
newCmd.__transform = parserWithTransform.__transform;
|
|
241
|
+
}
|
|
242
|
+
state.commands.set(defaultName, {
|
|
243
|
+
cmd: newCmd,
|
|
244
|
+
description: undefined,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
throw new Error('defaultCommand() requires a name, Command, or Parser');
|
|
249
|
+
}
|
|
250
|
+
return createCliBuilder({
|
|
251
|
+
...state,
|
|
252
|
+
defaultCommandName: defaultName,
|
|
253
|
+
});
|
|
254
|
+
},
|
|
255
|
+
globals(parser) {
|
|
256
|
+
return createCliBuilder({
|
|
257
|
+
...state,
|
|
258
|
+
globalParser: parser,
|
|
259
|
+
});
|
|
260
|
+
},
|
|
261
|
+
parse(args = process.argv.slice(2)) {
|
|
262
|
+
const result = parseCore(state, args, false);
|
|
263
|
+
if (result instanceof Promise) {
|
|
264
|
+
throw new BargsError('Async transform or handler detected. Use parseAsync() instead of parse().');
|
|
265
|
+
}
|
|
266
|
+
return result;
|
|
267
|
+
},
|
|
268
|
+
async parseAsync(args = process.argv.slice(2)) {
|
|
269
|
+
return parseCore(state, args, true);
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
* Core parse logic shared between parse() and parseAsync().
|
|
275
|
+
*/
|
|
276
|
+
const parseCore = (state, args, allowAsync) => {
|
|
277
|
+
const { commands, options, theme } = state;
|
|
278
|
+
// Handle --help
|
|
279
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
280
|
+
// Check for command-specific help
|
|
281
|
+
const helpIndex = args.findIndex((a) => a === '--help' || a === '-h');
|
|
282
|
+
const commandIndex = args.findIndex((a) => !a.startsWith('-'));
|
|
283
|
+
if (commandIndex >= 0 && commandIndex < helpIndex && commands.size > 0) {
|
|
284
|
+
const commandName = args[commandIndex];
|
|
285
|
+
if (commands.has(commandName)) {
|
|
286
|
+
console.log(generateCommandHelpNew(state, commandName, theme));
|
|
287
|
+
process.exit(0);
|
|
64
288
|
}
|
|
65
289
|
}
|
|
66
|
-
|
|
67
|
-
console.log(generateHelp(config, theme));
|
|
68
|
-
}
|
|
290
|
+
console.log(generateHelpNew(state, theme));
|
|
69
291
|
process.exit(0);
|
|
70
292
|
}
|
|
71
|
-
// Handle --version
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
console.log(config.version);
|
|
293
|
+
// Handle --version
|
|
294
|
+
if (args.includes('--version') && options.version) {
|
|
295
|
+
console.log(options.version);
|
|
75
296
|
process.exit(0);
|
|
76
297
|
}
|
|
77
|
-
|
|
298
|
+
// If we have commands, dispatch to the appropriate one
|
|
299
|
+
if (commands.size > 0) {
|
|
300
|
+
return runWithCommands(state, args, allowAsync);
|
|
301
|
+
}
|
|
302
|
+
// Simple CLI (no commands)
|
|
303
|
+
return runSimple(state, args, allowAsync);
|
|
78
304
|
};
|
|
79
305
|
/**
|
|
80
|
-
*
|
|
306
|
+
* Generate command-specific help.
|
|
81
307
|
*/
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
console.log(generateHelp(config, theme));
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
console.log(generateHelp(config, theme));
|
|
90
|
-
}
|
|
91
|
-
process.exit(1);
|
|
308
|
+
const generateCommandHelpNew = (state, commandName, theme) => {
|
|
309
|
+
const commandEntry = state.commands.get(commandName);
|
|
310
|
+
if (!commandEntry) {
|
|
311
|
+
return `Unknown command: ${commandName}`;
|
|
92
312
|
}
|
|
93
|
-
|
|
313
|
+
// TODO: Implement proper command help generation
|
|
314
|
+
const config = {
|
|
315
|
+
commands: {
|
|
316
|
+
[commandName]: {
|
|
317
|
+
description: commandEntry.description ?? '',
|
|
318
|
+
options: commandEntry.cmd.__optionsSchema,
|
|
319
|
+
positionals: commandEntry.cmd.__positionalsSchema,
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
name: state.name,
|
|
323
|
+
};
|
|
324
|
+
return generateCommandHelp(config, commandName, theme);
|
|
94
325
|
};
|
|
95
326
|
/**
|
|
96
|
-
*
|
|
97
|
-
* handler returns a thenable.
|
|
327
|
+
* Generate help for the new CLI structure.
|
|
98
328
|
*/
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
? runSyncTransforms(transforms, parsed.values, parsed.positionals)
|
|
122
|
-
: { positionals: parsed.positionals, values: parsed.values };
|
|
123
|
-
const result = {
|
|
124
|
-
command: undefined,
|
|
125
|
-
positionals: transformed.positionals,
|
|
126
|
-
values: transformed.values,
|
|
127
|
-
};
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
return handleHelpError(error, config, theme);
|
|
329
|
+
const generateHelpNew = (state, theme) => {
|
|
330
|
+
// TODO: Implement proper help generation for new structure
|
|
331
|
+
// For now, delegate to existing help generator with minimal config
|
|
332
|
+
const config = {
|
|
333
|
+
commands: Object.fromEntries(Array.from(state.commands.entries()).map(([name, { description }]) => [
|
|
334
|
+
name,
|
|
335
|
+
{ description: description ?? '' },
|
|
336
|
+
])),
|
|
337
|
+
description: state.options.description,
|
|
338
|
+
name: state.name,
|
|
339
|
+
options: state.globalParser?.__optionsSchema,
|
|
340
|
+
version: state.options.version,
|
|
341
|
+
};
|
|
342
|
+
return generateHelp(config, theme);
|
|
343
|
+
};
|
|
344
|
+
/**
|
|
345
|
+
* Check if something is a Parser (has __brand: 'Parser'). Parsers can be either
|
|
346
|
+
* objects or functions (CallableParser).
|
|
347
|
+
*/
|
|
348
|
+
const isParser = (x) => {
|
|
349
|
+
if (x === null || x === undefined) {
|
|
350
|
+
return false;
|
|
133
351
|
}
|
|
134
|
-
|
|
352
|
+
// Handle both plain objects and functions with Parser properties
|
|
353
|
+
const obj = x;
|
|
354
|
+
return '__brand' in obj && obj.__brand === 'Parser';
|
|
355
|
+
};
|
|
135
356
|
/**
|
|
136
|
-
*
|
|
137
|
-
* supporting async handlers.
|
|
357
|
+
* Run a simple CLI (no commands).
|
|
138
358
|
*/
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
: { positionals: parsed.positionals, values: parsed.values };
|
|
163
|
-
const result = {
|
|
359
|
+
const runSimple = (state, args, allowAsync) => {
|
|
360
|
+
const { globalParser } = state;
|
|
361
|
+
const optionsSchema = globalParser?.__optionsSchema ?? {};
|
|
362
|
+
const positionalsSchema = globalParser?.__positionalsSchema ?? [];
|
|
363
|
+
const parsed = parseSimple({
|
|
364
|
+
args,
|
|
365
|
+
options: optionsSchema,
|
|
366
|
+
positionals: positionalsSchema,
|
|
367
|
+
});
|
|
368
|
+
let result = {
|
|
369
|
+
positionals: parsed.positionals,
|
|
370
|
+
values: parsed.values,
|
|
371
|
+
};
|
|
372
|
+
// Apply transforms if any
|
|
373
|
+
const transform = globalParser?.__transform;
|
|
374
|
+
if (transform) {
|
|
375
|
+
const transformed = transform(result);
|
|
376
|
+
if (transformed instanceof Promise) {
|
|
377
|
+
if (!allowAsync) {
|
|
378
|
+
throw new BargsError('Async transform detected. Use parseAsync() instead of parse().');
|
|
379
|
+
}
|
|
380
|
+
return transformed.then((r) => ({
|
|
381
|
+
...r,
|
|
164
382
|
command: undefined,
|
|
165
|
-
|
|
166
|
-
values: transformed.values,
|
|
167
|
-
};
|
|
168
|
-
return result;
|
|
383
|
+
}));
|
|
169
384
|
}
|
|
385
|
+
result = transformed;
|
|
386
|
+
}
|
|
387
|
+
return { ...result, command: undefined };
|
|
388
|
+
};
|
|
389
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
390
|
+
// PUBLIC API
|
|
391
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
392
|
+
/**
|
|
393
|
+
* Run a CLI with commands.
|
|
394
|
+
*/
|
|
395
|
+
const runWithCommands = (state, args, allowAsync) => {
|
|
396
|
+
const { commands, defaultCommandName, globalParser } = state;
|
|
397
|
+
// Find command name (first non-flag argument)
|
|
398
|
+
const commandIndex = args.findIndex((arg) => !arg.startsWith('-'));
|
|
399
|
+
const potentialCommandName = commandIndex >= 0 ? args[commandIndex] : undefined;
|
|
400
|
+
// Check if it's a known command
|
|
401
|
+
let commandName;
|
|
402
|
+
let remainingArgs;
|
|
403
|
+
if (potentialCommandName && commands.has(potentialCommandName)) {
|
|
404
|
+
// It's a known command - remove it from args
|
|
405
|
+
commandName = potentialCommandName;
|
|
406
|
+
remainingArgs = [
|
|
407
|
+
...args.slice(0, commandIndex),
|
|
408
|
+
...args.slice(commandIndex + 1),
|
|
409
|
+
];
|
|
170
410
|
}
|
|
171
|
-
|
|
172
|
-
|
|
411
|
+
else if (defaultCommandName) {
|
|
412
|
+
// Not a known command, but we have a default - use all args as positionals/options
|
|
413
|
+
commandName = defaultCommandName;
|
|
414
|
+
remainingArgs = args;
|
|
173
415
|
}
|
|
174
|
-
|
|
416
|
+
else if (potentialCommandName) {
|
|
417
|
+
// Not a known command and no default
|
|
418
|
+
throw new HelpError(`Unknown command: ${potentialCommandName}`);
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
// No command and no default
|
|
422
|
+
throw new HelpError('No command specified.');
|
|
423
|
+
}
|
|
424
|
+
const commandEntry = commands.get(commandName);
|
|
425
|
+
if (!commandEntry) {
|
|
426
|
+
throw new HelpError(`Unknown command: ${commandName}`);
|
|
427
|
+
}
|
|
428
|
+
const { cmd } = commandEntry;
|
|
429
|
+
// Merge global and command options schemas
|
|
430
|
+
const globalOptionsSchema = globalParser?.__optionsSchema ?? {};
|
|
431
|
+
const commandOptionsSchema = cmd.__optionsSchema;
|
|
432
|
+
const mergedOptionsSchema = {
|
|
433
|
+
...globalOptionsSchema,
|
|
434
|
+
...commandOptionsSchema,
|
|
435
|
+
};
|
|
436
|
+
const commandPositionalsSchema = cmd.__positionalsSchema;
|
|
437
|
+
// Parse with merged schema
|
|
438
|
+
const parsed = parseSimple({
|
|
439
|
+
args: remainingArgs,
|
|
440
|
+
options: mergedOptionsSchema,
|
|
441
|
+
positionals: commandPositionalsSchema,
|
|
442
|
+
});
|
|
443
|
+
let result = {
|
|
444
|
+
positionals: parsed.positionals,
|
|
445
|
+
values: parsed.values,
|
|
446
|
+
};
|
|
447
|
+
// Helper to check for async and throw if not allowed
|
|
448
|
+
const checkAsync = (value, context) => {
|
|
449
|
+
if (value instanceof Promise && !allowAsync) {
|
|
450
|
+
throw new BargsError(`Async ${context} detected. Use parseAsync() instead of parse().`);
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
// Get transforms
|
|
454
|
+
const globalTransform = globalParser?.__transform;
|
|
455
|
+
const commandTransform = cmd?.__transform;
|
|
456
|
+
// Apply transforms and run handler
|
|
457
|
+
const applyTransformsAndHandle = () => {
|
|
458
|
+
// Apply global transforms first
|
|
459
|
+
if (globalTransform) {
|
|
460
|
+
const transformed = globalTransform(result);
|
|
461
|
+
checkAsync(transformed, 'global transform');
|
|
462
|
+
if (transformed instanceof Promise) {
|
|
463
|
+
return transformed.then((r) => {
|
|
464
|
+
result = r;
|
|
465
|
+
return continueWithCommandTransform();
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
result = transformed;
|
|
469
|
+
}
|
|
470
|
+
return continueWithCommandTransform();
|
|
471
|
+
};
|
|
472
|
+
const continueWithCommandTransform = () => {
|
|
473
|
+
// Apply command transforms
|
|
474
|
+
if (commandTransform) {
|
|
475
|
+
const transformed = commandTransform(result);
|
|
476
|
+
checkAsync(transformed, 'command transform');
|
|
477
|
+
if (transformed instanceof Promise) {
|
|
478
|
+
return transformed.then((r) => {
|
|
479
|
+
result = r;
|
|
480
|
+
return runHandler();
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
result = transformed;
|
|
484
|
+
}
|
|
485
|
+
return runHandler();
|
|
486
|
+
};
|
|
487
|
+
const runHandler = () => {
|
|
488
|
+
const handlerResult = cmd.handler(result);
|
|
489
|
+
checkAsync(handlerResult, 'handler');
|
|
490
|
+
if (handlerResult instanceof Promise) {
|
|
491
|
+
return handlerResult.then(() => ({ ...result, command: commandName }));
|
|
492
|
+
}
|
|
493
|
+
return { ...result, command: commandName };
|
|
494
|
+
};
|
|
495
|
+
return applyTransformsAndHandle();
|
|
496
|
+
};
|
|
497
|
+
/**
|
|
498
|
+
* Main bargs namespace.
|
|
499
|
+
*/
|
|
500
|
+
export const bargs = {
|
|
501
|
+
create,
|
|
502
|
+
};
|
|
175
503
|
//# sourceMappingURL=bargs.js.map
|