@gunshi/plugin-global 0.26.3
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 +20 -0
- package/README.md +145 -0
- package/lib/index.d.ts +74 -0
- package/lib/index.js +122 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 kazuya kawaguchi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# @gunshi/plugin-global
|
|
2
|
+
|
|
3
|
+
> global options plugin for gunshi.
|
|
4
|
+
|
|
5
|
+
This plugin provides standard global options (`--help` and `--version`) for all commands in your CLI application. It's installed by default in gunshi, ensuring consistent behavior across all CLI applications.
|
|
6
|
+
|
|
7
|
+
## 💿 Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
# npm
|
|
11
|
+
npm install --save @gunshi/plugin-global
|
|
12
|
+
|
|
13
|
+
# pnpm
|
|
14
|
+
pnpm add @gunshi/plugin-global
|
|
15
|
+
|
|
16
|
+
# yarn
|
|
17
|
+
yarn add @gunshi/plugin-global
|
|
18
|
+
|
|
19
|
+
# deno
|
|
20
|
+
deno add jsr:@gunshi/plugin-global
|
|
21
|
+
|
|
22
|
+
# bun
|
|
23
|
+
bun add @gunshi/plugin-global
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 🚀 Usage
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import global from '@gunshi/plugin-global'
|
|
30
|
+
import { cli } from 'gunshi'
|
|
31
|
+
|
|
32
|
+
const command = {
|
|
33
|
+
name: 'my-command',
|
|
34
|
+
args: {
|
|
35
|
+
target: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
description: 'Target to process'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
run: ctx => {
|
|
41
|
+
console.log(`Processing ${ctx.values.target}`)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await cli(process.argv.slice(2), command, {
|
|
46
|
+
name: 'my-cli',
|
|
47
|
+
version: '1.0.0',
|
|
48
|
+
plugins: [
|
|
49
|
+
global() // Adds --help and --version options
|
|
50
|
+
]
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
<!-- eslint-disable markdown/no-missing-label-refs -->
|
|
55
|
+
|
|
56
|
+
> [!TIP]
|
|
57
|
+
> This plugin is installed in gunshi **by default**. You don't need to explicitly add it unless you've disabled default plugins.
|
|
58
|
+
|
|
59
|
+
<!-- eslint-enable markdown/no-missing-label-refs -->
|
|
60
|
+
|
|
61
|
+
## ✨ Features
|
|
62
|
+
|
|
63
|
+
### Global Options
|
|
64
|
+
|
|
65
|
+
This plugin automatically adds the following options to all commands:
|
|
66
|
+
|
|
67
|
+
- **`--help`, `-h`**: Display the command usage and available options
|
|
68
|
+
- **`--version`, `-v`**: Display the application version
|
|
69
|
+
|
|
70
|
+
### Automatic Behavior
|
|
71
|
+
|
|
72
|
+
When these options are used:
|
|
73
|
+
|
|
74
|
+
- **With `--help`**: The command execution is bypassed, and the usage information is displayed instead
|
|
75
|
+
- **With `--version`**: The command execution is bypassed, and only the version number is printed
|
|
76
|
+
|
|
77
|
+
## 🧩 Context Extensions
|
|
78
|
+
|
|
79
|
+
When using the global options plugin, your command context is extended via `ctx.extensions['g:global']`.
|
|
80
|
+
|
|
81
|
+
<!-- eslint-disable markdown/no-missing-label-refs -->
|
|
82
|
+
|
|
83
|
+
> [!IMPORTANT]
|
|
84
|
+
> This plugin extension is namespaced in `CommandContext.extensions` using this plugin ID `g:global` by the gunshi plugin system.
|
|
85
|
+
|
|
86
|
+
<!-- eslint-enable markdown/no-missing-label-refs -->
|
|
87
|
+
|
|
88
|
+
Available extensions:
|
|
89
|
+
|
|
90
|
+
- **`showVersion(): string`**: Display the application version. Returns `'unknown'` if no version is specified in the CLI configuration.
|
|
91
|
+
|
|
92
|
+
- **`showHeader(): Awaitable<string | undefined>`**: Display the application header. Returns `undefined` if no `renderHeader` function is provided in the CLI configuration.
|
|
93
|
+
|
|
94
|
+
- **`showUsage(): Awaitable<string | undefined>`**: Display the command usage information. This is automatically called when `--help` is used. Returns `undefined` if no `renderUsage` function is provided.
|
|
95
|
+
|
|
96
|
+
- **`showValidationErrors(error: AggregateError): Awaitable<string | undefined>`**: Display validation errors when argument validation fails. Returns `undefined` if `renderValidationErrors` is null.
|
|
97
|
+
|
|
98
|
+
### Usage Example
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import global, { pluginId } from '@gunshi/plugin-global'
|
|
102
|
+
import { cli } from 'gunshi'
|
|
103
|
+
|
|
104
|
+
const command = {
|
|
105
|
+
name: 'deploy',
|
|
106
|
+
run: async ctx => {
|
|
107
|
+
// Access globals extensions
|
|
108
|
+
const { showVersion, showHeader } = ctx.extensions[pluginId]
|
|
109
|
+
|
|
110
|
+
// Manually show version if needed
|
|
111
|
+
console.log(`Deploying with CLI version: ${showVersion()}`)
|
|
112
|
+
|
|
113
|
+
// Show custom header
|
|
114
|
+
const header = await showHeader()
|
|
115
|
+
if (header) {
|
|
116
|
+
console.log(header)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Your command logic here...
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
await cli(process.argv.slice(2), command, {
|
|
124
|
+
name: 'deploy-cli',
|
|
125
|
+
version: '2.1.0',
|
|
126
|
+
plugins: [global()],
|
|
127
|
+
|
|
128
|
+
// Optional: Custom header renderer
|
|
129
|
+
renderHeader: async () => {
|
|
130
|
+
return `
|
|
131
|
+
╔══════════════════════╗
|
|
132
|
+
║ Deploy CLI v2.1.0 ║
|
|
133
|
+
╚══════════════════════╝
|
|
134
|
+
`
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## 📚 API References
|
|
140
|
+
|
|
141
|
+
See the [API References](./docs/index.md)
|
|
142
|
+
|
|
143
|
+
## ©️ License
|
|
144
|
+
|
|
145
|
+
[MIT](http://opensource.org/licenses/MIT)
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Awaitable, PluginWithExtension } from "@gunshi/plugin";
|
|
2
|
+
|
|
3
|
+
//#region src/extension.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Extended command context which provides utilities via global options plugin.
|
|
6
|
+
* These utilities are available via `CommandContext.extensions['g:global']`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Extended command context which provides utilities via global options plugin.
|
|
11
|
+
* These utilities are available via `CommandContext.extensions['g:global']`.
|
|
12
|
+
*/
|
|
13
|
+
interface GlobalCommandContext {
|
|
14
|
+
/**
|
|
15
|
+
* Show the version of the application. if `--version` option is specified, it will print the version to the console.
|
|
16
|
+
* @returns The version of the application, or `unknown` if the version is not specified.
|
|
17
|
+
*/
|
|
18
|
+
showVersion: () => string;
|
|
19
|
+
/**
|
|
20
|
+
* Show the header of the application.
|
|
21
|
+
* @returns The header of the application, or `undefined` if the `renderHeader` is not specified.
|
|
22
|
+
*/
|
|
23
|
+
showHeader: () => Awaitable<string | undefined>;
|
|
24
|
+
/**
|
|
25
|
+
* Show the usage of the application. if `--help` option is specified, it will print the usage to the console.
|
|
26
|
+
* @returns The usage of the application, or `undefined` if the `renderUsage` is not specified.
|
|
27
|
+
*/
|
|
28
|
+
showUsage: () => Awaitable<string | undefined>;
|
|
29
|
+
/**
|
|
30
|
+
* Show validation errors. This is called when argument validation fails.
|
|
31
|
+
* @param error The aggregate error containing validation failures
|
|
32
|
+
* @returns The rendered error message, or `undefined` if `renderValidationErrors` is null
|
|
33
|
+
*/
|
|
34
|
+
showValidationErrors: (error: AggregateError) => Awaitable<string | undefined>;
|
|
35
|
+
} //#endregion
|
|
36
|
+
//#region ../shared/src/constants.d.ts
|
|
37
|
+
/**
|
|
38
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
39
|
+
* @license MIT
|
|
40
|
+
*/
|
|
41
|
+
declare const BUILT_IN_PREFIX = "_";
|
|
42
|
+
declare const PLUGIN_PREFIX = "g";
|
|
43
|
+
declare const BUILT_IN_KEY_SEPARATOR = ":";
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region ../shared/src/types.d.ts
|
|
47
|
+
/**
|
|
48
|
+
* Generate a namespaced key.
|
|
49
|
+
*/
|
|
50
|
+
type GenerateNamespacedKey<Key extends string, Prefixed extends string = typeof BUILT_IN_PREFIX> = `${Prefixed}${typeof BUILT_IN_KEY_SEPARATOR}${Key}`;
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/types.d.ts
|
|
54
|
+
/**
|
|
55
|
+
* Command i18n built-in arguments keys.
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* The unique identifier for the global options plugin.
|
|
59
|
+
*/
|
|
60
|
+
declare const pluginId: GenerateNamespacedKey<'global', typeof PLUGIN_PREFIX>;
|
|
61
|
+
/**
|
|
62
|
+
* Type representing the unique identifier for the global options plugin.
|
|
63
|
+
*/
|
|
64
|
+
type PluginId = typeof pluginId;
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/index.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* global options plugin
|
|
70
|
+
*/
|
|
71
|
+
declare function global(): PluginWithExtension<GlobalCommandContext>;
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
export { GlobalCommandContext, PluginId, global as default, pluginId };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { plugin } from "@gunshi/plugin";
|
|
2
|
+
|
|
3
|
+
//#region ../shared/src/constants.ts
|
|
4
|
+
/**
|
|
5
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
6
|
+
* @license MIT
|
|
7
|
+
*/
|
|
8
|
+
const BUILT_IN_PREFIX = "_";
|
|
9
|
+
const PLUGIN_PREFIX = "g";
|
|
10
|
+
const ARG_PREFIX = "arg";
|
|
11
|
+
const BUILT_IN_KEY_SEPARATOR = ":";
|
|
12
|
+
const BUILD_IN_PREFIX_AND_KEY_SEPARATOR = `${BUILT_IN_PREFIX}${BUILT_IN_KEY_SEPARATOR}`;
|
|
13
|
+
const ARG_PREFIX_AND_KEY_SEPARATOR = `${ARG_PREFIX}${BUILT_IN_KEY_SEPARATOR}`;
|
|
14
|
+
const COMMON_ARGS = {
|
|
15
|
+
help: {
|
|
16
|
+
type: "boolean",
|
|
17
|
+
short: "h",
|
|
18
|
+
description: "Display this help message"
|
|
19
|
+
},
|
|
20
|
+
version: {
|
|
21
|
+
type: "boolean",
|
|
22
|
+
short: "v",
|
|
23
|
+
description: "Display this version"
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region ../shared/src/utils.ts
|
|
29
|
+
function namespacedId(id) {
|
|
30
|
+
return `${PLUGIN_PREFIX}${BUILT_IN_KEY_SEPARATOR}${id}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/types.ts
|
|
35
|
+
/**
|
|
36
|
+
* The unique identifier for the global options plugin.
|
|
37
|
+
*/
|
|
38
|
+
const pluginId = namespacedId("global");
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/decorator.ts
|
|
42
|
+
/**
|
|
43
|
+
* Decorator function to extend the command with global options.
|
|
44
|
+
*/
|
|
45
|
+
const decorator = (baseRunner) => async (ctx) => {
|
|
46
|
+
const { values, validationError, extensions: { [pluginId]: { showVersion, showHeader, showUsage, showValidationErrors } } } = ctx;
|
|
47
|
+
if (values.version) return showVersion();
|
|
48
|
+
const buf = [];
|
|
49
|
+
const header = await showHeader();
|
|
50
|
+
if (header) buf.push(header);
|
|
51
|
+
if (values.help) {
|
|
52
|
+
const usage = await showUsage();
|
|
53
|
+
if (usage) {
|
|
54
|
+
buf.push(usage);
|
|
55
|
+
return buf.join("\n");
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (validationError) return await showValidationErrors(validationError);
|
|
60
|
+
return baseRunner(ctx);
|
|
61
|
+
};
|
|
62
|
+
var decorator_default = decorator;
|
|
63
|
+
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/extension.ts
|
|
66
|
+
function extension(ctx) {
|
|
67
|
+
return {
|
|
68
|
+
showVersion: () => {
|
|
69
|
+
const version = ctx.env.version || "unknown";
|
|
70
|
+
if (!ctx.env.usageSilent) ctx.log(version);
|
|
71
|
+
return version;
|
|
72
|
+
},
|
|
73
|
+
showHeader: async () => {
|
|
74
|
+
let header;
|
|
75
|
+
if (ctx.env.renderHeader != null) {
|
|
76
|
+
header = await ctx.env.renderHeader(ctx);
|
|
77
|
+
if (header) {
|
|
78
|
+
ctx.log(header);
|
|
79
|
+
ctx.log();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return header;
|
|
83
|
+
},
|
|
84
|
+
showUsage: async () => {
|
|
85
|
+
if (ctx.env.renderUsage != null) {
|
|
86
|
+
const usage = await ctx.env.renderUsage(ctx);
|
|
87
|
+
if (usage) {
|
|
88
|
+
ctx.log(usage);
|
|
89
|
+
return usage;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
showValidationErrors: async (error) => {
|
|
94
|
+
if (ctx.env.renderValidationErrors === null) return;
|
|
95
|
+
if (ctx.env.renderValidationErrors !== void 0) {
|
|
96
|
+
const message = await ctx.env.renderValidationErrors(ctx, error);
|
|
97
|
+
ctx.log(message);
|
|
98
|
+
return message;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/index.ts
|
|
106
|
+
/**
|
|
107
|
+
* global options plugin
|
|
108
|
+
*/
|
|
109
|
+
function global() {
|
|
110
|
+
return plugin({
|
|
111
|
+
id: pluginId,
|
|
112
|
+
name: "global options",
|
|
113
|
+
extension,
|
|
114
|
+
setup(ctx) {
|
|
115
|
+
for (const [name, schema] of Object.entries(COMMON_ARGS)) ctx.addGlobalOption(name, schema);
|
|
116
|
+
ctx.decorateCommand(decorator_default);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
//#endregion
|
|
122
|
+
export { global as default, pluginId };
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gunshi/plugin-global",
|
|
3
|
+
"description": "global options plugin for gunshi",
|
|
4
|
+
"version": "0.26.3",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "kazuya kawaguchi",
|
|
7
|
+
"email": "kawakazu80@gmail.com"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"funding": "https://github.com/sponsors/kazupon",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/kazupon/gunshi/issues"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/kazupon/gunshi.git",
|
|
17
|
+
"directory": "packages/plugin-global"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"gunshi",
|
|
21
|
+
"plugin",
|
|
22
|
+
"cli"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">= 20"
|
|
29
|
+
},
|
|
30
|
+
"type": "module",
|
|
31
|
+
"files": [
|
|
32
|
+
"lib"
|
|
33
|
+
],
|
|
34
|
+
"module": "lib/index.js",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./lib/index.d.ts",
|
|
38
|
+
"import": "./lib/index.js",
|
|
39
|
+
"require": "./lib/index.js",
|
|
40
|
+
"default": "./lib/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./package.json": "./package.json"
|
|
43
|
+
},
|
|
44
|
+
"types": "lib/index.d.ts",
|
|
45
|
+
"typesVersions": {
|
|
46
|
+
"*": {
|
|
47
|
+
"*": [
|
|
48
|
+
"./lib/*",
|
|
49
|
+
"./*"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@gunshi/plugin": "0.26.3"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"deno": "^2.3.3",
|
|
58
|
+
"jsr": "^0.13.4",
|
|
59
|
+
"jsr-exports-lint": "^0.4.1",
|
|
60
|
+
"publint": "^0.3.12",
|
|
61
|
+
"tsdown": "^0.12.3",
|
|
62
|
+
"typedoc": "^0.28.4",
|
|
63
|
+
"typedoc-plugin-markdown": "^4.6.3",
|
|
64
|
+
"@gunshi/shared": "0.26.3"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsdown",
|
|
68
|
+
"build:docs": "typedoc --excludeInternal",
|
|
69
|
+
"lint:jsr": "jsr publish --dry-run --allow-dirty",
|
|
70
|
+
"typecheck:deno": "deno check ./src"
|
|
71
|
+
}
|
|
72
|
+
}
|