cli-kiss 0.2.1 → 0.2.3
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 +1 -2
- package/dist/index.d.ts +527 -830
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +3 -0
- package/docs/guide/01_getting_started.md +9 -9
- package/docs/guide/02_commands.md +6 -11
- package/docs/guide/03_options.md +4 -6
- package/docs/guide/04_positionals.md +6 -8
- package/docs/guide/05_types.md +8 -10
- package/docs/guide/06_run.md +6 -7
- package/docs/index.md +4 -4
- package/package.json +1 -1
- package/src/lib/Command.ts +189 -256
- package/src/lib/Operation.ts +68 -82
- package/src/lib/Option.ts +115 -132
- package/src/lib/Positional.ts +95 -100
- package/src/lib/Reader.ts +53 -78
- package/src/lib/Run.ts +40 -58
- package/src/lib/Type.ts +81 -141
- package/src/lib/Typo.ts +121 -164
- package/src/lib/Usage.ts +56 -18
- package/tests/unit.command.execute.ts +83 -71
- package/tests/unit.command.usage.ts +230 -109
- package/tests/unit.runner.cycle.ts +56 -7
|
@@ -8,7 +8,7 @@ npm install cli-kiss
|
|
|
8
8
|
|
|
9
9
|
## Your first CLI
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Minimal "greet" CLI with:
|
|
12
12
|
|
|
13
13
|
- a required `NAME` positional
|
|
14
14
|
- optional `--loud` flag:
|
|
@@ -53,27 +53,27 @@ await runAndExit("greet", process.argv.slice(2), undefined, greetCommand, {
|
|
|
53
53
|
Run it:
|
|
54
54
|
|
|
55
55
|
```sh
|
|
56
|
-
|
|
56
|
+
greet Alice
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
```text
|
|
60
60
|
Hello, Alice!
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
Pass
|
|
63
|
+
Pass a flag:
|
|
64
64
|
|
|
65
65
|
```sh
|
|
66
|
-
|
|
66
|
+
greet --loud Alice
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
```text
|
|
70
70
|
HELLO, ALICE!
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
Help (built-in):
|
|
74
74
|
|
|
75
75
|
```sh
|
|
76
|
-
|
|
76
|
+
greet --help
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
```text
|
|
@@ -88,10 +88,10 @@ Options:
|
|
|
88
88
|
--loud[=no] Print in uppercase
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
Version (built-in):
|
|
92
92
|
|
|
93
93
|
```sh
|
|
94
|
-
|
|
94
|
+
greet --version
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
```text
|
|
@@ -102,7 +102,7 @@ greet 1.0.0
|
|
|
102
102
|
|
|
103
103
|
A typical `cli-kiss` project looks like this:
|
|
104
104
|
|
|
105
|
-
```
|
|
105
|
+
```text
|
|
106
106
|
my-cli/
|
|
107
107
|
├── src/
|
|
108
108
|
│ ├── index.ts ← entry point: calls runAndExit
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# Commands
|
|
2
2
|
|
|
3
|
-
Commands are the building blocks of a `cli-kiss` CLI.
|
|
4
|
-
|
|
5
3
|
Three factory functions cover every use-case.
|
|
6
4
|
|
|
7
5
|
## `command` — leaf command
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
No subcommands — directly runs an operation.
|
|
10
8
|
|
|
11
9
|
```ts
|
|
12
10
|
import { command, operation, positionalRequired, typeString } from "cli-kiss";
|
|
@@ -51,7 +49,7 @@ command(
|
|
|
51
49
|
|
|
52
50
|
## `commandWithSubcommands` — dispatch to a subcommand
|
|
53
51
|
|
|
54
|
-
|
|
52
|
+
User must pick one of several sub-actions.
|
|
55
53
|
|
|
56
54
|
```ts
|
|
57
55
|
import {
|
|
@@ -90,7 +88,7 @@ await runAndExit("deploy-cli", process.argv.slice(2), undefined, rootCmd);
|
|
|
90
88
|
Check it:
|
|
91
89
|
|
|
92
90
|
```sh
|
|
93
|
-
|
|
91
|
+
deploy-cli --help
|
|
94
92
|
```
|
|
95
93
|
|
|
96
94
|
```text
|
|
@@ -105,13 +103,11 @@ Subcommands:
|
|
|
105
103
|
|
|
106
104
|
### Subcommand names
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
lowercase strings.
|
|
106
|
+
Keys are the tokens users type — must be lowercase strings.
|
|
110
107
|
|
|
111
108
|
## `commandChained` — sequential stages
|
|
112
109
|
|
|
113
|
-
|
|
114
|
-
user-visible subcommand token.
|
|
110
|
+
Splits a command into reusable steps with no extra user-visible token.
|
|
115
111
|
|
|
116
112
|
```ts
|
|
117
113
|
import {
|
|
@@ -153,5 +149,4 @@ const authenticatedDeploy = commandChained(
|
|
|
153
149
|
);
|
|
154
150
|
```
|
|
155
151
|
|
|
156
|
-
|
|
157
|
-
output — the user sees one combined command.
|
|
152
|
+
All stages share a single flat usage — users see one combined command.
|
package/docs/guide/03_options.md
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# Options
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
them in the `options` map of [`operation`](/guide/02_commands).
|
|
3
|
+
Named `--` arguments (or `-` for short forms). Declared in the `options` map of [`operation`](/guide/02_commands).
|
|
5
4
|
|
|
6
5
|
## `optionFlag` — boolean toggle
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
`--flag=no`.
|
|
7
|
+
Present or absent. Also accepts `--flag=yes` / `--flag=no`.
|
|
10
8
|
|
|
11
9
|
```ts
|
|
12
10
|
import { optionFlag } from "cli-kiss";
|
|
@@ -39,7 +37,7 @@ multiple values.
|
|
|
39
37
|
|
|
40
38
|
## `optionSingleValue` — one typed value
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
Exactly one typed value.
|
|
43
41
|
|
|
44
42
|
```ts
|
|
45
43
|
import { optionSingleValue, typeString } from "cli-kiss";
|
|
@@ -71,7 +69,7 @@ const output = optionSingleValue({
|
|
|
71
69
|
|
|
72
70
|
## `optionRepeatable` — collect multiple values
|
|
73
71
|
|
|
74
|
-
Collects every occurrence into an array.
|
|
72
|
+
Collects every occurrence into an array.
|
|
75
73
|
|
|
76
74
|
```ts
|
|
77
75
|
import { optionRepeatable, typeString } from "cli-kiss";
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# Positionals
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
order in the `positionals` array of [`operation`](/guide/02_commands).
|
|
3
|
+
Bare (non-`--`) arguments, consumed in order. Declared in the `positionals` array of [`operation`](/guide/02_commands).
|
|
5
4
|
|
|
6
5
|
## `positionalRequired` — must be present
|
|
7
6
|
|
|
8
|
-
Fails
|
|
7
|
+
Fails if missing.
|
|
9
8
|
|
|
10
9
|
```ts
|
|
11
10
|
import { positionalRequired, typeString } from "cli-kiss";
|
|
@@ -28,7 +27,7 @@ const name = positionalRequired({
|
|
|
28
27
|
|
|
29
28
|
## `positionalOptional` — may be absent
|
|
30
29
|
|
|
31
|
-
Falls back to a default
|
|
30
|
+
Falls back to a default when absent.
|
|
32
31
|
|
|
33
32
|
```ts
|
|
34
33
|
import { positionalOptional, typeString } from "cli-kiss";
|
|
@@ -53,7 +52,7 @@ const greeting = positionalOptional({
|
|
|
53
52
|
|
|
54
53
|
## `positionalVariadics` — zero or more
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
Consumes all remaining tokens into an array.
|
|
57
56
|
|
|
58
57
|
```ts
|
|
59
58
|
import { positionalVariadics, typeString } from "cli-kiss";
|
|
@@ -78,7 +77,7 @@ const args = positionalVariadics({
|
|
|
78
77
|
endDelimiter: "STOP",
|
|
79
78
|
description: "Arguments (end with STOP)",
|
|
80
79
|
});
|
|
81
|
-
// my-cli foo bar STOP
|
|
80
|
+
// my-cli foo bar STOP → ["foo", "bar"]
|
|
82
81
|
```
|
|
83
82
|
|
|
84
83
|
| Parameter | Type | Description |
|
|
@@ -91,8 +90,7 @@ const args = positionalVariadics({
|
|
|
91
90
|
|
|
92
91
|
## Ordering rules
|
|
93
92
|
|
|
94
|
-
|
|
95
|
-
come first; variadics should be last.
|
|
93
|
+
Consumed **in declaration order** — required first, variadics last.
|
|
96
94
|
|
|
97
95
|
```ts
|
|
98
96
|
operation(
|
package/docs/guide/05_types.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Types
|
|
2
2
|
|
|
3
|
-
A `Type<Value>`
|
|
4
|
-
function. It tells cli-kiss how to convert a raw CLI string into a typed value.
|
|
3
|
+
A `Type<Value>` converts a raw CLI string into a typed value: a `content` label paired with a `decoder`.
|
|
5
4
|
|
|
6
5
|
## Built-in types
|
|
7
6
|
|
|
@@ -34,7 +33,7 @@ typeUrl.decoder("https://example.com/path"); // → URL object
|
|
|
34
33
|
|
|
35
34
|
## `typeOneOf` — string enum
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
Accepts only a fixed set of strings:
|
|
38
37
|
|
|
39
38
|
```ts
|
|
40
39
|
import { typeOneOf } from "cli-kiss";
|
|
@@ -46,14 +45,14 @@ typeEnv.decoder("unknown");
|
|
|
46
45
|
// Error: Invalid value: "unknown" (expected one of: "dev" | "staging" | "prod")
|
|
47
46
|
```
|
|
48
47
|
|
|
49
|
-
## `
|
|
48
|
+
## `typeMapped` — transform an existing type
|
|
50
49
|
|
|
51
50
|
Chain a `before` type with an `after` transformation:
|
|
52
51
|
|
|
53
52
|
```ts
|
|
54
|
-
import {
|
|
53
|
+
import { typeMapped, typeNumber } from "cli-kiss";
|
|
55
54
|
|
|
56
|
-
const typePort =
|
|
55
|
+
const typePort = typeMapped(typeNumber, {
|
|
57
56
|
content: "Port",
|
|
58
57
|
decoder: (n) => {
|
|
59
58
|
if (n < 1 || n > 65535) throw new Error("Out of range");
|
|
@@ -64,12 +63,11 @@ const typePort = typeConverted(typeNumber, {
|
|
|
64
63
|
// "--port 99999" → Error: --port: <PORT>: Port: Out of range
|
|
65
64
|
```
|
|
66
65
|
|
|
67
|
-
Errors from the `before` decoder are
|
|
68
|
-
`from: <content>` for easy debugging.
|
|
66
|
+
Errors from the `before` decoder are prefixed with `from: <content>`.
|
|
69
67
|
|
|
70
68
|
## `typeTuple` — fixed-length delimited value
|
|
71
69
|
|
|
72
|
-
|
|
70
|
+
Splits a string into a fixed-length typed tuple:
|
|
73
71
|
|
|
74
72
|
```ts
|
|
75
73
|
import { typeTuple, typeNumber } from "cli-kiss";
|
|
@@ -89,7 +87,7 @@ typeTuple([typeString, typeNumber], ":");
|
|
|
89
87
|
|
|
90
88
|
## `typeList` — variable-length delimited value
|
|
91
89
|
|
|
92
|
-
|
|
90
|
+
Splits a string into an array of typed values:
|
|
93
91
|
|
|
94
92
|
```ts
|
|
95
93
|
import { typeList, typeNumber } from "cli-kiss";
|
package/docs/guide/06_run.md
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## `runAndExit`
|
|
4
4
|
|
|
5
|
-
`runAndExit`
|
|
6
|
-
runs the matched command, and exits the process.
|
|
5
|
+
`runAndExit` parses arguments, runs the matched command, and exits.
|
|
7
6
|
|
|
8
7
|
```ts
|
|
9
8
|
await runAndExit(cliName, cliArgs, context, command, options?);
|
|
@@ -14,7 +13,7 @@ await runAndExit(cliName, cliArgs, context, command, options?);
|
|
|
14
13
|
| `cliName` | `Lowercase<string>` | Program name used in help and `--version` output |
|
|
15
14
|
| `cliArgs` | `ReadonlyArray<string>` | Raw arguments — typically `process.argv.slice(2)` |
|
|
16
15
|
| `context` | `Context` | Value forwarded to every command handler |
|
|
17
|
-
| `command` | `
|
|
16
|
+
| `command` | `Command<Context, void>` | The root command |
|
|
18
17
|
| `options` | `object?` | See below |
|
|
19
18
|
|
|
20
19
|
### Options
|
|
@@ -100,7 +99,7 @@ await runAndExit("my-cli", process.argv.slice(2), undefined, rootCmd, {
|
|
|
100
99
|
Check it
|
|
101
100
|
|
|
102
101
|
```sh
|
|
103
|
-
|
|
102
|
+
my-cli --help
|
|
104
103
|
```
|
|
105
104
|
|
|
106
105
|
```text
|
|
@@ -118,7 +117,7 @@ Options:
|
|
|
118
117
|
Try it
|
|
119
118
|
|
|
120
119
|
```sh
|
|
121
|
-
|
|
120
|
+
my-cli deploy --dry-run
|
|
122
121
|
```
|
|
123
122
|
|
|
124
123
|
```text
|
|
@@ -127,7 +126,7 @@ $ my-cli deploy --dry-run
|
|
|
127
126
|
|
|
128
127
|
## Color control
|
|
129
128
|
|
|
130
|
-
|
|
129
|
+
Colors are auto-detected. Override:
|
|
131
130
|
|
|
132
131
|
```ts
|
|
133
132
|
// Force colors on
|
|
@@ -142,7 +141,7 @@ await runAndExit("my-cli", args, ctx, cmd, { useTtyColors: "mock" });
|
|
|
142
141
|
|
|
143
142
|
## Testing your CLI
|
|
144
143
|
|
|
145
|
-
Override `onExit`
|
|
144
|
+
Override `onExit` to prevent process exit during tests:
|
|
146
145
|
|
|
147
146
|
```ts
|
|
148
147
|
import { runAndExit } from "cli-kiss";
|
package/docs/index.md
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
layout: home
|
|
3
3
|
|
|
4
4
|
hero:
|
|
5
|
-
name:
|
|
5
|
+
name: CLI-kiss
|
|
6
6
|
text: CLI for TypeScript.
|
|
7
7
|
tagline:
|
|
8
|
-
No bloat, no
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
No bloat, no dependencies.<br/>Standard behavior users expect.<br/><span>K</span>eep
|
|
9
|
+
<span>I</span>t <span>S</span>imple and <span>S</span>tupid, it just does the
|
|
10
|
+
job.
|
|
11
11
|
|
|
12
12
|
actions:
|
|
13
13
|
- theme: brand
|