citty 0.1.2 → 0.1.4

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
@@ -65,7 +65,7 @@ const main = defineCommand({
65
65
  },
66
66
  },
67
67
  run({ args }) {
68
- consol.log(`${args.friendly ? "Hi" : "Greetings"} ${args.name}!`);
68
+ console.log(`${args.friendly ? "Hi" : "Greetings"} ${args.name}!`);
69
69
  },
70
70
  });
71
71
 
@@ -82,6 +82,10 @@ runMain(main);
82
82
 
83
83
  Runs a command with usage support and graceful error handling.
84
84
 
85
+ ### `createMain`
86
+
87
+ Create a wrapper around command that calls `runMain` when called.
88
+
85
89
  ### `runCommand`
86
90
 
87
91
  Parses input args and runs command and sub-commands (unsupervised).
package/dist/index.cjs CHANGED
@@ -293,30 +293,37 @@ async function runCommand(cmd, opts) {
293
293
  if (typeof cmd.setup === "function") {
294
294
  await cmd.setup(context);
295
295
  }
296
- const subCommands = await resolveValue(cmd.subCommands);
297
- if (subCommands && Object.keys(subCommands).length > 0) {
298
- const subCommandArgIndex = opts.rawArgs.findIndex(
299
- (arg) => !arg.startsWith("-")
300
- );
301
- const subCommandName = opts.rawArgs[subCommandArgIndex];
302
- if (!subCommandName && !cmd.run) {
303
- throw new CLIError(`No command specified.`, "E_NO_COMMAND");
304
- }
305
- if (!subCommands[subCommandName]) {
306
- throw new CLIError(
307
- `Unknown command \`${subCommandName}\``,
308
- "E_UNKNOWN_COMMAND"
296
+ try {
297
+ const subCommands = await resolveValue(cmd.subCommands);
298
+ if (subCommands && Object.keys(subCommands).length > 0) {
299
+ const subCommandArgIndex = opts.rawArgs.findIndex(
300
+ (arg) => !arg.startsWith("-")
309
301
  );
302
+ const subCommandName = opts.rawArgs[subCommandArgIndex];
303
+ if (subCommandName) {
304
+ if (!subCommands[subCommandName]) {
305
+ throw new CLIError(
306
+ `Unknown command \`${subCommandName}\``,
307
+ "E_UNKNOWN_COMMAND"
308
+ );
309
+ }
310
+ const subCommand = await resolveValue(subCommands[subCommandName]);
311
+ if (subCommand) {
312
+ await runCommand(subCommand, {
313
+ rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1)
314
+ });
315
+ }
316
+ } else if (!cmd.run) {
317
+ throw new CLIError(`No command specified.`, "E_NO_COMMAND");
318
+ }
310
319
  }
311
- const subCommand = await resolveValue(subCommands[subCommandName]);
312
- if (subCommand) {
313
- await runCommand(subCommand, {
314
- rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1)
315
- });
320
+ if (typeof cmd.run === "function") {
321
+ await cmd.run(context);
322
+ }
323
+ } finally {
324
+ if (typeof cmd.cleanup === "function") {
325
+ await cmd.cleanup(context);
316
326
  }
317
- }
318
- if (typeof cmd.run === "function") {
319
- await cmd.run(context);
320
327
  }
321
328
  }
322
329
  async function resolveSubCommand(cmd, rawArgs, parent) {
@@ -427,6 +434,12 @@ async function runMain(cmd, opts = {}) {
427
434
  if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
428
435
  await showUsage(...await resolveSubCommand(cmd, rawArgs));
429
436
  process.exit(0);
437
+ } else if (rawArgs.length === 1 && rawArgs[0] === "--version") {
438
+ const meta = typeof cmd.meta === "function" ? await cmd.meta() : await cmd.meta;
439
+ if (!meta?.version) {
440
+ throw new CLIError("No version specified", "E_NO_VERSION");
441
+ }
442
+ consola__default.log(meta.version);
430
443
  } else {
431
444
  await runCommand(cmd, { rawArgs });
432
445
  }
@@ -442,7 +455,11 @@ async function runMain(cmd, opts = {}) {
442
455
  process.exit(1);
443
456
  }
444
457
  }
458
+ function createMain(cmd) {
459
+ return (opts = {}) => runMain(cmd, opts);
460
+ }
445
461
 
462
+ exports.createMain = createMain;
446
463
  exports.defineCommand = defineCommand;
447
464
  exports.parseArgs = parseArgs;
448
465
  exports.renderUsage = renderUsage;
@@ -0,0 +1,77 @@
1
+ type ArgType = "boolean" | "string" | "positional" | undefined;
2
+ type _ArgDef<T extends ArgType, VT extends boolean | string> = {
3
+ type?: T;
4
+ description?: string;
5
+ valueHint?: string;
6
+ alias?: string | string[];
7
+ default?: VT;
8
+ required?: boolean;
9
+ };
10
+ type BooleanArgDef = _ArgDef<"boolean", boolean>;
11
+ type StringArgDef = _ArgDef<"string", string>;
12
+ type PositionalArgDef = Omit<_ArgDef<"positional", string>, "alias">;
13
+ type ArgDef = BooleanArgDef | StringArgDef | PositionalArgDef;
14
+ type ArgsDef = Record<string, ArgDef>;
15
+ type Arg = ArgDef & {
16
+ name: string;
17
+ alias: string[];
18
+ };
19
+ type ParsedArgs<T extends ArgsDef = ArgsDef> = {
20
+ _: string[];
21
+ } & Record<{
22
+ [K in keyof T]: T[K] extends {
23
+ type: "positional";
24
+ } ? K : never;
25
+ }[keyof T], string> & Record<{
26
+ [K in keyof T]: T[K] extends {
27
+ type: "string";
28
+ } ? K : never;
29
+ }[keyof T], string> & Record<{
30
+ [K in keyof T]: T[K] extends {
31
+ type: "boolean";
32
+ } ? K : never;
33
+ }[keyof T], boolean> & Record<string, string | boolean | string[]>;
34
+ interface CommandMeta {
35
+ name?: string;
36
+ version?: string;
37
+ description?: string;
38
+ }
39
+ type SubCommandsDef = Record<string, Resolvable<CommandDef<any>>>;
40
+ type CommandDef<T extends ArgsDef = ArgsDef> = {
41
+ meta?: Resolvable<CommandMeta>;
42
+ args?: Resolvable<T>;
43
+ subCommands?: Resolvable<SubCommandsDef>;
44
+ setup?: (context: CommandContext<T>) => any | Promise<any>;
45
+ cleanup?: (context: CommandContext<T>) => any | Promise<any>;
46
+ run?: (context: CommandContext<T>) => any | Promise<any>;
47
+ };
48
+ type CommandContext<T extends ArgsDef = ArgsDef> = {
49
+ rawArgs: string[];
50
+ args: ParsedArgs<T>;
51
+ cmd: CommandDef<T>;
52
+ subCommand?: CommandDef<T>;
53
+ data?: any;
54
+ };
55
+ type Awaitable<T> = () => T | Promise<T>;
56
+ type Resolvable<T> = T | Promise<T> | (() => T) | (() => Promise<T>);
57
+
58
+ declare function defineCommand<T extends ArgsDef = ArgsDef>(def: CommandDef<T>): CommandDef<T>;
59
+ interface RunCommandOptions {
60
+ rawArgs: string[];
61
+ data?: any;
62
+ showUsage?: boolean;
63
+ }
64
+ declare function runCommand<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, opts: RunCommandOptions): Promise<void>;
65
+
66
+ interface RunMainOptions {
67
+ rawArgs?: string[];
68
+ }
69
+ declare function runMain<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, opts?: RunMainOptions): Promise<void>;
70
+ declare function createMain<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>): (opts?: RunMainOptions) => Promise<void>;
71
+
72
+ declare function parseArgs<T extends ArgsDef = ArgsDef>(rawArgs: string[], argsDef: ArgsDef): ParsedArgs<T>;
73
+
74
+ declare function showUsage<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, parent?: CommandDef<T>): Promise<void>;
75
+ declare function renderUsage<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, parent?: CommandDef<T>): Promise<string>;
76
+
77
+ export { type Arg, type ArgDef, type ArgType, type ArgsDef, type Awaitable, type BooleanArgDef, type CommandContext, type CommandDef, type CommandMeta, type ParsedArgs, type PositionalArgDef, type Resolvable, type RunCommandOptions, type RunMainOptions, type StringArgDef, type SubCommandsDef, type _ArgDef, createMain, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
@@ -0,0 +1,77 @@
1
+ type ArgType = "boolean" | "string" | "positional" | undefined;
2
+ type _ArgDef<T extends ArgType, VT extends boolean | string> = {
3
+ type?: T;
4
+ description?: string;
5
+ valueHint?: string;
6
+ alias?: string | string[];
7
+ default?: VT;
8
+ required?: boolean;
9
+ };
10
+ type BooleanArgDef = _ArgDef<"boolean", boolean>;
11
+ type StringArgDef = _ArgDef<"string", string>;
12
+ type PositionalArgDef = Omit<_ArgDef<"positional", string>, "alias">;
13
+ type ArgDef = BooleanArgDef | StringArgDef | PositionalArgDef;
14
+ type ArgsDef = Record<string, ArgDef>;
15
+ type Arg = ArgDef & {
16
+ name: string;
17
+ alias: string[];
18
+ };
19
+ type ParsedArgs<T extends ArgsDef = ArgsDef> = {
20
+ _: string[];
21
+ } & Record<{
22
+ [K in keyof T]: T[K] extends {
23
+ type: "positional";
24
+ } ? K : never;
25
+ }[keyof T], string> & Record<{
26
+ [K in keyof T]: T[K] extends {
27
+ type: "string";
28
+ } ? K : never;
29
+ }[keyof T], string> & Record<{
30
+ [K in keyof T]: T[K] extends {
31
+ type: "boolean";
32
+ } ? K : never;
33
+ }[keyof T], boolean> & Record<string, string | boolean | string[]>;
34
+ interface CommandMeta {
35
+ name?: string;
36
+ version?: string;
37
+ description?: string;
38
+ }
39
+ type SubCommandsDef = Record<string, Resolvable<CommandDef<any>>>;
40
+ type CommandDef<T extends ArgsDef = ArgsDef> = {
41
+ meta?: Resolvable<CommandMeta>;
42
+ args?: Resolvable<T>;
43
+ subCommands?: Resolvable<SubCommandsDef>;
44
+ setup?: (context: CommandContext<T>) => any | Promise<any>;
45
+ cleanup?: (context: CommandContext<T>) => any | Promise<any>;
46
+ run?: (context: CommandContext<T>) => any | Promise<any>;
47
+ };
48
+ type CommandContext<T extends ArgsDef = ArgsDef> = {
49
+ rawArgs: string[];
50
+ args: ParsedArgs<T>;
51
+ cmd: CommandDef<T>;
52
+ subCommand?: CommandDef<T>;
53
+ data?: any;
54
+ };
55
+ type Awaitable<T> = () => T | Promise<T>;
56
+ type Resolvable<T> = T | Promise<T> | (() => T) | (() => Promise<T>);
57
+
58
+ declare function defineCommand<T extends ArgsDef = ArgsDef>(def: CommandDef<T>): CommandDef<T>;
59
+ interface RunCommandOptions {
60
+ rawArgs: string[];
61
+ data?: any;
62
+ showUsage?: boolean;
63
+ }
64
+ declare function runCommand<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, opts: RunCommandOptions): Promise<void>;
65
+
66
+ interface RunMainOptions {
67
+ rawArgs?: string[];
68
+ }
69
+ declare function runMain<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, opts?: RunMainOptions): Promise<void>;
70
+ declare function createMain<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>): (opts?: RunMainOptions) => Promise<void>;
71
+
72
+ declare function parseArgs<T extends ArgsDef = ArgsDef>(rawArgs: string[], argsDef: ArgsDef): ParsedArgs<T>;
73
+
74
+ declare function showUsage<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, parent?: CommandDef<T>): Promise<void>;
75
+ declare function renderUsage<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, parent?: CommandDef<T>): Promise<string>;
76
+
77
+ export { type Arg, type ArgDef, type ArgType, type ArgsDef, type Awaitable, type BooleanArgDef, type CommandContext, type CommandDef, type CommandMeta, type ParsedArgs, type PositionalArgDef, type Resolvable, type RunCommandOptions, type RunMainOptions, type StringArgDef, type SubCommandsDef, type _ArgDef, createMain, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
package/dist/index.d.ts CHANGED
@@ -30,7 +30,7 @@ type ParsedArgs<T extends ArgsDef = ArgsDef> = {
30
30
  [K in keyof T]: T[K] extends {
31
31
  type: "boolean";
32
32
  } ? K : never;
33
- }[keyof T], boolean> & Record<string, string | boolean>;
33
+ }[keyof T], boolean> & Record<string, string | boolean | string[]>;
34
34
  interface CommandMeta {
35
35
  name?: string;
36
36
  version?: string;
@@ -67,10 +67,11 @@ interface RunMainOptions {
67
67
  rawArgs?: string[];
68
68
  }
69
69
  declare function runMain<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, opts?: RunMainOptions): Promise<void>;
70
+ declare function createMain<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>): (opts?: RunMainOptions) => Promise<void>;
70
71
 
71
72
  declare function parseArgs<T extends ArgsDef = ArgsDef>(rawArgs: string[], argsDef: ArgsDef): ParsedArgs<T>;
72
73
 
73
74
  declare function showUsage<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, parent?: CommandDef<T>): Promise<void>;
74
75
  declare function renderUsage<T extends ArgsDef = ArgsDef>(cmd: CommandDef<T>, parent?: CommandDef<T>): Promise<string>;
75
76
 
76
- export { Arg, ArgDef, ArgType, ArgsDef, Awaitable, BooleanArgDef, CommandContext, CommandDef, CommandMeta, ParsedArgs, PositionalArgDef, Resolvable, RunCommandOptions, RunMainOptions, StringArgDef, SubCommandsDef, _ArgDef, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
77
+ export { type Arg, type ArgDef, type ArgType, type ArgsDef, type Awaitable, type BooleanArgDef, type CommandContext, type CommandDef, type CommandMeta, type ParsedArgs, type PositionalArgDef, type Resolvable, type RunCommandOptions, type RunMainOptions, type StringArgDef, type SubCommandsDef, type _ArgDef, createMain, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
package/dist/index.mjs CHANGED
@@ -287,30 +287,37 @@ async function runCommand(cmd, opts) {
287
287
  if (typeof cmd.setup === "function") {
288
288
  await cmd.setup(context);
289
289
  }
290
- const subCommands = await resolveValue(cmd.subCommands);
291
- if (subCommands && Object.keys(subCommands).length > 0) {
292
- const subCommandArgIndex = opts.rawArgs.findIndex(
293
- (arg) => !arg.startsWith("-")
294
- );
295
- const subCommandName = opts.rawArgs[subCommandArgIndex];
296
- if (!subCommandName && !cmd.run) {
297
- throw new CLIError(`No command specified.`, "E_NO_COMMAND");
298
- }
299
- if (!subCommands[subCommandName]) {
300
- throw new CLIError(
301
- `Unknown command \`${subCommandName}\``,
302
- "E_UNKNOWN_COMMAND"
290
+ try {
291
+ const subCommands = await resolveValue(cmd.subCommands);
292
+ if (subCommands && Object.keys(subCommands).length > 0) {
293
+ const subCommandArgIndex = opts.rawArgs.findIndex(
294
+ (arg) => !arg.startsWith("-")
303
295
  );
296
+ const subCommandName = opts.rawArgs[subCommandArgIndex];
297
+ if (subCommandName) {
298
+ if (!subCommands[subCommandName]) {
299
+ throw new CLIError(
300
+ `Unknown command \`${subCommandName}\``,
301
+ "E_UNKNOWN_COMMAND"
302
+ );
303
+ }
304
+ const subCommand = await resolveValue(subCommands[subCommandName]);
305
+ if (subCommand) {
306
+ await runCommand(subCommand, {
307
+ rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1)
308
+ });
309
+ }
310
+ } else if (!cmd.run) {
311
+ throw new CLIError(`No command specified.`, "E_NO_COMMAND");
312
+ }
304
313
  }
305
- const subCommand = await resolveValue(subCommands[subCommandName]);
306
- if (subCommand) {
307
- await runCommand(subCommand, {
308
- rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1)
309
- });
314
+ if (typeof cmd.run === "function") {
315
+ await cmd.run(context);
316
+ }
317
+ } finally {
318
+ if (typeof cmd.cleanup === "function") {
319
+ await cmd.cleanup(context);
310
320
  }
311
- }
312
- if (typeof cmd.run === "function") {
313
- await cmd.run(context);
314
321
  }
315
322
  }
316
323
  async function resolveSubCommand(cmd, rawArgs, parent) {
@@ -421,6 +428,12 @@ async function runMain(cmd, opts = {}) {
421
428
  if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
422
429
  await showUsage(...await resolveSubCommand(cmd, rawArgs));
423
430
  process.exit(0);
431
+ } else if (rawArgs.length === 1 && rawArgs[0] === "--version") {
432
+ const meta = typeof cmd.meta === "function" ? await cmd.meta() : await cmd.meta;
433
+ if (!meta?.version) {
434
+ throw new CLIError("No version specified", "E_NO_VERSION");
435
+ }
436
+ consola.log(meta.version);
424
437
  } else {
425
438
  await runCommand(cmd, { rawArgs });
426
439
  }
@@ -436,5 +449,8 @@ async function runMain(cmd, opts = {}) {
436
449
  process.exit(1);
437
450
  }
438
451
  }
452
+ function createMain(cmd) {
453
+ return (opts = {}) => runMain(cmd, opts);
454
+ }
439
455
 
440
- export { defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
456
+ export { createMain, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "citty",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Elegant CLI Builder",
5
5
  "repository": "unjs/citty",
6
6
  "license": "MIT",
@@ -33,17 +33,17 @@
33
33
  "consola": "^3.2.3"
34
34
  },
35
35
  "devDependencies": {
36
- "@types/node": "^20.4.0",
37
- "@vitest/coverage-v8": "^0.32.4",
38
- "changelogen": "^0.5.4",
39
- "eslint": "^8.44.0",
36
+ "@types/node": "^20.6.0",
37
+ "@vitest/coverage-v8": "^0.34.4",
38
+ "changelogen": "^0.5.5",
39
+ "eslint": "^8.49.0",
40
40
  "eslint-config-unjs": "^0.2.1",
41
- "jiti": "^1.19.1",
42
- "prettier": "^3.0.0",
41
+ "jiti": "^1.20.0",
42
+ "prettier": "^3.0.3",
43
43
  "scule": "^1.0.0",
44
- "typescript": "^5.1.6",
45
- "unbuild": "^1.2.1",
46
- "vitest": "^0.32.4"
44
+ "typescript": "^5.2.2",
45
+ "unbuild": "^2.0.0",
46
+ "vitest": "^0.34.4"
47
47
  },
48
- "packageManager": "pnpm@8.6.6"
48
+ "packageManager": "pnpm@8.7.4"
49
49
  }