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 +144 -50
- package/dist/index.d.ts +46 -34
- package/dist/index.mjs +141 -51
- package/package.json +2 -2
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
|
|
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 "${
|
|
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 (
|
|
81
|
+
return (getCtx) => {
|
|
53
82
|
return dispatch(0);
|
|
54
83
|
function dispatch(i) {
|
|
55
84
|
const inspector = inspectors[i];
|
|
56
|
-
return inspector(
|
|
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
|
|
110
|
+
const _Clerc = class {
|
|
63
111
|
constructor() {
|
|
64
|
-
this
|
|
65
|
-
this
|
|
66
|
-
this
|
|
67
|
-
this
|
|
68
|
-
this
|
|
69
|
-
this
|
|
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
|
|
72
|
-
return this
|
|
130
|
+
get _inspectors() {
|
|
131
|
+
return __privateGet(this, _inspectors);
|
|
73
132
|
}
|
|
74
|
-
get
|
|
75
|
-
return
|
|
133
|
+
get _commands() {
|
|
134
|
+
return __privateGet(this, _commands);
|
|
76
135
|
}
|
|
77
136
|
static create() {
|
|
78
|
-
return new
|
|
137
|
+
return new _Clerc();
|
|
79
138
|
}
|
|
80
139
|
name(name) {
|
|
81
|
-
this
|
|
140
|
+
__privateSet(this, _name, name);
|
|
82
141
|
return this;
|
|
83
142
|
}
|
|
84
143
|
description(description) {
|
|
85
|
-
this
|
|
144
|
+
__privateSet(this, _description, description);
|
|
86
145
|
return this;
|
|
87
146
|
}
|
|
88
147
|
version(version) {
|
|
89
|
-
this
|
|
148
|
+
__privateSet(this, _version, version);
|
|
90
149
|
return this;
|
|
91
150
|
}
|
|
92
151
|
command(name, description, options = {}) {
|
|
93
|
-
if (this
|
|
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
|
|
100
|
-
throw new SingleCommandError(
|
|
158
|
+
if (__privateGet(this, _isSingleCommand, isSingleCommand_get)) {
|
|
159
|
+
throw new SingleCommandError();
|
|
101
160
|
}
|
|
102
|
-
if (name === SingleCommand && this
|
|
103
|
-
throw new CommonCommandExistsError(
|
|
161
|
+
if (name === SingleCommand && __privateGet(this, _hasCommands, hasCommands_get)) {
|
|
162
|
+
throw new CommonCommandExistsError();
|
|
104
163
|
}
|
|
105
|
-
|
|
106
|
-
|
|
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.
|
|
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
|
|
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 =
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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(
|
|
215
|
+
throw new NoSuchCommandError(stringName);
|
|
142
216
|
}
|
|
143
|
-
this.
|
|
217
|
+
__privateGet(this, _commandEmitter).emit(command.name, handlerContext);
|
|
144
218
|
};
|
|
145
|
-
const inspectors = [...this
|
|
219
|
+
const inspectors = [...__privateGet(this, _inspectors), emitHandler];
|
|
146
220
|
const inspector = compose(inspectors);
|
|
147
|
-
inspector(
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
68
|
+
type TypeFlag<Schemas extends Flags> = ParsedFlags<{
|
|
68
69
|
[flag in keyof Schemas]: InferFlagType<Schemas[flag]>;
|
|
69
70
|
}>;
|
|
70
71
|
|
|
71
|
-
|
|
72
|
+
type FlagOptions = FlagSchema & {
|
|
72
73
|
description: string;
|
|
73
74
|
required?: boolean;
|
|
74
75
|
};
|
|
75
|
-
|
|
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
|
-
|
|
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
|
-
|
|
89
|
+
type CommandRecord = Dict<Command> & {
|
|
87
90
|
[SingleCommand]?: Command;
|
|
88
91
|
};
|
|
89
|
-
|
|
92
|
+
type MakeEventMap<T extends CommandRecord> = {
|
|
90
93
|
[K in keyof T]: [InspectorContext];
|
|
91
94
|
};
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
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
|
-
|
|
118
|
+
type SingleCommandType = typeof SingleCommand;
|
|
116
119
|
declare class Clerc<C extends CommandRecord = {}> {
|
|
117
|
-
|
|
118
|
-
_description: string;
|
|
119
|
-
_version: string;
|
|
120
|
-
_inspectors: Inspector[];
|
|
121
|
-
_commands: C;
|
|
122
|
-
private __commandEmitter;
|
|
120
|
+
#private;
|
|
123
121
|
private constructor();
|
|
124
|
-
|
|
125
|
-
|
|
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[]):
|
|
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[]): (
|
|
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
|
|
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 "${
|
|
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 (
|
|
73
|
+
return (getCtx) => {
|
|
45
74
|
return dispatch(0);
|
|
46
75
|
function dispatch(i) {
|
|
47
76
|
const inspector = inspectors[i];
|
|
48
|
-
return inspector(
|
|
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
|
|
102
|
+
const _Clerc = class {
|
|
55
103
|
constructor() {
|
|
56
|
-
this
|
|
57
|
-
this
|
|
58
|
-
this
|
|
59
|
-
this
|
|
60
|
-
this
|
|
61
|
-
this
|
|
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
|
|
64
|
-
return this
|
|
119
|
+
get _version() {
|
|
120
|
+
return __privateGet(this, _version);
|
|
65
121
|
}
|
|
66
|
-
get
|
|
67
|
-
return
|
|
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
|
|
129
|
+
return new _Clerc();
|
|
71
130
|
}
|
|
72
131
|
name(name) {
|
|
73
|
-
this
|
|
132
|
+
__privateSet(this, _name, name);
|
|
74
133
|
return this;
|
|
75
134
|
}
|
|
76
135
|
description(description) {
|
|
77
|
-
this
|
|
136
|
+
__privateSet(this, _description, description);
|
|
78
137
|
return this;
|
|
79
138
|
}
|
|
80
139
|
version(version) {
|
|
81
|
-
this
|
|
140
|
+
__privateSet(this, _version, version);
|
|
82
141
|
return this;
|
|
83
142
|
}
|
|
84
143
|
command(name, description, options = {}) {
|
|
85
|
-
if (this
|
|
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
|
|
92
|
-
throw new SingleCommandError(
|
|
150
|
+
if (__privateGet(this, _isSingleCommand, isSingleCommand_get)) {
|
|
151
|
+
throw new SingleCommandError();
|
|
93
152
|
}
|
|
94
|
-
if (name === SingleCommand && this
|
|
95
|
-
throw new CommonCommandExistsError(
|
|
153
|
+
if (name === SingleCommand && __privateGet(this, _hasCommands, hasCommands_get)) {
|
|
154
|
+
throw new CommonCommandExistsError();
|
|
96
155
|
}
|
|
97
|
-
|
|
98
|
-
|
|
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.
|
|
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
|
|
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 =
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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(
|
|
207
|
+
throw new NoSuchCommandError(stringName);
|
|
134
208
|
}
|
|
135
|
-
this.
|
|
209
|
+
__privateGet(this, _commandEmitter).emit(command.name, handlerContext);
|
|
136
210
|
};
|
|
137
|
-
const inspectors = [...this
|
|
211
|
+
const inspectors = [...__privateGet(this, _inspectors), emitHandler];
|
|
138
212
|
const inspector = compose(inspectors);
|
|
139
|
-
inspector(
|
|
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
|
+
"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.
|
|
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",
|