Skip to content

Commit b6269d6

Browse files
committed
docs: basic distributable command example
1 parent 3412c73 commit b6269d6

5 files changed

Lines changed: 191 additions & 6 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,65 @@
11
# @examples/distributable-command
22

3+
An example of a @qui-cli command that can be distributed as an Node package
4+
35
[![npm version](https://badge.fury.io/js/@examples%2fdistributable-command.svg)](https://npmjs.com/package/@examples/distributable-command)
46
[![Module type: ESM](https://img.shields.io/badge/module%20type-esm-brightgreen)](https://nodejs.org/api/esm.html)
7+
8+
## Create from template
9+
10+
This package is created using the @qui-cli/command template and making a few quick edits:
11+
12+
```sh
13+
> pnpm create @qui-cli/command --scope examples "Distributable Command" --description "An example of a @qui-cli command that can be distributed as an Node package"
14+
```
15+
16+
## Consistent Usage
17+
18+
The command itself is distributed in the module's [bin](./bin/) directory (as indicated in [package.json](./package.json#L16-L18)) as Node executable. It can be invoked either by installing the package globally (and adding the global package manager's bin directory to your path, as one does) or by invoking you favorite package manager's exec function:
19+
20+
```sh
21+
> pnpm exec distributable-command
22+
```
23+
24+
The command is self-documenting, and its usage can be invoked with `--help` (or `-h`):
25+
26+
```sh
27+
> ./bin/distributable-command -h
28+
Usage:
29+
distributable-command -hf --t=<"argle bargle"> --number=<3.14159> --logFilePath=<logFilePath> --stdoutLevel=<all|trace|debug|info|warning|error|fatal|off>
30+
--fileLevel=<all|trace|debug|info|warning|error|fatal|off> [target]
31+
32+
Positional arguments
33+
34+
target
35+
36+
A positional text argument
37+
38+
-h --help Show this usage information
39+
40+
Command Options
41+
42+
-t<"argle bargle"> --text=<"argle bargle">
43+
A text parameter
44+
45+
--number=<3.14159>
46+
A numeric parameter (Default: 2.171)
47+
-f --flag A boolean parameter
48+
49+
Logging options
50+
51+
--logFilePath=<logFilePath>
52+
Path to log file (optional)
53+
54+
--stdoutLevel=<all|trace|debug|info|warning|error|fatal|off>
55+
Log level to console stdout (Default: "info")
56+
57+
--fileLevel=<all|trace|debug|info|warning|error|fatal|off>
58+
Log level to log file if --logFilePath provided (Default: "all")
59+
```
60+
61+
## Easy development
62+
63+
All of the API hooks that are defined in the [example](./src/DistributableCommand.ts) are optional (with the exception of the plugin [name](./src/DistributableCommand.ts#30-L31)). The hooks are documented in detail in the [@qui-cli/plugin](https://www.npmjs.com/package/@qui-cli/plugin) module.
64+
65+
In combination with [@qui-cli/core](https://www.npmjs.com/package/@qui-cli/core), the plugin can be [registered an the Core invoked](./src/index.ts).
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#!/usr/bin/env node
22

3-
import '../dist.index.js';
3+
import '../dist/index.js';

examples/01 Distributable Command/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@examples/distributable-command",
33
"version": "0.0.0",
4-
"description": "",
4+
"description": "An example of a @qui-cli command that can be distributed as an Node package",
55
"homepage": "https://github.com/battis/qui-cli/tree/main/examples/01%20Distributable%20Command#readme",
66
"repository": {
77
"type": "git",
@@ -23,7 +23,10 @@
2323
"build:compile": "tsc"
2424
},
2525
"dependencies": {
26-
"@qui-cli/core": "^7.0.0"
26+
"@qui-cli/colors": "workspace:*",
27+
"@qui-cli/core": "workspace:*",
28+
"@qui-cli/log": "workspace:*",
29+
"@qui-cli/plugin": "workspace:*"
2730
},
2831
"devDependencies": {
2932
"@tsconfig/node-lts": "^24.0.0",
Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,94 @@
1+
import { Colors } from '@qui-cli/colors';
2+
import { Positionals } from '@qui-cli/core';
3+
import { Log } from '@qui-cli/log';
14
import * as Plugin from '@qui-cli/plugin';
25

3-
export type Configuration = Plugin.Configuration & {};
6+
/**
7+
* The expected configuration parameters, which may the same as or different
8+
* from the command line options
9+
*/
10+
export type Configuration = Plugin.Configuration & {
11+
target?: string;
12+
text?: string;
13+
number?: number;
14+
flag?: boolean;
15+
};
416

17+
/**
18+
* Configure positionals outside of the hooks, so that you don't run the risk of
19+
* having the configuration invoked multiple times, creating a series of
20+
* unanticipated positional arguments
21+
*/
22+
Positionals.require({
23+
target: {
24+
description: 'A positional text argument'
25+
}
26+
});
27+
Positionals.allowOnlyNamedArgs();
28+
Positionals.requireAtLeast(0);
29+
30+
/** A unique name for the command to identify it within the Plugin.Registrar */
531
export const name = 'distributable-command';
632

7-
export async function run() {}
33+
const config: Configuration = {
34+
number: 2.171
35+
};
36+
37+
/**
38+
* The command line optoons that the can be passed to the command
39+
*
40+
* @returns Plugin.Options …but don't declare that, because it is _way_ more
41+
* useful to have it typed as the literal object that it returns
42+
*/
43+
export function options() {
44+
return {
45+
man: [{ level: 1, text: 'Command Options' }],
46+
opt: {
47+
text: {
48+
description: 'A text parameter',
49+
short: 't',
50+
hint: Colors.quotedValue(`"argle bargle"`)
51+
}
52+
},
53+
num: {
54+
number: {
55+
description: 'A numeric parameter',
56+
hint: Colors.value('3.14159'),
57+
/**
58+
* Setting defaults in the config variable above allows
59+
* pre-initialization updates to the defaults by other modules that
60+
* depend on this one
61+
*/
62+
default: config.number
63+
}
64+
},
65+
flag: {
66+
flag: {
67+
description: 'A boolean parameter',
68+
short: 'f'
69+
}
70+
}
71+
};
72+
}
73+
74+
/**
75+
* Update the configuration (may be called by other modules and may be called
76+
* multiple times)
77+
*/
78+
export function configure(proposal: Configuration = {}) {
79+
for (const key in proposal) {
80+
if (proposal[key] !== undefined) {
81+
config[key] = proposal[key];
82+
}
83+
}
84+
}
85+
86+
/** Initialize the command with the command line arguments */
87+
export function init({ values }: Plugin.ExpectedArguments<typeof options>) {
88+
configure({ target: Positionals.get('target'), ...values });
89+
}
90+
91+
/** The actual "business logic" of the command */
92+
export async function run() {
93+
Log.syntaxColor({ config });
94+
}

pnpm-lock.yaml

Lines changed: 35 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)