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