cli-kiss 0.2.2 → 0.2.4

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.
@@ -14,6 +14,7 @@ export default defineConfig({
14
14
  ],
15
15
  ],
16
16
  themeConfig: {
17
+ search: { provider: "local", options: { detailedView: true } },
17
18
  nav: [
18
19
  { text: "Guide", link: "/guide/01_getting_started" },
19
20
  { text: "npm", link: "https://www.npmjs.com/package/cli-kiss" },
@@ -0,0 +1,4 @@
1
+ import DefaultTheme from "vitepress/theme";
2
+ import "./style.css";
3
+
4
+ export default DefaultTheme;
@@ -0,0 +1,4 @@
1
+ :root {
2
+ --vp-home-hero-image-background-image: linear-gradient( -50deg, #ff003cff 0%, #00000000 50%, #459900ff 100% );
3
+ --vp-home-hero-image-filter: blur(150px);
4
+ }
@@ -8,7 +8,7 @@ npm install cli-kiss
8
8
 
9
9
  ## Your first CLI
10
10
 
11
- Here is a minimal "greet" CLI that takes:
11
+ Minimal "greet" CLI with:
12
12
 
13
13
  - a required `NAME` positional
14
14
  - optional `--loud` flag:
@@ -60,7 +60,7 @@ greet Alice
60
60
  Hello, Alice!
61
61
  ```
62
62
 
63
- Pass some flags:
63
+ Pass a flag:
64
64
 
65
65
  ```sh
66
66
  greet --loud Alice
@@ -70,7 +70,7 @@ greet --loud Alice
70
70
  HELLO, ALICE!
71
71
  ```
72
72
 
73
- Get some help (built-in)
73
+ Help (built-in):
74
74
 
75
75
  ```sh
76
76
  greet --help
@@ -88,7 +88,7 @@ Options:
88
88
  --loud[=no] Print in uppercase
89
89
  ```
90
90
 
91
- Get the version (built-in)
91
+ Version (built-in):
92
92
 
93
93
  ```sh
94
94
  greet --version
@@ -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
- A leaf command has no subcommands. It directly runs an operation.
7
+ No subcommands directly runs an operation.
10
8
 
11
9
  ```ts
12
10
  import { command, operation, positionalRequired, typeString } from "cli-kiss";
@@ -18,40 +16,16 @@ const greet = command(
18
16
  options: {},
19
17
  positionals: [positionalRequired({ type: typeString, label: "NAME" })],
20
18
  },
21
- async (_ctx, { positionals: [name] }) => {
19
+ async function (_ctx, { positionals: [name] }) {
22
20
  console.log(`Hello, ${name}!`);
23
21
  },
24
22
  ),
25
23
  );
26
24
  ```
27
25
 
28
- ### `CommandInformation`
29
-
30
- Every command accepts a metadata object:
31
-
32
- | Field | Type | Description |
33
- | ------------- | ----------- | ------------------------------------------------- |
34
- | `description` | `string` | Short description shown in help output |
35
- | `hint` | `string?` | Note shown in parentheses next to the description |
36
- | `details` | `string[]?` | Extra lines printed below the description |
37
-
38
- ```ts
39
- command(
40
- {
41
- description: "Deploy the application",
42
- hint: "experimental",
43
- details: [
44
- "Pushes to the configured remote.",
45
- "Runs migrations after push.",
46
- ],
47
- },
48
- deployOperation,
49
- );
50
- ```
51
-
52
26
  ## `commandWithSubcommands` — dispatch to a subcommand
53
27
 
54
- Use this when the user must pick one of several sub-actions.
28
+ User must pick one of several sub-actions.
55
29
 
56
30
  ```ts
57
31
  import {
@@ -65,19 +39,19 @@ const rootCmd = commandWithSubcommands(
65
39
  { description: "My deployment CLI" },
66
40
  // This operation runs before the subcommand is selected.
67
41
  // Its return value becomes the subcommand's context.
68
- operation({ options: {}, positionals: [] }, async (_ctx) => ({
69
- db: "postgres://localhost/mydb",
70
- })),
42
+ operation({ options: {}, positionals: [] }, async function (_ctx) {
43
+ return { db: "postgres://localhost/mydb" };
44
+ }),
71
45
  {
72
46
  deploy: command(
73
47
  { description: "Deploy the latest build" },
74
- operation({ options: {}, positionals: [] }, async (ctx) => {
48
+ operation({ options: {}, positionals: [] }, async function (ctx) {
75
49
  console.log(`Deploying with DB: ${ctx.db}`);
76
50
  }),
77
51
  ),
78
52
  rollback: command(
79
53
  { description: "Rollback to the previous release" },
80
- operation({ options: {}, positionals: [] }, async (ctx) => {
54
+ operation({ options: {}, positionals: [] }, async function (ctx) {
81
55
  console.log(`Rolling back, DB: ${ctx.db}`);
82
56
  }),
83
57
  ),
@@ -105,13 +79,11 @@ Subcommands:
105
79
 
106
80
  ### Subcommand names
107
81
 
108
- The keys of the subcommand map are the literal tokens users type. They must be
109
- lowercase strings.
82
+ Keys are the tokens users type must be lowercase strings.
110
83
 
111
84
  ## `commandChained` — sequential stages
112
85
 
113
- Use this to split a command into reusable steps without introducing a
114
- user-visible subcommand token.
86
+ Splits a command into reusable steps with no extra user-visible token.
115
87
 
116
88
  ```ts
117
89
  import {
@@ -132,7 +104,7 @@ const authenticatedDeploy = commandChained(
132
104
  long: "token",
133
105
  type: typeString,
134
106
  description: "API token",
135
- default: () => {
107
+ default: function () {
136
108
  const t = process.env.API_TOKEN;
137
109
  if (!t) throw new Error("API_TOKEN env var is required");
138
110
  return t;
@@ -153,5 +125,64 @@ const authenticatedDeploy = commandChained(
153
125
  );
154
126
  ```
155
127
 
156
- The two stages' options and positionals are merged into a single flat usage
157
- output — the user sees one combined command.
128
+ All stages share a single flat usage users see one combined command.
129
+
130
+ ## `CommandInformation`
131
+
132
+ Every command accepts a metadata object:
133
+
134
+ | Field | Type | Description |
135
+ | ------------- | ------------ | ------------------------------------------------- |
136
+ | `description` | `string` | Short description shown in help output |
137
+ | `hint` | `string?` | Note shown in parentheses next to the description |
138
+ | `details` | `string[]?` | Extra lines printed below the description |
139
+ | `examples` | `Example[]?` | Usage examples shown in the `Examples:` section |
140
+
141
+ Each `Example` entry has:
142
+
143
+ | Field | Type | Description |
144
+ | ------------- | -------------- | ------------------------------------------------------- |
145
+ | `explanation` | `string` | Comment line shown above the example command |
146
+ | `commandArgs` | `CommandArg[]` | Ordered list of arguments to render on the command line |
147
+
148
+ Each `CommandArg` is one of:
149
+
150
+ | Shape | Renders as |
151
+ | ----------------------------------------------- | ---------------- |
152
+ | `string` | literal text |
153
+ | `{ positional: string }` | positional label |
154
+ | `{ subcommand: string }` | subcommand name |
155
+ | `{ option: { long: string; value?: string } }` | `--long[=value]` |
156
+ | `{ option: { short: string; value?: string } }` | `-s[=value]` |
157
+
158
+ ```ts
159
+ command(
160
+ {
161
+ description: "Deploy the application",
162
+ hint: "experimental",
163
+ details: [
164
+ "Pushes to the configured remote.",
165
+ "Runs migrations after push.",
166
+ ],
167
+ examples: [
168
+ {
169
+ explanation: "Deploy with a specific tag",
170
+ commandArgs: [
171
+ { positional: "v1.2.3" },
172
+ { option: { long: "dry-run" } },
173
+ ],
174
+ },
175
+ ],
176
+ },
177
+ deployOperation,
178
+ );
179
+ ```
180
+
181
+ The `Examples:` section in `--help` output renders each entry as a comment
182
+ followed by the reconstructed command line:
183
+
184
+ ```text
185
+ Examples:
186
+ # Deploy with a specific tag
187
+ deploy v1.2.3 --dry-run
188
+ ```
@@ -1,12 +1,11 @@
1
1
  # Options
2
2
 
3
- Options are named arguments prefixed with `--` (or `-` for short forms). Declare
4
- them in the `options` map of [`operation`](/guide/02_commands).
3
+ Named `--` arguments (or `-` for short forms). Declared in the `options` map of
4
+ [`operation`](/guide/02_commands).
5
5
 
6
6
  ## `optionFlag` — boolean toggle
7
7
 
8
- A flag that is either present or absent. The user can also pass `--flag=yes` /
9
- `--flag=no`.
8
+ Present or absent. Also accepts `--flag=true` / `--flag=no` / `--no-flag`.
10
9
 
11
10
  ```ts
12
11
  import { optionFlag } from "cli-kiss";
@@ -22,14 +21,14 @@ const verbose = optionFlag({
22
21
  // (absent) → false
23
22
  ```
24
23
 
25
- | Parameter | Type | Description |
26
- | ------------- | --------------------- | -------------------------------------------- |
27
- | `long` | `Lowercase<string>` | Long flag name (without `--`) |
28
- | `short` | `string?` | Short flag name (without `-`) |
29
- | `description` | `string?` | Help text |
30
- | `hint` | `string?` | Short note in parentheses |
31
- | `default` | `() => boolean` | Default when absent (default: `() => false`) |
32
- | `aliases` | `{ longs?, shorts? }` | Additional names for the flag |
24
+ | Parameter | Type | Description |
25
+ | ------------- | --------------------- | ------------------------------------ |
26
+ | `long` | `Lowercase<string>` | Long flag name (without `--`) |
27
+ | `short` | `string?` | Short flag name (without `-`) |
28
+ | `description` | `string?` | Help text |
29
+ | `hint` | `string?` | Short note in parentheses |
30
+ | `default` | `boolean? ` | Value when absent (default: `false`) |
31
+ | `aliases` | `{ longs?, shorts? }` | Additional names for the flag |
33
32
 
34
33
  ::: tip A flag specified more than once triggers a parse error. Use
35
34
  [`optionRepeatable`](#optionrepeatable-collect-multiple-values) if you need
@@ -39,7 +38,7 @@ multiple values.
39
38
 
40
39
  ## `optionSingleValue` — one typed value
41
40
 
42
- Accepts exactly one value. Use any [`Type`](/guide/05_types) to decode it.
41
+ Exactly one typed value.
43
42
 
44
43
  ```ts
45
44
  import { optionSingleValue, typeString } from "cli-kiss";
@@ -71,7 +70,7 @@ const output = optionSingleValue({
71
70
 
72
71
  ## `optionRepeatable` — collect multiple values
73
72
 
74
- Collects every occurrence into an array. Safe to specify zero or many times.
73
+ Collects every occurrence into an array.
75
74
 
76
75
  ```ts
77
76
  import { optionRepeatable, typeString } from "cli-kiss";
@@ -1,11 +1,10 @@
1
1
  # Positionals
2
2
 
3
- Positionals are bare (non-option) arguments passed by position. Declare them in
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 with a parse error if the argument is missing.
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 value when the argument is not provided.
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
- Greedily consumes all remaining positional tokens into an array.
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 ignored → ["foo", "bar"]
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
- Positionals are consumed **in declaration order**. Required positionals should
95
- come first; variadics should be last.
93
+ Consumed **in declaration order** required first, variadics last.
96
94
 
97
95
  ```ts
98
96
  operation(
@@ -1,14 +1,13 @@
1
1
  # Types
2
2
 
3
- A `Type<Value>` is a pair of a human-readable `content` string and a `decoder`
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
 
8
7
  | Export | TypeScript type | Accepts |
9
8
  | ------------- | --------------- | ---------------------------------------------------------- |
10
9
  | `typeString` | `string` | Any string |
11
- | `typeBoolean` | `boolean` | `true`, `yes`, `false`, `no` (case-insensitive) |
10
+ | `typeBoolean` | `boolean` | `true/yes/on/1/y/t` → true, `false/no/off/0/n/f` → false (case-insensitive) |
12
11
  | `typeNumber` | `number` | Integers, floats, scientific notation |
13
12
  | `typeInteger` | `bigint` | Integer strings only |
14
13
  | `typeDate` | `Date` | Any format accepted by `Date.parse` (ISO 8601 recommended) |
@@ -34,7 +33,7 @@ typeUrl.decoder("https://example.com/path"); // → URL object
34
33
 
35
34
  ## `typeOneOf` — string enum
36
35
 
37
- Accept only a fixed set of strings:
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
- ## `typeConverted` — transform an existing type
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 { typeConverted, typeNumber } from "cli-kiss";
53
+ import { typeMapped, typeNumber } from "cli-kiss";
55
54
 
56
- const typePort = typeConverted(typeNumber, {
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 automatically prefixed with
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
- Split a single string into a fixed-length typed tuple:
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
- Split a single string into an array of homogeneous values:
90
+ Splits a string into an array of typed values:
93
91
 
94
92
  ```ts
95
93
  import { typeList, typeNumber } from "cli-kiss";
@@ -2,8 +2,7 @@
2
2
 
3
3
  ## `runAndExit`
4
4
 
5
- `runAndExit` is the entry point for every `cli-kiss` CLI. It parses arguments,
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?);
@@ -25,7 +24,7 @@ await runAndExit(cliName, cliArgs, context, command, options?);
25
24
  | `usageOnHelp` | `boolean?` | `true` | Enables `--help` flag |
26
25
  | `usageOnError` | `boolean?` | `true` | Prints usage to stderr when parsing fails |
27
26
  | `useTtyColors` | `boolean \| "mock"?` | auto | Controls ANSI color output |
28
- | `onError` | `(error: unknown) => void` | — | Custom handler for execution errors |
27
+ | `onError` | `(error: unknown) => void` | — | Custom handler for parse and execution errors |
29
28
  | `onExit` | `(code: number) => never` | `process.exit` | Override for testing |
30
29
 
31
30
  ### Exit codes
@@ -127,7 +126,7 @@ my-cli deploy --dry-run
127
126
 
128
127
  ## Color control
129
128
 
130
- By default colors are auto-detected from the terminal. You can override:
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` so that `runAndExit` does not terminate your test process:
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
@@ -4,10 +4,12 @@ layout: home
4
4
  hero:
5
5
  name: CLI-kiss
6
6
  text: CLI for TypeScript.
7
+
7
8
  tagline:
8
- No bloat, no dependency. Only what you need.</br>Standard expected behaviour
9
- that users are used to.</br><span>K</span>eep <span>I</span>t
10
- <span>S</span>imple and <span>S</span>tupid, it just does the job.
9
+ No bloat, no dependencies.<br/>Standard behavior users expect.<br/>Keep It Simple and Stupid, it just does the job.
10
+
11
+ image:
12
+ src: /hero.png
11
13
 
12
14
  actions:
13
15
  - theme: brand
@@ -19,12 +21,15 @@ hero:
19
21
 
20
22
  features:
21
23
  - title: Zero dependencies
24
+ icon: 📦
22
25
  details:
23
26
  Ships with no runtime dependencies.<br/>Pure TypeScript, 5kb bundled.
24
27
  - title: Fully typed
28
+ icon: 🧠
25
29
  details:
26
30
  TypeScript first.<br/>Options and positionals inputs strongly typed.
27
31
  - title: Composable
32
+ icon: 🧩
28
33
  details:
29
34
  Easily create nested subcommands.<br/>Build complex CLIs by nesting logic.
30
35
  ---
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cli-kiss",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "devDependencies": {