@optique/core 1.3.0-dev.2513 → 1.3.0-dev.2519

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/facade.cjs CHANGED
@@ -516,10 +516,14 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
516
516
  function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, termWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = []) {
517
517
  const shellName = completionArgs[0] || "";
518
518
  const args = completionArgs.slice(1);
519
- const callOnError = (code) => onError(code);
519
+ const callOnError = (code, error) => onError(code, error);
520
520
  const callOnCompletion = (code) => onCompletion(code);
521
521
  if (!shellName) {
522
- stderr("Error: Missing shell name for completion.\n");
522
+ const error = require_message.message`Missing shell name for completion.`;
523
+ stderr(`Error: ${require_message.formatMessage(error, {
524
+ colors,
525
+ quotes: !colors
526
+ })}\n`);
523
527
  if (completionParser) {
524
528
  const displayName = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
525
529
  const doc = require_internal_parser.getDocPage(completionParser, [displayName]);
@@ -532,10 +536,10 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
532
536
  }));
533
537
  }
534
538
  return require_mode_dispatch.dispatchByMode(parser.mode, () => {
535
- const result = callOnError(1);
539
+ const result = callOnError(1, error);
536
540
  if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
537
541
  return result;
538
- }, async () => callOnError(1));
542
+ }, async () => callOnError(1, error));
539
543
  }
540
544
  const shell = availableShells[shellName];
541
545
  if (!shell) {
@@ -544,15 +548,16 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
544
548
  if (available.length > 0) available.push(require_message.text(", "));
545
549
  available.push(require_message.value(name));
546
550
  }
547
- stderr(require_message.formatMessage(require_message.message`Error: Unsupported shell ${shellName}. Available shells: ${available}.`, {
551
+ const error = require_message.message`Unsupported shell ${shellName}. Available shells: ${available}.`;
552
+ stderr(`Error: ${require_message.formatMessage(error, {
548
553
  colors,
549
554
  quotes: !colors
550
- }));
555
+ })}`);
551
556
  return require_mode_dispatch.dispatchByMode(parser.mode, () => {
552
- const result = callOnError(1);
557
+ const result = callOnError(1, error);
553
558
  if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
554
559
  return result;
555
- }, async () => callOnError(1));
560
+ }, async () => callOnError(1, error));
556
561
  }
557
562
  if (args.length === 0) {
558
563
  const completionArg = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
@@ -870,7 +875,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
870
875
  const completionOptionConfig = norm(options.completion?.option);
871
876
  const onCompletion = options.completion?.onShow ?? (() => ({}));
872
877
  const onCompletionResult = (code) => onCompletion(code);
873
- const onErrorResult = (code) => onError(code);
878
+ const onErrorResult = (code, error) => onError(code, error);
874
879
  if (helpOptionConfig?.names) require_validate.validateOptionNames(helpOptionConfig.names, "Help option");
875
880
  if (helpCommandConfig?.names) require_validate.validateCommandNames(helpCommandConfig.names, "Help command");
876
881
  if (versionOptionConfig?.names) require_validate.validateOptionNames(versionOptionConfig.names, "Version option");
@@ -1022,7 +1027,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1022
1027
  quotes: !colors
1023
1028
  });
1024
1029
  stderr(`Error: ${errorMessage}`);
1025
- return onError(1);
1030
+ return onError(1, validationError);
1026
1031
  };
1027
1032
  const displayHelp = (doc) => {
1028
1033
  if (doc != null) {
@@ -1133,7 +1138,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1133
1138
  quotes: !colors
1134
1139
  });
1135
1140
  stderr(`Error: ${errorMessage}`);
1136
- return onError(1);
1141
+ return onError(1, classified.error);
1137
1142
  };
1138
1143
  if (aboveError === "help") {
1139
1144
  const parserForDoc = args.length < 1 ? augmentedParser : parser;
package/dist/facade.d.cts CHANGED
@@ -240,14 +240,21 @@ interface RunOptions<THelp, TError> {
240
240
  */
241
241
  readonly aboveError?: "usage" | "help" | "none";
242
242
  /**
243
- * Callback function invoked when parsing fails. The function can
244
- * optionally receive an exit code parameter.
243
+ * Callback invoked after error output for a parse failure, an invalid
244
+ * command path before help, or a missing or unsupported completion shell.
245
+ * Receives the exit code and the structured error message used for output.
246
+ * The message does not include the runner's `Error: ` prefix or usage/help
247
+ * output. The runner preserves any formatting terms in the original message.
248
+ *
249
+ * Handlers may ignore either argument. Wrappers that invoke this callback
250
+ * themselves must forward both the exit code and the message.
245
251
  *
246
252
  * You usually want to pass `process.exit` on Node.js or Bun and `Deno.exit`
247
253
  * on Deno to this option.
248
254
  * @default Throws a {@link RunParserError}.
255
+ * @since 1.3.0 Added the `error` parameter.
249
256
  */
250
- readonly onError?: (() => TError) | ((exitCode: number) => TError);
257
+ readonly onError?: (exitCode: number, error: Message) => TError;
251
258
  /**
252
259
  * Function used to output error messages. Assumes it prints the ending
253
260
  * newline.
package/dist/facade.d.ts CHANGED
@@ -240,14 +240,21 @@ interface RunOptions<THelp, TError> {
240
240
  */
241
241
  readonly aboveError?: "usage" | "help" | "none";
242
242
  /**
243
- * Callback function invoked when parsing fails. The function can
244
- * optionally receive an exit code parameter.
243
+ * Callback invoked after error output for a parse failure, an invalid
244
+ * command path before help, or a missing or unsupported completion shell.
245
+ * Receives the exit code and the structured error message used for output.
246
+ * The message does not include the runner's `Error: ` prefix or usage/help
247
+ * output. The runner preserves any formatting terms in the original message.
248
+ *
249
+ * Handlers may ignore either argument. Wrappers that invoke this callback
250
+ * themselves must forward both the exit code and the message.
245
251
  *
246
252
  * You usually want to pass `process.exit` on Node.js or Bun and `Deno.exit`
247
253
  * on Deno to this option.
248
254
  * @default Throws a {@link RunParserError}.
255
+ * @since 1.3.0 Added the `error` parameter.
249
256
  */
250
- readonly onError?: (() => TError) | ((exitCode: number) => TError);
257
+ readonly onError?: (exitCode: number, error: Message) => TError;
251
258
  /**
252
259
  * Function used to output error messages. Assumes it prints the ending
253
260
  * newline.
package/dist/facade.js CHANGED
@@ -516,10 +516,14 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
516
516
  function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, termWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = []) {
517
517
  const shellName = completionArgs[0] || "";
518
518
  const args = completionArgs.slice(1);
519
- const callOnError = (code) => onError(code);
519
+ const callOnError = (code, error) => onError(code, error);
520
520
  const callOnCompletion = (code) => onCompletion(code);
521
521
  if (!shellName) {
522
- stderr("Error: Missing shell name for completion.\n");
522
+ const error = message`Missing shell name for completion.`;
523
+ stderr(`Error: ${formatMessage(error, {
524
+ colors,
525
+ quotes: !colors
526
+ })}\n`);
523
527
  if (completionParser) {
524
528
  const displayName = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
525
529
  const doc = getDocPage(completionParser, [displayName]);
@@ -532,10 +536,10 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
532
536
  }));
533
537
  }
534
538
  return dispatchByMode(parser.mode, () => {
535
- const result = callOnError(1);
539
+ const result = callOnError(1, error);
536
540
  if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
537
541
  return result;
538
- }, async () => callOnError(1));
542
+ }, async () => callOnError(1, error));
539
543
  }
540
544
  const shell = availableShells[shellName];
541
545
  if (!shell) {
@@ -544,15 +548,16 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
544
548
  if (available.length > 0) available.push(text(", "));
545
549
  available.push(value(name));
546
550
  }
547
- stderr(formatMessage(message`Error: Unsupported shell ${shellName}. Available shells: ${available}.`, {
551
+ const error = message`Unsupported shell ${shellName}. Available shells: ${available}.`;
552
+ stderr(`Error: ${formatMessage(error, {
548
553
  colors,
549
554
  quotes: !colors
550
- }));
555
+ })}`);
551
556
  return dispatchByMode(parser.mode, () => {
552
- const result = callOnError(1);
557
+ const result = callOnError(1, error);
553
558
  if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
554
559
  return result;
555
- }, async () => callOnError(1));
560
+ }, async () => callOnError(1, error));
556
561
  }
557
562
  if (args.length === 0) {
558
563
  const completionArg = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
@@ -870,7 +875,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
870
875
  const completionOptionConfig = norm(options.completion?.option);
871
876
  const onCompletion = options.completion?.onShow ?? (() => ({}));
872
877
  const onCompletionResult = (code) => onCompletion(code);
873
- const onErrorResult = (code) => onError(code);
878
+ const onErrorResult = (code, error) => onError(code, error);
874
879
  if (helpOptionConfig?.names) validateOptionNames(helpOptionConfig.names, "Help option");
875
880
  if (helpCommandConfig?.names) validateCommandNames(helpCommandConfig.names, "Help command");
876
881
  if (versionOptionConfig?.names) validateOptionNames(versionOptionConfig.names, "Version option");
@@ -1022,7 +1027,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1022
1027
  quotes: !colors
1023
1028
  });
1024
1029
  stderr(`Error: ${errorMessage}`);
1025
- return onError(1);
1030
+ return onError(1, validationError);
1026
1031
  };
1027
1032
  const displayHelp = (doc) => {
1028
1033
  if (doc != null) {
@@ -1133,7 +1138,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1133
1138
  quotes: !colors
1134
1139
  });
1135
1140
  stderr(`Error: ${errorMessage}`);
1136
- return onError(1);
1141
+ return onError(1, classified.error);
1137
1142
  };
1138
1143
  if (aboveError === "help") {
1139
1144
  const parserForDoc = args.length < 1 ? augmentedParser : parser;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.3.0-dev.2513",
3
+ "version": "1.3.0-dev.2519",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  "sideEffects": false,
223
223
  "devDependencies": {
224
- "@optique/env": "1.3.0-dev.2513+35aeb8e0",
224
+ "@optique/env": "1.3.0-dev.2519+af660a4e",
225
225
  "@types/node": "^24.0.0",
226
226
  "fast-check": "^4.7.0",
227
227
  "tsdown": "^0.13.0",
@@ -11,19 +11,19 @@ description: >
11
11
  license: MIT
12
12
  ---
13
13
 
14
- Optique is a type-safe combinatorial CLI parser. Use it by describing the CLI
15
- grammar with parsers and combinators, not by manually walking `argv`.
14
+ Build CLI grammars by composing Optique parsers instead of walking `argv`.
16
15
 
17
- If web access is available, start from <https://optique.dev/llms.txt> for the
18
- maintained documentation index. Keep the rules below in mind even when offline;
19
- they cover the parts agents most often get wrong.
16
+ If online, start at <https://optique.dev/llms.txt> for maintained docs. These
17
+ rules also cover common pitfalls when offline.
20
18
 
21
19
 
22
20
  Core rules
23
21
  ----------
24
22
 
25
23
  - Use `run()` from *@optique/run* for applications; use `parse()` or
26
- `runParser()` for embedded and custom runtimes.
24
+ `runParser()` for embedded and custom runtimes. With `runParser()`,
25
+ `onError(exitCode, error)` receives a structured `Message` after stderr
26
+ output; use that argument instead of parsing rendered error text.
27
27
  - In tests, use `parseArgs()`/`parseArgsSync()` from *@optique/testing/parser*
28
28
  for parser results, `captureRun()` from *@optique/testing/run* for runner
29
29
  output/exits, `captureProgramRun()` from *@optique/testing/discover* for