Skip to content

Commit

Permalink
feat: set exitCode when debug-logs are generated (#58)
Browse files Browse the repository at this point in the history
* feat: set exitCode when debug-logs are generated

* chore: reorder readme sections

* docs: update documentation
  • Loading branch information
carloscortonc committed Sep 2, 2023
1 parent f9f5a27 commit 485b878
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 18 deletions.
54 changes: 39 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
# cli-er

[![NPM version](https://img.shields.io/npm/v/cli-er.svg)](https://www.npmjs.com/package/cli-er)
[![build](https://github.com/carloscortonc/cli-er/actions/workflows/build.yml/badge.svg)](https://github.com/carloscortonc/cli-er/actions/workflows/build.yml)

Tool for building advanced CLI applications using a definition object. It implements a folder structure strategy that helps organize all the logic, also including help-generation.
</br>
<h1 align="center">cli-er</h1>

<p align="center">
<a href="https://www.npmjs.com/package/cli-er" target="_blank">
<img src="https://img.shields.io/npm/v/cli-er.svg" alt="NPM version">
</a>
<a href="https://github.com/carloscortonc/cli-er/actions/workflows/build.yml" target="_blank">
<img src="https://github.com/carloscortonc/cli-er/actions/workflows/build.yml/badge.svg" alt="build">
</a>
</p>

<p align="center">
Tool for building advanced CLI applications using a definition object.</br>
Implements a folder structure strategy that helps organize all the logic, also including help-generation.
</p>

<h4 align="center">
<a href="#features">Features</a>
<span>&nbsp;·&nbsp;</span>
<a href="#installation">Installation</a>
<span>&nbsp;·&nbsp;</span>
<a href="#usage">Usage</a>
<span>&nbsp;·&nbsp;</span>
<a href="./docs/definition.md">Definition</a>
<span>&nbsp;·&nbsp;</span>
<a href="./docs/cli-options.md">Options</a>
</h4>

_cli.js_:

Expand Down Expand Up @@ -79,6 +99,14 @@ This allows us to organize and structure the logic nicely.

You can check the full [docker-based example](./examples/docker) for a more in-depth demo.


## Features
- [**Intl support**](./docs/features.md#intl-support): support for internationalized messages.
- [**Routing**](./docs/features.md#routing): routes are generated where command handlers are expected to be found.
- [**Debug mode**](./docs/features.md#debug-mode): validate the definition and options, especially when upgrading to a new version.
- [**Typescript support**](./docs/features.md#typescript-support): build the cli with typescript.


## Installation

```sh
Expand All @@ -89,16 +117,12 @@ npm install cli-er

`cli-er` default-exports a class, which takes in a [definition object](./docs/definition.md) and an optional argument [CliOptions](./docs/cli-options.md). The available methods are the following:

- [parse(args)](./docs/api.md#parseargs): parse the given arguments and return an object containing the options, errors and calculated location.
- [run(args?)](./docs/api.md#runargs): parse the given arguments and execute the corresponding script found in the calculated location. Integrates help and version generation.
- [help(location?)](./docs/api.md#helplocation): generate help based on the definition. Can be scoped to a namespace/command.
- [version()](./docs/api.md#version): generate a formatted version of the application's version.
- [**parse(args)**](./docs/api.md#parseargs): parse the given arguments and return an object containing the options, errors and calculated location.
- [**run(args?)**](./docs/api.md#runargs): parse the given arguments and execute the corresponding script found in the calculated location. Integrates help and version generation.
- [**help(location?)**](./docs/api.md#helplocation): generate help based on the definition. Can be scoped to a namespace/command.
- [**version()**](./docs/api.md#version): generate a formatted version of the application's version.

#### Glossary
- **Namespace**: is used to group commands, but cannot be invoked. Can contain other namespaces, commands or options.
- **Command**: Is the final invocable element. Can only contain options.
- **Option**: arguments that hold values of different types, like string, boolean, list...

## Typescript cli

You can check [this example](./examples/ts-cli) on how to write a full typescript cli application.
47 changes: 47 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## Intl support
To internationalize library messages, the [`CliOptions.messages`](./cli-options.md#messages) can be used to override the default messages. Check the [intl-cli example](/examples/intl-cli) for a use case.
`CliOptions.messages` can be also be used to specify descriptions for element's definition. For this, the key must be the full route to such element, followed by `".description"`, e.g:
```javascript
new Cli({
nms: {
options: {
cmd: {
debug: { type: "boolean"}
}
}
}
}, {
messages: {
"nms.description": "Namespace",
"nms.cmd.description": "Command",
"nms.cmd.debug.description": "Option",
}
})
```

## Routing
A "location" is calculated and returned by [`Cli.parse`](./api.md#parseargs): this is the route to the final invocable command.
With this location, the [`Cli.run`](./api.md#runargs) method generates a list of candidate files to execute and forward the parsed options. For each element of the location list (`[...rest, element]`):
1. `{...rest}/{element}/index` file.
2. `{...rest}/{element}` file.
3. The name of the entrypoint file

For all of these candidates, only the two from the last element are imported with default import, the rest with named import (the name of the last element).
For single commands, the location is prefixed with [`CliOptions.rootCommand`](./cli-options.md#rootcommand), if declared as string.

### Example
If the location is `["nms", "cmd"]` for an entryfile `cli.js`, the list of candidates (in order) will be:
1. `/nms/cmd/index.js` - default import
2. `/nms/cmd.js` - default import
3. `/nms/index.js` - named import (`cmd`)
4. `/nms.js` - named import (`cmd`)
5. `/index.js` - named import (`cmd`)
6. `/cli.js` - named import (`cmd`)

## Debug mode
When active, the library will generate debug logs warning about problems, deprecations or suggestions.
If any is generated, the `exitCode` will be set to `1`, so a simple validation-workflow can be built with this.
To see how to enable it check [`CliOptions.debug`](./cli-options.md#debug).

## Typescript support
You can check [this example](./examples/ts-cli) on how to write a full typescript cli application.
2 changes: 1 addition & 1 deletion src/option-syntax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const flagsProcessor: ArgumentProcessor = (args, definition) => {
}, [] as string[]);
};

/** Apply supported syntaxis to generate the final flatten list of arguments */
/** Apply supported syntaxis to generate the final flattened list of arguments */
const flattenArguments: ArgumentProcessor = (args, definition) => {
return [flagsProcessor, equalsSymbolProcessor].reduce((acc, processor) => processor(acc, definition), args);
};
Expand Down
8 changes: 6 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,13 @@ export function findPackageJson(baseLocation: string) {

export const isDebugActive = () => process.env[CLIER_DEBUG_KEY];

/** Utility to print messages only when debug mode is active */
/** Utility to print messages only when debug mode is active
* This will set the process exitcode to 1 */
export function debug(message: string) {
isDebugActive() && process.stderr.write("[CLIER_DEBUG] ".concat(message, "\n"));
if (isDebugActive()) {
process.stderr.write("[CLIER_DEBUG] ".concat(message, "\n"));
process.exitCode = 1;
}
}

/** Class containing the logic for logging deprecations. It holds the list of deprecation-messages already
Expand Down

0 comments on commit 485b878

Please sign in to comment.