@qigy/run
Version:
A collection of tools capable of executing complex commands through their abbreviation.
135 lines (131 loc) • 4.83 kB
JavaScript
const { fs, spawn } = require('./libs');
const { Item, Result, configPath, batPath, uiPath, includesPro, isUnix, ulid, welcome, yellow } = require('./utils');
class Core {
list = [];
constructor() {
this.#readCfg();
}
get indexMapping() {
return this.list.reduce((pre, next, index) => {
pre.set(next.alias, index);
return pre;
}, new Map());
}
get commandMapping() {
return this.list.reduce((pre, next, index) => {
pre.set(next.alias, next.command);
return pre;
}, new Map());
}
get aliasList() {
return this.list.map((it) => it.alias);
}
#readCfg() {
const config = fs.readFileSync(configPath, 'utf-8');
this.list = JSON.parse(config);
}
#writeCfg() {
fs.writeFileSync(configPath, JSON.stringify(this.list, null, 2), 'utf-8');
}
async get(keyword = '') {
await this.#readCfg();
const query = decodeURIComponent(keyword);
const result = this.list.filter((it) => {
return includesPro(it.alias, query) || includesPro(it.command, query) || includesPro(it.remark || '', query);
});
return new Result(true, result);
}
async del(aliasList = []) {
const validData = aliasList.filter(Boolean);
if (!validData.length) return new Result(false, null, 'Alias cannot be empty');
const target = validData.find((it) => !this.aliasList.includes(it));
if (target) return new Result(false, null, `Alias ${target} is not exists`);
for (const alias of validData) {
const index = this.indexMapping.get(alias);
this.list.splice(index, 1);
}
await this.#writeCfg();
return new Result(true, null, `${validData.toString()} are deleted successfully`);
}
async add(alias, command, remark = '') {
if (!alias || !command) return new Result(false, null, 'Alias or Command cannot be empty');
if (this.aliasList.includes(alias)) return new Result(false, null, `Alias ${alias} is already exists`);
this.list.push(new Item(alias, command, remark));
await this.#writeCfg();
return new Result(true, null, `Alias ${alias} are added successfully`);
}
async update(alias, command, remark = '') {
if (!alias || !command) return new Result(false, null, 'Alias or Command cannot be empty');
if (!this.aliasList.includes(alias)) return new Result(false, null, `Alias ${alias} is not exists`);
const index = this.indexMapping.get(alias);
this.list[index] = new Item(alias, command, remark);
await this.#writeCfg();
return new Result(true, null, `Alias ${alias} are updated successfully`);
}
ui() {
const { status } = spawn.sync('node', ['server.js'], {
cwd: uiPath,
stdio: 'inherit'
});
return status;
}
run(alias = '', options = []) {
if (!alias) return new Result(false, null, 'Alias cannot be empty');
let command = this.commandMapping.get(alias);
if (!command) return new Result(false, null, `Alias ${alias} is not exists`);
const varList = [...new Set(command.match(/\{([^}]*)\}/gi))];
for (const i in varList) {
command = command.replaceAll(varList[i], options[i] || '');
}
options = options.slice(varList.length);
if (!isUnix) command = command.replaceAll('/', '\\');
fs.writeFileSync(batPath, command);
const { status } = spawn.sync(isUnix ? 'sh' : batPath, [...(isUnix ? [batPath] : []), ...options], {
stdio: 'inherit'
});
return status;
}
async import(cfgList = []) {
if (!Array.isArray(cfgList) || !cfgList.length) {
return new Result(false, null, 'Config list cannot be empty');
}
const tmp = {};
const newCfg = cfgList.reduce((pre, it) => {
if (!it.alias || !it.command) return pre;
let alias = it.alias;
const command = it.command;
const remark = it.remark || '';
if (!tmp[alias]) {
tmp[alias] = true;
} else {
alias = `${alias}_${ulid()}`;
}
if (this.aliasList.includes(alias)) {
alias = `${alias}_${ulid()}`;
}
pre.push({ alias, command, remark });
return pre;
}, []);
this.list = [...this.list, ...newCfg];
await this.#writeCfg();
return new Result(true, null, `Import successfully`);
}
doc() {
console.log(welcome());
const document = `
Commands:
add <alias> <command> <?remark> Add the config [command] or [remark] corresponding to [alias]
update <alias> <command> <?remark> Update the config [command] or [remark] corresponding to [alias]
del <alias> Delete the config corresponding to [alias]
get [?keyword] Get the config corresponding to [keyword]
ui Open the UI interface
Use:
You can use ${yellow('run alias')} to execute the corresponding command
Variable:
set: run add md "mkdir { dirName }"
use: run md dirName
`;
console.log(document);
}
}
module.exports = new Core();