gunshi 0.12.0 → 0.13.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 CHANGED
@@ -32,8 +32,6 @@ Gunshi is designed to simplify the creation of modern command-line interfaces:
32
32
 
33
33
  ## 💿 Installation
34
34
 
35
- ### 🐢 Node
36
-
37
35
  ```sh
38
36
  # npm
39
37
  npm install --save gunshi
@@ -43,41 +41,16 @@ pnpm add gunshi
43
41
 
44
42
  ## yarn
45
43
  yarn add gunshi
46
- ```
47
-
48
- ### 🦕 Deno
49
44
 
50
- ```sh
45
+ ## deno
51
46
  deno add jsr:@kazupon/gunshi
52
- ```
53
47
 
54
- ### 🥟 Bun
55
-
56
- ```sh
48
+ ## bun
57
49
  bun add gunshi
58
50
  ```
59
51
 
60
52
  ## 🚀 Usage
61
53
 
62
- ### 📏 Simple API
63
-
64
- Gunshi has a simple API that is a facade:
65
-
66
- ```js
67
- import { cli } from 'gunshi'
68
-
69
- const args = process.argv.slice(2)
70
- // run a simple command
71
- await cli(args, () => {
72
- // something logic ...
73
- console.log('Hello from Gunshi!', args)
74
- })
75
- ```
76
-
77
- ### ⚙️ Declarative Configuration
78
-
79
- Configure commands declaratively:
80
-
81
54
  ```js
82
55
  import { cli } from 'gunshi'
83
56
 
@@ -121,289 +94,7 @@ await cli(process.argv.slice(2), command, {
121
94
  })
122
95
  ```
123
96
 
124
- For more detailed examples, check out the [playground/declarative](https://github.com/kazupon/gunshi/tree/main/playground/declarative) in the repository.
125
-
126
- ### 🛡️ Type-Safe Arguments
127
-
128
- Gunshi provides type-safe argument parsing with TypeScript:
129
-
130
- ```ts
131
- import { cli } from 'gunshi'
132
- import type { ArgOptions, Command, CommandContext } from 'gunshi'
133
-
134
- // type-safe arguments parsing example
135
- // this demonstrates how to define and use typed command options with `satisfies`
136
-
137
- // define 'type-safe' command options with types
138
- const options = {
139
- // define string option with short alias
140
- name: {
141
- type: 'string',
142
- short: 'n'
143
- },
144
- // define number option with default value
145
- age: {
146
- type: 'number',
147
- short: 'a',
148
- default: 25
149
- },
150
- // define boolean flag
151
- verbose: {
152
- type: 'boolean',
153
- short: 'v'
154
- }
155
- } satisfies ArgOptions
156
-
157
- // define 'type-safe' command
158
- const command = {
159
- name: 'type-safe',
160
- options,
161
- run: (ctx: CommandContext<UserOptions, UserValues>) => {
162
- const { name, age, verbose } = ctx.values
163
- console.log(`Hello, ${name || 'World'}! You are ${age} years old.`)
164
- }
165
- } satisfies Command<typeof options>
166
-
167
- await cli(process.argv.slice(2), command)
168
- ```
169
-
170
- For more detailed examples, check out the [playground/type-safe](https://github.com/kazupon/gunshi/tree/main/playground/type-safe) in the repository.
171
-
172
- ### 🧩 Composable Sub-commands
173
-
174
- Run a CLI with composable sub-commands:
175
-
176
- ```js
177
- import { cli } from 'gunshi'
178
-
179
- // define 'create' command
180
- const createCommand = {
181
- name: 'create',
182
- description: 'Create a new resource',
183
- options: {
184
- name: { type: 'string', short: 'n' }
185
- },
186
- run: ctx => {
187
- console.log(`Creating resource: ${ctx.values.name}`)
188
- }
189
- }
190
-
191
- // define 'list' command
192
- const listCommand = {
193
- name: 'list',
194
- description: 'List all resources',
195
- run: () => {
196
- console.log('Listing all resources...')
197
- }
198
- }
199
-
200
- // prepare a Map of sub-commands
201
- const subCommands = new Map()
202
- subCommands.set('create', createCommand)
203
- subCommands.set('list', listCommand)
204
-
205
- // define the main ('resource-manager') command
206
- const mainCommand = {
207
- name: 'resource-manager',
208
- description: 'Manage resources',
209
- run: () => {
210
- console.log('Use one of the sub-commands: create, list')
211
- }
212
- }
213
-
214
- // run the CLI with composable sub-commands
215
- await cli(process.argv.slice(2), mainCommand, {
216
- name: 'my-app',
217
- version: '1.0.0',
218
- subCommands
219
- })
220
- ```
221
-
222
- For more detailed examples, check out the [playground/composable](https://github.com/kazupon/gunshi/tree/main/playground/composable) in the repository.
223
-
224
- ### ⏳ Lazy & Async Command Loading
225
-
226
- Load commands lazily and execute them asynchronously:
227
-
228
- ```js
229
- import { cli } from 'gunshi'
230
-
231
- // define a command that will be loaded lazily
232
- const lazyCommand = async () => {
233
- // simulate async loading
234
- await new Promise(resolve => setTimeout(resolve, 1000))
235
-
236
- // return the actual command
237
- return {
238
- name: 'lazy',
239
- description: 'A command that is loaded lazily',
240
- run: async ctx => {
241
- // async execution
242
- await new Promise(resolve => setTimeout(resolve, 500))
243
- console.log('Command executed!')
244
- }
245
- }
246
- }
247
-
248
- // prepare a Map of sub-commands with lazy-loaded commands
249
- const subCommands = new Map()
250
- subCommands.set('lazy', lazyCommand)
251
-
252
- // run the CLI with lazy-loaded commands
253
- await cli(
254
- process.argv.slice(2),
255
- { name: 'main', run: () => {} },
256
- {
257
- name: 'my-app',
258
- subCommands
259
- }
260
- )
261
- ```
262
-
263
- For more detailed examples, check out the [playground/lazy-async](https://github.com/kazupon/gunshi/tree/main/playground/lazy-async) in the repository.
264
-
265
- ### 📜 Auto Usage Generation
266
-
267
- Gunshi automatically generates usage information:
268
-
269
- ```js
270
- import { cli } from 'gunshi'
271
-
272
- const command = {
273
- name: 'app',
274
- description: 'My application',
275
- options: {
276
- path: {
277
- type: 'string',
278
- short: 'p',
279
- description: 'File or directory path'
280
- },
281
- recursive: {
282
- type: 'boolean',
283
- short: 'r',
284
- description: 'Operate recursively on directories'
285
- },
286
- operation: {
287
- type: 'string',
288
- short: 'o',
289
- required: true,
290
- description: 'Operation to perform (list, copy, move, delete)'
291
- }
292
- },
293
- // define examples
294
- examples: '# Example\n$ my-app --operation list --path ./src',
295
- run: ctx => {
296
- // command implementation
297
- }
298
- }
299
-
300
- // run with --help to see the automatically generated usage information
301
- await cli(process.argv.slice(2), command, {
302
- name: 'my-app',
303
- version: '1.0.0'
304
- })
305
- ```
306
-
307
- For more detailed examples, check out the [playground/auto-usage](https://github.com/kazupon/gunshi/tree/main/playground/auto-usage) in the repository.
308
-
309
- ### 🎨 Custom Usage Generation
310
-
311
- Customize the usage message generation:
312
-
313
- ```js
314
- import { cli } from 'gunshi'
315
-
316
- // define custom header renderer
317
- const customHeaderRenderer = ctx => {
318
- return Promise.resolve(`
319
- ╔═══════════════════════╗
320
- ║ ${ctx.env.name.toUpperCase()} ║
321
- ╚═══════════════════════╝
322
- ${ctx.env.description}
323
- Version: ${ctx.env.version}
324
- `)
325
- }
326
-
327
- // define custom usage renderer
328
- const customUsageRenderer = ctx => {
329
- const lines = []
330
- lines.push('USAGE:')
331
- lines.push(` $ ${ctx.env.name} [options]`)
332
- lines.push('')
333
- lines.push('OPTIONS:')
334
-
335
- for (const [key, option] of Object.entries(ctx.options || Object.create(null))) {
336
- const shortFlag = option.short ? `-${option.short}, ` : ' '
337
- lines.push(` ${shortFlag}--${key.padEnd(10)} ${ctx.translate(key)}`)
338
- }
339
-
340
- return Promise.resolve(lines.join('\n'))
341
- }
342
-
343
- // run with custom renderers
344
- await cli(
345
- process.argv.slice(2),
346
- { name: 'app', run: () => {} },
347
- {
348
- name: 'my-app',
349
- version: '1.0.0',
350
- description: 'My application',
351
- renderHeader: customHeaderRenderer,
352
- renderUsage: customUsageRenderer
353
- }
354
- )
355
- ```
356
-
357
- For more detailed examples, check out the [playground/custom-usage](https://github.com/kazupon/gunshi/tree/main/playground/custom-usage) in the repository.
358
-
359
- ### 🌍 Internationalization
360
-
361
- Support internationalization:
362
-
363
- ```js
364
- import { cli } from 'gunshi'
365
- import enUS from './locales/en-US.json' with { type: 'json' }
366
-
367
- const command = {
368
- name: 'greeter',
369
- options: {
370
- name: {
371
- type: 'string',
372
- short: 'n'
373
- },
374
- formal: {
375
- type: 'boolean',
376
- short: 'f'
377
- }
378
- },
379
- // resource fetcher for translations
380
- resource: async ctx => {
381
- if (ctx.locale.toString() === 'ja-JP') {
382
- const resource = await import('./locales/ja-JP.json', { with: { type: 'json' } })
383
- return resource.default
384
- }
385
-
386
- // default to English
387
- return enUS
388
- },
389
- run: ctx => {
390
- const { name = 'World', formal } = ctx.values
391
- const greeting = formal ? ctx.translate('formal_greeting') : ctx.translate('informal_greeting')
392
- console.log(`${greeting}, ${name}!`)
393
- }
394
- }
395
-
396
- // run with locale support
397
- await cli(process.argv.slice(2), command, {
398
- name: 'my-app',
399
- version: '1.0.0',
400
- // set the locale via an environment variable
401
- // if Node v21 or later is used, you can use the built-in `navigator.language` instead)
402
- locale: new Intl.Locale(process.env.MY_LOCALE || 'en-US')
403
- })
404
- ```
405
-
406
- For more detailed examples, check out the [playground/i18n](https://github.com/kazupon/gunshi/tree/main/playground/i18n) in the repository.
97
+ About more details and usage, see [documentations](https://gunshi.dev)
407
98
 
408
99
  ## 💁‍♀️ Showcases
409
100
 
@@ -423,6 +114,16 @@ This project is inspired and powered by:
423
114
 
424
115
  Thank you!
425
116
 
117
+ ## 🤝 Sponsors
118
+
119
+ The development of Gunish is supported by my OSS sponsors!
120
+
121
+ <p align="center">
122
+ <a href="https://cdn.jsdelivr.net/gh/kazupon/sponsors/sponsors.svg">
123
+ <img src='https://cdn.jsdelivr.net/gh/kazupon/sponsors/sponsors.svg'/>
124
+ </a>
125
+ </p>
126
+
426
127
  ## ©️ License
427
128
 
428
129
  [MIT](http://opensource.org/licenses/MIT)
@@ -60,7 +60,7 @@ var DefaultTranslation = class {
60
60
  //#endregion
61
61
  //#region src/context.ts
62
62
  const BUILT_IN_PREFIX_CODE = BUILT_IN_PREFIX.codePointAt(0);
63
- async function createCommandContext({ options, values, positionals, command, commandOptions, omitted = false }) {
63
+ async function createCommandContext({ options, values, positionals, args, command, commandOptions, omitted = false }) {
64
64
  /**
65
65
  * normailize the options schema and values, to avoid prototype pollution
66
66
  */
@@ -121,6 +121,7 @@ async function createCommandContext({ options, values, positionals, command, com
121
121
  options: _options,
122
122
  values,
123
123
  positionals,
124
+ _: args,
124
125
  log: commandOptions.usageSilent ? NOOP : log,
125
126
  loadCommands,
126
127
  translate
@@ -179,6 +180,7 @@ async function cli(args, entry, opts = {}) {
179
180
  options,
180
181
  values,
181
182
  positionals,
183
+ args,
182
184
  omitted,
183
185
  command,
184
186
  commandOptions: resolvedCommandOptions
@@ -1,5 +1,5 @@
1
1
  import { ArgOptions } from 'args-tokens';
2
- import { C as Command, a as CommandOptions } from './types.d-DIY9YbHU.js';
2
+ import { C as Command, a as CommandOptions } from './types.d-DqtZy3HN.js';
3
3
 
4
4
  /**
5
5
  * Generate the command usage.
package/lib/generator.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { create } from "./renderer-DAUAIZxV.js";
2
- import { cli } from "./cli-C-y15OeH.js";
2
+ import { cli } from "./cli-D_4MqIMP.js";
3
3
 
4
4
  //#region src/generator.ts
5
5
  async function generate(command, entry, opts = {}) {
package/lib/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ArgOptions } from 'args-tokens';
2
- export { ArgOptionSchema, ArgOptions, ArgValues } from 'args-tokens';
3
- import { C as Command, b as CommandRunner, a as CommandOptions, T as TranslationAdapter, c as TranslationAdapterFactoryOptions } from './types.d-DIY9YbHU.js';
4
- export { f as CommandBuiltinKeys, d as CommandBuiltinOptionsKeys, e as CommandBuiltinResourceKeys, h as CommandContext, g as CommandEnvironment, i as CommandResource, j as CommandResourceFetcher, l as Commandable, D as DEFAULT_LOCALE, G as GenerateNamespacedKey, L as LazyCommand, k as TranslationAdapterFactory } from './types.d-DIY9YbHU.js';
2
+ export { ArgOptionSchema, ArgOptions, ArgValues, parseArgs, resolveArgs } from 'args-tokens';
3
+ import { C as Command, b as CommandRunner, a as CommandOptions, T as TranslationAdapter, c as TranslationAdapterFactoryOptions } from './types.d-DqtZy3HN.js';
4
+ export { f as CommandBuiltinKeys, d as CommandBuiltinOptionsKeys, e as CommandBuiltinResourceKeys, h as CommandContext, g as CommandEnvironment, i as CommandResource, j as CommandResourceFetcher, l as Commandable, D as DEFAULT_LOCALE, G as GenerateNamespacedKey, L as LazyCommand, k as TranslationAdapterFactory } from './types.d-DqtZy3HN.js';
5
5
 
6
6
  /**
7
7
  * Run the command.
package/lib/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { DEFAULT_LOCALE } from "./renderer-DAUAIZxV.js";
2
- import { DefaultTranslation, cli } from "./cli-C-y15OeH.js";
2
+ import { DefaultTranslation, cli } from "./cli-D_4MqIMP.js";
3
+ import { parseArgs, resolveArgs } from "args-tokens";
3
4
 
4
- export { DEFAULT_LOCALE, DefaultTranslation, cli };
5
+ export { DEFAULT_LOCALE, DefaultTranslation, cli, parseArgs, resolveArgs };
@@ -1,5 +1,5 @@
1
1
  import { ArgOptions } from 'args-tokens';
2
- import { h as CommandContext } from '../types.d-DIY9YbHU.js';
2
+ import { h as CommandContext } from '../types.d-DqtZy3HN.js';
3
3
 
4
4
  /**
5
5
  * Render the header.
@@ -235,6 +235,11 @@ interface CommandContext<
235
235
  */
236
236
  positionals: string[];
237
237
  /**
238
+ * Original command line arguments.
239
+ * This argument is passed from `cli` function.
240
+ */
241
+ _: string[];
242
+ /**
238
243
  * Whether the currently executing command has been executed with the sub-command name omitted.
239
244
  */
240
245
  omitted: boolean;
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.12.0",
4
+ "version": "0.13.0",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -87,13 +87,15 @@
87
87
  "eslint-plugin-regexp": "^2.7.0",
88
88
  "eslint-plugin-unicorn": "^58.0.0",
89
89
  "eslint-plugin-unused-imports": "^4.1.4",
90
+ "eslint-plugin-vue": "^10.0.0",
91
+ "eslint-plugin-vue-composable": "^1.0.0",
90
92
  "eslint-plugin-yml": "^1.17.0",
91
93
  "gh-changelogen": "^0.2.8",
92
94
  "jsr": "^0.13.4",
93
95
  "knip": "^5.46.3",
94
96
  "lint-staged": "^15.5.0",
95
97
  "messageformat": "4.0.0-10",
96
- "pkg-pr-new": "^0.0.41",
98
+ "pkg-pr-new": "^0.0.42",
97
99
  "prettier": "^3.5.3",
98
100
  "tsdown": "^0.6.10",
99
101
  "typedoc": "^0.28.1",
@@ -103,8 +105,9 @@
103
105
  "typescript-eslint": "^8.28.0",
104
106
  "vitepress": "^1.6.3",
105
107
  "vitepress-plugin-group-icons": "^1.3.8",
106
- "vitepress-plugin-llms": "^0.0.21",
107
- "vitest": "^3.0.9"
108
+ "vitepress-plugin-llms": "^0.0.22",
109
+ "vitest": "^3.0.9",
110
+ "vue": "^3.5.13"
108
111
  },
109
112
  "prettier": "@kazupon/prettier-config",
110
113
  "lint-staged": {