├── .github └── workflows │ └── publish.yml ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── example ├── docker └── docker.ts ├── package-lock.json ├── package.json ├── src ├── index.ts └── test │ └── index.test.ts └── tsconfig.json /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | publish: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: technote-space/can-npm-publish-action@v1 14 | - name: Use Node.js 16 15 | uses: actions/setup-node@v1 16 | with: 17 | node-version: 16 18 | cache: 'npm' 19 | cache-dependency-path: 'package-lock.json' 20 | - run: npm i -g npm@latest 21 | - run: npm ci 22 | - run: npm run build 23 | - run: npm test 24 | - name: npmjs.org npm publish 25 | uses: JS-DevTools/npm-publish@v1 26 | with: 27 | token: ${{ secrets.NPM_TOKEN }} 28 | registry: https://registry.npmjs.org 29 | access: public 30 | - run: npm pkg set "name=@${{ GITHUB.REPOSITORY }}" 31 | - name: github.com npm publish 32 | uses: JS-DevTools/npm-publish@v1 33 | with: 34 | token: ${{ GITHUB.TOKEN }} 35 | registry: https://npm.pkg.github.com 36 | access: public 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # app data 2 | .store 3 | 4 | # mac 5 | .DS_Store 6 | 7 | # windows 8 | Thumbs.db 9 | 10 | # vscode 11 | **/.vscode 12 | 13 | # codec 14 | core 15 | 16 | # npm 17 | **/node_modules 18 | **/.npmrc 19 | **/.npm 20 | 21 | # Log files 22 | **/logs 23 | *.log 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | lerna-debug.log* 28 | 29 | # apps 30 | *.app 31 | *.exe 32 | *.war 33 | 34 | # media files 35 | *.mp4 36 | *.tiff 37 | *.avi 38 | *.flv 39 | *.mov 40 | *.wmv 41 | 42 | # typescript 43 | dist 44 | src 45 | !src/**/*.ts 46 | 47 | # git 48 | !.keep 49 | !.gitkeep 50 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # global ignore 2 | * 3 | 4 | # exe scripts 5 | !bin 6 | 7 | # npm configs 8 | !package-lock.json 9 | !package.json 10 | 11 | # project infos 12 | !README.md 13 | !LICENCE 14 | 15 | # dist 16 | !dist/**/* 17 | dist/**/*.d.ts.map 18 | dist/**/*.js.map 19 | 20 | # tests 21 | dist/test/**/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 majo418 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cmdy (deprecated) 2 | 3 | ![CI/CD](https://github.com/majo418/cmdy/workflows/Publish/badge.svg) 4 | ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) 5 | ![typescript](https://img.shields.io/badge/dynamic/json?style=plastic&color=blue&label=Typescript&prefix=v&query=devDependencies.typescript&url=https%3A%2F%2Fraw.githubusercontent.com%2Fmajo418%2Fcmdy%2Fmain%2Fpackage.json) 6 | ![npm](https://img.shields.io/npm/v/cmdy.svg?style=plastic&logo=npm&color=red) 7 | ![github](https://img.shields.io/badge/dynamic/json?style=plastic&color=darkviolet&label=GitHub&prefix=v&query=version&url=https%3A%2F%2Fraw.githubusercontent.com%2Fmajo418%2Fcmdy%2Fmain%2Fpackage.json) 8 | 9 | ![](https://img.shields.io/badge/dynamic/json?color=green&label=watchers&query=watchers&suffix=x&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fmajo418%2Fcmdy) 10 | ![](https://img.shields.io/badge/dynamic/json?color=yellow&label=stars&query=stargazers_count&suffix=x&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fmajo418%2Fcmdy) 11 | ![](https://img.shields.io/badge/dynamic/json?color=orange&label=subscribers&query=subscribers_count&suffix=x&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fmajo418%2Fcmdy) 12 | ![](https://img.shields.io/badge/dynamic/json?color=navy&label=forks&query=forks&suffix=x&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fmajo418%2Fcmdy) 13 | ![](https://img.shields.io/badge/dynamic/json?color=darkred&label=open%20issues&query=open_issues&suffix=x&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fmajo418%2Fcmdy) 14 | 15 | # table of contents 16 | - [cmdy](#cmdy) 17 | - [table of contents](#table-of-contents) 18 | - [about](#about) 19 | - [Features](#features) 20 | - [General](#general) 21 | - [cmd (sub cmd)](#cmd-sub-cmd) 22 | - [flags](#flags) 23 | - [Getting started](#getting-started) 24 | - [1. Install package](#1-install-package) 25 | - [2. Add example code](#2-add-example-code) 26 | - [npm scripts](#npm-scripts) 27 | - [use](#use) 28 | - [base scripts](#base-scripts) 29 | - [watch mode](#watch-mode) 30 | - [contribution](#contribution) 31 | 32 | # about 33 | "cmdy" is a node js cmd argument framework that looks like the docker cli tool. 34 | 35 | # Features 36 | 37 | ## General 38 | - root and sub commands 39 | - differend cmd callbacks 40 | - state and value flags 41 | 42 | ## cmd (sub cmd) 43 | - own flags 44 | - global gflas 45 | - premade or custom help function/generator 46 | - cmd groups 47 | 48 | ## flags 49 | - value flags with types 50 | - default values 51 | - aliases 52 | - shorthand 53 | 54 | # Getting started 55 | ## 1. Install package 56 | ```sh 57 | npm i cmdy 58 | ``` 59 | 60 | ## 2. Add example code 61 | ```ts 62 | import { Flag, parseCmd, CmdDefinition } from "../src/index" 63 | 64 | const force: Flag = { 65 | name: "force", 66 | description: "The force flag", 67 | } 68 | 69 | const port: Flag = { 70 | name: "port", 71 | description: "The port flag", 72 | shorthand: "p", 73 | types: ["number"] 74 | } 75 | 76 | const verbose: Flag = { 77 | name: "verbose", 78 | description: "The verbose flag", 79 | shorthand: "V", 80 | } 81 | 82 | const version: Flag = { 83 | name: "version", 84 | description: "The verbose flag", 85 | alias: ["v", "ve", "ver", "vers", "versi", "versio"], 86 | shorthand: "v", 87 | } 88 | 89 | const ps: CmdDefinition = { 90 | name: "ps", 91 | description: "The ps command", 92 | flags: [ 93 | port 94 | ], 95 | allowUnknownArgs: true, 96 | exe: async (res) => console.log("ps: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 97 | } 98 | 99 | const start: CmdDefinition = { 100 | name: "start", 101 | description: "The start command", 102 | flags: [ 103 | port 104 | ], 105 | exe: async (res) => console.log("start: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 106 | } 107 | 108 | const stop: CmdDefinition = { 109 | name: "stop", 110 | description: "The stop command", 111 | flags: [ 112 | force 113 | ], 114 | exe: async (res) => console.log("stop: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 115 | } 116 | 117 | const root: CmdDefinition = { 118 | name: "testcmd", 119 | description: "The root testcmd command", 120 | cmds: [ 121 | start, 122 | stop, 123 | ps, 124 | ], 125 | flags: [ 126 | version 127 | ], 128 | //exe: async () => console.log("asdasdd") 129 | } 130 | 131 | parseCmd({ 132 | cmd: root, 133 | globalFlags: [ 134 | verbose 135 | ] 136 | }).exe() 137 | ``` 138 | 139 | # npm scripts 140 | The npm scripts are made for linux but can also work on mac and windows. 141 | ## use 142 | You can run npm scripts in the project folder like this: 143 | ```sh 144 | npm run 145 | ``` 146 | Here is an example: 147 | ```sh 148 | npm run test 149 | ``` 150 | 151 | ## base scripts 152 | You can find all npm scripts in the `package.json` file. 153 | This is a list of the most important npm scripts: 154 | - test // test the app 155 | - build // build the app 156 | - exec // run the app 157 | - start // build and run the app 158 | 159 | ## watch mode 160 | Like this example you can run all npm scripts in watch mode: 161 | ```sh 162 | npm run start:watch 163 | ``` 164 | 165 | # contribution 166 | - 1. fork the project 167 | - 2. implement your idea 168 | - 3. create a pull/merge request 169 | ```ts 170 | // please create seperated forks for different kind of featues/ideas/structure changes/implementations 171 | ``` 172 | 173 | --- 174 | **cya ;3** 175 | *by majo418* 176 | -------------------------------------------------------------------------------- /example/docker: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node ../node_modules/ts-node/dist/bin ./docker.ts $@ -------------------------------------------------------------------------------- /example/docker.ts: -------------------------------------------------------------------------------- 1 | import { Flag, parseCmd, CmdDefinition, CmdError } from "../src/index" 2 | 3 | const force: Flag = { 4 | name: "force", 5 | description: "The force flag", 6 | } 7 | 8 | const port: Flag = { 9 | name: "port", 10 | description: "The port flag", 11 | shorthand: "p", 12 | types: ["number"] 13 | } 14 | 15 | const publish: Flag = { 16 | name: "publish", 17 | description: "The publish flag", 18 | shorthand: "P", 19 | types: ["string"] 20 | } 21 | 22 | const volume: Flag = { 23 | name: "volume", 24 | description: "The volume flag", 25 | shorthand: "v", 26 | types: ["string"] 27 | } 28 | 29 | const removeF: Flag = { 30 | name: "remove", 31 | description: "The remove flag", 32 | alias: ["rm"], 33 | } 34 | 35 | const verbose: Flag = { 36 | name: "verbose", 37 | description: "The verbose flag", 38 | shorthand: "V", 39 | } 40 | 41 | const version: Flag = { 42 | name: "version", 43 | description: "The verbose flag", 44 | alias: ["v", "ve", "ver", "vers", "versi", "versio"], 45 | shorthand: "v", 46 | } 47 | 48 | const run: CmdDefinition = { 49 | name: "run", 50 | description: "The run command", 51 | group: "management", 52 | flags: [ 53 | removeF, 54 | publish, 55 | volume, 56 | port 57 | ], 58 | allowUnknownArgs: true, 59 | exe: async (res) => console.log("cmd: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 60 | } 61 | 62 | const start: CmdDefinition = { 63 | name: "start", 64 | description: "The start command", 65 | group: "management", 66 | flags: [ 67 | removeF, 68 | port 69 | ], 70 | exe: async (res) => console.log("cmd: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 71 | } 72 | 73 | const create: CmdDefinition = { 74 | name: "create", 75 | description: "The create command", 76 | group: "management", 77 | flags: [ 78 | volume, 79 | publish, 80 | removeF 81 | ], 82 | exe: async (res) => console.log("cmd: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 83 | } 84 | 85 | const remove: CmdDefinition = { 86 | name: "remove", 87 | description: "The remove command", 88 | group: "management", 89 | flags: [ 90 | force 91 | ], 92 | exe: async (res) => console.log("cmd: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 93 | } 94 | 95 | const stop: CmdDefinition = { 96 | name: "stop", 97 | description: "The stop command", 98 | group: "management", 99 | flags: [ 100 | force 101 | ], 102 | exe: async (res) => console.log("cmd: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 103 | } 104 | 105 | const search: CmdDefinition = { 106 | name: "search", 107 | description: "The search command", 108 | flags: [ 109 | ], 110 | exe: async (res) => console.log("cmd: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 111 | } 112 | 113 | const wait: CmdDefinition = { 114 | name: "wait", 115 | description: "The wait command", 116 | flags: [ 117 | ], 118 | exe: async (res) => console.log("cmd: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 119 | } 120 | 121 | const events: CmdDefinition = { 122 | name: "events", 123 | description: "The wait command", 124 | flags: [ 125 | ], 126 | exe: async (res) => console.log("cmd: ", res.cmd.name + "\nres-data:\n", res.flags, res.valueFlags) 127 | } 128 | 129 | const root: CmdDefinition = { 130 | name: "docker", 131 | description: "The root docker command", 132 | cmds: [ 133 | run, 134 | start, 135 | stop, 136 | create, 137 | remove, 138 | events, 139 | wait, 140 | search 141 | ], 142 | //exe: async () => console.log("asdasdd") 143 | } 144 | 145 | parseCmd({ 146 | cmd: root, 147 | globalFlags: [ 148 | verbose, 149 | version 150 | ] 151 | }).exe() 152 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cmdy", 3 | "version": "1.4.5", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "cmdy", 9 | "version": "1.4.5", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@types/chai": "4", 13 | "@types/mocha": "9", 14 | "@types/node": "16", 15 | "chai": "4", 16 | "mocha": "9", 17 | "nodemon": "2", 18 | "ts-node": "10", 19 | "typescript": "4" 20 | } 21 | }, 22 | "node_modules/@cspotcode/source-map-support": { 23 | "version": "0.8.1", 24 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", 25 | "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", 26 | "dev": true, 27 | "dependencies": { 28 | "@jridgewell/trace-mapping": "0.3.9" 29 | }, 30 | "engines": { 31 | "node": ">=12" 32 | } 33 | }, 34 | "node_modules/@jridgewell/resolve-uri": { 35 | "version": "3.1.0", 36 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", 37 | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", 38 | "dev": true, 39 | "engines": { 40 | "node": ">=6.0.0" 41 | } 42 | }, 43 | "node_modules/@jridgewell/sourcemap-codec": { 44 | "version": "1.4.14", 45 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", 46 | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", 47 | "dev": true 48 | }, 49 | "node_modules/@jridgewell/trace-mapping": { 50 | "version": "0.3.9", 51 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", 52 | "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", 53 | "dev": true, 54 | "dependencies": { 55 | "@jridgewell/resolve-uri": "^3.0.3", 56 | "@jridgewell/sourcemap-codec": "^1.4.10" 57 | } 58 | }, 59 | "node_modules/@tsconfig/node10": { 60 | "version": "1.0.9", 61 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", 62 | "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", 63 | "dev": true 64 | }, 65 | "node_modules/@tsconfig/node12": { 66 | "version": "1.0.11", 67 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", 68 | "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", 69 | "dev": true 70 | }, 71 | "node_modules/@tsconfig/node14": { 72 | "version": "1.0.3", 73 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", 74 | "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", 75 | "dev": true 76 | }, 77 | "node_modules/@tsconfig/node16": { 78 | "version": "1.0.3", 79 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", 80 | "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", 81 | "dev": true 82 | }, 83 | "node_modules/@types/chai": { 84 | "version": "4.3.4", 85 | "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", 86 | "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", 87 | "dev": true 88 | }, 89 | "node_modules/@types/mocha": { 90 | "version": "9.1.1", 91 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", 92 | "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", 93 | "dev": true 94 | }, 95 | "node_modules/@types/node": { 96 | "version": "16.18.10", 97 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", 98 | "integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==", 99 | "dev": true 100 | }, 101 | "node_modules/@ungap/promise-all-settled": { 102 | "version": "1.1.2", 103 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 104 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 105 | "dev": true 106 | }, 107 | "node_modules/abbrev": { 108 | "version": "1.1.1", 109 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 110 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 111 | "dev": true 112 | }, 113 | "node_modules/acorn": { 114 | "version": "8.8.1", 115 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", 116 | "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", 117 | "dev": true, 118 | "bin": { 119 | "acorn": "bin/acorn" 120 | }, 121 | "engines": { 122 | "node": ">=0.4.0" 123 | } 124 | }, 125 | "node_modules/acorn-walk": { 126 | "version": "8.2.0", 127 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", 128 | "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", 129 | "dev": true, 130 | "engines": { 131 | "node": ">=0.4.0" 132 | } 133 | }, 134 | "node_modules/ansi-colors": { 135 | "version": "4.1.1", 136 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 137 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 138 | "dev": true, 139 | "engines": { 140 | "node": ">=6" 141 | } 142 | }, 143 | "node_modules/ansi-regex": { 144 | "version": "5.0.1", 145 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 146 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 147 | "dev": true, 148 | "engines": { 149 | "node": ">=8" 150 | } 151 | }, 152 | "node_modules/ansi-styles": { 153 | "version": "4.3.0", 154 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 155 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 156 | "dev": true, 157 | "dependencies": { 158 | "color-convert": "^2.0.1" 159 | }, 160 | "engines": { 161 | "node": ">=8" 162 | }, 163 | "funding": { 164 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 165 | } 166 | }, 167 | "node_modules/anymatch": { 168 | "version": "3.1.3", 169 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 170 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 171 | "dev": true, 172 | "dependencies": { 173 | "normalize-path": "^3.0.0", 174 | "picomatch": "^2.0.4" 175 | }, 176 | "engines": { 177 | "node": ">= 8" 178 | } 179 | }, 180 | "node_modules/arg": { 181 | "version": "4.1.3", 182 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 183 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 184 | "dev": true 185 | }, 186 | "node_modules/argparse": { 187 | "version": "2.0.1", 188 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 189 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 190 | "dev": true 191 | }, 192 | "node_modules/assertion-error": { 193 | "version": "1.1.0", 194 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 195 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 196 | "dev": true, 197 | "engines": { 198 | "node": "*" 199 | } 200 | }, 201 | "node_modules/balanced-match": { 202 | "version": "1.0.2", 203 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 204 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 205 | "dev": true 206 | }, 207 | "node_modules/binary-extensions": { 208 | "version": "2.2.0", 209 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 210 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 211 | "dev": true, 212 | "engines": { 213 | "node": ">=8" 214 | } 215 | }, 216 | "node_modules/brace-expansion": { 217 | "version": "1.1.11", 218 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 219 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 220 | "dev": true, 221 | "dependencies": { 222 | "balanced-match": "^1.0.0", 223 | "concat-map": "0.0.1" 224 | } 225 | }, 226 | "node_modules/braces": { 227 | "version": "3.0.2", 228 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 229 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 230 | "dev": true, 231 | "dependencies": { 232 | "fill-range": "^7.0.1" 233 | }, 234 | "engines": { 235 | "node": ">=8" 236 | } 237 | }, 238 | "node_modules/browser-stdout": { 239 | "version": "1.3.1", 240 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 241 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 242 | "dev": true 243 | }, 244 | "node_modules/camelcase": { 245 | "version": "6.3.0", 246 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 247 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 248 | "dev": true, 249 | "engines": { 250 | "node": ">=10" 251 | }, 252 | "funding": { 253 | "url": "https://github.com/sponsors/sindresorhus" 254 | } 255 | }, 256 | "node_modules/chai": { 257 | "version": "4.3.7", 258 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", 259 | "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", 260 | "dev": true, 261 | "dependencies": { 262 | "assertion-error": "^1.1.0", 263 | "check-error": "^1.0.2", 264 | "deep-eql": "^4.1.2", 265 | "get-func-name": "^2.0.0", 266 | "loupe": "^2.3.1", 267 | "pathval": "^1.1.1", 268 | "type-detect": "^4.0.5" 269 | }, 270 | "engines": { 271 | "node": ">=4" 272 | } 273 | }, 274 | "node_modules/chalk": { 275 | "version": "4.1.2", 276 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 277 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 278 | "dev": true, 279 | "dependencies": { 280 | "ansi-styles": "^4.1.0", 281 | "supports-color": "^7.1.0" 282 | }, 283 | "engines": { 284 | "node": ">=10" 285 | }, 286 | "funding": { 287 | "url": "https://github.com/chalk/chalk?sponsor=1" 288 | } 289 | }, 290 | "node_modules/chalk/node_modules/supports-color": { 291 | "version": "7.2.0", 292 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 293 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 294 | "dev": true, 295 | "dependencies": { 296 | "has-flag": "^4.0.0" 297 | }, 298 | "engines": { 299 | "node": ">=8" 300 | } 301 | }, 302 | "node_modules/check-error": { 303 | "version": "1.0.2", 304 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 305 | "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", 306 | "dev": true, 307 | "engines": { 308 | "node": "*" 309 | } 310 | }, 311 | "node_modules/chokidar": { 312 | "version": "3.5.3", 313 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 314 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 315 | "dev": true, 316 | "funding": [ 317 | { 318 | "type": "individual", 319 | "url": "https://paulmillr.com/funding/" 320 | } 321 | ], 322 | "dependencies": { 323 | "anymatch": "~3.1.2", 324 | "braces": "~3.0.2", 325 | "glob-parent": "~5.1.2", 326 | "is-binary-path": "~2.1.0", 327 | "is-glob": "~4.0.1", 328 | "normalize-path": "~3.0.0", 329 | "readdirp": "~3.6.0" 330 | }, 331 | "engines": { 332 | "node": ">= 8.10.0" 333 | }, 334 | "optionalDependencies": { 335 | "fsevents": "~2.3.2" 336 | } 337 | }, 338 | "node_modules/cliui": { 339 | "version": "7.0.4", 340 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 341 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 342 | "dev": true, 343 | "dependencies": { 344 | "string-width": "^4.2.0", 345 | "strip-ansi": "^6.0.0", 346 | "wrap-ansi": "^7.0.0" 347 | } 348 | }, 349 | "node_modules/color-convert": { 350 | "version": "2.0.1", 351 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 352 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 353 | "dev": true, 354 | "dependencies": { 355 | "color-name": "~1.1.4" 356 | }, 357 | "engines": { 358 | "node": ">=7.0.0" 359 | } 360 | }, 361 | "node_modules/color-name": { 362 | "version": "1.1.4", 363 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 364 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 365 | "dev": true 366 | }, 367 | "node_modules/concat-map": { 368 | "version": "0.0.1", 369 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 370 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 371 | "dev": true 372 | }, 373 | "node_modules/create-require": { 374 | "version": "1.1.1", 375 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", 376 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", 377 | "dev": true 378 | }, 379 | "node_modules/debug": { 380 | "version": "4.3.3", 381 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 382 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 383 | "dev": true, 384 | "dependencies": { 385 | "ms": "2.1.2" 386 | }, 387 | "engines": { 388 | "node": ">=6.0" 389 | }, 390 | "peerDependenciesMeta": { 391 | "supports-color": { 392 | "optional": true 393 | } 394 | } 395 | }, 396 | "node_modules/debug/node_modules/ms": { 397 | "version": "2.1.2", 398 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 399 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 400 | "dev": true 401 | }, 402 | "node_modules/decamelize": { 403 | "version": "4.0.0", 404 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 405 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 406 | "dev": true, 407 | "engines": { 408 | "node": ">=10" 409 | }, 410 | "funding": { 411 | "url": "https://github.com/sponsors/sindresorhus" 412 | } 413 | }, 414 | "node_modules/deep-eql": { 415 | "version": "4.1.3", 416 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", 417 | "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", 418 | "dev": true, 419 | "dependencies": { 420 | "type-detect": "^4.0.0" 421 | }, 422 | "engines": { 423 | "node": ">=6" 424 | } 425 | }, 426 | "node_modules/diff": { 427 | "version": "5.0.0", 428 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 429 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 430 | "dev": true, 431 | "engines": { 432 | "node": ">=0.3.1" 433 | } 434 | }, 435 | "node_modules/emoji-regex": { 436 | "version": "8.0.0", 437 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 438 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 439 | "dev": true 440 | }, 441 | "node_modules/escalade": { 442 | "version": "3.1.1", 443 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 444 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 445 | "dev": true, 446 | "engines": { 447 | "node": ">=6" 448 | } 449 | }, 450 | "node_modules/escape-string-regexp": { 451 | "version": "4.0.0", 452 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 453 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 454 | "dev": true, 455 | "engines": { 456 | "node": ">=10" 457 | }, 458 | "funding": { 459 | "url": "https://github.com/sponsors/sindresorhus" 460 | } 461 | }, 462 | "node_modules/fill-range": { 463 | "version": "7.0.1", 464 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 465 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 466 | "dev": true, 467 | "dependencies": { 468 | "to-regex-range": "^5.0.1" 469 | }, 470 | "engines": { 471 | "node": ">=8" 472 | } 473 | }, 474 | "node_modules/find-up": { 475 | "version": "5.0.0", 476 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 477 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 478 | "dev": true, 479 | "dependencies": { 480 | "locate-path": "^6.0.0", 481 | "path-exists": "^4.0.0" 482 | }, 483 | "engines": { 484 | "node": ">=10" 485 | }, 486 | "funding": { 487 | "url": "https://github.com/sponsors/sindresorhus" 488 | } 489 | }, 490 | "node_modules/flat": { 491 | "version": "5.0.2", 492 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 493 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 494 | "dev": true, 495 | "bin": { 496 | "flat": "cli.js" 497 | } 498 | }, 499 | "node_modules/fs.realpath": { 500 | "version": "1.0.0", 501 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 502 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 503 | "dev": true 504 | }, 505 | "node_modules/fsevents": { 506 | "version": "2.3.2", 507 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 508 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 509 | "dev": true, 510 | "hasInstallScript": true, 511 | "optional": true, 512 | "os": [ 513 | "darwin" 514 | ], 515 | "engines": { 516 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 517 | } 518 | }, 519 | "node_modules/get-caller-file": { 520 | "version": "2.0.5", 521 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 522 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 523 | "dev": true, 524 | "engines": { 525 | "node": "6.* || 8.* || >= 10.*" 526 | } 527 | }, 528 | "node_modules/get-func-name": { 529 | "version": "2.0.0", 530 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 531 | "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", 532 | "dev": true, 533 | "engines": { 534 | "node": "*" 535 | } 536 | }, 537 | "node_modules/glob": { 538 | "version": "7.2.0", 539 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 540 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 541 | "dev": true, 542 | "dependencies": { 543 | "fs.realpath": "^1.0.0", 544 | "inflight": "^1.0.4", 545 | "inherits": "2", 546 | "minimatch": "^3.0.4", 547 | "once": "^1.3.0", 548 | "path-is-absolute": "^1.0.0" 549 | }, 550 | "engines": { 551 | "node": "*" 552 | }, 553 | "funding": { 554 | "url": "https://github.com/sponsors/isaacs" 555 | } 556 | }, 557 | "node_modules/glob-parent": { 558 | "version": "5.1.2", 559 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 560 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 561 | "dev": true, 562 | "dependencies": { 563 | "is-glob": "^4.0.1" 564 | }, 565 | "engines": { 566 | "node": ">= 6" 567 | } 568 | }, 569 | "node_modules/glob/node_modules/minimatch": { 570 | "version": "3.1.2", 571 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 572 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 573 | "dev": true, 574 | "dependencies": { 575 | "brace-expansion": "^1.1.7" 576 | }, 577 | "engines": { 578 | "node": "*" 579 | } 580 | }, 581 | "node_modules/growl": { 582 | "version": "1.10.5", 583 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 584 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 585 | "dev": true, 586 | "engines": { 587 | "node": ">=4.x" 588 | } 589 | }, 590 | "node_modules/has-flag": { 591 | "version": "4.0.0", 592 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 593 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 594 | "dev": true, 595 | "engines": { 596 | "node": ">=8" 597 | } 598 | }, 599 | "node_modules/he": { 600 | "version": "1.2.0", 601 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 602 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 603 | "dev": true, 604 | "bin": { 605 | "he": "bin/he" 606 | } 607 | }, 608 | "node_modules/ignore-by-default": { 609 | "version": "1.0.1", 610 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 611 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", 612 | "dev": true 613 | }, 614 | "node_modules/inflight": { 615 | "version": "1.0.6", 616 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 617 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 618 | "dev": true, 619 | "dependencies": { 620 | "once": "^1.3.0", 621 | "wrappy": "1" 622 | } 623 | }, 624 | "node_modules/inherits": { 625 | "version": "2.0.4", 626 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 627 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 628 | "dev": true 629 | }, 630 | "node_modules/is-binary-path": { 631 | "version": "2.1.0", 632 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 633 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 634 | "dev": true, 635 | "dependencies": { 636 | "binary-extensions": "^2.0.0" 637 | }, 638 | "engines": { 639 | "node": ">=8" 640 | } 641 | }, 642 | "node_modules/is-extglob": { 643 | "version": "2.1.1", 644 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 645 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 646 | "dev": true, 647 | "engines": { 648 | "node": ">=0.10.0" 649 | } 650 | }, 651 | "node_modules/is-fullwidth-code-point": { 652 | "version": "3.0.0", 653 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 654 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 655 | "dev": true, 656 | "engines": { 657 | "node": ">=8" 658 | } 659 | }, 660 | "node_modules/is-glob": { 661 | "version": "4.0.3", 662 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 663 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 664 | "dev": true, 665 | "dependencies": { 666 | "is-extglob": "^2.1.1" 667 | }, 668 | "engines": { 669 | "node": ">=0.10.0" 670 | } 671 | }, 672 | "node_modules/is-number": { 673 | "version": "7.0.0", 674 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 675 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 676 | "dev": true, 677 | "engines": { 678 | "node": ">=0.12.0" 679 | } 680 | }, 681 | "node_modules/is-plain-obj": { 682 | "version": "2.1.0", 683 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 684 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 685 | "dev": true, 686 | "engines": { 687 | "node": ">=8" 688 | } 689 | }, 690 | "node_modules/is-unicode-supported": { 691 | "version": "0.1.0", 692 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 693 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 694 | "dev": true, 695 | "engines": { 696 | "node": ">=10" 697 | }, 698 | "funding": { 699 | "url": "https://github.com/sponsors/sindresorhus" 700 | } 701 | }, 702 | "node_modules/isexe": { 703 | "version": "2.0.0", 704 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 705 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 706 | "dev": true 707 | }, 708 | "node_modules/js-yaml": { 709 | "version": "4.1.0", 710 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 711 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 712 | "dev": true, 713 | "dependencies": { 714 | "argparse": "^2.0.1" 715 | }, 716 | "bin": { 717 | "js-yaml": "bin/js-yaml.js" 718 | } 719 | }, 720 | "node_modules/locate-path": { 721 | "version": "6.0.0", 722 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 723 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 724 | "dev": true, 725 | "dependencies": { 726 | "p-locate": "^5.0.0" 727 | }, 728 | "engines": { 729 | "node": ">=10" 730 | }, 731 | "funding": { 732 | "url": "https://github.com/sponsors/sindresorhus" 733 | } 734 | }, 735 | "node_modules/log-symbols": { 736 | "version": "4.1.0", 737 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 738 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 739 | "dev": true, 740 | "dependencies": { 741 | "chalk": "^4.1.0", 742 | "is-unicode-supported": "^0.1.0" 743 | }, 744 | "engines": { 745 | "node": ">=10" 746 | }, 747 | "funding": { 748 | "url": "https://github.com/sponsors/sindresorhus" 749 | } 750 | }, 751 | "node_modules/loupe": { 752 | "version": "2.3.6", 753 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", 754 | "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", 755 | "dev": true, 756 | "dependencies": { 757 | "get-func-name": "^2.0.0" 758 | } 759 | }, 760 | "node_modules/make-error": { 761 | "version": "1.3.6", 762 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 763 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 764 | "dev": true 765 | }, 766 | "node_modules/minimatch": { 767 | "version": "4.2.1", 768 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", 769 | "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", 770 | "dev": true, 771 | "dependencies": { 772 | "brace-expansion": "^1.1.7" 773 | }, 774 | "engines": { 775 | "node": ">=10" 776 | } 777 | }, 778 | "node_modules/mocha": { 779 | "version": "9.2.2", 780 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", 781 | "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", 782 | "dev": true, 783 | "dependencies": { 784 | "@ungap/promise-all-settled": "1.1.2", 785 | "ansi-colors": "4.1.1", 786 | "browser-stdout": "1.3.1", 787 | "chokidar": "3.5.3", 788 | "debug": "4.3.3", 789 | "diff": "5.0.0", 790 | "escape-string-regexp": "4.0.0", 791 | "find-up": "5.0.0", 792 | "glob": "7.2.0", 793 | "growl": "1.10.5", 794 | "he": "1.2.0", 795 | "js-yaml": "4.1.0", 796 | "log-symbols": "4.1.0", 797 | "minimatch": "4.2.1", 798 | "ms": "2.1.3", 799 | "nanoid": "3.3.1", 800 | "serialize-javascript": "6.0.0", 801 | "strip-json-comments": "3.1.1", 802 | "supports-color": "8.1.1", 803 | "which": "2.0.2", 804 | "workerpool": "6.2.0", 805 | "yargs": "16.2.0", 806 | "yargs-parser": "20.2.4", 807 | "yargs-unparser": "2.0.0" 808 | }, 809 | "bin": { 810 | "_mocha": "bin/_mocha", 811 | "mocha": "bin/mocha" 812 | }, 813 | "engines": { 814 | "node": ">= 12.0.0" 815 | }, 816 | "funding": { 817 | "type": "opencollective", 818 | "url": "https://opencollective.com/mochajs" 819 | } 820 | }, 821 | "node_modules/ms": { 822 | "version": "2.1.3", 823 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 824 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 825 | "dev": true 826 | }, 827 | "node_modules/nanoid": { 828 | "version": "3.3.1", 829 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", 830 | "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", 831 | "dev": true, 832 | "bin": { 833 | "nanoid": "bin/nanoid.cjs" 834 | }, 835 | "engines": { 836 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 837 | } 838 | }, 839 | "node_modules/nodemon": { 840 | "version": "2.0.20", 841 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", 842 | "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", 843 | "dev": true, 844 | "dependencies": { 845 | "chokidar": "^3.5.2", 846 | "debug": "^3.2.7", 847 | "ignore-by-default": "^1.0.1", 848 | "minimatch": "^3.1.2", 849 | "pstree.remy": "^1.1.8", 850 | "semver": "^5.7.1", 851 | "simple-update-notifier": "^1.0.7", 852 | "supports-color": "^5.5.0", 853 | "touch": "^3.1.0", 854 | "undefsafe": "^2.0.5" 855 | }, 856 | "bin": { 857 | "nodemon": "bin/nodemon.js" 858 | }, 859 | "engines": { 860 | "node": ">=8.10.0" 861 | }, 862 | "funding": { 863 | "type": "opencollective", 864 | "url": "https://opencollective.com/nodemon" 865 | } 866 | }, 867 | "node_modules/nodemon/node_modules/debug": { 868 | "version": "3.2.7", 869 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 870 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 871 | "dev": true, 872 | "dependencies": { 873 | "ms": "^2.1.1" 874 | } 875 | }, 876 | "node_modules/nodemon/node_modules/has-flag": { 877 | "version": "3.0.0", 878 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 879 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 880 | "dev": true, 881 | "engines": { 882 | "node": ">=4" 883 | } 884 | }, 885 | "node_modules/nodemon/node_modules/minimatch": { 886 | "version": "3.1.2", 887 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 888 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 889 | "dev": true, 890 | "dependencies": { 891 | "brace-expansion": "^1.1.7" 892 | }, 893 | "engines": { 894 | "node": "*" 895 | } 896 | }, 897 | "node_modules/nodemon/node_modules/supports-color": { 898 | "version": "5.5.0", 899 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 900 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 901 | "dev": true, 902 | "dependencies": { 903 | "has-flag": "^3.0.0" 904 | }, 905 | "engines": { 906 | "node": ">=4" 907 | } 908 | }, 909 | "node_modules/nopt": { 910 | "version": "1.0.10", 911 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 912 | "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", 913 | "dev": true, 914 | "dependencies": { 915 | "abbrev": "1" 916 | }, 917 | "bin": { 918 | "nopt": "bin/nopt.js" 919 | }, 920 | "engines": { 921 | "node": "*" 922 | } 923 | }, 924 | "node_modules/normalize-path": { 925 | "version": "3.0.0", 926 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 927 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 928 | "dev": true, 929 | "engines": { 930 | "node": ">=0.10.0" 931 | } 932 | }, 933 | "node_modules/once": { 934 | "version": "1.4.0", 935 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 936 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 937 | "dev": true, 938 | "dependencies": { 939 | "wrappy": "1" 940 | } 941 | }, 942 | "node_modules/p-limit": { 943 | "version": "3.1.0", 944 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 945 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 946 | "dev": true, 947 | "dependencies": { 948 | "yocto-queue": "^0.1.0" 949 | }, 950 | "engines": { 951 | "node": ">=10" 952 | }, 953 | "funding": { 954 | "url": "https://github.com/sponsors/sindresorhus" 955 | } 956 | }, 957 | "node_modules/p-locate": { 958 | "version": "5.0.0", 959 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 960 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 961 | "dev": true, 962 | "dependencies": { 963 | "p-limit": "^3.0.2" 964 | }, 965 | "engines": { 966 | "node": ">=10" 967 | }, 968 | "funding": { 969 | "url": "https://github.com/sponsors/sindresorhus" 970 | } 971 | }, 972 | "node_modules/path-exists": { 973 | "version": "4.0.0", 974 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 975 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 976 | "dev": true, 977 | "engines": { 978 | "node": ">=8" 979 | } 980 | }, 981 | "node_modules/path-is-absolute": { 982 | "version": "1.0.1", 983 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 984 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 985 | "dev": true, 986 | "engines": { 987 | "node": ">=0.10.0" 988 | } 989 | }, 990 | "node_modules/pathval": { 991 | "version": "1.1.1", 992 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 993 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 994 | "dev": true, 995 | "engines": { 996 | "node": "*" 997 | } 998 | }, 999 | "node_modules/picomatch": { 1000 | "version": "2.3.1", 1001 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1002 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1003 | "dev": true, 1004 | "engines": { 1005 | "node": ">=8.6" 1006 | }, 1007 | "funding": { 1008 | "url": "https://github.com/sponsors/jonschlinkert" 1009 | } 1010 | }, 1011 | "node_modules/pstree.remy": { 1012 | "version": "1.1.8", 1013 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 1014 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 1015 | "dev": true 1016 | }, 1017 | "node_modules/randombytes": { 1018 | "version": "2.1.0", 1019 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1020 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1021 | "dev": true, 1022 | "dependencies": { 1023 | "safe-buffer": "^5.1.0" 1024 | } 1025 | }, 1026 | "node_modules/readdirp": { 1027 | "version": "3.6.0", 1028 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1029 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1030 | "dev": true, 1031 | "dependencies": { 1032 | "picomatch": "^2.2.1" 1033 | }, 1034 | "engines": { 1035 | "node": ">=8.10.0" 1036 | } 1037 | }, 1038 | "node_modules/require-directory": { 1039 | "version": "2.1.1", 1040 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1041 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 1042 | "dev": true, 1043 | "engines": { 1044 | "node": ">=0.10.0" 1045 | } 1046 | }, 1047 | "node_modules/safe-buffer": { 1048 | "version": "5.2.1", 1049 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1050 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1051 | "dev": true, 1052 | "funding": [ 1053 | { 1054 | "type": "github", 1055 | "url": "https://github.com/sponsors/feross" 1056 | }, 1057 | { 1058 | "type": "patreon", 1059 | "url": "https://www.patreon.com/feross" 1060 | }, 1061 | { 1062 | "type": "consulting", 1063 | "url": "https://feross.org/support" 1064 | } 1065 | ] 1066 | }, 1067 | "node_modules/semver": { 1068 | "version": "5.7.1", 1069 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1070 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1071 | "dev": true, 1072 | "bin": { 1073 | "semver": "bin/semver" 1074 | } 1075 | }, 1076 | "node_modules/serialize-javascript": { 1077 | "version": "6.0.0", 1078 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 1079 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 1080 | "dev": true, 1081 | "dependencies": { 1082 | "randombytes": "^2.1.0" 1083 | } 1084 | }, 1085 | "node_modules/simple-update-notifier": { 1086 | "version": "1.1.0", 1087 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", 1088 | "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", 1089 | "dev": true, 1090 | "dependencies": { 1091 | "semver": "~7.0.0" 1092 | }, 1093 | "engines": { 1094 | "node": ">=8.10.0" 1095 | } 1096 | }, 1097 | "node_modules/simple-update-notifier/node_modules/semver": { 1098 | "version": "7.0.0", 1099 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", 1100 | "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", 1101 | "dev": true, 1102 | "bin": { 1103 | "semver": "bin/semver.js" 1104 | } 1105 | }, 1106 | "node_modules/string-width": { 1107 | "version": "4.2.3", 1108 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1109 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1110 | "dev": true, 1111 | "dependencies": { 1112 | "emoji-regex": "^8.0.0", 1113 | "is-fullwidth-code-point": "^3.0.0", 1114 | "strip-ansi": "^6.0.1" 1115 | }, 1116 | "engines": { 1117 | "node": ">=8" 1118 | } 1119 | }, 1120 | "node_modules/strip-ansi": { 1121 | "version": "6.0.1", 1122 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1123 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1124 | "dev": true, 1125 | "dependencies": { 1126 | "ansi-regex": "^5.0.1" 1127 | }, 1128 | "engines": { 1129 | "node": ">=8" 1130 | } 1131 | }, 1132 | "node_modules/strip-json-comments": { 1133 | "version": "3.1.1", 1134 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1135 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1136 | "dev": true, 1137 | "engines": { 1138 | "node": ">=8" 1139 | }, 1140 | "funding": { 1141 | "url": "https://github.com/sponsors/sindresorhus" 1142 | } 1143 | }, 1144 | "node_modules/supports-color": { 1145 | "version": "8.1.1", 1146 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 1147 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 1148 | "dev": true, 1149 | "dependencies": { 1150 | "has-flag": "^4.0.0" 1151 | }, 1152 | "engines": { 1153 | "node": ">=10" 1154 | }, 1155 | "funding": { 1156 | "url": "https://github.com/chalk/supports-color?sponsor=1" 1157 | } 1158 | }, 1159 | "node_modules/to-regex-range": { 1160 | "version": "5.0.1", 1161 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1162 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1163 | "dev": true, 1164 | "dependencies": { 1165 | "is-number": "^7.0.0" 1166 | }, 1167 | "engines": { 1168 | "node": ">=8.0" 1169 | } 1170 | }, 1171 | "node_modules/touch": { 1172 | "version": "3.1.0", 1173 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 1174 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 1175 | "dev": true, 1176 | "dependencies": { 1177 | "nopt": "~1.0.10" 1178 | }, 1179 | "bin": { 1180 | "nodetouch": "bin/nodetouch.js" 1181 | } 1182 | }, 1183 | "node_modules/ts-node": { 1184 | "version": "10.9.1", 1185 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", 1186 | "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", 1187 | "dev": true, 1188 | "dependencies": { 1189 | "@cspotcode/source-map-support": "^0.8.0", 1190 | "@tsconfig/node10": "^1.0.7", 1191 | "@tsconfig/node12": "^1.0.7", 1192 | "@tsconfig/node14": "^1.0.0", 1193 | "@tsconfig/node16": "^1.0.2", 1194 | "acorn": "^8.4.1", 1195 | "acorn-walk": "^8.1.1", 1196 | "arg": "^4.1.0", 1197 | "create-require": "^1.1.0", 1198 | "diff": "^4.0.1", 1199 | "make-error": "^1.1.1", 1200 | "v8-compile-cache-lib": "^3.0.1", 1201 | "yn": "3.1.1" 1202 | }, 1203 | "bin": { 1204 | "ts-node": "dist/bin.js", 1205 | "ts-node-cwd": "dist/bin-cwd.js", 1206 | "ts-node-esm": "dist/bin-esm.js", 1207 | "ts-node-script": "dist/bin-script.js", 1208 | "ts-node-transpile-only": "dist/bin-transpile.js", 1209 | "ts-script": "dist/bin-script-deprecated.js" 1210 | }, 1211 | "peerDependencies": { 1212 | "@swc/core": ">=1.2.50", 1213 | "@swc/wasm": ">=1.2.50", 1214 | "@types/node": "*", 1215 | "typescript": ">=2.7" 1216 | }, 1217 | "peerDependenciesMeta": { 1218 | "@swc/core": { 1219 | "optional": true 1220 | }, 1221 | "@swc/wasm": { 1222 | "optional": true 1223 | } 1224 | } 1225 | }, 1226 | "node_modules/ts-node/node_modules/diff": { 1227 | "version": "4.0.2", 1228 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 1229 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 1230 | "dev": true, 1231 | "engines": { 1232 | "node": ">=0.3.1" 1233 | } 1234 | }, 1235 | "node_modules/type-detect": { 1236 | "version": "4.0.8", 1237 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 1238 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 1239 | "dev": true, 1240 | "engines": { 1241 | "node": ">=4" 1242 | } 1243 | }, 1244 | "node_modules/typescript": { 1245 | "version": "4.9.4", 1246 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", 1247 | "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", 1248 | "dev": true, 1249 | "bin": { 1250 | "tsc": "bin/tsc", 1251 | "tsserver": "bin/tsserver" 1252 | }, 1253 | "engines": { 1254 | "node": ">=4.2.0" 1255 | } 1256 | }, 1257 | "node_modules/undefsafe": { 1258 | "version": "2.0.5", 1259 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1260 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 1261 | "dev": true 1262 | }, 1263 | "node_modules/v8-compile-cache-lib": { 1264 | "version": "3.0.1", 1265 | "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", 1266 | "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", 1267 | "dev": true 1268 | }, 1269 | "node_modules/which": { 1270 | "version": "2.0.2", 1271 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1272 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1273 | "dev": true, 1274 | "dependencies": { 1275 | "isexe": "^2.0.0" 1276 | }, 1277 | "bin": { 1278 | "node-which": "bin/node-which" 1279 | }, 1280 | "engines": { 1281 | "node": ">= 8" 1282 | } 1283 | }, 1284 | "node_modules/workerpool": { 1285 | "version": "6.2.0", 1286 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", 1287 | "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", 1288 | "dev": true 1289 | }, 1290 | "node_modules/wrap-ansi": { 1291 | "version": "7.0.0", 1292 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1293 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1294 | "dev": true, 1295 | "dependencies": { 1296 | "ansi-styles": "^4.0.0", 1297 | "string-width": "^4.1.0", 1298 | "strip-ansi": "^6.0.0" 1299 | }, 1300 | "engines": { 1301 | "node": ">=10" 1302 | }, 1303 | "funding": { 1304 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1305 | } 1306 | }, 1307 | "node_modules/wrappy": { 1308 | "version": "1.0.2", 1309 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1310 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1311 | "dev": true 1312 | }, 1313 | "node_modules/y18n": { 1314 | "version": "5.0.8", 1315 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1316 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1317 | "dev": true, 1318 | "engines": { 1319 | "node": ">=10" 1320 | } 1321 | }, 1322 | "node_modules/yargs": { 1323 | "version": "16.2.0", 1324 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 1325 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 1326 | "dev": true, 1327 | "dependencies": { 1328 | "cliui": "^7.0.2", 1329 | "escalade": "^3.1.1", 1330 | "get-caller-file": "^2.0.5", 1331 | "require-directory": "^2.1.1", 1332 | "string-width": "^4.2.0", 1333 | "y18n": "^5.0.5", 1334 | "yargs-parser": "^20.2.2" 1335 | }, 1336 | "engines": { 1337 | "node": ">=10" 1338 | } 1339 | }, 1340 | "node_modules/yargs-parser": { 1341 | "version": "20.2.4", 1342 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 1343 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 1344 | "dev": true, 1345 | "engines": { 1346 | "node": ">=10" 1347 | } 1348 | }, 1349 | "node_modules/yargs-unparser": { 1350 | "version": "2.0.0", 1351 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 1352 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 1353 | "dev": true, 1354 | "dependencies": { 1355 | "camelcase": "^6.0.0", 1356 | "decamelize": "^4.0.0", 1357 | "flat": "^5.0.2", 1358 | "is-plain-obj": "^2.1.0" 1359 | }, 1360 | "engines": { 1361 | "node": ">=10" 1362 | } 1363 | }, 1364 | "node_modules/yn": { 1365 | "version": "3.1.1", 1366 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 1367 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 1368 | "dev": true, 1369 | "engines": { 1370 | "node": ">=6" 1371 | } 1372 | }, 1373 | "node_modules/yocto-queue": { 1374 | "version": "0.1.0", 1375 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1376 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1377 | "dev": true, 1378 | "engines": { 1379 | "node": ">=10" 1380 | }, 1381 | "funding": { 1382 | "url": "https://github.com/sponsors/sindresorhus" 1383 | } 1384 | } 1385 | } 1386 | } 1387 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cmdy", 3 | "description": "A simple cmd parser framework for node js/ts cli apps.", 4 | "version": "1.4.5", 5 | "main": "dist/index.js", 6 | "author": "majo418", 7 | "license": "MIT", 8 | "private": false, 9 | "keywords": [ 10 | "typescript", 11 | "node", 12 | "lib", 13 | "cli", 14 | "cmd", 15 | "arg", 16 | "command" 17 | ], 18 | "repository": { 19 | "url": "git@github.com:majo418/cmdy.git", 20 | "type": "git" 21 | }, 22 | "scripts": { 23 | "tsc": "tsc -p tsconfig.json", 24 | "start": "ts-node src/index.ts", 25 | "exec": "node dist/index.js", 26 | "test": "mocha --require ts-node/register src/test/**/*.test.ts", 27 | "build": "npm run tsc", 28 | "start:watch": "nodemon -w ./src -x \"npm run start\" --ext *.ts", 29 | "build:watch": "nodemon -w ./src -x \"npm run build\" --ext *.ts", 30 | "test:watch": "nodemon -w ./src -x \"npm run test\" --ext *.ts", 31 | "exec:watch": "nodemon -w ./dist -x \"npm run exec\"", 32 | "dev": "npm run start:watch" 33 | }, 34 | "devDependencies": { 35 | "@types/chai": "4", 36 | "@types/mocha": "9", 37 | "@types/node": "16", 38 | "chai": "4", 39 | "mocha": "9", 40 | "nodemon": "2", 41 | "ts-node": "10", 42 | "typescript": "4" 43 | } 44 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { promises as fs, Stats } from "fs" 2 | 3 | exports = module.exports = parseCmd 4 | export default exports 5 | 6 | export type Awaitable = Promise | PromiseLike | T 7 | 8 | export class CmdError extends Error { 9 | constructor( 10 | msg: string 11 | ) { 12 | super(msg) 13 | } 14 | } 15 | 16 | export interface InputValidator { 17 | name: string, 18 | validate: (value: any) => Awaitable, 19 | } 20 | 21 | export type FlagValueTypes = "string" | "number" | "boolean" | InputValidator 22 | 23 | export interface Flag { 24 | name: string, 25 | description: string, 26 | displayName?: string, 27 | required?: boolean, 28 | default?: string | number | boolean, 29 | types?: FlagValueTypes[], 30 | shorthand?: string, 31 | alias?: string[], 32 | control?: (value: string) => Awaitable, 33 | exe?: (cmd: CmdResult, value: string) => Awaitable, 34 | exePriority?: number, 35 | multiValues?: boolean, 36 | } 37 | 38 | export interface BoolFlag extends Flag { 39 | types?: undefined 40 | control?: undefined, 41 | default?: undefined, 42 | required?: undefined, 43 | multiValues?: undefined, 44 | } 45 | 46 | export interface ValueFlag extends Flag { 47 | types: FlagValueTypes[] 48 | } 49 | 50 | export type DefinedFlag = BoolFlag | ValueFlag 51 | 52 | export interface CmdDefinition { 53 | name: string, 54 | description: string, 55 | displayName?: string, 56 | cmds?: CmdDefinition[], 57 | allowUnknownArgs?: boolean, 58 | allowUnknownFlags?: boolean, 59 | details?: string | undefined, 60 | alias?: string[], 61 | flags?: DefinedFlag[], 62 | group?: string | undefined, 63 | exe?: (cmd: CmdResult) => Awaitable, 64 | } 65 | 66 | export interface ValueFlags { 67 | [key: string]: string 68 | } 69 | 70 | export interface ArrayFlags { 71 | [key: string]: string[] 72 | } 73 | 74 | export interface CmdResult { 75 | cmd: CmdDefinition, 76 | args: string[], 77 | flags: string[], 78 | arrayFlags: ArrayFlags, 79 | valueFlags: ValueFlags, 80 | parents: [CmdDefinition, ...CmdDefinition[]], 81 | settings: CmdParserSettings, 82 | exe: () => Promise, 83 | helpResult: boolean, 84 | meta: { [key: string]: any }, 85 | msg?: string, 86 | err?: CmdError | any, 87 | exeFlags: Flag[], 88 | exeValueFlags: [string, Flag][] 89 | } 90 | 91 | export function anyToString(value: any): string { 92 | if (typeof value == "object") { 93 | if (value == null) { 94 | return "NULL" 95 | } 96 | let v: string 97 | try { 98 | v = JSON.stringify(value) 99 | } catch (err) { 100 | } 101 | if ( 102 | typeof v == "string" && 103 | v.length > 0 104 | ) { 105 | return v 106 | } 107 | v = "" + value 108 | if ( 109 | typeof v == "string" && 110 | v.length > 0 111 | ) { 112 | return v 113 | } 114 | return "{}" 115 | } else { 116 | return "" + value 117 | } 118 | } 119 | 120 | export interface StartArgs { 121 | nodePath: string, 122 | appPath: string, 123 | args: string[] 124 | } 125 | 126 | export function getProcessArgs(): StartArgs { 127 | return { 128 | nodePath: process.argv[0], 129 | appPath: process.argv[1], 130 | args: process.argv.slice(2) 131 | } 132 | } 133 | 134 | export const defaultCmdDefinitionSettings = { 135 | cmds: [], 136 | allowUnknownArgs: false, 137 | allowUnknownFlags: false, 138 | multiValues: false, 139 | details: undefined, 140 | alias: [], 141 | flags: [], 142 | group: undefined, 143 | } 144 | 145 | export function fillCmdDefinitionRecursive( 146 | cmd: CmdDefinition, 147 | globalFlags: DefinedFlag[], 148 | helpFlag: DefinedFlag 149 | ): CmdDefinition { 150 | const cmd2: CmdDefinition = { 151 | ...defaultCmdDefinitionSettings, 152 | ...cmd, 153 | name: cmd.name.toLowerCase(), 154 | alias: cmd.alias ? 155 | cmd.alias.map((a) => a.toLowerCase()) : 156 | [] 157 | } 158 | cmd2.flags = [ 159 | ...globalFlags, 160 | ...cmd2.flags, 161 | helpFlag 162 | ].map((f) => { 163 | f.name = f.name.toLowerCase() 164 | f.alias = f.alias ? f.alias.map((a) => a.toLowerCase()) : [] 165 | return f 166 | }) 167 | 168 | cmd2.cmds = cmd2.cmds.map( 169 | (subCmd: CmdDefinition) => fillCmdDefinitionRecursive( 170 | subCmd, 171 | globalFlags, 172 | helpFlag 173 | ) 174 | ) 175 | return cmd2 176 | } 177 | 178 | export const helpFlag: BoolFlag = { 179 | name: "help", 180 | description: "Shows this help output", 181 | shorthand: "h", 182 | } 183 | 184 | export interface CmdParserOptions { 185 | cmd: CmdDefinition, 186 | args?: string[], 187 | helpWords?: string[], 188 | globalFlags?: DefinedFlag[] 189 | globalHelpMsg?: string | undefined, 190 | helpGeneratorFunction?: HelpGenerator, 191 | helpFlag?: DefinedFlag 192 | } 193 | 194 | export interface CmdParserSettings extends CmdParserOptions { 195 | helpWords: string[], 196 | globalFlags: DefinedFlag[] 197 | globalHelpMsg: string | undefined, 198 | helpGeneratorFunction: HelpGenerator, 199 | helpFlag: DefinedFlag 200 | } 201 | 202 | export const defaultCmdParserSettings: CmdParserSettings = { 203 | cmd: {} as any, 204 | args: getProcessArgs().args, 205 | helpWords: ["-h", "--help"], 206 | globalFlags: [], 207 | globalHelpMsg: undefined, 208 | helpGeneratorFunction: defaultHelpGenerator, 209 | helpFlag: helpFlag 210 | } 211 | 212 | export function parseValueFlag( 213 | flag: ValueFlag, 214 | flagvalue: string, 215 | restArgs: string[], 216 | res: CmdResult, 217 | ): void { 218 | if (flagvalue.startsWith("\"")) { 219 | while (restArgs.length > 0) { 220 | flagvalue += restArgs.shift() 221 | if (flagvalue.endsWith("\"")) { 222 | break 223 | } 224 | } 225 | flagvalue = flagvalue.slice(1, -1) 226 | } 227 | let value: any = undefined 228 | let tmp: any = flagvalue.toLowerCase() 229 | if (flag.types.includes("boolean")) { 230 | if (tmp == "true") { 231 | value = true 232 | } else if (tmp == "false") { 233 | value = false 234 | } 235 | } 236 | if ( 237 | !value && 238 | flag.types.includes("number") 239 | ) { 240 | tmp = Number(flagvalue) 241 | if (!isNaN(tmp)) { 242 | value = flagvalue 243 | } 244 | } 245 | if ( 246 | !value && 247 | flag.types.includes("string") 248 | ) { 249 | value = flagvalue 250 | } 251 | flag.types.forEach((type) => { 252 | if (typeof type == "string") { 253 | return 254 | } 255 | value = type.validate(flagvalue) 256 | }) 257 | if (value == undefined) { 258 | throw new CmdError( 259 | "Type of '" + flag.name + 260 | "' needs to be a '" + 261 | flag.types.map( 262 | (t) => typeof t == "string" ? 263 | t : 264 | t.name 265 | ).join("', '") + "'!" 266 | ) 267 | } 268 | if (flag.multiValues) { 269 | if (!res.arrayFlags[flag.name]) { 270 | res.arrayFlags[flag.name] = [] 271 | } 272 | res.arrayFlags[flag.name].push(value) 273 | if (flag.exe) { 274 | res.exeValueFlags.push([value, flag]) 275 | } 276 | } else { 277 | if (typeof res.valueFlags[flag.name] == "string") { 278 | throw new Error( 279 | "Value flag for '" + flag.name + 280 | "' is set multiple times but is just allows once" 281 | ) 282 | } 283 | res.valueFlags[flag.name] = value 284 | if (flag.exe) { 285 | res.exeValueFlags.push([value, flag]) 286 | } 287 | } 288 | } 289 | 290 | export function parseFlag( 291 | flag: BoolFlag, 292 | res: CmdResult, 293 | ): void { 294 | if (!res.flags.includes(flag.name)) { 295 | res.flags.push(flag.name) 296 | if (flag.exe) { 297 | res.exeFlags.push(flag) 298 | } 299 | } 300 | } 301 | 302 | export function parseCmd( 303 | options: CmdParserOptions 304 | ): CmdResult { 305 | const settings: CmdParserSettings = { 306 | ...defaultCmdParserSettings, 307 | ...options, 308 | } 309 | settings.cmd = fillCmdDefinitionRecursive( 310 | settings.cmd, 311 | settings.globalFlags, 312 | settings.helpFlag 313 | ) 314 | let restArgs = settings.args 315 | if ( 316 | restArgs.length > 0 && 317 | restArgs[0] == settings.cmd.name 318 | ) { 319 | restArgs.shift() 320 | } 321 | const res: CmdResult = { 322 | cmd: settings.cmd, 323 | args: [], 324 | flags: [], 325 | arrayFlags: {}, 326 | valueFlags: {}, 327 | parents: [settings.cmd], 328 | settings: settings, 329 | err: undefined, 330 | exe: undefined as any, 331 | meta: {}, 332 | helpResult: false, 333 | exeFlags: [], 334 | exeValueFlags: [], 335 | } 336 | 337 | while (restArgs.length > 0) { 338 | const arg = restArgs[0] 339 | const lowerArg = arg.toLowerCase() 340 | let found: boolean = false 341 | for (const cmd of res.cmd.cmds) { 342 | if ( 343 | cmd.name == lowerArg || 344 | ( 345 | cmd.alias && 346 | cmd.alias.includes(lowerArg) 347 | ) 348 | ) { 349 | restArgs.shift() 350 | res.cmd = cmd 351 | found = true 352 | break 353 | } 354 | } 355 | if (!found) { 356 | break 357 | } 358 | } 359 | 360 | try { 361 | // parse flags to 362 | for (let index2 = 0; index2 < res.cmd.flags.length; index2++) { 363 | const flag = res.cmd.flags[index2] 364 | flag.name = flag.name.toLowerCase() 365 | if ( 366 | flag.alias && 367 | Array.isArray(flag.alias) && 368 | flag.alias.length > 0 369 | ) { 370 | flag.alias = flag.alias.map((a) => a.toLowerCase()) 371 | } 372 | } 373 | 374 | 375 | while (restArgs.length > 0) { 376 | const arg: string = restArgs.shift() 377 | const lowerArg: string = arg.toLowerCase() 378 | if (arg == "") { 379 | continue 380 | } else if ( 381 | lowerArg == "--help" || 382 | lowerArg == "-h" 383 | ) { 384 | if (!res.flags.includes("help")) { 385 | res.flags.push("help") 386 | } 387 | } else if (arg.startsWith("--")) { 388 | const equalIndex: number = arg.indexOf("=") 389 | let flagname: string 390 | let flagvalue: string = undefined 391 | if (equalIndex == -1) { 392 | flagname = arg.substring(2) 393 | } else { 394 | flagname = arg.substring(2, equalIndex) 395 | flagvalue = arg.substring(equalIndex + 1) 396 | } 397 | if (flagname.length == 0) { 398 | throw new Error("Empty flag!") 399 | } 400 | let found: boolean = false 401 | for ( 402 | let index2 = 0; 403 | index2 < res.cmd.flags.length; 404 | index2++ 405 | ) { 406 | const flag = res.cmd.flags[index2] 407 | if (flag.alias) { 408 | if (!flag.alias.includes(flagname)) { 409 | 410 | } 411 | } 412 | if ( 413 | flag.name.toLowerCase() != flagname && ( 414 | !flag.alias || 415 | !flag.alias.includes(flagname) 416 | ) 417 | ) { 418 | continue 419 | } 420 | flag.types && flag.types.length > 0 ? 421 | parseValueFlag( 422 | flag as ValueFlag, 423 | flagvalue ?? restArgs.shift(), 424 | restArgs, 425 | res 426 | ) : 427 | parseFlag( 428 | flag as BoolFlag, 429 | res 430 | ) 431 | found = true 432 | break 433 | } 434 | if (!found) { 435 | if (res.cmd.allowUnknownFlags) { 436 | res.args.push(arg) 437 | continue 438 | } 439 | throw new CmdError( 440 | "Unknown flag: \"--" + flagname + "\"" 441 | ) 442 | } 443 | } else if (arg.startsWith("-")) { 444 | const shorthands: string[] = arg.substring(1).split("") 445 | for (let index2 = shorthands.length - 1; index2 >= 0; index2--) { 446 | const shorthand = shorthands[index2] 447 | let found: boolean = false 448 | for (const flag of res.cmd.flags) { 449 | if ( 450 | flag.shorthand && 451 | flag.shorthand == shorthand 452 | ) { 453 | restArgs = [ 454 | "--" + flag.name, 455 | ...restArgs 456 | ] 457 | found = true 458 | break 459 | } 460 | } 461 | if (!found) { 462 | if (res.cmd.allowUnknownFlags) { 463 | res.args.push(arg) 464 | continue 465 | } 466 | throw new CmdError( 467 | "Unknown shorthand flag: \"-" + shorthand + 468 | "\"" 469 | ) 470 | } 471 | } 472 | } else { 473 | if (!res.cmd.allowUnknownArgs) { 474 | throw new CmdError( 475 | "Unknown command argument: \"" + arg + "\"" 476 | ) 477 | } 478 | res.args.push(arg) 479 | } 480 | } 481 | 482 | for (let index = 0; index < res.cmd.flags.length; index++) { 483 | const flag = res.cmd.flags[index] 484 | if ( 485 | flag.types && 486 | !Object.keys(res.valueFlags).includes(flag.name) 487 | ) { 488 | const type = typeof flag.default 489 | if ( 490 | type == "string" || 491 | type == "number" || 492 | type == "boolean" 493 | ) { 494 | if (flag.multiValues) { 495 | res.arrayFlags[flag.name] = ["" + flag.default] 496 | } else { 497 | res.valueFlags[flag.name] = "" + flag.default 498 | } 499 | } else if (flag.required) { 500 | throw new CmdError( 501 | "Flag '" + flag.name + 502 | "' is required but not set!" 503 | ) 504 | } 505 | } else if ( 506 | !res.flags.includes(flag.name) && 507 | !Object.keys(res.valueFlags).includes(flag.name) 508 | ) { 509 | const type = typeof flag.default 510 | if ( 511 | type == "string" || 512 | type == "number" || 513 | type == "boolean" 514 | ) { 515 | if (flag.multiValues) { 516 | res.arrayFlags[flag.name] = ["" + flag.default] 517 | } else { 518 | res.valueFlags[flag.name] = "" + flag.default 519 | } 520 | } else if (flag.required) { 521 | throw new CmdError( 522 | "Flag '" + flag.name + 523 | "' is required but not set!" 524 | ) 525 | } 526 | } 527 | } 528 | } catch (err: CmdError | any) { 529 | res.err = err 530 | res.exe = async () => { 531 | console.error( 532 | err instanceof CmdError ? 533 | "Cmdy" + err.message : 534 | "UnknownError | " + (err.stack ?? err) 535 | ) 536 | return res 537 | } 538 | } 539 | res.cmd.flags.forEach((f) => { 540 | if (!Array.isArray(f.types)) { 541 | return 542 | } 543 | if (!res.arrayFlags[f.name]) { 544 | if (f.multiValues) { 545 | res.arrayFlags[f.name] = [] 546 | } 547 | } 548 | }) 549 | res.exeFlags = res.exeFlags.sort( 550 | (a, b) => (a.exePriority ?? 0) - (b.exePriority ?? 0) 551 | ) 552 | res.exeValueFlags = res.exeValueFlags.sort( 553 | (a, b) => (a[1].exePriority ?? 0) - (b[1].exePriority ?? 0) 554 | ) 555 | if (!res.cmd.exe) { 556 | settings.helpGeneratorFunction(res) 557 | } else if (!res.err) { 558 | if (res.flags.includes("help")) { 559 | settings.helpGeneratorFunction(res) 560 | } else { 561 | res.exe = async () => { 562 | for (const flag of res.exeFlags) { 563 | await flag.exe(res, undefined) 564 | } 565 | for (const flag of res.exeValueFlags) { 566 | await flag[1].exe(res, flag[0]) 567 | } 568 | res.cmd.exe(res) 569 | return res 570 | } 571 | } 572 | } 573 | 574 | return res 575 | } 576 | 577 | // ##### ##### ##### ##### ##### HelpGenerator ##### ##### ##### ##### ##### 578 | 579 | export type HelpGenerator = ( 580 | data: CmdResult, 581 | ) => CmdResult 582 | 583 | export function defaultHelpGenerator( 584 | data: CmdResult, 585 | ): CmdResult { 586 | data.helpResult = true 587 | let message: string = "# " + data.cmd.name.toUpperCase() + " #" 588 | 589 | !data.cmd.exe && ( 590 | message += "\n\nERROR: Command " + 591 | data.cmd.name + 592 | " not directly executeable!" 593 | ) 594 | 595 | message += "\n\nUsage: " + data.parents.map((a) => a.name).join(" ") 596 | 597 | if (data.cmd.flags.length > 0) { 598 | message += " [OPTIONS]" 599 | } 600 | 601 | if (data.cmd.cmds && data.cmd.cmds.length > 0) { 602 | message += " COMMAND" 603 | } 604 | 605 | if (data.cmd.allowUnknownArgs) { 606 | message += " [ARGUMENTS]" 607 | } 608 | 609 | message += "\n\n" + data.cmd.description 610 | 611 | if (data.cmd.flags.length > 0) { 612 | message += "\n\nOptions:\n" 613 | const options: string[] = [] 614 | let biggest: number = 0 615 | for (let index = 0; index < data.cmd.flags.length; index++) { 616 | const flag = data.cmd.flags[index] 617 | let flagMsg: string 618 | if (flag.shorthand) { 619 | flagMsg = " -" + flag.shorthand + ", --" + flag.name 620 | } else { 621 | flagMsg = " --" + flag.name 622 | } 623 | if (flag.types && flag.types.length > 0) { 624 | flagMsg += " [" + flag.types.map((t) => typeof t == "string" ? t : t.name).join(" | ") + "]" 625 | } 626 | if (flagMsg.length > biggest) { 627 | biggest = flagMsg.length 628 | } 629 | options.push(flagMsg) 630 | } 631 | for (let index = 0; index < options.length; index++) { 632 | while (options[index].length <= biggest) { 633 | options[index] += " " 634 | } 635 | options[index] += data.cmd.flags[index].description 636 | } 637 | message += options.join("\n") 638 | } 639 | 640 | if (data.cmd.cmds && data.cmd.cmds.length > 0) { 641 | const groups: { 642 | [key: string]: CmdDefinition[] 643 | } = { 644 | "default": [] 645 | } 646 | 647 | data.cmd.cmds.forEach((cmd) => { 648 | const group: string = cmd.group ?? "default" 649 | if (!groups[group]) { 650 | groups[group] = [] 651 | } 652 | groups[group].push(cmd) 653 | }) 654 | 655 | const keys = Object.keys(groups).reverse() 656 | for (let index = 0; index < keys.length; index++) { 657 | const group = keys[index] 658 | const groupCmds = groups[group] 659 | const formatedGroupName = group == "default" ? "" : group.substring(0, 1).toUpperCase() + group.substring(1) + " " 660 | message += "\n\n" + formatedGroupName + "Commands:\n" 661 | const commands: string[] = [] 662 | let biggest: number = 7 663 | for (let index2 = 0; index2 < groupCmds.length; index2++) { 664 | const cmdName = groupCmds[index2].name 665 | if (cmdName.length > biggest) [ 666 | biggest = cmdName.length 667 | ] 668 | commands.push(cmdName) 669 | } 670 | for (let index2 = 0; index2 < commands.length; index2++) { 671 | while (commands[index2].length <= biggest) { 672 | commands[index2] += " " 673 | } 674 | commands[index2] += groupCmds[index2].description 675 | } 676 | message += commands.join("\n") 677 | } 678 | } 679 | 680 | if (data.cmd.details && data.flags.includes("help")) { 681 | message += "\n\nDetails:\n" + data.cmd.details 682 | } else { 683 | message += "\n\nRun '" + data.parents.map((a) => a.name).join(" ") + " --help' for more informations on a command." 684 | } 685 | 686 | if (data.settings.globalHelpMsg) { 687 | message += "\n\n" + data.settings.globalHelpMsg 688 | } 689 | 690 | data.msg = message 691 | data.exe = async () => { 692 | console.info(message) 693 | return data 694 | } 695 | 696 | return data 697 | } 698 | -------------------------------------------------------------------------------- /src/test/index.test.ts: -------------------------------------------------------------------------------- 1 | import "mocha" 2 | import "chai" 3 | import { parseCmd, CmdDefinition, Flag, getProcessArgs, ValueFlag, BoolFlag } from '../index'; 4 | import { expect } from "chai" 5 | import exp = require("constants"); 6 | 7 | export type AllTypes = "string" | "number" | "object" | 8 | "instance" | "function" | "class" | "array" | "null" | 9 | "undefined" | "symbol" | "bigint" | "boolean" 10 | 11 | export function getType(any: any): AllTypes { 12 | const type = typeof any 13 | if (type == "object") { 14 | if (any == null) { 15 | return "null" 16 | } else if (Array.isArray(any)) { 17 | return "array" 18 | } else if ( 19 | any.constructor && 20 | typeof any.constructor.name == "string" && 21 | any.constructor.name != "Object" 22 | ) { 23 | return "instance" 24 | } 25 | } 26 | return type 27 | } 28 | 29 | let exec: boolean 30 | const simpleCmd: CmdDefinition = { 31 | name: "simple", 32 | description: "A simple test command!", 33 | exe: async () => { exec = true } 34 | } 35 | 36 | describe('base cmd tests', () => { 37 | beforeEach(() => { 38 | exec = false 39 | }) 40 | 41 | it("get process args method", async () => { 42 | expect(JSON.stringify( 43 | getProcessArgs().args 44 | )).is.equals( 45 | JSON.stringify([ 46 | "--require", 47 | "ts-node/register", 48 | "src/test/**/*.test.ts" 49 | ]) 50 | ) 51 | }) 52 | 53 | it("cmd", async () => { 54 | let res = parseCmd({ 55 | cmd: simpleCmd, 56 | args: [], 57 | }) 58 | 59 | expect(exec).is.false 60 | res = await res.exe() 61 | 62 | expect(res).is.not.undefined 63 | expect(res.err).is.undefined 64 | expect(exec).is.true 65 | 66 | expect(res.flags).is.not.undefined 67 | expect(getType(res.flags)).is.equals("array") 68 | expect(res.flags.length).is.equals(0) 69 | 70 | expect(res.valueFlags).is.not.undefined 71 | expect(getType(res.valueFlags)).is.equals("object") 72 | expect(Object.keys(res.valueFlags).length).is.equals(0) 73 | }) 74 | 75 | it("test flags args", async () => { 76 | const test: BoolFlag = { 77 | name: "test", 78 | description: "A test flag", 79 | } 80 | 81 | const qwer: BoolFlag = { 82 | name: "qwer", 83 | description: "A qwer flag", 84 | } 85 | 86 | const qwe1: ValueFlag = { 87 | name: "qwe1", 88 | description: "A qwe1 flag", 89 | types: ["string"] 90 | } 91 | 92 | const qwe2: ValueFlag = { 93 | name: "qwe2", 94 | description: "A qwe2 flag", 95 | types: ["string"] 96 | } 97 | 98 | simpleCmd.flags = [ 99 | test, 100 | qwer, 101 | qwe1, 102 | qwe2 103 | ] 104 | 105 | let res = parseCmd({ 106 | cmd: simpleCmd, 107 | args: [ 108 | "--qwe1", 109 | "test", 110 | "--test", 111 | ], 112 | }) 113 | 114 | expect(exec).is.false 115 | res = await res.exe() 116 | expect(exec).is.true 117 | 118 | expect(res.args.length).is.equals(0) 119 | expect(res.err).is.undefined 120 | 121 | expect(res.flags.includes("test")).is.true 122 | expect(res.flags.includes("qwer")).is.false 123 | 124 | expect(Object.keys(res.valueFlags).length).is.equals(1) 125 | expect(res.valueFlags.qwe1).is.not.undefined 126 | expect(typeof res.valueFlags.qwe1).is.equals("string") 127 | expect(res.valueFlags.qwe1).is.equals("test") 128 | 129 | expect(Object.keys(res.arrayFlags).length).is.equals(0) 130 | }) 131 | }) 132 | 133 | describe('unknown args tests', () => { 134 | beforeEach(() => { 135 | exec = false 136 | }) 137 | 138 | it("dont allow unknown args", async () => { 139 | const test: BoolFlag = { 140 | name: "test", 141 | description: "A test flag", 142 | } 143 | 144 | const qwer: BoolFlag = { 145 | name: "qwer", 146 | description: "A qwer flag", 147 | } 148 | 149 | const qwe1: ValueFlag = { 150 | name: "qwe1", 151 | description: "A qwe1 flag", 152 | types: ["string"] 153 | } 154 | 155 | const qwe2: ValueFlag = { 156 | name: "qwe2", 157 | description: "A qwe2 flag", 158 | types: ["string"] 159 | } 160 | 161 | simpleCmd.flags = [ 162 | test, 163 | qwer, 164 | qwe1, 165 | qwe2 166 | ] 167 | 168 | let res = parseCmd({ 169 | cmd: simpleCmd, 170 | args: ["--qwe1", "test", "ddd", "--test", "asdasd"] 171 | }) 172 | 173 | expect(typeof res.err).is.equals("object") 174 | expect(res.args.length).is.equals(0) 175 | expect(res.err.message).is.equals('Unknown command argument: "ddd"') 176 | }) 177 | 178 | it("allow unknown args", async () => { 179 | const test: BoolFlag = { 180 | name: "test", 181 | description: "A test flag", 182 | } 183 | 184 | const qwer: BoolFlag = { 185 | name: "qwer", 186 | description: "A qwer flag", 187 | } 188 | 189 | const qwe1: ValueFlag = { 190 | name: "qwe1", 191 | description: "A qwe1 flag", 192 | types: ["string"] 193 | } 194 | 195 | const qwe2: ValueFlag = { 196 | name: "qwe2", 197 | description: "A qwe2 flag", 198 | types: ["string"] 199 | } 200 | 201 | simpleCmd.flags = [ 202 | test, 203 | qwer, 204 | qwe1, 205 | qwe2 206 | ] 207 | 208 | let res = parseCmd({ 209 | cmd: { 210 | ...simpleCmd, 211 | allowUnknownArgs: true, 212 | }, 213 | args: ["--qwe1", "test", "ddd", "--test", "asdasd"] 214 | }) 215 | 216 | expect(exec).is.false 217 | res = await res.exe() 218 | expect(exec).is.true 219 | 220 | expect(res.args.length).is.equals(2) 221 | expect(res.err).is.undefined 222 | 223 | expect(res.flags.includes("test")).is.true 224 | expect(res.flags.includes("qwer")).is.false 225 | 226 | expect(res.valueFlags.qwe1).is.not.undefined 227 | expect(typeof res.valueFlags.qwe1).is.equals("string") 228 | expect(res.valueFlags.qwe1).is.equals("test") 229 | }) 230 | 231 | it("allow just args", async () => { 232 | const test: BoolFlag = { 233 | name: "test", 234 | description: "A test flag", 235 | } 236 | 237 | const qwer: BoolFlag = { 238 | name: "qwer", 239 | description: "A qwer flag", 240 | } 241 | 242 | const qwe1: ValueFlag = { 243 | name: "qwe1", 244 | description: "A qwe1 flag", 245 | types: ["string"] 246 | } 247 | 248 | const qwe2: ValueFlag = { 249 | name: "qwe2", 250 | description: "A qwe2 flag", 251 | types: ["string"] 252 | } 253 | 254 | simpleCmd.flags = [ 255 | test, 256 | qwer, 257 | qwe1, 258 | qwe2 259 | ] 260 | 261 | let res = parseCmd({ 262 | cmd: { 263 | ...simpleCmd, 264 | allowUnknownArgs: true, 265 | }, 266 | args: ["qwe1", "test", "ddd", "test", "asdasd"] 267 | }) 268 | 269 | expect(exec).is.false 270 | res = await res.exe() 271 | expect(exec).is.true 272 | 273 | expect(res.args.length).is.equals(5) 274 | expect(res.err).is.undefined 275 | 276 | expect(res.flags.includes("test")).is.false 277 | expect(res.flags.includes("qwer")).is.false 278 | 279 | expect(typeof res.valueFlags).is.equals("object") 280 | expect(Object.keys(res.valueFlags).length).is.equals(0) 281 | }) 282 | }) 283 | 284 | const requireCmd: CmdDefinition = { 285 | name: "test", 286 | description: "some test command", 287 | flags: [ 288 | { 289 | name: "path", 290 | description: "some path flag", 291 | required: true, 292 | types: ["string"], 293 | } 294 | ] 295 | } 296 | 297 | describe('required flag', () => { 298 | it("require flag test", async () => { 299 | let res = parseCmd({ 300 | cmd: requireCmd, 301 | args: ["--path", "/test/wow/home"], 302 | }) 303 | 304 | expect(typeof res).is.equals("object") 305 | expect(res.err).is.undefined 306 | expect(typeof res.cmd).is.equals("object") 307 | expect(typeof res.valueFlags).is.equals("object") 308 | expect(typeof res.valueFlags.path).is.equals("string") 309 | expect(typeof res.valueFlags.path[0]).is.equals("string") 310 | }) 311 | 312 | it("require flag error", async () => { 313 | let res = parseCmd({ 314 | cmd: requireCmd, 315 | args: [], 316 | }) 317 | 318 | expect(typeof res).is.equals("object") 319 | expect(typeof res.err).is.equals("object") 320 | expect(res.err.message).is.equals("Flag 'path' is required but not set!") 321 | }) 322 | }) 323 | 324 | const subsubsubCmd: CmdDefinition = { 325 | name: "subsubsub", 326 | description: "some sub sub sub command", 327 | flags: [], 328 | allowUnknownArgs: true, 329 | allowUnknownFlags: true, 330 | } 331 | 332 | const subsubCmd: CmdDefinition = { 333 | name: "subsub", 334 | description: "some sub sub command", 335 | flags: [], 336 | allowUnknownArgs: true, 337 | allowUnknownFlags: true, 338 | cmds: [subsubsubCmd], 339 | } 340 | 341 | const subCmd: CmdDefinition = { 342 | name: "sub", 343 | description: "some sub command", 344 | flags: [], 345 | allowUnknownArgs: true, 346 | allowUnknownFlags: true, 347 | cmds: [subsubCmd], 348 | } 349 | 350 | const superCmd: CmdDefinition = { 351 | name: "root", 352 | description: "some super root command", 353 | flags: [ 354 | { 355 | name: "verbose", 356 | description: "some path flag", 357 | shorthand: "v", 358 | } 359 | ], 360 | allowUnknownArgs: false, 361 | allowUnknownFlags: true, 362 | cmds: [ 363 | requireCmd, 364 | simpleCmd, 365 | subCmd, 366 | ], 367 | } 368 | 369 | describe('sub commands tests', () => { 370 | it("check super cmd without args", async () => { 371 | exec = false 372 | let res = parseCmd({ 373 | cmd: superCmd, 374 | args: [], 375 | }) 376 | 377 | expect(exec).is.false 378 | expect(res.helpResult).is.true 379 | 380 | expect(res).is.not.undefined 381 | expect(res.err).is.undefined 382 | expect(exec).is.false 383 | 384 | expect(res.flags).is.not.undefined 385 | expect(getType(res.flags)).is.equals("array") 386 | expect(res.flags.length).is.equals(0) 387 | expect(res.args.length).is.equals(0) 388 | 389 | expect(res.valueFlags).is.not.undefined 390 | expect(getType(res.valueFlags)).is.equals("object") 391 | expect(Object.keys(res.valueFlags).length).is.equals(0) 392 | }) 393 | 394 | it("check super cmd with random undefined args", async () => { 395 | exec = false 396 | let res = parseCmd({ 397 | cmd: superCmd, 398 | args: ["asdad", "pkvjrklgdf", "ölkiecnfvdnf", "-path", "-g", "sldkfjsdogvb", "osiucbs"], 399 | }) 400 | 401 | expect(exec).is.false 402 | expect(res.helpResult).is.true 403 | 404 | expect(res).is.not.undefined 405 | expect(typeof res.err).is.equals("object") 406 | expect(res.err.message).is.equals('Unknown command argument: "asdad"') 407 | 408 | expect(res.flags).is.not.undefined 409 | expect(getType(res.flags)).is.equals("array") 410 | expect(res.args.length).is.equals(0) 411 | expect(res.flags.length).is.equals(0) 412 | 413 | expect(res.valueFlags).is.not.undefined 414 | expect(getType(res.valueFlags)).is.equals("object") 415 | expect(Object.keys(res.valueFlags).length).is.equals(0) 416 | }) 417 | 418 | it("check sub cmd without arg", async () => { 419 | exec = false 420 | let res = parseCmd({ 421 | cmd: superCmd, 422 | args: ["sub"], 423 | }) 424 | 425 | expect(exec).is.false 426 | expect(res.helpResult).is.true 427 | 428 | expect(res).is.not.undefined 429 | expect(res.err).is.undefined 430 | 431 | expect(res.flags).is.not.undefined 432 | expect(getType(res.flags)).is.equals("array") 433 | expect(res.args.length).is.equals(0) 434 | expect(res.flags.length).is.equals(0) 435 | 436 | expect(res.valueFlags).is.not.undefined 437 | expect(getType(res.valueFlags)).is.equals("object") 438 | expect(Object.keys(res.valueFlags).length).is.equals(0) 439 | }) 440 | 441 | it("check sub with random args", async () => { 442 | exec = false 443 | let res = parseCmd({ 444 | cmd: superCmd, 445 | args: ["sub", "asdad", "lvkjfvb", "csoicjkso", "--flagtest", "asdad", "-v", "09ev0weuv"], 446 | }) 447 | 448 | expect(exec).is.false 449 | expect(res.helpResult).is.true 450 | 451 | expect(res.cmd.name).is.equals("sub") 452 | 453 | expect(res).is.not.undefined 454 | expect(res.err).is.undefined 455 | 456 | expect(res.flags).is.not.undefined 457 | expect(getType(res.flags)).is.equals("array") 458 | expect(res.args.length).is.equals(7) 459 | expect(res.flags.length).is.equals(0) 460 | 461 | expect(res.valueFlags).is.not.undefined 462 | expect(getType(res.valueFlags)).is.equals("object") 463 | expect(Object.keys(res.valueFlags).length).is.equals(0) 464 | }) 465 | 466 | it("check subsubsub with random args", async () => { 467 | exec = false 468 | let res = parseCmd({ 469 | cmd: superCmd, 470 | args: ["sub", "subsub", "subsubsub", "asdad", "lvkjfvb", "csoicjkso", "--flagtest", "asdad", "-v", "09ev0weuv"], 471 | }) 472 | 473 | expect(exec).is.false 474 | expect(res.helpResult).is.true 475 | 476 | expect(res.cmd.name).is.equals("subsubsub") 477 | 478 | expect(res).is.not.undefined 479 | expect(res.err).is.undefined 480 | 481 | expect(res.flags).is.not.undefined 482 | expect(getType(res.flags)).is.equals("array") 483 | expect(res.args.length).is.equals(7) 484 | expect(res.flags.length).is.equals(0) 485 | 486 | expect(res.valueFlags).is.not.undefined 487 | expect(getType(res.valueFlags)).is.equals("object") 488 | expect(Object.keys(res.valueFlags).length).is.equals(0) 489 | }) 490 | 491 | it("check sub is in sub", async () => { 492 | exec = false 493 | let res = parseCmd({ 494 | cmd: superCmd, 495 | args: ["sub", "sub", "asdad", "lvkjfvb", "csoicjkso", "--flagtest", "asdad", "-v", "09ev0weuv"], 496 | }) 497 | 498 | expect(exec).is.false 499 | expect(res.helpResult).is.true 500 | 501 | expect(res.cmd.name).is.equals("sub") 502 | 503 | expect(res).is.not.undefined 504 | expect(res.err).is.undefined 505 | 506 | expect(res.flags).is.not.undefined 507 | expect(getType(res.flags)).is.equals("array") 508 | expect(res.args.length).is.equals(8) 509 | expect(res.args[0]).is.equals("sub") 510 | expect(res.flags.length).is.equals(0) 511 | 512 | expect(res.valueFlags).is.not.undefined 513 | expect(getType(res.valueFlags)).is.equals("object") 514 | expect(Object.keys(res.valueFlags).length).is.equals(0) 515 | }) 516 | }) 517 | 518 | let verbose: boolean 519 | let path: string[] 520 | let number: string[] 521 | 522 | const execFlagCmd: CmdDefinition = { 523 | name: "execflagcmd", 524 | description: "some command with executable flags", 525 | flags: [ 526 | { 527 | name: "verbose", 528 | description: "some path flag", 529 | shorthand: "v", 530 | exe(res) { 531 | verbose = true 532 | } 533 | }, 534 | { 535 | name: "path", 536 | description: "some path flag", 537 | shorthand: "p", 538 | types: ["string"], 539 | multiValues: true, 540 | exe(res, value) { 541 | path.push(value) 542 | } 543 | }, 544 | { 545 | name: "number", 546 | description: "some number flag", 547 | shorthand: "n", 548 | types: ["number"], 549 | multiValues: true, 550 | exe(res, value) { 551 | number.push(value) 552 | } 553 | }, 554 | ], 555 | exe: async (cmd) => { exec = true } 556 | } 557 | 558 | describe('executable flags', () => { 559 | beforeEach(() => { 560 | exec = false 561 | verbose = false 562 | path = [] 563 | number = [] 564 | }) 565 | 566 | it("check without flags", async () => { 567 | let res = parseCmd({ 568 | cmd: execFlagCmd, 569 | args: [], 570 | }) 571 | 572 | expect(exec).is.false 573 | res = await res.exe() 574 | expect(exec).is.true 575 | 576 | expect(res.args.length).is.equals(0) 577 | expect(res.err).is.undefined 578 | 579 | expect(res).is.not.undefined 580 | expect(res.err).is.undefined 581 | 582 | expect(verbose).is.false 583 | expect(path.length).is.equals(0) 584 | expect(number.length).is.equals(0) 585 | 586 | expect(res.flags).is.not.undefined 587 | expect(getType(res.flags)).is.equals("array") 588 | expect(res.flags.length).is.equals(0) 589 | expect(res.args.length).is.equals(0) 590 | 591 | expect(res.valueFlags).is.not.undefined 592 | expect(getType(res.valueFlags)).is.equals("object") 593 | expect(Object.keys(res.valueFlags).length).is.equals(0) 594 | 595 | expect(res.arrayFlags).is.not.undefined 596 | expect(getType(res.arrayFlags)).is.equals("object") 597 | expect(Object.keys(res.arrayFlags).length).is.equals(2) 598 | expect(Object.keys(res.arrayFlags.path).length).is.equals(0) 599 | expect(Object.keys(res.arrayFlags.number).length).is.equals(0) 600 | }) 601 | 602 | it("check with verbose", async () => { 603 | let res = parseCmd({ 604 | cmd: execFlagCmd, 605 | args: ["-v"], 606 | }) 607 | 608 | expect(exec).is.false 609 | res = await res.exe() 610 | expect(exec).is.true 611 | 612 | expect(res.args.length).is.equals(0) 613 | expect(res.err).is.undefined 614 | 615 | expect(res).is.not.undefined 616 | expect(res.err).is.undefined 617 | 618 | expect(verbose).is.true 619 | expect(path.length).is.equals(0) 620 | expect(number.length).is.equals(0) 621 | 622 | expect(res.flags).is.not.undefined 623 | expect(getType(res.flags)).is.equals("array") 624 | expect(res.flags.length).is.equals(1) 625 | expect(res.args.length).is.equals(0) 626 | 627 | expect(res.valueFlags).is.not.undefined 628 | expect(getType(res.valueFlags)).is.equals("object") 629 | expect(Object.keys(res.valueFlags).length).is.equals(0) 630 | 631 | expect(res.arrayFlags).is.not.undefined 632 | expect(getType(res.arrayFlags)).is.equals("object") 633 | expect(Object.keys(res.arrayFlags).length).is.equals(2) 634 | expect(Object.keys(res.arrayFlags.path).length).is.equals(0) 635 | expect(Object.keys(res.arrayFlags.number).length).is.equals(0) 636 | }) 637 | 638 | it("check with one path", async () => { 639 | let res = parseCmd({ 640 | cmd: execFlagCmd, 641 | args: ["--path", "/var/www/html"], 642 | }) 643 | 644 | expect(exec).is.false 645 | res = await res.exe() 646 | expect(exec).is.true 647 | 648 | expect(res.args.length).is.equals(0) 649 | expect(res.err).is.undefined 650 | 651 | expect(res).is.not.undefined 652 | expect(res.err).is.undefined 653 | 654 | expect(verbose).is.false 655 | expect(path.length).is.equals(1) 656 | expect(path[0]).is.equals("/var/www/html") 657 | expect(number.length).is.equals(0) 658 | 659 | expect(res.flags).is.not.undefined 660 | expect(getType(res.flags)).is.equals("array") 661 | expect(res.flags.length).is.equals(0) 662 | expect(res.args.length).is.equals(0) 663 | 664 | expect(res.valueFlags).is.not.undefined 665 | expect(getType(res.valueFlags)).is.equals("object") 666 | expect(Object.keys(res.valueFlags).length).is.equals(0) 667 | 668 | expect(res.arrayFlags).is.not.undefined 669 | expect(getType(res.arrayFlags)).is.equals("object") 670 | expect(Object.keys(res.arrayFlags).length).is.equals(2) 671 | expect(Object.keys(res.arrayFlags.path).length).is.equals(1) 672 | expect(res.arrayFlags.path[0]).is.equals("/var/www/html") 673 | expect(Object.keys(res.arrayFlags.number).length).is.equals(0) 674 | }) 675 | 676 | it("check with multiple paths", async () => { 677 | let res = parseCmd({ 678 | cmd: execFlagCmd, 679 | args: [ 680 | "--path", "/var/www/html", 681 | "--path", "/some/new/path", 682 | "--path", "/some/old/path", 683 | "--path", "/test/path" 684 | ], 685 | }) 686 | 687 | expect(exec).is.false 688 | res = await res.exe() 689 | expect(exec).is.true 690 | 691 | expect(res.args.length).is.equals(0) 692 | expect(res.err).is.undefined 693 | 694 | expect(res).is.not.undefined 695 | expect(res.err).is.undefined 696 | 697 | expect(verbose).is.false 698 | expect(path.length).is.equals(4) 699 | expect(JSON.stringify(path)).is.equals(JSON.stringify([ 700 | "/var/www/html", 701 | "/some/new/path", 702 | "/some/old/path", 703 | "/test/path" 704 | ])) 705 | expect(number.length).is.equals(0) 706 | 707 | expect(res.flags).is.not.undefined 708 | expect(getType(res.flags)).is.equals("array") 709 | expect(res.flags.length).is.equals(0) 710 | expect(res.args.length).is.equals(0) 711 | 712 | expect(res.valueFlags).is.not.undefined 713 | expect(getType(res.valueFlags)).is.equals("object") 714 | expect(Object.keys(res.valueFlags).length).is.equals(0) 715 | 716 | expect(res.arrayFlags).is.not.undefined 717 | expect(getType(res.arrayFlags)).is.equals("object") 718 | expect(Object.keys(res.arrayFlags).length).is.equals(2) 719 | expect(Object.keys(res.arrayFlags.path).length).is.equals(4) 720 | expect(JSON.stringify(res.arrayFlags.path)).is.equals(JSON.stringify([ 721 | "/var/www/html", 722 | "/some/new/path", 723 | "/some/old/path", 724 | "/test/path" 725 | ])) 726 | expect(res.valueFlags.number).is.undefined 727 | }) 728 | 729 | it("check with multiple paths and numbers and verbose", async () => { 730 | let res = parseCmd({ 731 | cmd: execFlagCmd, 732 | args: [ 733 | "--number", "1", 734 | "--path", "/var/www/html", 735 | "--path", "/some/new/path", 736 | "-v", 737 | "--path", "/some/old/path", 738 | "--number", "2", 739 | "--number", "3", 740 | "--number", "4", 741 | "--number", "5", 742 | "--number", "6", 743 | "--path", "/test/path" 744 | ], 745 | }) 746 | 747 | expect(exec).is.false 748 | res = await res.exe() 749 | expect(exec).is.true 750 | 751 | expect(res.args.length).is.equals(0) 752 | expect(res.err).is.undefined 753 | 754 | expect(res).is.not.undefined 755 | expect(res.err).is.undefined 756 | 757 | expect(verbose).is.true 758 | expect(path.length).is.equals(4) 759 | expect(JSON.stringify(path)).is.equals(JSON.stringify([ 760 | "/var/www/html", 761 | "/some/new/path", 762 | "/some/old/path", 763 | "/test/path" 764 | ])) 765 | expect(number.length).is.equals(6) 766 | expect(JSON.stringify(number)).is.equals(JSON.stringify([ 767 | "1", 768 | "2", 769 | "3", 770 | "4", 771 | "5", 772 | "6", 773 | ])) 774 | 775 | expect(res.flags).is.not.undefined 776 | expect(getType(res.flags)).is.equals("array") 777 | expect(res.flags.length).is.equals(1) 778 | expect(res.args.length).is.equals(0) 779 | 780 | expect(res.valueFlags).is.not.undefined 781 | expect(getType(res.valueFlags)).is.equals("object") 782 | expect(Object.keys(res.valueFlags).length).is.equals(0) 783 | 784 | expect(res.arrayFlags).is.not.undefined 785 | expect(getType(res.arrayFlags)).is.equals("object") 786 | expect(Object.keys(res.arrayFlags).length).is.equals(2) 787 | expect(Object.keys(res.arrayFlags.path).length).is.equals(4) 788 | expect(JSON.stringify(res.arrayFlags.path)).is.equals(JSON.stringify([ 789 | "/var/www/html", 790 | "/some/new/path", 791 | "/some/old/path", 792 | "/test/path" 793 | ])) 794 | expect(Object.keys(res.arrayFlags.number).length).is.equals(6) 795 | expect(JSON.stringify(res.arrayFlags.number)).is.equals(JSON.stringify([ 796 | "1", 797 | "2", 798 | "3", 799 | "4", 800 | "5", 801 | "6", 802 | ])) 803 | }) 804 | 805 | it("check error on unknown arg", async () => { 806 | let res = parseCmd({ 807 | cmd: execFlagCmd, 808 | args: [ 809 | "--number", "1", 810 | "--path", "/var/www/html", 811 | "--path", "/some/new/path", 812 | "-v", 813 | "--path", "/some/old/path", 814 | "--number", "2", 815 | "--number", "3", 816 | "asdasd", 817 | "--number", "4", 818 | "--number", "5", 819 | "--number", "6", 820 | "--path", "/test/path" 821 | ], 822 | }) 823 | 824 | expect(typeof res.err).is.equals("object") 825 | expect(res.err.message).is.equals('Unknown command argument: "asdasd"') 826 | }) 827 | 828 | it("check error on unknown allowed arg", async () => { 829 | let res = parseCmd({ 830 | cmd: { 831 | ...execFlagCmd, 832 | allowUnknownArgs: true, 833 | }, 834 | args: [ 835 | "--number", "1", 836 | "--path", "/var/www/html", 837 | "--path", "/some/new/path", 838 | "-v", 839 | "--path", "/some/old/path", 840 | "--number", "2", 841 | "--number", "3", 842 | "asdasd", 843 | "--number", "4", 844 | "--number", "5", 845 | "--number", "6", 846 | "--path", "/test/path" 847 | ], 848 | }) 849 | 850 | expect(exec).is.false 851 | res = await res.exe() 852 | expect(exec).is.true 853 | 854 | expect(res.args.length).is.equals(1) 855 | expect(res.args[0]).is.equals("asdasd") 856 | expect(res.err).is.undefined 857 | 858 | expect(res).is.not.undefined 859 | expect(res.err).is.undefined 860 | 861 | expect(verbose).is.true 862 | expect(path.length).is.equals(4) 863 | expect(JSON.stringify(path)).is.equals(JSON.stringify([ 864 | "/var/www/html", 865 | "/some/new/path", 866 | "/some/old/path", 867 | "/test/path" 868 | ])) 869 | expect(number.length).is.equals(6) 870 | expect(JSON.stringify(number)).is.equals(JSON.stringify([ 871 | "1", 872 | "2", 873 | "3", 874 | "4", 875 | "5", 876 | "6", 877 | ])) 878 | 879 | expect(res.flags).is.not.undefined 880 | expect(getType(res.flags)).is.equals("array") 881 | expect(res.flags.length).is.equals(1) 882 | expect(res.args.length).is.equals(1) 883 | expect(res.args[0]).is.equals("asdasd") 884 | 885 | expect(res.valueFlags).is.not.undefined 886 | expect(getType(res.valueFlags)).is.equals("object") 887 | expect(Object.keys(res.valueFlags).length).is.equals(0) 888 | 889 | expect(res.arrayFlags).is.not.undefined 890 | expect(getType(res.arrayFlags)).is.equals("object") 891 | expect(Object.keys(res.arrayFlags).length).is.equals(2) 892 | expect(Object.keys(res.arrayFlags.path).length).is.equals(4) 893 | expect(JSON.stringify(res.arrayFlags.path)).is.equals(JSON.stringify([ 894 | "/var/www/html", 895 | "/some/new/path", 896 | "/some/old/path", 897 | "/test/path" 898 | ])) 899 | expect(Object.keys(res.arrayFlags.number).length).is.equals(6) 900 | expect(JSON.stringify(res.arrayFlags.number)).is.equals(JSON.stringify([ 901 | "1", 902 | "2", 903 | "3", 904 | "4", 905 | "5", 906 | "6", 907 | ])) 908 | }) 909 | 910 | 911 | it("check error on unknown flag", async () => { 912 | let res = parseCmd({ 913 | cmd: execFlagCmd, 914 | args: [ 915 | "--number", "1", 916 | "--path", "/var/www/html", 917 | "--path", "/some/new/path", 918 | "-v", 919 | "--path", "/some/old/path", 920 | "--number", "2", 921 | "--number", "3", 922 | "--port", 923 | "--number", "4", 924 | "--number", "5", 925 | "--number", "6", 926 | "--path", "/test/path" 927 | ], 928 | }) 929 | 930 | expect(typeof res.err).is.equals("object") 931 | expect(res.err.message).is.equals('Unknown flag: "--port"') 932 | }) 933 | 934 | it("check error on unknown allowed flag", async () => { 935 | let res = parseCmd({ 936 | cmd: { 937 | ...execFlagCmd, 938 | allowUnknownFlags: true, 939 | }, 940 | args: [ 941 | "--number", "1", 942 | "--path", "/var/www/html", 943 | "--path", "/some/new/path", 944 | "-v", 945 | "--path", "/some/old/path", 946 | "--number", "2", 947 | "--number", "3", 948 | "--port", 949 | "--number", "4", 950 | "--number", "5", 951 | "--number", "6", 952 | "--path", "/test/path" 953 | ], 954 | }) 955 | 956 | expect(exec).is.false 957 | res = await res.exe() 958 | expect(exec).is.true 959 | 960 | expect(res.args.length).is.equals(1) 961 | expect(res.args[0]).is.equals("--port") 962 | expect(res.err).is.undefined 963 | 964 | expect(res).is.not.undefined 965 | expect(res.err).is.undefined 966 | 967 | expect(verbose).is.true 968 | expect(path.length).is.equals(4) 969 | expect(JSON.stringify(path)).is.equals(JSON.stringify([ 970 | "/var/www/html", 971 | "/some/new/path", 972 | "/some/old/path", 973 | "/test/path" 974 | ])) 975 | expect(number.length).is.equals(6) 976 | expect(JSON.stringify(number)).is.equals(JSON.stringify([ 977 | "1", 978 | "2", 979 | "3", 980 | "4", 981 | "5", 982 | "6", 983 | ])) 984 | 985 | expect(res.flags).is.not.undefined 986 | expect(getType(res.flags)).is.equals("array") 987 | expect(res.flags.length).is.equals(1) 988 | expect(res.args.length).is.equals(1) 989 | expect(res.args[0]).is.equals("--port") 990 | 991 | expect(res.valueFlags).is.not.undefined 992 | expect(getType(res.valueFlags)).is.equals("object") 993 | expect(Object.keys(res.valueFlags).length).is.equals(0) 994 | 995 | expect(res.arrayFlags).is.not.undefined 996 | expect(getType(res.arrayFlags)).is.equals("object") 997 | expect(Object.keys(res.arrayFlags).length).is.equals(2) 998 | expect(Object.keys(res.arrayFlags.path).length).is.equals(4) 999 | expect(JSON.stringify(res.arrayFlags.path)).is.equals(JSON.stringify([ 1000 | "/var/www/html", 1001 | "/some/new/path", 1002 | "/some/old/path", 1003 | "/test/path", 1004 | ])) 1005 | expect(Object.keys(res.arrayFlags.number).length).is.equals(6) 1006 | expect(JSON.stringify(res.arrayFlags.number)).is.equals(JSON.stringify([ 1007 | "1", 1008 | "2", 1009 | "3", 1010 | "4", 1011 | "5", 1012 | "6", 1013 | ])) 1014 | }) 1015 | }) 1016 | 1017 | 1018 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": true, 3 | "compilerOptions": { 4 | /* Basic Options */ 5 | "target": "ES5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 6 | "module": "CommonJS", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 7 | "lib": [ 8 | "ESNext", 9 | "ES6", 10 | "ES5" 11 | ], /* Specify library files to be included in the compilation. */ 12 | "allowJs": false, /* Allow javascript files to be compiled. */ 13 | // "skipLibCheck": true, 14 | // "checkJs": true, /* Report errors in .js files. */ 15 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 16 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 17 | "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 18 | "sourceMap": true, /* Generates corresponding '.map' file. */ 19 | // "outFile": "./", /* Concatenate and emit output to single file. */ 20 | "outDir": "dist", /* Redirect output structure to the directory. */ 21 | "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 22 | // "composite": true, /* Enable project compilation */ 23 | // "incremental": true, /* Enable incremental compilation */ 24 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 25 | "removeComments": true, /* Do not emit comments to output. */ 26 | // "noEmit": true, /* Do not emit outputs. */ 27 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 28 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 29 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 30 | /* Strict Type-Checking Options */ 31 | // "strict": true, /* Enable all strict type-checking options. */ 32 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 33 | // "strictNullChecks": true, /* Enable strict null checks. */ 34 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 35 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 36 | //"strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 37 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 38 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 39 | /* Additional Checks */ 40 | //"noUnusedLocals": true, /* Report errors on unused locals. */ 41 | //"noUnusedParameters": false, /* Report errors on unused parameters. */ 42 | //"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 43 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 44 | /* Module Resolution Options */ 45 | "resolveJsonModule": true, 46 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 47 | "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 48 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 49 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 50 | "typeRoots": [ 51 | "./node_modules/@types", 52 | ], /* List of folders to include type definitions from. */ 53 | "types": [ 54 | "node" 55 | ], /* Type declaration files to be included in compilation. */ 56 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 57 | // "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 58 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 59 | /* Source Map Options */ 60 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 61 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 62 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 63 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 64 | /* Experimental Options */ 65 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 66 | "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 67 | }, 68 | "include": [ 69 | "src/**/*.ts", 70 | ], 71 | "exclude": [ 72 | "dist", 73 | "node_modules" 74 | ] 75 | } --------------------------------------------------------------------------------