gunshi 0.7.0 → 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.
@@ -1,4 +1,4 @@
1
- import { BUILT_IN_PREFIX, COMMAND_OPTIONS_DEFAULT, DEFAULT_LOCALE, create, deepFreeze, mapResourceWithBuiltinKey, resolveLazyCommand } from "./utils-B39blQOf.js";
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";
@@ -22,6 +22,40 @@ var en_US_default = {
22
22
  version
23
23
  };
24
24
 
25
+ //#endregion
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);
56
+ }
57
+ };
58
+
25
59
  //#endregion
26
60
  //#region src/context.ts
27
61
  const BUILT_IN_PREFIX_CODE = BUILT_IN_PREFIX.codePointAt(0);
@@ -48,8 +82,12 @@ async function createCommandContext({ options, values, positionals, command, com
48
82
  */
49
83
  const env = Object.assign(create(), COMMAND_OPTIONS_DEFAULT, commandOptions);
50
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
+ });
51
90
  const localeResources = new Map();
52
- const commandResources = new Map();
53
91
  let builtInLoadedResources;
54
92
  /**
55
93
  * load the built-in locale resources
@@ -63,14 +101,12 @@ async function createCommandContext({ options, values, positionals, command, com
63
101
  * define the translation function, which is used to {@link CommandContext.translate}.
64
102
  *
65
103
  */
66
- function translate(key) {
67
- if (key.codePointAt(0) === BUILT_IN_PREFIX_CODE) {
104
+ function translate(key, values$1 = create()) {
105
+ const strKey = key;
106
+ if (strKey.codePointAt(0) === BUILT_IN_PREFIX_CODE) {
68
107
  const resource = localeResources.get(locale.toString()) || localeResources.get(DEFAULT_LOCALE);
69
- return resource[key] || key;
70
- } else {
71
- const resource = commandResources.get(locale.toString()) || commandResources.get(DEFAULT_LOCALE);
72
- return resource[key] || "";
73
- }
108
+ return resource[strKey] || strKey;
109
+ } else return adapter.translate(locale.toString(), strKey, values$1) || "";
74
110
  }
75
111
  /**
76
112
  * load the sub commands
@@ -110,7 +146,7 @@ async function createCommandContext({ options, values, positionals, command, com
110
146
  }, create());
111
147
  defaultCommandResource.description = command.description || "";
112
148
  defaultCommandResource.examples = usage.examples || "";
113
- commandResources.set(DEFAULT_LOCALE, defaultCommandResource);
149
+ adapter.setResource(DEFAULT_LOCALE, defaultCommandResource);
114
150
  const originalResource = await loadCommandResource(ctx, command);
115
151
  if (originalResource) {
116
152
  const resource = Object.assign(create(), {
@@ -121,7 +157,7 @@ async function createCommandContext({ options, values, positionals, command, com
121
157
  resource.help = builtInLoadedResources.help;
122
158
  resource.version = builtInLoadedResources.version;
123
159
  }
124
- commandResources.set(locale.toString(), resource);
160
+ adapter.setResource(locale.toString(), resource);
125
161
  }
126
162
  return ctx;
127
163
  }
@@ -137,4 +173,4 @@ async function loadCommandResource(ctx, command) {
137
173
  }
138
174
 
139
175
  //#endregion
140
- export { createCommandContext };
176
+ export { DefaultTranslation, createCommandContext };
package/lib/context.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ArgOptions, ArgValues } from 'args-tokens';
2
- import { C as Command, a as CommandOptions, b as CommandContext } from './types.d-BvzTOO8I.js';
2
+ import { C as Command, a as CommandOptions, b as CommandContext } from './types.d-CX4RmDVT.js';
3
3
 
4
4
  /**
5
5
  * Parameters of {@link createCommandContext}
package/lib/context.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createCommandContext } from "./context-CEZVz8Dg.js";
2
- import "./utils-B39blQOf.js";
1
+ import { createCommandContext } from "./context-DYokJ5k3.js";
2
+ import "./utils-CU_LSsUg.js";
3
3
 
4
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-BvzTOO8I.js';
4
- export { f as CommandBuiltinKeys, d as CommandBuiltinOptionsKeys, e as CommandBuiltinResourceKeys, b as CommandContext, g as CommandEnvironment, h as CommandResource, i as CommandResourceFetcher, j as Commandable, G as GenerateNamespacedKey, L as LazyCommand } from './types.d-BvzTOO8I.js';
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
- export { Command, CommandOptions, CommandRunner, cli };
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 { createCommandContext } from "./context-CEZVz8Dg.js";
2
- import { COMMAND_OPTIONS_DEFAULT, COMMON_OPTIONS, create, log, resolveLazyCommand } from "./utils-B39blQOf.js";
3
- import { renderHeader, renderUsage, renderValidationErrors } from "./renderer-CD-yc-xk.js";
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
@@ -93,4 +93,4 @@ async function resolveCommand(sub, entry, options) {
93
93
  }
94
94
 
95
95
  //#endregion
96
- export { cli };
96
+ export { DefaultTranslation, cli };
@@ -1,5 +1,5 @@
1
1
  import { ArgOptions } from 'args-tokens';
2
- import { b as CommandContext } from '../types.d-BvzTOO8I.js';
2
+ import { b as CommandContext } from '../types.d-CX4RmDVT.js';
3
3
 
4
4
  /**
5
5
  * Render the header
@@ -1,4 +1,4 @@
1
- import "../utils-B39blQOf.js";
2
- import { renderHeader, renderUsage, renderValidationErrors } from "../renderer-CD-yc-xk.js";
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, resolveBuiltInKey } from "./utils-B39blQOf.js";
1
+ import { create, resolveBuiltInKey } from "./utils-CU_LSsUg.js";
2
2
 
3
3
  //#region src/renderer/header.ts
4
4
  function renderHeader(ctx) {
@@ -168,6 +168,11 @@ interface CommandOptions<Options extends ArgOptions = ArgOptions> {
168
168
  * Render function the validation errors
169
169
  */
170
170
  renderValidationErrors?: ((ctx: Readonly<CommandContext<Options>>, error: AggregateError) => Promise<string>) | null;
171
+ /**
172
+ * Translation adapter factory
173
+ * @experimental
174
+ */
175
+ translationAdapterFactory?: TranslationAdapterFactory;
171
176
  }
172
177
  /**
173
178
  * Command context
@@ -229,13 +234,14 @@ interface CommandContext<
229
234
  /**
230
235
  * Translate function
231
236
  * @param key the key to be translated
237
+ * @param values the values to be formatted
232
238
  * @returns A translated string
233
239
  * @experimental
234
240
  */
235
241
  translate: <
236
242
  T extends string = CommandBuiltinKeys,
237
243
  Key = CommandBuiltinKeys | keyof Options | T
238
- >(key: Key) => string;
244
+ >(key: Key, values?: Record<string, unknown>) => string;
239
245
  }
240
246
  /**
241
247
  * Command usage
@@ -315,6 +321,59 @@ type CommandResource<Options extends ArgOptions = ArgOptions> = {
315
321
  */
316
322
  type CommandResourceFetcher<Options extends ArgOptions = ArgOptions> = (ctx: Readonly<CommandContext<Options>>) => Promise<CommandResource<Options>>;
317
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
+ /**
318
377
  * Command runner
319
378
  * @param ctx A {@link CommandContext | command context}
320
379
  */
@@ -329,4 +388,4 @@ type LazyCommand<Options extends ArgOptions = ArgOptions> = () => Awaitable<Comm
329
388
  */
330
389
  type Commandable<Options extends ArgOptions> = Command<Options> | LazyCommand<Options>;
331
390
 
332
- export type { Command as C, GenerateNamespacedKey as G, 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, Commandable as j };
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 };
@@ -24,7 +24,8 @@ const COMMAND_OPTIONS_DEFAULT = {
24
24
  usageOptionType: false,
25
25
  renderHeader: undefined,
26
26
  renderUsage: undefined,
27
- renderValidationErrors: undefined
27
+ renderValidationErrors: undefined,
28
+ translationAdapterFactory: undefined
28
29
  };
29
30
 
30
31
  //#endregion
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.7.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",