clerc 0.1.1 → 0.3.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/dist/index.cjs CHANGED
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var liteEmit = require('lite-emit');
6
6
  var minimist = require('minimist');
7
+ var typeFlag = require('type-flag');
7
8
  var isPlatform = require('is-platform');
8
9
 
9
10
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -16,7 +17,7 @@ class CommandExistsError extends Error {
16
17
  }
17
18
  class CommonCommandExistsError extends Error {
18
19
  }
19
- class NoSuchCommandsError extends Error {
20
+ class NoSuchCommandError extends Error {
20
21
  }
21
22
 
22
23
  const mustArray = (a) => Array.isArray(a) ? a : [a];
@@ -103,8 +104,8 @@ class Clerc {
103
104
  if (name === SingleCommand && this.__hasCommands) {
104
105
  throw new CommonCommandExistsError("Common command exists");
105
106
  }
106
- const { alias, flags, parameters } = options;
107
- this._commands[name] = { name, description, alias, flags, parameters };
107
+ const { alias, flags } = options;
108
+ this._commands[name] = { name, description, alias, flags };
108
109
  return this;
109
110
  }
110
111
  on(name, handler) {
@@ -119,31 +120,26 @@ class Clerc {
119
120
  return this;
120
121
  }
121
122
  parse(argv = resolveArgv()) {
122
- let parsed = minimist__default["default"](argv);
123
+ const parsed = minimist__default["default"](argv);
123
124
  const name = String(parsed._[0]);
124
125
  const command = this.__isSingleCommand ? this._commands[SingleCommand] : resolveCommand(this._commands, name);
125
126
  const isCommandResolved = !!command;
126
- parsed = minimist__default["default"](argv, {
127
- alias: command ? resolveFlagAlias(command) : {},
128
- default: command ? resolveFlagDefault(command) : {}
129
- });
130
- const { _: args, ...flags } = parsed;
131
- const camelCaseFlags = Object.fromEntries(
132
- Object.entries(flags).map(([key, value]) => [camelCase(key), value])
133
- );
127
+ const parsedWithType = typeFlag.typeFlag((command == null ? void 0 : command.flags) || {}, argv);
128
+ const { _: args, flags } = parsedWithType;
134
129
  const parameters = this.__isSingleCommand || !isCommandResolved ? args : args.slice(1);
135
130
  const inspectorContext = {
136
131
  name: command == null ? void 0 : command.name,
137
132
  resolved: isCommandResolved,
138
- raw: parsed,
133
+ isSingleCommand: this.__isSingleCommand,
134
+ raw: parsedWithType,
139
135
  parameters,
140
- flags: camelCaseFlags,
136
+ flags,
141
137
  cli: this
142
138
  };
143
139
  const handlerContext = inspectorContext;
144
140
  const emitHandler = () => {
145
141
  if (!command) {
146
- throw new NoSuchCommandsError(`No such command: ${name}`);
142
+ throw new NoSuchCommandError(`No such command: ${name}`);
147
143
  }
148
144
  this.__commandEmitter.emit(command.name, handlerContext);
149
145
  };
@@ -154,17 +150,22 @@ class Clerc {
154
150
  }
155
151
 
156
152
  const definePlugin = (p) => p;
153
+ const defineHandler = (_cli, _key, handler) => handler;
154
+ const defineInspector = (_cli, inspector) => inspector;
157
155
 
158
156
  exports.Clerc = Clerc;
159
157
  exports.CommandExistsError = CommandExistsError;
160
158
  exports.CommonCommandExistsError = CommonCommandExistsError;
161
- exports.NoSuchCommandsError = NoSuchCommandsError;
159
+ exports.NoSuchCommandError = NoSuchCommandError;
162
160
  exports.SingleCommand = SingleCommand;
163
161
  exports.SingleCommandError = SingleCommandError;
164
162
  exports.camelCase = camelCase;
165
163
  exports.compose = compose;
164
+ exports.defineHandler = defineHandler;
165
+ exports.defineInspector = defineInspector;
166
166
  exports.definePlugin = definePlugin;
167
167
  exports.kebabCase = kebabCase;
168
+ exports.mustArray = mustArray;
168
169
  exports.resolveArgv = resolveArgv;
169
170
  exports.resolveCommand = resolveCommand;
170
171
  exports.resolveFlagAlias = resolveFlagAlias;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,79 @@
1
- interface Plugin<T extends Clerc = Clerc, U extends Clerc = Clerc> {
2
- setup: (cli: T) => U;
1
+ declare const DOUBLE_DASH = "--";
2
+ declare type TypeFunction<ReturnType = any> = (value: any) => ReturnType;
3
+ declare type TypeFunctionArray<ReturnType> = readonly [TypeFunction<ReturnType>];
4
+ declare type FlagType<ReturnType = any> = TypeFunction<ReturnType> | TypeFunctionArray<ReturnType>;
5
+ declare type FlagSchemaBase<TF> = {
6
+ /**
7
+ Type of the flag as a function that parses the argv string and returns the parsed value.
8
+
9
+ @example
10
+ ```
11
+ type: String
12
+ ```
13
+
14
+ @example Wrap in an array to accept multiple values.
15
+ ```
16
+ type: [Boolean]
17
+ ```
18
+
19
+ @example Custom function type that uses moment.js to parse string as date.
20
+ ```
21
+ type: function CustomDate(value: string) {
22
+ return moment(value).toDate();
23
+ }
24
+ ```
25
+ */
26
+ type: TF;
27
+ /**
28
+ A single-character alias for the flag.
29
+
30
+ @example
31
+ ```
32
+ alias: 's'
33
+ ```
34
+ */
35
+ alias?: string;
36
+ } & Record<PropertyKey, unknown>;
37
+ declare type FlagSchemaDefault<TF, DefaultType = any> = FlagSchemaBase<TF> & {
38
+ /**
39
+ Default value of the flag. Also accepts a function that returns the default value.
40
+ [Default: undefined]
41
+
42
+ @example
43
+ ```
44
+ default: 'hello'
45
+ ```
46
+
47
+ @example
48
+ ```
49
+ default: () => [1, 2, 3]
50
+ ```
51
+ */
52
+ default: DefaultType | (() => DefaultType);
53
+ };
54
+ declare type FlagSchema<TF = FlagType> = (FlagSchemaBase<TF> | FlagSchemaDefault<TF>);
55
+ declare type FlagTypeOrSchema<ExtraOptions = Record<string, unknown>> = FlagType | (FlagSchema & ExtraOptions);
56
+ declare type Flags<ExtraOptions = Record<string, unknown>> = Record<string, FlagTypeOrSchema<ExtraOptions>>;
57
+ declare type InferFlagType<Flag extends FlagTypeOrSchema> = (Flag extends (TypeFunctionArray<infer T> | FlagSchema<TypeFunctionArray<infer T>>) ? (Flag extends FlagSchemaDefault<TypeFunctionArray<T>, infer D> ? T[] | D : T[]) : (Flag extends TypeFunction<infer T> | FlagSchema<TypeFunction<infer T>> ? (Flag extends FlagSchemaDefault<TypeFunction<T>, infer D> ? T | D : T | undefined) : never));
58
+ interface ParsedFlags<Schemas = Record<string, unknown>> {
59
+ flags: Schemas;
60
+ unknownFlags: Record<string, (string | boolean)[]>;
61
+ _: string[] & {
62
+ [DOUBLE_DASH]: string[];
63
+ };
3
64
  }
4
- declare const definePlugin: <T extends Clerc<{}>, U extends Clerc<{}>>(p: Plugin<T, U>) => Plugin<T, U>;
65
+ declare type TypeFlag<Schemas extends Flags> = ParsedFlags<{
66
+ [flag in keyof Schemas]: InferFlagType<Schemas[flag]>;
67
+ }>;
5
68
 
69
+ /**
70
+ * Copied from type-fest
71
+ */
72
+ declare type Primitive = null | undefined | string | number | boolean | symbol | bigint;
73
+ /**
74
+ * Copied from type-fest
75
+ */
76
+ declare type LiteralUnion<LiteralType, BaseType extends Primitive> = LiteralType | (BaseType & Record<never, never>);
6
77
  declare type Dict<T> = Record<string, T>;
7
78
  declare type MustArray<T> = T extends any[] ? T : [T];
8
79
  declare type MaybeArray<T> = T | T[];
@@ -12,36 +83,21 @@ declare type GetLength<T extends any[]> = T extends {
12
83
  declare type GetTail<T extends any[]> = T extends [infer _Head, ...infer Tail] ? Tail : never;
13
84
  declare type EnhanceSingle<T, E extends Dict<any>> = T & E;
14
85
  declare type Enhance<T, E extends Dict<any> | Dict<any>[]> = GetLength<MustArray<E>> extends 0 ? T : Enhance<EnhanceSingle<T, MustArray<E>[0]>, GetTail<MustArray<E>>>;
15
- interface ParsedArgs {
16
- [arg: string]: any;
17
- "--"?: string[] | undefined;
18
- _: string[];
19
- }
20
- interface FlagOptions {
21
- description: string;
22
- alias?: MaybeArray<string>;
23
- default?: PossibleInputKind;
24
- required?: boolean;
25
- }
26
- interface Flag extends FlagOptions {
27
- name: string;
28
- }
29
- interface ParameterOptions {
86
+ declare type FlagOptions = FlagSchema & {
30
87
  description: string;
31
88
  required?: boolean;
32
- }
33
- interface Parameter extends ParameterOptions {
89
+ };
90
+ declare type Flag = FlagOptions & {
34
91
  name: string;
92
+ };
93
+ interface CommandOptions<A extends MaybeArray<string> = MaybeArray<string>, F extends Dict<FlagOptions> = Dict<FlagOptions>> {
94
+ alias?: A;
95
+ flags?: F;
35
96
  }
36
- interface CommandOptions {
37
- alias?: MaybeArray<string>;
38
- parameters?: Dict<ParameterOptions>;
39
- flags?: Dict<FlagOptions>;
40
- }
41
- interface Command<N extends string | SingleCommandType = string, D extends string = string> extends CommandOptions {
97
+ declare type Command<N extends string | SingleCommandType = string, D extends string = string, Options extends CommandOptions = CommandOptions> = Options & {
42
98
  name: N;
43
99
  description: D;
44
- }
100
+ };
45
101
  declare type CommandRecord = Dict<Command> & {
46
102
  [SingleCommand]?: Command;
47
103
  };
@@ -49,18 +105,24 @@ declare type MakeEventMap<T extends CommandRecord> = {
49
105
  [K in keyof T]: [InspectorContext];
50
106
  };
51
107
  declare type PossibleInputKind = string | number | boolean | Dict<any>;
108
+ declare type NonNullableFlag<T extends Dict<FlagOptions> | undefined> = T extends undefined ? {} : NonNullable<T>;
52
109
  interface HandlerContext<C extends CommandRecord = CommandRecord, N extends keyof C = keyof C> {
53
110
  name?: N;
54
111
  resolved: boolean;
55
- raw: ParsedArgs;
112
+ isSingleCommand: boolean;
113
+ raw: ParsedFlags;
56
114
  parameters: PossibleInputKind[];
57
- flags: Dict<MaybeArray<PossibleInputKind> | undefined>;
115
+ flags: TypeFlag<NonNullableFlag<C[N]["flags"]>>["flags"];
58
116
  cli: Clerc<C>;
59
117
  }
60
- declare type Handler = (ctx: HandlerContext) => void;
61
- interface InspectorContext<C extends CommandRecord = CommandRecord, N extends keyof C = keyof C> extends HandlerContext<C, N> {
62
- }
63
- declare type Inspector = (ctx: InspectorContext<any>, next: () => void) => void;
118
+ declare type Handler<C extends CommandRecord = CommandRecord, K extends keyof C = keyof C> = (ctx: HandlerContext<C, K>) => void;
119
+ declare type InspectorContext<C extends CommandRecord = CommandRecord> = HandlerContext<C> & {
120
+ flags: {} extends TypeFlag<NonNullableFlag<C[keyof C]["flags"]>>["flags"] ? Dict<any> : TypeFlag<NonNullableFlag<C[keyof C]["flags"]>>["flags"];
121
+ };
122
+ declare type Inspector<C extends CommandRecord = CommandRecord> = (ctx: InspectorContext<C>, next: () => void) => void;
123
+ interface Plugin<T extends Clerc = Clerc, U extends Clerc = Clerc> {
124
+ setup: (cli: T) => U;
125
+ }
64
126
 
65
127
  declare const SingleCommand: unique symbol;
66
128
  declare type SingleCommandType = typeof SingleCommand;
@@ -146,7 +208,7 @@ declare class Clerc<C extends CommandRecord = {}> {
146
208
  * })
147
209
  * ```
148
210
  */
149
- command<N extends string | SingleCommandType, D extends string>(name: N, description: D, options?: CommandOptions): this & Clerc<C & Record<N, Command<N, D>>>;
211
+ command<N extends string | SingleCommandType, D extends string, O extends CommandOptions>(name: N, description: D, options?: O): this & Clerc<C & Record<N, Command<N, D, O>>>;
150
212
  /**
151
213
  * Register a handler
152
214
  * @param name
@@ -161,7 +223,7 @@ declare class Clerc<C extends CommandRecord = {}> {
161
223
  * })
162
224
  * ```
163
225
  */
164
- on<K extends keyof C>(name: K, handler: Handler): this;
226
+ on<K extends keyof CM, CM extends this["_commands"] = this["_commands"]>(name: LiteralUnion<K, string>, handler: Handler<CM, K>): this;
165
227
  /**
166
228
  * Use a plugin
167
229
  * @param plugin
@@ -200,23 +262,28 @@ declare class Clerc<C extends CommandRecord = {}> {
200
262
  parse(argv?: string[]): void;
201
263
  }
202
264
 
265
+ declare const definePlugin: <T extends Clerc<{}>, U extends Clerc<{}>>(p: Plugin<T, U>) => Plugin<T, U>;
266
+ declare const defineHandler: <C extends Clerc<{}>, K extends keyof C["_commands"]>(_cli: C, _key: K, handler: Handler<C["_commands"], K>) => Handler<C["_commands"], K>;
267
+ declare const defineInspector: <C extends Clerc<{}>>(_cli: C, inspector: Inspector<C["_commands"]>) => Inspector<C["_commands"]>;
268
+
203
269
  declare class SingleCommandError extends Error {
204
270
  }
205
271
  declare class CommandExistsError extends Error {
206
272
  }
207
273
  declare class CommonCommandExistsError extends Error {
208
274
  }
209
- declare class NoSuchCommandsError extends Error {
275
+ declare class NoSuchCommandError extends Error {
210
276
  }
211
277
 
278
+ declare const mustArray: <T>(a: MaybeArray<T>) => T[];
212
279
  declare type CamelCase<T extends string> = T extends `${infer A}-${infer B}${infer C}` ? `${A}${Capitalize<B>}${CamelCase<C>}` : T;
213
280
  declare const camelCase: <T extends string>(s: T) => CamelCase<T>;
214
281
  declare type KebabCase<T extends string, A extends string = ""> = T extends `${infer F}${infer R}` ? KebabCase<R, `${A}${F extends Lowercase<F> ? "" : "-"}${Lowercase<F>}`> : A;
215
282
  declare const kebabCase: <T extends string>(s: T) => KebabCase<T, "">;
216
283
  declare const resolveFlagAlias: (_command: Command) => Dict<string[]>;
217
- declare const resolveFlagDefault: (_command: Command) => Dict<PossibleInputKind | undefined>;
284
+ declare const resolveFlagDefault: (_command: Command) => Dict<any>;
218
285
  declare function resolveCommand(commands: CommandRecord, name: string | SingleCommandType): Command | undefined;
219
286
  declare const resolveArgv: () => string[];
220
287
  declare function compose(inspectors: Inspector[]): (ctx: InspectorContext) => void;
221
288
 
222
- export { CamelCase, Clerc, Command, CommandExistsError, CommandOptions, CommandRecord, CommonCommandExistsError, Dict, Enhance, Flag, FlagOptions, Handler, HandlerContext, Inspector, InspectorContext, KebabCase, MakeEventMap, MaybeArray, NoSuchCommandsError, Parameter, ParameterOptions, Plugin, PossibleInputKind, SingleCommand, SingleCommandError, SingleCommandType, camelCase, compose, definePlugin, kebabCase, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault };
289
+ export { CamelCase, Clerc, Command, CommandExistsError, CommandOptions, CommandRecord, CommonCommandExistsError, Dict, Enhance, Flag, FlagOptions, Handler, HandlerContext, Inspector, InspectorContext, KebabCase, LiteralUnion, MakeEventMap, MaybeArray, NoSuchCommandError, Plugin, PossibleInputKind, Primitive, SingleCommand, SingleCommandError, SingleCommandType, camelCase, compose, defineHandler, defineInspector, definePlugin, kebabCase, mustArray, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault };
package/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { LiteEmit } from 'lite-emit';
2
2
  import minimist from 'minimist';
3
+ import { typeFlag } from 'type-flag';
3
4
  import { isNode, isDeno } from 'is-platform';
4
5
 
5
6
  class SingleCommandError extends Error {
@@ -8,7 +9,7 @@ class CommandExistsError extends Error {
8
9
  }
9
10
  class CommonCommandExistsError extends Error {
10
11
  }
11
- class NoSuchCommandsError extends Error {
12
+ class NoSuchCommandError extends Error {
12
13
  }
13
14
 
14
15
  const mustArray = (a) => Array.isArray(a) ? a : [a];
@@ -95,8 +96,8 @@ class Clerc {
95
96
  if (name === SingleCommand && this.__hasCommands) {
96
97
  throw new CommonCommandExistsError("Common command exists");
97
98
  }
98
- const { alias, flags, parameters } = options;
99
- this._commands[name] = { name, description, alias, flags, parameters };
99
+ const { alias, flags } = options;
100
+ this._commands[name] = { name, description, alias, flags };
100
101
  return this;
101
102
  }
102
103
  on(name, handler) {
@@ -111,31 +112,26 @@ class Clerc {
111
112
  return this;
112
113
  }
113
114
  parse(argv = resolveArgv()) {
114
- let parsed = minimist(argv);
115
+ const parsed = minimist(argv);
115
116
  const name = String(parsed._[0]);
116
117
  const command = this.__isSingleCommand ? this._commands[SingleCommand] : resolveCommand(this._commands, name);
117
118
  const isCommandResolved = !!command;
118
- parsed = minimist(argv, {
119
- alias: command ? resolveFlagAlias(command) : {},
120
- default: command ? resolveFlagDefault(command) : {}
121
- });
122
- const { _: args, ...flags } = parsed;
123
- const camelCaseFlags = Object.fromEntries(
124
- Object.entries(flags).map(([key, value]) => [camelCase(key), value])
125
- );
119
+ const parsedWithType = typeFlag((command == null ? void 0 : command.flags) || {}, argv);
120
+ const { _: args, flags } = parsedWithType;
126
121
  const parameters = this.__isSingleCommand || !isCommandResolved ? args : args.slice(1);
127
122
  const inspectorContext = {
128
123
  name: command == null ? void 0 : command.name,
129
124
  resolved: isCommandResolved,
130
- raw: parsed,
125
+ isSingleCommand: this.__isSingleCommand,
126
+ raw: parsedWithType,
131
127
  parameters,
132
- flags: camelCaseFlags,
128
+ flags,
133
129
  cli: this
134
130
  };
135
131
  const handlerContext = inspectorContext;
136
132
  const emitHandler = () => {
137
133
  if (!command) {
138
- throw new NoSuchCommandsError(`No such command: ${name}`);
134
+ throw new NoSuchCommandError(`No such command: ${name}`);
139
135
  }
140
136
  this.__commandEmitter.emit(command.name, handlerContext);
141
137
  };
@@ -146,5 +142,7 @@ class Clerc {
146
142
  }
147
143
 
148
144
  const definePlugin = (p) => p;
145
+ const defineHandler = (_cli, _key, handler) => handler;
146
+ const defineInspector = (_cli, inspector) => inspector;
149
147
 
150
- export { Clerc, CommandExistsError, CommonCommandExistsError, NoSuchCommandsError, SingleCommand, SingleCommandError, camelCase, compose, definePlugin, kebabCase, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault };
148
+ export { Clerc, CommandExistsError, CommonCommandExistsError, NoSuchCommandError, SingleCommand, SingleCommandError, camelCase, compose, defineHandler, defineInspector, definePlugin, kebabCase, mustArray, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clerc",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "author": "Ray <nn_201312@163.com> (https://github.com/so1ve)",
5
5
  "description": "Clerc is a simple and easy-to-use cli framework.",
6
6
  "keywords": [
@@ -41,10 +41,8 @@
41
41
  "dependencies": {
42
42
  "is-platform": "^0.2.0",
43
43
  "lite-emit": "^1.4.0",
44
- "minimist": "^1.2.7"
45
- },
46
- "devDependencies": {
47
- "@types/minimist": "^1.2.2"
44
+ "mri": "^1.2.0",
45
+ "type-flag": "^3.0.0"
48
46
  },
49
47
  "scripts": {
50
48
  "build": "puild",