gunshi 0.2.0 → 0.2.2
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/lib/context-DmZAeiph.js +178 -0
- package/lib/context.d.ts +48 -12
- package/lib/context.js +4 -0
- package/lib/index.d.ts +14 -2
- package/lib/index.js +5 -640
- package/lib/renderer-Bo0DibAK.js +115 -0
- package/lib/renderer.d.ts +24 -5
- package/lib/renderer.js +4 -0
- package/lib/types.d-00BVt8hZ.d.ts +316 -0
- package/lib/utils-NHs5DuHk.js +24 -0
- package/package.json +3 -4
- package/lib/cli.d.ts +0 -9
- package/lib/constants.d.ts +0 -14
- package/lib/types.d.ts +0 -302
- package/lib/utils.d.ts +0 -6
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { create } from "./utils-NHs5DuHk.js";
|
|
2
|
+
|
|
3
|
+
//#region src/renderer.ts
|
|
4
|
+
function renderHeader(ctx) {
|
|
5
|
+
const title = ctx.env.description || ctx.env.name || "";
|
|
6
|
+
return Promise.resolve(title ? `${title} (${ctx.env.name || ""}${ctx.env.version ? ` v${ctx.env.version}` : ""})` : title);
|
|
7
|
+
}
|
|
8
|
+
async function renderUsage(ctx) {
|
|
9
|
+
const messages = [];
|
|
10
|
+
if (!ctx.omitted && hasDescription(ctx)) messages.push(ctx.description, "");
|
|
11
|
+
messages.push(...await renderUsageSection(ctx), "");
|
|
12
|
+
if (ctx.omitted && await hasCommands(ctx)) messages.push(...await renderCommandsSection(ctx), "");
|
|
13
|
+
if (hasOptions(ctx)) messages.push(...await renderOptionsSection(ctx), "");
|
|
14
|
+
if (hasExamples(ctx)) messages.push(...renderExamplesSection(ctx), "");
|
|
15
|
+
return messages.join("\n");
|
|
16
|
+
}
|
|
17
|
+
function renderValidationErrors(_ctx, error) {
|
|
18
|
+
const messages = [];
|
|
19
|
+
for (const err of error.errors) messages.push(err.message);
|
|
20
|
+
return Promise.resolve(messages.join("\n"));
|
|
21
|
+
}
|
|
22
|
+
async function renderOptionsSection(ctx) {
|
|
23
|
+
const messages = [];
|
|
24
|
+
messages.push(`${ctx.translation("OPTIONS")}:`);
|
|
25
|
+
const optionsPairs = getOptionsPairs(ctx);
|
|
26
|
+
messages.push(await generateOptionsUsage(ctx, optionsPairs));
|
|
27
|
+
return messages;
|
|
28
|
+
}
|
|
29
|
+
function renderExamplesSection(ctx) {
|
|
30
|
+
const messages = [];
|
|
31
|
+
const examples = ctx.usage.examples.split("\n").map((example) => example.padStart(ctx.env.leftMargin + example.length));
|
|
32
|
+
messages.push(`${ctx.translation("EXAMPLES")}:`, ...examples);
|
|
33
|
+
return messages;
|
|
34
|
+
}
|
|
35
|
+
async function renderUsageSection(ctx) {
|
|
36
|
+
const messages = [`${ctx.translation("USAGE")}:`];
|
|
37
|
+
if (ctx.omitted) {
|
|
38
|
+
const defaultCommand = `${resolveEntry(ctx)}${await hasCommands(ctx) ? ` [${resolveSubCommand(ctx)}]` : ""} ${hasOptions(ctx) ? `<${ctx.translation("OPTIONS")}>` : ""} `;
|
|
39
|
+
messages.push(defaultCommand.padStart(ctx.env.leftMargin + defaultCommand.length));
|
|
40
|
+
if (await hasCommands(ctx)) {
|
|
41
|
+
const commandsUsage = `${resolveEntry(ctx)} <${ctx.translation("COMMANDS")}>`;
|
|
42
|
+
messages.push(commandsUsage.padStart(ctx.env.leftMargin + commandsUsage.length));
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
const usageStr = `${resolveEntry(ctx)} ${resolveSubCommand(ctx)} ${generateOptionsSymbols(ctx)}`;
|
|
46
|
+
messages.push(usageStr.padStart(ctx.env.leftMargin + usageStr.length));
|
|
47
|
+
}
|
|
48
|
+
return messages;
|
|
49
|
+
}
|
|
50
|
+
async function renderCommandsSection(ctx) {
|
|
51
|
+
const messages = [`${ctx.translation("COMMANDS")}:`];
|
|
52
|
+
const loadedCommands = await ctx.loadCommands();
|
|
53
|
+
const commandMaxLength = Math.max(...loadedCommands.map((cmd) => (cmd.name || "").length));
|
|
54
|
+
const commandsStr = await Promise.all(loadedCommands.map((cmd) => {
|
|
55
|
+
const key = cmd.name || "";
|
|
56
|
+
const desc = cmd.description || "";
|
|
57
|
+
const command = `${key.padEnd(commandMaxLength + ctx.env.middleMargin)}${desc} `;
|
|
58
|
+
return `${command.padStart(ctx.env.leftMargin + command.length)} `;
|
|
59
|
+
}));
|
|
60
|
+
messages.push(...commandsStr, "", ctx.translation("FORMORE"));
|
|
61
|
+
messages.push(...loadedCommands.map((cmd) => {
|
|
62
|
+
const commandHelp = `${ctx.env.name} ${cmd.name} --help`;
|
|
63
|
+
return `${commandHelp.padStart(ctx.env.leftMargin + commandHelp.length)}`;
|
|
64
|
+
}));
|
|
65
|
+
return messages;
|
|
66
|
+
}
|
|
67
|
+
function resolveEntry(ctx) {
|
|
68
|
+
return ctx.env.name || ctx.translation("COMMAND");
|
|
69
|
+
}
|
|
70
|
+
function resolveSubCommand(ctx) {
|
|
71
|
+
return ctx.name || ctx.translation("SUBCOMMAND");
|
|
72
|
+
}
|
|
73
|
+
function hasDescription(ctx) {
|
|
74
|
+
return !!ctx.description;
|
|
75
|
+
}
|
|
76
|
+
async function hasCommands(ctx) {
|
|
77
|
+
const loadedCommands = await ctx.loadCommands();
|
|
78
|
+
return loadedCommands.length > 1;
|
|
79
|
+
}
|
|
80
|
+
function hasOptions(ctx) {
|
|
81
|
+
return !!(ctx.options && Object.keys(ctx.options).length > 0);
|
|
82
|
+
}
|
|
83
|
+
function hasExamples(ctx) {
|
|
84
|
+
return !!ctx.usage.examples;
|
|
85
|
+
}
|
|
86
|
+
function hasAllDefaultOptions(ctx) {
|
|
87
|
+
return !!(ctx.options && Object.values(ctx.options).every((opt) => opt.default));
|
|
88
|
+
}
|
|
89
|
+
function generateOptionsSymbols(ctx) {
|
|
90
|
+
return hasOptions(ctx) ? hasAllDefaultOptions(ctx) ? `[${ctx.translation("OPTIONS")}]` : `<${ctx.translation("OPTIONS")}>` : "";
|
|
91
|
+
}
|
|
92
|
+
function getOptionsPairs(ctx) {
|
|
93
|
+
return Object.entries(ctx.options).reduce((acc, [name, value]) => {
|
|
94
|
+
let key = `--${name}`;
|
|
95
|
+
if (value.short) key = `-${value.short}, ${key}`;
|
|
96
|
+
if (value.type !== "boolean") key = value.default ? `${key} [${name}]` : `${key} <${name}>`;
|
|
97
|
+
acc[name] = key;
|
|
98
|
+
return acc;
|
|
99
|
+
}, create());
|
|
100
|
+
}
|
|
101
|
+
async function generateOptionsUsage(ctx, optionsPairs) {
|
|
102
|
+
const optionsMaxLength = Math.max(...Object.entries(optionsPairs).map(([_, value]) => value.length));
|
|
103
|
+
const optionSchemaMaxLength = ctx.env.usageOptionType ? Math.max(...Object.entries(optionsPairs).map(([key, _]) => ctx.options[key].type.length)) : 0;
|
|
104
|
+
const usages = await Promise.all(Object.entries(optionsPairs).map(([key, value]) => {
|
|
105
|
+
const rawDesc = ctx.translation(key);
|
|
106
|
+
const optionsSchema = ctx.env.usageOptionType ? `[${ctx.options[key].type}] ` : "";
|
|
107
|
+
const desc = `${optionsSchema ? optionsSchema.padEnd(optionSchemaMaxLength + 3) : ""}${rawDesc}`;
|
|
108
|
+
const option = `${value.padEnd(optionsMaxLength + ctx.env.middleMargin)}${desc}`;
|
|
109
|
+
return `${option.padStart(ctx.env.leftMargin + option.length)}`;
|
|
110
|
+
}));
|
|
111
|
+
return usages.join("\n");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
//#endregion
|
|
115
|
+
export { renderHeader, renderUsage, renderValidationErrors };
|
package/lib/renderer.d.ts
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { ArgOptions } from 'args-tokens';
|
|
2
|
+
import { b as CommandContext } from './types.d-00BVt8hZ.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Render the header
|
|
6
|
+
* @param ctx A {@link CommandContext | command context}
|
|
7
|
+
* @returns A rendered header
|
|
8
|
+
*/
|
|
9
|
+
declare function renderHeader<Options extends ArgOptions>(ctx: Readonly<CommandContext<Options>>): Promise<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Render the usage
|
|
12
|
+
* @param ctx A {@link CommandContext | command context}
|
|
13
|
+
* @returns A rendered usage
|
|
14
|
+
*/
|
|
15
|
+
declare function renderUsage<Options extends ArgOptions>(ctx: Readonly<CommandContext<Options>>): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Render the validation errors
|
|
18
|
+
* @param ctx A {@link CommandContext | command context}
|
|
19
|
+
* @param error An {@link AggregateError} of option in `args-token` validation
|
|
20
|
+
* @returns A rendered validation error
|
|
21
|
+
*/
|
|
22
|
+
declare function renderValidationErrors<Options extends ArgOptions>(_ctx: CommandContext<Options>, error: AggregateError): Promise<string>;
|
|
23
|
+
|
|
24
|
+
export { renderHeader, renderUsage, renderValidationErrors };
|
package/lib/renderer.js
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { ArgOptions, ArgValues } from 'args-tokens';
|
|
2
|
+
|
|
3
|
+
declare const COMMON_OPTIONS: {
|
|
4
|
+
readonly help: {
|
|
5
|
+
readonly type: "boolean"
|
|
6
|
+
readonly short: "h"
|
|
7
|
+
}
|
|
8
|
+
readonly version: {
|
|
9
|
+
readonly type: "boolean"
|
|
10
|
+
readonly short: "v"
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
declare const COMMAND_OPTIONS_DEFAULT: CommandOptions<ArgOptions>;
|
|
14
|
+
declare const COMMAND_I18N_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "OPTIONS", "EXAMPLES", "FORMORE"];
|
|
15
|
+
|
|
16
|
+
declare const __constants_COMMAND_I18N_RESOURCE_KEYS: typeof COMMAND_I18N_RESOURCE_KEYS;
|
|
17
|
+
declare const __constants_COMMAND_OPTIONS_DEFAULT: typeof COMMAND_OPTIONS_DEFAULT;
|
|
18
|
+
declare const __constants_COMMON_OPTIONS: typeof COMMON_OPTIONS;
|
|
19
|
+
declare namespace __constants {
|
|
20
|
+
export { __constants_COMMAND_I18N_RESOURCE_KEYS as COMMAND_I18N_RESOURCE_KEYS, __constants_COMMAND_OPTIONS_DEFAULT as COMMAND_OPTIONS_DEFAULT, __constants_COMMON_OPTIONS as COMMON_OPTIONS };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Define a promise type that can be await from T
|
|
25
|
+
*/
|
|
26
|
+
type Awaitable<T> = T | Promise<T>;
|
|
27
|
+
/**
|
|
28
|
+
* Command i18n built-in options keys
|
|
29
|
+
* @experimental
|
|
30
|
+
*/
|
|
31
|
+
type CommandBuiltinOptionsKeys = keyof (typeof __constants)["COMMON_OPTIONS"];
|
|
32
|
+
/**
|
|
33
|
+
* Command i18n built-in resource keys
|
|
34
|
+
* @experimental
|
|
35
|
+
*/
|
|
36
|
+
type CommandBuiltinResourceKeys = (typeof __constants)["COMMAND_I18N_RESOURCE_KEYS"][number];
|
|
37
|
+
/**
|
|
38
|
+
* Command i18n built-in keys
|
|
39
|
+
* @description The command i18n built-in keys are used to {@link CommandContext.translation | translate} function
|
|
40
|
+
* @experimental
|
|
41
|
+
*/
|
|
42
|
+
type CommandBuiltinKeys = CommandBuiltinOptionsKeys | CommandBuiltinResourceKeys | "description" | "examples";
|
|
43
|
+
/**
|
|
44
|
+
* Command environment
|
|
45
|
+
*/
|
|
46
|
+
interface CommandEnvironment<Options extends ArgOptions = ArgOptions> {
|
|
47
|
+
/**
|
|
48
|
+
* Current working directory
|
|
49
|
+
* @see {@link CommandOptions.cwd}
|
|
50
|
+
*/
|
|
51
|
+
cwd: string | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Command name
|
|
54
|
+
* @see {@link CommandOptions.name}
|
|
55
|
+
*/
|
|
56
|
+
name: string | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Command description
|
|
59
|
+
* @see {@link CommandOptions.description}
|
|
60
|
+
*
|
|
61
|
+
*/
|
|
62
|
+
description: string | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Command version
|
|
65
|
+
* @see {@link CommandOptions.version}
|
|
66
|
+
*/
|
|
67
|
+
version: string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Left margin of the command output
|
|
70
|
+
* @default 2
|
|
71
|
+
* @see {@link CommandOptions.leftMargin}
|
|
72
|
+
*/
|
|
73
|
+
leftMargin: number;
|
|
74
|
+
/**
|
|
75
|
+
* Middle margin of the command output
|
|
76
|
+
* @default 10
|
|
77
|
+
* @see {@link CommandOptions.middleMargin}
|
|
78
|
+
*/
|
|
79
|
+
middleMargin: number;
|
|
80
|
+
/**
|
|
81
|
+
* Whether to display the usage option type
|
|
82
|
+
* @default false
|
|
83
|
+
* @see {@link CommandOptions.usageOptionType}
|
|
84
|
+
*/
|
|
85
|
+
usageOptionType: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Sub commands
|
|
88
|
+
* @see {@link CommandOptions.subCommands}
|
|
89
|
+
*/
|
|
90
|
+
subCommands: Map<string, Command<Options> | LazyCommand<Options>> | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Render function the command usage
|
|
93
|
+
*/
|
|
94
|
+
renderUsage: ((ctx: CommandContext<Options>) => Promise<string>) | null | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Render function the header section in the command usage
|
|
97
|
+
*/
|
|
98
|
+
renderHeader: ((ctx: CommandContext<Options>) => Promise<string>) | null | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Render function the validation errors
|
|
101
|
+
*/
|
|
102
|
+
renderValidationErrors: ((ctx: CommandContext<Options>, error: AggregateError) => Promise<string>) | null | undefined;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Command options
|
|
106
|
+
*/
|
|
107
|
+
interface CommandOptions<Options extends ArgOptions> {
|
|
108
|
+
/**
|
|
109
|
+
* Current working directory
|
|
110
|
+
*/
|
|
111
|
+
cwd?: string;
|
|
112
|
+
/**
|
|
113
|
+
* Command program name
|
|
114
|
+
*/
|
|
115
|
+
name?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Command program description
|
|
118
|
+
*
|
|
119
|
+
*/
|
|
120
|
+
description?: string;
|
|
121
|
+
/**
|
|
122
|
+
* Command program version
|
|
123
|
+
*/
|
|
124
|
+
version?: string;
|
|
125
|
+
/**
|
|
126
|
+
* Command program locale
|
|
127
|
+
*/
|
|
128
|
+
locale?: string | Intl.Locale;
|
|
129
|
+
/**
|
|
130
|
+
* Sub commands
|
|
131
|
+
*/
|
|
132
|
+
subCommands?: Map<string, Command<Options> | LazyCommand<Options>>;
|
|
133
|
+
/**
|
|
134
|
+
* Left margin of the command output
|
|
135
|
+
*/
|
|
136
|
+
leftMargin?: number;
|
|
137
|
+
/**
|
|
138
|
+
* Middle margin of the command output
|
|
139
|
+
*/
|
|
140
|
+
middleMargin?: number;
|
|
141
|
+
/**
|
|
142
|
+
* Whether to display the usage option type
|
|
143
|
+
*/
|
|
144
|
+
usageOptionType?: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Render function the command usage
|
|
147
|
+
*/
|
|
148
|
+
renderUsage?: ((ctx: Readonly<CommandContext<Options>>) => Promise<string>) | null;
|
|
149
|
+
/**
|
|
150
|
+
* Render function the header section in the command usage
|
|
151
|
+
*/
|
|
152
|
+
renderHeader?: ((ctx: Readonly<CommandContext<Options>>) => Promise<string>) | null;
|
|
153
|
+
/**
|
|
154
|
+
* Render function the validation errors
|
|
155
|
+
*/
|
|
156
|
+
renderValidationErrors?: ((ctx: Readonly<CommandContext<Options>>, error: AggregateError) => Promise<string>) | null;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Command context
|
|
160
|
+
* @description Command context is the context of the command execution
|
|
161
|
+
*/
|
|
162
|
+
interface CommandContext<
|
|
163
|
+
Options extends ArgOptions,
|
|
164
|
+
Values = ArgValues<Options>
|
|
165
|
+
> {
|
|
166
|
+
/**
|
|
167
|
+
* Command name, that is the command that is executed
|
|
168
|
+
* @description The command name is same {@link CommandEnvironment.name}
|
|
169
|
+
*/
|
|
170
|
+
name: string | undefined;
|
|
171
|
+
/**
|
|
172
|
+
* Command description, that is the description of the command that is executed
|
|
173
|
+
* @description The command description is same {@link CommandEnvironment.description}
|
|
174
|
+
*/
|
|
175
|
+
description: string | undefined;
|
|
176
|
+
/**
|
|
177
|
+
* Command locale, that is the locale of the command that is executed
|
|
178
|
+
*/
|
|
179
|
+
locale: Intl.Locale;
|
|
180
|
+
/**
|
|
181
|
+
* Command environment, that is the environment of the command that is executed
|
|
182
|
+
* @description The command environment is same {@link CommandEnvironment}
|
|
183
|
+
*/
|
|
184
|
+
env: CommandEnvironment<Options>;
|
|
185
|
+
/**
|
|
186
|
+
* Command options, that is the options of the command that is executed
|
|
187
|
+
* @description The command options is same {@link Command.options}
|
|
188
|
+
*/
|
|
189
|
+
options: Options | undefined;
|
|
190
|
+
/**
|
|
191
|
+
* Command values, that is the values of the command that is executed
|
|
192
|
+
* @description Resolve values with `resolveArgs` from command arguments and {@link Command.options}
|
|
193
|
+
*/
|
|
194
|
+
values: Values;
|
|
195
|
+
/**
|
|
196
|
+
* Command positionals arguments, that is the positionals of the command that is executed
|
|
197
|
+
* @description Resolve positionals with `resolveArgs` from command arguments
|
|
198
|
+
*/
|
|
199
|
+
positionals: string[];
|
|
200
|
+
/**
|
|
201
|
+
* Whether the currently executing command has been executed with the sub-command name omitted
|
|
202
|
+
*/
|
|
203
|
+
omitted: boolean;
|
|
204
|
+
/**
|
|
205
|
+
* Command usage
|
|
206
|
+
* @description Usage of the command is same {@link Command.usage}, and more has `--help` and `--version` options
|
|
207
|
+
*/
|
|
208
|
+
usage: CommandUsage<Options>;
|
|
209
|
+
/**
|
|
210
|
+
* Load sub-commands
|
|
211
|
+
* @description The loaded commands are cached and returned when called again
|
|
212
|
+
* @returns loaded commands
|
|
213
|
+
*/
|
|
214
|
+
loadCommands: () => Promise<Command<Options>[]>;
|
|
215
|
+
/**
|
|
216
|
+
* Translation function
|
|
217
|
+
* @param key the key to be translated
|
|
218
|
+
* @returns A translated string
|
|
219
|
+
* @experimental
|
|
220
|
+
*/
|
|
221
|
+
translation: <
|
|
222
|
+
T = CommandBuiltinKeys,
|
|
223
|
+
Key = CommandBuiltinKeys | T
|
|
224
|
+
>(key: Key) => string;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Command usage
|
|
228
|
+
*/
|
|
229
|
+
interface CommandUsage<Options extends ArgOptions> {
|
|
230
|
+
/**
|
|
231
|
+
* Options usage
|
|
232
|
+
*/
|
|
233
|
+
options?: { [Option in keyof Options] : string };
|
|
234
|
+
/**
|
|
235
|
+
* Examples usage
|
|
236
|
+
*/
|
|
237
|
+
examples?: string;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Command interface
|
|
241
|
+
*/
|
|
242
|
+
interface Command<Options extends ArgOptions> {
|
|
243
|
+
/**
|
|
244
|
+
* Command name
|
|
245
|
+
* @description
|
|
246
|
+
* Command name is used to find command line arguments to execute from sub commands, so it's recommended to specify.
|
|
247
|
+
*/
|
|
248
|
+
name?: string;
|
|
249
|
+
/**
|
|
250
|
+
* Command description
|
|
251
|
+
* @description
|
|
252
|
+
* Command description is used to describe the command in usage, so it's recommended to specify.
|
|
253
|
+
*/
|
|
254
|
+
description?: string;
|
|
255
|
+
/**
|
|
256
|
+
* whether the command is default or not
|
|
257
|
+
* @description if the command is default, it is executed when no sub-command is specified
|
|
258
|
+
*/
|
|
259
|
+
default?: boolean;
|
|
260
|
+
/**
|
|
261
|
+
* Command options
|
|
262
|
+
*/
|
|
263
|
+
options?: Options;
|
|
264
|
+
/**
|
|
265
|
+
* Command usage
|
|
266
|
+
* @description
|
|
267
|
+
* Command usage is used to describe the command in usage, so it's recommended to specify.
|
|
268
|
+
*/
|
|
269
|
+
usage?: CommandUsage<Options>;
|
|
270
|
+
/**
|
|
271
|
+
* Command runner, that's the command to be executed
|
|
272
|
+
*/
|
|
273
|
+
run: CommandRunner<Options>;
|
|
274
|
+
/**
|
|
275
|
+
* Command resource fetcher
|
|
276
|
+
* @experimental
|
|
277
|
+
*/
|
|
278
|
+
resource?: CommandResourceFetcher<Options>;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Command resource
|
|
282
|
+
* @experimental
|
|
283
|
+
*/
|
|
284
|
+
interface CommandResource<Options extends ArgOptions> {
|
|
285
|
+
/**
|
|
286
|
+
* Command description
|
|
287
|
+
*/
|
|
288
|
+
description: string;
|
|
289
|
+
/**
|
|
290
|
+
* Options usage
|
|
291
|
+
*/
|
|
292
|
+
options: { [Option in keyof Options] : string };
|
|
293
|
+
/**
|
|
294
|
+
* Examples usage
|
|
295
|
+
*/
|
|
296
|
+
examples: string;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Command resource fetcher
|
|
300
|
+
* @param ctx A {@link CommandContext | command context}
|
|
301
|
+
* @returns A fetched {@link CommandResource | command resource}
|
|
302
|
+
* @experimental
|
|
303
|
+
*/
|
|
304
|
+
type CommandResourceFetcher<Options extends ArgOptions> = (ctx: Readonly<CommandContext<Options>>) => Promise<CommandResource<Options>>;
|
|
305
|
+
/**
|
|
306
|
+
* Command runner
|
|
307
|
+
* @param ctx A {@link CommandContext | command context}
|
|
308
|
+
*/
|
|
309
|
+
type CommandRunner<Options extends ArgOptions> = (ctx: Readonly<CommandContext<Options>>) => Awaitable<void>;
|
|
310
|
+
/**
|
|
311
|
+
* Lazy command interface
|
|
312
|
+
* @description lazy command that's not loaded until it is executed
|
|
313
|
+
*/
|
|
314
|
+
type LazyCommand<Options extends ArgOptions> = () => Awaitable<Command<Options>>;
|
|
315
|
+
|
|
316
|
+
export type { Command as C, LazyCommand as L, CommandOptions as a, CommandContext as b, CommandRunner as c, CommandBuiltinOptionsKeys as d, CommandBuiltinResourceKeys as e, CommandBuiltinKeys as f, CommandEnvironment as g, CommandResource as h, CommandResourceFetcher as i };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/utils.ts
|
|
3
|
+
async function resolveLazyCommand(cmd, name, entry = false) {
|
|
4
|
+
const resolved = Object.assign(create(), typeof cmd == "function" ? await cmd() : cmd, { default: entry });
|
|
5
|
+
if (resolved.name == null && name) resolved.name = name;
|
|
6
|
+
return deepFreeze(resolved);
|
|
7
|
+
}
|
|
8
|
+
function create(obj = null) {
|
|
9
|
+
return Object.create(obj);
|
|
10
|
+
}
|
|
11
|
+
function log(...args) {
|
|
12
|
+
console.log(...args);
|
|
13
|
+
}
|
|
14
|
+
function deepFreeze(obj) {
|
|
15
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
16
|
+
for (const key of Object.keys(obj)) {
|
|
17
|
+
const value = obj[key];
|
|
18
|
+
if (typeof value === "object" && value !== null) deepFreeze(value);
|
|
19
|
+
}
|
|
20
|
+
return Object.freeze(obj);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
export { create, deepFreeze, log, resolveLazyCommand };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gunshi",
|
|
3
3
|
"description": "Modern javascript command-line library",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "kazuya kawaguchi",
|
|
7
7
|
"email": "kawakazu80@gmail.com"
|
|
@@ -88,10 +88,9 @@
|
|
|
88
88
|
"lint-staged": "^15.4.3",
|
|
89
89
|
"pkg-pr-new": "^0.0.40",
|
|
90
90
|
"prettier": "^3.5.3",
|
|
91
|
-
"
|
|
91
|
+
"tsdown": "^0.6.4",
|
|
92
92
|
"typescript": "^5.8.2",
|
|
93
93
|
"typescript-eslint": "^8.26.0",
|
|
94
|
-
"unplugin-isolated-decl": "^0.13.1",
|
|
95
94
|
"vitest": "^3.0.7"
|
|
96
95
|
},
|
|
97
96
|
"prettier": "@kazupon/prettier-config",
|
|
@@ -109,7 +108,7 @@
|
|
|
109
108
|
]
|
|
110
109
|
},
|
|
111
110
|
"scripts": {
|
|
112
|
-
"build": "
|
|
111
|
+
"build": "tsdown",
|
|
113
112
|
"changelog": "gh-changelogen --repo=kazupon/gunshi",
|
|
114
113
|
"clean": "git clean -df",
|
|
115
114
|
"dev": "pnpx @eslint/config-inspector --config eslint.config.ts",
|
package/lib/cli.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ArgOptions } from "args-tokens";
|
|
2
|
-
import type { Command, CommandOptions, CommandRunner } from "./types.js";
|
|
3
|
-
/**
|
|
4
|
-
* Run the command
|
|
5
|
-
* @param args - command line arguments
|
|
6
|
-
* @param entry - a {@link Command | entry command} or an {@link CommandRunner | inline command runner}
|
|
7
|
-
* @param opts - a {@link CommandOptions | command options}
|
|
8
|
-
*/
|
|
9
|
-
export declare function cli<Options extends ArgOptions>(args: string[], entry: Command<Options> | CommandRunner<Options>, opts?: CommandOptions<Options>): Promise<void>;
|
package/lib/constants.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { ArgOptions } from "args-tokens";
|
|
2
|
-
import type { CommandOptions } from "./types.js";
|
|
3
|
-
export declare const COMMON_OPTIONS: {
|
|
4
|
-
readonly help: {
|
|
5
|
-
readonly type: "boolean"
|
|
6
|
-
readonly short: "h"
|
|
7
|
-
}
|
|
8
|
-
readonly version: {
|
|
9
|
-
readonly type: "boolean"
|
|
10
|
-
readonly short: "v"
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
export declare const COMMAND_OPTIONS_DEFAULT: CommandOptions<ArgOptions>;
|
|
14
|
-
export declare const COMMAND_I18N_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "OPTIONS", "EXAMPLES", "FORMORE"];
|