gunshi 0.6.2 → 0.8.0
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/README.md +2 -2
- package/lib/{context-DmZAeiph.js → context-DYokJ5k3.js} +52 -54
- package/lib/context.d.ts +3 -7
- package/lib/context.js +3 -3
- package/lib/index.d.ts +13 -3
- package/lib/index.js +6 -5
- package/lib/renderer/index.d.ts +1 -1
- package/lib/renderer/index.js +2 -2
- package/lib/{renderer-v5Uq0km9.js → renderer-KLx2dW-W.js} +14 -15
- package/lib/{types.d-CxaX4FVV.d.ts → types.d-CX4RmDVT.d.ts} +91 -21
- package/lib/utils-CU_LSsUg.js +63 -0
- package/package.json +3 -1
- package/lib/utils-NHs5DuHk.js +0 -24
package/README.md
CHANGED
|
@@ -317,7 +317,7 @@ const customUsageRenderer = ctx => {
|
|
|
317
317
|
|
|
318
318
|
for (const [key, option] of Object.entries(ctx.options || Object.create(null))) {
|
|
319
319
|
const shortFlag = option.short ? `-${option.short}, ` : ' '
|
|
320
|
-
lines.push(` ${shortFlag}--${key.padEnd(10)} ${ctx.
|
|
320
|
+
lines.push(` ${shortFlag}--${key.padEnd(10)} ${ctx.translate(key)}`)
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
return Promise.resolve(lines.join('\n'))
|
|
@@ -365,7 +365,7 @@ const command = {
|
|
|
365
365
|
},
|
|
366
366
|
run: ctx => {
|
|
367
367
|
const { name = 'World', formal } = ctx.values
|
|
368
|
-
const greeting = formal ? ctx.
|
|
368
|
+
const greeting = formal ? ctx.translate('formal_greeting') : ctx.translate('informal_greeting')
|
|
369
369
|
console.log(`${greeting}, ${name}!`)
|
|
370
370
|
}
|
|
371
371
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { create, deepFreeze, resolveLazyCommand } from "./utils-
|
|
1
|
+
import { BUILT_IN_PREFIX, COMMAND_OPTIONS_DEFAULT, DEFAULT_LOCALE, create, deepFreeze, mapResourceWithBuiltinKey, resolveLazyCommand } from "./utils-CU_LSsUg.js";
|
|
2
2
|
|
|
3
3
|
//#region locales/en-US.json
|
|
4
4
|
var COMMAND = "COMMAND";
|
|
@@ -23,48 +23,47 @@ var en_US_default = {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
//#endregion
|
|
26
|
-
//#region src/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
//#region src/translation.ts
|
|
27
|
+
function createTranslationAdapter(options) {
|
|
28
|
+
return new DefaultTranslation(options);
|
|
29
|
+
}
|
|
30
|
+
var DefaultTranslation = class {
|
|
31
|
+
#resources = new Map();
|
|
32
|
+
options;
|
|
33
|
+
constructor(options) {
|
|
34
|
+
this.options = options;
|
|
35
|
+
this.#resources = new Map();
|
|
36
|
+
}
|
|
37
|
+
getResource(locale) {
|
|
38
|
+
return this.#resources.get(locale);
|
|
39
|
+
}
|
|
40
|
+
setResource(locale, resource) {
|
|
41
|
+
this.#resources.set(locale, resource);
|
|
42
|
+
}
|
|
43
|
+
getMessage(locale, key) {
|
|
44
|
+
const resource = this.getResource(locale);
|
|
45
|
+
if (resource) return resource[key];
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
translate(locale, key, _values = create()) {
|
|
49
|
+
/**
|
|
50
|
+
* NOTE:
|
|
51
|
+
* DefaultTranslation support static message only
|
|
52
|
+
* If you want to resolve message with values and use the complex message format,
|
|
53
|
+
* you should inherit this class or implement your own translation adapter.
|
|
54
|
+
*/
|
|
55
|
+
return this.getMessage(locale, key) || this.getMessage(this.options.fallbackLocale, key);
|
|
35
56
|
}
|
|
36
57
|
};
|
|
37
|
-
const COMMAND_OPTIONS_DEFAULT = {
|
|
38
|
-
name: undefined,
|
|
39
|
-
description: undefined,
|
|
40
|
-
version: undefined,
|
|
41
|
-
cwd: undefined,
|
|
42
|
-
subCommands: undefined,
|
|
43
|
-
leftMargin: 2,
|
|
44
|
-
middleMargin: 10,
|
|
45
|
-
usageOptionType: false,
|
|
46
|
-
renderHeader: undefined,
|
|
47
|
-
renderUsage: undefined,
|
|
48
|
-
renderValidationErrors: undefined
|
|
49
|
-
};
|
|
50
|
-
const COMMAND_I18N_RESOURCE_KEYS = [
|
|
51
|
-
"USAGE",
|
|
52
|
-
"COMMAND",
|
|
53
|
-
"SUBCOMMAND",
|
|
54
|
-
"COMMANDS",
|
|
55
|
-
"OPTIONS",
|
|
56
|
-
"EXAMPLES",
|
|
57
|
-
"FORMORE"
|
|
58
|
-
];
|
|
59
58
|
|
|
60
59
|
//#endregion
|
|
61
60
|
//#region src/context.ts
|
|
62
|
-
const
|
|
61
|
+
const BUILT_IN_PREFIX_CODE = BUILT_IN_PREFIX.codePointAt(0);
|
|
63
62
|
async function createCommandContext({ options, values, positionals, command, commandOptions, omitted = false }) {
|
|
64
63
|
/**
|
|
65
64
|
* tweak the options and values
|
|
66
65
|
*/
|
|
67
|
-
const _options =
|
|
66
|
+
const _options = Object.entries(options).reduce((acc, [key, value]) => {
|
|
68
67
|
acc[key] = Object.assign(create(), value);
|
|
69
68
|
return acc;
|
|
70
69
|
}, create());
|
|
@@ -83,29 +82,31 @@ async function createCommandContext({ options, values, positionals, command, com
|
|
|
83
82
|
*/
|
|
84
83
|
const env = Object.assign(create(), COMMAND_OPTIONS_DEFAULT, commandOptions);
|
|
85
84
|
const locale = resolveLocale(commandOptions.locale);
|
|
85
|
+
const translationAdapterFactory = commandOptions.translationAdapterFactory || createTranslationAdapter;
|
|
86
|
+
const adapter = translationAdapterFactory({
|
|
87
|
+
locale: locale.toString(),
|
|
88
|
+
fallbackLocale: DEFAULT_LOCALE
|
|
89
|
+
});
|
|
86
90
|
const localeResources = new Map();
|
|
87
|
-
const commandResources = new Map();
|
|
88
91
|
let builtInLoadedResources;
|
|
89
92
|
/**
|
|
90
93
|
* load the built-in locale resources
|
|
91
94
|
*/
|
|
92
|
-
localeResources.set(DEFAULT_LOCALE, en_US_default);
|
|
95
|
+
localeResources.set(DEFAULT_LOCALE, mapResourceWithBuiltinKey(en_US_default));
|
|
93
96
|
if (DEFAULT_LOCALE !== locale.toString()) try {
|
|
94
97
|
builtInLoadedResources = await import(`../locales/${locale.toString()}.json`, { with: { type: "json" } });
|
|
95
|
-
localeResources.set(locale.toString(), builtInLoadedResources);
|
|
98
|
+
localeResources.set(locale.toString(), mapResourceWithBuiltinKey(builtInLoadedResources));
|
|
96
99
|
} catch {}
|
|
97
100
|
/**
|
|
98
|
-
* define the translation function, which is used to {@link CommandContext.
|
|
101
|
+
* define the translation function, which is used to {@link CommandContext.translate}.
|
|
99
102
|
*
|
|
100
103
|
*/
|
|
101
|
-
function
|
|
102
|
-
|
|
104
|
+
function translate(key, values$1 = create()) {
|
|
105
|
+
const strKey = key;
|
|
106
|
+
if (strKey.codePointAt(0) === BUILT_IN_PREFIX_CODE) {
|
|
103
107
|
const resource = localeResources.get(locale.toString()) || localeResources.get(DEFAULT_LOCALE);
|
|
104
|
-
return resource[
|
|
105
|
-
} else
|
|
106
|
-
const resource = commandResources.get(locale.toString()) || commandResources.get(DEFAULT_LOCALE);
|
|
107
|
-
return resource[key] || "";
|
|
108
|
-
}
|
|
108
|
+
return resource[strKey] || strKey;
|
|
109
|
+
} else return adapter.translate(locale.toString(), strKey, values$1) || "";
|
|
109
110
|
}
|
|
110
111
|
/**
|
|
111
112
|
* load the sub commands
|
|
@@ -130,7 +131,7 @@ async function createCommandContext({ options, values, positionals, command, com
|
|
|
130
131
|
positionals,
|
|
131
132
|
usage,
|
|
132
133
|
loadCommands,
|
|
133
|
-
|
|
134
|
+
translate
|
|
134
135
|
}));
|
|
135
136
|
/**
|
|
136
137
|
* load the command resources
|
|
@@ -145,21 +146,18 @@ async function createCommandContext({ options, values, positionals, command, com
|
|
|
145
146
|
}, create());
|
|
146
147
|
defaultCommandResource.description = command.description || "";
|
|
147
148
|
defaultCommandResource.examples = usage.examples || "";
|
|
148
|
-
|
|
149
|
+
adapter.setResource(DEFAULT_LOCALE, defaultCommandResource);
|
|
149
150
|
const originalResource = await loadCommandResource(ctx, command);
|
|
150
151
|
if (originalResource) {
|
|
151
|
-
const resource = Object.
|
|
152
|
-
res[key] = value;
|
|
153
|
-
return res;
|
|
154
|
-
}, Object.assign(create(), {
|
|
152
|
+
const resource = Object.assign(create(), {
|
|
155
153
|
description: originalResource.description,
|
|
156
154
|
examples: originalResource.examples
|
|
157
|
-
})
|
|
155
|
+
}, originalResource);
|
|
158
156
|
if (builtInLoadedResources) {
|
|
159
157
|
resource.help = builtInLoadedResources.help;
|
|
160
158
|
resource.version = builtInLoadedResources.version;
|
|
161
159
|
}
|
|
162
|
-
|
|
160
|
+
adapter.setResource(locale.toString(), resource);
|
|
163
161
|
}
|
|
164
162
|
return ctx;
|
|
165
163
|
}
|
|
@@ -175,4 +173,4 @@ async function loadCommandResource(ctx, command) {
|
|
|
175
173
|
}
|
|
176
174
|
|
|
177
175
|
//#endregion
|
|
178
|
-
export {
|
|
176
|
+
export { DefaultTranslation, createCommandContext };
|
package/lib/context.d.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { ArgOptions, ArgValues } from 'args-tokens';
|
|
2
|
-
import { C as Command, a as CommandOptions, b as CommandContext } from './types.d-
|
|
2
|
+
import { C as Command, a as CommandOptions, b as CommandContext } from './types.d-CX4RmDVT.js';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* The default locale string, which format is BCP 47 language tag
|
|
6
|
-
*/
|
|
7
|
-
declare const DEFAULT_LOCALE = "en-US";
|
|
8
4
|
/**
|
|
9
5
|
* Parameters of {@link createCommandContext}
|
|
10
6
|
*/
|
|
@@ -15,7 +11,7 @@ interface CommandContextParams<
|
|
|
15
11
|
/**
|
|
16
12
|
* An options of target command
|
|
17
13
|
*/
|
|
18
|
-
options: Options
|
|
14
|
+
options: Options;
|
|
19
15
|
/**
|
|
20
16
|
* A values of target command
|
|
21
17
|
*/
|
|
@@ -47,4 +43,4 @@ declare function createCommandContext<
|
|
|
47
43
|
Values = ArgValues<Options>
|
|
48
44
|
>({ options, values, positionals, command, commandOptions, omitted }: CommandContextParams<Options, Values>): Promise<Readonly<CommandContext<Options, Values>>>;
|
|
49
45
|
|
|
50
|
-
export {
|
|
46
|
+
export { createCommandContext };
|
package/lib/context.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "./utils-
|
|
1
|
+
import { createCommandContext } from "./context-DYokJ5k3.js";
|
|
2
|
+
import "./utils-CU_LSsUg.js";
|
|
3
3
|
|
|
4
|
-
export {
|
|
4
|
+
export { createCommandContext };
|
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ArgOptions } from 'args-tokens';
|
|
2
2
|
export { ArgOptionSchema, ArgOptions, ArgValues } from 'args-tokens';
|
|
3
|
-
import { C as Command, c as CommandRunner, a as CommandOptions } from './types.d-
|
|
4
|
-
export {
|
|
3
|
+
import { C as Command, c as CommandRunner, a as CommandOptions, T as TranslationAdapter, d as TranslationAdapterFactoryOptions } from './types.d-CX4RmDVT.js';
|
|
4
|
+
export { g as CommandBuiltinKeys, e as CommandBuiltinOptionsKeys, f as CommandBuiltinResourceKeys, b as CommandContext, h as CommandEnvironment, i as CommandResource, j as CommandResourceFetcher, l as Commandable, G as GenerateNamespacedKey, L as LazyCommand, k as TranslationAdapterFactory } from './types.d-CX4RmDVT.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Run the command
|
|
@@ -11,4 +11,14 @@ export { f as CommandBuiltinKeys, d as CommandBuiltinOptionsKeys, e as CommandBu
|
|
|
11
11
|
*/
|
|
12
12
|
declare function cli<Options extends ArgOptions = ArgOptions>(args: string[], entry: Command<Options> | CommandRunner<Options>, opts?: CommandOptions<Options>): Promise<string | undefined>;
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
declare class DefaultTranslation implements TranslationAdapter {
|
|
15
|
+
#private;
|
|
16
|
+
options: TranslationAdapterFactoryOptions;
|
|
17
|
+
constructor(options: TranslationAdapterFactoryOptions);
|
|
18
|
+
getResource(locale: string): Record<string, string> | undefined;
|
|
19
|
+
setResource(locale: string, resource: Record<string, string>): void;
|
|
20
|
+
getMessage(locale: string, key: string): string | undefined;
|
|
21
|
+
translate(locale: string, key: string, _values?: Record<string, unknown>): string | undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { Command, CommandOptions, CommandRunner, DefaultTranslation, TranslationAdapter, TranslationAdapterFactoryOptions, cli };
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { create, log, resolveLazyCommand } from "./utils-
|
|
3
|
-
import { renderHeader, renderUsage, renderValidationErrors } from "./renderer-
|
|
1
|
+
import { DefaultTranslation, createCommandContext } from "./context-DYokJ5k3.js";
|
|
2
|
+
import { COMMAND_OPTIONS_DEFAULT, COMMON_OPTIONS, create, log, resolveLazyCommand } from "./utils-CU_LSsUg.js";
|
|
3
|
+
import { renderHeader, renderUsage, renderValidationErrors } from "./renderer-KLx2dW-W.js";
|
|
4
4
|
import { parseArgs, resolveArgs } from "args-tokens";
|
|
5
5
|
|
|
6
6
|
//#region src/cli.ts
|
|
@@ -45,7 +45,8 @@ function resolveArgOptions(options) {
|
|
|
45
45
|
function resolveCommandOptions(options, entry) {
|
|
46
46
|
const subCommands = new Map(options.subCommands);
|
|
47
47
|
if (typeof entry === "object" && entry.name) subCommands.set(entry.name, entry);
|
|
48
|
-
|
|
48
|
+
const resolvedOptions = Object.assign(create(), COMMAND_OPTIONS_DEFAULT, options, { subCommands });
|
|
49
|
+
return resolvedOptions;
|
|
49
50
|
}
|
|
50
51
|
function getSubCommand(tokens) {
|
|
51
52
|
const firstToken = tokens[0];
|
|
@@ -92,4 +93,4 @@ async function resolveCommand(sub, entry, options) {
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
//#endregion
|
|
95
|
-
export { cli };
|
|
96
|
+
export { DefaultTranslation, cli };
|
package/lib/renderer/index.d.ts
CHANGED
package/lib/renderer/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../utils-
|
|
2
|
-
import { renderHeader, renderUsage, renderValidationErrors } from "../renderer-
|
|
1
|
+
import "../utils-CU_LSsUg.js";
|
|
2
|
+
import { renderHeader, renderUsage, renderValidationErrors } from "../renderer-KLx2dW-W.js";
|
|
3
3
|
|
|
4
4
|
export { renderHeader, renderUsage, renderValidationErrors };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { create } from "./utils-
|
|
1
|
+
import { create, resolveBuiltInKey } from "./utils-CU_LSsUg.js";
|
|
2
2
|
|
|
3
3
|
//#region src/renderer/header.ts
|
|
4
4
|
function renderHeader(ctx) {
|
|
@@ -27,9 +27,8 @@ async function renderUsage(ctx) {
|
|
|
27
27
|
*/
|
|
28
28
|
async function renderOptionsSection(ctx) {
|
|
29
29
|
const messages = [];
|
|
30
|
-
messages.push(`${ctx.
|
|
31
|
-
|
|
32
|
-
messages.push(await generateOptionsUsage(ctx, optionsPairs));
|
|
30
|
+
messages.push(`${ctx.translate(resolveBuiltInKey("OPTIONS"))}:`);
|
|
31
|
+
messages.push(await generateOptionsUsage(ctx, getOptionsPairs(ctx)));
|
|
33
32
|
return messages;
|
|
34
33
|
}
|
|
35
34
|
/**
|
|
@@ -40,7 +39,7 @@ async function renderOptionsSection(ctx) {
|
|
|
40
39
|
function renderExamplesSection(ctx) {
|
|
41
40
|
const messages = [];
|
|
42
41
|
const examples = ctx.usage.examples.split("\n").map((example) => example.padStart(ctx.env.leftMargin + example.length));
|
|
43
|
-
messages.push(`${ctx.
|
|
42
|
+
messages.push(`${ctx.translate(resolveBuiltInKey("EXAMPLES"))}:`, ...examples);
|
|
44
43
|
return messages;
|
|
45
44
|
}
|
|
46
45
|
/**
|
|
@@ -49,12 +48,12 @@ function renderExamplesSection(ctx) {
|
|
|
49
48
|
* @returns A rendered usage section
|
|
50
49
|
*/
|
|
51
50
|
async function renderUsageSection(ctx) {
|
|
52
|
-
const messages = [`${ctx.
|
|
51
|
+
const messages = [`${ctx.translate(resolveBuiltInKey("USAGE"))}:`];
|
|
53
52
|
if (ctx.omitted) {
|
|
54
|
-
const defaultCommand = `${resolveEntry(ctx)}${await hasCommands(ctx) ? ` [${resolveSubCommand(ctx)}]` : ""} ${hasOptions(ctx) ? `<${ctx.
|
|
53
|
+
const defaultCommand = `${resolveEntry(ctx)}${await hasCommands(ctx) ? ` [${resolveSubCommand(ctx)}]` : ""} ${hasOptions(ctx) ? `<${ctx.translate(resolveBuiltInKey("OPTIONS"))}>` : ""} `;
|
|
55
54
|
messages.push(defaultCommand.padStart(ctx.env.leftMargin + defaultCommand.length));
|
|
56
55
|
if (await hasCommands(ctx)) {
|
|
57
|
-
const commandsUsage = `${resolveEntry(ctx)} <${ctx.
|
|
56
|
+
const commandsUsage = `${resolveEntry(ctx)} <${ctx.translate(resolveBuiltInKey("COMMANDS"))}>`;
|
|
58
57
|
messages.push(commandsUsage.padStart(ctx.env.leftMargin + commandsUsage.length));
|
|
59
58
|
}
|
|
60
59
|
} else {
|
|
@@ -69,7 +68,7 @@ async function renderUsageSection(ctx) {
|
|
|
69
68
|
* @returns A rendered commands section
|
|
70
69
|
*/
|
|
71
70
|
async function renderCommandsSection(ctx) {
|
|
72
|
-
const messages = [`${ctx.
|
|
71
|
+
const messages = [`${ctx.translate(resolveBuiltInKey("COMMANDS"))}:`];
|
|
73
72
|
const loadedCommands = await ctx.loadCommands();
|
|
74
73
|
const commandMaxLength = Math.max(...loadedCommands.map((cmd) => (cmd.name || "").length));
|
|
75
74
|
const commandsStr = await Promise.all(loadedCommands.map((cmd) => {
|
|
@@ -78,7 +77,7 @@ async function renderCommandsSection(ctx) {
|
|
|
78
77
|
const command = `${key.padEnd(commandMaxLength + ctx.env.middleMargin)}${desc} `;
|
|
79
78
|
return `${command.padStart(ctx.env.leftMargin + command.length)} `;
|
|
80
79
|
}));
|
|
81
|
-
messages.push(...commandsStr, "", ctx.
|
|
80
|
+
messages.push(...commandsStr, "", ctx.translate(resolveBuiltInKey("FORMORE")));
|
|
82
81
|
messages.push(...loadedCommands.map((cmd) => {
|
|
83
82
|
const commandHelp = `${ctx.env.name} ${cmd.name} --help`;
|
|
84
83
|
return `${commandHelp.padStart(ctx.env.leftMargin + commandHelp.length)}`;
|
|
@@ -91,7 +90,7 @@ async function renderCommandsSection(ctx) {
|
|
|
91
90
|
* @returns The entry command name
|
|
92
91
|
*/
|
|
93
92
|
function resolveEntry(ctx) {
|
|
94
|
-
return ctx.env.name || ctx.
|
|
93
|
+
return ctx.env.name || ctx.translate(resolveBuiltInKey("COMMAND"));
|
|
95
94
|
}
|
|
96
95
|
/**
|
|
97
96
|
* Resolve the sub command name
|
|
@@ -99,7 +98,7 @@ function resolveEntry(ctx) {
|
|
|
99
98
|
* @returns The sub command name
|
|
100
99
|
*/
|
|
101
100
|
function resolveSubCommand(ctx) {
|
|
102
|
-
return ctx.name || ctx.
|
|
101
|
+
return ctx.name || ctx.translate(resolveBuiltInKey("SUBCOMMAND"));
|
|
103
102
|
}
|
|
104
103
|
/**
|
|
105
104
|
* Resolve the command description
|
|
@@ -107,7 +106,7 @@ function resolveSubCommand(ctx) {
|
|
|
107
106
|
* @returns resolved command description
|
|
108
107
|
*/
|
|
109
108
|
function resolveDescription(ctx) {
|
|
110
|
-
return ctx.
|
|
109
|
+
return ctx.translate("description") || ctx.description || "";
|
|
111
110
|
}
|
|
112
111
|
/**
|
|
113
112
|
* Check if the command has sub commands
|
|
@@ -148,7 +147,7 @@ function hasAllDefaultOptions(ctx) {
|
|
|
148
147
|
* @returns Options symbols for usage
|
|
149
148
|
*/
|
|
150
149
|
function generateOptionsSymbols(ctx) {
|
|
151
|
-
return hasOptions(ctx) ? hasAllDefaultOptions(ctx) ? `[${ctx.
|
|
150
|
+
return hasOptions(ctx) ? hasAllDefaultOptions(ctx) ? `[${ctx.translate("_:OPTIONS")}]` : `<${ctx.translate("_:OPTIONS")}>` : "";
|
|
152
151
|
}
|
|
153
152
|
/**
|
|
154
153
|
* Get options pairs for usage
|
|
@@ -174,7 +173,7 @@ async function generateOptionsUsage(ctx, optionsPairs) {
|
|
|
174
173
|
const optionsMaxLength = Math.max(...Object.entries(optionsPairs).map(([_, value]) => value.length));
|
|
175
174
|
const optionSchemaMaxLength = ctx.env.usageOptionType ? Math.max(...Object.entries(optionsPairs).map(([key, _]) => ctx.options[key].type.length)) : 0;
|
|
176
175
|
const usages = await Promise.all(Object.entries(optionsPairs).map(([key, value]) => {
|
|
177
|
-
const rawDesc = ctx.
|
|
176
|
+
const rawDesc = ctx.translate(key);
|
|
178
177
|
const optionsSchema = ctx.env.usageOptionType ? `[${ctx.options[key].type}] ` : "";
|
|
179
178
|
const desc = `${optionsSchema ? optionsSchema.padEnd(optionSchemaMaxLength + 3) : ""}${rawDesc}`;
|
|
180
179
|
const option = `${value.padEnd(optionsMaxLength + ctx.env.middleMargin)}${desc}`;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ArgOptions, ArgValues } from 'args-tokens';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* The default locale string, which format is BCP 47 language tag
|
|
5
|
+
*/
|
|
6
|
+
declare const DEFAULT_LOCALE = "en-US";
|
|
7
|
+
declare const BUILT_IN_PREFIX = "_";
|
|
8
|
+
declare const BUILT_IN_KEY_SEPARATOR = ":";
|
|
3
9
|
type CommonOptionType = {
|
|
4
10
|
readonly help: {
|
|
5
11
|
readonly type: "boolean"
|
|
@@ -12,19 +18,26 @@ type CommonOptionType = {
|
|
|
12
18
|
};
|
|
13
19
|
declare const COMMON_OPTIONS: CommonOptionType;
|
|
14
20
|
declare const COMMAND_OPTIONS_DEFAULT: CommandOptions<ArgOptions>;
|
|
15
|
-
declare const
|
|
21
|
+
declare const COMMAND_BUILTIN_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "OPTIONS", "EXAMPLES", "FORMORE"];
|
|
16
22
|
|
|
17
|
-
declare const
|
|
23
|
+
declare const __constants_BUILT_IN_KEY_SEPARATOR: typeof BUILT_IN_KEY_SEPARATOR;
|
|
24
|
+
declare const __constants_BUILT_IN_PREFIX: typeof BUILT_IN_PREFIX;
|
|
25
|
+
declare const __constants_COMMAND_BUILTIN_RESOURCE_KEYS: typeof COMMAND_BUILTIN_RESOURCE_KEYS;
|
|
18
26
|
declare const __constants_COMMAND_OPTIONS_DEFAULT: typeof COMMAND_OPTIONS_DEFAULT;
|
|
19
27
|
declare const __constants_COMMON_OPTIONS: typeof COMMON_OPTIONS;
|
|
28
|
+
declare const __constants_DEFAULT_LOCALE: typeof DEFAULT_LOCALE;
|
|
20
29
|
declare namespace __constants {
|
|
21
|
-
export {
|
|
30
|
+
export { __constants_BUILT_IN_KEY_SEPARATOR as BUILT_IN_KEY_SEPARATOR, __constants_BUILT_IN_PREFIX as BUILT_IN_PREFIX, __constants_COMMAND_BUILTIN_RESOURCE_KEYS as COMMAND_BUILTIN_RESOURCE_KEYS, __constants_COMMAND_OPTIONS_DEFAULT as COMMAND_OPTIONS_DEFAULT, __constants_COMMON_OPTIONS as COMMON_OPTIONS, __constants_DEFAULT_LOCALE as DEFAULT_LOCALE };
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
/**
|
|
25
34
|
* Define a promise type that can be await from T
|
|
26
35
|
*/
|
|
27
36
|
type Awaitable<T> = T | Promise<T>;
|
|
37
|
+
type GenerateNamespacedKey<
|
|
38
|
+
Key extends string,
|
|
39
|
+
Prefixed extends string = typeof BUILT_IN_PREFIX
|
|
40
|
+
> = `${Prefixed}${typeof BUILT_IN_KEY_SEPARATOR}${Key}`;
|
|
28
41
|
/**
|
|
29
42
|
* Command i18n built-in options keys
|
|
30
43
|
* @experimental
|
|
@@ -34,13 +47,13 @@ type CommandBuiltinOptionsKeys = keyof (typeof __constants)["COMMON_OPTIONS"];
|
|
|
34
47
|
* Command i18n built-in resource keys
|
|
35
48
|
* @experimental
|
|
36
49
|
*/
|
|
37
|
-
type CommandBuiltinResourceKeys = (typeof __constants)["
|
|
50
|
+
type CommandBuiltinResourceKeys = (typeof __constants)["COMMAND_BUILTIN_RESOURCE_KEYS"][number];
|
|
38
51
|
/**
|
|
39
52
|
* Command i18n built-in keys
|
|
40
|
-
* @description The command i18n built-in keys are used to {@link CommandContext.
|
|
53
|
+
* @description The command i18n built-in keys are used to {@link CommandContext.translate | translate} function
|
|
41
54
|
* @experimental
|
|
42
55
|
*/
|
|
43
|
-
type CommandBuiltinKeys = CommandBuiltinOptionsKeys | CommandBuiltinResourceKeys | "description" | "examples";
|
|
56
|
+
type CommandBuiltinKeys = GenerateNamespacedKey<CommandBuiltinOptionsKeys> | GenerateNamespacedKey<CommandBuiltinResourceKeys> | "description" | "examples";
|
|
44
57
|
/**
|
|
45
58
|
* Command environment
|
|
46
59
|
*/
|
|
@@ -155,6 +168,11 @@ interface CommandOptions<Options extends ArgOptions = ArgOptions> {
|
|
|
155
168
|
* Render function the validation errors
|
|
156
169
|
*/
|
|
157
170
|
renderValidationErrors?: ((ctx: Readonly<CommandContext<Options>>, error: AggregateError) => Promise<string>) | null;
|
|
171
|
+
/**
|
|
172
|
+
* Translation adapter factory
|
|
173
|
+
* @experimental
|
|
174
|
+
*/
|
|
175
|
+
translationAdapterFactory?: TranslationAdapterFactory;
|
|
158
176
|
}
|
|
159
177
|
/**
|
|
160
178
|
* Command context
|
|
@@ -187,7 +205,7 @@ interface CommandContext<
|
|
|
187
205
|
* Command options, that is the options of the command that is executed
|
|
188
206
|
* @description The command options is same {@link Command.options}
|
|
189
207
|
*/
|
|
190
|
-
options: Options
|
|
208
|
+
options: Options;
|
|
191
209
|
/**
|
|
192
210
|
* Command values, that is the values of the command that is executed
|
|
193
211
|
* @description Resolve values with `resolveArgs` from command arguments and {@link Command.options}
|
|
@@ -214,15 +232,16 @@ interface CommandContext<
|
|
|
214
232
|
*/
|
|
215
233
|
loadCommands: () => Promise<Command<Options>[]>;
|
|
216
234
|
/**
|
|
217
|
-
*
|
|
235
|
+
* Translate function
|
|
218
236
|
* @param key the key to be translated
|
|
237
|
+
* @param values the values to be formatted
|
|
219
238
|
* @returns A translated string
|
|
220
239
|
* @experimental
|
|
221
240
|
*/
|
|
222
|
-
|
|
223
|
-
T = CommandBuiltinKeys,
|
|
224
|
-
Key = CommandBuiltinKeys | T
|
|
225
|
-
>(key: Key) => string;
|
|
241
|
+
translate: <
|
|
242
|
+
T extends string = CommandBuiltinKeys,
|
|
243
|
+
Key = CommandBuiltinKeys | keyof Options | T
|
|
244
|
+
>(key: Key, values?: Record<string, unknown>) => string;
|
|
226
245
|
}
|
|
227
246
|
/**
|
|
228
247
|
* Command usage
|
|
@@ -282,20 +301,18 @@ interface Command<Options extends ArgOptions = ArgOptions> {
|
|
|
282
301
|
* Command resource
|
|
283
302
|
* @experimental
|
|
284
303
|
*/
|
|
285
|
-
|
|
304
|
+
type CommandResource<Options extends ArgOptions = ArgOptions> = {
|
|
286
305
|
/**
|
|
287
306
|
* Command description
|
|
288
307
|
*/
|
|
289
|
-
description: string
|
|
290
|
-
/**
|
|
291
|
-
* Options usage
|
|
292
|
-
*/
|
|
293
|
-
options: { [Option in keyof Options] : string };
|
|
308
|
+
description: string
|
|
294
309
|
/**
|
|
295
310
|
* Examples usage
|
|
296
311
|
*/
|
|
297
|
-
examples: string
|
|
298
|
-
}
|
|
312
|
+
examples: string
|
|
313
|
+
} & { [Option in keyof Options] : string } & {
|
|
314
|
+
[key: string]: string
|
|
315
|
+
};
|
|
299
316
|
/**
|
|
300
317
|
* Command resource fetcher
|
|
301
318
|
* @param ctx A {@link CommandContext | command context}
|
|
@@ -304,6 +321,59 @@ interface CommandResource<Options extends ArgOptions = ArgOptions> {
|
|
|
304
321
|
*/
|
|
305
322
|
type CommandResourceFetcher<Options extends ArgOptions = ArgOptions> = (ctx: Readonly<CommandContext<Options>>) => Promise<CommandResource<Options>>;
|
|
306
323
|
/**
|
|
324
|
+
* Translation adapter factory
|
|
325
|
+
*/
|
|
326
|
+
type TranslationAdapterFactory = (options: TranslationAdapterFactoryOptions) => TranslationAdapter;
|
|
327
|
+
/**
|
|
328
|
+
* Translation adapter factory options
|
|
329
|
+
*/
|
|
330
|
+
interface TranslationAdapterFactoryOptions {
|
|
331
|
+
/**
|
|
332
|
+
* A locale
|
|
333
|
+
*/
|
|
334
|
+
locale: string;
|
|
335
|
+
/**
|
|
336
|
+
* A fallback locale
|
|
337
|
+
*/
|
|
338
|
+
fallbackLocale: string;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Translation adapter
|
|
342
|
+
*
|
|
343
|
+
* @description
|
|
344
|
+
* This adapter is used to custom message formatter like {@link https://github.com/intlify/vue-i18n/blob/master/spec/syntax.ebnf | Intlify message format}, {@link https://github.com/tc39/proposal-intl-messageformat | `Intl.MessageFormat` (MF2)}, and etc.
|
|
345
|
+
* This adapter will support localization with your preferred message format
|
|
346
|
+
*/
|
|
347
|
+
interface TranslationAdapter<MessageResource = string> {
|
|
348
|
+
/**
|
|
349
|
+
* Get a resource of locale
|
|
350
|
+
* @param locale A Locale at the time of command execution. That is Unicord locale ID (BCP 47)
|
|
351
|
+
* @returns A resource of locale. if resource not found, return `undefined`
|
|
352
|
+
*/
|
|
353
|
+
getResource(locale: string): Record<string, string> | undefined;
|
|
354
|
+
/**
|
|
355
|
+
* Set a resource of locale
|
|
356
|
+
* @param locale A Locale at the time of command execution. That is Unicord locale ID (BCP 47)
|
|
357
|
+
* @param resource A resource of locale
|
|
358
|
+
*/
|
|
359
|
+
setResource(locale: string, resource: Record<string, string>): void;
|
|
360
|
+
/**
|
|
361
|
+
* Get a message of locale
|
|
362
|
+
* @param locale A Locale at the time of command execution. That is Unicord locale ID (BCP 47)
|
|
363
|
+
* @param key A key of message resource
|
|
364
|
+
* @returns A message of locale. if message not found, return `undefined`
|
|
365
|
+
*/
|
|
366
|
+
getMessage(locale: string, key: string): MessageResource | undefined;
|
|
367
|
+
/**
|
|
368
|
+
* Translate a message
|
|
369
|
+
* @param locale A Locale at the time of command execution. That is Unicord locale ID (BCP 47)
|
|
370
|
+
* @param key A key of message resource
|
|
371
|
+
* @param values A values to be resolved in the message
|
|
372
|
+
* @returns A translated message, if message is not translated, return `undefined`
|
|
373
|
+
*/
|
|
374
|
+
translate(locale: string, key: string, values?: Record<string, unknown>): string | undefined;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
307
377
|
* Command runner
|
|
308
378
|
* @param ctx A {@link CommandContext | command context}
|
|
309
379
|
*/
|
|
@@ -318,4 +388,4 @@ type LazyCommand<Options extends ArgOptions = ArgOptions> = () => Awaitable<Comm
|
|
|
318
388
|
*/
|
|
319
389
|
type Commandable<Options extends ArgOptions> = Command<Options> | LazyCommand<Options>;
|
|
320
390
|
|
|
321
|
-
export type { Command as C, LazyCommand as L, CommandOptions as a, CommandContext as b, CommandRunner as c,
|
|
391
|
+
export type { Command as C, GenerateNamespacedKey as G, LazyCommand as L, TranslationAdapter as T, CommandOptions as a, CommandContext as b, CommandRunner as c, TranslationAdapterFactoryOptions as d, CommandBuiltinOptionsKeys as e, CommandBuiltinResourceKeys as f, CommandBuiltinKeys as g, CommandEnvironment as h, CommandResource as i, CommandResourceFetcher as j, TranslationAdapterFactory as k, Commandable as l };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/constants.ts
|
|
3
|
+
const DEFAULT_LOCALE = "en-US";
|
|
4
|
+
const BUILT_IN_PREFIX = "_";
|
|
5
|
+
const BUILT_IN_KEY_SEPARATOR = ":";
|
|
6
|
+
const COMMON_OPTIONS = {
|
|
7
|
+
help: {
|
|
8
|
+
type: "boolean",
|
|
9
|
+
short: "h"
|
|
10
|
+
},
|
|
11
|
+
version: {
|
|
12
|
+
type: "boolean",
|
|
13
|
+
short: "v"
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const COMMAND_OPTIONS_DEFAULT = {
|
|
17
|
+
name: undefined,
|
|
18
|
+
description: undefined,
|
|
19
|
+
version: undefined,
|
|
20
|
+
cwd: undefined,
|
|
21
|
+
subCommands: undefined,
|
|
22
|
+
leftMargin: 2,
|
|
23
|
+
middleMargin: 10,
|
|
24
|
+
usageOptionType: false,
|
|
25
|
+
renderHeader: undefined,
|
|
26
|
+
renderUsage: undefined,
|
|
27
|
+
renderValidationErrors: undefined,
|
|
28
|
+
translationAdapterFactory: undefined
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/utils.ts
|
|
33
|
+
async function resolveLazyCommand(cmd, name, entry = false) {
|
|
34
|
+
const resolved = Object.assign(create(), typeof cmd == "function" ? await cmd() : cmd, { default: entry });
|
|
35
|
+
if (resolved.name == null && name) resolved.name = name;
|
|
36
|
+
return deepFreeze(resolved);
|
|
37
|
+
}
|
|
38
|
+
function resolveBuiltInKey(key) {
|
|
39
|
+
return `${BUILT_IN_PREFIX}${BUILT_IN_KEY_SEPARATOR}${key}`;
|
|
40
|
+
}
|
|
41
|
+
function mapResourceWithBuiltinKey(resource) {
|
|
42
|
+
return Object.entries(resource).reduce((acc, [key, value]) => {
|
|
43
|
+
acc[resolveBuiltInKey(key)] = value;
|
|
44
|
+
return acc;
|
|
45
|
+
}, create());
|
|
46
|
+
}
|
|
47
|
+
function create(obj = null) {
|
|
48
|
+
return Object.create(obj);
|
|
49
|
+
}
|
|
50
|
+
function log(...args) {
|
|
51
|
+
console.log(...args);
|
|
52
|
+
}
|
|
53
|
+
function deepFreeze(obj) {
|
|
54
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
55
|
+
for (const key of Object.keys(obj)) {
|
|
56
|
+
const value = obj[key];
|
|
57
|
+
if (typeof value === "object" && value !== null) deepFreeze(value);
|
|
58
|
+
}
|
|
59
|
+
return Object.freeze(obj);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { BUILT_IN_PREFIX, COMMAND_OPTIONS_DEFAULT, COMMON_OPTIONS, DEFAULT_LOCALE, create, deepFreeze, log, mapResourceWithBuiltinKey, resolveBuiltInKey, 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.
|
|
4
|
+
"version": "0.8.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "kazuya kawaguchi",
|
|
7
7
|
"email": "kawakazu80@gmail.com"
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@eslint/markdown": "^6.2.2",
|
|
74
|
+
"@intlify/core": "next",
|
|
74
75
|
"@kazupon/eslint-config": "^0.22.0",
|
|
75
76
|
"@kazupon/prettier-config": "^0.1.1",
|
|
76
77
|
"@types/node": "^22.13.9",
|
|
@@ -87,6 +88,7 @@
|
|
|
87
88
|
"jsr": "^0.13.4",
|
|
88
89
|
"knip": "^5.45.0",
|
|
89
90
|
"lint-staged": "^15.4.3",
|
|
91
|
+
"messageformat": "4.0.0-9",
|
|
90
92
|
"pkg-pr-new": "^0.0.41",
|
|
91
93
|
"prettier": "^3.5.3",
|
|
92
94
|
"tsdown": "^0.6.4",
|
package/lib/utils-NHs5DuHk.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
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 };
|