termkit 1.7.1 → 2.0.1

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2018 Jay Deaton
3
+ Copyright (c) 2018–2026 Jay Deaton
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,104 +1,165 @@
1
1
  # Termkit
2
2
 
3
- A terminal input parsing kit
3
+ A fluent CLI framework for Node.js with nested subcommands, middleware, and TypeScript support.
4
4
 
5
- ## Getting Started
5
+ ## Installation
6
6
 
7
- This is how to get started using Termkit
8
-
9
- ### Installing
10
-
11
- Add this package to your project
12
7
  ```bash
13
- npm install --save termkit
8
+ npm install termkit
14
9
  ```
15
10
 
16
- ### Using
11
+ ## Usage
17
12
 
18
- Configure your command line program
19
- ```node
20
- const { command, middleware, option } = require('termkit')
13
+ ### Basic program
21
14
 
22
- const program = command('example')
15
+ ```ts
16
+ import { command, option, parse } from 'termkit'
17
+
18
+ const program = command('my-app')
23
19
  .version('1.0.0')
24
- .description('example program')
25
- .option('a', 'array', '[arr...]', 'Array variable')
26
- .option('r', 'required', '<reqA> <reqB>', 'Two required variables')
27
- .option('o', 'optional', '[opt]', 'One optional variable')
28
- .option('b', 'boolean', null, 'No variable')
29
- .middleware((options) => console.log('middleware is run before action, manipulate the options object as needed'))
30
- .action((options) => console.log('run action with given options'))
31
- .commands([
32
- command('first')
33
- .description('first nested command')
34
- .options([
35
- // Same style options as before
36
- ])
37
- .middleware((options) => console.log('middleware can be nested too'))
38
- .action((options) => console.log('run action with given options'))
39
- .commands([
40
- // So on and so forth
41
- ])
42
- ])
20
+ .description('My CLI application')
21
+ .option('v', 'verbose', null, 'Enable verbose output')
22
+ .option('o', 'output', '<file>', 'Output file path')
23
+ .action((options) => {
24
+ console.log(options.output)
25
+ })
26
+
27
+ try {
28
+ program.parse(process.argv)
29
+ } catch (err) {
30
+ console.error(err)
31
+ }
43
32
  ```
44
33
 
45
- Alternatively supply options and middlewares to command in arrays
46
- ```node
47
- command('example')
48
- .options([
49
- option('a', 'array', '[arr...]', 'Array variable'),
50
- option('r', 'required', '<reqA> <reqB>', 'Two required variables'),
51
- option('o', 'optional', '[opt]', 'One optional variable'),
52
- option('b', 'boolean', null, 'No variable')
53
- ])
54
- .middlewares([
55
- middleware(() => console.log(1)),
56
- middleware(() => console.log(2)),
57
- middleware(() => console.log(3))
34
+ ### Options
35
+
36
+ Options support four variable shapes:
37
+
38
+ ```ts
39
+ command('app')
40
+ .option('b', 'boolean', null, 'Flag with no value')
41
+ .option('o', 'optional', '[val]', 'Optional value')
42
+ .option('r', 'required', '<val>', 'Required value')
43
+ .option('a', 'array', '[val...]', 'Array of values')
44
+ ```
45
+
46
+ Accessible in actions and middleware via the long name:
47
+
48
+ ```ts
49
+ .action((options) => {
50
+ options.boolean // true | undefined
51
+ options.optional // string | true
52
+ options.required // string
53
+ options.array // string[]
54
+ })
55
+ ```
56
+
57
+ ### Value coercion
58
+
59
+ Append `:number` or `:boolean` to a variable to coerce the parsed string:
60
+
61
+ ```ts
62
+ command('app')
63
+ .option('p', 'port', '<port:number>', 'Port number')
64
+ .option('v', 'verbose', '[verbose:boolean]', 'Verbose mode')
65
+ .option('n', 'nums', '[nums:number...]', 'List of numbers')
66
+ .action((options) => {
67
+ options.port // number
68
+ options.verbose // boolean
69
+ options.nums // number[]
70
+ })
71
+ ```
72
+
73
+ ### Subcommands
74
+
75
+ Commands nest to any depth. Each level can have its own options and middleware.
76
+
77
+ ```ts
78
+ import { command, option } from 'termkit'
79
+
80
+ command('app')
81
+ .commands([
82
+ command('serve')
83
+ .option('p', 'port', '<port:number>', 'Port to listen on')
84
+ .action((options) => startServer(options.port)),
85
+
86
+ command('build')
87
+ .option('w', 'watch', null, 'Watch for changes')
88
+ .action((options) => runBuild(options)),
58
89
  ])
59
90
  ```
60
91
 
61
- Commands nest and can have variables themselves
62
- ```node
63
- command('example').commands([
64
- command('another', '[optional]'),
65
- command('another', '<required>'),
66
- command('another', '[array...]')
67
- ])
92
+ Commands can also carry their own positional variables:
93
+
94
+ ```ts
95
+ command('get', '<id>') // required
96
+ command('list', '[filter]') // optional
97
+ command('tag', '[tags...]') // array
68
98
  ```
69
99
 
70
- Variables, and options are passed into middleware and action functions.
71
- ```node
72
- command('example', <var>)
73
- .option('r', 'require', <req>, 'Another example')
74
- .middleware(options) => {
75
- console.log(options.require)
100
+ ### Middleware
101
+
102
+ Middleware runs before the action. It can mutate the options object and supports async.
103
+
104
+ ```ts
105
+ command('app')
106
+ .middleware(async (options) => {
107
+ options.user = await getUser(options.token)
76
108
  })
77
109
  .action((options) => {
78
- console.log(options.require)
110
+ console.log(options.user)
79
111
  })
80
112
  ```
81
113
 
82
- After completing constructing the CLI flow, parse the input and catch possible errors
83
- ```node
84
- try {
85
- program.parse(process.argv)
86
- } catch(err) {
87
- console.log(err)
88
- }
114
+ Use `.middlewares([...])` to register several at once. When navigating into a subcommand, parent middleware runs first.
115
+
116
+ ### Default middleware and options
117
+
118
+ Apply middleware or options to every command created after the call:
119
+
120
+ ```ts
121
+ import { setDefaults } from 'termkit'
122
+
123
+ setDefaults({
124
+ middlewares: [
125
+ async (options) => { options.timestamp = Date.now() }
126
+ ]
127
+ })
89
128
  ```
90
129
 
91
- Built in terminal help usage function
92
- ```node
93
- program.parse('_ _ help'.split(' '))
130
+ ### Built-in help
131
+
132
+ Passing `help` anywhere in argv prints a formatted usage table and stops execution:
133
+
134
+ ```bash
135
+ my-app help
136
+ my-app serve help
94
137
  ```
95
138
 
96
- Stay tuned for more
139
+ ## API
140
+
141
+ ### Functions
142
+
143
+ | Function | Signature | Description |
144
+ |---|---|---|
145
+ | `command` | `(name, variables?, info?) => Command` | Create a command |
146
+ | `option` | `(short, long, variables, info) => Option` | Create an option |
147
+ | `middleware` | `(fn) => fn` | Identity helper for typing middleware inline |
148
+ | `parse` | `(argv) => Promise<unknown>` | Parse using the root command |
149
+ | `setDefaults` | `(defaults) => void` | Set defaults applied to all new commands |
150
+
151
+ ### Classes
152
+
153
+ `Command`, `Option`, `Variable`, `Termkit`
154
+
155
+ ### Types
156
+
157
+ `ActionFn`, `MiddlewareFn`, `ParsedOptions`, `CommandDefaults`, `VariableType`
97
158
 
98
159
  ## Authors
99
160
 
100
- * **Jay Deaton** - [Github](https://github.com/jayrdeaton)
161
+ **Jay Deaton** [GitHub](https://github.com/jayrdeaton)
101
162
 
102
163
  ## License
103
164
 
104
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
165
+ MIT
@@ -0,0 +1,99 @@
1
+ type VariableType = 'string' | 'number' | 'boolean';
2
+ interface ParsedOptions {
3
+ _source: string[];
4
+ _parents?: Record<string, Record<string, unknown>>;
5
+ [key: string]: unknown;
6
+ }
7
+ type ActionFn = (options: ParsedOptions) => unknown | Promise<unknown>;
8
+ type MiddlewareFn = (options: ParsedOptions) => void | Promise<void>;
9
+
10
+ interface VariableData {
11
+ array?: boolean;
12
+ name?: string;
13
+ raw?: string;
14
+ required?: boolean;
15
+ type?: VariableType;
16
+ }
17
+ declare class Variable {
18
+ array: boolean;
19
+ name: string | null;
20
+ raw: string | null;
21
+ required: boolean;
22
+ type: VariableType;
23
+ value: unknown[] | null;
24
+ constructor(data?: VariableData);
25
+ }
26
+
27
+ interface OptionData {
28
+ short?: string | null;
29
+ long?: string | null;
30
+ info?: string | null;
31
+ variables?: string | null;
32
+ }
33
+ declare class Option {
34
+ short: string | null;
35
+ long: string | null;
36
+ info: string | null;
37
+ variables: Variable[] | null;
38
+ constructor(data?: OptionData);
39
+ description(info: string): this;
40
+ }
41
+
42
+ interface CommandData {
43
+ name?: string;
44
+ variables?: string | null;
45
+ info?: string;
46
+ middlewares?: MiddlewareFn[];
47
+ options?: Option[];
48
+ }
49
+ declare class Command {
50
+ actionFunction: ActionFn | null;
51
+ commandsArray: Command[];
52
+ commandStrings: string[];
53
+ info: string | null;
54
+ middlewaresArray: MiddlewareFn[];
55
+ name: string | null;
56
+ optionsArray: Option[];
57
+ variables: Variable[] | null;
58
+ versionString: string | null;
59
+ constructor(data?: CommandData);
60
+ description(info: string): this;
61
+ variable(string: string): this;
62
+ action(fn: ActionFn): this;
63
+ command(cmd: Command): this;
64
+ commands(cmds: Command[]): this;
65
+ middleware(fn: MiddlewareFn): this;
66
+ middlewares(fns: MiddlewareFn[]): this;
67
+ option(short: string | null, long: string | null, variables: string | null, info: string): this;
68
+ options(opts: Option[]): this;
69
+ version(v: string): this;
70
+ help(_source?: string[]): void;
71
+ parse(input: string[]): Promise<unknown>;
72
+ }
73
+
74
+ interface TermkitDefaults {
75
+ middlewares?: MiddlewareFn[];
76
+ options?: Option[];
77
+ }
78
+ declare class Termkit {
79
+ private static base;
80
+ private static commandDefaults;
81
+ static set defaults(obj: TermkitDefaults);
82
+ static setDefaults(obj: TermkitDefaults): void;
83
+ static command(name: string, variables?: string | null, info?: string): Command;
84
+ static middleware(action: MiddlewareFn): MiddlewareFn;
85
+ static option(short: string | null, long: string | null, variables: string | null, info: string): Option;
86
+ static parse(arr: string[]): Promise<unknown>;
87
+ }
88
+
89
+ interface CommandDefaults {
90
+ middlewares?: MiddlewareFn[];
91
+ options?: Option[];
92
+ }
93
+ declare const command: (name: string, variables?: string | null, info?: string) => Command;
94
+ declare const middleware: (fn: MiddlewareFn) => MiddlewareFn;
95
+ declare const option: (short: string | null, long: string | null, variables: string | null, info: string) => Option;
96
+ declare const parse: (arr: string[]) => Promise<unknown>;
97
+ declare const setDefaults: (data: CommandDefaults) => void;
98
+
99
+ export { type ActionFn, Command, type CommandDefaults, type MiddlewareFn, Option, type ParsedOptions, Termkit, Variable, type VariableType, command, middleware, option, parse, setDefaults };
@@ -0,0 +1,99 @@
1
+ type VariableType = 'string' | 'number' | 'boolean';
2
+ interface ParsedOptions {
3
+ _source: string[];
4
+ _parents?: Record<string, Record<string, unknown>>;
5
+ [key: string]: unknown;
6
+ }
7
+ type ActionFn = (options: ParsedOptions) => unknown | Promise<unknown>;
8
+ type MiddlewareFn = (options: ParsedOptions) => void | Promise<void>;
9
+
10
+ interface VariableData {
11
+ array?: boolean;
12
+ name?: string;
13
+ raw?: string;
14
+ required?: boolean;
15
+ type?: VariableType;
16
+ }
17
+ declare class Variable {
18
+ array: boolean;
19
+ name: string | null;
20
+ raw: string | null;
21
+ required: boolean;
22
+ type: VariableType;
23
+ value: unknown[] | null;
24
+ constructor(data?: VariableData);
25
+ }
26
+
27
+ interface OptionData {
28
+ short?: string | null;
29
+ long?: string | null;
30
+ info?: string | null;
31
+ variables?: string | null;
32
+ }
33
+ declare class Option {
34
+ short: string | null;
35
+ long: string | null;
36
+ info: string | null;
37
+ variables: Variable[] | null;
38
+ constructor(data?: OptionData);
39
+ description(info: string): this;
40
+ }
41
+
42
+ interface CommandData {
43
+ name?: string;
44
+ variables?: string | null;
45
+ info?: string;
46
+ middlewares?: MiddlewareFn[];
47
+ options?: Option[];
48
+ }
49
+ declare class Command {
50
+ actionFunction: ActionFn | null;
51
+ commandsArray: Command[];
52
+ commandStrings: string[];
53
+ info: string | null;
54
+ middlewaresArray: MiddlewareFn[];
55
+ name: string | null;
56
+ optionsArray: Option[];
57
+ variables: Variable[] | null;
58
+ versionString: string | null;
59
+ constructor(data?: CommandData);
60
+ description(info: string): this;
61
+ variable(string: string): this;
62
+ action(fn: ActionFn): this;
63
+ command(cmd: Command): this;
64
+ commands(cmds: Command[]): this;
65
+ middleware(fn: MiddlewareFn): this;
66
+ middlewares(fns: MiddlewareFn[]): this;
67
+ option(short: string | null, long: string | null, variables: string | null, info: string): this;
68
+ options(opts: Option[]): this;
69
+ version(v: string): this;
70
+ help(_source?: string[]): void;
71
+ parse(input: string[]): Promise<unknown>;
72
+ }
73
+
74
+ interface TermkitDefaults {
75
+ middlewares?: MiddlewareFn[];
76
+ options?: Option[];
77
+ }
78
+ declare class Termkit {
79
+ private static base;
80
+ private static commandDefaults;
81
+ static set defaults(obj: TermkitDefaults);
82
+ static setDefaults(obj: TermkitDefaults): void;
83
+ static command(name: string, variables?: string | null, info?: string): Command;
84
+ static middleware(action: MiddlewareFn): MiddlewareFn;
85
+ static option(short: string | null, long: string | null, variables: string | null, info: string): Option;
86
+ static parse(arr: string[]): Promise<unknown>;
87
+ }
88
+
89
+ interface CommandDefaults {
90
+ middlewares?: MiddlewareFn[];
91
+ options?: Option[];
92
+ }
93
+ declare const command: (name: string, variables?: string | null, info?: string) => Command;
94
+ declare const middleware: (fn: MiddlewareFn) => MiddlewareFn;
95
+ declare const option: (short: string | null, long: string | null, variables: string | null, info: string) => Option;
96
+ declare const parse: (arr: string[]) => Promise<unknown>;
97
+ declare const setDefaults: (data: CommandDefaults) => void;
98
+
99
+ export { type ActionFn, Command, type CommandDefaults, type MiddlewareFn, Option, type ParsedOptions, Termkit, Variable, type VariableType, command, middleware, option, parse, setDefaults };