@optique/core 0.10.0-dev.323 → 0.10.0-dev.327
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/constructs.cjs +39 -52
- package/dist/constructs.js +39 -52
- package/dist/dependency.cjs +31 -0
- package/dist/dependency.d.cts +26 -2
- package/dist/dependency.d.ts +26 -2
- package/dist/dependency.js +30 -1
- package/dist/facade.cjs +24 -1
- package/dist/facade.d.cts +4 -0
- package/dist/facade.d.ts +4 -0
- package/dist/facade.js +24 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/mode-dispatch.cjs +38 -0
- package/dist/mode-dispatch.js +36 -0
- package/dist/modifiers.cjs +23 -42
- package/dist/modifiers.js +23 -42
- package/dist/parser.d.cts +2 -3
- package/dist/parser.d.ts +2 -3
- package/dist/primitives.cjs +10 -10
- package/dist/primitives.js +11 -11
- package/dist/program.cjs +44 -0
- package/dist/program.d.cts +124 -0
- package/dist/program.d.ts +124 -0
- package/dist/program.js +43 -0
- package/dist/registry-types.d.cts +38 -0
- package/dist/registry-types.d.ts +38 -0
- package/package.json +9 -1
package/dist/modifiers.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { formatMessage, message, text } from "./message.js";
|
|
2
2
|
import { createDependencySourceState, dependencyId, isDependencySourceState, isPendingDependencySourceState, isWrappedDependencySource, transformsDependencyValue, transformsDependencyValueMarker, wrappedDependencySourceMarker } from "./dependency.js";
|
|
3
|
+
import { dispatchByMode, dispatchIterableByMode } from "./mode-dispatch.js";
|
|
3
4
|
|
|
4
5
|
//#region src/modifiers.ts
|
|
5
6
|
/**
|
|
@@ -74,7 +75,6 @@ function processOptionalStyleResult(result, innerState, context) {
|
|
|
74
75
|
*/
|
|
75
76
|
function optional(parser) {
|
|
76
77
|
const syncParser = parser;
|
|
77
|
-
const isAsync = parser.$mode === "async";
|
|
78
78
|
function* suggestSync(context, prefix) {
|
|
79
79
|
const innerState = typeof context.state === "undefined" ? syncParser.initialState : context.state[0];
|
|
80
80
|
yield* syncParser.suggest({
|
|
@@ -107,36 +107,27 @@ function optional(parser) {
|
|
|
107
107
|
initialState: void 0,
|
|
108
108
|
...wrappedDependencyMarker,
|
|
109
109
|
parse(context) {
|
|
110
|
-
|
|
111
|
-
return parseOptionalStyleSync(context, syncParser);
|
|
110
|
+
return dispatchByMode(parser.$mode, () => parseOptionalStyleSync(context, syncParser), () => parseOptionalStyleAsync(context, parser));
|
|
112
111
|
},
|
|
113
112
|
complete(state) {
|
|
114
113
|
if (typeof state === "undefined") {
|
|
115
|
-
if (innerHasWrappedDependency && wrappedPendingState)
|
|
116
|
-
if (!isAsync) return syncParser.complete([wrappedPendingState]);
|
|
117
|
-
return parser.complete([wrappedPendingState]);
|
|
118
|
-
}
|
|
114
|
+
if (innerHasWrappedDependency && wrappedPendingState) return dispatchByMode(parser.$mode, () => syncParser.complete([wrappedPendingState]), () => parser.complete([wrappedPendingState]));
|
|
119
115
|
return {
|
|
120
116
|
success: true,
|
|
121
117
|
value: void 0
|
|
122
118
|
};
|
|
123
119
|
}
|
|
124
120
|
if (Array.isArray(state) && state.length === 1 && isPendingDependencySourceState(state[0])) {
|
|
125
|
-
if (innerHasWrappedDependency)
|
|
126
|
-
if (!isAsync) return syncParser.complete(state);
|
|
127
|
-
return parser.complete(state);
|
|
128
|
-
}
|
|
121
|
+
if (innerHasWrappedDependency) return dispatchByMode(parser.$mode, () => syncParser.complete(state), () => parser.complete(state));
|
|
129
122
|
return {
|
|
130
123
|
success: true,
|
|
131
124
|
value: void 0
|
|
132
125
|
};
|
|
133
126
|
}
|
|
134
|
-
|
|
135
|
-
return parser.complete(state[0]);
|
|
127
|
+
return dispatchByMode(parser.$mode, () => syncParser.complete(state[0]), () => parser.complete(state[0]));
|
|
136
128
|
},
|
|
137
129
|
suggest(context, prefix) {
|
|
138
|
-
|
|
139
|
-
return suggestSync(context, prefix);
|
|
130
|
+
return dispatchIterableByMode(parser.$mode, () => suggestSync(context, prefix), () => suggestAsync(context, prefix));
|
|
140
131
|
},
|
|
141
132
|
getDocFragments(state, defaultValue) {
|
|
142
133
|
const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state === void 0 ? { kind: "unavailable" } : {
|
|
@@ -183,7 +174,6 @@ var WithDefaultError = class extends Error {
|
|
|
183
174
|
};
|
|
184
175
|
function withDefault(parser, defaultValue, options) {
|
|
185
176
|
const syncParser = parser;
|
|
186
|
-
const isAsync = parser.$mode === "async";
|
|
187
177
|
function* suggestSync(context, prefix) {
|
|
188
178
|
const innerState = typeof context.state === "undefined" ? syncParser.initialState : context.state[0];
|
|
189
179
|
yield* syncParser.suggest({
|
|
@@ -213,13 +203,12 @@ function withDefault(parser, defaultValue, options) {
|
|
|
213
203
|
initialState: void 0,
|
|
214
204
|
...wrappedDependencyMarker,
|
|
215
205
|
parse(context) {
|
|
216
|
-
|
|
217
|
-
return parseOptionalStyleSync(context, syncParser);
|
|
206
|
+
return dispatchByMode(parser.$mode, () => parseOptionalStyleSync(context, syncParser), () => parseOptionalStyleAsync(context, parser));
|
|
218
207
|
},
|
|
219
208
|
complete(state) {
|
|
220
209
|
if (typeof state === "undefined") {
|
|
221
210
|
if (transformsDependencyValue(parser)) {
|
|
222
|
-
const innerResult =
|
|
211
|
+
const innerResult = dispatchByMode(parser.$mode, () => syncParser.complete(void 0), () => parser.complete(void 0));
|
|
223
212
|
const handleInnerResult = (res) => {
|
|
224
213
|
if (isDependencySourceState(res)) try {
|
|
225
214
|
const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
|
|
@@ -277,7 +266,7 @@ function withDefault(parser, defaultValue, options) {
|
|
|
277
266
|
}
|
|
278
267
|
if (isPendingDependencySourceState(state[0])) {
|
|
279
268
|
if (transformsDependencyValue(parser)) {
|
|
280
|
-
const innerResult =
|
|
269
|
+
const innerResult = dispatchByMode(parser.$mode, () => syncParser.complete(state), () => parser.complete(state));
|
|
281
270
|
const handleInnerResult = (res) => {
|
|
282
271
|
if (isDependencySourceState(res)) try {
|
|
283
272
|
const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
|
|
@@ -320,12 +309,10 @@ function withDefault(parser, defaultValue, options) {
|
|
|
320
309
|
};
|
|
321
310
|
}
|
|
322
311
|
}
|
|
323
|
-
|
|
324
|
-
return parser.complete(state[0]);
|
|
312
|
+
return dispatchByMode(parser.$mode, () => syncParser.complete(state[0]), () => parser.complete(state[0]));
|
|
325
313
|
},
|
|
326
314
|
suggest(context, prefix) {
|
|
327
|
-
|
|
328
|
-
return suggestSync(context, prefix);
|
|
315
|
+
return dispatchIterableByMode(parser.$mode, () => suggestSync(context, prefix), () => suggestAsync(context, prefix));
|
|
329
316
|
},
|
|
330
317
|
getDocFragments(state, upperDefaultValue) {
|
|
331
318
|
const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state === void 0 ? { kind: "unavailable" } : {
|
|
@@ -432,7 +419,6 @@ function map(parser, transform) {
|
|
|
432
419
|
*/
|
|
433
420
|
function multiple(parser, options = {}) {
|
|
434
421
|
const syncParser = parser;
|
|
435
|
-
const isAsync = parser.$mode === "async";
|
|
436
422
|
const { min = 0, max = Infinity } = options;
|
|
437
423
|
const parseSync = (context) => {
|
|
438
424
|
let added = context.state.length < 1;
|
|
@@ -494,11 +480,10 @@ function multiple(parser, options = {}) {
|
|
|
494
480
|
}],
|
|
495
481
|
initialState: [],
|
|
496
482
|
parse(context) {
|
|
497
|
-
|
|
498
|
-
return parseSync(context);
|
|
483
|
+
return dispatchByMode(parser.$mode, () => parseSync(context), () => parseAsync(context));
|
|
499
484
|
},
|
|
500
485
|
complete(state) {
|
|
501
|
-
|
|
486
|
+
return dispatchByMode(parser.$mode, () => {
|
|
502
487
|
const result = [];
|
|
503
488
|
for (const s of state) {
|
|
504
489
|
const valueResult = syncParser.complete(s);
|
|
@@ -509,8 +494,7 @@ function multiple(parser, options = {}) {
|
|
|
509
494
|
};
|
|
510
495
|
}
|
|
511
496
|
return validateMultipleResult(result);
|
|
512
|
-
}
|
|
513
|
-
return (async () => {
|
|
497
|
+
}, async () => {
|
|
514
498
|
const results = await Promise.all(state.map((s) => parser.complete(s)));
|
|
515
499
|
const values = [];
|
|
516
500
|
for (const valueResult of results) if (valueResult.success) values.push(valueResult.value);
|
|
@@ -519,7 +503,7 @@ function multiple(parser, options = {}) {
|
|
|
519
503
|
error: valueResult.error
|
|
520
504
|
};
|
|
521
505
|
return validateMultipleResult(values);
|
|
522
|
-
})
|
|
506
|
+
});
|
|
523
507
|
},
|
|
524
508
|
suggest(context, prefix) {
|
|
525
509
|
const innerState = context.state.length > 0 ? context.state.at(-1) : parser.initialState;
|
|
@@ -535,19 +519,18 @@ function multiple(parser, options = {}) {
|
|
|
535
519
|
if (suggestion.kind === "literal") return !selectedValues.has(suggestion.text);
|
|
536
520
|
return true;
|
|
537
521
|
};
|
|
538
|
-
|
|
522
|
+
return dispatchIterableByMode(parser.$mode, function* () {
|
|
523
|
+
for (const s of syncParser.suggest({
|
|
524
|
+
...context,
|
|
525
|
+
state: innerState
|
|
526
|
+
}, prefix)) if (shouldInclude(s)) yield s;
|
|
527
|
+
}, async function* () {
|
|
539
528
|
const suggestions = parser.suggest({
|
|
540
529
|
...context,
|
|
541
530
|
state: innerState
|
|
542
531
|
}, prefix);
|
|
543
532
|
for await (const s of suggestions) if (shouldInclude(s)) yield s;
|
|
544
|
-
}
|
|
545
|
-
return function* () {
|
|
546
|
-
for (const s of syncParser.suggest({
|
|
547
|
-
...context,
|
|
548
|
-
state: innerState
|
|
549
|
-
}, prefix)) if (shouldInclude(s)) yield s;
|
|
550
|
-
}();
|
|
533
|
+
});
|
|
551
534
|
},
|
|
552
535
|
getDocFragments(state, defaultValue) {
|
|
553
536
|
const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state.length > 0 ? {
|
|
@@ -617,7 +600,6 @@ function multiple(parser, options = {}) {
|
|
|
617
600
|
*/
|
|
618
601
|
function nonEmpty(parser) {
|
|
619
602
|
const syncParser = parser;
|
|
620
|
-
const isAsync = parser.$mode === "async";
|
|
621
603
|
const processNonEmptyResult = (result) => {
|
|
622
604
|
if (!result.success) return result;
|
|
623
605
|
if (result.consumed.length === 0) return {
|
|
@@ -643,8 +625,7 @@ function nonEmpty(parser) {
|
|
|
643
625
|
usage: parser.usage,
|
|
644
626
|
initialState: parser.initialState,
|
|
645
627
|
parse(context) {
|
|
646
|
-
|
|
647
|
-
return parseSync(context);
|
|
628
|
+
return dispatchByMode(parser.$mode, () => parseSync(context), () => parseAsync(context));
|
|
648
629
|
},
|
|
649
630
|
complete(state) {
|
|
650
631
|
return parser.complete(state);
|
package/dist/parser.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Message } from "./message.cjs";
|
|
2
2
|
import { Usage } from "./usage.cjs";
|
|
3
3
|
import { DocFragments, DocPage } from "./doc.cjs";
|
|
4
|
+
import { DependencyRegistryLike } from "./registry-types.cjs";
|
|
4
5
|
import { ValueParserResult } from "./valueparser.cjs";
|
|
5
6
|
import { ConditionalErrorOptions, ConditionalOptions, DuplicateOptionError, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OrErrorOptions, OrOptions, TupleOptions, concat, conditional, group, longestMatch, merge, object, or, tuple } from "./constructs.cjs";
|
|
6
7
|
import { MultipleErrorOptions, MultipleOptions, WithDefaultError, WithDefaultOptions, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.cjs";
|
|
@@ -191,11 +192,9 @@ interface ParserContext<TState> {
|
|
|
191
192
|
* A registry containing resolved dependency values from DependencySource parsers.
|
|
192
193
|
* This is used during shell completion to provide suggestions based on
|
|
193
194
|
* the actual dependency values that have been parsed, rather than defaults.
|
|
194
|
-
* The type is `unknown` to avoid circular dependency issues; the actual type
|
|
195
|
-
* is `DependencyRegistry` from `./dependency.ts`.
|
|
196
195
|
* @since 0.10.0
|
|
197
196
|
*/
|
|
198
|
-
readonly dependencyRegistry?:
|
|
197
|
+
readonly dependencyRegistry?: DependencyRegistryLike;
|
|
199
198
|
}
|
|
200
199
|
/**
|
|
201
200
|
* Represents a suggestion for command-line completion or guidance.
|
package/dist/parser.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Message } from "./message.js";
|
|
2
2
|
import { Usage } from "./usage.js";
|
|
3
3
|
import { DocFragments, DocPage } from "./doc.js";
|
|
4
|
+
import { DependencyRegistryLike } from "./registry-types.js";
|
|
4
5
|
import { ValueParserResult } from "./valueparser.js";
|
|
5
6
|
import { ConditionalErrorOptions, ConditionalOptions, DuplicateOptionError, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OrErrorOptions, OrOptions, TupleOptions, concat, conditional, group, longestMatch, merge, object, or, tuple } from "./constructs.js";
|
|
6
7
|
import { MultipleErrorOptions, MultipleOptions, WithDefaultError, WithDefaultOptions, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.js";
|
|
@@ -191,11 +192,9 @@ interface ParserContext<TState> {
|
|
|
191
192
|
* A registry containing resolved dependency values from DependencySource parsers.
|
|
192
193
|
* This is used during shell completion to provide suggestions based on
|
|
193
194
|
* the actual dependency values that have been parsed, rather than defaults.
|
|
194
|
-
* The type is `unknown` to avoid circular dependency issues; the actual type
|
|
195
|
-
* is `DependencyRegistry` from `./dependency.ts`.
|
|
196
195
|
* @since 0.10.0
|
|
197
196
|
*/
|
|
198
|
-
readonly dependencyRegistry?:
|
|
197
|
+
readonly dependencyRegistry?: DependencyRegistryLike;
|
|
199
198
|
}
|
|
200
199
|
/**
|
|
201
200
|
* Represents a suggestion for command-line completion or guidance.
|
package/dist/primitives.cjs
CHANGED
|
@@ -63,15 +63,15 @@ function* getSuggestionsWithDependency(valueParser, prefix, dependencyRegistry)
|
|
|
63
63
|
const derived = valueParser;
|
|
64
64
|
const suggestWithDep = derived[require_dependency.suggestWithDependency];
|
|
65
65
|
if (suggestWithDep && dependencyRegistry) {
|
|
66
|
-
const depIds = require_dependency.
|
|
67
|
-
const
|
|
68
|
-
const
|
|
66
|
+
const depIds = require_dependency.getDependencyIds(derived);
|
|
67
|
+
const defaultsFn = require_dependency.getDefaultValuesFunction(derived);
|
|
68
|
+
const defaults = defaultsFn?.();
|
|
69
69
|
const dependencyValues = [];
|
|
70
70
|
let hasAnyValue = false;
|
|
71
71
|
for (let i = 0; i < depIds.length; i++) {
|
|
72
72
|
const depId = depIds[i];
|
|
73
|
-
if (
|
|
74
|
-
dependencyValues.push(
|
|
73
|
+
if (dependencyRegistry.has(depId)) {
|
|
74
|
+
dependencyValues.push(dependencyRegistry.get(depId));
|
|
75
75
|
hasAnyValue = true;
|
|
76
76
|
} else if (defaults && i < defaults.length) dependencyValues.push(defaults[i]);
|
|
77
77
|
else {
|
|
@@ -144,15 +144,15 @@ async function* getSuggestionsWithDependencyAsync(valueParser, prefix, dependenc
|
|
|
144
144
|
const derived = valueParser;
|
|
145
145
|
const suggestWithDep = derived[require_dependency.suggestWithDependency];
|
|
146
146
|
if (suggestWithDep && dependencyRegistry) {
|
|
147
|
-
const depIds = require_dependency.
|
|
148
|
-
const
|
|
149
|
-
const
|
|
147
|
+
const depIds = require_dependency.getDependencyIds(derived);
|
|
148
|
+
const defaultsFn = require_dependency.getDefaultValuesFunction(derived);
|
|
149
|
+
const defaults = defaultsFn?.();
|
|
150
150
|
const dependencyValues = [];
|
|
151
151
|
let hasAnyValue = false;
|
|
152
152
|
for (let i = 0; i < depIds.length; i++) {
|
|
153
153
|
const depId = depIds[i];
|
|
154
|
-
if (
|
|
155
|
-
dependencyValues.push(
|
|
154
|
+
if (dependencyRegistry.has(depId)) {
|
|
155
|
+
dependencyValues.push(dependencyRegistry.get(depId));
|
|
156
156
|
hasAnyValue = true;
|
|
157
157
|
} else if (defaults && i < defaults.length) dependencyValues.push(defaults[i]);
|
|
158
158
|
else {
|
package/dist/primitives.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { message, metavar, optionName, optionNames } from "./message.js";
|
|
2
|
-
import { createDeferredParseState, createDependencySourceState, createPendingDependencySourceState,
|
|
2
|
+
import { createDeferredParseState, createDependencySourceState, createPendingDependencySourceState, dependencyId, getDefaultValuesFunction, getDependencyIds, isDeferredParseState, isDependencySource, isDependencySourceState, isDerivedValueParser, isPendingDependencySourceState, suggestWithDependency } from "./dependency.js";
|
|
3
3
|
import { extractCommandNames, extractOptionNames } from "./usage.js";
|
|
4
4
|
import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, findSimilar } from "./suggestion.js";
|
|
5
5
|
import { isValueParser } from "./valueparser.js";
|
|
@@ -63,15 +63,15 @@ function* getSuggestionsWithDependency(valueParser, prefix, dependencyRegistry)
|
|
|
63
63
|
const derived = valueParser;
|
|
64
64
|
const suggestWithDep = derived[suggestWithDependency];
|
|
65
65
|
if (suggestWithDep && dependencyRegistry) {
|
|
66
|
-
const depIds =
|
|
67
|
-
const
|
|
68
|
-
const
|
|
66
|
+
const depIds = getDependencyIds(derived);
|
|
67
|
+
const defaultsFn = getDefaultValuesFunction(derived);
|
|
68
|
+
const defaults = defaultsFn?.();
|
|
69
69
|
const dependencyValues = [];
|
|
70
70
|
let hasAnyValue = false;
|
|
71
71
|
for (let i = 0; i < depIds.length; i++) {
|
|
72
72
|
const depId = depIds[i];
|
|
73
|
-
if (
|
|
74
|
-
dependencyValues.push(
|
|
73
|
+
if (dependencyRegistry.has(depId)) {
|
|
74
|
+
dependencyValues.push(dependencyRegistry.get(depId));
|
|
75
75
|
hasAnyValue = true;
|
|
76
76
|
} else if (defaults && i < defaults.length) dependencyValues.push(defaults[i]);
|
|
77
77
|
else {
|
|
@@ -144,15 +144,15 @@ async function* getSuggestionsWithDependencyAsync(valueParser, prefix, dependenc
|
|
|
144
144
|
const derived = valueParser;
|
|
145
145
|
const suggestWithDep = derived[suggestWithDependency];
|
|
146
146
|
if (suggestWithDep && dependencyRegistry) {
|
|
147
|
-
const depIds =
|
|
148
|
-
const
|
|
149
|
-
const
|
|
147
|
+
const depIds = getDependencyIds(derived);
|
|
148
|
+
const defaultsFn = getDefaultValuesFunction(derived);
|
|
149
|
+
const defaults = defaultsFn?.();
|
|
150
150
|
const dependencyValues = [];
|
|
151
151
|
let hasAnyValue = false;
|
|
152
152
|
for (let i = 0; i < depIds.length; i++) {
|
|
153
153
|
const depId = depIds[i];
|
|
154
|
-
if (
|
|
155
|
-
dependencyValues.push(
|
|
154
|
+
if (dependencyRegistry.has(depId)) {
|
|
155
|
+
dependencyValues.push(dependencyRegistry.get(depId));
|
|
156
156
|
hasAnyValue = true;
|
|
157
157
|
} else if (defaults && i < defaults.length) dependencyValues.push(defaults[i]);
|
|
158
158
|
else {
|
package/dist/program.cjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/program.ts
|
|
3
|
+
/**
|
|
4
|
+
* Defines a CLI program with a parser and metadata.
|
|
5
|
+
*
|
|
6
|
+
* This is a helper function that returns its argument unchanged, but provides
|
|
7
|
+
* automatic type inference for the program. This eliminates the need to
|
|
8
|
+
* manually specify type parameters when defining a program.
|
|
9
|
+
*
|
|
10
|
+
* @template M - The mode of the parser ("sync" or "async").
|
|
11
|
+
* @template T - The type of value produced by the parser.
|
|
12
|
+
* @param program - The program definition with parser and metadata.
|
|
13
|
+
* @returns The same program object with inferred types.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { defineProgram } from "@optique/core/program";
|
|
18
|
+
* import { object } from "@optique/core/constructs";
|
|
19
|
+
* import { option } from "@optique/core/primitives";
|
|
20
|
+
* import { string } from "@optique/core/valueparser";
|
|
21
|
+
* import { message } from "@optique/core/message";
|
|
22
|
+
*
|
|
23
|
+
* const prog = defineProgram({
|
|
24
|
+
* parser: object({
|
|
25
|
+
* name: option("-n", "--name", string()),
|
|
26
|
+
* }),
|
|
27
|
+
* metadata: {
|
|
28
|
+
* name: "myapp",
|
|
29
|
+
* version: "1.0.0",
|
|
30
|
+
* brief: message`A simple CLI tool`,
|
|
31
|
+
* },
|
|
32
|
+
* });
|
|
33
|
+
* // TypeScript automatically infers:
|
|
34
|
+
* // Program<"sync", { readonly name: string }>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @since 0.11.0
|
|
38
|
+
*/
|
|
39
|
+
function defineProgram(program) {
|
|
40
|
+
return program;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
exports.defineProgram = defineProgram;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Message } from "./message.cjs";
|
|
2
|
+
import { Mode, Parser } from "./parser.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/program.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Metadata for a CLI program.
|
|
8
|
+
*
|
|
9
|
+
* @since 0.11.0
|
|
10
|
+
*/
|
|
11
|
+
interface ProgramMetadata {
|
|
12
|
+
/**
|
|
13
|
+
* The name of the program.
|
|
14
|
+
*/
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/**
|
|
17
|
+
* The version of the program.
|
|
18
|
+
*/
|
|
19
|
+
readonly version?: string;
|
|
20
|
+
/**
|
|
21
|
+
* A brief one-line description of the program.
|
|
22
|
+
*/
|
|
23
|
+
readonly brief?: Message;
|
|
24
|
+
/**
|
|
25
|
+
* A detailed description of the program.
|
|
26
|
+
*/
|
|
27
|
+
readonly description?: Message;
|
|
28
|
+
/**
|
|
29
|
+
* Author information.
|
|
30
|
+
*/
|
|
31
|
+
readonly author?: Message;
|
|
32
|
+
/**
|
|
33
|
+
* Information about where to report bugs.
|
|
34
|
+
*/
|
|
35
|
+
readonly bugs?: Message;
|
|
36
|
+
/**
|
|
37
|
+
* Usage examples for the program.
|
|
38
|
+
*/
|
|
39
|
+
readonly examples?: Message;
|
|
40
|
+
/**
|
|
41
|
+
* Footer text shown at the end of help output.
|
|
42
|
+
*/
|
|
43
|
+
readonly footer?: Message;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A CLI program consisting of a parser and its metadata.
|
|
47
|
+
*
|
|
48
|
+
* This interface bundles a parser with its metadata (name, version,
|
|
49
|
+
* description, etc.), providing a single source of truth for CLI application
|
|
50
|
+
* information that can be shared across different functionalities.
|
|
51
|
+
*
|
|
52
|
+
* @template M - The mode of the parser ("sync" or "async").
|
|
53
|
+
* @template T - The type of value produced by the parser.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import type { Program } from "@optique/core/program";
|
|
58
|
+
* import { command, option, string } from "@optique/core";
|
|
59
|
+
* import { message } from "@optique/core/message";
|
|
60
|
+
*
|
|
61
|
+
* const prog: Program<"sync", { name: string }> = {
|
|
62
|
+
* parser: command("greet", () => ({
|
|
63
|
+
* name: option("name", string()).default("World"),
|
|
64
|
+
* })),
|
|
65
|
+
* metadata: {
|
|
66
|
+
* name: "greet",
|
|
67
|
+
* version: "1.0.0",
|
|
68
|
+
* brief: message`A simple greeting CLI tool`,
|
|
69
|
+
* author: message`Jane Doe <jane@example.com>`,
|
|
70
|
+
* },
|
|
71
|
+
* };
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @since 0.11.0
|
|
75
|
+
*/
|
|
76
|
+
interface Program<M extends Mode, T> {
|
|
77
|
+
/**
|
|
78
|
+
* The parser for the program.
|
|
79
|
+
*/
|
|
80
|
+
readonly parser: Parser<M, T, unknown>;
|
|
81
|
+
/**
|
|
82
|
+
* Metadata about the program.
|
|
83
|
+
*/
|
|
84
|
+
readonly metadata: ProgramMetadata;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Defines a CLI program with a parser and metadata.
|
|
88
|
+
*
|
|
89
|
+
* This is a helper function that returns its argument unchanged, but provides
|
|
90
|
+
* automatic type inference for the program. This eliminates the need to
|
|
91
|
+
* manually specify type parameters when defining a program.
|
|
92
|
+
*
|
|
93
|
+
* @template M - The mode of the parser ("sync" or "async").
|
|
94
|
+
* @template T - The type of value produced by the parser.
|
|
95
|
+
* @param program - The program definition with parser and metadata.
|
|
96
|
+
* @returns The same program object with inferred types.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* import { defineProgram } from "@optique/core/program";
|
|
101
|
+
* import { object } from "@optique/core/constructs";
|
|
102
|
+
* import { option } from "@optique/core/primitives";
|
|
103
|
+
* import { string } from "@optique/core/valueparser";
|
|
104
|
+
* import { message } from "@optique/core/message";
|
|
105
|
+
*
|
|
106
|
+
* const prog = defineProgram({
|
|
107
|
+
* parser: object({
|
|
108
|
+
* name: option("-n", "--name", string()),
|
|
109
|
+
* }),
|
|
110
|
+
* metadata: {
|
|
111
|
+
* name: "myapp",
|
|
112
|
+
* version: "1.0.0",
|
|
113
|
+
* brief: message`A simple CLI tool`,
|
|
114
|
+
* },
|
|
115
|
+
* });
|
|
116
|
+
* // TypeScript automatically infers:
|
|
117
|
+
* // Program<"sync", { readonly name: string }>
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @since 0.11.0
|
|
121
|
+
*/
|
|
122
|
+
declare function defineProgram<M extends Mode, T>(program: Program<M, T>): Program<M, T>;
|
|
123
|
+
//#endregion
|
|
124
|
+
export { Program, ProgramMetadata, defineProgram };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Message } from "./message.js";
|
|
2
|
+
import { Mode, Parser } from "./parser.js";
|
|
3
|
+
|
|
4
|
+
//#region src/program.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Metadata for a CLI program.
|
|
8
|
+
*
|
|
9
|
+
* @since 0.11.0
|
|
10
|
+
*/
|
|
11
|
+
interface ProgramMetadata {
|
|
12
|
+
/**
|
|
13
|
+
* The name of the program.
|
|
14
|
+
*/
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/**
|
|
17
|
+
* The version of the program.
|
|
18
|
+
*/
|
|
19
|
+
readonly version?: string;
|
|
20
|
+
/**
|
|
21
|
+
* A brief one-line description of the program.
|
|
22
|
+
*/
|
|
23
|
+
readonly brief?: Message;
|
|
24
|
+
/**
|
|
25
|
+
* A detailed description of the program.
|
|
26
|
+
*/
|
|
27
|
+
readonly description?: Message;
|
|
28
|
+
/**
|
|
29
|
+
* Author information.
|
|
30
|
+
*/
|
|
31
|
+
readonly author?: Message;
|
|
32
|
+
/**
|
|
33
|
+
* Information about where to report bugs.
|
|
34
|
+
*/
|
|
35
|
+
readonly bugs?: Message;
|
|
36
|
+
/**
|
|
37
|
+
* Usage examples for the program.
|
|
38
|
+
*/
|
|
39
|
+
readonly examples?: Message;
|
|
40
|
+
/**
|
|
41
|
+
* Footer text shown at the end of help output.
|
|
42
|
+
*/
|
|
43
|
+
readonly footer?: Message;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A CLI program consisting of a parser and its metadata.
|
|
47
|
+
*
|
|
48
|
+
* This interface bundles a parser with its metadata (name, version,
|
|
49
|
+
* description, etc.), providing a single source of truth for CLI application
|
|
50
|
+
* information that can be shared across different functionalities.
|
|
51
|
+
*
|
|
52
|
+
* @template M - The mode of the parser ("sync" or "async").
|
|
53
|
+
* @template T - The type of value produced by the parser.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import type { Program } from "@optique/core/program";
|
|
58
|
+
* import { command, option, string } from "@optique/core";
|
|
59
|
+
* import { message } from "@optique/core/message";
|
|
60
|
+
*
|
|
61
|
+
* const prog: Program<"sync", { name: string }> = {
|
|
62
|
+
* parser: command("greet", () => ({
|
|
63
|
+
* name: option("name", string()).default("World"),
|
|
64
|
+
* })),
|
|
65
|
+
* metadata: {
|
|
66
|
+
* name: "greet",
|
|
67
|
+
* version: "1.0.0",
|
|
68
|
+
* brief: message`A simple greeting CLI tool`,
|
|
69
|
+
* author: message`Jane Doe <jane@example.com>`,
|
|
70
|
+
* },
|
|
71
|
+
* };
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @since 0.11.0
|
|
75
|
+
*/
|
|
76
|
+
interface Program<M extends Mode, T> {
|
|
77
|
+
/**
|
|
78
|
+
* The parser for the program.
|
|
79
|
+
*/
|
|
80
|
+
readonly parser: Parser<M, T, unknown>;
|
|
81
|
+
/**
|
|
82
|
+
* Metadata about the program.
|
|
83
|
+
*/
|
|
84
|
+
readonly metadata: ProgramMetadata;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Defines a CLI program with a parser and metadata.
|
|
88
|
+
*
|
|
89
|
+
* This is a helper function that returns its argument unchanged, but provides
|
|
90
|
+
* automatic type inference for the program. This eliminates the need to
|
|
91
|
+
* manually specify type parameters when defining a program.
|
|
92
|
+
*
|
|
93
|
+
* @template M - The mode of the parser ("sync" or "async").
|
|
94
|
+
* @template T - The type of value produced by the parser.
|
|
95
|
+
* @param program - The program definition with parser and metadata.
|
|
96
|
+
* @returns The same program object with inferred types.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* import { defineProgram } from "@optique/core/program";
|
|
101
|
+
* import { object } from "@optique/core/constructs";
|
|
102
|
+
* import { option } from "@optique/core/primitives";
|
|
103
|
+
* import { string } from "@optique/core/valueparser";
|
|
104
|
+
* import { message } from "@optique/core/message";
|
|
105
|
+
*
|
|
106
|
+
* const prog = defineProgram({
|
|
107
|
+
* parser: object({
|
|
108
|
+
* name: option("-n", "--name", string()),
|
|
109
|
+
* }),
|
|
110
|
+
* metadata: {
|
|
111
|
+
* name: "myapp",
|
|
112
|
+
* version: "1.0.0",
|
|
113
|
+
* brief: message`A simple CLI tool`,
|
|
114
|
+
* },
|
|
115
|
+
* });
|
|
116
|
+
* // TypeScript automatically infers:
|
|
117
|
+
* // Program<"sync", { readonly name: string }>
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @since 0.11.0
|
|
121
|
+
*/
|
|
122
|
+
declare function defineProgram<M extends Mode, T>(program: Program<M, T>): Program<M, T>;
|
|
123
|
+
//#endregion
|
|
124
|
+
export { Program, ProgramMetadata, defineProgram };
|
package/dist/program.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/program.ts
|
|
2
|
+
/**
|
|
3
|
+
* Defines a CLI program with a parser and metadata.
|
|
4
|
+
*
|
|
5
|
+
* This is a helper function that returns its argument unchanged, but provides
|
|
6
|
+
* automatic type inference for the program. This eliminates the need to
|
|
7
|
+
* manually specify type parameters when defining a program.
|
|
8
|
+
*
|
|
9
|
+
* @template M - The mode of the parser ("sync" or "async").
|
|
10
|
+
* @template T - The type of value produced by the parser.
|
|
11
|
+
* @param program - The program definition with parser and metadata.
|
|
12
|
+
* @returns The same program object with inferred types.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { defineProgram } from "@optique/core/program";
|
|
17
|
+
* import { object } from "@optique/core/constructs";
|
|
18
|
+
* import { option } from "@optique/core/primitives";
|
|
19
|
+
* import { string } from "@optique/core/valueparser";
|
|
20
|
+
* import { message } from "@optique/core/message";
|
|
21
|
+
*
|
|
22
|
+
* const prog = defineProgram({
|
|
23
|
+
* parser: object({
|
|
24
|
+
* name: option("-n", "--name", string()),
|
|
25
|
+
* }),
|
|
26
|
+
* metadata: {
|
|
27
|
+
* name: "myapp",
|
|
28
|
+
* version: "1.0.0",
|
|
29
|
+
* brief: message`A simple CLI tool`,
|
|
30
|
+
* },
|
|
31
|
+
* });
|
|
32
|
+
* // TypeScript automatically infers:
|
|
33
|
+
* // Program<"sync", { readonly name: string }>
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @since 0.11.0
|
|
37
|
+
*/
|
|
38
|
+
function defineProgram(program) {
|
|
39
|
+
return program;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { defineProgram };
|