feat(): Begin implementing class 'This'

This commit is contained in:
Chris Daßler 2024-06-29 11:11:48 +02:00
parent a2674bfa0e
commit 94cc6816d5
8 changed files with 249 additions and 109 deletions

View File

@ -1,19 +1,31 @@
#!/usr/bin/env node
const This = require('./this');
const shell = require('shelljs');
// 1) Use shell object with its methods
if (!shell.which('git')) {
shell.echo('Sorry, this script requires git');
shell.exit(1);
class MyUpdateSubCommand extends This {
constructor() {
super();
this.version = '0.0.1';
}
start() {
// Usage
const myUpdateSubCommand = new MyUpdateSubCommand();
// Output: Methods of ExampleClass: [ 'methodOne', 'methodTwo' ]
// Properties of ExampleClass: [ 'propertyOne', 'propertyTwo', 'version' ] and Version: 1.1.0
// myUpdateSubCommand.discovery();
if (!shell.which('git')) {
shell.echo('Sorry, this script requires git');
shell.exit(1);
} else {
shell.echo('Woohoo! You have git installed!');
shell.exit(0);
}
}
}
// 2) or the following 'with' statement to specify that the `shell` object is the default object.
// The statements following the with statement refer to the echo methods, without specifying
// an object. JavaScript assumes the `shell` object for these references.
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with
with (shell) {
echo('hello world');
echo('-n', 'no newline at end -> ');
let str = echo('hello world');
}
// main
const myUpdateSubCommand = new MyUpdateSubCommand();
myUpdateSubCommand.start();

View File

@ -10,4 +10,4 @@
"devDependencies": {
"prettier": "^3.3.2"
}
}
}

66
pm
View File

@ -1,7 +1,7 @@
#!/usr/bin/env node
const path = require('path');
const { Command } = require('commander');
const This = require('./this');
const {Command} = require('commander');
const program = new Command();
// Example of subcommands which are implemented as stand-alone executable files.
@ -10,28 +10,46 @@ const program = new Command();
// this tells Commander that you're going to use a stand-alone executable for the subcommand.
//
// Only `install` and `list` are implemented, see pm-install and pm-list.js
class Pm extends This {
constructor() {
super();
this.version = '0.0.1';
}
program
.name(path.parse(process.argv[1]).base)
.version('0.0.1')
.description('Fake package manager')
.command('install [name]', 'install one or more packages')
.alias('i')
.command('search [query]', 'search with optional query')
.alias('s')
.command('update', 'update installed packages', {
executableFile: 'myUpdateSubCommand',
})
.command('list', 'list packages installed', { isDefault: false });
start() {
// Usage
const pm = new Pm();
// Output: Methods of ExampleClass: [ 'methodOne', 'methodTwo' ]
// Properties of ExampleClass: [ 'propertyOne', 'propertyTwo', 'version' ] and Version: 1.1.0
// pm.discovery();
program.parse();
program
.name(this.scriptName)
.version('0.0.1')
.description('Fake package manager')
.command('install [name]', 'install one or more packages')
.alias('i')
.command('search [query]', 'search with optional query')
.alias('s')
.command('update', 'update installed packages', {
executableFile: 'myUpdateSubCommand',
})
.command('list', 'list packages installed', {isDefault: false});
// 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
program.parse();
// 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
}
}
// main
const pm = new Pm();
pm.start();

View File

@ -1,42 +1,61 @@
#!/usr/bin/env node
const path = require('path');
const { Command } = require('commander');
const This = require('./this');
const {Command} = require('commander');
const program = new Command();
const errorColor = (str) => {
// Add ANSI escape codes to display text in red.
return `\x1b[31m${str}\x1b[0m`;
};
class PmInstall extends This {
constructor() {
super();
this.version = '0.0.1';
}
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();
program
.name(this.scriptName)
.version('0.0.1')
.description('Install package with fake package manager')
.usage('-n 3 32 -l x y z -- op')
.configureOutput({
// Visibly override write routines as example!
//writeOut: (str) => process.stdout.write(`[OUT] ${str}`),
writeErr: (str) => process.stdout.write(`[ERR] ${str}`),
// Highlight errors in color.
outputError: (str, write) => write(errorColor(str)),
});
program
.option('-n, --number <numbers...>', 'specify numbers')
.option('-l, --letter [letters...]', 'specify letters')
.parse();
// console.log('options array');
// console.log(program.options.map(o => o.flags));
// console.log('visible options');
// const helper = program.createHelp();
// console.log(helper.visibleOptions(program).map(o => o.flags));
if (Object.keys(program.opts()).length || program.args.length) {
console.log('Options: ', program.opts());
console.log('Remaining arguments: ', program.args);
} else {
program.outputHelp();
}
}
}
program
.name(path.parse(process.argv[1]).base)
.version('0.0.1')
.description('Install package with fake package manager')
.usage("-n 3 32 -l x y z -- op")
.configureOutput({
// Visibly override write routines as example!
//writeOut: (str) => process.stdout.write(`[OUT] ${str}`),
writeErr: (str) => process.stdout.write(`[ERR] ${str}`),
// Highlight errors in color.
outputError: (str, write) => write(errorColor(str))
});
program
.option('-n, --number <numbers...>', 'specify numbers')
.option('-l, --letter [letters...]', 'specify letters')
.parse();
// console.log('options array');
// console.log(program.options.map(o => o.flags));
// console.log('visible options');
// const helper = program.createHelp();
// console.log(helper.visibleOptions(program).map(o => o.flags));
if (Object.keys(program.opts()).length || program.args.length) {
console.log('Options: ', program.opts());
console.log('Remaining arguments: ', program.args);
} else {
program.outputHelp();
}
// main
const pmInstall = new PmInstall();
pmInstall.start();

29
pm-list
View File

@ -1,11 +1,26 @@
#!/usr/bin/env node
const path = require('path');
const { Command } = require('commander');
const This = require('./this');
const {Command} = require('commander');
const program = new Command();
program
.name(path.parse(process.argv[1]).base)
.version('0.0.1')
.description('List packages of fake package manager')
.outputHelp();
class PmList extends This {
constructor() {
super();
this.version = '0.0.1';
}
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();
}
}
// main
const pmList = new PmList();
pmList.start();

View File

@ -1,11 +1,26 @@
#!/usr/bin/env node
const path = require('path');
const { Command } = require('commander');
const This = require('./this');
const {Command} = require('commander');
const program = new Command();
program
.name(path.parse(process.argv[1]).base)
.version('0.0.1')
.description('Search packages of fake package manager')
.outputHelp();
class PmSearch extends This {
constructor() {
super();
this.version = '0.0.1';
}
start() {
// Usage
const pmSearch = new PmSearch();
// Output: Methods of ExampleClass: [ 'methodOne', 'methodTwo' ]
// Properties of ExampleClass: [ 'propertyOne', 'propertyTwo', 'version' ] and Version: 1.1.0
// pmSearch.discovery();
program.name(this.scriptName).version('0.0.1').description('Search packages of fake package manager').outputHelp();
}
}
// main
const pmSearch = new PmSearch();
pmSearch.start();

View File

@ -21,37 +21,43 @@ devDependencies:
version: 3.3.2
packages:
/balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
resolution:
{integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: false
/brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
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==}
resolution:
{integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
dev: false
/concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
resolution:
{integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: false
/fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
resolution:
{integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: false
/function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
resolution:
{integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
dev: false
/glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
resolution:
{integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
dependencies:
fs.realpath: 1.0.0
@ -63,14 +69,16 @@ packages:
dev: false
/hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
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==}
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
@ -78,62 +86,73 @@ packages:
dev: false
/inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
resolution:
{integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: false
/interpret@1.4.0:
resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
resolution:
{integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
engines: {node: '>= 0.10'}
dev: false
/is-core-module@2.14.0:
resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==}
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==}
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==}
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==}
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==}
resolution:
{integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
dev: false
/path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
resolution:
{integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: false
/prettier@3.3.2:
resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==}
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==}
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==}
resolution:
{integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
hasBin: true
dependencies:
is-core-module: 2.14.0
@ -142,7 +161,8 @@ packages:
dev: false
/shelljs@0.8.5:
resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==}
resolution:
{integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==}
engines: {node: '>=4'}
hasBin: true
dependencies:
@ -152,10 +172,12 @@ packages:
dev: false
/supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
resolution:
{integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
dev: false
/wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
resolution:
{integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: false

39
this Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env node
const path = require('path');
class This {
constructor() {
this.version = '0.0.1'; // Default version, can be overridden in subclasses
this.scriptName = path.parse(process.argv[1]).base;
}
getClassName() {
return this.constructor.name;
}
listMethods() {
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(this)).filter(
(prop) => typeof this[prop] === 'function' && prop !== 'constructor' && !prop.startsWith('_')
);
return methods;
}
listProperties() {
const properties = Object.keys(this).filter((prop) => typeof this[prop] !== 'function');
return properties;
}
discovery() {
console.log(`My name is '${this.getClassName()}' and I have the version: ${this.version}`);
console.log(`My methods are:`, this.listMethods());
console.log(`My properties are:`, this.listProperties());
}
// Method to create a context manager for this instance
withContext(callback) {
callback(this);
}
}
module.exports = This;