@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.
Files changed (58) hide show
  1. package/README.md +305 -299
  2. package/dist/bargs.cjs +465 -135
  3. package/dist/bargs.cjs.map +1 -1
  4. package/dist/bargs.d.cts +35 -17
  5. package/dist/bargs.d.cts.map +1 -1
  6. package/dist/bargs.d.ts +35 -17
  7. package/dist/bargs.d.ts.map +1 -1
  8. package/dist/bargs.js +463 -135
  9. package/dist/bargs.js.map +1 -1
  10. package/dist/help.cjs +1 -2
  11. package/dist/help.cjs.map +1 -1
  12. package/dist/help.d.cts +20 -3
  13. package/dist/help.d.cts.map +1 -1
  14. package/dist/help.d.ts +20 -3
  15. package/dist/help.d.ts.map +1 -1
  16. package/dist/help.js +1 -2
  17. package/dist/help.js.map +1 -1
  18. package/dist/index.cjs +27 -31
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +15 -79
  21. package/dist/index.d.cts.map +1 -1
  22. package/dist/index.d.ts +15 -79
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +20 -30
  25. package/dist/index.js.map +1 -1
  26. package/dist/opt.cjs +148 -122
  27. package/dist/opt.cjs.map +1 -1
  28. package/dist/opt.d.cts +87 -113
  29. package/dist/opt.d.cts.map +1 -1
  30. package/dist/opt.d.ts +87 -113
  31. package/dist/opt.d.ts.map +1 -1
  32. package/dist/opt.js +147 -121
  33. package/dist/opt.js.map +1 -1
  34. package/dist/parser.cjs +3 -230
  35. package/dist/parser.cjs.map +1 -1
  36. package/dist/parser.d.cts +3 -51
  37. package/dist/parser.d.cts.map +1 -1
  38. package/dist/parser.d.ts +3 -51
  39. package/dist/parser.d.ts.map +1 -1
  40. package/dist/parser.js +2 -223
  41. package/dist/parser.js.map +1 -1
  42. package/dist/types.cjs +1 -3
  43. package/dist/types.cjs.map +1 -1
  44. package/dist/types.d.cts +111 -233
  45. package/dist/types.d.cts.map +1 -1
  46. package/dist/types.d.ts +111 -233
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/types.js +1 -3
  49. package/dist/types.js.map +1 -1
  50. package/package.json +2 -2
  51. package/dist/validate.cjs +0 -463
  52. package/dist/validate.cjs.map +0 -1
  53. package/dist/validate.d.cts +0 -28
  54. package/dist/validate.d.cts.map +0 -1
  55. package/dist/validate.d.ts +0 -28
  56. package/dist/validate.d.ts.map +0 -1
  57. package/dist/validate.js +0 -459
  58. package/dist/validate.js.map +0 -1
package/dist/bargs.js CHANGED
@@ -1,175 +1,503 @@
1
1
  /**
2
- * Core bargs parsing functions for both sync and async CLI execution.
2
+ * Core bargs API using parser combinator pattern.
3
3
  *
4
- * Provides `bargs()` (synchronous) and `bargsAsync()` (asynchronous) entry
5
- * points that handle configuration validation, built-in `--help` and
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 { parseCommandsAsync, parseCommandsSync, parseSimple, runSyncTransforms, runTransforms, } from "./parser.js";
11
+ import { parseSimple } from "./parser.js";
15
12
  import { defaultTheme, getTheme } from "./theme.js";
16
- import { validateConfig } from "./validate.js";
17
- /**
18
- * Check if config has commands.
19
- */
20
- const hasCommands = (config) => config.commands !== undefined && Object.keys(config.commands).length > 0;
21
- /**
22
- * Check if user defined their own help option (by name or alias).
23
- */
24
- const hasUserDefinedHelp = (options) => {
25
- if (!options) {
26
- return false;
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
- if ('help' in options) {
29
- return true;
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
- // Check if any option has 'h' as an alias
32
- return Object.values(options).some((opt) => opt.aliases?.includes('h'));
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 user defined their own version option (by name or alias).
161
+ * Check if something is a Command (has __brand: 'Command').
36
162
  */
37
- const hasUserDefinedVersion = (options) => {
38
- if (!options) {
163
+ const isCommand = (x) => {
164
+ if (x === null || x === undefined) {
39
165
  return false;
40
166
  }
41
- if ('version' in options) {
42
- return true;
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
- * Handle help and version flags. Returns true if we should exit.
171
+ * Create a CLI builder.
49
172
  */
50
- const handleBuiltinFlags = (config, args, theme = defaultTheme) => {
51
- // Handle --help (unless user defined their own help option)
52
- const userDefinedHelp = hasUserDefinedHelp(config.options);
53
- if (!userDefinedHelp && (args.includes('--help') || args.includes('-h'))) {
54
- if (hasCommands(config)) {
55
- // Check for command-specific help: cmd --help
56
- const helpIndex = args.findIndex((a) => a === '--help' || a === '-h');
57
- const commandIndex = args.findIndex((a) => !a.startsWith('-'));
58
- if (commandIndex >= 0 && commandIndex < helpIndex) {
59
- const commandName = args[commandIndex];
60
- console.log(generateCommandHelp(config, commandName, theme));
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
- console.log(generateHelp(config, theme));
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
- else {
67
- console.log(generateHelp(config, theme));
68
- }
290
+ console.log(generateHelpNew(state, theme));
69
291
  process.exit(0);
70
292
  }
71
- // Handle --version (unless user defined their own version option)
72
- const userDefinedVersion = hasUserDefinedVersion(config.options);
73
- if (!userDefinedVersion && args.includes('--version') && config.version) {
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
- return false;
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
- * Handle HelpError by printing message and help text.
306
+ * Generate command-specific help.
81
307
  */
82
- const handleHelpError = (error, config, theme = defaultTheme) => {
83
- if (error instanceof HelpError) {
84
- console.error(error.message);
85
- if (hasCommands(config)) {
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
- throw error;
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
- * Main bargs entry point (sync implementation). Throws BargsError if any
97
- * handler returns a thenable.
327
+ * Generate help for the new CLI structure.
98
328
  */
99
- export function bargs(config, options) {
100
- // Validate config upfront (throws ValidationError if invalid)
101
- validateConfig(config);
102
- const args = config.args ?? process.argv.slice(2);
103
- const theme = options?.theme
104
- ? getTheme(options.theme)
105
- : getTheme('default');
106
- try {
107
- handleBuiltinFlags(config, args, theme);
108
- // Parse
109
- if (hasCommands(config)) {
110
- return parseCommandsSync({ ...config, args });
111
- }
112
- else {
113
- const parsed = parseSimple({
114
- args,
115
- options: config.options,
116
- positionals: config.positionals,
117
- });
118
- // Run transforms if present (type-erased in implementation)
119
- const transforms = config.transforms;
120
- const transformed = transforms
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
- * Main bargs entry point (async implementation). Awaits all handlers,
137
- * supporting async handlers.
357
+ * Run a simple CLI (no commands).
138
358
  */
139
- export async function bargsAsync(config, options) {
140
- // Validate config upfront (throws ValidationError if invalid)
141
- validateConfig(config);
142
- const args = config.args ?? process.argv.slice(2);
143
- const theme = options?.theme
144
- ? getTheme(options.theme)
145
- : getTheme('default');
146
- try {
147
- handleBuiltinFlags(config, args, theme);
148
- // Parse
149
- if (hasCommands(config)) {
150
- return await parseCommandsAsync({ ...config, args });
151
- }
152
- else {
153
- const parsed = parseSimple({
154
- args,
155
- options: config.options,
156
- positionals: config.positionals,
157
- });
158
- // Run transforms if present (type-erased in implementation)
159
- const transforms = config.transforms;
160
- const transformed = transforms
161
- ? await runTransforms(transforms, parsed.values, parsed.positionals)
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
- positionals: transformed.positionals,
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
- catch (error) {
172
- return handleHelpError(error, config, theme);
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