@moostjs/event-cli 0.2.27 → 0.2.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,8 +35,6 @@ app.init()
35
35
  // "command run with flag test=true"
36
36
  ```
37
37
 
38
-
39
-
40
38
  ## Install
41
39
 
42
40
  `npm install moost @moostjs/event-cli`
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var eventCli = require('@wooksjs/event-cli');
4
- var eventCore = require('@wooksjs/event-core');
5
3
  var moost = require('moost');
4
+ var eventCli = require('@wooksjs/event-cli');
5
+ var cliHelp = require('@prostojs/cli-help');
6
6
 
7
7
  /******************************************************************************
8
8
  Copyright (c) Microsoft Corporation.
@@ -18,6 +18,8 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
18
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
19
  PERFORMANCE OF THIS SOFTWARE.
20
20
  ***************************************************************************** */
21
+ /* global Reflect, Promise */
22
+
21
23
 
22
24
  function __awaiter(thisArg, _arguments, P, generator) {
23
25
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -29,106 +31,241 @@ function __awaiter(thisArg, _arguments, P, generator) {
29
31
  });
30
32
  }
31
33
 
34
+ function getCliMate() {
35
+ return moost.getMoostMate();
36
+ }
37
+
38
+ /**
39
+ * ### setCliHelpForEvent
40
+ * Used internally to set CliHelpRenderer instance for an event state
41
+ * @param cliHelp CliHelpRenderer
42
+ */
43
+ function setCliHelpForEvent(cliHelp) {
44
+ eventCli.useCliContext().store('event').set('cliHelp', cliHelp);
45
+ }
46
+ /**
47
+ * ## useCliHelp
48
+ * ### Composable
49
+ * ```js
50
+ * // example of printing cli instructions
51
+ * const { print } = useCliHelp()
52
+ * print(true)
53
+ * ```
54
+ * @returns
55
+ */
56
+ function useCliHelp() {
57
+ const event = eventCli.useCliContext().store('event');
58
+ const getCliHelp = () => event.get('cliHelp');
59
+ return {
60
+ getCliHelp,
61
+ render: (width, withColors) => getCliHelp().render(event.get('pathParams').join(' '), width, withColors),
62
+ print: (withColors) => getCliHelp().print(event.get('pathParams').join(' '), withColors),
63
+ };
64
+ }
65
+
66
+ const LOGGER_TITLE = 'moost-cli';
67
+ const CONTEXT_TYPE = 'CLI';
68
+ /**
69
+ * ## Moost Cli Adapter
70
+ *
71
+ * Moost Adapter for CLI events
72
+ *
73
+ * ```ts
74
+ * │ // Quick example
75
+ * │ import { MoostCli, Cli, CliOption, cliHelpInterceptor } from '@moostjs/event-cli'
76
+ * │ import { Moost, Param } from 'moost'
77
+ * │
78
+ * │ class MyApp extends Moost {
79
+ * │ @Cli('command/:arg')
80
+ * │ command(
81
+ * │ @Param('arg')
82
+ * │ arg: string,
83
+ * │ @CliOption('test', 't')
84
+ * │ test: boolean,
85
+ * │ ) {
86
+ * │ return `command run with flag arg=${ arg }, test=${ test }`
87
+ * │ }
88
+ * │ }
89
+ * │
90
+ * │ const app = new MyApp()
91
+ * │ app.applyGlobalInterceptors(cliHelpInterceptor())
92
+ * │
93
+ * │ const cli = new MoostCli()
94
+ * │ app.adapter(cli)
95
+ * │ app.init()
96
+ * ```
97
+ */
32
98
  class MoostCli {
33
- constructor(cliApp) {
34
- if (cliApp && cliApp instanceof eventCli.WooksCli) {
35
- this.cliApp = cliApp;
99
+ constructor(opts) {
100
+ this.opts = opts;
101
+ const cliAppOpts = opts === null || opts === void 0 ? void 0 : opts.wooksCli;
102
+ if (cliAppOpts && cliAppOpts instanceof eventCli.WooksCli) {
103
+ this.cliApp = cliAppOpts;
104
+ }
105
+ else if (cliAppOpts) {
106
+ this.cliApp = eventCli.createCliApp(Object.assign(Object.assign({}, cliAppOpts), { onNotFound: this.onNotFound.bind(this) }));
107
+ }
108
+ else {
109
+ this.cliApp = eventCli.createCliApp({
110
+ onNotFound: this.onNotFound.bind(this),
111
+ });
36
112
  }
37
- else if (cliApp) {
38
- this.cliApp = eventCli.createCliApp(cliApp);
113
+ const cliHelpOpts = opts === null || opts === void 0 ? void 0 : opts.cliHelp;
114
+ if (cliHelpOpts && cliHelpOpts instanceof cliHelp.CliHelpRenderer) {
115
+ this.cliHelp = cliHelpOpts;
116
+ }
117
+ else if (cliHelpOpts) {
118
+ this.cliHelp = new cliHelp.CliHelpRenderer(cliHelpOpts);
39
119
  }
40
120
  else {
41
- this.cliApp = eventCli.createCliApp();
121
+ this.cliHelp = new cliHelp.CliHelpRenderer();
122
+ }
123
+ if (!(opts === null || opts === void 0 ? void 0 : opts.debug)) {
124
+ moost.getMoostInfact().silent(true);
42
125
  }
43
126
  }
44
- onInit() {
127
+ onNotFound() {
128
+ var _a;
129
+ return __awaiter(this, void 0, void 0, function* () {
130
+ const pathParams = eventCli.useCliContext().store('event').get('pathParams');
131
+ const response = yield moost.defineMoostEventHandler({
132
+ loggerTitle: LOGGER_TITLE,
133
+ getIterceptorHandler: () => { var _a; return (_a = this.moost) === null || _a === void 0 ? void 0 : _a.getGlobalInterceptorHandler(); },
134
+ getControllerInstance: () => this.moost,
135
+ callControllerMethod: () => undefined,
136
+ logErrors: (_a = this.opts) === null || _a === void 0 ? void 0 : _a.debug,
137
+ hooks: {
138
+ init: () => setCliHelpForEvent(this.cliHelp),
139
+ },
140
+ })();
141
+ if (typeof response === 'undefined') {
142
+ this.cliApp.onUnknownCommand(pathParams);
143
+ }
144
+ return response;
145
+ });
146
+ }
147
+ onInit(moost) {
148
+ var _a;
149
+ this.moost = moost;
150
+ for (const [alias, entry] of Object.entries(this.cliHelp.getComputedAliases())) {
151
+ if (entry.custom) {
152
+ const vars = Object.keys(entry.args || {}).map(k => ':' + k).join('/');
153
+ const path = '/' + alias.replace(/\s+/g, '/').replace(/:/g, '\\:') + (vars ? '/' + vars : '');
154
+ this.cliApp.cli(path, entry.custom.fn);
155
+ if ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.debug) {
156
+ entry.custom.log(`${''}(CLI-alias*)${''}${path}`);
157
+ }
158
+ }
159
+ }
45
160
  void this.cliApp.run();
46
161
  }
47
162
  bindHandler(opts) {
163
+ var _a, _b, _c, _d, _e, _f;
48
164
  let fn;
49
165
  for (const handler of opts.handlers) {
50
166
  if (handler.type !== 'CLI')
51
167
  continue;
52
- const path = typeof handler.path === 'string' ? handler.path : typeof opts.method === 'string' ? opts.method : '';
53
- const targetPath = `${opts.prefix || ''}/${path}`.replace(/\/\/+/g, '/');
168
+ const path = typeof handler.path === 'string'
169
+ ? handler.path
170
+ : typeof opts.method === 'string'
171
+ ? opts.method
172
+ : '';
173
+ const makePath = (p) => `${opts.prefix.replace(/\s+/g, '/') || ''}/${p}`
174
+ .replace(/\/\/+/g, '/')
175
+ // avoid interpreting "cmd:tail" as "cmd/:tail"
176
+ .replace(/\/\\:/g, '\\:');
177
+ let cliCommand = '';
54
178
  if (!fn) {
55
- fn = () => __awaiter(this, void 0, void 0, function* () {
56
- const { restoreCtx } = eventCli.useCliContext();
57
- const scopeId = eventCore.useEventId().getId();
58
- const unscope = opts.registerEventScope(scopeId);
59
- const instance = yield opts.getInstance();
60
- restoreCtx();
61
- let response;
62
- const interceptorHandler = yield opts.getIterceptorHandler();
63
- restoreCtx();
64
- yield interceptorHandler.init();
65
- // params
66
- let args = [];
67
- try {
68
- restoreCtx();
69
- args = yield opts.resolveArgs();
70
- }
71
- catch (e) {
72
- response = e;
73
- }
74
- if (!response) {
75
- restoreCtx();
76
- // fire before interceptors
77
- response = yield interceptorHandler.fireBefore(response);
78
- // fire request handler
79
- if (!interceptorHandler.responseOverwritten) {
80
- try {
81
- restoreCtx();
82
- response = yield instance[opts.method](...args);
83
- }
84
- catch (e) {
85
- response = e;
86
- }
87
- }
88
- }
89
- restoreCtx();
90
- // fire after interceptors
91
- response = yield interceptorHandler.fireAfter(response);
92
- unscope();
93
- return response;
179
+ fn = moost.defineMoostEventHandler({
180
+ contextType: CONTEXT_TYPE,
181
+ loggerTitle: LOGGER_TITLE,
182
+ getIterceptorHandler: opts.getIterceptorHandler,
183
+ getControllerInstance: opts.getInstance,
184
+ controllerMethod: opts.method,
185
+ resolveArgs: opts.resolveArgs,
186
+ logErrors: (_a = this.opts) === null || _a === void 0 ? void 0 : _a.debug,
187
+ hooks: {
188
+ init: () => setCliHelpForEvent(this.cliHelp),
189
+ },
94
190
  });
95
191
  }
96
- this.cliApp.cli(targetPath, fn);
97
- opts.logHandler(`${''}(CLI)${''}${targetPath}`);
192
+ const targetPath = makePath(path);
193
+ const { getArgs, getStaticPart } = this.cliApp.cli(targetPath, fn);
194
+ const meta = getCliMate().read(opts.fakeInstance, opts.method);
195
+ const classMeta = getCliMate().read(opts.fakeInstance);
196
+ const args = {};
197
+ getArgs().forEach(a => {
198
+ var _a;
199
+ const argParam = (_a = meta === null || meta === void 0 ? void 0 : meta.params) === null || _a === void 0 ? void 0 : _a.find(p => p.label === a && p.description);
200
+ args[a] = (argParam === null || argParam === void 0 ? void 0 : argParam.description) || '';
201
+ });
202
+ cliCommand = getStaticPart().replace(/\//g, ' ').trim();
203
+ const cliOptions = new Map();
204
+ [
205
+ ...(((_c = (_b = this.opts) === null || _b === void 0 ? void 0 : _b.globalCliOptions) === null || _c === void 0 ? void 0 : _c.length) ? this.opts.globalCliOptions : []),
206
+ ...((classMeta === null || classMeta === void 0 ? void 0 : classMeta.cliOptions) || []),
207
+ ...(((_d = meta === null || meta === void 0 ? void 0 : meta.params) === null || _d === void 0 ? void 0 : _d.filter(param => !!param.cliParamKeys && param.cliParamKeys.length > 0).map(param => ({
208
+ keys: param.cliParamKeys,
209
+ value: typeof param.value === 'string' ? param.value : '',
210
+ description: param.description || '',
211
+ }))) || []),
212
+ ].forEach(o => cliOptions.set(o.keys[0], o));
213
+ if ((_e = this.opts) === null || _e === void 0 ? void 0 : _e.debug) {
214
+ opts.logHandler(`${''}(CLI)${''}${targetPath}`);
215
+ }
216
+ const aliases = [];
217
+ if (meta === null || meta === void 0 ? void 0 : meta.cliAliases) {
218
+ for (const alias of meta.cliAliases) {
219
+ const targetPath = makePath(alias);
220
+ const { getStaticPart } = this.cliApp.cli(targetPath, fn);
221
+ aliases.push(getStaticPart().replace(/\//g, ' ').trim());
222
+ if ((_f = this.opts) === null || _f === void 0 ? void 0 : _f.debug) {
223
+ opts.logHandler(`${''}(CLI-alias)${''}${targetPath}`);
224
+ }
225
+ }
226
+ }
227
+ this.cliHelp.addEntry({
228
+ description: (meta === null || meta === void 0 ? void 0 : meta.description) || '',
229
+ command: cliCommand,
230
+ options: Array.from(cliOptions.values()),
231
+ args,
232
+ aliases: aliases,
233
+ custom: { fn, log: opts.logHandler },
234
+ examples: (meta === null || meta === void 0 ? void 0 : meta.cliExamples) || [],
235
+ });
98
236
  }
99
237
  }
100
238
  }
101
239
 
102
- function getCliMate() {
103
- return moost.getMoostMate();
240
+ function formatParams(keys) {
241
+ const names = [keys].flat();
242
+ return names.map((n) => (n.length === 1 ? '-' + n : '--' + n));
104
243
  }
105
244
 
106
245
  /**
107
- * Get Cli Flag
108
- * @decorator
109
- * @param name - flag name
110
- * @paramType string
111
- */
112
- function Flag(name) {
113
- return moost.Resolve(() => eventCli.useFlags()[name], name);
114
- }
115
- /**
116
- * Get Cli Flags
117
- * @decorator
118
- * @paramType object
246
+ * ## Define CLI Option
247
+ * ### @ParameterDecorator
248
+ * Use together with @Description('...') to document cli option
249
+ *
250
+ * ```ts
251
+ * │ @Cli('command')
252
+ * │ command(
253
+ * │ @Description('Test flag...')
254
+ * │ @CliOption('test', 't')
255
+ * │ test: boolean,
256
+ * │ ) {
257
+ * │ return `test=${ test }`
258
+ * │ }
259
+ * ```
260
+ *
261
+ * @param keys list of keys (short and long alternatives)
262
+ * @returns
119
263
  */
120
- function Flags() {
121
- return moost.Resolve(() => eventCli.useFlags(), 'flags');
122
- }
123
- function formatParams(keys) {
124
- const names = [keys].flat();
125
- return names.map(n => n.length === 1 ? '-' + n : '--' + n);
126
- }
127
- function CliParam(keys, descr) {
264
+ function CliOption(...keys) {
128
265
  const mate = getCliMate();
129
- return mate.apply(mate.decorate('cliParams', { keys, descr }, true), moost.Resolve(() => {
266
+ return mate.apply(mate.decorate('cliParamKeys', keys, false), moost.Resolve(() => {
130
267
  const flags = eventCli.useFlags();
131
- const names = [keys].flat();
268
+ const names = keys;
132
269
  const vals = [];
133
270
  for (const name of names) {
134
271
  if (flags[name]) {
@@ -143,14 +280,152 @@ function CliParam(keys, descr) {
143
280
  }
144
281
  return vals[0];
145
282
  }, formatParams(keys).join(', ')));
283
+ }
284
+ /**
285
+ * ## Define Global CLI Option
286
+ * ### @ClassDecorator
287
+ * The option described here will appear in every command instructions
288
+ * @param option keys and description of CLI option
289
+ * @returns
290
+ */
291
+ function CliGlobalOption(option) {
292
+ const mate = getCliMate();
293
+ return mate.decorate('cliOptions', option, true);
146
294
  }
147
295
 
296
+ /**
297
+ * ## Define CLI Command
298
+ * ### @MethodDecorator
299
+ *
300
+ * Command path segments may be separated by / or space.
301
+ *
302
+ * For example the folowing path are interpreted the same:
303
+ * - "command test use:dev :name"
304
+ * - "command/test/use:dev/:name"
305
+ * Where name will become an argument
306
+ *
307
+ * @param path - command path
308
+ * @returns
309
+ */
148
310
  function Cli(path) {
149
- return getCliMate().decorate('handlers', { path, type: 'CLI' }, true);
311
+ return getCliMate().decorate('handlers', { path: path === null || path === void 0 ? void 0 : path.replace(/\s+/g, '/'), type: 'CLI' }, true);
312
+ }
313
+ /**
314
+ * ## Define CLI Command Alias
315
+ * ### @MethodDecorator
316
+ *
317
+ * Use it to define alias for @Cli('...') command
318
+ *
319
+ * @param path - command alias path
320
+ * @returns
321
+ */
322
+ function CliAlias(alias) {
323
+ return getCliMate().decorate('cliAliases', alias, true);
324
+ }
325
+ /**
326
+ * ## Define CLI Example
327
+ * ### @MethodDecorator
328
+ *
329
+ * Use it to define example for Cli Help display
330
+ *
331
+ * @param path - command alias path
332
+ * @returns
333
+ */
334
+ function CliExample(cmd, description) {
335
+ return getCliMate().decorate('cliExamples', { cmd, description }, true);
150
336
  }
151
337
 
338
+ /**
339
+ * ### Interceptor Factory for CliHelpRenderer
340
+ *
341
+ * By default intercepts cli calls with flag --help
342
+ * and prints help.
343
+ *
344
+ * ```js
345
+ * new Moost().applyGlobalInterceptors(cliHelpInterceptor({ colors: true }))
346
+ * ```
347
+ * @param opts {} { helpOptions: ['help', 'h'], colors: true } cli options to invoke help renderer
348
+ * @returns TInterceptorFn
349
+ */
350
+ const cliHelpInterceptor = (opts) => {
351
+ return moost.defineInterceptorFn(() => {
352
+ const helpOptions = (opts === null || opts === void 0 ? void 0 : opts.helpOptions) || ['help'];
353
+ for (const option of helpOptions) {
354
+ if (eventCli.useFlag(option) === true) {
355
+ try {
356
+ useCliHelp().print(opts === null || opts === void 0 ? void 0 : opts.colors);
357
+ return '';
358
+ }
359
+ catch (e) {
360
+ //
361
+ }
362
+ }
363
+ }
364
+ if ((opts === null || opts === void 0 ? void 0 : opts.helpWithArgs) || (opts === null || opts === void 0 ? void 0 : opts.helpWithIncompleteCmd)) {
365
+ const { getMethod } = moost.useControllerContext();
366
+ if (!getMethod()) {
367
+ const parts = eventCli.useCliContext().store('event').get('pathParams');
368
+ const cliHelp = useCliHelp().getCliHelp();
369
+ const cmd = cliHelp.getCliName();
370
+ let data;
371
+ for (let i = 0; i < Math.min(parts.length, 4); i++) {
372
+ const pathParams = parts.slice(0, i ? -i : parts.length).join(' ');
373
+ try {
374
+ data = cliHelp.match(pathParams);
375
+ break;
376
+ }
377
+ catch (e) {
378
+ if (opts === null || opts === void 0 ? void 0 : opts.helpWithIncompleteCmd) {
379
+ const variants = cliHelp.lookup(pathParams);
380
+ if (variants.length) {
381
+ throw new Error(`Wrong command, did you mean:\n${variants.slice(0, 7).map(c => ` $ ${cmd} ${c.main.command}`).join('\n')}`);
382
+ }
383
+ }
384
+ }
385
+ }
386
+ if (data) {
387
+ const { main, children } = data;
388
+ if ((opts === null || opts === void 0 ? void 0 : opts.helpWithArgs) && main.args && Object.keys(main.args).length) {
389
+ throw new Error(`Arguments expected: ${Object.keys(main.args).map(l => `<${l}>`).join(', ')}`);
390
+ }
391
+ else if ((opts === null || opts === void 0 ? void 0 : opts.helpWithIncompleteCmd) && children && children.length) {
392
+ throw new Error(`Wrong command, did you mean:\n${children.slice(0, 7).map(c => ` $ ${cmd} ${c.command}`).join('\n')}`);
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }, moost.TInterceptorPriority.BEFORE_ALL);
398
+ };
399
+ /**
400
+ * ## @Decorator
401
+ * ### Interceptor Factory for CliHelpRenderer
402
+ *
403
+ * By default intercepts cli calls with flag --help
404
+ * and prints help.
405
+ *
406
+ * ```ts
407
+ * // default configuration
408
+ * • @CliHelpInterceptor({ helpOptions: 'help', colors: true })
409
+ *
410
+ * // additional option -h to invoke help renderer
411
+ * • @CliHelpInterceptor({ helpOptions: ['help', 'h'], colors: true })
412
+ *
413
+ * // redefine cli option to invoke help renderer
414
+ * • @CliHelpInterceptor({ helpOptions: ['usage'] })
415
+ * ```
416
+ *
417
+ * @param opts {} { helpOptions: ['help', 'h'], colors: true } cli options to invoke help renderer
418
+ * @returns Decorator
419
+ */
420
+ const CliHelpInterceptor = (...opts) => moost.Intercept(cliHelpInterceptor(...opts));
421
+
152
422
  exports.Cli = Cli;
153
- exports.CliParam = CliParam;
154
- exports.Flag = Flag;
155
- exports.Flags = Flags;
423
+ exports.CliAlias = CliAlias;
424
+ exports.CliExample = CliExample;
425
+ exports.CliGlobalOption = CliGlobalOption;
426
+ exports.CliHelpInterceptor = CliHelpInterceptor;
427
+ exports.CliOption = CliOption;
156
428
  exports.MoostCli = MoostCli;
429
+ exports.cliHelpInterceptor = cliHelpInterceptor;
430
+ exports.setCliHelpForEvent = setCliHelpForEvent;
431
+ exports.useCliHelp = useCliHelp;
package/dist/index.d.ts CHANGED
@@ -1,36 +1,257 @@
1
+ import { CliHelpRenderer } from '@prostojs/cli-help';
2
+ import { Moost } from 'moost';
3
+ import { TCliHelpOptions } from '@prostojs/cli-help';
4
+ import { TInterceptorFn } from 'moost';
1
5
  import { TMoostAdapter } from 'moost';
2
6
  import { TMoostAdapterOptions } from 'moost';
3
7
  import { TWooksCliOptions } from '@wooksjs/event-cli';
8
+ import { TWooksHandler } from 'wooks';
4
9
  import { WooksCli } from '@wooksjs/event-cli';
5
10
 
11
+ /**
12
+ * ## Define CLI Command
13
+ * ### @MethodDecorator
14
+ *
15
+ * Command path segments may be separated by / or space.
16
+ *
17
+ * For example the folowing path are interpreted the same:
18
+ * - "command test use:dev :name"
19
+ * - "command/test/use:dev/:name"
20
+ * Where name will become an argument
21
+ *
22
+ * @param path - command path
23
+ * @returns
24
+ */
6
25
  export declare function Cli(path?: string): MethodDecorator;
7
26
 
8
- export declare function CliParam(keys: string | [string, string], descr?: string): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
27
+ /**
28
+ * ## Define CLI Command Alias
29
+ * ### @MethodDecorator
30
+ *
31
+ * Use it to define alias for @Cli('...') command
32
+ *
33
+ * @param path - command alias path
34
+ * @returns
35
+ */
36
+ export declare function CliAlias(alias: string): MethodDecorator;
37
+
38
+ /**
39
+ * ## Define CLI Example
40
+ * ### @MethodDecorator
41
+ *
42
+ * Use it to define example for Cli Help display
43
+ *
44
+ * @param path - command alias path
45
+ * @returns
46
+ */
47
+ export declare function CliExample(cmd: string, description?: string): MethodDecorator;
48
+
49
+ /**
50
+ * ## Define Global CLI Option
51
+ * ### @ClassDecorator
52
+ * The option described here will appear in every command instructions
53
+ * @param option keys and description of CLI option
54
+ * @returns
55
+ */
56
+ export declare function CliGlobalOption(option: {
57
+ keys: string[];
58
+ description?: string;
59
+ value?: string;
60
+ }): ClassDecorator;
61
+
62
+ /**
63
+ * ## @Decorator
64
+ * ### Interceptor Factory for CliHelpRenderer
65
+ *
66
+ * By default intercepts cli calls with flag --help
67
+ * and prints help.
68
+ *
69
+ * ```ts
70
+ * // default configuration
71
+ * • @CliHelpInterceptor({ helpOptions: 'help', colors: true })
72
+ *
73
+ * // additional option -h to invoke help renderer
74
+ * • @CliHelpInterceptor({ helpOptions: ['help', 'h'], colors: true })
75
+ *
76
+ * // redefine cli option to invoke help renderer
77
+ * • @CliHelpInterceptor({ helpOptions: ['usage'] })
78
+ * ```
79
+ *
80
+ * @param opts {} { helpOptions: ['help', 'h'], colors: true } cli options to invoke help renderer
81
+ * @returns Decorator
82
+ */
83
+ export declare const CliHelpInterceptor: (opts?: {
84
+ /**
85
+ * CLI Options that invoke help
86
+ * ```js
87
+ * helpOptions: ['help', 'h']
88
+ * ```
89
+ */
90
+ helpOptions?: string[] | undefined;
91
+ /**
92
+ * Enable colored help
93
+ */
94
+ colors?: boolean | undefined;
95
+ /**
96
+ * Enable help message when arguments are missing
97
+ */
98
+ helpWithArgs?: boolean | undefined;
99
+ /**
100
+ * Enable help message when command is incomplete
101
+ * and it is possible to suggest related commands
102
+ */
103
+ helpWithIncompleteCmd?: boolean | undefined;
104
+ } | undefined) => ClassDecorator & MethodDecorator;
9
105
 
10
106
  /**
11
- * Get Cli Flag
12
- * @decorator
13
- * @param name - flag name
14
- * @paramType string
107
+ * ### Interceptor Factory for CliHelpRenderer
108
+ *
109
+ * By default intercepts cli calls with flag --help
110
+ * and prints help.
111
+ *
112
+ * ```js
113
+ * new Moost().applyGlobalInterceptors(cliHelpInterceptor({ colors: true }))
114
+ * ```
115
+ * @param opts {} { helpOptions: ['help', 'h'], colors: true } cli options to invoke help renderer
116
+ * @returns TInterceptorFn
15
117
  */
16
- export declare function Flag(name: string): ParameterDecorator & PropertyDecorator;
118
+ export declare const cliHelpInterceptor: (opts?: {
119
+ /**
120
+ * CLI Options that invoke help
121
+ * ```js
122
+ * helpOptions: ['help', 'h']
123
+ * ```
124
+ */
125
+ helpOptions?: string[];
126
+ /**
127
+ * Enable colored help
128
+ */
129
+ colors?: boolean;
130
+ /**
131
+ * Enable help message when arguments are missing
132
+ */
133
+ helpWithArgs?: boolean;
134
+ /**
135
+ * Enable help message when command is incomplete
136
+ * and it is possible to suggest related commands
137
+ */
138
+ helpWithIncompleteCmd?: boolean;
139
+ }) => TInterceptorFn;
140
+
141
+ declare type CliHelpRendererWithFn = CliHelpRenderer<{
142
+ fn: TWooksHandler;
143
+ log: ((eventName: string) => void);
144
+ }>;
17
145
 
18
146
  /**
19
- * Get Cli Flags
20
- * @decorator
21
- * @paramType object
147
+ * ## Define CLI Option
148
+ * ### @ParameterDecorator
149
+ * Use together with @Description('...') to document cli option
150
+ *
151
+ * ```ts
152
+ * │ @Cli('command')
153
+ * │ command(
154
+ * │ @Description('Test flag...')
155
+ * │ @CliOption('test', 't')
156
+ * │ test: boolean,
157
+ * │ ) {
158
+ * │ return `test=${ test }`
159
+ * │ }
160
+ * ```
161
+ *
162
+ * @param keys list of keys (short and long alternatives)
163
+ * @returns
22
164
  */
23
- export declare function Flags(): ParameterDecorator & PropertyDecorator;
165
+ export declare function CliOption(...keys: string[]): ParameterDecorator;
24
166
 
167
+ /**
168
+ * ## Moost Cli Adapter
169
+ *
170
+ * Moost Adapter for CLI events
171
+ *
172
+ * ```ts
173
+ * │ // Quick example
174
+ * │ import { MoostCli, Cli, CliOption, cliHelpInterceptor } from '@moostjs/event-cli'
175
+ * │ import { Moost, Param } from 'moost'
176
+ * │
177
+ * │ class MyApp extends Moost {
178
+ * │ @Cli('command/:arg')
179
+ * │ command(
180
+ * │ @Param('arg')
181
+ * │ arg: string,
182
+ * │ @CliOption('test', 't')
183
+ * │ test: boolean,
184
+ * │ ) {
185
+ * │ return `command run with flag arg=${ arg }, test=${ test }`
186
+ * │ }
187
+ * │ }
188
+ * │
189
+ * │ const app = new MyApp()
190
+ * │ app.applyGlobalInterceptors(cliHelpInterceptor())
191
+ * │
192
+ * │ const cli = new MoostCli()
193
+ * │ app.adapter(cli)
194
+ * │ app.init()
195
+ * ```
196
+ */
25
197
  export declare class MoostCli implements TMoostAdapter<TCliHandlerMeta> {
198
+ protected opts?: TMoostCliOpts | undefined;
26
199
  protected cliApp: WooksCli;
27
- constructor(cliApp?: WooksCli | TWooksCliOptions);
28
- onInit(): void;
200
+ protected cliHelp: CliHelpRendererWithFn;
201
+ constructor(opts?: TMoostCliOpts | undefined);
202
+ onNotFound(): Promise<unknown>;
203
+ protected moost?: Moost;
204
+ onInit(moost: Moost): void;
29
205
  bindHandler<T extends object = object>(opts: TMoostAdapterOptions<TCliHandlerMeta, T>): void | Promise<void>;
30
206
  }
31
207
 
208
+ /**
209
+ * ### setCliHelpForEvent
210
+ * Used internally to set CliHelpRenderer instance for an event state
211
+ * @param cliHelp CliHelpRenderer
212
+ */
213
+ export declare function setCliHelpForEvent(cliHelp: CliHelpRendererWithFn): void;
214
+
32
215
  export declare interface TCliHandlerMeta {
33
216
  path: string;
34
217
  }
35
218
 
219
+ export declare interface TMoostCliOpts {
220
+ /**
221
+ * WooksCli options or instance
222
+ */
223
+ wooksCli?: WooksCli | TWooksCliOptions;
224
+ /**
225
+ * CliHelpRenderer options or instance
226
+ */
227
+ cliHelp?: CliHelpRendererWithFn | TCliHelpOptions;
228
+ /**
229
+ * more internal logs are printed when true
230
+ */
231
+ debug?: boolean;
232
+ /**
233
+ * Array of cli options applicable to every cli command
234
+ */
235
+ globalCliOptions?: {
236
+ keys: string[];
237
+ description?: string;
238
+ }[];
239
+ }
240
+
241
+ /**
242
+ * ## useCliHelp
243
+ * ### Composable
244
+ * ```js
245
+ * // example of printing cli instructions
246
+ * const { print } = useCliHelp()
247
+ * print(true)
248
+ * ```
249
+ * @returns
250
+ */
251
+ export declare function useCliHelp(): {
252
+ getCliHelp: () => CliHelpRendererWithFn;
253
+ render: (width?: number, withColors?: boolean) => string[];
254
+ print: (withColors?: boolean) => void;
255
+ };
256
+
36
257
  export { }
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { WooksCli, createCliApp, useCliContext, useFlags } from '@wooksjs/event-cli';
2
- import { useEventId } from '@wooksjs/event-core';
3
- import { getMoostMate, Resolve } from 'moost';
1
+ import { getMoostMate, getMoostInfact, defineMoostEventHandler, Resolve, defineInterceptorFn, useControllerContext, TInterceptorPriority, Intercept } from 'moost';
2
+ import { useCliContext, WooksCli, createCliApp, useFlags, useFlag } from '@wooksjs/event-cli';
3
+ import { CliHelpRenderer } from '@prostojs/cli-help';
4
4
 
5
5
  /******************************************************************************
6
6
  Copyright (c) Microsoft Corporation.
@@ -16,6 +16,8 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
16
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
17
  PERFORMANCE OF THIS SOFTWARE.
18
18
  ***************************************************************************** */
19
+ /* global Reflect, Promise */
20
+
19
21
 
20
22
  function __awaiter(thisArg, _arguments, P, generator) {
21
23
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -27,106 +29,241 @@ function __awaiter(thisArg, _arguments, P, generator) {
27
29
  });
28
30
  }
29
31
 
32
+ function getCliMate() {
33
+ return getMoostMate();
34
+ }
35
+
36
+ /**
37
+ * ### setCliHelpForEvent
38
+ * Used internally to set CliHelpRenderer instance for an event state
39
+ * @param cliHelp CliHelpRenderer
40
+ */
41
+ function setCliHelpForEvent(cliHelp) {
42
+ useCliContext().store('event').set('cliHelp', cliHelp);
43
+ }
44
+ /**
45
+ * ## useCliHelp
46
+ * ### Composable
47
+ * ```js
48
+ * // example of printing cli instructions
49
+ * const { print } = useCliHelp()
50
+ * print(true)
51
+ * ```
52
+ * @returns
53
+ */
54
+ function useCliHelp() {
55
+ const event = useCliContext().store('event');
56
+ const getCliHelp = () => event.get('cliHelp');
57
+ return {
58
+ getCliHelp,
59
+ render: (width, withColors) => getCliHelp().render(event.get('pathParams').join(' '), width, withColors),
60
+ print: (withColors) => getCliHelp().print(event.get('pathParams').join(' '), withColors),
61
+ };
62
+ }
63
+
64
+ const LOGGER_TITLE = 'moost-cli';
65
+ const CONTEXT_TYPE = 'CLI';
66
+ /**
67
+ * ## Moost Cli Adapter
68
+ *
69
+ * Moost Adapter for CLI events
70
+ *
71
+ * ```ts
72
+ * │ // Quick example
73
+ * │ import { MoostCli, Cli, CliOption, cliHelpInterceptor } from '@moostjs/event-cli'
74
+ * │ import { Moost, Param } from 'moost'
75
+ * │
76
+ * │ class MyApp extends Moost {
77
+ * │ @Cli('command/:arg')
78
+ * │ command(
79
+ * │ @Param('arg')
80
+ * │ arg: string,
81
+ * │ @CliOption('test', 't')
82
+ * │ test: boolean,
83
+ * │ ) {
84
+ * │ return `command run with flag arg=${ arg }, test=${ test }`
85
+ * │ }
86
+ * │ }
87
+ * │
88
+ * │ const app = new MyApp()
89
+ * │ app.applyGlobalInterceptors(cliHelpInterceptor())
90
+ * │
91
+ * │ const cli = new MoostCli()
92
+ * │ app.adapter(cli)
93
+ * │ app.init()
94
+ * ```
95
+ */
30
96
  class MoostCli {
31
- constructor(cliApp) {
32
- if (cliApp && cliApp instanceof WooksCli) {
33
- this.cliApp = cliApp;
97
+ constructor(opts) {
98
+ this.opts = opts;
99
+ const cliAppOpts = opts === null || opts === void 0 ? void 0 : opts.wooksCli;
100
+ if (cliAppOpts && cliAppOpts instanceof WooksCli) {
101
+ this.cliApp = cliAppOpts;
34
102
  }
35
- else if (cliApp) {
36
- this.cliApp = createCliApp(cliApp);
103
+ else if (cliAppOpts) {
104
+ this.cliApp = createCliApp(Object.assign(Object.assign({}, cliAppOpts), { onNotFound: this.onNotFound.bind(this) }));
37
105
  }
38
106
  else {
39
- this.cliApp = createCliApp();
107
+ this.cliApp = createCliApp({
108
+ onNotFound: this.onNotFound.bind(this),
109
+ });
110
+ }
111
+ const cliHelpOpts = opts === null || opts === void 0 ? void 0 : opts.cliHelp;
112
+ if (cliHelpOpts && cliHelpOpts instanceof CliHelpRenderer) {
113
+ this.cliHelp = cliHelpOpts;
114
+ }
115
+ else if (cliHelpOpts) {
116
+ this.cliHelp = new CliHelpRenderer(cliHelpOpts);
117
+ }
118
+ else {
119
+ this.cliHelp = new CliHelpRenderer();
120
+ }
121
+ if (!(opts === null || opts === void 0 ? void 0 : opts.debug)) {
122
+ getMoostInfact().silent(true);
40
123
  }
41
124
  }
42
- onInit() {
125
+ onNotFound() {
126
+ var _a;
127
+ return __awaiter(this, void 0, void 0, function* () {
128
+ const pathParams = useCliContext().store('event').get('pathParams');
129
+ const response = yield defineMoostEventHandler({
130
+ loggerTitle: LOGGER_TITLE,
131
+ getIterceptorHandler: () => { var _a; return (_a = this.moost) === null || _a === void 0 ? void 0 : _a.getGlobalInterceptorHandler(); },
132
+ getControllerInstance: () => this.moost,
133
+ callControllerMethod: () => undefined,
134
+ logErrors: (_a = this.opts) === null || _a === void 0 ? void 0 : _a.debug,
135
+ hooks: {
136
+ init: () => setCliHelpForEvent(this.cliHelp),
137
+ },
138
+ })();
139
+ if (typeof response === 'undefined') {
140
+ this.cliApp.onUnknownCommand(pathParams);
141
+ }
142
+ return response;
143
+ });
144
+ }
145
+ onInit(moost) {
146
+ var _a;
147
+ this.moost = moost;
148
+ for (const [alias, entry] of Object.entries(this.cliHelp.getComputedAliases())) {
149
+ if (entry.custom) {
150
+ const vars = Object.keys(entry.args || {}).map(k => ':' + k).join('/');
151
+ const path = '/' + alias.replace(/\s+/g, '/').replace(/:/g, '\\:') + (vars ? '/' + vars : '');
152
+ this.cliApp.cli(path, entry.custom.fn);
153
+ if ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.debug) {
154
+ entry.custom.log(`${''}(CLI-alias*)${''}${path}`);
155
+ }
156
+ }
157
+ }
43
158
  void this.cliApp.run();
44
159
  }
45
160
  bindHandler(opts) {
161
+ var _a, _b, _c, _d, _e, _f;
46
162
  let fn;
47
163
  for (const handler of opts.handlers) {
48
164
  if (handler.type !== 'CLI')
49
165
  continue;
50
- const path = typeof handler.path === 'string' ? handler.path : typeof opts.method === 'string' ? opts.method : '';
51
- const targetPath = `${opts.prefix || ''}/${path}`.replace(/\/\/+/g, '/');
166
+ const path = typeof handler.path === 'string'
167
+ ? handler.path
168
+ : typeof opts.method === 'string'
169
+ ? opts.method
170
+ : '';
171
+ const makePath = (p) => `${opts.prefix.replace(/\s+/g, '/') || ''}/${p}`
172
+ .replace(/\/\/+/g, '/')
173
+ // avoid interpreting "cmd:tail" as "cmd/:tail"
174
+ .replace(/\/\\:/g, '\\:');
175
+ let cliCommand = '';
52
176
  if (!fn) {
53
- fn = () => __awaiter(this, void 0, void 0, function* () {
54
- const { restoreCtx } = useCliContext();
55
- const scopeId = useEventId().getId();
56
- const unscope = opts.registerEventScope(scopeId);
57
- const instance = yield opts.getInstance();
58
- restoreCtx();
59
- let response;
60
- const interceptorHandler = yield opts.getIterceptorHandler();
61
- restoreCtx();
62
- yield interceptorHandler.init();
63
- // params
64
- let args = [];
65
- try {
66
- restoreCtx();
67
- args = yield opts.resolveArgs();
68
- }
69
- catch (e) {
70
- response = e;
71
- }
72
- if (!response) {
73
- restoreCtx();
74
- // fire before interceptors
75
- response = yield interceptorHandler.fireBefore(response);
76
- // fire request handler
77
- if (!interceptorHandler.responseOverwritten) {
78
- try {
79
- restoreCtx();
80
- response = yield instance[opts.method](...args);
81
- }
82
- catch (e) {
83
- response = e;
84
- }
85
- }
86
- }
87
- restoreCtx();
88
- // fire after interceptors
89
- response = yield interceptorHandler.fireAfter(response);
90
- unscope();
91
- return response;
177
+ fn = defineMoostEventHandler({
178
+ contextType: CONTEXT_TYPE,
179
+ loggerTitle: LOGGER_TITLE,
180
+ getIterceptorHandler: opts.getIterceptorHandler,
181
+ getControllerInstance: opts.getInstance,
182
+ controllerMethod: opts.method,
183
+ resolveArgs: opts.resolveArgs,
184
+ logErrors: (_a = this.opts) === null || _a === void 0 ? void 0 : _a.debug,
185
+ hooks: {
186
+ init: () => setCliHelpForEvent(this.cliHelp),
187
+ },
92
188
  });
93
189
  }
94
- this.cliApp.cli(targetPath, fn);
95
- opts.logHandler(`${''}(CLI)${''}${targetPath}`);
190
+ const targetPath = makePath(path);
191
+ const { getArgs, getStaticPart } = this.cliApp.cli(targetPath, fn);
192
+ const meta = getCliMate().read(opts.fakeInstance, opts.method);
193
+ const classMeta = getCliMate().read(opts.fakeInstance);
194
+ const args = {};
195
+ getArgs().forEach(a => {
196
+ var _a;
197
+ const argParam = (_a = meta === null || meta === void 0 ? void 0 : meta.params) === null || _a === void 0 ? void 0 : _a.find(p => p.label === a && p.description);
198
+ args[a] = (argParam === null || argParam === void 0 ? void 0 : argParam.description) || '';
199
+ });
200
+ cliCommand = getStaticPart().replace(/\//g, ' ').trim();
201
+ const cliOptions = new Map();
202
+ [
203
+ ...(((_c = (_b = this.opts) === null || _b === void 0 ? void 0 : _b.globalCliOptions) === null || _c === void 0 ? void 0 : _c.length) ? this.opts.globalCliOptions : []),
204
+ ...((classMeta === null || classMeta === void 0 ? void 0 : classMeta.cliOptions) || []),
205
+ ...(((_d = meta === null || meta === void 0 ? void 0 : meta.params) === null || _d === void 0 ? void 0 : _d.filter(param => !!param.cliParamKeys && param.cliParamKeys.length > 0).map(param => ({
206
+ keys: param.cliParamKeys,
207
+ value: typeof param.value === 'string' ? param.value : '',
208
+ description: param.description || '',
209
+ }))) || []),
210
+ ].forEach(o => cliOptions.set(o.keys[0], o));
211
+ if ((_e = this.opts) === null || _e === void 0 ? void 0 : _e.debug) {
212
+ opts.logHandler(`${''}(CLI)${''}${targetPath}`);
213
+ }
214
+ const aliases = [];
215
+ if (meta === null || meta === void 0 ? void 0 : meta.cliAliases) {
216
+ for (const alias of meta.cliAliases) {
217
+ const targetPath = makePath(alias);
218
+ const { getStaticPart } = this.cliApp.cli(targetPath, fn);
219
+ aliases.push(getStaticPart().replace(/\//g, ' ').trim());
220
+ if ((_f = this.opts) === null || _f === void 0 ? void 0 : _f.debug) {
221
+ opts.logHandler(`${''}(CLI-alias)${''}${targetPath}`);
222
+ }
223
+ }
224
+ }
225
+ this.cliHelp.addEntry({
226
+ description: (meta === null || meta === void 0 ? void 0 : meta.description) || '',
227
+ command: cliCommand,
228
+ options: Array.from(cliOptions.values()),
229
+ args,
230
+ aliases: aliases,
231
+ custom: { fn, log: opts.logHandler },
232
+ examples: (meta === null || meta === void 0 ? void 0 : meta.cliExamples) || [],
233
+ });
96
234
  }
97
235
  }
98
236
  }
99
237
 
100
- function getCliMate() {
101
- return getMoostMate();
238
+ function formatParams(keys) {
239
+ const names = [keys].flat();
240
+ return names.map((n) => (n.length === 1 ? '-' + n : '--' + n));
102
241
  }
103
242
 
104
243
  /**
105
- * Get Cli Flag
106
- * @decorator
107
- * @param name - flag name
108
- * @paramType string
244
+ * ## Define CLI Option
245
+ * ### @ParameterDecorator
246
+ * Use together with @Description('...') to document cli option
247
+ *
248
+ * ```ts
249
+ * │ @Cli('command')
250
+ * │ command(
251
+ * │ @Description('Test flag...')
252
+ * │ @CliOption('test', 't')
253
+ * │ test: boolean,
254
+ * │ ) {
255
+ * │ return `test=${ test }`
256
+ * │ }
257
+ * ```
258
+ *
259
+ * @param keys list of keys (short and long alternatives)
260
+ * @returns
109
261
  */
110
- function Flag(name) {
111
- return Resolve(() => useFlags()[name], name);
112
- }
113
- /**
114
- * Get Cli Flags
115
- * @decorator
116
- * @paramType object
117
- */
118
- function Flags() {
119
- return Resolve(() => useFlags(), 'flags');
120
- }
121
- function formatParams(keys) {
122
- const names = [keys].flat();
123
- return names.map(n => n.length === 1 ? '-' + n : '--' + n);
124
- }
125
- function CliParam(keys, descr) {
262
+ function CliOption(...keys) {
126
263
  const mate = getCliMate();
127
- return mate.apply(mate.decorate('cliParams', { keys, descr }, true), Resolve(() => {
264
+ return mate.apply(mate.decorate('cliParamKeys', keys, false), Resolve(() => {
128
265
  const flags = useFlags();
129
- const names = [keys].flat();
266
+ const names = keys;
130
267
  const vals = [];
131
268
  for (const name of names) {
132
269
  if (flags[name]) {
@@ -141,10 +278,143 @@ function CliParam(keys, descr) {
141
278
  }
142
279
  return vals[0];
143
280
  }, formatParams(keys).join(', ')));
281
+ }
282
+ /**
283
+ * ## Define Global CLI Option
284
+ * ### @ClassDecorator
285
+ * The option described here will appear in every command instructions
286
+ * @param option keys and description of CLI option
287
+ * @returns
288
+ */
289
+ function CliGlobalOption(option) {
290
+ const mate = getCliMate();
291
+ return mate.decorate('cliOptions', option, true);
144
292
  }
145
293
 
294
+ /**
295
+ * ## Define CLI Command
296
+ * ### @MethodDecorator
297
+ *
298
+ * Command path segments may be separated by / or space.
299
+ *
300
+ * For example the folowing path are interpreted the same:
301
+ * - "command test use:dev :name"
302
+ * - "command/test/use:dev/:name"
303
+ * Where name will become an argument
304
+ *
305
+ * @param path - command path
306
+ * @returns
307
+ */
146
308
  function Cli(path) {
147
- return getCliMate().decorate('handlers', { path, type: 'CLI' }, true);
309
+ return getCliMate().decorate('handlers', { path: path === null || path === void 0 ? void 0 : path.replace(/\s+/g, '/'), type: 'CLI' }, true);
310
+ }
311
+ /**
312
+ * ## Define CLI Command Alias
313
+ * ### @MethodDecorator
314
+ *
315
+ * Use it to define alias for @Cli('...') command
316
+ *
317
+ * @param path - command alias path
318
+ * @returns
319
+ */
320
+ function CliAlias(alias) {
321
+ return getCliMate().decorate('cliAliases', alias, true);
322
+ }
323
+ /**
324
+ * ## Define CLI Example
325
+ * ### @MethodDecorator
326
+ *
327
+ * Use it to define example for Cli Help display
328
+ *
329
+ * @param path - command alias path
330
+ * @returns
331
+ */
332
+ function CliExample(cmd, description) {
333
+ return getCliMate().decorate('cliExamples', { cmd, description }, true);
148
334
  }
149
335
 
150
- export { Cli, CliParam, Flag, Flags, MoostCli };
336
+ /**
337
+ * ### Interceptor Factory for CliHelpRenderer
338
+ *
339
+ * By default intercepts cli calls with flag --help
340
+ * and prints help.
341
+ *
342
+ * ```js
343
+ * new Moost().applyGlobalInterceptors(cliHelpInterceptor({ colors: true }))
344
+ * ```
345
+ * @param opts {} { helpOptions: ['help', 'h'], colors: true } cli options to invoke help renderer
346
+ * @returns TInterceptorFn
347
+ */
348
+ const cliHelpInterceptor = (opts) => {
349
+ return defineInterceptorFn(() => {
350
+ const helpOptions = (opts === null || opts === void 0 ? void 0 : opts.helpOptions) || ['help'];
351
+ for (const option of helpOptions) {
352
+ if (useFlag(option) === true) {
353
+ try {
354
+ useCliHelp().print(opts === null || opts === void 0 ? void 0 : opts.colors);
355
+ return '';
356
+ }
357
+ catch (e) {
358
+ //
359
+ }
360
+ }
361
+ }
362
+ if ((opts === null || opts === void 0 ? void 0 : opts.helpWithArgs) || (opts === null || opts === void 0 ? void 0 : opts.helpWithIncompleteCmd)) {
363
+ const { getMethod } = useControllerContext();
364
+ if (!getMethod()) {
365
+ const parts = useCliContext().store('event').get('pathParams');
366
+ const cliHelp = useCliHelp().getCliHelp();
367
+ const cmd = cliHelp.getCliName();
368
+ let data;
369
+ for (let i = 0; i < Math.min(parts.length, 4); i++) {
370
+ const pathParams = parts.slice(0, i ? -i : parts.length).join(' ');
371
+ try {
372
+ data = cliHelp.match(pathParams);
373
+ break;
374
+ }
375
+ catch (e) {
376
+ if (opts === null || opts === void 0 ? void 0 : opts.helpWithIncompleteCmd) {
377
+ const variants = cliHelp.lookup(pathParams);
378
+ if (variants.length) {
379
+ throw new Error(`Wrong command, did you mean:\n${variants.slice(0, 7).map(c => ` $ ${cmd} ${c.main.command}`).join('\n')}`);
380
+ }
381
+ }
382
+ }
383
+ }
384
+ if (data) {
385
+ const { main, children } = data;
386
+ if ((opts === null || opts === void 0 ? void 0 : opts.helpWithArgs) && main.args && Object.keys(main.args).length) {
387
+ throw new Error(`Arguments expected: ${Object.keys(main.args).map(l => `<${l}>`).join(', ')}`);
388
+ }
389
+ else if ((opts === null || opts === void 0 ? void 0 : opts.helpWithIncompleteCmd) && children && children.length) {
390
+ throw new Error(`Wrong command, did you mean:\n${children.slice(0, 7).map(c => ` $ ${cmd} ${c.command}`).join('\n')}`);
391
+ }
392
+ }
393
+ }
394
+ }
395
+ }, TInterceptorPriority.BEFORE_ALL);
396
+ };
397
+ /**
398
+ * ## @Decorator
399
+ * ### Interceptor Factory for CliHelpRenderer
400
+ *
401
+ * By default intercepts cli calls with flag --help
402
+ * and prints help.
403
+ *
404
+ * ```ts
405
+ * // default configuration
406
+ * • @CliHelpInterceptor({ helpOptions: 'help', colors: true })
407
+ *
408
+ * // additional option -h to invoke help renderer
409
+ * • @CliHelpInterceptor({ helpOptions: ['help', 'h'], colors: true })
410
+ *
411
+ * // redefine cli option to invoke help renderer
412
+ * • @CliHelpInterceptor({ helpOptions: ['usage'] })
413
+ * ```
414
+ *
415
+ * @param opts {} { helpOptions: ['help', 'h'], colors: true } cli options to invoke help renderer
416
+ * @returns Decorator
417
+ */
418
+ const CliHelpInterceptor = (...opts) => Intercept(cliHelpInterceptor(...opts));
419
+
420
+ export { Cli, CliAlias, CliExample, CliGlobalOption, CliHelpInterceptor, CliOption, MoostCli, cliHelpInterceptor, setCliHelpForEvent, useCliHelp };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moostjs/event-cli",
3
- "version": "0.2.27",
3
+ "version": "0.2.29",
4
4
  "description": "@moostjs/event-cli",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -28,11 +28,12 @@
28
28
  },
29
29
  "homepage": "https://github.com/moostjs/moostjs/tree/main/packages/event-cli#readme",
30
30
  "peerDependencies": {
31
- "moost": "0.2.27",
32
- "wooks": "^0.2.18",
33
- "@wooksjs/event-core": "^0.2.18"
31
+ "moost": "0.2.29",
32
+ "wooks": "^0.2.23",
33
+ "@wooksjs/event-core": "^0.2.23"
34
34
  },
35
35
  "dependencies": {
36
- "@wooksjs/event-cli": "^0.2.18"
36
+ "@wooksjs/event-cli": "^0.2.23",
37
+ "@prostojs/cli-help": "^0.0.9"
37
38
  }
38
39
  }