New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@kearisp/cli

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@kearisp/cli - npm Package Compare versions

Comparing version 1.0.7 to 2.0.0

lib/errors/InvalidError.d.ts

3

lib/index.d.ts

@@ -1,3 +0,2 @@

import { Cli } from "./makes";
export * from "./makes";
export * from "./types";
export { Cli };

@@ -17,5 +17,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Cli = void 0;
const makes_1 = require("./makes");
Object.defineProperty(exports, "Cli", { enumerable: true, get: function () { return makes_1.Cli; } });
__exportStar(require("./makes"), exports);
__exportStar(require("./types"), exports);

@@ -1,10 +0,12 @@

import { Logger } from "../types";
import { Command } from "./Command";
declare class Cli extends Command {
protected scriptPath: string;
constructor(logger?: Logger);
declare class Cli {
protected name: string;
protected commands: Command[];
completionScript(): string;
protected parseCommand(command: string): string[];
run(argv: string[]): Promise<any>;
protected parseCommand(command: string, index: number): string[];
command(name: string): Command;
protected process(parts: string[]): Promise<string | void>;
protected complete(parts: string[]): Promise<string[]>;
run(argv: string[]): Promise<string | void>;
}
export { Cli };

@@ -6,12 +6,14 @@ "use strict";

const Path = require("path");
const InvalidError_1 = require("../errors/InvalidError");
const Command_1 = require("./Command");
const Logger_1 = require("./Logger");
const utils_1 = require("../utils");
class Cli extends Command_1.Command {
constructor(logger) {
super("", logger);
class Cli {
constructor() {
this.commands = [];
}
completionScript() {
return (0, utils_1.generateCompletion)(this._command);
return (0, utils_1.generateCompletion)(this.name);
}
parseCommand(command) {
parseCommand(command, index) {
const parts = [];

@@ -48,55 +50,76 @@ let current = "", quotes = "", escape = 0;

}
return parts;
const [, ...args] = parts;
return args.length < index ? [...args, ""] : args;
}
async run(argv) {
const [, scriptPath, ...rest] = argv;
this.scriptPath = scriptPath;
this._command = Path.basename(scriptPath);
const parts = [this._command, ...rest];
if (parts.indexOf("--completion") > -1 || parts.indexOf("--compbash") > -1 || parts.indexOf("--compgen") > -1) {
const completion = new Command_1.Command(`${this._command} <index> <prev> <command>`, this._logger);
const promise = new Promise((resolve) => {
completion
.option("completion", {
type: "boolean"
})
.option("compbash", {
type: "boolean"
})
.option("compgen", {
type: "boolean"
})
.action((options, index, prev, command) => {
resolve([index, command]);
return "1";
});
});
command(name) {
let command = this.commands.find((command) => {
return command.name === name;
});
if (!command) {
command = new Command_1.Command(name);
this.commands.push(command);
}
return command;
}
async process(parts) {
for (const command of this.commands) {
try {
const res = await completion.process(parts);
if (res === "1") {
const [index, command] = await promise;
const p = this.parseCommand(command);
const res = await this.complete(p.length - 1 < parseInt(index) ? [...p, ""] : p);
return res
.map((predict) => {
if (/\s/.test(predict)) {
return predict.replace(/\s/g, "\\ ");
}
return predict;
})
.join(OS.EOL);
const input = command.parse(parts);
return command.emit(this.name, input);
}
catch (err) {
if (!(err instanceof InvalidError_1.InvalidError)) {
Logger_1.Logger.error(err.message);
}
}
}
throw new Error("Invalid command");
}
async complete(parts) {
let predicts = [];
for (const command of this.commands) {
try {
const res = await command.complete(parts);
predicts = [
...predicts,
...res
];
}
catch (err) {
this.error(err.message);
}
return "";
}
const res = await this.process(parts);
if (res === null) {
throw new Error("Command not found");
}
return res;
return predicts;
}
async run(argv) {
const [, scriptPath, ...parts] = argv;
this.name = Path.basename(scriptPath);
this.command(`complete <index> <prev> <command>`)
.help({
description: "Generate completion script",
disabled: true
})
.option("compbash", {
type: "boolean"
})
.option("compgen", {
type: "boolean"
})
.option("compzsh", {
type: "boolean"
})
.action(async (input) => {
const parts = this.parseCommand(input.argument("command"), parseInt(input.argument("index")));
const res = await this.complete(parts);
return res
.map((predict) => {
if (/\s/.test(predict)) {
return predict.replace(/\s/g, "\\ ");
}
return predict;
})
.join(OS.EOL);
});
return this.process(parts);
}
}
exports.Cli = Cli;

@@ -1,2 +0,3 @@

import { Logger, Option } from "../types";
import { Option } from "../types";
import { CommandInput } from "./CommandInput";
type HelpParams = false | {

@@ -12,46 +13,25 @@ disabled?: boolean;

isOption?: boolean;
action: (options: any, ...args: (string | string[])[]) => string[] | Promise<string[]>;
action: (input: CommandInput) => string[] | Promise<string[]>;
};
type Action = (options: any, ...args: (string | string[])[]) => void | string | Promise<void | string>;
declare class Command {
type Action = (input: CommandInput) => void | string | Promise<void | string>;
export declare class Command {
protected _command: string;
protected _help: boolean;
protected _description: string;
protected _commands: Command[];
protected _options: Option[];
protected _action: Action;
protected _completions: Completion[];
protected _logger?: Logger;
constructor(command: string, logger?: Logger);
getName(): string;
command(name: string): Command;
constructor(command: string);
get name(): string;
option(name: string, params: OptionParams): this;
protected getOptionSettings(name?: string, alias?: string): Option;
help(params: HelpParams): this;
completion(name: Completion["name"], handle: Completion["action"]): this;
action(action: Action): void;
parse(parts: string[], partial?: boolean): {
args: (string | string[])[];
options: {
[name: string]: string | number | boolean;
};
command: string;
part: string;
parts?: undefined;
} | {
args: (string | string[])[];
options: {
[name: string]: string | number | boolean;
};
parts: string[];
command?: undefined;
part?: undefined;
};
process(parts: string[], parentOptions?: any, parentArgs?: (string | string[])[]): any;
predictCommand(command: string, part: string, options?: any, args?: (string | string[])[]): Promise<string[]>;
action(action: Action): this;
parse(parts: string[]): CommandInput;
emit(name: string, input: CommandInput): Promise<string | void>;
protected predictCommand(command: string, part: string, input: CommandInput): Promise<string[]>;
protected predictOption(part: string): Promise<string[]>;
complete(parts: string[]): Promise<string[]>;
protected log(...args: any[]): void;
protected info(...args: any[]): void;
protected warn(...args: any[]): void;
protected error(...args: any[]): void;
}
export { Command };
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Command = void 0;
const OS = require("os");
const utils_1 = require("../utils");
const regOption = /^-(?:-(\w[\w\d_-]*)|(\w))$/;
const regOptionWithValue = /^-(?:-(\w[\w\d_-]*)|(\w))=(.*)$/;
const regShortMultipleOption = /^-(\w+)$/;
const InvalidError_1 = require("../errors/InvalidError");
const Parser_1 = require("./Parser");
const CommandInput_1 = require("./CommandInput");
class Command {
constructor(command, logger) {
this._commands = [];
constructor(command) {
this._options = [];
this._completions = [];
this._command = command;
this._logger = logger;
this._help = true;
}
getName() {
get name() {
return this._command;
}
command(name) {
let command = this._commands.find((command) => {
return command.getName() === name;
});
if (!command) {
command = new Command(name, this._logger);
this._commands.push(command);
}
return command;
}
option(name, params) {
const { type = "boolean", default: defaultValue, ...rest } = params || {};
this._options.push({
name,
type: type,
default: type === "boolean"
? typeof defaultValue === "boolean" ? defaultValue : false
: defaultValue,
...rest
});
const { type = "boolean", default: defaultValue, help = true, ...rest } = params || {};
this._options = [
...this._options.filter((option) => {
return option.name !== name;
}),
{
name,
help,
type: type,
default: type === "boolean"
? typeof defaultValue === "boolean" ? defaultValue : false
: defaultValue,
...rest
}
];
return this;
}
getOptionSettings(name, alias) {
return this._options.find((option) => {
return (name && option.name === name) || (alias && option.alias === alias);
});
}
help(params) {

@@ -51,3 +52,4 @@ const { disabled = false, description = "" } = typeof params === "boolean" ? {

alias: "h",
description: "Help"
description: "Help",
help: false
});

@@ -66,164 +68,106 @@ }

this._action = action;
return this;
}
parse(parts, partial = false) {
parse(parts) {
const commands = this._command
? this._command.split(/\s+/g)
: [];
const args = [];
const args = {};
const options = {};
let current = 0;
const parser = new Parser_1.Parser(parts);
for (const command of commands) {
let part = parts[current] || "";
let isLast = current === parts.length - 1;
if ((0, utils_1.isSpread)(command)) {
let value = [];
while (current < parts.length) {
isLast = current === parts.length - 1;
if (partial && isLast) {
args.push(value);
return {
args,
options,
command,
part: parts[current]
};
}
value.push(parts[current]);
current++;
if (parser.isSpread(command)) {
const name = parser.parseSpreadCommand(command);
const values = [];
while (!parser.eol) {
values.push(parser.part);
parser.next();
}
args.push(value);
args[name] = values;
parser.next();
}
else if ((0, utils_1.isCommand)(command)) {
const regExp = (0, utils_1.generateCommandRegExp)(command);
if (!regExp) {
throw new Error(`Something wrong: ${command}`);
else if (parser.isCommand(command)) {
const res = parser.getArguments(command);
for (const name in res) {
args[name] = res[name];
}
if (partial && isLast) {
const partExp = (0, utils_1.generateCommandRegExp)(command, true);
if (partExp.test(part)) {
return {
args,
options,
command,
part
};
}
}
if (!regExp.test(part)) {
return null;
}
const [, ...match] = regExp.exec(part) || [];
args.push(...match);
current++;
parser.next();
}
let isOption = true;
do {
part = parts[current] || "";
if (regOption.test(part)) {
const [, name, alias] = regOption.exec(part) || [];
const option = this._options.find((option) => {
return (name && option.name === name) || (alias && option.alias === alias);
});
if (!option) {
throw new Error(`Option "${name || alias}" is not defined (1)`);
else {
throw new InvalidError_1.InvalidError("Invalid command");
}
while (parser.isOption()) {
if (parser.isRegOption()) {
const { name, alias } = parser.parseOption();
const option = this.getOptionSettings(name, alias);
if (option) {
switch (option.type) {
case "boolean":
options[option.name] = true;
break;
case "number":
parser.next();
options[option.name] = parseFloat(parser.part);
break;
case "string":
parser.next();
options[option.name] = parser.part;
break;
}
}
switch (option.type) {
case "boolean":
options[option.name] = true;
break;
case "number":
options[option.name] = parseFloat(parts[++current]);
break;
case "string":
options[option.name] = parts[++current];
break;
}
current++;
}
else if (regOptionWithValue.test(part)) {
const [, name, alias, value] = regOptionWithValue.exec(part) || [];
const option = this._options.find((option) => {
if (name) {
return option.name === name;
else if (parser.isOptionWithValue()) {
const { name, alias, value } = parser.parseOptionWithValue();
const option = this.getOptionSettings(name, alias);
if (option) {
switch (option.type) {
case "boolean":
options[option.name] = true;
break;
case "number":
options[option.name] = parseFloat(value);
break;
case "string":
options[option.name] = value;
break;
}
if (alias) {
return option.alias === alias;
}
return false;
});
if (!option) {
throw new Error(`Option not found ${name || alias} (2)`);
}
switch (option.type) {
case "boolean":
options[option.name] = ["true", "1"].includes(value);
break;
case "string":
options[option.name] = value;
break;
case "number":
options[option.name] = parseFloat(value);
break;
}
current++;
}
else if (regShortMultipleOption.test(part)) {
const [, alias] = regShortMultipleOption.exec(part) || [];
this._options.filter((option) => {
if (!option.alias) {
return false;
}
return alias.split("").includes(option.alias);
}).forEach((option) => {
if (option.type === "boolean") {
options[option.name] = true;
}
});
current++;
isOption = true;
}
else {
isOption = false;
}
} while (isOption);
parser.next();
}
}
return {
args,
options,
parts: parts.slice(current)
};
if (!parser.eol) {
throw new InvalidError_1.InvalidError("Haven't ended");
}
return new CommandInput_1.CommandInput(args, options);
}
async process(parts, parentOptions = {}, parentArgs = []) {
const res = this.parse(parts);
if (!res) {
return null;
async emit(name, input) {
if (this._help && input.option("help")) {
const options = this._options.filter((option) => {
return option.help;
});
return [
"",
`Usage: ${name} ${this.name}`,
"",
...this._description ? [
this._description,
""
] : [],
...options.length > 0 ? [
"Options:",
...options.map((option) => {
const alias = option.alias ? `-${option.alias},` : " ";
return ` ${alias} --${option.name}\t\t${option.description}`;
}),
""
] : []
].join(OS.EOL);
}
const { args, parts: childParts } = res;
const options = {
...parentOptions,
...res.options
};
if (this._action) {
if (this._help && options.help) {
const optionsDescription = this._options.map((option) => {
const { alias, name, description = "" } = option;
const aliasDescription = alias ? `, -${alias}` : "";
return ` --${name}${aliasDescription} - ${description}`;
}).join("\n");
return `Help:\n ${this._description || ""}\n\n${optionsDescription}\n`;
}
return (await this._action(options, ...parentArgs, ...args)) || "";
if (!this._action) {
throw new Error("Command without action");
}
for (const command of this._commands) {
const res = await command.process(childParts, options, [
...parentArgs,
...args
]);
if (res !== null) {
return res;
}
}
return null;
return this._action(input);
}
async predictCommand(command, part, options = {}, args = []) {
async predictCommand(command, part, input) {
const comAttrReq = /^<([\w_-]+)>(.*)?$/;

@@ -279,3 +223,3 @@ const comAttrOpt = /^\[([\w_-]+)](.*)?$/;

if (exitCount > 100) {
this.warn("Emergency exit", {
console.warn("Emergency exit", {
restCommand

@@ -291,3 +235,3 @@ });

if (completion) {
const predicts = await completion.action(options, ...args);
const predicts = await Promise.resolve(completion.action(input));
resPredicts = predicts.reduce((res, predict) => {

@@ -317,45 +261,50 @@ return [

}
async predictOption(part) {
const [, dash, name] = /^(--?)(\w+)?/.exec(part) || [];
return this._options.reduce((res, option) => {
if (dash === "-") {
res.push(`-${option.alias}`, `--${option.name}`);
}
else if (dash === "--") {
res.push(`--${option.name}`);
}
return res;
}, []);
}
async complete(parts) {
const res = this.parse(parts, true);
if (!res) {
return null;
if (!this._help) {
return [];
}
const { args, options, parts: childParts, part, command } = res;
if (command && typeof part !== "undefined") {
return this.predictCommand(command, part, options, args);
}
const predicts = [];
for (const command of this._commands) {
const res = await command.complete(childParts);
if (res) {
predicts.push(...res);
const commands = this._command
? this._command.split(/\s+/g)
: [];
const parser = new Parser_1.Parser(parts);
const args = {};
const options = {};
for (const command of commands) {
if (parser.isSpread(command)) {
}
else if (!parser.isLast && parser.isCommand(command)) {
const partArguments = parser.getArguments(command);
for (const name in partArguments) {
args[name] = partArguments[name];
}
parser.next();
}
else if (parser.isLast && parser.isCommand(command, true)) {
return this.predictCommand(command, parser.part, new CommandInput_1.CommandInput(args, options));
}
else {
throw new InvalidError_1.InvalidError("Error");
}
while (parser.isOption(true)) {
if (parser.isLast && parser.isCommand(command)) {
return this.predictOption(parser.part);
}
parser.next();
}
}
return predicts;
return [];
}
log(...args) {
if (!this._logger) {
return;
}
this._logger.log(...args);
}
info(...args) {
if (!this._logger) {
return;
}
this._logger.info(...args);
}
warn(...args) {
if (!this._logger) {
return;
}
this._logger.warn(...args);
}
error(...args) {
if (!this._logger) {
return;
}
this._logger.error(...args);
}
}
exports.Command = Command;
export * from "./Cli";
export * from "./Command";
export * from "./CommandInput";
export * from "./Logger";
export * from "./Parser";

@@ -18,1 +18,5 @@ "use strict";

__exportStar(require("./Cli"), exports);
__exportStar(require("./Command"), exports);
__exportStar(require("./CommandInput"), exports);
__exportStar(require("./Logger"), exports);
__exportStar(require("./Parser"), exports);

@@ -1,2 +0,1 @@

export * from "./Logger";
export * from "./Option";

@@ -17,3 +17,2 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./Logger"), exports);
__exportStar(require("./Option"), exports);
export type Option = {
name: string;
type: "string" | "boolean" | "number";
help?: boolean;
alias?: string;

@@ -5,0 +6,0 @@ description?: string;

@@ -9,3 +9,3 @@ "use strict";

_${name}_completion() {
compadd -- \`${name} --compzsh --compgen "\${CURRENT}" "\${words[CURRENT - 1]}" \${BUFFER}\`
compadd -- \`${name} complete --compzsh --compgen "\${CURRENT}" "\${words[CURRENT - 1]}" \${BUFFER}\`
}

@@ -20,3 +20,3 @@

local OPTIONS=$(${name} --compbash --compgen "$((COMP_CWORD - (nb_colon * 2)))" "$prev" "\${COMP_LINE}")
local OPTIONS=$(${name} complete --compbash --compgen "$((COMP_CWORD - (nb_colon * 2)))" "$prev" "\${COMP_LINE}")

@@ -47,3 +47,3 @@ COMPREPLY=()

si="$IFS"
if ! IFS=$'\n' reply=($(${name} --compzsh --compgen "\${cword}" "\${words[cword - 1]}" \${line})); then
if ! IFS=$'\n' reply=($(${name} complete --compzsh --compgen "\${cword}" "\${words[cword - 1]}" \${line})); then
local ret=$?

@@ -50,0 +50,0 @@ IFS="$si"

{
"name": "@kearisp/cli",
"version": "1.0.7",
"version": "2.0.0",
"license": "MIT",

@@ -23,6 +23,9 @@ "author": "Kris Papercut <krispcut@gmail.com>",

"prepare": "npm run build",
"watch": "tsc --watch",
"watch": "KP_LOG=disable tsc --watch",
"watch:test": "KP_LOG=log jest --colors --watchAll",
"watch:test-cli": "KP_LOG=log jest --colors --watchAll --runTestsByPath ./src/makes/Cli.spec.ts",
"watch:test-command": "KP_LOG=log jest --colors --watchAll --runTestsByPath ./src/makes/Command.spec.ts",
"watch:test-parser": "KP_LOG=log jest --colors --watchAll --runTestsByPath ./src/makes/Parser.spec.ts",
"build": "tsc",
"test": "jest --colors",
"test:watch": "jest --colors --watch"
"test": "KP_LOG=none jest --colors"
},

@@ -35,8 +38,10 @@ "dependencies": {

"@types/jest": "^29.5.12",
"@types/node": "^20.11.16",
"@types/node": "^20.12.7",
"date-fns": "^3.6.0",
"fs": "^0.0.1-security",
"jest": "^29.7.0",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
"typescript": "^5.4.5"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc