UNPKG

@moostjs/event-cli

Version:
459 lines (451 loc) 14.1 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); let moost = require("moost"); let _wooksjs_event_cli = require("@wooksjs/event-cli"); let _wooksjs_event_core = require("@wooksjs/event-core"); //#region packages/event-cli/src/meta-types.ts function getCliMate() { return (0, moost.getMoostMate)(); } //#endregion //#region packages/event-cli/src/decorators/cli.decorator.ts /** * ## Define CLI Command * ### @MethodDecorator * * Command path segments may be separated by / or space. * * For example the folowing path are interpreted the same: * - "command test use:dev :name" * - "command/test/use:dev/:name" * * Where name will become an argument * * @param path - command path * @returns */ function Cli(path) { return getCliMate().decorate("handlers", { path: path?.replaceAll(/\s+/g, "/"), type: "CLI" }, true); } /** * ## Define CLI Command Alias * ### @MethodDecorator * * Use it to define alias for @Cli('...') command * * @param path - command alias path * @returns */ function CliAlias(alias) { return getCliMate().decorate("cliAliases", alias, true); } /** * ## Define CLI Example * ### @MethodDecorator * * Use it to define example for Cli Help display * * @param path - command alias path * @returns */ function CliExample(cmd, description) { return getCliMate().decorate("cliExamples", { cmd, description }, true); } //#endregion //#region packages/event-cli/src/utils.ts function formatParams(keys) { return [keys].flat().map((n) => n.length === 1 ? `-${n}` : `--${n}`); } //#endregion //#region packages/event-cli/src/decorators/option.decorator.ts /** * ## Define CLI Option * ### @ParameterDecorator * Use together with @Description('...') to document cli option * * ```ts * │ @Cli('command') * │ command( * │ @Description('Test option...') * │ @CliOption('test', 't') * │ test: boolean, * │ ) { * │ return `test=${ test }` * │ } * ``` * * @param keys list of keys (short and long alternatives) * @returns */ function CliOption(...keys) { const mate = getCliMate(); return mate.apply(mate.decorate("cliOptionsKeys", keys, false), (0, moost.Resolve)(() => (0, _wooksjs_event_cli.useCliOption)(keys[0]), formatParams(keys).join(", "))); } /** * ## Define Global CLI Option * ### @ClassDecorator * The option described here will appear in every command instructions * @param option keys and description of CLI option * @returns */ function CliGlobalOption(option) { return getCliMate().decorate("cliOptions", option, true); } //#endregion //#region packages/event-cli/src/event-cli.ts function _define_property$1(obj, key, value) { if (key in obj) Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true }); else obj[key] = value; return obj; } const LOGGER_TITLE = "moost-cli"; /** * ## Moost Cli Adapter * * Moost Adapter for CLI events * * ```ts * │ // Quick example * │ import { MoostCli, Cli, CliOption, cliHelpInterceptor } from '@moostjs/event-cli' * │ import { Moost, Param } from 'moost' * │ * │ class MyApp extends Moost { * │ @Cli('command/:arg') * │ command( * │ @Param('arg') * │ arg: string, * │ @CliOption('test', 't') * │ test: boolean, * │ ) { * │ return `command run with flag arg=${ arg }, test=${ test }` * │ } * │ } * │ * │ const app = new MyApp() * │ app.applyGlobalInterceptors(cliHelpInterceptor()) * │ * │ const cli = new MoostCli() * │ app.adapter(cli) * │ app.init() * ``` */ var MoostCli = class { async onNotFound() { const pathParams = (0, _wooksjs_event_core.current)().get(_wooksjs_event_cli.cliKind.keys.pathParams) || []; const response = await (0, moost.defineMoostEventHandler)({ loggerTitle: LOGGER_TITLE, getIterceptorHandler: () => this.moost?.getGlobalInterceptorHandler(), getControllerInstance: () => this.moost, callControllerMethod: () => void 0, logErrors: this.opts?.debug, targetPath: "", handlerType: "__SYSTEM__" })(); if (response === void 0) this.cliApp.onUnknownCommand(pathParams); return response; } onInit(moost$1) { this.moost = moost$1; const boolean = Object.entries(this.optionTypes).filter(([_key, val]) => val.length === 1 && val[0] === Boolean).map(([key, _val]) => key); this.cliApp.run(void 0, { boolean }); } bindHandler(opts) { let fn; for (const handler of opts.handlers) { if (handler.type !== "CLI") continue; const path = typeof handler.path === "string" ? handler.path : typeof opts.method === "string" ? opts.method : ""; const prefix = opts.prefix.replaceAll(/\s+/g, "/") || ""; const makePath = (p) => `${prefix}/${p}`.replaceAll(/\/\/+/g, "/").replaceAll(/\/\\:/g, "\\:").replaceAll(/^\/+/g, ""); const targetPath = makePath(path); fn = (0, moost.defineMoostEventHandler)({ loggerTitle: LOGGER_TITLE, getIterceptorHandler: opts.getIterceptorHandler, getControllerInstance: opts.getInstance, controllerMethod: opts.method, controllerName: opts.controllerName, resolveArgs: opts.resolveArgs, logErrors: this.opts?.debug, targetPath, controllerPrefix: opts.prefix, handlerType: handler.type }); const meta = getCliMate().read(opts.fakeInstance, opts.method); const classMeta = getCliMate().read(opts.fakeInstance); const cliOptions = /* @__PURE__ */ new Map(); [ ...this.opts?.globalCliOptions?.length ? this.opts.globalCliOptions : [], ...classMeta?.cliOptions || [], ...meta?.params ? meta.params.filter((param) => param.cliOptionsKeys?.length).map((param) => ({ keys: param.cliOptionsKeys, value: typeof param.value === "string" ? param.value : "", description: param.description || "", type: param.type })) : [] ].forEach((o) => cliOptions.set(o.keys[0], o)); const aliases = []; if (meta?.cliAliases) for (const alias of meta.cliAliases) { const targetPath = makePath(alias); aliases.push(targetPath); } const cliOptionsArray = Array.from(cliOptions.values()); cliOptionsArray.forEach((o) => { for (const key of o.keys) { if (!this.optionTypes[key]) this.optionTypes[key] = []; if (!this.optionTypes[key].includes(o.type)) this.optionTypes[key].push(o.type); } }); const args = {}; meta?.params.filter((p) => p.paramSource === "ROUTE" && p.description).forEach((p) => args[p.paramName] = p.description); const routerBinding = this.cliApp.cli(targetPath, { description: meta?.description || "", options: cliOptionsArray, args, aliases, examples: meta?.cliExamples || [], handler: fn, onRegister: (path, aliasType, route) => { opts.register(handler, path, route?.getArgs() || routerBinding.getArgs()); if (this.opts?.debug) opts.logHandler(`(${aliasTypes[aliasType]})${path}`); } }); opts.register(handler, targetPath, routerBinding.getArgs()); } } constructor(opts) { _define_property$1(this, "opts", void 0); _define_property$1(this, "name", void 0); _define_property$1(this, "cliApp", void 0); _define_property$1(this, "optionTypes", void 0); _define_property$1(this, "moost", void 0); this.opts = opts; this.name = "cli"; this.optionTypes = {}; const cliAppOpts = opts?.wooksCli; if (cliAppOpts && cliAppOpts instanceof _wooksjs_event_cli.WooksCli) this.cliApp = cliAppOpts; else if (cliAppOpts) this.cliApp = (0, _wooksjs_event_cli.createCliApp)({ ...cliAppOpts, onNotFound: this.onNotFound.bind(this) }); else this.cliApp = (0, _wooksjs_event_cli.createCliApp)({ onNotFound: this.onNotFound.bind(this) }); if (!opts?.debug) (0, moost.setInfactLoggingOptions)({ newInstance: false, error: false, warn: false }); } }; const aliasTypes = [ "CLI", "CLI-alias", "CLI-alias*", "CLI-alias*" ]; //#endregion //#region packages/event-cli/src/interceptors/help.interceptor.ts /** * ### Interceptor Factory for CliHelpRenderer * * By default intercepts cli calls with flag --help * and prints help. * * ```js * new Moost().applyGlobalInterceptors(cliHelpInterceptor({ colors: true })) * ``` * @param opts {} { helpOptions: ['help', 'h'], colors: true } cli options to invoke help renderer * @returns TInterceptorDef */ const cliHelpInterceptor = (opts) => (0, moost.defineBeforeInterceptor)((reply) => { try { if ((0, _wooksjs_event_cli.useAutoHelp)(opts?.helpOptions, opts?.colors)) { reply(""); return; } } catch (error) {} if (opts?.lookupLevel) { const { getMethod } = (0, moost.useControllerContext)(); if (!getMethod()) (0, _wooksjs_event_cli.useCommandLookupHelp)(opts.lookupLevel); } }, moost.TInterceptorPriority.BEFORE_ALL); /** * ## @Decorator * ### Interceptor Factory for CliHelpRenderer * * By default intercepts cli calls with flag --help * and prints help. * * ```ts * // default configuration * • @CliHelpInterceptor({ helpOptions: 'help', colors: true }) * * // additional option -h to invoke help renderer * • @CliHelpInterceptor({ helpOptions: ['help', 'h'], colors: true }) * * // redefine cli option to invoke help renderer * • @CliHelpInterceptor({ helpOptions: ['usage'] }) * ``` * * @param opts {} { helpOptions: ['help', 'h'], colors: true } cli options to invoke help renderer * @returns Decorator */ const CliHelpInterceptor = (...opts) => (0, moost.Intercept)(cliHelpInterceptor(...opts)); //#endregion //#region packages/event-cli/src/quick-cli.ts function _define_property(obj, key, value) { if (key in obj) Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true }); else obj[key] = value; return obj; } /** * Quick CLI App factory class. * * Use this class to quickly build a CLI application with controllers, help options, * and global CLI options. It extends the Moost class and wraps the initialization of MoostCli. * * @example * ```typescript * import { CliApp } from '@wooksjs/event-cli' * import { Commands } from './commands.controller.ts' * new CliApp() * .controllers(Commands) * .useHelp({ name: 'myCli' }) * .useOptions([{ keys: ['help'], description: 'Display instructions for the command.' }]) * .start() * ``` */ var CliApp = class extends moost.Moost { /** * Registers one or more CLI controllers. * * (Shortcut for `registerControllers` method.) * * @param {...(object|Function|[string, object|Function])} controllers - List of controllers. * Each controller can be an object, a class, or a tuple with a name and the controller. * @returns {this} The CliApp instance for method chaining. */ controllers(...controllers) { return this.registerControllers(...controllers); } /** * Configures the CLI help options. * * This method sets the help options for the CLI. It ensures that colored output is enabled * (unless explicitly disabled) and that the lookup level defaults to 3 if not provided. * * @param {THelpOptions} helpOpts - Help options configuration. * @param {boolean} helpOpts.colors - Enable colored output. * @param {number} helpOpts.lookupLevel - Level for help lookup. * @returns {this} The CliApp instance for method chaining. */ useHelp(helpOpts) { this._helpOpts = helpOpts; if (this._helpOpts.colors !== false) this._helpOpts.colors = true; if (typeof this._helpOpts.lookupLevel !== "number") this._helpOpts.lookupLevel = 3; return this; } /** * Sets the global CLI options. * * @param {TMoostCliOpts['globalCliOptions']} globalOpts - Global options for the CLI. * @returns {this} The CliApp instance for method chaining. */ useOptions(globalOpts) { this._globalOpts = globalOpts; return this; } /** * Starts the CLI application. * * This method creates a MoostCli instance using the configured help and global options, * attaches it via the adapter, applies the CLI help interceptor (if help options are set), * and then initializes the application. * * @returns {any} The result of the initialization process. */ start() { const cli = new MoostCli({ wooksCli: { cliHelp: this._helpOpts ? { name: this._helpOpts.name, title: this._helpOpts.title, maxWidth: this._helpOpts.maxWidth, maxLeft: this._helpOpts.maxLeft, mark: this._helpOpts.mark } : void 0 }, globalCliOptions: this._globalOpts }); this.adapter(cli); if (this._helpOpts) this.applyGlobalInterceptors(cliHelpInterceptor({ colors: this._helpOpts.colors, lookupLevel: this._helpOpts.lookupLevel })); return this.init(); } constructor(...args) { super(...args), _define_property(this, "_helpOpts", void 0), _define_property(this, "_globalOpts", void 0); } }; //#endregion exports.Cli = Cli; exports.CliAlias = CliAlias; exports.CliApp = CliApp; exports.CliExample = CliExample; exports.CliGlobalOption = CliGlobalOption; exports.CliHelpInterceptor = CliHelpInterceptor; exports.CliOption = CliOption; Object.defineProperty(exports, 'Controller', { enumerable: true, get: function () { return moost.Controller; } }); Object.defineProperty(exports, 'Description', { enumerable: true, get: function () { return moost.Description; } }); Object.defineProperty(exports, 'Intercept', { enumerable: true, get: function () { return moost.Intercept; } }); exports.MoostCli = MoostCli; Object.defineProperty(exports, 'Optional', { enumerable: true, get: function () { return moost.Optional; } }); Object.defineProperty(exports, 'Param', { enumerable: true, get: function () { return moost.Param; } }); exports.cliHelpInterceptor = cliHelpInterceptor; Object.defineProperty(exports, 'cliKind', { enumerable: true, get: function () { return _wooksjs_event_cli.cliKind; } }); Object.defineProperty(exports, 'defineAfterInterceptor', { enumerable: true, get: function () { return moost.defineAfterInterceptor; } }); Object.defineProperty(exports, 'defineBeforeInterceptor', { enumerable: true, get: function () { return moost.defineBeforeInterceptor; } }); Object.defineProperty(exports, 'defineInterceptor', { enumerable: true, get: function () { return moost.defineInterceptor; } });