citty 0.0.1 → 0.0.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/dist/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const scule = require('scule');
3
4
  const tty = require('tty');
4
5
 
5
6
  function _interopNamespaceDefault(e) {
@@ -180,23 +181,30 @@ function parseArgs(rawArgs, argsDef) {
180
181
  }
181
182
  }
182
183
  const parsed = parseRawArgs(rawArgs, parseOptions);
183
- for (const [i, arg] of args.entries()) {
184
+ const [, ...positionalArguments] = parsed._;
185
+ const parsedArgsProxy = new Proxy(parsed, {
186
+ get(target, prop) {
187
+ return target[prop] ?? target[scule.camelCase(prop)] ?? target[scule.kebabCase(prop)];
188
+ }
189
+ });
190
+ for (const [, arg] of args.entries()) {
184
191
  if (arg.type === "positional") {
185
- if (parsed._[i] !== void 0) {
186
- parsed[arg.name] = parsed._[i];
192
+ const nextPositionalArgument = positionalArguments.shift();
193
+ if (nextPositionalArgument !== void 0) {
194
+ parsedArgsProxy[arg.name] = nextPositionalArgument;
187
195
  } else if (arg.default !== void 0) {
188
- parsed[arg.name] = arg.default;
196
+ parsedArgsProxy[arg.name] = arg.default;
189
197
  } else {
190
198
  throw new CLIError(
191
199
  `Missing required positional argument: ${arg.name.toUpperCase()}`,
192
200
  "EARG"
193
201
  );
194
202
  }
195
- } else if (arg.required && parsed[arg.name] === void 0) {
203
+ } else if (arg.required && parsedArgsProxy[arg.name] === void 0) {
196
204
  throw new CLIError(`Missing required argument: --${arg.name}`, "EARG");
197
205
  }
198
206
  }
199
- return parsed;
207
+ return parsedArgsProxy;
200
208
  }
201
209
  function resolveArgs(argsDef) {
202
210
  const args = [];
@@ -214,17 +222,18 @@ function defineCommand(def) {
214
222
  return def;
215
223
  }
216
224
  async function runCommand(cmd, opts) {
217
- if (typeof cmd.run === "function") {
218
- const cmdArgs = await resolveValue(cmd.args || {});
219
- const parsedArgs = parseArgs(opts.rawArgs, cmdArgs);
220
- await cmd.run({
221
- rawArgs: opts.rawArgs,
222
- args: parsedArgs,
223
- cmd
224
- });
225
+ const cmdArgs = await resolveValue(cmd.args || {});
226
+ const parsedArgs = parseArgs(opts.rawArgs, cmdArgs);
227
+ const context = {
228
+ rawArgs: opts.rawArgs,
229
+ args: parsedArgs,
230
+ cmd
231
+ };
232
+ if (typeof cmd.setup === "function") {
233
+ await cmd.setup(context);
225
234
  }
226
235
  const subCommands = await resolveValue(cmd.subCommands);
227
- if (subCommands && Object.keys(subCommands.length > 0)) {
236
+ if (subCommands && Object.keys(subCommands).length > 0) {
228
237
  const subCommandArgIndex = opts.rawArgs.findIndex(
229
238
  (arg) => !arg.startsWith("-")
230
239
  );
@@ -248,10 +257,13 @@ async function runCommand(cmd, opts) {
248
257
  });
249
258
  }
250
259
  }
260
+ if (typeof cmd.run === "function") {
261
+ await cmd.run(context);
262
+ }
251
263
  }
252
264
  async function resolveSubCommand(cmd, rawArgs, parent) {
253
265
  const subCommands = await resolveValue(cmd.subCommands);
254
- if (subCommands && Object.keys(subCommands.length > 0)) {
266
+ if (subCommands && Object.keys(subCommands).length > 0) {
255
267
  const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-"));
256
268
  const subCommandName = rawArgs[subCommandArgIndex];
257
269
  const subCommand = await resolveValue(subCommands[subCommandName]);
package/dist/index.d.ts CHANGED
@@ -16,31 +16,45 @@ type Arg = ArgDef & {
16
16
  name: string;
17
17
  alias: string[];
18
18
  };
19
- type ParsedArgs = Record<string, string | boolean> & {
19
+ type ParsedArgs<T extends ArgsDef = ArgsDef> = {
20
20
  _: string[];
21
- };
21
+ } & Record<{
22
+ [K in keyof T]: T[K] extends {
23
+ type: "positional";
24
+ } ? K : never;
25
+ }[keyof T], string | boolean> & 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>;
22
34
  interface CommandMeta {
23
35
  name?: string;
24
36
  version?: string;
25
37
  description?: string;
26
38
  }
27
- type SubCommandsDef = Record<string, Resolvable<CommandDef>>;
28
- type CommandDef = {
39
+ type SubCommandsDef = Record<string, Resolvable<CommandDef<any>>>;
40
+ type CommandDef<T extends ArgsDef = ArgsDef> = {
29
41
  meta?: Resolvable<CommandMeta>;
30
- args?: Resolvable<ArgsDef>;
42
+ args?: Resolvable<T>;
31
43
  subCommands?: Resolvable<SubCommandsDef>;
32
- run?: CommandRun;
44
+ setup?: (context: CommandContext<T>) => any | Promise<any>;
45
+ cleanup?: (context: CommandContext<T>) => any | Promise<any>;
46
+ run?: (context: CommandContext<T>) => any | Promise<any>;
33
47
  };
34
- type CommandRun = (context: CommandContext) => any | Promise<any>;
35
- interface CommandContext {
48
+ type CommandContext<T extends ArgsDef = ArgsDef> = {
36
49
  rawArgs: string[];
37
- args: ParsedArgs;
50
+ args: ParsedArgs<T>;
38
51
  cmd: CommandDef;
39
- }
52
+ subCommand?: CommandDef<T>;
53
+ };
40
54
  type Awaitable<T> = () => T | Promise<T>;
41
55
  type Resolvable<T> = T | Promise<T> | (() => T) | (() => Promise<T>);
42
56
 
43
- declare function defineCommand(def: CommandDef): CommandDef;
57
+ declare function defineCommand<T extends ArgsDef = ArgsDef>(def: CommandDef<T>): CommandDef<T>;
44
58
  interface RunCommandOptions {
45
59
  rawArgs: string[];
46
60
  showUsage?: boolean;
@@ -57,4 +71,4 @@ declare function parseArgs(rawArgs: string[], argsDef: ArgsDef): ParsedArgs;
57
71
  declare function showUsage(cmd: CommandDef, parent?: CommandDef): Promise<void>;
58
72
  declare function renderUsage(cmd: CommandDef, parent?: CommandDef): Promise<string>;
59
73
 
60
- export { Arg, ArgDef, ArgType, ArgsDef, Awaitable, BooleanArgDef, CommandContext, CommandDef, CommandMeta, CommandRun, ParsedArgs, PositionalArgDef, Resolvable, RunCommandOptions, RunMainOptions, StringArgDef, SubCommandsDef, _ArgDef, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
74
+ export { Arg, ArgDef, ArgType, ArgsDef, Awaitable, BooleanArgDef, CommandContext, CommandDef, CommandMeta, ParsedArgs, PositionalArgDef, Resolvable, RunCommandOptions, RunMainOptions, StringArgDef, SubCommandsDef, _ArgDef, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { camelCase, kebabCase } from 'scule';
1
2
  import * as tty from 'tty';
2
3
 
3
4
  function toArray(val) {
@@ -165,23 +166,30 @@ function parseArgs(rawArgs, argsDef) {
165
166
  }
166
167
  }
167
168
  const parsed = parseRawArgs(rawArgs, parseOptions);
168
- for (const [i, arg] of args.entries()) {
169
+ const [, ...positionalArguments] = parsed._;
170
+ const parsedArgsProxy = new Proxy(parsed, {
171
+ get(target, prop) {
172
+ return target[prop] ?? target[camelCase(prop)] ?? target[kebabCase(prop)];
173
+ }
174
+ });
175
+ for (const [, arg] of args.entries()) {
169
176
  if (arg.type === "positional") {
170
- if (parsed._[i] !== void 0) {
171
- parsed[arg.name] = parsed._[i];
177
+ const nextPositionalArgument = positionalArguments.shift();
178
+ if (nextPositionalArgument !== void 0) {
179
+ parsedArgsProxy[arg.name] = nextPositionalArgument;
172
180
  } else if (arg.default !== void 0) {
173
- parsed[arg.name] = arg.default;
181
+ parsedArgsProxy[arg.name] = arg.default;
174
182
  } else {
175
183
  throw new CLIError(
176
184
  `Missing required positional argument: ${arg.name.toUpperCase()}`,
177
185
  "EARG"
178
186
  );
179
187
  }
180
- } else if (arg.required && parsed[arg.name] === void 0) {
188
+ } else if (arg.required && parsedArgsProxy[arg.name] === void 0) {
181
189
  throw new CLIError(`Missing required argument: --${arg.name}`, "EARG");
182
190
  }
183
191
  }
184
- return parsed;
192
+ return parsedArgsProxy;
185
193
  }
186
194
  function resolveArgs(argsDef) {
187
195
  const args = [];
@@ -199,17 +207,18 @@ function defineCommand(def) {
199
207
  return def;
200
208
  }
201
209
  async function runCommand(cmd, opts) {
202
- if (typeof cmd.run === "function") {
203
- const cmdArgs = await resolveValue(cmd.args || {});
204
- const parsedArgs = parseArgs(opts.rawArgs, cmdArgs);
205
- await cmd.run({
206
- rawArgs: opts.rawArgs,
207
- args: parsedArgs,
208
- cmd
209
- });
210
+ const cmdArgs = await resolveValue(cmd.args || {});
211
+ const parsedArgs = parseArgs(opts.rawArgs, cmdArgs);
212
+ const context = {
213
+ rawArgs: opts.rawArgs,
214
+ args: parsedArgs,
215
+ cmd
216
+ };
217
+ if (typeof cmd.setup === "function") {
218
+ await cmd.setup(context);
210
219
  }
211
220
  const subCommands = await resolveValue(cmd.subCommands);
212
- if (subCommands && Object.keys(subCommands.length > 0)) {
221
+ if (subCommands && Object.keys(subCommands).length > 0) {
213
222
  const subCommandArgIndex = opts.rawArgs.findIndex(
214
223
  (arg) => !arg.startsWith("-")
215
224
  );
@@ -233,10 +242,13 @@ async function runCommand(cmd, opts) {
233
242
  });
234
243
  }
235
244
  }
245
+ if (typeof cmd.run === "function") {
246
+ await cmd.run(context);
247
+ }
236
248
  }
237
249
  async function resolveSubCommand(cmd, rawArgs, parent) {
238
250
  const subCommands = await resolveValue(cmd.subCommands);
239
- if (subCommands && Object.keys(subCommands.length > 0)) {
251
+ if (subCommands && Object.keys(subCommands).length > 0) {
240
252
  const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-"));
241
253
  const subCommandName = rawArgs[subCommandArgIndex];
242
254
  const subCommand = await resolveValue(subCommands[subCommandName]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "citty",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Elegant CLI Builder",
5
5
  "repository": "unjs/citty",
6
6
  "license": "MIT",
@@ -29,18 +29,21 @@
29
29
  "release": "pnpm test && changelogen --release --push && npm publish",
30
30
  "test": "pnpm lint && vitest run --coverage"
31
31
  },
32
+ "dependencies": {
33
+ "scule": "^1.0.0"
34
+ },
32
35
  "devDependencies": {
33
- "@types/node": "^18.15.3",
34
- "@vitest/coverage-c8": "^0.29.2",
35
- "changelogen": "^0.5.1",
36
+ "@types/node": "^18.15.10",
37
+ "@vitest/coverage-c8": "^0.29.8",
38
+ "changelogen": "^0.5.2",
36
39
  "colorette": "^2.0.19",
37
40
  "eslint": "^8.36.0",
38
41
  "eslint-config-unjs": "^0.1.0",
39
- "jiti": "^1.17.2",
40
- "prettier": "^2.8.4",
41
- "typescript": "^4.9.5",
42
+ "jiti": "^1.18.2",
43
+ "prettier": "^2.8.7",
44
+ "typescript": "^5.0.2",
42
45
  "unbuild": "^1.1.2",
43
- "vitest": "^0.29.2"
46
+ "vitest": "^0.29.8"
44
47
  },
45
- "packageManager": "pnpm@7.25.1"
46
- }
48
+ "packageManager": "pnpm@8.0.0"
49
+ }