Launch Week Day 3: Introducing Organization Notifications in Socket.Learn More
Socket
Book a DemoSign in
Socket

clerc

Package Overview
Dependencies
Maintainers
1
Versions
130
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

clerc - npm Package Compare versions

Comparing version
0.0.3
to
0.1.0
+99
-46
dist/index.cjs

@@ -7,2 +7,3 @@ 'use strict';

var minimist = require('minimist');
var isPlatform = require('is-platform');

@@ -13,15 +14,35 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

function resolveFlagAlias(command) {
return Object.entries((command == null ? void 0 : command.flags) || {}).reduce((acc, [name, { alias }]) => {
if (alias) {
acc[name] = alias;
}
return acc;
}, {});
class SingleCommandError extends Error {
}
class CommandExistsError extends Error {
}
class CommonCommandExistsError extends Error {
}
class NoSuchCommandsError extends Error {
}
const mustArray = (a) => Array.isArray(a) ? a : [a];
const camelCase = (s) => s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
const kebabCase = (s) => s.replace(/([A-Z])/g, (_, c) => `-${c.toLowerCase()}`);
const resolveFlagAlias = (_command) => Object.entries((_command == null ? void 0 : _command.flags) || {}).reduce((acc, [name, command]) => {
if (command.alias) {
const item = mustArray(command.alias).map(kebabCase);
acc[kebabCase(name)] = item;
}
return acc;
}, {});
const resolveFlagDefault = (_command) => Object.entries((_command == null ? void 0 : _command.flags) || {}).reduce((acc, [name, command]) => {
const item = command.default;
if (item) {
acc[name] = item;
}
return acc;
}, {});
function resolveCommand(commands, name) {
const possibleCommands = Object.values(commands).filter((c) => {
var _a;
return c.name === name || ((_a = c.alias) == null ? void 0 : _a.includes(name));
});
if (name === SingleCommand) {
return commands[SingleCommand];
}
const possibleCommands = Object.values(commands).filter(
(c) => c.name === name || mustArray(c.alias || []).map(String).includes(name)
);
if (possibleCommands.length > 1) {

@@ -32,8 +53,9 @@ throw new Error(`Multiple commands found with name "${name}"`);

}
function compose(invokers) {
return function fn(ctx) {
const resolveArgv = () => isPlatform.isNode() ? process.argv.slice(2) : isPlatform.isDeno() ? Deno.args : [];
function compose(inspectors) {
return (ctx) => {
return dispatch(0);
function dispatch(i) {
const invoker = invokers[i];
return invoker(ctx, dispatch.bind(null, i + 1));
const inspector = inspectors[i];
return inspector(ctx, dispatch.bind(null, i + 1));
}

@@ -43,2 +65,3 @@ };

const SingleCommand = Symbol("SingleCommand");
class Clerc {

@@ -49,6 +72,12 @@ constructor() {

this._version = "";
this._invokers = [];
this._inspectors = [];
this._commands = {};
this.__command_emitter = new liteEmit.LiteEmit();
this.__commandEmitter = new liteEmit.LiteEmit();
}
get __isSingleCommand() {
return this._commands[SingleCommand] !== void 0;
}
get __hasCommands() {
return Object.keys(this._commands).length > 0;
}
static create() {

@@ -70,8 +99,20 @@ return new Clerc();

command(name, description, options = {}) {
const { alias = [], flags = {} } = options;
this._commands[name] = { name, description, alias, flags };
if (this._commands[name]) {
if (name === SingleCommand) {
throw new CommandExistsError("Single command already exists");
}
throw new CommandExistsError(`Command "${name === SingleCommand ? "[SingleCommand]" : name}" already exists`);
}
if (this.__isSingleCommand) {
throw new SingleCommandError("Single command mode enabled");
}
if (name === SingleCommand && this.__hasCommands) {
throw new CommonCommandExistsError("Common command exists");
}
const { alias, flags, parameters } = options;
this._commands[name] = { name, description, alias, flags, parameters };
return this;
}
on(name, cb) {
this.__command_emitter.on(name, cb);
on(name, handler) {
this.__commandEmitter.on(name, handler);
return this;

@@ -82,44 +123,56 @@ }

}
registerInvoker(invoker) {
this._invokers.push(invoker);
inspector(inspector) {
this._inspectors.push(inspector);
return this;
}
parse() {
const argv = process.argv.slice(2);
parse(argv = resolveArgv()) {
let parsed = minimist__default["default"](argv);
const name = parsed._[0];
const command = resolveCommand(this._commands, name || "_");
if (!command) {
throw new Error(`No such command: ${name}`);
}
const commandName = command.name;
const name = String(parsed._[0]);
const command = this.__isSingleCommand ? this._commands[SingleCommand] : resolveCommand(this._commands, name);
const isCommandResolved = !!command;
parsed = minimist__default["default"](argv, {
alias: resolveFlagAlias(this._commands[commandName])
alias: command ? resolveFlagAlias(command) : {},
default: command ? resolveFlagDefault(command) : {}
});
if (!command) {
throw new Error(`Command "${name}" not found`);
}
const invokerContext = {
name,
flags: parsed,
const { _: args, ...flags } = parsed;
const camelCaseFlags = Object.fromEntries(
Object.entries(flags).map(([key, value]) => [camelCase(key), value])
);
const parameters = this.__isSingleCommand || !isCommandResolved ? args : args.slice(1);
const inspectorContext = {
name: command == null ? void 0 : command.name,
resolved: isCommandResolved,
raw: parsed,
parameters,
flags: camelCaseFlags,
cli: this
};
const handlerContext = invokerContext;
const handlerContext = inspectorContext;
const emitHandler = () => {
this.__command_emitter.emit(commandName, handlerContext);
if (!command) {
throw new NoSuchCommandsError(`No such command: ${name}`);
}
this.__commandEmitter.emit(command.name, handlerContext);
};
const invokers = [...this._invokers, emitHandler];
const invoker = compose(invokers);
invoker(invokerContext);
const inspectors = [...this._inspectors, emitHandler];
const inspector = compose(inspectors);
inspector(inspectorContext);
}
}
function definePlugin(p) {
return p;
}
const definePlugin = (p) => p;
exports.Clerc = Clerc;
exports.CommandExistsError = CommandExistsError;
exports.CommonCommandExistsError = CommonCommandExistsError;
exports.NoSuchCommandsError = NoSuchCommandsError;
exports.SingleCommand = SingleCommand;
exports.SingleCommandError = SingleCommandError;
exports.camelCase = camelCase;
exports.compose = compose;
exports.definePlugin = definePlugin;
exports.kebabCase = kebabCase;
exports.resolveArgv = resolveArgv;
exports.resolveCommand = resolveCommand;
exports.resolveFlagAlias = resolveFlagAlias;
exports.resolveFlagDefault = resolveFlagDefault;

@@ -1,7 +0,5 @@

import { LiteEmit } from 'lite-emit';
interface Plugin<U, T extends Clerc = Clerc> {
interface Plugin<T extends Clerc = Clerc, U extends Clerc = Clerc> {
setup: (cli: T) => U;
}
declare function definePlugin<T extends Clerc, U extends Clerc>(p: Plugin<T, U>): Plugin<T, U>;
declare const definePlugin: <T extends Clerc<{}>, U extends Clerc<{}>>(p: Plugin<T, U>) => Plugin<T, U>;

@@ -17,5 +15,12 @@ declare type Dict<T> = Record<string, T>;

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>>>;
interface ParsedArgs {
[arg: string]: any;
"--"?: string[] | undefined;
_: string[];
}
interface FlagOptions {
description: string;
alias?: MaybeArray<string>;
description: string;
default?: PossibleInputKind;
required?: boolean;
}

@@ -25,25 +30,40 @@ interface Flag extends FlagOptions {

}
interface ParameterOptions {
description: string;
required?: boolean;
}
interface Parameter extends ParameterOptions {
name: string;
}
interface CommandOptions {
alias?: MaybeArray<string>;
parameters?: Dict<ParameterOptions>;
flags?: Dict<FlagOptions>;
}
interface Command<N extends string = string, D extends string = string> extends CommandOptions {
interface Command<N extends string | SingleCommandType = string, D extends string = string> extends CommandOptions {
name: N;
description: D;
}
declare type CommandRecord = Dict<Command>;
declare type CommandRecord = Dict<Command> & {
[SingleCommand]?: Command;
};
declare type MakeEventMap<T extends CommandRecord> = {
[K in keyof T]: [InvokerContext];
[K in keyof T]: [InspectorContext];
};
declare type PossibleFlagKind = string | number | boolean | Dict<any>;
declare type PossibleInputKind = string | number | boolean | Dict<any>;
interface HandlerContext<C extends CommandRecord = CommandRecord, N extends keyof C = keyof C> {
name: N;
flags: Dict<PossibleFlagKind | PossibleFlagKind[]>;
name?: N;
resolved: boolean;
raw: ParsedArgs;
parameters: PossibleInputKind[];
flags: Dict<MaybeArray<PossibleInputKind> | undefined>;
cli: Clerc<C>;
}
declare type Handler = (ctx: HandlerContext) => void;
interface InvokerContext<C extends CommandRecord = CommandRecord, N extends keyof C = keyof C> extends HandlerContext<C, N> {
interface InspectorContext<C extends CommandRecord = CommandRecord, N extends keyof C = keyof C> extends HandlerContext<C, N> {
}
declare type Invoker = (ctx: InvokerContext<any>, next: Invoker) => void;
declare type Inspector = (ctx: InspectorContext<any>, next: () => void) => void;
declare const SingleCommand: unique symbol;
declare type SingleCommandType = typeof SingleCommand;
declare class Clerc<C extends CommandRecord = {}> {

@@ -53,21 +73,153 @@ _name: string;

_version: string;
_invokers: Invoker[];
_inspectors: Inspector[];
_commands: C;
__command_emitter: LiteEmit<MakeEventMap<C>>;
private __commandEmitter;
private constructor();
private get __isSingleCommand();
private get __hasCommands();
/**
* Create a new cli
* @returns
* @example
* ```ts
* const cli = Clerc.create()
* ```
*/
static create(): Clerc<{}>;
/**
* Set the name of the cli
* @param name
* @returns
* @example
* ```ts
* Clerc.create()
* .name("test")
* ```
*/
name(name: string): this;
/**
* Set the description of the cli
* @param description
* @returns
* @example
* ```ts
* Clerc.create()
* .description("test cli")
*/
description(description: string): this;
/**
* Set the version of the cli
* @param version
* @returns
* @example
* ```ts
* Clerc.create()
* .version("1.0.0")
*/
version(version: string): this;
command<N extends string, D extends string>(name: N, description: D, options?: CommandOptions): this & Clerc<C & Record<N, Command<N, D>>>;
on<K extends keyof C>(name: K, cb: Handler): this;
use<T extends Clerc, U>(plugin: Plugin<U, T>): U;
registerInvoker(invoker: Invoker): this;
parse(): void;
/**
* Register a command
* @param name
* @param description
* @param options
* @returns
* @example
* ```ts
* Clerc.create()
* .command("test", "test command", {
* alias: "t",
* flags: {
* foo: {
* alias: "f",
* description: "foo flag",
* }
* }
* })
* ```
* @example
* ```ts
* Clerc.create()
* .command("", "single command", {
* flags: {
* foo: {
* alias: "f",
* description: "foo flag",
* }
* }
* })
* ```
*/
command<N extends string | SingleCommandType, D extends string>(name: N, description: D, options?: CommandOptions): this & Clerc<C & Record<N, Command<N, D>>>;
/**
* Register a handler
* @param name
* @param handler
* @returns
* @example
* ```ts
* Clerc.create()
* .command("test", "test command")
* .on("test", (ctx) => {
* console.log(ctx);
* })
* ```
*/
on<K extends keyof C>(name: K, handler: Handler): this;
/**
* Use a plugin
* @param plugin
* @returns
* @example
* ```ts
* Clerc.create()
* .use(plugin)
* ```
*/
use<T extends Clerc, U extends Clerc>(plugin: Plugin<T, U>): U;
/**
* Register a inspector
* @param inspector
* @returns
* @example
* ```ts
* Clerc.create()
* .inspector((ctx, next) => {
* console.log(ctx);
* next();
* })
* ```
*/
inspector(inspector: Inspector): this;
/**
* Parse the command line arguments
* @param args
* @returns
* @example
* ```ts
* Clerc.create()
* .parse(process.argv.slice(2)) // Optional
* ```
*/
parse(argv?: string[]): void;
}
declare function resolveFlagAlias(command: Command): Dict<MaybeArray<string>>;
declare function resolveCommand(commands: CommandRecord, name: string): Command<string, string>;
declare function compose(invokers: Invoker[]): (ctx: HandlerContext) => void;
declare class SingleCommandError extends Error {
}
declare class CommandExistsError extends Error {
}
declare class CommonCommandExistsError extends Error {
}
declare class NoSuchCommandsError extends Error {
}
export { Clerc, Command, CommandOptions, CommandRecord, Dict, Enhance, Flag, FlagOptions, Handler, HandlerContext, Invoker, InvokerContext, MakeEventMap, MaybeArray, Plugin, PossibleFlagKind, compose, definePlugin, resolveCommand, resolveFlagAlias };
declare type CamelCase<T extends string> = T extends `${infer A}-${infer B}${infer C}` ? `${A}${Capitalize<B>}${CamelCase<C>}` : T;
declare const camelCase: <T extends string>(s: T) => CamelCase<T>;
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;
declare const kebabCase: <T extends string>(s: T) => KebabCase<T, "">;
declare const resolveFlagAlias: (_command: Command) => Dict<string[]>;
declare const resolveFlagDefault: (_command: Command) => Dict<PossibleInputKind | undefined>;
declare function resolveCommand(commands: CommandRecord, name: string | SingleCommandType): Command | undefined;
declare const resolveArgv: () => string[];
declare function compose(inspectors: Inspector[]): (ctx: InspectorContext) => void;
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 };
import { LiteEmit } from 'lite-emit';
import minimist from 'minimist';
import { isNode, isDeno } from 'is-platform';
function resolveFlagAlias(command) {
return Object.entries((command == null ? void 0 : command.flags) || {}).reduce((acc, [name, { alias }]) => {
if (alias) {
acc[name] = alias;
}
return acc;
}, {});
class SingleCommandError extends Error {
}
class CommandExistsError extends Error {
}
class CommonCommandExistsError extends Error {
}
class NoSuchCommandsError extends Error {
}
const mustArray = (a) => Array.isArray(a) ? a : [a];
const camelCase = (s) => s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
const kebabCase = (s) => s.replace(/([A-Z])/g, (_, c) => `-${c.toLowerCase()}`);
const resolveFlagAlias = (_command) => Object.entries((_command == null ? void 0 : _command.flags) || {}).reduce((acc, [name, command]) => {
if (command.alias) {
const item = mustArray(command.alias).map(kebabCase);
acc[kebabCase(name)] = item;
}
return acc;
}, {});
const resolveFlagDefault = (_command) => Object.entries((_command == null ? void 0 : _command.flags) || {}).reduce((acc, [name, command]) => {
const item = command.default;
if (item) {
acc[name] = item;
}
return acc;
}, {});
function resolveCommand(commands, name) {
const possibleCommands = Object.values(commands).filter((c) => {
var _a;
return c.name === name || ((_a = c.alias) == null ? void 0 : _a.includes(name));
});
if (name === SingleCommand) {
return commands[SingleCommand];
}
const possibleCommands = Object.values(commands).filter(
(c) => c.name === name || mustArray(c.alias || []).map(String).includes(name)
);
if (possibleCommands.length > 1) {

@@ -22,8 +43,9 @@ throw new Error(`Multiple commands found with name "${name}"`);

}
function compose(invokers) {
return function fn(ctx) {
const resolveArgv = () => isNode() ? process.argv.slice(2) : isDeno() ? Deno.args : [];
function compose(inspectors) {
return (ctx) => {
return dispatch(0);
function dispatch(i) {
const invoker = invokers[i];
return invoker(ctx, dispatch.bind(null, i + 1));
const inspector = inspectors[i];
return inspector(ctx, dispatch.bind(null, i + 1));
}

@@ -33,2 +55,3 @@ };

const SingleCommand = Symbol("SingleCommand");
class Clerc {

@@ -39,6 +62,12 @@ constructor() {

this._version = "";
this._invokers = [];
this._inspectors = [];
this._commands = {};
this.__command_emitter = new LiteEmit();
this.__commandEmitter = new LiteEmit();
}
get __isSingleCommand() {
return this._commands[SingleCommand] !== void 0;
}
get __hasCommands() {
return Object.keys(this._commands).length > 0;
}
static create() {

@@ -60,8 +89,20 @@ return new Clerc();

command(name, description, options = {}) {
const { alias = [], flags = {} } = options;
this._commands[name] = { name, description, alias, flags };
if (this._commands[name]) {
if (name === SingleCommand) {
throw new CommandExistsError("Single command already exists");
}
throw new CommandExistsError(`Command "${name === SingleCommand ? "[SingleCommand]" : name}" already exists`);
}
if (this.__isSingleCommand) {
throw new SingleCommandError("Single command mode enabled");
}
if (name === SingleCommand && this.__hasCommands) {
throw new CommonCommandExistsError("Common command exists");
}
const { alias, flags, parameters } = options;
this._commands[name] = { name, description, alias, flags, parameters };
return this;
}
on(name, cb) {
this.__command_emitter.on(name, cb);
on(name, handler) {
this.__commandEmitter.on(name, handler);
return this;

@@ -72,40 +113,43 @@ }

}
registerInvoker(invoker) {
this._invokers.push(invoker);
inspector(inspector) {
this._inspectors.push(inspector);
return this;
}
parse() {
const argv = process.argv.slice(2);
parse(argv = resolveArgv()) {
let parsed = minimist(argv);
const name = parsed._[0];
const command = resolveCommand(this._commands, name || "_");
if (!command) {
throw new Error(`No such command: ${name}`);
}
const commandName = command.name;
const name = String(parsed._[0]);
const command = this.__isSingleCommand ? this._commands[SingleCommand] : resolveCommand(this._commands, name);
const isCommandResolved = !!command;
parsed = minimist(argv, {
alias: resolveFlagAlias(this._commands[commandName])
alias: command ? resolveFlagAlias(command) : {},
default: command ? resolveFlagDefault(command) : {}
});
if (!command) {
throw new Error(`Command "${name}" not found`);
}
const invokerContext = {
name,
flags: parsed,
const { _: args, ...flags } = parsed;
const camelCaseFlags = Object.fromEntries(
Object.entries(flags).map(([key, value]) => [camelCase(key), value])
);
const parameters = this.__isSingleCommand || !isCommandResolved ? args : args.slice(1);
const inspectorContext = {
name: command == null ? void 0 : command.name,
resolved: isCommandResolved,
raw: parsed,
parameters,
flags: camelCaseFlags,
cli: this
};
const handlerContext = invokerContext;
const handlerContext = inspectorContext;
const emitHandler = () => {
this.__command_emitter.emit(commandName, handlerContext);
if (!command) {
throw new NoSuchCommandsError(`No such command: ${name}`);
}
this.__commandEmitter.emit(command.name, handlerContext);
};
const invokers = [...this._invokers, emitHandler];
const invoker = compose(invokers);
invoker(invokerContext);
const inspectors = [...this._inspectors, emitHandler];
const inspector = compose(inspectors);
inspector(inspectorContext);
}
}
function definePlugin(p) {
return p;
}
const definePlugin = (p) => p;
export { Clerc, compose, definePlugin, resolveCommand, resolveFlagAlias };
export { Clerc, CommandExistsError, CommonCommandExistsError, NoSuchCommandsError, SingleCommand, SingleCommandError, camelCase, compose, definePlugin, kebabCase, resolveArgv, resolveCommand, resolveFlagAlias, resolveFlagDefault };
{
"name": "clerc",
"version": "0.0.3",
"version": "0.1.0",
"author": "Ray <nn_201312@163.com> (https://github.com/so1ve)",

@@ -42,2 +42,3 @@ "description": "Clerc is a simple and easy-to-use cli framework.",

"dependencies": {
"is-platform": "^0.2.0",
"lite-emit": "^1.4.0",

@@ -44,0 +45,0 @@ "minimist": "^1.2.7"