@moostjs/event-cli
Version:
@moostjs/event-cli
459 lines (451 loc) • 14.1 kB
JavaScript
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(`[36m(${aliasTypes[aliasType]})[32m${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;
}
});