clerc 0.3.4 → 0.5.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
@@ -5,20 +5,39 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var liteEmit = require('lite-emit');
6
6
  var mri = require('mri');
7
7
  var typeFlag = require('type-flag');
8
- var isPlatform = require('is-platform');
9
8
  var utils = require('@clerc/utils');
9
+ var isPlatform = require('is-platform');
10
10
 
11
11
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
12
 
13
13
  var mri__default = /*#__PURE__*/_interopDefaultLegacy(mri);
14
14
 
15
15
  class SingleCommandError extends Error {
16
+ constructor() {
17
+ super("Single command mode enabled.");
18
+ }
16
19
  }
17
20
  class CommandExistsError extends Error {
18
21
  }
19
22
  class CommonCommandExistsError extends Error {
23
+ constructor() {
24
+ super("Common command exists.");
25
+ }
20
26
  }
21
27
  class NoSuchCommandError extends Error {
28
+ constructor(name) {
29
+ super(`No such command: ${name}`);
30
+ }
31
+ }
32
+ class ParentCommandExistsError extends Error {
33
+ constructor(name) {
34
+ super(`Command "${name}" cannot exist with its parent`);
35
+ }
36
+ }
37
+ class SubcommandExistsError extends Error {
38
+ constructor(name) {
39
+ super(`Command "${name}" cannot exist with its subcommand`);
40
+ }
22
41
  }
23
42
 
24
43
  const resolveFlagAlias = (_command) => Object.entries((_command == null ? void 0 : _command.flags) || {}).reduce((acc, [name, command]) => {
@@ -39,114 +58,185 @@ function resolveCommand(commands, name) {
39
58
  if (name === SingleCommand) {
40
59
  return commands[SingleCommand];
41
60
  }
61
+ const nameArr = Array.isArray(name) ? name : name.split(" ");
62
+ const nameString = nameArr.join(" ");
42
63
  const possibleCommands = Object.values(commands).filter(
43
- (c) => c.name === name || utils.mustArray(c.alias || []).map(String).includes(name)
64
+ (c) => utils.arrayStartsWith(nameArr, c.name.split(" ")) || utils.mustArray(c.alias || []).map(String).includes(nameString)
44
65
  );
45
66
  if (possibleCommands.length > 1) {
46
- throw new Error(`Multiple commands found with name "${name}"`);
67
+ throw new Error(`Multiple commands found with name "${nameString}"`);
47
68
  }
48
69
  return possibleCommands[0];
49
70
  }
71
+ function resolveSubcommandsByParent(commands, parent, depth = Infinity) {
72
+ const parentArr = parent === "" ? [] : Array.isArray(parent) ? parent : parent.split(" ");
73
+ return Object.values(commands).filter((c) => {
74
+ const commandNameArr = c.name.split(" ");
75
+ return utils.arrayStartsWith(commandNameArr, parentArr) && commandNameArr.length - parentArr.length <= depth;
76
+ });
77
+ }
78
+ const resolveRootCommands = (commands) => resolveSubcommandsByParent(commands, "", 1);
50
79
  const resolveArgv = () => isPlatform.isNode() ? process.argv.slice(2) : isPlatform.isDeno() ? Deno.args : [];
51
80
  function compose(inspectors) {
52
- return (ctx) => {
81
+ return (getCtx) => {
53
82
  return dispatch(0);
54
83
  function dispatch(i) {
55
84
  const inspector = inspectors[i];
56
- return inspector(ctx, dispatch.bind(null, i + 1));
85
+ return inspector(getCtx(), dispatch.bind(null, i + 1));
57
86
  }
58
87
  };
59
88
  }
60
89
 
90
+ var __accessCheck = (obj, member, msg) => {
91
+ if (!member.has(obj))
92
+ throw TypeError("Cannot " + msg);
93
+ };
94
+ var __privateGet = (obj, member, getter) => {
95
+ __accessCheck(obj, member, "read from private field");
96
+ return getter ? getter.call(obj) : member.get(obj);
97
+ };
98
+ var __privateAdd = (obj, member, value) => {
99
+ if (member.has(obj))
100
+ throw TypeError("Cannot add the same private member more than once");
101
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
102
+ };
103
+ var __privateSet = (obj, member, value, setter) => {
104
+ __accessCheck(obj, member, "write to private field");
105
+ setter ? setter.call(obj, value) : member.set(obj, value);
106
+ return value;
107
+ };
108
+ var _name, _description, _version, _inspectors, _commands, _commandEmitter, _isSingleCommand, isSingleCommand_get, _hasCommands, hasCommands_get;
61
109
  const SingleCommand = Symbol("SingleCommand");
62
- class Clerc {
110
+ const _Clerc = class {
63
111
  constructor() {
64
- this._name = "";
65
- this._description = "";
66
- this._version = "";
67
- this._inspectors = [];
68
- this._commands = {};
69
- this.__commandEmitter = new liteEmit.LiteEmit();
112
+ __privateAdd(this, _isSingleCommand);
113
+ __privateAdd(this, _hasCommands);
114
+ __privateAdd(this, _name, "");
115
+ __privateAdd(this, _description, "");
116
+ __privateAdd(this, _version, "");
117
+ __privateAdd(this, _inspectors, []);
118
+ __privateAdd(this, _commands, {});
119
+ __privateAdd(this, _commandEmitter, new liteEmit.LiteEmit());
120
+ }
121
+ get _name() {
122
+ return __privateGet(this, _name);
123
+ }
124
+ get _description() {
125
+ return __privateGet(this, _description);
126
+ }
127
+ get _version() {
128
+ return __privateGet(this, _version);
70
129
  }
71
- get __isSingleCommand() {
72
- return this._commands[SingleCommand] !== void 0;
130
+ get _inspectors() {
131
+ return __privateGet(this, _inspectors);
73
132
  }
74
- get __hasCommands() {
75
- return Object.keys(this._commands).length > 0;
133
+ get _commands() {
134
+ return __privateGet(this, _commands);
76
135
  }
77
136
  static create() {
78
- return new Clerc();
137
+ return new _Clerc();
79
138
  }
80
139
  name(name) {
81
- this._name = name;
140
+ __privateSet(this, _name, name);
82
141
  return this;
83
142
  }
84
143
  description(description) {
85
- this._description = description;
144
+ __privateSet(this, _description, description);
86
145
  return this;
87
146
  }
88
147
  version(version) {
89
- this._version = version;
148
+ __privateSet(this, _version, version);
90
149
  return this;
91
150
  }
92
151
  command(name, description, options = {}) {
93
- if (this._commands[name]) {
152
+ if (__privateGet(this, _commands)[name]) {
94
153
  if (name === SingleCommand) {
95
154
  throw new CommandExistsError("Single command already exists");
96
155
  }
97
156
  throw new CommandExistsError(`Command "${name === SingleCommand ? "[SingleCommand]" : name}" already exists`);
98
157
  }
99
- if (this.__isSingleCommand) {
100
- throw new SingleCommandError("Single command mode enabled");
158
+ if (__privateGet(this, _isSingleCommand, isSingleCommand_get)) {
159
+ throw new SingleCommandError();
101
160
  }
102
- if (name === SingleCommand && this.__hasCommands) {
103
- throw new CommonCommandExistsError("Common command exists");
161
+ if (name === SingleCommand && __privateGet(this, _hasCommands, hasCommands_get)) {
162
+ throw new CommonCommandExistsError();
104
163
  }
105
- const { alias, flags } = options;
106
- this._commands[name] = { name, description, alias, flags };
164
+ if (name !== SingleCommand) {
165
+ const splitedName = name.split(" ");
166
+ const existedCommandNames = Object.keys(__privateGet(this, _commands)).filter((name2) => typeof name2 === "string").map((name2) => name2.split(" "));
167
+ if (existedCommandNames.some((name2) => utils.arrayStartsWith(splitedName, name2))) {
168
+ throw new ParentCommandExistsError(splitedName.join(" "));
169
+ }
170
+ if (existedCommandNames.some((name2) => utils.arrayStartsWith(name2, splitedName))) {
171
+ throw new SubcommandExistsError(splitedName.join(" "));
172
+ }
173
+ }
174
+ __privateGet(this, _commands)[name] = { name, description, ...options };
107
175
  return this;
108
176
  }
109
177
  on(name, handler) {
110
- this.__commandEmitter.on(name, handler);
178
+ __privateGet(this, _commandEmitter).on(name, handler);
111
179
  return this;
112
180
  }
113
181
  use(plugin) {
114
182
  return plugin.setup(this);
115
183
  }
116
184
  inspector(inspector) {
117
- this._inspectors.push(inspector);
185
+ __privateGet(this, _inspectors).push(inspector);
118
186
  return this;
119
187
  }
120
188
  parse(argv = resolveArgv()) {
121
189
  const parsed = mri__default["default"](argv);
122
- const name = String(parsed._[0]);
123
- const command = this.__isSingleCommand ? this._commands[SingleCommand] : resolveCommand(this._commands, name);
124
- const isCommandResolved = !!command;
125
- const parsedWithType = typeFlag.typeFlag((command == null ? void 0 : command.flags) || {}, argv);
126
- const { _: args, flags } = parsedWithType;
127
- const parameters = this.__isSingleCommand || !isCommandResolved ? args : args.slice(1);
128
- const inspectorContext = {
129
- name: command == null ? void 0 : command.name,
130
- resolved: isCommandResolved,
131
- isSingleCommand: this.__isSingleCommand,
132
- raw: parsedWithType,
133
- parameters,
134
- flags,
135
- unknownFlags: parsedWithType.unknownFlags,
136
- cli: this
190
+ const name = parsed._.map(String);
191
+ const stringName = name.join(" ");
192
+ const getCommand = () => __privateGet(this, _isSingleCommand, isSingleCommand_get) ? __privateGet(this, _commands)[SingleCommand] : resolveCommand(__privateGet(this, _commands), name);
193
+ const getContext = () => {
194
+ const command = getCommand();
195
+ const isCommandResolved = !!command;
196
+ const parsedWithType = typeFlag.typeFlag((command == null ? void 0 : command.flags) || {}, [...argv]);
197
+ const { _: args, flags } = parsedWithType;
198
+ const parameters = __privateGet(this, _isSingleCommand, isSingleCommand_get) || !isCommandResolved ? args : args.slice(command.name.split(" ").length);
199
+ const context = {
200
+ name: command == null ? void 0 : command.name,
201
+ resolved: isCommandResolved,
202
+ isSingleCommand: __privateGet(this, _isSingleCommand, isSingleCommand_get),
203
+ raw: parsedWithType,
204
+ parameters,
205
+ flags,
206
+ unknownFlags: parsedWithType.unknownFlags,
207
+ cli: this
208
+ };
209
+ return context;
137
210
  };
138
- const handlerContext = inspectorContext;
139
211
  const emitHandler = () => {
212
+ const command = getCommand();
213
+ const handlerContext = getContext();
140
214
  if (!command) {
141
- throw new NoSuchCommandError(`No such command: ${name}`);
215
+ throw new NoSuchCommandError(stringName);
142
216
  }
143
- this.__commandEmitter.emit(command.name, handlerContext);
217
+ __privateGet(this, _commandEmitter).emit(command.name, handlerContext);
144
218
  };
145
- const inspectors = [...this._inspectors, emitHandler];
219
+ const inspectors = [...__privateGet(this, _inspectors), emitHandler];
146
220
  const inspector = compose(inspectors);
147
- inspector(inspectorContext);
221
+ inspector(getContext);
222
+ return this;
148
223
  }
149
- }
224
+ };
225
+ let Clerc = _Clerc;
226
+ _name = new WeakMap();
227
+ _description = new WeakMap();
228
+ _version = new WeakMap();
229
+ _inspectors = new WeakMap();
230
+ _commands = new WeakMap();
231
+ _commandEmitter = new WeakMap();
232
+ _isSingleCommand = new WeakSet();
233
+ isSingleCommand_get = function() {
234
+ return __privateGet(this, _commands)[SingleCommand] !== void 0;
235
+ };
236
+ _hasCommands = new WeakSet();
237
+ hasCommands_get = function() {
238
+ return Object.keys(__privateGet(this, _commands)).length > 0;
239
+ };
150
240
 
151
241
  const definePlugin = (p) => p;
152
242
  const defineHandler = (_cli, _key, handler) => handler;
@@ -156,8 +246,10 @@ exports.Clerc = Clerc;
156
246
  exports.CommandExistsError = CommandExistsError;
157
247
  exports.CommonCommandExistsError = CommonCommandExistsError;
158
248
  exports.NoSuchCommandError = NoSuchCommandError;
249
+ exports.ParentCommandExistsError = ParentCommandExistsError;
159
250
  exports.SingleCommand = SingleCommand;
160
251
  exports.SingleCommandError = SingleCommandError;
252
+ exports.SubcommandExistsError = SubcommandExistsError;
161
253
  exports.compose = compose;
162
254
  exports.defineHandler = defineHandler;
163
255
  exports.defineInspector = defineInspector;
@@ -166,3 +258,5 @@ exports.resolveArgv = resolveArgv;
166
258
  exports.resolveCommand = resolveCommand;
167
259
  exports.resolveFlagAlias = resolveFlagAlias;
168
260
  exports.resolveFlagDefault = resolveFlagDefault;
261
+ exports.resolveRootCommands = resolveRootCommands;
262
+ exports.resolveSubcommandsByParent = resolveSubcommandsByParent;
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
+ import * as _clerc_utils from '@clerc/utils';
1
2
  import { MaybeArray, Dict, LiteralUnion } from '@clerc/utils';
2
3
 
3
4
  declare const DOUBLE_DASH = "--";
4
- declare type TypeFunction<ReturnType = any> = (value: any) => ReturnType;
5
- declare type TypeFunctionArray<ReturnType> = readonly [TypeFunction<ReturnType>];
6
- declare type FlagType<ReturnType = any> = TypeFunction<ReturnType> | TypeFunctionArray<ReturnType>;
7
- declare type FlagSchemaBase<TF> = {
5
+ type TypeFunction<ReturnType = any> = (value: any) => ReturnType;
6
+ type TypeFunctionArray<ReturnType> = readonly [TypeFunction<ReturnType>];
7
+ type FlagType<ReturnType = any> = TypeFunction<ReturnType> | TypeFunctionArray<ReturnType>;
8
+ type FlagSchemaBase<TF> = {
8
9
  /**
9
10
  Type of the flag as a function that parses the argv string and returns the parsed value.
10
11
 
@@ -36,7 +37,7 @@ declare type FlagSchemaBase<TF> = {
36
37
  */
37
38
  alias?: string;
38
39
  } & Record<PropertyKey, unknown>;
39
- declare type FlagSchemaDefault<TF, DefaultType = any> = FlagSchemaBase<TF> & {
40
+ type FlagSchemaDefault<TF, DefaultType = any> = FlagSchemaBase<TF> & {
40
41
  /**
41
42
  Default value of the flag. Also accepts a function that returns the default value.
42
43
  [Default: undefined]
@@ -53,10 +54,10 @@ declare type FlagSchemaDefault<TF, DefaultType = any> = FlagSchemaBase<TF> & {
53
54
  */
54
55
  default: DefaultType | (() => DefaultType);
55
56
  };
56
- declare type FlagSchema<TF = FlagType> = (FlagSchemaBase<TF> | FlagSchemaDefault<TF>);
57
- declare type FlagTypeOrSchema<ExtraOptions = Record<string, unknown>> = FlagType | (FlagSchema & ExtraOptions);
58
- declare type Flags<ExtraOptions = Record<string, unknown>> = Record<string, FlagTypeOrSchema<ExtraOptions>>;
59
- 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));
57
+ type FlagSchema<TF = FlagType> = (FlagSchemaBase<TF> | FlagSchemaDefault<TF>);
58
+ type FlagTypeOrSchema<ExtraOptions = Record<string, unknown>> = FlagType | (FlagSchema & ExtraOptions);
59
+ type Flags<ExtraOptions = Record<string, unknown>> = Record<string, FlagTypeOrSchema<ExtraOptions>>;
60
+ 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));
60
61
  interface ParsedFlags<Schemas = Record<string, unknown>> {
61
62
  flags: Schemas;
62
63
  unknownFlags: Record<string, (string | boolean)[]>;
@@ -64,33 +65,35 @@ interface ParsedFlags<Schemas = Record<string, unknown>> {
64
65
  [DOUBLE_DASH]: string[];
65
66
  };
66
67
  }
67
- declare type TypeFlag<Schemas extends Flags> = ParsedFlags<{
68
+ type TypeFlag<Schemas extends Flags> = ParsedFlags<{
68
69
  [flag in keyof Schemas]: InferFlagType<Schemas[flag]>;
69
70
  }>;
70
71
 
71
- declare type FlagOptions = FlagSchema & {
72
+ type FlagOptions = FlagSchema & {
72
73
  description: string;
73
74
  required?: boolean;
74
75
  };
75
- declare type Flag = FlagOptions & {
76
+ type Flag = FlagOptions & {
76
77
  name: string;
77
78
  };
78
79
  interface CommandOptions<A extends MaybeArray<string> = MaybeArray<string>, F extends Dict<FlagOptions> = Dict<FlagOptions>> {
79
80
  alias?: A;
80
81
  flags?: F;
82
+ examples?: [string, string][];
83
+ notes?: string[];
81
84
  }
82
- declare type Command<N extends string | SingleCommandType = string, D extends string = string, Options extends CommandOptions = CommandOptions> = Options & {
85
+ type Command<N extends string | SingleCommandType = string, D extends string = string, Options extends CommandOptions = CommandOptions> = Options & {
83
86
  name: N;
84
87
  description: D;
85
88
  };
86
- declare type CommandRecord = Dict<Command> & {
89
+ type CommandRecord = Dict<Command> & {
87
90
  [SingleCommand]?: Command;
88
91
  };
89
- declare type MakeEventMap<T extends CommandRecord> = {
92
+ type MakeEventMap<T extends CommandRecord> = {
90
93
  [K in keyof T]: [InspectorContext];
91
94
  };
92
- declare type PossibleInputKind = string | number | boolean | Dict<any>;
93
- declare type NonNullableFlag<T extends Dict<FlagOptions> | undefined> = T extends undefined ? {} : NonNullable<T>;
95
+ type PossibleInputKind = string | number | boolean | Dict<any>;
96
+ type NonNullableFlag<T extends Dict<FlagOptions> | undefined> = T extends undefined ? {} : NonNullable<T>;
94
97
  interface HandlerContext<C extends CommandRecord = CommandRecord, N extends keyof C = keyof C> {
95
98
  name?: N;
96
99
  resolved: boolean;
@@ -101,28 +104,26 @@ interface HandlerContext<C extends CommandRecord = CommandRecord, N extends keyo
101
104
  flags: TypeFlag<NonNullableFlag<C[N]["flags"]>>["flags"];
102
105
  cli: Clerc<C>;
103
106
  }
104
- declare type Handler<C extends CommandRecord = CommandRecord, K extends keyof C = keyof C> = (ctx: HandlerContext<C, K>) => void;
105
- declare type FallbackType<T, U> = {} extends T ? U : T;
106
- declare type InspectorContext<C extends CommandRecord = CommandRecord> = HandlerContext<C> & {
107
+ type Handler<C extends CommandRecord = CommandRecord, K extends keyof C = keyof C> = (ctx: HandlerContext<C, K>) => void;
108
+ type FallbackType<T, U> = {} extends T ? U : T;
109
+ type InspectorContext<C extends CommandRecord = CommandRecord> = HandlerContext<C> & {
107
110
  flags: FallbackType<TypeFlag<NonNullableFlag<C[keyof C]["flags"]>>["flags"], Dict<any>>;
108
111
  };
109
- declare type Inspector<C extends CommandRecord = CommandRecord> = (ctx: InspectorContext<C>, next: () => void) => void;
112
+ type Inspector<C extends CommandRecord = CommandRecord> = (ctx: InspectorContext<C>, next: () => void) => void;
110
113
  interface Plugin<T extends Clerc = Clerc, U extends Clerc = Clerc> {
111
114
  setup: (cli: T) => U;
112
115
  }
113
116
 
114
117
  declare const SingleCommand: unique symbol;
115
- declare type SingleCommandType = typeof SingleCommand;
118
+ type SingleCommandType = typeof SingleCommand;
116
119
  declare class Clerc<C extends CommandRecord = {}> {
117
- _name: string;
118
- _description: string;
119
- _version: string;
120
- _inspectors: Inspector[];
121
- _commands: C;
122
- private __commandEmitter;
120
+ #private;
123
121
  private constructor();
124
- private get __isSingleCommand();
125
- private get __hasCommands();
122
+ get _name(): string;
123
+ get _description(): string;
124
+ get _version(): string;
125
+ get _inspectors(): Inspector<CommandRecord>[];
126
+ get _commands(): C;
126
127
  /**
127
128
  * Create a new cli
128
129
  * @returns
@@ -246,7 +247,7 @@ declare class Clerc<C extends CommandRecord = {}> {
246
247
  * .parse(process.argv.slice(2)) // Optional
247
248
  * ```
248
249
  */
249
- parse(argv?: string[]): void;
250
+ parse(argv?: string[]): this;
250
251
  }
251
252
 
252
253
  declare const definePlugin: <T extends Clerc<{}>, U extends Clerc<{}>>(p: Plugin<T, U>) => Plugin<T, U>;
@@ -254,18 +255,29 @@ declare const defineHandler: <C extends Clerc<{}>, K extends keyof C["_commands"
254
255
  declare const defineInspector: <C extends Clerc<{}>>(_cli: C, inspector: Inspector<C["_commands"]>) => Inspector<C["_commands"]>;
255
256
 
256
257
  declare class SingleCommandError extends Error {
258
+ constructor();
257
259
  }
258
260
  declare class CommandExistsError extends Error {
259
261
  }
260
262
  declare class CommonCommandExistsError extends Error {
263
+ constructor();
261
264
  }
262
265
  declare class NoSuchCommandError extends Error {
266
+ constructor(name: string);
267
+ }
268
+ declare class ParentCommandExistsError extends Error {
269
+ constructor(name: string);
270
+ }
271
+ declare class SubcommandExistsError extends Error {
272
+ constructor(name: string);
263
273
  }
264
274
 
265
275
  declare const resolveFlagAlias: (_command: Command) => Dict<string[]>;
266
276
  declare const resolveFlagDefault: (_command: Command) => Dict<any>;
267
- declare function resolveCommand(commands: CommandRecord, name: string | SingleCommandType): Command | undefined;
277
+ declare function resolveCommand(commands: CommandRecord, name: string | string[] | SingleCommandType): Command | undefined;
278
+ declare function resolveSubcommandsByParent(commands: CommandRecord, parent: string | string[], depth?: number): Command<string, string, CommandOptions<_clerc_utils.MaybeArray<string>, Dict<FlagOptions>>>[];
279
+ declare const resolveRootCommands: (commands: CommandRecord) => Command<string, string, CommandOptions<_clerc_utils.MaybeArray<string>, Dict<FlagOptions>>>[];
268
280
  declare const resolveArgv: () => string[];
269
- declare function compose(inspectors: Inspector[]): (ctx: InspectorContext) => void;
281
+ declare function compose(inspectors: Inspector[]): (getCtx: () => InspectorContext) => void;
270
282
 
271
- export { Clerc, Command, CommandExistsError, CommandOptions, CommandRecord, CommonCommandExistsError, FallbackType, Flag, FlagOptions, Handler, HandlerContext, Inspector, InspectorContext, MakeEventMap, NoSuchCommandError, Plugin, PossibleInputKind, SingleCommand, SingleCommandError, SingleCommandType, compose, defineHandler, defineInspector, definePlugin, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault };
283
+ export { Clerc, Command, CommandExistsError, CommandOptions, CommandRecord, CommonCommandExistsError, FallbackType, Flag, FlagOptions, Handler, HandlerContext, Inspector, InspectorContext, MakeEventMap, NoSuchCommandError, ParentCommandExistsError, Plugin, PossibleInputKind, SingleCommand, SingleCommandError, SingleCommandType, SubcommandExistsError, compose, defineHandler, defineInspector, definePlugin, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault, resolveRootCommands, resolveSubcommandsByParent };
package/dist/index.mjs CHANGED
@@ -1,16 +1,35 @@
1
1
  import { LiteEmit } from 'lite-emit';
2
2
  import mri from 'mri';
3
3
  import { typeFlag } from 'type-flag';
4
+ import { mustArray, kebabCase, arrayStartsWith } from '@clerc/utils';
4
5
  import { isNode, isDeno } from 'is-platform';
5
- import { mustArray, kebabCase } from '@clerc/utils';
6
6
 
7
7
  class SingleCommandError extends Error {
8
+ constructor() {
9
+ super("Single command mode enabled.");
10
+ }
8
11
  }
9
12
  class CommandExistsError extends Error {
10
13
  }
11
14
  class CommonCommandExistsError extends Error {
15
+ constructor() {
16
+ super("Common command exists.");
17
+ }
12
18
  }
13
19
  class NoSuchCommandError extends Error {
20
+ constructor(name) {
21
+ super(`No such command: ${name}`);
22
+ }
23
+ }
24
+ class ParentCommandExistsError extends Error {
25
+ constructor(name) {
26
+ super(`Command "${name}" cannot exist with its parent`);
27
+ }
28
+ }
29
+ class SubcommandExistsError extends Error {
30
+ constructor(name) {
31
+ super(`Command "${name}" cannot exist with its subcommand`);
32
+ }
14
33
  }
15
34
 
16
35
  const resolveFlagAlias = (_command) => Object.entries((_command == null ? void 0 : _command.flags) || {}).reduce((acc, [name, command]) => {
@@ -31,117 +50,188 @@ function resolveCommand(commands, name) {
31
50
  if (name === SingleCommand) {
32
51
  return commands[SingleCommand];
33
52
  }
53
+ const nameArr = Array.isArray(name) ? name : name.split(" ");
54
+ const nameString = nameArr.join(" ");
34
55
  const possibleCommands = Object.values(commands).filter(
35
- (c) => c.name === name || mustArray(c.alias || []).map(String).includes(name)
56
+ (c) => arrayStartsWith(nameArr, c.name.split(" ")) || mustArray(c.alias || []).map(String).includes(nameString)
36
57
  );
37
58
  if (possibleCommands.length > 1) {
38
- throw new Error(`Multiple commands found with name "${name}"`);
59
+ throw new Error(`Multiple commands found with name "${nameString}"`);
39
60
  }
40
61
  return possibleCommands[0];
41
62
  }
63
+ function resolveSubcommandsByParent(commands, parent, depth = Infinity) {
64
+ const parentArr = parent === "" ? [] : Array.isArray(parent) ? parent : parent.split(" ");
65
+ return Object.values(commands).filter((c) => {
66
+ const commandNameArr = c.name.split(" ");
67
+ return arrayStartsWith(commandNameArr, parentArr) && commandNameArr.length - parentArr.length <= depth;
68
+ });
69
+ }
70
+ const resolveRootCommands = (commands) => resolveSubcommandsByParent(commands, "", 1);
42
71
  const resolveArgv = () => isNode() ? process.argv.slice(2) : isDeno() ? Deno.args : [];
43
72
  function compose(inspectors) {
44
- return (ctx) => {
73
+ return (getCtx) => {
45
74
  return dispatch(0);
46
75
  function dispatch(i) {
47
76
  const inspector = inspectors[i];
48
- return inspector(ctx, dispatch.bind(null, i + 1));
77
+ return inspector(getCtx(), dispatch.bind(null, i + 1));
49
78
  }
50
79
  };
51
80
  }
52
81
 
82
+ var __accessCheck = (obj, member, msg) => {
83
+ if (!member.has(obj))
84
+ throw TypeError("Cannot " + msg);
85
+ };
86
+ var __privateGet = (obj, member, getter) => {
87
+ __accessCheck(obj, member, "read from private field");
88
+ return getter ? getter.call(obj) : member.get(obj);
89
+ };
90
+ var __privateAdd = (obj, member, value) => {
91
+ if (member.has(obj))
92
+ throw TypeError("Cannot add the same private member more than once");
93
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
94
+ };
95
+ var __privateSet = (obj, member, value, setter) => {
96
+ __accessCheck(obj, member, "write to private field");
97
+ setter ? setter.call(obj, value) : member.set(obj, value);
98
+ return value;
99
+ };
100
+ var _name, _description, _version, _inspectors, _commands, _commandEmitter, _isSingleCommand, isSingleCommand_get, _hasCommands, hasCommands_get;
53
101
  const SingleCommand = Symbol("SingleCommand");
54
- class Clerc {
102
+ const _Clerc = class {
55
103
  constructor() {
56
- this._name = "";
57
- this._description = "";
58
- this._version = "";
59
- this._inspectors = [];
60
- this._commands = {};
61
- this.__commandEmitter = new LiteEmit();
104
+ __privateAdd(this, _isSingleCommand);
105
+ __privateAdd(this, _hasCommands);
106
+ __privateAdd(this, _name, "");
107
+ __privateAdd(this, _description, "");
108
+ __privateAdd(this, _version, "");
109
+ __privateAdd(this, _inspectors, []);
110
+ __privateAdd(this, _commands, {});
111
+ __privateAdd(this, _commandEmitter, new LiteEmit());
112
+ }
113
+ get _name() {
114
+ return __privateGet(this, _name);
115
+ }
116
+ get _description() {
117
+ return __privateGet(this, _description);
62
118
  }
63
- get __isSingleCommand() {
64
- return this._commands[SingleCommand] !== void 0;
119
+ get _version() {
120
+ return __privateGet(this, _version);
65
121
  }
66
- get __hasCommands() {
67
- return Object.keys(this._commands).length > 0;
122
+ get _inspectors() {
123
+ return __privateGet(this, _inspectors);
124
+ }
125
+ get _commands() {
126
+ return __privateGet(this, _commands);
68
127
  }
69
128
  static create() {
70
- return new Clerc();
129
+ return new _Clerc();
71
130
  }
72
131
  name(name) {
73
- this._name = name;
132
+ __privateSet(this, _name, name);
74
133
  return this;
75
134
  }
76
135
  description(description) {
77
- this._description = description;
136
+ __privateSet(this, _description, description);
78
137
  return this;
79
138
  }
80
139
  version(version) {
81
- this._version = version;
140
+ __privateSet(this, _version, version);
82
141
  return this;
83
142
  }
84
143
  command(name, description, options = {}) {
85
- if (this._commands[name]) {
144
+ if (__privateGet(this, _commands)[name]) {
86
145
  if (name === SingleCommand) {
87
146
  throw new CommandExistsError("Single command already exists");
88
147
  }
89
148
  throw new CommandExistsError(`Command "${name === SingleCommand ? "[SingleCommand]" : name}" already exists`);
90
149
  }
91
- if (this.__isSingleCommand) {
92
- throw new SingleCommandError("Single command mode enabled");
150
+ if (__privateGet(this, _isSingleCommand, isSingleCommand_get)) {
151
+ throw new SingleCommandError();
93
152
  }
94
- if (name === SingleCommand && this.__hasCommands) {
95
- throw new CommonCommandExistsError("Common command exists");
153
+ if (name === SingleCommand && __privateGet(this, _hasCommands, hasCommands_get)) {
154
+ throw new CommonCommandExistsError();
96
155
  }
97
- const { alias, flags } = options;
98
- this._commands[name] = { name, description, alias, flags };
156
+ if (name !== SingleCommand) {
157
+ const splitedName = name.split(" ");
158
+ const existedCommandNames = Object.keys(__privateGet(this, _commands)).filter((name2) => typeof name2 === "string").map((name2) => name2.split(" "));
159
+ if (existedCommandNames.some((name2) => arrayStartsWith(splitedName, name2))) {
160
+ throw new ParentCommandExistsError(splitedName.join(" "));
161
+ }
162
+ if (existedCommandNames.some((name2) => arrayStartsWith(name2, splitedName))) {
163
+ throw new SubcommandExistsError(splitedName.join(" "));
164
+ }
165
+ }
166
+ __privateGet(this, _commands)[name] = { name, description, ...options };
99
167
  return this;
100
168
  }
101
169
  on(name, handler) {
102
- this.__commandEmitter.on(name, handler);
170
+ __privateGet(this, _commandEmitter).on(name, handler);
103
171
  return this;
104
172
  }
105
173
  use(plugin) {
106
174
  return plugin.setup(this);
107
175
  }
108
176
  inspector(inspector) {
109
- this._inspectors.push(inspector);
177
+ __privateGet(this, _inspectors).push(inspector);
110
178
  return this;
111
179
  }
112
180
  parse(argv = resolveArgv()) {
113
181
  const parsed = mri(argv);
114
- const name = String(parsed._[0]);
115
- const command = this.__isSingleCommand ? this._commands[SingleCommand] : resolveCommand(this._commands, name);
116
- const isCommandResolved = !!command;
117
- const parsedWithType = typeFlag((command == null ? void 0 : command.flags) || {}, argv);
118
- const { _: args, flags } = parsedWithType;
119
- const parameters = this.__isSingleCommand || !isCommandResolved ? args : args.slice(1);
120
- const inspectorContext = {
121
- name: command == null ? void 0 : command.name,
122
- resolved: isCommandResolved,
123
- isSingleCommand: this.__isSingleCommand,
124
- raw: parsedWithType,
125
- parameters,
126
- flags,
127
- unknownFlags: parsedWithType.unknownFlags,
128
- cli: this
182
+ const name = parsed._.map(String);
183
+ const stringName = name.join(" ");
184
+ const getCommand = () => __privateGet(this, _isSingleCommand, isSingleCommand_get) ? __privateGet(this, _commands)[SingleCommand] : resolveCommand(__privateGet(this, _commands), name);
185
+ const getContext = () => {
186
+ const command = getCommand();
187
+ const isCommandResolved = !!command;
188
+ const parsedWithType = typeFlag((command == null ? void 0 : command.flags) || {}, [...argv]);
189
+ const { _: args, flags } = parsedWithType;
190
+ const parameters = __privateGet(this, _isSingleCommand, isSingleCommand_get) || !isCommandResolved ? args : args.slice(command.name.split(" ").length);
191
+ const context = {
192
+ name: command == null ? void 0 : command.name,
193
+ resolved: isCommandResolved,
194
+ isSingleCommand: __privateGet(this, _isSingleCommand, isSingleCommand_get),
195
+ raw: parsedWithType,
196
+ parameters,
197
+ flags,
198
+ unknownFlags: parsedWithType.unknownFlags,
199
+ cli: this
200
+ };
201
+ return context;
129
202
  };
130
- const handlerContext = inspectorContext;
131
203
  const emitHandler = () => {
204
+ const command = getCommand();
205
+ const handlerContext = getContext();
132
206
  if (!command) {
133
- throw new NoSuchCommandError(`No such command: ${name}`);
207
+ throw new NoSuchCommandError(stringName);
134
208
  }
135
- this.__commandEmitter.emit(command.name, handlerContext);
209
+ __privateGet(this, _commandEmitter).emit(command.name, handlerContext);
136
210
  };
137
- const inspectors = [...this._inspectors, emitHandler];
211
+ const inspectors = [...__privateGet(this, _inspectors), emitHandler];
138
212
  const inspector = compose(inspectors);
139
- inspector(inspectorContext);
213
+ inspector(getContext);
214
+ return this;
140
215
  }
141
- }
216
+ };
217
+ let Clerc = _Clerc;
218
+ _name = new WeakMap();
219
+ _description = new WeakMap();
220
+ _version = new WeakMap();
221
+ _inspectors = new WeakMap();
222
+ _commands = new WeakMap();
223
+ _commandEmitter = new WeakMap();
224
+ _isSingleCommand = new WeakSet();
225
+ isSingleCommand_get = function() {
226
+ return __privateGet(this, _commands)[SingleCommand] !== void 0;
227
+ };
228
+ _hasCommands = new WeakSet();
229
+ hasCommands_get = function() {
230
+ return Object.keys(__privateGet(this, _commands)).length > 0;
231
+ };
142
232
 
143
233
  const definePlugin = (p) => p;
144
234
  const defineHandler = (_cli, _key, handler) => handler;
145
235
  const defineInspector = (_cli, inspector) => inspector;
146
236
 
147
- export { Clerc, CommandExistsError, CommonCommandExistsError, NoSuchCommandError, SingleCommand, SingleCommandError, compose, defineHandler, defineInspector, definePlugin, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault };
237
+ export { Clerc, CommandExistsError, CommonCommandExistsError, NoSuchCommandError, ParentCommandExistsError, SingleCommand, SingleCommandError, SubcommandExistsError, compose, defineHandler, defineInspector, definePlugin, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault, resolveRootCommands, resolveSubcommandsByParent };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clerc",
3
- "version": "0.3.4",
3
+ "version": "0.5.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": [
@@ -39,7 +39,7 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@clerc/utils": "0.3.4",
42
+ "@clerc/utils": "0.5.0",
43
43
  "is-platform": "^0.2.0",
44
44
  "lite-emit": "^1.4.0",
45
45
  "mri": "^1.2.0",