@slimio/arg-parser
Advanced tools
Comparing version 0.1.0 to 0.2.0
/// <reference types="node" /> | ||
declare class ArgParser { | ||
constructor(version: string, description?: string); | ||
public version: string; | ||
public description: string; | ||
public commands: Map<string, ArgParser.Command>; | ||
public shortcuts: Map<string, string>; | ||
addCommand(cmd: string, description?: string): ArgParser; | ||
parse(argv?: string[]): Map<string, any>; | ||
showHelp(): void; | ||
} | ||
declare namespace ArgParser { | ||
type valueType = number | string | boolean | any[]; | ||
interface Command { | ||
name: string; | ||
type: string; | ||
description: string; | ||
shortcut?: string; | ||
defaultVal?: valueType; | ||
defaultVal?: number | string | boolean | any[]; | ||
} | ||
export type ArgvResult<T> = Map<keyof T, T[keyof T]>; | ||
export function argDefinition(cmd: string, description?: string): Command; | ||
export function parseArg<T>(argDefinitions?: Command[], argv?: string[]): ArgvResult<T>; | ||
} | ||
@@ -26,0 +16,0 @@ |
139
index.js
@@ -1,2 +0,137 @@ | ||
const ArgParser = require("./src/argParser.class"); | ||
module.exports = ArgParser; | ||
/** | ||
* @namespace ArgParser | ||
*/ | ||
/** @typedef {(Number|String|Boolean)} ArgValueType */ | ||
/** | ||
* @typedef {Object} Command | ||
* @property {String} name | ||
* @property {String} type | ||
* @property {String} shortcut | ||
* @property {String} description | ||
* @property {*} defaultVal | ||
*/ | ||
// eslint-disable-next-line | ||
const CMD_REG = /^(-{1}(?<shortcut>[a-z]){1})?\s?(-{2}(?<name>[a-z]+)){1}\s?(\[(?<type>number|string|array)(=(?<defaultVal>.*))?\])?$/; | ||
/** | ||
* @version 0.2.0 | ||
* | ||
* @method argDefinition | ||
* @desc Adds a command to the command list. All command that will not be in this list will be ignored. | ||
* @memberof ArgParser# | ||
* @param {!String} cmd name of command | ||
* @param {String} [description] command description | ||
* @returns {Command} | ||
* | ||
* @throws {Error} | ||
*/ | ||
function argDefinition(cmd, description = "") { | ||
// Retrieve command options | ||
const result = CMD_REG.exec(cmd); | ||
if (result === null) { | ||
throw new Error("Unable to parse command"); | ||
} | ||
const { shortcut, name, type = "boolean" } = result.groups; | ||
let defaultVal = result.groups.defaultVal; | ||
if (type === "boolean" && typeof defaultVal === "undefined") { | ||
defaultVal = false; | ||
} | ||
else if (type === "number" && typeof defaultVal !== "undefined") { | ||
defaultVal = Number(defaultVal); | ||
} | ||
return { name, shortcut, type, description, defaultVal }; | ||
} | ||
/** | ||
* @version 0.2.0 | ||
* | ||
* @method parseArg | ||
* @desc Parse and verify if arguments passed in command line are correct commands. | ||
* @memberof ArgParser# | ||
* @param {Command[]} [argDefinitions] arguments definitions | ||
* @param {String[]} [argv] list of command and argument of command inputted | ||
* @returns {Map<String, (ArgValueType | ArgValueType[])>} result | ||
* | ||
* @throws {TypeError} | ||
* @throws {Error} | ||
*/ | ||
function parseArg(argDefinitions = [], argv = process.argv.slice(2)) { | ||
if (!Array.isArray(argv)) { | ||
throw new TypeError("argv must be an array"); | ||
} | ||
// Hydrate commands and shortcuts | ||
const commands = new Map(); | ||
const shortcuts = new Map(); | ||
const parsedArg = new Map(); | ||
for (const def of argDefinitions) { | ||
commands.set(def.name, def); | ||
if (typeof def.shortcut === "string") { | ||
shortcuts.set(def.shortcut, def.name); | ||
} | ||
} | ||
const E_TYPES = new Map([ | ||
["number", (val) => Number.isNaN(Number(val))], | ||
["string", (val) => typeof val !== "string"], | ||
["array", (val) => !Array.isArray(val)], | ||
["boolean", (val) => typeof val !== "boolean"] | ||
]); | ||
let currCmd = null; | ||
let values = []; | ||
// STEP 1: Parse argv | ||
function writeCommand() { | ||
parsedArg.set(shortcuts.has(currCmd) ? shortcuts.get(currCmd) : currCmd, | ||
values.length === 1 ? values[0] : values); | ||
values = []; | ||
} | ||
for (const arg of argv) { | ||
if (/^-{1,2}/g.test(arg)) { | ||
currCmd !== null && writeCommand(); | ||
currCmd = arg.replace(/-/g, ""); | ||
} | ||
else { | ||
values.push(arg); | ||
} | ||
} | ||
writeCommand(); | ||
// STEP 2: Check parsedArg | ||
const result = new Map(); | ||
for (const [commandName, values] of parsedArg) { | ||
if (!commands.has(commandName)) { | ||
continue; | ||
} | ||
const { type, defaultVal } = commands.get(commandName); | ||
const value = values.length === 0 ? defaultVal || true : values; | ||
if (E_TYPES.get(type)(value)) { | ||
throw new Error(`<${commandName}> CLI argument must be type of ${type}`); | ||
} | ||
result.set(commandName, value); | ||
} | ||
// STEP 3: Setup default commands values! | ||
for (const [name, cmd] of commands.entries()) { | ||
if (result.has(name) || typeof cmd.defaultVal === "undefined") { | ||
continue; | ||
} | ||
result.set(name, cmd.defaultVal); | ||
} | ||
return result; | ||
} | ||
module.exports = { | ||
argDefinition, | ||
parseArg | ||
}; |
{ | ||
"name": "@slimio/arg-parser", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "SlimIO argument parser", | ||
@@ -9,5 +9,3 @@ "main": "index.js", | ||
}, | ||
"dependencies": { | ||
"@slimio/is": "^1.3.0" | ||
}, | ||
"dependencies": {}, | ||
"husky": { | ||
@@ -23,2 +21,3 @@ "hooks": { | ||
"@slimio/eslint-config": "^1.1.8", | ||
"@slimio/is": "^1.4.0", | ||
"@types/node": "^10.12.9", | ||
@@ -25,0 +24,0 @@ "ava": "^0.25.0", |
# ArgParser | ||
[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/SlimIO/is/commit-activity) | ||
![MIT](https://img.shields.io/github/license/mashape/apistatus.svg) | ||
![V1.0](https://img.shields.io/badge/version-0.1.0-blue.svg) | ||
![V1.0](https://img.shields.io/badge/version-0.2.0-blue.svg) | ||
![0DEP](https://img.shields.io/badge/Dependencies-0-yellow.svg) | ||
NodeJS light Argv parser. | ||
Fast, Secure and light Command Line Argument parser for Node.js ! ArgParser was designed to be embedded in a SlimIO agent, most popular library was not matching our expectation of a light and secure Arg parser. | ||
> This project has been designed for an internal usage. | ||
It does not aim to replace popular CLI lib like `yargs` or `commander`. Please, do not use this package if you do not know what you are doing. | ||
> Warning: The API doesn't aim to be "runtime" safe. | ||
## Why | ||
- Focus on security | ||
- Secure with 0 external dependencies. | ||
- Only ship feature required for SlimIO. | ||
- Light and fast ! | ||
@@ -27,34 +31,55 @@ ## Getting Started | ||
Create the following javascript script: | ||
```js | ||
const { strictEqual } = require("assert"); | ||
const ArgParser = require("@slimio/arg-parser"); | ||
const { parseArg, argDefinition } = require("@slimio/arg-parser"); | ||
const argv = new ArgParser("v1.0.0") | ||
.addCommand("-c --colors [array]", "Array of colors") | ||
.addCommand("--verbose", "Enable verbose mode!"); | ||
const result = parseArg([ | ||
argDefinition("-c --colors [array]", "Array of colors"), | ||
argDefinition("--verbose", "Enable verbose mode!") | ||
]); | ||
const colors = ["red", "yellow"]; | ||
const result = argv.parse(["-c" , ...colors, "--verbose"]); | ||
strictEqual(result.get("verbose"), true); | ||
strictEqual(result.get("colors").toString(), colors.toString()); | ||
console.log(result); | ||
``` | ||
## API | ||
And then run the following command line: | ||
```bash | ||
$ node yourscript --colors red blue --verbose | ||
``` | ||
### constructor(version: string, description?: string) | ||
Create a new ArgParser instance. | ||
For help run: | ||
```bash | ||
$ node yourscript --help | ||
``` | ||
- description describe the CLI itself and is intended to be used in **showHelp()**. | ||
## API | ||
### argDefinition(cmd: string, description?: string): Command | ||
Generate a new Command definition. cmd argument is a string pattern that will be matched against the following regex: | ||
```js | ||
new ArgParser("V1.0.0", "A super CLI!!"); | ||
/^(-{1}(?<shortcut>[a-z]){1})?\s?(-{2}(?<name>[a-z]+)){1}\s?(\[(?<type>number|string|array)(=(?<defaultVal>.*))?\])?$/; | ||
``` | ||
### addCommand(cmd: string, description?: string): ArgParser | ||
Add a new command. cmd is a string pattern that will be matched against the following regex: | ||
Take a look at the root directory `example` for more examples of how to use addCommand ! | ||
```js | ||
/^(-{1}(?<shortcut>[a-z]){1})?\s?(-{2}(?<name>[a-z]+)){1}\s?(\[(?<type>number|string|array)(=(?<defaultVal>.*))?\])?$/; | ||
const { parseArg, argDefinition } = require("@slimio/arg-parser"); | ||
const result = parseArg([ | ||
argDefinition("--verbose", "Enable verbose mode!"), | ||
argDefinition("-a --autoreload [number=500]", "Configuration Autoreload delay in number") | ||
]); | ||
``` | ||
### showHelp() | ||
Stdout help instructions on how to use the CLI. | ||
A command is described as follow on TypeScript: | ||
```ts | ||
interface Command { | ||
name: string; | ||
type: string; | ||
description: string; | ||
shortcut?: string; | ||
defaultVal?: number | string | boolean | any[]; | ||
} | ||
``` | ||
Feel free to redefine the wrapper as you want ! | ||
### parseArg(argDefinitions: Command[], argv?: string[]): Map< string, any > | ||
Parse Argv (or any input array). |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
0
85
9744
12
140
1
- Removed@slimio/is@^1.3.0
- Removed@slimio/is@1.5.1(transitive)