@jill64/ts-cli
Advanced tools
Comparing version 0.0.1 to 0.1.0
@@ -1,1 +0,1 @@ | ||
export { command } from './command.js'; | ||
export { App } from './App.js'; |
@@ -1,1 +0,1 @@ | ||
export { command } from './command.js'; | ||
export { App } from './App.js'; |
@@ -1,2 +0,2 @@ | ||
import { Config } from '../context/Config.js'; | ||
import { Config } from '../Config.js'; | ||
export type MergeConfig<RootConfig extends Config, T extends Config> = T & (RootConfig extends { | ||
@@ -3,0 +3,0 @@ options: unknown; |
@@ -1,5 +0,5 @@ | ||
import { ArgumentDescriptions } from '../describe/ArgumentDescriptions.js'; | ||
import { Empty } from '../literal/Empty.js'; | ||
import { ArgumentDescriptions } from '../config/ArgumentDescriptions.js'; | ||
import { Empty } from '../Empty.js'; | ||
export type NormalizedArguments<T extends ArgumentDescriptions | undefined> = T extends Map<infer U, string> ? Record<U extends string ? U : never, string> : T extends [infer U, string][] ? Record<U extends string ? U : never, string> : T extends { | ||
description: Record<infer U, string>; | ||
} ? Record<U, string> : T extends Record<infer U, string> ? Record<U extends string ? U : never, string> : Empty; |
@@ -1,4 +0,4 @@ | ||
import { OptionDescriptions } from '../describe/OptionDescriptions.js'; | ||
import { OptionType } from '../literal/OptionType.js'; | ||
import { OptionTypeMap } from '../literal/OptionTypeMap.js'; | ||
import { OptionDescriptions } from '../config/OptionDescriptions.js'; | ||
import { OptionType } from '../OptionType.js'; | ||
import { OptionTypeMap } from '../OptionTypeMap.js'; | ||
export type NormalizedOptions<T extends OptionDescriptions | undefined> = { | ||
@@ -5,0 +5,0 @@ [K in keyof T]: T[K] extends { |
{ | ||
"name": "@jill64/ts-cli", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"type": "module", | ||
@@ -44,5 +44,5 @@ "files": [ | ||
"url": "https://github.com/jill64/ts-cli.git", | ||
"image": "https://opengraph.githubassets.com/59e6a4029f25b818e068d082b2969ac08df1cc6c7069522a275332dcbca835c1/jill64/ts-cli" | ||
"image": "https://opengraph.githubassets.com/8f62a9306055fb3b0aa92185a4a5805897ef1ed84d351d1dee197860320d505b/jill64/ts-cli" | ||
}, | ||
"description": "> Easy Node CLI creation with opinionated POSIX-like defaults", | ||
"description": "> Solidly-Typed CLI Application Builder", | ||
"publishConfig": { | ||
@@ -49,0 +49,0 @@ "access": "public" |
282
README.md
@@ -11,29 +11,6 @@ <!----- BEGIN GHOST DOCS HEADER -----> | ||
> Easy Node CLI creation with opinionated POSIX-like defaults | ||
> Solidly-Typed CLI Application Builder | ||
<!----- END GHOST DOCS HEADER -----> | ||
## Features | ||
- ✅ Declaratively Self-Documented Source of Truth. | ||
- Route definition (Sub Command) | ||
- Argument | ||
- Exit code | ||
- Option (Short option, Long option) | ||
- Optional argument | ||
- Rest argument | ||
- Root definitions + route-specific definitions | ||
- ✅ Type-Safety | ||
- Schema-constrained command route handler | ||
- Generation of CLI and API with common definitions | ||
- ✅ Opinionated | ||
- All options require a short version | ||
- POSIX-compliant exit code | ||
- Default option handle | ||
- Pre-built loggers | ||
## Installation | ||
@@ -45,53 +22,9 @@ | ||
## Minimum Start | ||
## Example | ||
The `command` function defines a single CLI command and serves as the root for all other subcommands. | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
import { App } from '@jill64/ts-cli' | ||
command('example', () => { | ||
// It is executed as a handler when the command is invoked. | ||
}) | ||
``` | ||
### Auto Generated Help | ||
Out of box, help is always generated automatically. | ||
Also, if the command has a help option (`-h`, `--help`), it will display help and exit. (No handler is executed). | ||
Help is automatically added as you add more schemas. | ||
## Define Schema | ||
### Version | ||
This value is used to display the version of the command (`-v`, `--version`). | ||
> [!NOTE] | ||
> If this value is set, handler functions will not be executed when the `--version` and `-v` options are specified. | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
command( | ||
'example', | ||
new App( | ||
{ | ||
version: '1.0.0' | ||
}, | ||
() => { | ||
// ... | ||
} | ||
) | ||
``` | ||
### Positional Arguments | ||
The `args` property of the command definition is used to define positional arguments. | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
command( | ||
'example', | ||
{ | ||
args: [ | ||
@@ -101,31 +34,3 @@ ['arg1', 'Argument 1'], | ||
['arg3', 'Argument 3'] | ||
] | ||
}, | ||
({ args }) => { | ||
// `example <arg1> <arg2> <arg3>` | ||
// [arg1, arg2, arg3] | ||
args | ||
} | ||
) | ||
``` | ||
### Options | ||
Defines options that can be specified when executing the command. | ||
These have their own limitations | ||
- All options require a single alphanumeric abbreviation as the key to the object. | ||
- All options must specify default values and be optional. | ||
- Only lowercase alphanumeric characters and `-` are allowed in option names. | ||
> [!TIP] | ||
> Some of these restrictions are found in [POSIX Utility Conventions](https://pubs.opengroup.org/onlinepubs/9699919799/) and [POSIX Rationale Utility Conventions](https://pubs.opengroup.org/onlinepubs/9699919799/). | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
command( | ||
'example', | ||
{ | ||
], | ||
options: { | ||
@@ -141,21 +46,3 @@ verbose: { | ||
} | ||
} | ||
}, | ||
({ options }) => { | ||
options.verbose // boolean | ||
options.host // string | ||
} | ||
) | ||
``` | ||
### Optional Arguments | ||
The `optional` property of the command definition is used to define optional arguments. | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
command( | ||
'example', | ||
{ | ||
}, | ||
optional: [ | ||
@@ -165,30 +52,20 @@ ['optional-1', 'Optional Argument 1'], | ||
['optional-3', 'Optional Argument 3'] | ||
] | ||
}, | ||
({ optional }) => { | ||
// [optional 1, optional 2, optional 3] | ||
optional | ||
} | ||
) | ||
``` | ||
### Rest Arguments | ||
Edge cases must accept arguments of variable length. | ||
This can be accomplished using the `rest` property. | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
command( | ||
'example', | ||
{ | ||
], | ||
rest: { | ||
placeholder: 'rest-argument', | ||
description: 'Rest Argument' | ||
}, | ||
codes: { | ||
0: success, | ||
1: failure | ||
} | ||
}, | ||
({ rest }) => { | ||
// [...] | ||
rest | ||
({ args, options, optional, rest }) => { | ||
// `<command> <arg1> <arg2> <arg3> [options] [optional1?] [optional2?] [optional3?] <...rest>` | ||
options.verbose // boolean | ||
options.host // string | ||
// Allow 0 or 1 or void | ||
return 0 | ||
} | ||
@@ -198,8 +75,4 @@ ) | ||
> [!NOTE] | ||
> `rest` and `optional` are exclusive. | ||
> Only one of them may be specified for a single route. | ||
## Add Route (Subcommands) | ||
### Route (Subcommands) | ||
The `add` function defines a route. | ||
@@ -211,18 +84,22 @@ | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
import { App } from '@jill64/ts-cli' | ||
command('example', () => { | ||
// ... | ||
}) | ||
.add('test', () => { | ||
// `example test` | ||
// ... | ||
}) | ||
new App(/* ... */) | ||
.add( | ||
'test', | ||
{ | ||
// Config | ||
}, | ||
() => { | ||
// `<command> test` | ||
// ... | ||
} | ||
) | ||
.add( | ||
'test start', | ||
{ | ||
// ... | ||
// Config | ||
}, | ||
() => { | ||
// `example test start` | ||
// `<command> test start` | ||
// ... | ||
@@ -233,42 +110,26 @@ } | ||
## Execution | ||
## Run as Command | ||
### Run a command | ||
The `run` function executes the command immediately using `process.argv`. | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
import { App } from '@jill64/ts-cli' | ||
import process from 'node:process' | ||
command('example', () => { | ||
// ... | ||
}).run(process.argv) | ||
new App(/* ... */).run(process.argv) | ||
``` | ||
### Export as API | ||
## Export as API | ||
Occasionally, you may need an API that has the same options as the CLI. | ||
In this case, you can export it as an API and use it, keeping it type-safe and portable. | ||
```js | ||
// index.js | ||
import { command } from '@jill64/ts-cli' | ||
import { App } from '@jill64/ts-cli' | ||
export const { execute, invoke } = command('example', () => { | ||
// `example` | ||
// ... | ||
}) | ||
.add('test', () => { | ||
// `example test` | ||
// ... | ||
}) | ||
.add('test start', () => { | ||
// `example test start` | ||
// ... | ||
}) | ||
export const { execute, invoke } = new App(/* ... */) | ||
.add(/* ... */) | ||
.add(/* ... */) | ||
``` | ||
```js | ||
import { execute, invoke } from 'index.js' | ||
import { invoke } from 'index.js' | ||
@@ -296,3 +157,3 @@ // `example` | ||
// `example test` | ||
invoke.test({ | ||
invoke('test', { | ||
// ... | ||
@@ -302,3 +163,3 @@ }) | ||
// `example test start` | ||
invoke.['test start']({ | ||
invoke('test start', { | ||
// ... | ||
@@ -308,55 +169,2 @@ }) | ||
## Exit Code | ||
In some cases, a custom exit code may be required. | ||
These can also be defined together to add verification and documentation of the exit code. | ||
- The range of the exit code is an integer from 0 to 255. | ||
- If no exit code is specified, the return value is automatically set by node. | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
command( | ||
'example', | ||
{ | ||
codes: { | ||
0: success, | ||
1: failure | ||
} | ||
}, | ||
() => { | ||
// ... | ||
// Allow 0 or 1 or void | ||
return 0 | ||
} | ||
) | ||
``` | ||
## Logger | ||
The output content of this logger is automatically controlled by the log level options entered. | ||
| | | Level | | ||
| ----------- | ----------- | ----------------------------------------- | | ||
| `-s` | `--silent` | - (None) | | ||
| `-q` | `--quiet` | `ERROR` | | ||
| - (default) | - (default) | `WARN`, `ERROR` | | ||
| `-V` | `--verbose` | `INFO`, `WARN`, `ERROR` | | ||
| `-d` | `--debug` | `DEBUG`, `INFO`, `WARN`, `ERROR` | | ||
| `-t` | `--trace` | `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR` | | ||
```js | ||
import { command } from '@jill64/ts-cli' | ||
command('example', ({ logger }) => { | ||
logger.error('ERROR') | ||
logger.warn('WARN') | ||
logger.info('INFO') | ||
logger.debug('DEBUG') | ||
logger.trace('TRACE') | ||
}) | ||
``` | ||
<!----- BEGIN GHOST DOCS FOOTER -----> | ||
@@ -363,0 +171,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
20976
49
479
166
1