@optique/run 0.10.7 → 1.0.0-dev.1116
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 +21 -11
- package/dist/run.cjs +142 -78
- package/dist/run.d.cts +162 -80
- package/dist/run.d.ts +162 -80
- package/dist/run.js +143 -79
- package/dist/valueparser.cjs +30 -5
- package/dist/valueparser.d.cts +17 -0
- package/dist/valueparser.d.ts +17 -0
- package/dist/valueparser.js +31 -6
- package/package.json +2 -2
package/dist/run.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { CommandSubConfig, ContextOptionsParam, OptionSubConfig } from "@optique/core/facade";
|
|
1
2
|
import { Message } from "@optique/core/message";
|
|
2
3
|
import { ShellCompletion } from "@optique/core/completion";
|
|
4
|
+
import { SourceContext } from "@optique/core/context";
|
|
3
5
|
import { InferMode, InferValue, Mode, ModeValue, Parser } from "@optique/core/parser";
|
|
4
6
|
import { Program } from "@optique/core/program";
|
|
5
|
-
import { ShowChoicesOptions, ShowDefaultOptions } from "@optique/core/doc";
|
|
7
|
+
import { DocSection, ShowChoicesOptions, ShowDefaultOptions } from "@optique/core/doc";
|
|
6
8
|
|
|
7
9
|
//#region src/run.d.ts
|
|
8
10
|
|
|
@@ -22,6 +24,26 @@ interface RunOptions {
|
|
|
22
24
|
* @default `process.argv.slice(2)` (arguments after the script name)
|
|
23
25
|
*/
|
|
24
26
|
readonly args?: readonly string[];
|
|
27
|
+
/**
|
|
28
|
+
* Function used to output help and usage messages. Assumes it prints the
|
|
29
|
+
* ending newline.
|
|
30
|
+
*
|
|
31
|
+
* @default Writes to `process.stdout` with a trailing newline
|
|
32
|
+
*/
|
|
33
|
+
readonly stdout?: (text: string) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Function used to output error messages. Assumes it prints the ending
|
|
36
|
+
* newline.
|
|
37
|
+
*
|
|
38
|
+
* @default Writes to `process.stderr` with a trailing newline
|
|
39
|
+
*/
|
|
40
|
+
readonly stderr?: (text: string) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Function used to exit the process on help/version display or parse error.
|
|
43
|
+
*
|
|
44
|
+
* @default `process.exit`
|
|
45
|
+
*/
|
|
46
|
+
readonly onExit?: (exitCode: number) => never;
|
|
25
47
|
/**
|
|
26
48
|
* Whether to enable colored output in help and error messages.
|
|
27
49
|
*
|
|
@@ -62,69 +84,86 @@ interface RunOptions {
|
|
|
62
84
|
* @since 0.10.0
|
|
63
85
|
*/
|
|
64
86
|
readonly showChoices?: boolean | ShowChoicesOptions;
|
|
87
|
+
/**
|
|
88
|
+
* A custom comparator function to control the order of sections in the
|
|
89
|
+
* help output. When provided, it is used instead of the default smart
|
|
90
|
+
* sort (command-only sections first, then mixed, then option/argument-only
|
|
91
|
+
* sections). Sections that compare equal (return `0`) preserve their
|
|
92
|
+
* original relative order.
|
|
93
|
+
*
|
|
94
|
+
* @param a The first section to compare.
|
|
95
|
+
* @param b The second section to compare.
|
|
96
|
+
* @returns A negative number if `a` should appear before `b`, a positive
|
|
97
|
+
* number if `a` should appear after `b`, or `0` if they are equal.
|
|
98
|
+
* @since 1.0.0
|
|
99
|
+
*/
|
|
100
|
+
readonly sectionOrder?: (a: DocSection, b: DocSection) => number;
|
|
65
101
|
/**
|
|
66
102
|
* Help configuration. Determines how help is made available:
|
|
67
103
|
*
|
|
68
104
|
* - `"command"`: Only the `help` subcommand is available
|
|
69
105
|
* - `"option"`: Only the `--help` option is available
|
|
70
106
|
* - `"both"`: Both `help` subcommand and `--help` option are available
|
|
71
|
-
* - `object`: Advanced configuration with
|
|
72
|
-
* - `
|
|
73
|
-
* - `group`: Group label for help command in help output (optional)
|
|
107
|
+
* - `object`: Advanced configuration with `command` and/or `option`
|
|
108
|
+
* sub-configs. At least one of `command` or `option` must be specified.
|
|
74
109
|
*
|
|
75
110
|
* When not provided, help functionality is disabled.
|
|
111
|
+
*
|
|
112
|
+
* @since 1.0.0
|
|
76
113
|
*/
|
|
77
|
-
readonly help?: "command" | "option" | "both" | {
|
|
78
|
-
readonly
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
};
|
|
114
|
+
readonly help?: "command" | "option" | "both" | (({
|
|
115
|
+
readonly command: true | CommandSubConfig;
|
|
116
|
+
readonly option?: true | OptionSubConfig;
|
|
117
|
+
} | {
|
|
118
|
+
readonly option: true | OptionSubConfig;
|
|
119
|
+
readonly command?: true | CommandSubConfig;
|
|
120
|
+
}));
|
|
85
121
|
/**
|
|
86
122
|
* Version configuration. Determines how version is made available:
|
|
87
123
|
*
|
|
88
124
|
* - `string`: Version value with default `"option"` mode (--version only)
|
|
89
|
-
* - `object`: Advanced configuration with version value and
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* - `group`: Group label for version command in help output (only
|
|
93
|
-
* when mode is "command" or "both")
|
|
125
|
+
* - `object`: Advanced configuration with version value and `command`
|
|
126
|
+
* and/or `option` sub-configs. At least one of `command` or `option`
|
|
127
|
+
* must be specified.
|
|
94
128
|
*
|
|
95
129
|
* When not provided, version functionality is disabled.
|
|
130
|
+
*
|
|
131
|
+
* @since 1.0.0
|
|
96
132
|
*/
|
|
97
|
-
readonly version?: string | {
|
|
133
|
+
readonly version?: string | ({
|
|
98
134
|
readonly value: string;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* @since 0.10.0
|
|
103
|
-
*/
|
|
104
|
-
readonly group?: string;
|
|
135
|
+
} & ({
|
|
136
|
+
readonly command: true | CommandSubConfig;
|
|
137
|
+
readonly option?: true | OptionSubConfig;
|
|
105
138
|
} | {
|
|
106
|
-
readonly
|
|
107
|
-
readonly
|
|
108
|
-
|
|
109
|
-
};
|
|
139
|
+
readonly option: true | OptionSubConfig;
|
|
140
|
+
readonly command?: true | CommandSubConfig;
|
|
141
|
+
}));
|
|
110
142
|
/**
|
|
111
|
-
* Completion configuration. Determines how shell completion is made
|
|
143
|
+
* Completion configuration. Determines how shell completion is made
|
|
144
|
+
* available:
|
|
112
145
|
*
|
|
113
146
|
* - `"command"`: Only the `completion` subcommand is available
|
|
114
147
|
* - `"option"`: Only the `--completion` option is available
|
|
115
|
-
* - `"both"`: Both `completion` subcommand and `--completion` option
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* -
|
|
119
|
-
*
|
|
120
|
-
* (default: matches `name`)
|
|
121
|
-
* - `shells`: Custom shell completions (optional)
|
|
148
|
+
* - `"both"`: Both `completion` subcommand and `--completion` option
|
|
149
|
+
* are available
|
|
150
|
+
* - `object`: Advanced configuration with `command` and/or `option`
|
|
151
|
+
* sub-configs and optional custom shells. At least one of `command`
|
|
152
|
+
* or `option` must be specified.
|
|
122
153
|
*
|
|
123
154
|
* When not provided, completion functionality is disabled.
|
|
124
155
|
*
|
|
125
|
-
* @since 0.
|
|
156
|
+
* @since 1.0.0
|
|
126
157
|
*/
|
|
127
|
-
readonly completion?: "command" | "option" | "both" |
|
|
158
|
+
readonly completion?: "command" | "option" | "both" | ({
|
|
159
|
+
readonly shells?: Record<string, ShellCompletion>;
|
|
160
|
+
} & ({
|
|
161
|
+
readonly command: true | CommandSubConfig;
|
|
162
|
+
readonly option?: true | OptionSubConfig;
|
|
163
|
+
} | {
|
|
164
|
+
readonly option: true | OptionSubConfig;
|
|
165
|
+
readonly command?: true | CommandSubConfig;
|
|
166
|
+
}));
|
|
128
167
|
/**
|
|
129
168
|
* What to display above error messages:
|
|
130
169
|
*
|
|
@@ -177,49 +216,59 @@ interface RunOptions {
|
|
|
177
216
|
* @since 0.4.0
|
|
178
217
|
*/
|
|
179
218
|
readonly footer?: Message;
|
|
180
|
-
}
|
|
181
|
-
type CompletionHelpVisibility = "singular" | "plural" | "both" | "none";
|
|
182
|
-
type CompletionOptionsBase = {
|
|
183
|
-
readonly mode?: "command" | "both";
|
|
184
|
-
/**
|
|
185
|
-
* Group label for the completion command in help output.
|
|
186
|
-
* @since 0.10.0
|
|
187
|
-
*/
|
|
188
|
-
readonly group?: string;
|
|
189
|
-
readonly shells?: Record<string, ShellCompletion>;
|
|
190
|
-
} | {
|
|
191
|
-
readonly mode: "option";
|
|
192
|
-
readonly group?: never;
|
|
193
|
-
readonly shells?: Record<string, ShellCompletion>;
|
|
194
|
-
};
|
|
195
|
-
type CompletionOptionsBoth = CompletionOptionsBase & {
|
|
196
|
-
readonly name?: "both";
|
|
197
|
-
/**
|
|
198
|
-
* Controls which completion aliases are shown in help and usage output.
|
|
199
|
-
*
|
|
200
|
-
* @since 0.10.0
|
|
201
|
-
*/
|
|
202
|
-
readonly helpVisibility?: CompletionHelpVisibility;
|
|
203
|
-
};
|
|
204
|
-
type CompletionOptionsSingular = CompletionOptionsBase & {
|
|
205
|
-
readonly name: "singular";
|
|
206
219
|
/**
|
|
207
|
-
*
|
|
220
|
+
* Source contexts to use for two-phase parsing. When provided, the
|
|
221
|
+
* runner delegates to `runWith()` (or `runWithSync()` for sync parsers)
|
|
222
|
+
* from `@optique/core/facade`, which handles annotation collection and
|
|
223
|
+
* multi-phase parsing automatically.
|
|
208
224
|
*
|
|
209
|
-
* @since 0.
|
|
225
|
+
* @since 1.0.0
|
|
210
226
|
*/
|
|
211
|
-
readonly
|
|
212
|
-
};
|
|
213
|
-
type CompletionOptionsPlural = CompletionOptionsBase & {
|
|
214
|
-
readonly name: "plural";
|
|
227
|
+
readonly contexts?: readonly SourceContext<unknown>[];
|
|
215
228
|
/**
|
|
216
|
-
*
|
|
229
|
+
* Options to forward to source contexts. When contexts declare
|
|
230
|
+
* required options (via `$requiredOptions`), pass them here to
|
|
231
|
+
* avoid name collisions with runner-level options such as `help`,
|
|
232
|
+
* `programName`, or `version`.
|
|
217
233
|
*
|
|
218
|
-
* @since 0.
|
|
234
|
+
* @since 1.0.0
|
|
219
235
|
*/
|
|
220
|
-
readonly
|
|
221
|
-
}
|
|
222
|
-
|
|
236
|
+
readonly contextOptions?: Record<string, unknown>;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Rejects context tuples that are statically known to be empty so those calls
|
|
240
|
+
* fall back to the no-context overloads.
|
|
241
|
+
*/
|
|
242
|
+
type RejectEmptyContexts<TContexts extends readonly SourceContext<unknown>[]> = TContexts extends readonly [] ? never : unknown;
|
|
243
|
+
/**
|
|
244
|
+
* Represents a context tuple that is statically known to contain at least one
|
|
245
|
+
* source context.
|
|
246
|
+
*/
|
|
247
|
+
type NonEmptySourceContexts = readonly [SourceContext<unknown>, ...SourceContext<unknown>[]];
|
|
248
|
+
/**
|
|
249
|
+
* Rejects option shapes that may carry a non-empty `contexts` array so plain
|
|
250
|
+
* Program overloads do not bypass the context-aware overloads.
|
|
251
|
+
*/
|
|
252
|
+
type ContextsFromOptions<TOptions> = [Exclude<TOptions, undefined>] extends [never] ? undefined : Exclude<TOptions, undefined> extends {
|
|
253
|
+
readonly contexts?: infer TContexts extends readonly SourceContext<unknown>[] | undefined;
|
|
254
|
+
} ? TContexts : undefined;
|
|
255
|
+
type RejectContextfulOptions<TOptions> = [ContextsFromOptions<TOptions>] extends [undefined | readonly []] ? unknown : never;
|
|
256
|
+
/**
|
|
257
|
+
* Rejects option shapes that introduce keys outside the public `RunOptions`
|
|
258
|
+
* contract, preserving typo detection for direct object literals and wider
|
|
259
|
+
* option variables.
|
|
260
|
+
*/
|
|
261
|
+
type RejectUnknownRunOptionKeys<TOptions> = [TOptions] extends [undefined] ? unknown : Exclude<keyof TOptions, keyof RunOptions> extends never ? unknown : never;
|
|
262
|
+
/**
|
|
263
|
+
* Accepts only values typed exactly as `RunOptions`, which are widened to the
|
|
264
|
+
* conservative fallback overloads because they may hide context presence.
|
|
265
|
+
*/
|
|
266
|
+
type AcceptExactRunOptions<TOptions> = [TOptions] extends [RunOptions] ? [RunOptions] extends [TOptions] ? unknown : never : never;
|
|
267
|
+
/**
|
|
268
|
+
* Accepts only values typed exactly as `RunOptions | undefined`, which model
|
|
269
|
+
* optional forwarding wrappers without widening generic Program overloads.
|
|
270
|
+
*/
|
|
271
|
+
type AcceptExactOptionalRunOptions<TOptions> = [TOptions] extends [RunOptions | undefined] ? [RunOptions | undefined] extends [TOptions] ? unknown : never : never;
|
|
223
272
|
/**
|
|
224
273
|
* Runs a command-line parser with automatic process integration.
|
|
225
274
|
*
|
|
@@ -285,8 +334,25 @@ type CompletionOptions = CompletionOptionsBoth | CompletionOptionsSingular | Com
|
|
|
285
334
|
*
|
|
286
335
|
* @since 0.11.0 Added support for {@link Program} objects.
|
|
287
336
|
*/
|
|
288
|
-
declare function run<T>(
|
|
289
|
-
|
|
337
|
+
declare function run<T extends Parser<Mode, unknown, unknown>, const TContexts extends NonEmptySourceContexts>(parser: T, options: RunOptions & {
|
|
338
|
+
readonly contexts: TContexts;
|
|
339
|
+
} & ContextOptionsParam<TContexts, InferValue<T>>): Promise<InferValue<T>>;
|
|
340
|
+
declare function run<T extends Parser<Mode, unknown, unknown>, const TContexts extends readonly SourceContext<unknown>[]>(parser: T, options: RunOptions & {
|
|
341
|
+
readonly contexts: TContexts;
|
|
342
|
+
} & RejectEmptyContexts<TContexts> & ContextOptionsParam<TContexts, InferValue<T>>): ModeValue<InferMode<T>, InferValue<T>> | Promise<InferValue<T>>;
|
|
343
|
+
declare function run<M extends Mode, T, const TContexts extends NonEmptySourceContexts>(program: Program<M, T>, options: RunOptions & {
|
|
344
|
+
readonly contexts: TContexts;
|
|
345
|
+
} & ContextOptionsParam<TContexts, T>): Promise<T>;
|
|
346
|
+
declare function run<T, const TContexts extends readonly SourceContext<unknown>[]>(program: Program<"sync", T>, options: RunOptions & {
|
|
347
|
+
readonly contexts: TContexts;
|
|
348
|
+
} & RejectEmptyContexts<TContexts> & ContextOptionsParam<TContexts, T>): T | Promise<T>;
|
|
349
|
+
declare function run<T, const TContexts extends readonly SourceContext<unknown>[]>(program: Program<"async", T>, options: RunOptions & {
|
|
350
|
+
readonly contexts: TContexts;
|
|
351
|
+
} & RejectEmptyContexts<TContexts> & ContextOptionsParam<TContexts, T>): Promise<T>;
|
|
352
|
+
declare function run<T, const TOptions extends RunOptions | undefined>(program: Program<"sync", T>, options?: TOptions & RejectContextfulOptions<TOptions> & RejectUnknownRunOptionKeys<TOptions>): T;
|
|
353
|
+
declare function run<T, TOptions extends RunOptions>(program: Program<"sync", T>, options: TOptions & AcceptExactRunOptions<TOptions>): T | Promise<T>;
|
|
354
|
+
declare function run<T, const TOptions extends RunOptions | undefined>(program: Program<"async", T>, options?: TOptions & RejectContextfulOptions<TOptions> & RejectUnknownRunOptionKeys<TOptions>): Promise<T>;
|
|
355
|
+
declare function run<T, TOptions extends RunOptions>(program: Program<"async", T>, options: TOptions & AcceptExactRunOptions<TOptions>): Promise<T>;
|
|
290
356
|
declare function run<T extends Parser<"sync", unknown, unknown>>(parser: T, options?: RunOptions): InferValue<T>;
|
|
291
357
|
declare function run<T extends Parser<"async", unknown, unknown>>(parser: T, options?: RunOptions): Promise<InferValue<T>>;
|
|
292
358
|
declare function run<T extends Parser<Mode, unknown, unknown>>(parser: T, options?: RunOptions): ModeValue<InferMode<T>, InferValue<T>>;
|
|
@@ -303,7 +369,15 @@ declare function run<T extends Parser<Mode, unknown, unknown>>(parser: T, option
|
|
|
303
369
|
* @returns The parsed result if successful.
|
|
304
370
|
* @since 0.9.0
|
|
305
371
|
*/
|
|
306
|
-
declare function runSync<T
|
|
372
|
+
declare function runSync<T extends Parser<"sync", unknown, unknown>, TContexts extends readonly SourceContext<unknown>[]>(parser: T, options: RunOptions & {
|
|
373
|
+
readonly contexts: TContexts;
|
|
374
|
+
} & ContextOptionsParam<TContexts, InferValue<T>>): InferValue<T>;
|
|
375
|
+
declare function runSync<T, const TContexts extends readonly SourceContext<unknown>[]>(program: Program<"sync", T>, options: RunOptions & {
|
|
376
|
+
readonly contexts: TContexts;
|
|
377
|
+
} & RejectEmptyContexts<TContexts> & ContextOptionsParam<TContexts, T>): T;
|
|
378
|
+
declare function runSync<T, const TOptions extends RunOptions | undefined>(program: Program<"sync", T>, options?: TOptions & RejectContextfulOptions<TOptions> & RejectUnknownRunOptionKeys<TOptions>): T;
|
|
379
|
+
declare function runSync<T, TOptions extends RunOptions>(program: Program<"sync", T>, options: TOptions & AcceptExactRunOptions<TOptions>): T;
|
|
380
|
+
declare function runSync<T, TOptions extends RunOptions | undefined>(program: Program<"sync", T>, options: TOptions & AcceptExactOptionalRunOptions<TOptions>): T;
|
|
307
381
|
declare function runSync<T extends Parser<"sync", unknown, unknown>>(parser: T, options?: RunOptions): InferValue<T>;
|
|
308
382
|
/**
|
|
309
383
|
* Runs an asynchronous command-line parser with automatic process integration.
|
|
@@ -318,8 +392,16 @@ declare function runSync<T extends Parser<"sync", unknown, unknown>>(parser: T,
|
|
|
318
392
|
* @returns A Promise of the parsed result if successful.
|
|
319
393
|
* @since 0.9.0
|
|
320
394
|
*/
|
|
321
|
-
declare function runAsync<T>(
|
|
322
|
-
|
|
395
|
+
declare function runAsync<T extends Parser<Mode, unknown, unknown>, TContexts extends readonly SourceContext<unknown>[]>(parser: T, options: RunOptions & {
|
|
396
|
+
readonly contexts: TContexts;
|
|
397
|
+
} & ContextOptionsParam<TContexts, InferValue<T>>): Promise<InferValue<T>>;
|
|
398
|
+
declare function runAsync<M extends Mode, T, const TContexts extends readonly SourceContext<unknown>[]>(program: Program<M, T>, options: RunOptions & {
|
|
399
|
+
readonly contexts: TContexts;
|
|
400
|
+
} & RejectEmptyContexts<TContexts> & ContextOptionsParam<TContexts, T>): Promise<T>;
|
|
401
|
+
declare function runAsync<T, const TOptions extends RunOptions | undefined>(program: Program<"sync", T>, options?: TOptions & RejectContextfulOptions<TOptions> & RejectUnknownRunOptionKeys<TOptions>): Promise<T>;
|
|
402
|
+
declare function runAsync<T, const TOptions extends RunOptions | undefined>(program: Program<"async", T>, options?: TOptions & RejectContextfulOptions<TOptions> & RejectUnknownRunOptionKeys<TOptions>): Promise<T>;
|
|
403
|
+
declare function runAsync<T, TOptions extends RunOptions>(program: Program<Mode, T>, options: TOptions & AcceptExactRunOptions<TOptions>): Promise<T>;
|
|
404
|
+
declare function runAsync<T, TOptions extends RunOptions | undefined>(program: Program<Mode, T>, options: TOptions & AcceptExactOptionalRunOptions<TOptions>): Promise<T>;
|
|
323
405
|
declare function runAsync<T extends Parser<Mode, unknown, unknown>>(parser: T, options?: RunOptions): Promise<InferValue<T>>;
|
|
324
406
|
//#endregion
|
|
325
407
|
export { RunOptions, run, runAsync, runSync };
|
package/dist/run.js
CHANGED
|
@@ -1,113 +1,155 @@
|
|
|
1
|
-
import { runParser } from "@optique/core/facade";
|
|
1
|
+
import { runParser, runWith, runWithSync } from "@optique/core/facade";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
|
|
5
5
|
//#region src/run.ts
|
|
6
|
+
function getProgramHelpMetadata(metadata) {
|
|
7
|
+
return {
|
|
8
|
+
brief: metadata.brief,
|
|
9
|
+
description: metadata.description,
|
|
10
|
+
examples: metadata.examples,
|
|
11
|
+
author: metadata.author,
|
|
12
|
+
bugs: metadata.bugs,
|
|
13
|
+
footer: metadata.footer
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function resolveProgramInput(parserOrProgram, options) {
|
|
17
|
+
if ("parser" in parserOrProgram && "metadata" in parserOrProgram) return {
|
|
18
|
+
parser: parserOrProgram.parser,
|
|
19
|
+
options: options.programName == null ? {
|
|
20
|
+
...options,
|
|
21
|
+
programName: parserOrProgram.metadata.name
|
|
22
|
+
} : options,
|
|
23
|
+
programMetadata: getProgramHelpMetadata(parserOrProgram.metadata)
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
parser: parserOrProgram,
|
|
27
|
+
options
|
|
28
|
+
};
|
|
29
|
+
}
|
|
6
30
|
function run(parserOrProgram, options = {}) {
|
|
7
31
|
return runImpl(parserOrProgram, options);
|
|
8
32
|
}
|
|
9
33
|
function runSync(parserOrProgram, options = {}) {
|
|
34
|
+
const contexts = options.contexts;
|
|
35
|
+
if (contexts && contexts.length > 0) {
|
|
36
|
+
const resolved = resolveProgramInput(parserOrProgram, options);
|
|
37
|
+
const { parser, programMetadata } = resolved;
|
|
38
|
+
options = resolved.options;
|
|
39
|
+
const { programName, args, coreOptions } = buildCoreOptions(options, programMetadata);
|
|
40
|
+
const runWithOptions = {
|
|
41
|
+
...coreOptions,
|
|
42
|
+
contextOptions: options.contextOptions,
|
|
43
|
+
args
|
|
44
|
+
};
|
|
45
|
+
return runWithSync(parser, programName, contexts, runWithOptions);
|
|
46
|
+
}
|
|
10
47
|
return runImpl(parserOrProgram, options);
|
|
11
48
|
}
|
|
12
49
|
function runAsync(parserOrProgram, options = {}) {
|
|
13
50
|
const result = runImpl(parserOrProgram, options);
|
|
14
51
|
return Promise.resolve(result);
|
|
15
52
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Builds core run options from the simplified RunOptions format.
|
|
55
|
+
*
|
|
56
|
+
* Converts the user-friendly RunOptions (string-based help/version/completion)
|
|
57
|
+
* into the verbose CoreRunOptions format expected by `runParser()`, `runWith()`,
|
|
58
|
+
* and `runWithSync()` from `@optique/core/facade`.
|
|
59
|
+
*
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
function buildCoreOptions(options, programMetadata) {
|
|
63
|
+
const programName = options.programName ?? path.basename(process.argv[1] ?? "cli");
|
|
64
|
+
const args = options.args ?? process.argv.slice(2);
|
|
65
|
+
const stdout = options.stdout ?? ((line) => {
|
|
66
|
+
process.stdout.write(`${line}\n`);
|
|
67
|
+
});
|
|
68
|
+
const stderr = options.stderr ?? ((line) => {
|
|
69
|
+
process.stderr.write(`${line}\n`);
|
|
70
|
+
});
|
|
71
|
+
const onExit = options.onExit ?? ((exitCode) => process.exit(exitCode));
|
|
72
|
+
const colors = options.colors ?? process.stdout.isTTY;
|
|
73
|
+
const maxWidth = options.maxWidth ?? process.stdout.columns;
|
|
74
|
+
const showDefault = options.showDefault;
|
|
75
|
+
const showChoices = options.showChoices;
|
|
76
|
+
const sectionOrder = options.sectionOrder;
|
|
77
|
+
const help = options.help;
|
|
78
|
+
const version = options.version;
|
|
79
|
+
const completion = options.completion;
|
|
80
|
+
const aboveError = options.aboveError ?? "usage";
|
|
81
|
+
const errorExitCode = options.errorExitCode ?? 1;
|
|
82
|
+
const brief = options.brief ?? programMetadata?.brief;
|
|
83
|
+
const description = options.description ?? programMetadata?.description;
|
|
84
|
+
const examples = options.examples ?? programMetadata?.examples;
|
|
85
|
+
const author = options.author ?? programMetadata?.author;
|
|
86
|
+
const bugs = options.bugs ?? programMetadata?.bugs;
|
|
87
|
+
const footer = options.footer ?? programMetadata?.footer;
|
|
88
|
+
const onShow = () => onExit(0);
|
|
89
|
+
const helpConfig = (() => {
|
|
90
|
+
if (!help) return void 0;
|
|
91
|
+
if (typeof help === "string") switch (help) {
|
|
92
|
+
case "command": return {
|
|
93
|
+
command: true,
|
|
94
|
+
onShow
|
|
95
|
+
};
|
|
96
|
+
case "option": return {
|
|
97
|
+
option: true,
|
|
98
|
+
onShow
|
|
99
|
+
};
|
|
100
|
+
case "both": return {
|
|
101
|
+
command: true,
|
|
102
|
+
option: true,
|
|
103
|
+
onShow
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
...help,
|
|
108
|
+
onShow
|
|
32
109
|
};
|
|
33
|
-
}
|
|
34
|
-
const { programName = programNameFromProgram ?? path.basename(process.argv[1] || "cli"), args = process.argv.slice(2), colors = process.stdout.isTTY, maxWidth = process.stdout.columns, showDefault, showChoices, help, version, completion, aboveError = "usage", errorExitCode = 1, brief = programMetadata?.brief, description = programMetadata?.description, examples = programMetadata?.examples, author = programMetadata?.author, bugs = programMetadata?.bugs, footer = programMetadata?.footer } = options;
|
|
35
|
-
const helpConfig = help ? typeof help === "string" ? {
|
|
36
|
-
mode: help,
|
|
37
|
-
onShow: () => process.exit(0)
|
|
38
|
-
} : {
|
|
39
|
-
mode: help.mode,
|
|
40
|
-
group: help.group,
|
|
41
|
-
onShow: () => process.exit(0)
|
|
42
|
-
} : void 0;
|
|
110
|
+
})();
|
|
43
111
|
const versionConfig = (() => {
|
|
44
112
|
if (!version) return void 0;
|
|
45
113
|
if (typeof version === "string") return {
|
|
46
|
-
mode: "option",
|
|
47
114
|
value: version,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const mode = version.mode ?? "option";
|
|
51
|
-
if (mode === "command" || mode === "both") return {
|
|
52
|
-
mode,
|
|
53
|
-
value: version.value,
|
|
54
|
-
group: version.group,
|
|
55
|
-
onShow: () => process.exit(0)
|
|
115
|
+
option: true,
|
|
116
|
+
onShow
|
|
56
117
|
};
|
|
57
118
|
return {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
onShow: () => process.exit(0)
|
|
119
|
+
...version,
|
|
120
|
+
onShow
|
|
61
121
|
};
|
|
62
122
|
})();
|
|
63
123
|
const completionConfig = (() => {
|
|
64
124
|
if (!completion) return void 0;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
helpVisibility: completion.helpVisibility ?? "singular",
|
|
81
|
-
onShow
|
|
82
|
-
};
|
|
83
|
-
if (completion.name === "plural") return {
|
|
84
|
-
mode,
|
|
85
|
-
shells,
|
|
86
|
-
...cGroup != null && { group: cGroup },
|
|
87
|
-
name: "plural",
|
|
88
|
-
helpVisibility: completion.helpVisibility ?? "plural",
|
|
89
|
-
onShow
|
|
90
|
-
};
|
|
125
|
+
if (typeof completion === "string") switch (completion) {
|
|
126
|
+
case "command": return {
|
|
127
|
+
command: true,
|
|
128
|
+
onShow
|
|
129
|
+
};
|
|
130
|
+
case "option": return {
|
|
131
|
+
option: true,
|
|
132
|
+
onShow
|
|
133
|
+
};
|
|
134
|
+
case "both": return {
|
|
135
|
+
command: true,
|
|
136
|
+
option: true,
|
|
137
|
+
onShow
|
|
138
|
+
};
|
|
139
|
+
}
|
|
91
140
|
return {
|
|
92
|
-
|
|
93
|
-
shells,
|
|
94
|
-
...cGroup != null && { group: cGroup },
|
|
95
|
-
name: "both",
|
|
96
|
-
helpVisibility: completion.helpVisibility ?? "both",
|
|
141
|
+
...completion,
|
|
97
142
|
onShow
|
|
98
143
|
};
|
|
99
144
|
})();
|
|
100
|
-
|
|
101
|
-
stderr
|
|
102
|
-
|
|
103
|
-
},
|
|
104
|
-
stdout(line) {
|
|
105
|
-
process.stdout.write(`${line}\n`);
|
|
106
|
-
},
|
|
145
|
+
const coreOptions = {
|
|
146
|
+
stderr,
|
|
147
|
+
stdout,
|
|
107
148
|
colors,
|
|
108
149
|
maxWidth,
|
|
109
150
|
showDefault,
|
|
110
151
|
showChoices,
|
|
152
|
+
sectionOrder,
|
|
111
153
|
help: helpConfig,
|
|
112
154
|
version: versionConfig,
|
|
113
155
|
completion: completionConfig,
|
|
@@ -119,9 +161,31 @@ function runImpl(parserOrProgram, options = {}) {
|
|
|
119
161
|
bugs,
|
|
120
162
|
footer,
|
|
121
163
|
onError() {
|
|
122
|
-
return
|
|
164
|
+
return onExit(errorExitCode);
|
|
123
165
|
}
|
|
124
|
-
}
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
programName,
|
|
169
|
+
args,
|
|
170
|
+
coreOptions
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function runImpl(parserOrProgram, options = {}) {
|
|
174
|
+
const resolved = resolveProgramInput(parserOrProgram, options);
|
|
175
|
+
const { parser, programMetadata } = resolved;
|
|
176
|
+
options = resolved.options;
|
|
177
|
+
const contexts = options.contexts;
|
|
178
|
+
if (contexts && contexts.length > 0) {
|
|
179
|
+
const { programName: programName$1, args: args$1, coreOptions: coreOptions$1 } = buildCoreOptions(options, programMetadata);
|
|
180
|
+
const runWithOptions = {
|
|
181
|
+
...coreOptions$1,
|
|
182
|
+
contextOptions: options.contextOptions,
|
|
183
|
+
args: args$1
|
|
184
|
+
};
|
|
185
|
+
return runWith(parser, programName$1, contexts, runWithOptions);
|
|
186
|
+
}
|
|
187
|
+
const { programName, args, coreOptions } = buildCoreOptions(options, programMetadata);
|
|
188
|
+
return runParser(parser, programName, args, coreOptions);
|
|
125
189
|
}
|
|
126
190
|
|
|
127
191
|
//#endregion
|
package/dist/valueparser.cjs
CHANGED
|
@@ -14,6 +14,17 @@ const node_fs = require_rolldown_runtime.__toESM(require("node:fs"));
|
|
|
14
14
|
*
|
|
15
15
|
* @param options Configuration options for path validation.
|
|
16
16
|
* @returns A ValueParser that validates and returns string paths.
|
|
17
|
+
* @throws {TypeError} If {@link PathOptionsBase.type} is not one of
|
|
18
|
+
* `"file"`, `"directory"`, or `"either"`.
|
|
19
|
+
* @throws {TypeError} If any entry in {@link PathOptionsBase.extensions} does
|
|
20
|
+
* not start with a dot (e.g., `"json"` instead of `".json"`).
|
|
21
|
+
* @throws {TypeError} If {@link PathOptionsMustExist.mustExist} is not a
|
|
22
|
+
* boolean.
|
|
23
|
+
* @throws {TypeError} If {@link PathOptionsMustNotExist.mustNotExist} is not a
|
|
24
|
+
* boolean.
|
|
25
|
+
* @throws {TypeError} If {@link PathOptionsBase.allowCreate} is not a boolean.
|
|
26
|
+
* @throws {TypeError} If both {@link PathOptionsMustExist.mustExist} and
|
|
27
|
+
* {@link PathOptionsMustNotExist.mustNotExist} are `true`.
|
|
17
28
|
*
|
|
18
29
|
* @example
|
|
19
30
|
* ```typescript
|
|
@@ -43,16 +54,30 @@ const node_fs = require_rolldown_runtime.__toESM(require("node:fs"));
|
|
|
43
54
|
function path(options = {}) {
|
|
44
55
|
const { metavar = "PATH", type = "either", allowCreate = false, extensions } = options;
|
|
45
56
|
(0, __optique_core_nonempty.ensureNonEmptyString)(metavar);
|
|
57
|
+
if (type !== "file" && type !== "directory" && type !== "either") throw new TypeError(`Unsupported path type: ${JSON.stringify(type)}. Expected "file", "directory", or "either".`);
|
|
58
|
+
if (extensions) {
|
|
59
|
+
for (const ext of extensions) if (!ext.startsWith(".")) throw new TypeError(`Each extension must start with a dot, got: ${JSON.stringify(ext)}`);
|
|
60
|
+
}
|
|
61
|
+
if (options.allowCreate !== void 0 && typeof options.allowCreate !== "boolean") throw new TypeError(`Expected allowCreate to be a boolean, but got ${typeof options.allowCreate}: ${String(options.allowCreate)}.`);
|
|
62
|
+
const rawOptions = options;
|
|
63
|
+
if ("mustExist" in options && rawOptions.mustExist !== void 0 && typeof rawOptions.mustExist !== "boolean") throw new TypeError(`Expected mustExist to be a boolean, but got ${typeof rawOptions.mustExist}: ${String(rawOptions.mustExist)}.`);
|
|
64
|
+
if ("mustNotExist" in options && rawOptions.mustNotExist !== void 0 && typeof rawOptions.mustNotExist !== "boolean") throw new TypeError(`Expected mustNotExist to be a boolean, but got ${typeof rawOptions.mustNotExist}: ${String(rawOptions.mustNotExist)}.`);
|
|
46
65
|
const mustExist = "mustExist" in options ? options.mustExist : false;
|
|
47
66
|
const mustNotExist = "mustNotExist" in options ? options.mustNotExist : false;
|
|
67
|
+
if (mustExist && mustNotExist) throw new TypeError("Options mustExist and mustNotExist are mutually exclusive.");
|
|
48
68
|
return {
|
|
49
69
|
$mode: "sync",
|
|
50
70
|
metavar,
|
|
51
71
|
parse(input) {
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
if (input.trim() === "") return {
|
|
73
|
+
success: false,
|
|
74
|
+
error: options.errors?.emptyPath ? typeof options.errors.emptyPath === "function" ? options.errors.emptyPath(input) : options.errors.emptyPath : __optique_core_message.message`Path must not be empty.`
|
|
75
|
+
};
|
|
76
|
+
if (type !== "directory" && extensions && extensions.length > 0) {
|
|
77
|
+
const base = /[/\\]$/.test(input) ? "" : (0, node_path.basename)(input);
|
|
78
|
+
if (!extensions.some((ext) => base.endsWith(ext))) {
|
|
79
|
+
const ext = (0, node_path.extname)(input);
|
|
80
|
+
const actualExt = ext || (base.startsWith(".") ? base : "no extension");
|
|
56
81
|
return {
|
|
57
82
|
success: false,
|
|
58
83
|
error: options.errors?.invalidExtension ? typeof options.errors.invalidExtension === "function" ? options.errors.invalidExtension(input, extensions, actualExt) : options.errors.invalidExtension : __optique_core_message.message`Expected file with extension ${(0, __optique_core_message.text)(extensions.join(", "))}, got ${(0, __optique_core_message.text)(actualExt)}.`
|
|
@@ -112,7 +137,7 @@ function path(options = {}) {
|
|
|
112
137
|
pattern: prefix,
|
|
113
138
|
type: type === "either" ? "any" : type,
|
|
114
139
|
extensions,
|
|
115
|
-
includeHidden: prefix.startsWith("."),
|
|
140
|
+
includeHidden: (0, node_path.basename)(prefix).startsWith("."),
|
|
116
141
|
description: type === "directory" ? __optique_core_message.message`Directory` : type === "file" ? __optique_core_message.message`File` : __optique_core_message.message`File or directory`
|
|
117
142
|
};
|
|
118
143
|
}
|