UNPKG

@sudoo/coco

Version:

:ocean: A simple command line tool framework

136 lines (135 loc) 4.72 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const declare_1 = require("../panic/declare"); const util_1 = require("./util"); class Command { constructor(command) { this._command = command; this._arguments = []; this._options = []; this._listeners = []; } static create(command) { return new Command([command]); } static commands(commands) { return new Command(commands); } static multiple(...commands) { return new Command(commands); } static root() { return new Command([]); } get commands() { return this._command; } get simulate() { return this._command.join(' '); } match(argv) { return this._command.every((value, index) => { if (value === argv[index]) { return true; } return false; }); } argument(arg, ...args) { this._arguments.push(arg, ...args); return this; } arguments(args) { this._arguments.push(...args); return this; } option(option, ...options) { this._options.push(option, ...options); return this; } options(options) { this._options.push(...options); return this; } execute(args, globalOptions) { return __awaiter(this, void 0, void 0, function* () { const shifted = args.slice(this._command.length); const record = this.parseArgs(shifted, globalOptions); const promises = this._listeners.map((executable) => { return executable(record); }); yield Promise.all(promises); return; }); } then(func) { this._listeners.push(func); return this; } findOption(key, globalOptions) { for (const option of this._options.concat(globalOptions)) { if (option.match(key)) { return option; } } return null; } parseArgs(args, globalOptions) { const result = {}; const tempArguments = []; const matchOptionSet = new Set(); for (let pointer = 0; pointer < args.length; pointer++) { const current = args[pointer]; if (util_1.isOption(current)) { const option = this.findOption(current, globalOptions); if (!option) { throw declare_1.panic.code(declare_1.ERROR_CODE.OPTION_NOT_FOUND, current); } if (matchOptionSet.has(option)) { throw declare_1.panic.code(declare_1.ERROR_CODE.DUPLICATED_OPTION, current); } if (option.isBoolean) { result[option.name] = "true"; } else { const next = args[++pointer]; result[option.name] = next; } matchOptionSet.add(option); } else { tempArguments.push(current); } } if (tempArguments.length > this._arguments.length) { throw declare_1.panic.code(declare_1.ERROR_CODE.TOO_MANY_ARGUMENTS); } for (const argument of this._arguments) { const first = tempArguments.shift(); if (!first) { if (!argument.isOptional) { throw declare_1.panic.code(declare_1.ERROR_CODE.INSUFFICIENT_ARGUMENTS); } return result; } result[argument.name] = first; } const optionRequirementsMat = [...this._options, ...globalOptions] .filter((option) => option.isRequired) .every((option) => matchOptionSet.has(option)); if (!optionRequirementsMat) { throw declare_1.panic.code(declare_1.ERROR_CODE.REQUIRED_OPTION_INSUFFICIENT); } return result; } } exports.Command = Command;