feat(): Optimize docstring parser for commander and make depending changes

This commit is contained in:
Chris Daßler 2024-06-30 15:28:25 +02:00
parent 64815d15f6
commit e29f085961
9 changed files with 368 additions and 303 deletions

View File

@ -15,3 +15,12 @@ https://unix.stackexchange.com/questions/65235/universal-node-js-shebang
## Set location for npm packages with repl sessions
https://sabljakovich.medium.com/how-to-use-npm-packages-with-node-js-repl-sessions-cd77300ebfe2
## Dependencies versionn
The iSH-App on iOS has the following latest versions available
- nodejs v16.11.1
- npm v7.17.0
These versions are deprecated, but if we want to use these scripts on iSH, we have to make sure they run on that outdated versions.

18
log
View File

@ -13,7 +13,8 @@ class Log extends This {
echo(message) {
/**
* @command
* @program()
* @command()
* @argument('<message>')
*/
console.log(message);
@ -21,7 +22,8 @@ class Log extends This {
success(message) {
/**
* @command
* @program()
* @command()
* @argument('<message>')
*/
console.log(this._echoInGreen(message));
@ -29,7 +31,8 @@ class Log extends This {
info(message) {
/**
* @command
* @program()
* @command()
* @argument('<message>')
*/
console.log(`[INFO] ${message}`);
@ -37,7 +40,8 @@ class Log extends This {
warn(message) {
/**
* @command
* @program()
* @command()
* @argument('<message>')
*/
console.warn(`[WARN] ${this._echoInYellow(message)}`);
@ -45,13 +49,17 @@ class Log extends This {
error(message) {
/**
* @command
* @program()
* @command()
* @argument('<message>')
*/
console.error(`[ERR] ${this._echoInRed(message)}`);
}
start() {
/**
* @program()
*/
this.program.parse();
if (Object.keys(this.program.opts()).length || this.program.args.length) {

230
package-lock.json generated Normal file
View File

@ -0,0 +1,230 @@
{
"name": "once-nodejs",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"commander": "^12.1.0",
"shelljs": "^0.8.5"
},
"devDependencies": {
"prettier": "^3.3.2"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/commander": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
"engines": {
"node": ">=18"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/is-core-module": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz",
"integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==",
"dependencies": {
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/prettier": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
"integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
"dependencies": {
"resolve": "^1.1.6"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
"dependencies": {
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/shelljs": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
"dependencies": {
"glob": "^7.0.0",
"interpret": "^1.0.0",
"rechoir": "^0.6.2"
},
"bin": {
"shjs": "bin/shjs"
},
"engines": {
"node": ">=4"
}
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
}
}

View File

@ -4,7 +4,6 @@
},
"dependencies": {
"commander": "^12.1.0",
"omelette": "^0.4.17",
"shelljs": "^0.8.5"
},
"devDependencies": {

31
pm
View File

@ -1,7 +1,6 @@
#!/usr/bin/env node
const This = require('./this');
const util = require('util');
// Example of subcommands which are implemented as stand-alone executable files.
//
@ -19,6 +18,7 @@ class Pm extends This {
install() {
/**
* @program()
* @command('install one or more packages')
* @alias('i')
*/
@ -27,6 +27,7 @@ class Pm extends This {
search() {
/**
* @program()
* @command('search with optional query')
* @alias('s')
*/
@ -35,6 +36,7 @@ class Pm extends This {
update() {
/**
* @program()
* @command('update installed packages')
* @executable('myUpdateSubCommand')
*/
@ -43,6 +45,7 @@ class Pm extends This {
list() {
/**
* @program()
* @command('list packages installed')
*/
// Calls stand-alone excutable `pm-list` because of @command(<description>) in docstring
@ -118,31 +121,7 @@ class Pm extends This {
}
start() {
this.program.parse();
if (Object.keys(this.program.opts()).length || this.program.args.length) {
// Debugging commander options and arguments
const opts = util.inspect(this.program.opts(), { depth: null, colors: true, showHidden: true });
const args = util.inspect(this.program.args, { depth: null, colors: true, showHidden: true });
this.execCmd(`${this.workingDir}/log echo 'Options: ${opts}'`);
this.execCmd(`${this.workingDir}/log echo 'Remaining arguments: ${args}'`);
} else {
this.program.outputHelp();
}
// applies logDecorator to this.discovery() and binds it to 'this' to maintain the correct context
//const logDecoratedDiscovery = this._logDecorator(this.discovery).bind(this);
//logDecoratedDiscovery();
// Try the following on macOS or Linux:
// ./examples/pm
//
// Try the following:
// ./pm
// ./pm help install
// ./pm install -h
// ./pm install foo bar baz
// ./pm install foo bar baz --force
super.start();
}
}

View File

@ -1,39 +1,23 @@
#!/usr/bin/env node
const This = require('./this');
const util = require('util');
class PmInstall extends This {
constructor() {
super();
this.version = '0.0.1';
this.description = 'Install package with fake package manager'
this.description = 'Install package with fake package manager';
super.init(); // initialize commander with overridden version and description
}
start() {
// Usage
const pmInstall = new PmInstall();
// Output: Methods of ExampleClass: [ 'methodOne', 'methodTwo' ]
// Properties of ExampleClass: [ 'propertyOne', 'propertyTwo', 'version' ] and Version: 1.1.0
// pmInstall.discovery();
this.program
.usage('-n 3 32 -l x y z -- op')
.option('-n, --number <numbers...>', 'specify numbers')
.option('-l, --letter [letters...]', 'specify letters')
this.program.parse();
if (Object.keys(this.program.opts()).length || this.program.args.length) {
// Debugging commander options and arguments
const opts = util.inspect(this.program.opts(), { depth: null, colors: true, showHidden: true });
const args = util.inspect(this.program.args, { depth: null, colors: true, showHidden: true });
this.execCmd(`${this.workingDir}/log echo 'Options: ${opts}'`);
this.execCmd(`${this.workingDir}/log echo 'Remaining arguments: ${args}'`);
} else {
this.program.outputHelp();
}
/**
* @program()
* @usage('-n 3 32 -l x y z -- op')
* @option('-n, --number <numbers...>', 'specify numbers')
* @option('-l, --letter [letters...]', 'specify letters')
*/
super.start();
}
}

12
pm-list
View File

@ -1,23 +1,17 @@
#!/usr/bin/env node
const This = require('./this');
const { Command } = require('commander');
const program = new Command();
class PmList extends This {
constructor() {
super();
this.version = '0.0.1';
this.description = 'List packages of fake package manager';
super.init(); // initialize commander with overridden version and description
}
start() {
// Usage
const pmList = new PmList();
// Output: Methods of ExampleClass: [ 'methodOne', 'methodTwo' ]
// Properties of ExampleClass: [ 'propertyOne', 'propertyTwo', 'version' ] and Version: 1.1.0
// pmList.discovery();
program.name(this.scriptName).version('0.0.1').description('List packages of fake package manager').outputHelp();
super.start();
}
}

View File

@ -1,183 +0,0 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
commander:
specifier: ^12.1.0
version: 12.1.0
omelette:
specifier: ^0.4.17
version: 0.4.17
shelljs:
specifier: ^0.8.5
version: 0.8.5
devDependencies:
prettier:
specifier: ^3.3.2
version: 3.3.2
packages:
/balanced-match@1.0.2:
resolution:
{ integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== }
dev: false
/brace-expansion@1.1.11:
resolution:
{ integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== }
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
dev: false
/commander@12.1.0:
resolution:
{ integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== }
engines: { node: '>=18' }
dev: false
/concat-map@0.0.1:
resolution:
{ integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== }
dev: false
/fs.realpath@1.0.0:
resolution:
{ integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== }
dev: false
/function-bind@1.1.2:
resolution:
{ integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== }
dev: false
/glob@7.2.3:
resolution:
{ integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== }
deprecated: Glob versions prior to v9 are no longer supported
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
dev: false
/hasown@2.0.2:
resolution:
{ integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== }
engines: { node: '>= 0.4' }
dependencies:
function-bind: 1.1.2
dev: false
/inflight@1.0.6:
resolution:
{ integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== }
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
dependencies:
once: 1.4.0
wrappy: 1.0.2
dev: false
/inherits@2.0.4:
resolution:
{ integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== }
dev: false
/interpret@1.4.0:
resolution:
{ integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== }
engines: { node: '>= 0.10' }
dev: false
/is-core-module@2.14.0:
resolution:
{ integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== }
engines: { node: '>= 0.4' }
dependencies:
hasown: 2.0.2
dev: false
/minimatch@3.1.2:
resolution:
{ integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== }
dependencies:
brace-expansion: 1.1.11
dev: false
/omelette@0.4.17:
resolution:
{ integrity: sha512-UlU69G6Bhu0XFjw3tjFZ0qyiMUjAOR+rdzblA1nLQ8xiqFtxOVlkhM39BlgTpLFx9fxkm6rnxNNRsS5GxE/yww== }
engines: { node: '>=0.8.0' }
dev: false
/once@1.4.0:
resolution:
{ integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== }
dependencies:
wrappy: 1.0.2
dev: false
/path-is-absolute@1.0.1:
resolution:
{ integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== }
engines: { node: '>=0.10.0' }
dev: false
/path-parse@1.0.7:
resolution:
{ integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== }
dev: false
/prettier@3.3.2:
resolution:
{ integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== }
engines: { node: '>=14' }
hasBin: true
dev: true
/rechoir@0.6.2:
resolution:
{ integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== }
engines: { node: '>= 0.10' }
dependencies:
resolve: 1.22.8
dev: false
/resolve@1.22.8:
resolution:
{ integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== }
hasBin: true
dependencies:
is-core-module: 2.14.0
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
dev: false
/shelljs@0.8.5:
resolution:
{ integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== }
engines: { node: '>=4' }
hasBin: true
dependencies:
glob: 7.2.3
interpret: 1.4.0
rechoir: 0.6.2
dev: false
/supports-preserve-symlinks-flag@1.0.0:
resolution:
{ integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== }
engines: { node: '>= 0.4' }
dev: false
/wrappy@1.0.2:
resolution:
{ integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== }
dev: false

155
this
View File

@ -3,6 +3,7 @@
const path = require('path');
const { Command } = require('commander');
const shell = require('shelljs');
const util = require('util');
class This {
constructor() {
@ -60,8 +61,20 @@ class This {
}
start() {
// Not implemented, so it needs to be overridden!
console.warn(this._echoInYellow(`Method ${this._getCurrentFunctionName()} not implemented!`));
/**
* @program()
*/
this.program.parse();
if (Object.keys(this.program.opts()).length || this.program.args.length) {
// Debugging commander options and arguments
const opts = util.inspect(this.program.opts(), { depth: null, colors: true, showHidden: true });
const args = util.inspect(this.program.args, { depth: null, colors: true, showHidden: true });
this.execCmd(`${this.workingDir}/log echo 'Options: ${opts}'`);
this.execCmd(`${this.workingDir}/log echo 'Remaining arguments: ${args}'`);
} else {
this.program.outputHelp();
}
}
execCmd(cmd) {
@ -102,11 +115,22 @@ class This {
// Utility function to extract docstring from a function, e.g.
//
// start() {
// /**
// * @program()
// * @usage([options] [command])
// * @option('-d, --debug', 'Enable debug mode')
// ..
// }
//
//
// echo(str) {
// /**
// @command
// @argument('<message>')
// */
// * @program()
// * @command()
// * @argument('<message>')
// * @option('-c, --color <name>', 'Prints in color mode')
// */
// console.log(str);
// }
//
@ -128,66 +152,87 @@ class This {
}
// Extract command and arguments
const commandMatch = docString.match(/@command(?:\('([^']*)'\))?/);
const aliasMatch = docString.match(/@alias\('(.+?)'\)/);
const argumentsMatch = /@argument\('(.+?)'\)/g;
const optionsMatch = /@option\('(.+?)'\)/g;
const defaultMatch = docString.match(/@default/);
const executableMatch = docString.match(/@executable\('(.+?)'\)/);
const programRegex = /@program\(\)/;
const usageRegex = /@usage\('(.+?)'\)/;
const commandRegex = /@command(?:\('(.+?)'\))?/;
const aliasRegex = /@alias\('(.+?)'\)/;
const argumentsRegex = /@argument\('(.+?)'\)/g;
const optionsRegex = /@option\('(?<flag>.+?)',\s*'(?<description>.+?)'(?:,\s*'(?<defaultValue>.+?)')?\)/g;
const defaultRegex = /@default/;
const executableRegex = /@executable\('(.+?)'\)/;
if (!commandMatch) {
// No @command tag found
// get regex matches with capture groups
const programMatch = docString.match(programRegex);
const usageMatch = docString.match(usageRegex);
const commandMatch = docString.match(commandRegex);
const aliasMatch = docString.match(aliasRegex);
const defaultMatch = docString.match(defaultRegex);
const executableMatch = docString.match(executableRegex);
if (!programMatch) {
// No @program() tag found
return;
}
const commandName = fn.name;
const commandDescription = commandMatch ? commandMatch[1] : '';
const alias = aliasMatch ? aliasMatch[1] : '';
const defaultCommand = defaultMatch ? true : false;
const executable = executableMatch ? executableMatch[1] : '';
if (commandMatch) {
// Generate the commander statement
const commandName = fn.name;
const commandDescription = commandMatch ? commandMatch[1] : '';
const alias = aliasMatch ? aliasMatch[1] : '';
const defaultCommand = defaultMatch ? true : false;
const executable = executableMatch ? executableMatch[1] : '';
// Generate the commander statement
// Get the function reference
const func = this[commandName].bind(this);
// Get the function reference
const func = this[commandName].bind(this);
// Create a command
// When `.command()` is invoked with a description argument,
// this tells Commander that you're going to use a stand-alone executable for the subcommand.
let command;
if (commandDescription) {
command = this.program.command(commandName, commandDescription, {
isDefault: defaultCommand,
executableFile: executable,
});
// Create a command
// See https://github.com/tj/commander.js?tab=readme-ov-file#quick-start
// When `.command()` is invoked with a description argument,
// this tells Commander that you're going to use a stand-alone executable for the subcommand.
let command;
if (commandDescription) {
// build stand-alone command
command = this.program.command(commandName, commandDescription, {
isDefault: defaultCommand,
executableFile: executable,
});
if (alias) {
command.alias(alias);
if (alias) {
command.alias(alias);
}
} else {
// build command with function name as action
command = this.program.command(commandName, { isDefault: defaultCommand });
// Set the action for the command
command.action((arg) => {
func(arg);
});
}
// If the commandName expects arguments, we add them here
(docString.match(argumentsRegex) || [])
.map((e) => e.replace(argumentsRegex, '$1'))
.forEach((arg) => {
command.argument(arg);
});
// If the commandName expects options, we add them here
// See https://github.com/tj/commander.js?tab=readme-ov-file#options
for (const match of docString.matchAll(optionsRegex)) {
command.option(match.groups['flag'], match.groups['description'], match.groups['defaultValue']);
}
} else {
command = this.program.command(commandName, { isDefault: defaultCommand });
// Add usage
if (usageMatch) {
this.program.usage(usageMatch[1]);
}
// Set the action for the command
command.action((arg) => {
func(arg);
});
}
// If the commandName expects arguments, we add them here
let argMatch;
while ((argMatch = argumentsMatch.exec(docString)) !== null) {
command.argument(argMatch[1]);
}
// If the commandName expects options, we add them here
let optMatch;
while ((optMatch = optionsMatch.exec(docString)) !== null) {
command.option(optMatch[1]);
}
}
_addMethodsToClass(cls, metadata) {
if (cls) {
cls.commands.push(metadata);
// If the program expects options, we add them here
// See https://github.com/tj/commander.js?tab=readme-ov-file#options
for (const match of docString.matchAll(optionsRegex)) {
this.program.option(match.groups['flag'], match.groups['description'], match.groups['defaultValue']);
}
}
}