cli-kiss 0.2.6 → 0.2.8
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 +62 -4
- package/dist/index.d.ts +135 -128
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +1 -1
- package/docs/.vitepress/theme/Layout.vue +16 -0
- package/docs/.vitepress/theme/index.ts +5 -1
- package/docs/.vitepress/theme/style.css +5 -1
- package/docs/guide/02_commands.md +1 -1
- package/docs/guide/03_options.md +11 -11
- package/docs/guide/05_input_types.md +9 -10
- package/docs/guide/06_run_as_cli.md +1 -1
- package/docs/index.md +2 -2
- package/docs/public/favicon.ico +0 -0
- package/docs/public/logo.png +0 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/lib/Command.ts +50 -30
- package/src/lib/Operation.ts +29 -21
- package/src/lib/Option.ts +198 -133
- package/src/lib/Positional.ts +46 -24
- package/src/lib/Reader.ts +194 -207
- package/src/lib/Run.ts +19 -8
- package/src/lib/Suggest.ts +78 -0
- package/src/lib/Type.ts +46 -48
- package/src/lib/Typo.ts +72 -47
- package/src/lib/Usage.ts +13 -13
- package/tests/unit.Reader.commons.ts +92 -116
- package/tests/unit.Reader.parsings.ts +14 -26
- package/tests/unit.Reader.shortBig.ts +81 -96
- package/tests/unit.command.aliases.ts +100 -0
- package/tests/unit.command.execute.ts +1 -1
- package/tests/unit.command.usage.ts +12 -6
- package/tests/unit.fuzzed.alternatives.ts +43 -0
- package/tests/unit.runner.colors.ts +11 -35
- package/tests/unit.runner.cycle.ts +181 -128
- package/tests/unit.runner.errors.ts +26 -19
- package/docs/public/hero.png +0 -0
- package/tests/unit.Reader.aliases.ts +0 -62
|
@@ -2,7 +2,7 @@ import { defineConfig } from "vitepress";
|
|
|
2
2
|
|
|
3
3
|
export default defineConfig({
|
|
4
4
|
description: "Full-featured TypeScript CLI builder. No bloat, no dependency.",
|
|
5
|
-
title: "cli-kiss
|
|
5
|
+
title: "cli-kiss",
|
|
6
6
|
base: "/cli-kiss/",
|
|
7
7
|
head: [
|
|
8
8
|
["link", { rel: "icon", href: "/cli-kiss/favicon.ico" }],
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import DefaultTheme from 'vitepress/theme'
|
|
3
|
+
const { Layout } = DefaultTheme
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<Layout>
|
|
8
|
+
<template #nav-bar-title-before>
|
|
9
|
+
<img
|
|
10
|
+
src="/logo.png"
|
|
11
|
+
alt="logo"
|
|
12
|
+
style="width:32px;height:32px;margin-right:8px;display:block;"
|
|
13
|
+
>
|
|
14
|
+
</template>
|
|
15
|
+
</Layout>
|
|
16
|
+
</template>
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
--vp-home-hero-name-color: transparent;
|
|
4
4
|
--vp-home-hero-name-background: linear-gradient(-50deg, #ff003caa 30%, #459900aa 70%);
|
|
5
5
|
*/
|
|
6
|
-
--vp-home-hero-image-background-image: linear-gradient(
|
|
6
|
+
--vp-home-hero-image-background-image: linear-gradient(
|
|
7
|
+
-50deg,
|
|
8
|
+
#ff003c88 25%,
|
|
9
|
+
#008732aa 60%
|
|
10
|
+
);
|
|
7
11
|
--vp-home-hero-image-filter: blur(60px);
|
|
8
12
|
}
|
|
@@ -87,7 +87,7 @@ const authenticatedDeploy = commandChained(
|
|
|
87
87
|
long: "token",
|
|
88
88
|
type: type("secret"),
|
|
89
89
|
description: "API token",
|
|
90
|
-
|
|
90
|
+
fallbackValueIfAbsent: function () {
|
|
91
91
|
const t = process.env.API_TOKEN;
|
|
92
92
|
if (!t) throw new Error("API_TOKEN env var is required");
|
|
93
93
|
return t;
|
package/docs/guide/03_options.md
CHANGED
|
@@ -44,7 +44,7 @@ const output = optionSingleValue({
|
|
|
44
44
|
short: "o",
|
|
45
45
|
type: typePath(),
|
|
46
46
|
description: "Output directory",
|
|
47
|
-
|
|
47
|
+
fallbackValueIfAbsent: () => "dist/",
|
|
48
48
|
});
|
|
49
49
|
// --output dist/ → "dist/"
|
|
50
50
|
// --output=dist/ → "dist/"
|
|
@@ -52,16 +52,16 @@ const output = optionSingleValue({
|
|
|
52
52
|
// (absent) → "dist/"
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
| Parameter
|
|
56
|
-
|
|
|
57
|
-
| `long`
|
|
58
|
-
| `short`
|
|
59
|
-
| `type`
|
|
60
|
-
| `description`
|
|
61
|
-
| `hint`
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `aliases`
|
|
55
|
+
| Parameter | Type | Description |
|
|
56
|
+
| -------------------------- | --------------------- | ---------------------------------------------------------------------------- |
|
|
57
|
+
| `long` | `string` | Long option name |
|
|
58
|
+
| `short` | `string?` | Short option name |
|
|
59
|
+
| `type` | `Type<Value>` | Decoder for the value |
|
|
60
|
+
| `description` | `string?` | Help text |
|
|
61
|
+
| `hint` | `string?` | Short note in parentheses |
|
|
62
|
+
| `fallbackValueIfAbsent` | `() => Value` | Value when option is absent — **throw** to make it required |
|
|
63
|
+
| `impliedValueIfNotInlined` | `() => Value?` | Value when option is present but has no inline value (e.g. `--output` alone) |
|
|
64
|
+
| `aliases` | `{ longs?, shorts? }` | Additional names |
|
|
65
65
|
|
|
66
66
|
## `optionRepeatable` — collect multiple values
|
|
67
67
|
|
|
@@ -47,8 +47,7 @@ Accepts only a fixed set of strings (case-insensitive by default):
|
|
|
47
47
|
const typeEnv = typeChoice("environment", ["dev", "staging", "prod"]);
|
|
48
48
|
typeEnv.decoder("prod"); // → "prod"
|
|
49
49
|
typeEnv.decoder("PROD"); // → "prod" (case-insensitive)
|
|
50
|
-
typeEnv.decoder("unknown");
|
|
51
|
-
// Error: Invalid value: "unknown" (expected one of: "dev" | "staging" | "prod")
|
|
50
|
+
typeEnv.decoder("unknown"); // Error: Invalid value: "unknown"
|
|
52
51
|
```
|
|
53
52
|
|
|
54
53
|
Pass `true` as third argument to make matching case-sensitive.
|
|
@@ -58,9 +57,9 @@ Pass `true` as third argument to make matching case-sensitive.
|
|
|
58
57
|
Splits a string into a fixed-length typed tuple:
|
|
59
58
|
|
|
60
59
|
```ts
|
|
61
|
-
const typePoint = typeTuple([typeNumber(), typeNumber()]);
|
|
60
|
+
const typePoint = typeTuple([typeNumber("a"), typeNumber("b")]);
|
|
62
61
|
typePoint.decoder("3.14,2.71"); // → [3.14, 2.71]
|
|
63
|
-
typePoint.decoder("x,2"); // → Error: at 0:
|
|
62
|
+
typePoint.decoder("x,2"); // → Error: at 0: a: Unable to parse: "x"
|
|
64
63
|
```
|
|
65
64
|
|
|
66
65
|
The default separator is `","`. Pass a second argument to change it:
|
|
@@ -75,9 +74,9 @@ typeTuple([type("name"), typeNumber()], ":");
|
|
|
75
74
|
Splits a string into an array of typed values:
|
|
76
75
|
|
|
77
76
|
```ts
|
|
78
|
-
const typeNumbers = typeList(typeNumber());
|
|
77
|
+
const typeNumbers = typeList(typeNumber("v"));
|
|
79
78
|
typeNumbers.decoder("1,2,3"); // → [1, 2, 3]
|
|
80
|
-
typeNumbers.decoder("1,x,3"); // → Error: at 1:
|
|
79
|
+
typeNumbers.decoder("1,x,3"); // → Error: at 1: v: Unable to parse: "x"
|
|
81
80
|
```
|
|
82
81
|
|
|
83
82
|
Custom separator:
|
|
@@ -103,8 +102,8 @@ const typePort = typeConverted("port", typeNumber(), (n) => {
|
|
|
103
102
|
if (n < 1 || n > 65535) throw new Error("Out of range");
|
|
104
103
|
return n;
|
|
105
104
|
});
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
typePort.decoder("8080"); // → 8080
|
|
106
|
+
typePort.decoder("99999"); // → Error: Out of range
|
|
108
107
|
```
|
|
109
108
|
|
|
110
109
|
## `typeRenamed` — rename a type
|
|
@@ -129,6 +128,6 @@ const typeHexColor: Type<string> = {
|
|
|
129
128
|
throw new Error(`Not a valid hex color: "${value}"`);
|
|
130
129
|
},
|
|
131
130
|
};
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
typeHexColor.decoder("#ff0000"); // → "#ff0000"
|
|
132
|
+
typeHexColor.decoder("red"); // → Error: Not a valid hex color: "red"
|
|
134
133
|
```
|
|
@@ -67,7 +67,7 @@ const rootCmd = commandWithSubcommands(
|
|
|
67
67
|
long: "db",
|
|
68
68
|
type: typeUrl(),
|
|
69
69
|
description: "Database URL",
|
|
70
|
-
|
|
70
|
+
fallbackValueIfAbsent: () => new URL("postgres://localhost/mydb"),
|
|
71
71
|
}),
|
|
72
72
|
},
|
|
73
73
|
positionals: [],
|
package/docs/index.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
layout: home
|
|
3
3
|
|
|
4
4
|
hero:
|
|
5
|
-
name: CLI-
|
|
5
|
+
name: CLI-kiss
|
|
6
6
|
text: CLI for TypeScript.
|
|
7
7
|
|
|
8
8
|
tagline:
|
|
@@ -10,7 +10,7 @@ hero:
|
|
|
10
10
|
Simple and Stupid, it just does the job.
|
|
11
11
|
|
|
12
12
|
image:
|
|
13
|
-
src: /
|
|
13
|
+
src: /logo.png
|
|
14
14
|
|
|
15
15
|
actions:
|
|
16
16
|
- theme: brand
|
package/docs/public/favicon.ico
CHANGED
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/lib/Command.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Operation } from "./Operation";
|
|
2
2
|
import { ReaderArgs } from "./Reader";
|
|
3
|
+
import { suggestTextPushMessage } from "./Suggest";
|
|
3
4
|
import {
|
|
4
5
|
TypoError,
|
|
5
6
|
TypoString,
|
|
7
|
+
typoStyleConstants,
|
|
6
8
|
typoStyleQuote,
|
|
7
9
|
typoStyleUserInput,
|
|
8
10
|
TypoText,
|
|
@@ -42,7 +44,7 @@ export type CommandDecoder<Context, Result> = {
|
|
|
42
44
|
/**
|
|
43
45
|
* Creates a ready-to-execute {@link CommandInterpreter}.
|
|
44
46
|
*
|
|
45
|
-
* @throws
|
|
47
|
+
* @throws if parsing or decoding failed.
|
|
46
48
|
*/
|
|
47
49
|
decodeAndMakeInterpreter(): CommandInterpreter<Context, Result>;
|
|
48
50
|
};
|
|
@@ -80,6 +82,7 @@ export type CommandInformation = {
|
|
|
80
82
|
* Shown in the `Examples:` section.
|
|
81
83
|
*/
|
|
82
84
|
examples?: Array<{
|
|
85
|
+
// TODO - a nicer example system, maybe with --help=example support
|
|
83
86
|
/**
|
|
84
87
|
* Explanation shown above the example.
|
|
85
88
|
*/
|
|
@@ -115,13 +118,13 @@ export type CommandInformation = {
|
|
|
115
118
|
* const greet = command(
|
|
116
119
|
* { description: "Greet a user" },
|
|
117
120
|
* operation(
|
|
118
|
-
* {
|
|
121
|
+
* { positionals: [positionalRequired({ type: type("name") })] },
|
|
119
122
|
* async (_ctx, { positionals: [name] }) => console.log(`Hello, ${name}!`),
|
|
120
123
|
* ),
|
|
121
124
|
* );
|
|
122
125
|
* ```
|
|
123
126
|
*/
|
|
124
|
-
export function command<Context, Result>(
|
|
127
|
+
export function command<Context, Result = void>(
|
|
125
128
|
information: CommandInformation,
|
|
126
129
|
operation: Operation<Context, Result>,
|
|
127
130
|
): Command<Context, Result> {
|
|
@@ -134,12 +137,11 @@ export function command<Context, Result>(
|
|
|
134
137
|
const operationDecoder = operation.consumeAndMakeDecoder(readerArgs);
|
|
135
138
|
const endPositional = readerArgs.consumePositional();
|
|
136
139
|
if (endPositional !== undefined) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
);
|
|
140
|
+
const errorText = new TypoText();
|
|
141
|
+
errorText.push(new TypoString(`Unexpected argument: `));
|
|
142
|
+
errorText.push(new TypoString(`"${endPositional}"`, typoStyleQuote));
|
|
143
|
+
errorText.push(new TypoString(`.`));
|
|
144
|
+
throw new TypoError(errorText);
|
|
143
145
|
}
|
|
144
146
|
return {
|
|
145
147
|
generateUsage: () => generateUsageLeaf(information, operation),
|
|
@@ -166,7 +168,8 @@ export function command<Context, Result>(
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
/**
|
|
169
|
-
* Creates a command that runs `operation` first,
|
|
171
|
+
* Creates a command that runs `operation` first,
|
|
172
|
+
* then dispatches result to a named subcommand.
|
|
170
173
|
*
|
|
171
174
|
* @typeParam Context - Context accepted by `operation`.
|
|
172
175
|
* @typeParam Payload - Output of `operation`; becomes the subcommand's context.
|
|
@@ -189,11 +192,16 @@ export function command<Context, Result>(
|
|
|
189
192
|
* );
|
|
190
193
|
* ```
|
|
191
194
|
*/
|
|
192
|
-
export function commandWithSubcommands<Context, Payload, Result>(
|
|
195
|
+
export function commandWithSubcommands<Context, Payload, Result = void>(
|
|
193
196
|
information: CommandInformation,
|
|
194
197
|
operation: Operation<Context, Payload>,
|
|
195
198
|
subcommands: { [subcommand: string]: Command<Payload, Result> },
|
|
196
199
|
): Command<Context, Result> {
|
|
200
|
+
// TODO - forbid subcommands that start with a "-" ?
|
|
201
|
+
const subcommandNames = Object.keys(subcommands);
|
|
202
|
+
if (subcommandNames.length === 0) {
|
|
203
|
+
throw new Error("At least one subcommand is required");
|
|
204
|
+
}
|
|
197
205
|
return {
|
|
198
206
|
getInformation() {
|
|
199
207
|
return information;
|
|
@@ -203,22 +211,21 @@ export function commandWithSubcommands<Context, Payload, Result>(
|
|
|
203
211
|
const operationDecoder = operation.consumeAndMakeDecoder(readerArgs);
|
|
204
212
|
const subcommandName = readerArgs.consumePositional();
|
|
205
213
|
if (subcommandName === undefined) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
);
|
|
214
|
+
const errorText = new TypoText();
|
|
215
|
+
errorText.push(new TypoString(`<subcommand>`, typoStyleUserInput));
|
|
216
|
+
errorText.push(new TypoString(`: Missing argument.`));
|
|
217
|
+
suggestSubcommandNames(errorText, "", subcommandNames);
|
|
218
|
+
throw new TypoError(errorText);
|
|
212
219
|
}
|
|
213
220
|
const subcommandInput = subcommands[subcommandName];
|
|
214
221
|
if (subcommandInput === undefined) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
);
|
|
222
|
+
const errorText = new TypoText();
|
|
223
|
+
errorText.push(new TypoString(`<subcommand>`, typoStyleUserInput));
|
|
224
|
+
errorText.push(new TypoString(`: Unknown name: `));
|
|
225
|
+
errorText.push(new TypoString(`"${subcommandName}"`, typoStyleQuote));
|
|
226
|
+
errorText.push(new TypoString(`.`));
|
|
227
|
+
suggestSubcommandNames(errorText, subcommandName, subcommandNames);
|
|
228
|
+
throw new TypoError(errorText);
|
|
222
229
|
}
|
|
223
230
|
const subcommandDecoder =
|
|
224
231
|
subcommandInput.consumeAndMakeDecoder(readerArgs);
|
|
@@ -269,8 +276,8 @@ export function commandWithSubcommands<Context, Payload, Result>(
|
|
|
269
276
|
}
|
|
270
277
|
|
|
271
278
|
/**
|
|
272
|
-
* Chains an {@link Operation} and a {@link Command}: `operation` runs first,
|
|
273
|
-
* output becomes `subcommand`'s context. No token is consumed for routing.
|
|
279
|
+
* Chains an {@link Operation} and a {@link Command}: `operation` runs first,
|
|
280
|
+
* its output becomes `subcommand`'s context. No token is consumed for routing.
|
|
274
281
|
*
|
|
275
282
|
* @typeParam Context - Context accepted by `operation`.
|
|
276
283
|
* @typeParam Payload - Output of `operation`; becomes `subcommand`'s context.
|
|
@@ -281,7 +288,7 @@ export function commandWithSubcommands<Context, Payload, Result>(
|
|
|
281
288
|
* @param subcommand - Runs after `operation`.
|
|
282
289
|
* @returns A {@link Command} composing both stages.
|
|
283
290
|
*/
|
|
284
|
-
export function commandChained<Context, Payload, Result>(
|
|
291
|
+
export function commandChained<Context, Payload, Result = void>(
|
|
285
292
|
information: CommandInformation,
|
|
286
293
|
operation: Operation<Context, Payload>,
|
|
287
294
|
subcommand: Command<Payload, Result>,
|
|
@@ -341,12 +348,25 @@ function generateUsageLeaf(
|
|
|
341
348
|
): UsageCommand {
|
|
342
349
|
const { positionals, options } = operation.generateUsage();
|
|
343
350
|
return {
|
|
344
|
-
segments: positionals.map((
|
|
345
|
-
positional: positional.label,
|
|
346
|
-
})),
|
|
351
|
+
segments: positionals.map((p) => ({ positional: p.label })),
|
|
347
352
|
information,
|
|
348
353
|
positionals,
|
|
349
354
|
subcommands: [],
|
|
350
355
|
options,
|
|
351
356
|
};
|
|
352
357
|
}
|
|
358
|
+
|
|
359
|
+
function suggestSubcommandNames(
|
|
360
|
+
errorText: TypoText,
|
|
361
|
+
input: string,
|
|
362
|
+
subcommandNames: Array<string> = [],
|
|
363
|
+
) {
|
|
364
|
+
suggestTextPushMessage(
|
|
365
|
+
errorText,
|
|
366
|
+
input,
|
|
367
|
+
subcommandNames.map((subcommandName) => ({
|
|
368
|
+
reference: subcommandName,
|
|
369
|
+
hint: new TypoString(subcommandName, typoStyleConstants),
|
|
370
|
+
})),
|
|
371
|
+
);
|
|
372
|
+
}
|
package/src/lib/Operation.ts
CHANGED
|
@@ -44,7 +44,7 @@ export type OperationDecoder<Context, Result> = {
|
|
|
44
44
|
/**
|
|
45
45
|
* Creates a ready-to-execute {@link OperationInterpreter}.
|
|
46
46
|
*
|
|
47
|
-
* @throws
|
|
47
|
+
* @throws if parsing or decoding failed.
|
|
48
48
|
*/
|
|
49
49
|
decodeAndMakeInterpreter(): OperationInterpreter<Context, Result>;
|
|
50
50
|
};
|
|
@@ -83,7 +83,7 @@ export type OperationInterpreter<Context, Result> = {
|
|
|
83
83
|
* const greetOperation = operation(
|
|
84
84
|
* {
|
|
85
85
|
* options: {
|
|
86
|
-
* loud: optionFlag({ long: "loud", description: "Print in uppercase"
|
|
86
|
+
* loud: optionFlag({ long: "loud", description: "Print in uppercase" }),
|
|
87
87
|
* },
|
|
88
88
|
* positionals: [
|
|
89
89
|
* positionalRequired({ type: type("name"), description: "Name to greet" }),
|
|
@@ -99,46 +99,54 @@ export type OperationInterpreter<Context, Result> = {
|
|
|
99
99
|
export function operation<
|
|
100
100
|
Context,
|
|
101
101
|
Result,
|
|
102
|
-
Options extends { [option: string]: any },
|
|
103
|
-
const Positionals extends Array<any
|
|
102
|
+
const Options extends { [option: string]: any } = {},
|
|
103
|
+
const Positionals extends Array<any> = [],
|
|
104
104
|
>(
|
|
105
105
|
inputs: {
|
|
106
|
-
options
|
|
107
|
-
positionals
|
|
106
|
+
options?: { [K in keyof Options]: Option<Options[K]> };
|
|
107
|
+
positionals?: { [K in keyof Positionals]: Positional<Positionals[K]> };
|
|
108
108
|
},
|
|
109
109
|
handler: (
|
|
110
110
|
context: Context,
|
|
111
111
|
inputs: {
|
|
112
|
-
options: Options;
|
|
113
|
-
positionals: Positionals;
|
|
112
|
+
options: { [K in keyof Options]: Options[K] };
|
|
113
|
+
positionals: { [K in keyof Positionals]: Positionals[K] };
|
|
114
114
|
},
|
|
115
115
|
) => Promise<Result>,
|
|
116
116
|
): Operation<Context, Result> {
|
|
117
117
|
return {
|
|
118
118
|
generateUsage() {
|
|
119
119
|
const optionsUsage = new Array<UsageOption>();
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
|
|
120
|
+
if (inputs.options !== undefined) {
|
|
121
|
+
for (const optionKey in inputs.options) {
|
|
122
|
+
const optionInput = inputs.options[optionKey]!;
|
|
123
|
+
optionsUsage.push(optionInput.generateUsage());
|
|
124
|
+
}
|
|
123
125
|
}
|
|
124
126
|
const positionalsUsage = new Array<UsagePositional>();
|
|
125
|
-
|
|
126
|
-
|
|
127
|
+
if (inputs.positionals !== undefined) {
|
|
128
|
+
for (const positionalInput of inputs.positionals) {
|
|
129
|
+
positionalsUsage.push(positionalInput.generateUsage());
|
|
130
|
+
}
|
|
127
131
|
}
|
|
128
132
|
return { options: optionsUsage, positionals: positionalsUsage };
|
|
129
133
|
},
|
|
130
134
|
consumeAndMakeDecoder(readerArgs: ReaderArgs) {
|
|
131
135
|
const optionsDecoders: Record<string, OptionDecoder<any>> = {};
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
if (inputs.options !== undefined) {
|
|
137
|
+
for (const optionKey in inputs.options) {
|
|
138
|
+
const optionInput = inputs.options[optionKey]!;
|
|
139
|
+
optionsDecoders[optionKey] =
|
|
140
|
+
optionInput.registerAndMakeDecoder(readerArgs);
|
|
141
|
+
}
|
|
136
142
|
}
|
|
137
143
|
const positionalsDecoders: Array<PositionalDecoder<any>> = [];
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
if (inputs.positionals !== undefined) {
|
|
145
|
+
for (const positionalInput of inputs.positionals) {
|
|
146
|
+
positionalsDecoders.push(
|
|
147
|
+
positionalInput.consumeAndMakeDecoder(readerArgs),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
142
150
|
}
|
|
143
151
|
return {
|
|
144
152
|
decodeAndMakeInterpreter() {
|