@wooksjs/event-cli 0.4.9 → 0.4.11

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.
Files changed (3) hide show
  1. package/dist/index.cjs +398 -425
  2. package/dist/index.mjs +398 -425
  3. package/package.json +6 -3
package/dist/index.cjs CHANGED
@@ -5,438 +5,411 @@ var wooks = require('wooks');
5
5
  var cliHelp = require('@prostojs/cli-help');
6
6
  var minimist = require('minimist');
7
7
 
8
- function createCliContext(data, options) {
9
- return eventCore.createEventContext({
10
- event: Object.assign(Object.assign({}, data), { type: 'CLI' }),
11
- options,
12
- });
13
- }
14
- /**
15
- * Wrapper on top of useEventContext that provides
16
- * proper context types for CLI event
17
- * @returns set of hooks { getCtx, restoreCtx, clearCtx, hookStore, getStore, setStore }
18
- */
19
- function useCliContext() {
20
- return eventCore.useEventContext('CLI');
8
+ function createCliContext(data, options) {
9
+ return eventCore.createEventContext({
10
+ event: {
11
+ ...data,
12
+ type: 'CLI',
13
+ },
14
+ options,
15
+ });
21
16
  }
22
-
23
- /******************************************************************************
24
- Copyright (c) Microsoft Corporation.
25
-
26
- Permission to use, copy, modify, and/or distribute this software for any
27
- purpose with or without fee is hereby granted.
28
-
29
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
30
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
31
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
32
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
33
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
34
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
35
- PERFORMANCE OF THIS SOFTWARE.
36
- ***************************************************************************** */
37
-
38
- function __awaiter(thisArg, _arguments, P, generator) {
39
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
40
- return new (P || (P = Promise))(function (resolve, reject) {
41
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
42
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
43
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
44
- step((generator = generator.apply(thisArg, _arguments || [])).next());
45
- });
17
+ /**
18
+ * Wrapper on top of useEventContext that provides
19
+ * proper context types for CLI event
20
+ * @returns set of hooks { getCtx, restoreCtx, clearCtx, hookStore, getStore, setStore }
21
+ */
22
+ function useCliContext() {
23
+ return eventCore.useEventContext('CLI');
46
24
  }
47
25
 
48
- const cliShortcuts = {
49
- cli: 'CLI',
50
- };
51
- class WooksCli extends wooks.WooksAdapterBase {
52
- constructor(opts, wooks) {
53
- super(wooks, opts === null || opts === void 0 ? void 0 : opts.logger, opts === null || opts === void 0 ? void 0 : opts.router);
54
- this.opts = opts;
55
- this.alreadyComputedAliases = false;
56
- this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || this.getLogger('wooks-cli');
57
- this.cliHelp =
58
- (opts === null || opts === void 0 ? void 0 : opts.cliHelp) instanceof cliHelp.CliHelpRenderer
59
- ? opts.cliHelp
60
- : new cliHelp.CliHelpRenderer(opts === null || opts === void 0 ? void 0 : opts.cliHelp);
61
- }
62
- /**
63
- * ### Register CLI Command
64
- * Command path segments may be separated by / or space.
65
- *
66
- * For example the folowing path are interpreted the same:
67
- * - "command test use:dev :name"
68
- * - "command/test/use:dev/:name"
69
- *
70
- * Where name will become an argument
71
- *
72
- * ```js
73
- * // example without options
74
- * app.cli('command/:arg', () => 'arg = ' + useRouteParams().params.arg )
75
- *
76
- * // example with options
77
- * app.cli('command/:arg', {
78
- * description: 'Description of the command',
79
- * options: [{ keys: ['project', 'p'], description: 'Description of the option', value: 'myProject' }],
80
- * args: { arg: 'Description of the arg' },
81
- * aliases: ['cmd'], // alias "cmd/:arg" will be registered
82
- * examples: [{
83
- * description: 'Example of usage with someProject',
84
- * cmd: 'argValue -p=someProject',
85
- * // will result in help display:
86
- * // "# Example of usage with someProject\n" +
87
- * // "$ myCli command argValue -p=someProject\n"
88
- * }],
89
- * handler: () => 'arg = ' + useRouteParams().params.arg
90
- * })
91
- * ```
92
- *
93
- * @param path command path
94
- * @param _options handler or options
95
- *
96
- * @returns
97
- */
98
- cli(path, _options) {
99
- var _a;
100
- const options = typeof _options === 'function' ? { handler: _options } : _options;
101
- const handler = typeof _options === 'function' ? _options : _options.handler;
102
- const makePath = (s) => '/' + s.replace(/\s+/g, '/');
103
- // register handler
104
- const targetPath = makePath(path);
105
- const routed = this.on('CLI', targetPath, handler);
106
- if (options.onRegister) {
107
- options.onRegister(targetPath, 0, routed);
108
- }
109
- // register direct aliases
110
- for (const alias of options.aliases || []) {
111
- const vars = routed.getArgs().map((k) => ':' + k).join('/');
112
- const targetPath = makePath(alias) + (vars ? '/' + vars : '');
113
- this.on('CLI', targetPath, handler);
114
- if (options.onRegister) {
115
- options.onRegister(targetPath, 1, routed);
116
- }
117
- }
118
- // register helpCli entry
119
- const command = routed.getStaticPart().replace(/\//g, ' ').trim();
120
- const args = Object.assign({}, (options.args || {}));
121
- for (const arg of routed.getArgs()) {
122
- if (!args[arg]) {
123
- args[arg] = '';
124
- }
125
- }
126
- this.cliHelp.addEntry({
127
- command,
128
- aliases: (_a = options.aliases) === null || _a === void 0 ? void 0 : _a.map(alias => alias.replace(/\\:/g, ':')),
129
- args,
130
- description: options.description,
131
- examples: options.examples,
132
- options: options.options,
133
- custom: { handler: options.handler, cb: options.onRegister },
134
- });
135
- return routed;
136
- }
137
- computeAliases() {
138
- if (!this.alreadyComputedAliases) {
139
- this.alreadyComputedAliases = true;
140
- const aliases = this.cliHelp.getComputedAliases();
141
- for (const [alias, entry] of Object.entries(aliases)) {
142
- if (entry.custom) {
143
- const vars = Object.keys(entry.args || {})
144
- .map((k) => ':' + k)
145
- .join('/');
146
- const path = '/' +
147
- alias.replace(/\s+/g, '/').replace(/:/g, '\\:') +
148
- (vars ? '/' + vars : '');
149
- this.on('CLI', path, entry.custom.handler);
150
- if (entry.custom.cb) {
151
- entry.custom.cb(path, 3);
152
- }
153
- }
154
- }
155
- }
156
- }
157
- /**
158
- * ## run
159
- * ### Start command processing
160
- * Triggers command processing
161
- *
162
- * By default takes `process.argv.slice(2)` as a command
163
- *
164
- * It's possible to replace the command by passing an argument
165
- *
166
- * @param _argv optionally overwrite `process.argv.slice(2)` with your `argv` array
167
- */
168
- run(_argv, _opts) {
169
- var _a, _b;
170
- return __awaiter(this, void 0, void 0, function* () {
171
- const argv = _argv || process.argv.slice(2);
172
- const parsedFlags = minimist(argv, _opts);
173
- const pathParams = parsedFlags._;
174
- const path = '/' +
175
- pathParams.map((v) => encodeURI(v).replace(/\//g, '%2F')).join('/');
176
- const { restoreCtx, clearCtx, store } = createCliContext({ opts: _opts, argv, pathParams, cliHelp: this.cliHelp, command: path.replace(/\//g, ' ').trim() }, this.mergeEventOptions((_a = this.opts) === null || _a === void 0 ? void 0 : _a.eventOptions));
177
- store('flags').value = parsedFlags;
178
- this.computeAliases();
179
- const { handlers: foundHandlers, firstStatic } = this.wooks.lookup('CLI', path);
180
- if (typeof firstStatic === 'string') {
181
- // overwriting command with firstStatic to properly search for help
182
- store('event').set('command', firstStatic.replace(/\//g, ' ').trim());
183
- }
184
- const handlers = foundHandlers ||
185
- (((_b = this.opts) === null || _b === void 0 ? void 0 : _b.onNotFound) && [this.opts.onNotFound]) ||
186
- null;
187
- if (handlers) {
188
- try {
189
- for (const handler of handlers) {
190
- restoreCtx();
191
- const response = yield handler();
192
- if (typeof response === 'string') {
193
- console.log(response);
194
- }
195
- else if (Array.isArray(response)) {
196
- response.forEach((r) => console.log(typeof r === 'string'
197
- ? r
198
- : JSON.stringify(r, null, ' ')));
199
- }
200
- else if (response instanceof Error) {
201
- this.onError(response);
202
- }
203
- else if (response) {
204
- if (response) {
205
- console.log(JSON.stringify(response, null, ' '));
206
- }
207
- }
208
- }
209
- }
210
- catch (e) {
211
- this.onError(e);
212
- }
213
- clearCtx();
214
- }
215
- else {
216
- this.onUnknownCommand(pathParams);
217
- clearCtx();
218
- }
219
- });
220
- }
221
- onError(e) {
222
- var _a;
223
- if ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.onError) {
224
- this.opts.onError(e);
225
- }
226
- else {
227
- this.error(e.message);
228
- process.exit(1);
229
- }
230
- }
231
- /**
232
- * Triggers `unknown command` processing and callbacks
233
- * @param pathParams `string[]` containing command
234
- */
235
- onUnknownCommand(pathParams) {
236
- var _a;
237
- const raiseError = () => {
238
- this.error('' + 'Unknown command: ' + pathParams.join(' '));
239
- process.exit(1);
240
- };
241
- if ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.onUnknownCommand) {
242
- this.opts.onUnknownCommand(pathParams, raiseError);
243
- }
244
- else {
245
- raiseError();
246
- }
247
- }
248
- error(e) {
249
- if (typeof e === 'string') {
250
- console.error('' + 'ERROR: ' + '' + e);
251
- }
252
- else {
253
- console.error('' + 'ERROR: ' + '' + e.message);
254
- }
255
- }
256
- }
257
- /**
258
- * Factory for WooksCli App
259
- * @param opts TWooksCliOptions
260
- * @param wooks Wooks | WooksAdapterBase
261
- * @returns WooksCli
262
- */
263
- function createCliApp(opts, wooks) {
264
- return new WooksCli(opts, wooks);
26
+ const cliShortcuts = {
27
+ cli: 'CLI',
28
+ };
29
+ class WooksCli extends wooks.WooksAdapterBase {
30
+ constructor(opts, wooks) {
31
+ super(wooks, opts?.logger, opts?.router);
32
+ this.opts = opts;
33
+ this.alreadyComputedAliases = false;
34
+ this.logger = opts?.logger || this.getLogger('wooks-cli');
35
+ this.cliHelp =
36
+ opts?.cliHelp instanceof cliHelp.CliHelpRenderer
37
+ ? opts.cliHelp
38
+ : new cliHelp.CliHelpRenderer(opts?.cliHelp);
39
+ }
40
+ /**
41
+ * ### Register CLI Command
42
+ * Command path segments may be separated by / or space.
43
+ *
44
+ * For example the folowing path are interpreted the same:
45
+ * - "command test use:dev :name"
46
+ * - "command/test/use:dev/:name"
47
+ *
48
+ * Where name will become an argument
49
+ *
50
+ * ```js
51
+ * // example without options
52
+ * app.cli('command/:arg', () => 'arg = ' + useRouteParams().params.arg )
53
+ *
54
+ * // example with options
55
+ * app.cli('command/:arg', {
56
+ * description: 'Description of the command',
57
+ * options: [{ keys: ['project', 'p'], description: 'Description of the option', value: 'myProject' }],
58
+ * args: { arg: 'Description of the arg' },
59
+ * aliases: ['cmd'], // alias "cmd/:arg" will be registered
60
+ * examples: [{
61
+ * description: 'Example of usage with someProject',
62
+ * cmd: 'argValue -p=someProject',
63
+ * // will result in help display:
64
+ * // "# Example of usage with someProject\n" +
65
+ * // "$ myCli command argValue -p=someProject\n"
66
+ * }],
67
+ * handler: () => 'arg = ' + useRouteParams().params.arg
68
+ * })
69
+ * ```
70
+ *
71
+ * @param path command path
72
+ * @param _options handler or options
73
+ *
74
+ * @returns
75
+ */
76
+ cli(path, _options) {
77
+ const options = typeof _options === 'function' ? { handler: _options } : _options;
78
+ const handler = typeof _options === 'function' ? _options : _options.handler;
79
+ const makePath = (s) => '/' + s.replace(/\s+/g, '/');
80
+ // register handler
81
+ const targetPath = makePath(path);
82
+ const routed = this.on('CLI', targetPath, handler);
83
+ if (options.onRegister) {
84
+ options.onRegister(targetPath, 0, routed);
85
+ }
86
+ // register direct aliases
87
+ for (const alias of options.aliases || []) {
88
+ const vars = routed.getArgs().map((k) => ':' + k).join('/');
89
+ const targetPath = makePath(alias) + (vars ? '/' + vars : '');
90
+ this.on('CLI', targetPath, handler);
91
+ if (options.onRegister) {
92
+ options.onRegister(targetPath, 1, routed);
93
+ }
94
+ }
95
+ // register helpCli entry
96
+ const command = routed.getStaticPart().replace(/\//g, ' ').trim();
97
+ const args = {
98
+ ...(options.args || {}),
99
+ };
100
+ for (const arg of routed.getArgs()) {
101
+ if (!args[arg]) {
102
+ args[arg] = '';
103
+ }
104
+ }
105
+ this.cliHelp.addEntry({
106
+ command,
107
+ aliases: options.aliases?.map(alias => alias.replace(/\\:/g, ':')), // unescape ":" character
108
+ args,
109
+ description: options.description,
110
+ examples: options.examples,
111
+ options: options.options,
112
+ custom: { handler: options.handler, cb: options.onRegister },
113
+ });
114
+ return routed;
115
+ }
116
+ computeAliases() {
117
+ if (!this.alreadyComputedAliases) {
118
+ this.alreadyComputedAliases = true;
119
+ const aliases = this.cliHelp.getComputedAliases();
120
+ for (const [alias, entry] of Object.entries(aliases)) {
121
+ if (entry.custom) {
122
+ const vars = Object.keys(entry.args || {})
123
+ .map((k) => ':' + k)
124
+ .join('/');
125
+ const path = '/' +
126
+ alias.replace(/\s+/g, '/').replace(/:/g, '\\:') +
127
+ (vars ? '/' + vars : '');
128
+ this.on('CLI', path, entry.custom.handler);
129
+ if (entry.custom.cb) {
130
+ entry.custom.cb(path, 3);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ /**
137
+ * ## run
138
+ * ### Start command processing
139
+ * Triggers command processing
140
+ *
141
+ * By default takes `process.argv.slice(2)` as a command
142
+ *
143
+ * It's possible to replace the command by passing an argument
144
+ *
145
+ * @param _argv optionally overwrite `process.argv.slice(2)` with your `argv` array
146
+ */
147
+ async run(_argv, _opts) {
148
+ const argv = _argv || process.argv.slice(2);
149
+ const parsedFlags = minimist(argv, _opts);
150
+ const pathParams = parsedFlags._;
151
+ const path = '/' +
152
+ pathParams.map((v) => encodeURI(v).replace(/\//g, '%2F')).join('/');
153
+ const { restoreCtx, clearCtx, store } = createCliContext({ opts: _opts, argv, pathParams, cliHelp: this.cliHelp, command: path.replace(/\//g, ' ').trim() }, this.mergeEventOptions(this.opts?.eventOptions));
154
+ store('flags').value = parsedFlags;
155
+ this.computeAliases();
156
+ const { handlers: foundHandlers, firstStatic } = this.wooks.lookup('CLI', path);
157
+ if (typeof firstStatic === 'string') {
158
+ // overwriting command with firstStatic to properly search for help
159
+ store('event').set('command', firstStatic.replace(/\//g, ' ').trim());
160
+ }
161
+ const handlers = foundHandlers ||
162
+ (this.opts?.onNotFound && [this.opts.onNotFound]) ||
163
+ null;
164
+ if (handlers) {
165
+ try {
166
+ for (const handler of handlers) {
167
+ restoreCtx();
168
+ const response = await handler();
169
+ if (typeof response === 'string') {
170
+ console.log(response);
171
+ }
172
+ else if (Array.isArray(response)) {
173
+ response.forEach((r) => console.log(typeof r === 'string'
174
+ ? r
175
+ : JSON.stringify(r, null, ' ')));
176
+ }
177
+ else if (response instanceof Error) {
178
+ this.onError(response);
179
+ }
180
+ else if (response) {
181
+ if (response) {
182
+ console.log(JSON.stringify(response, null, ' '));
183
+ }
184
+ }
185
+ }
186
+ }
187
+ catch (e) {
188
+ this.onError(e);
189
+ }
190
+ clearCtx();
191
+ }
192
+ else {
193
+ this.onUnknownCommand(pathParams);
194
+ clearCtx();
195
+ }
196
+ }
197
+ onError(e) {
198
+ if (this.opts?.onError) {
199
+ this.opts.onError(e);
200
+ }
201
+ else {
202
+ this.error(e.message);
203
+ process.exit(1);
204
+ }
205
+ }
206
+ /**
207
+ * Triggers `unknown command` processing and callbacks
208
+ * @param pathParams `string[]` containing command
209
+ */
210
+ onUnknownCommand(pathParams) {
211
+ const raiseError = () => {
212
+ this.error('' + 'Unknown command: ' + pathParams.join(' '));
213
+ process.exit(1);
214
+ };
215
+ if (this.opts?.onUnknownCommand) {
216
+ this.opts.onUnknownCommand(pathParams, raiseError);
217
+ }
218
+ else {
219
+ raiseError();
220
+ }
221
+ }
222
+ error(e) {
223
+ if (typeof e === 'string') {
224
+ console.error('' + 'ERROR: ' + '' + e);
225
+ }
226
+ else {
227
+ console.error('' + 'ERROR: ' + '' + e.message);
228
+ }
229
+ }
230
+ }
231
+ /**
232
+ * Factory for WooksCli App
233
+ * @param opts TWooksCliOptions
234
+ * @param wooks Wooks | WooksAdapterBase
235
+ * @returns WooksCli
236
+ */
237
+ function createCliApp(opts, wooks) {
238
+ return new WooksCli(opts, wooks);
265
239
  }
266
240
 
267
- /**
268
- * ## useCliHelp
269
- * ### Composable
270
- * ```js
271
- * // example of printing cli instructions
272
- * const { print } = useCliHelp()
273
- * // print with colors
274
- * print(true)
275
- * // print with no colors
276
- * // print(false)
277
- * ```
278
- * @returns
279
- */
280
- function useCliHelp() {
281
- const event = useCliContext().store('event');
282
- const getCliHelp = () => event.get('cliHelp');
283
- const getEntry = () => { var _a; return (_a = getCliHelp().match(event.get('command'))) === null || _a === void 0 ? void 0 : _a.main; };
284
- return {
285
- getCliHelp,
286
- getEntry,
287
- render: (width, withColors) => getCliHelp().render(event.get('command'), width, withColors),
288
- print: (withColors) => getCliHelp().print(event.get('command'), withColors),
289
- };
290
- }
291
- /**
292
- * ## useAutoHelp
293
- * ### Composable
294
- *
295
- * Prints help if `--help` option provided.
296
- *
297
- * ```js
298
- * // example of use: print help and exit
299
- * app.cli('test', () => {
300
- * useAutoHelp() && process.exit(0)
301
- * return 'hit test command'
302
- * })
303
- *
304
- * // add option -h to print help, no colors
305
- * app.cli('test/nocolors', () => {
306
- * useAutoHelp(['help', 'h'], false) && process.exit(0)
307
- * return 'hit test nocolors command'
308
- * })
309
- * ```
310
- * @param keys default `['help']` - list of options to trigger help render
311
- * @param colors default `true`, prints with colors when true
312
- * @returns true when --help was provided. Otherwise returns false
313
- */
314
- function useAutoHelp(keys = ['help'], colors = true) {
315
- for (const option of keys) {
316
- if (useCliOption(option) === true) {
317
- // try {
318
- useCliHelp().print(colors);
319
- return true;
320
- // } catch (e) {
321
- // throw new
322
- // }
323
- }
324
- }
325
- }
326
- /**
327
- * ##useCommandLookupHelp
328
- * ### Composable
329
- *
330
- * Tries to find valid command based on provided command.
331
- *
332
- * If manages to find a valid command, throws an error
333
- * suggesting a list of valid commands
334
- *
335
- * Best to use in `onUnknownCommand` callback:
336
- *
337
- * ```js
338
- * const app = createCliApp({
339
- * onUnknownCommand: (path, raiseError) => {
340
- * // will throw an error suggesting a list
341
- * // of valid commands if could find some
342
- * useCommandLookupHelp()
343
- * // fallback to a regular error handler
344
- * raiseError()
345
- * },
346
- * })
347
- * ```
348
- *
349
- * @param lookupDepth depth of search in backwards
350
- * @example
351
- *
352
- * For provided command `run test:drive dir`
353
- * - lookup1: `run test:drive dir` (deep = 0)
354
- * - lookup2: `run test:drive` (deep = 1)
355
- * - lookup3: `run test` (deep = 2)
356
- * - lookup4: `run` (deep = 3)
357
- * ...
358
- */
359
- function useCommandLookupHelp(lookupDepth = 3) {
360
- const parts = useCliContext()
361
- .store('event')
362
- .get('pathParams')
363
- .map((p) => (p + ' ').split(':').map((s, i) => (i ? ':' + s : s)))
364
- .flat();
365
- const cliHelp = useCliHelp().getCliHelp();
366
- const cmd = cliHelp.getCliName();
367
- let data;
368
- for (let i = 0; i < Math.min(parts.length, lookupDepth + 1); i++) {
369
- const pathParams = parts
370
- .slice(0, i ? -i : parts.length)
371
- .join('')
372
- .trim();
373
- try {
374
- data = cliHelp.match(pathParams);
375
- break;
376
- }
377
- catch (e) {
378
- const variants = cliHelp.lookup(pathParams);
379
- if (variants.length) {
380
- throw new Error(`Wrong command, did you mean:\n${variants
381
- .slice(0, 7)
382
- .map((c) => ` $ ${cmd} ${c.main.command}`)
383
- .join('\n')}`);
384
- }
385
- }
386
- }
387
- if (data) {
388
- const { main, children } = data;
389
- if (main.args && Object.keys(main.args).length) {
390
- throw new Error(`Arguments expected: ${Object.keys(main.args)
391
- .map((l) => `<${l}>`)
392
- .join(', ')}`);
393
- }
394
- else if (children && children.length) {
395
- throw new Error(`Wrong command, did you mean:\n${children
396
- .slice(0, 7)
397
- .map((c) => ` $ ${cmd} ${c.command}`)
398
- .join('\n')}`);
399
- }
400
- }
241
+ /**
242
+ * ## useCliHelp
243
+ * ### Composable
244
+ * ```js
245
+ * // example of printing cli instructions
246
+ * const { print } = useCliHelp()
247
+ * // print with colors
248
+ * print(true)
249
+ * // print with no colors
250
+ * // print(false)
251
+ * ```
252
+ * @returns
253
+ */
254
+ function useCliHelp() {
255
+ const event = useCliContext().store('event');
256
+ const getCliHelp = () => event.get('cliHelp');
257
+ const getEntry = () => getCliHelp().match(event.get('command'))?.main;
258
+ return {
259
+ getCliHelp,
260
+ getEntry,
261
+ render: (width, withColors) => getCliHelp().render(event.get('command'), width, withColors),
262
+ print: (withColors) => getCliHelp().print(event.get('command'), withColors),
263
+ };
264
+ }
265
+ /**
266
+ * ## useAutoHelp
267
+ * ### Composable
268
+ *
269
+ * Prints help if `--help` option provided.
270
+ *
271
+ * ```js
272
+ * // example of use: print help and exit
273
+ * app.cli('test', () => {
274
+ * useAutoHelp() && process.exit(0)
275
+ * return 'hit test command'
276
+ * })
277
+ *
278
+ * // add option -h to print help, no colors
279
+ * app.cli('test/nocolors', () => {
280
+ * useAutoHelp(['help', 'h'], false) && process.exit(0)
281
+ * return 'hit test nocolors command'
282
+ * })
283
+ * ```
284
+ * @param keys default `['help']` - list of options to trigger help render
285
+ * @param colors default `true`, prints with colors when true
286
+ * @returns true when --help was provided. Otherwise returns false
287
+ */
288
+ function useAutoHelp(keys = ['help'], colors = true) {
289
+ for (const option of keys) {
290
+ if (useCliOption(option) === true) {
291
+ // try {
292
+ useCliHelp().print(colors);
293
+ return true;
294
+ // } catch (e) {
295
+ // throw new
296
+ // }
297
+ }
298
+ }
299
+ }
300
+ /**
301
+ * ##useCommandLookupHelp
302
+ * ### Composable
303
+ *
304
+ * Tries to find valid command based on provided command.
305
+ *
306
+ * If manages to find a valid command, throws an error
307
+ * suggesting a list of valid commands
308
+ *
309
+ * Best to use in `onUnknownCommand` callback:
310
+ *
311
+ * ```js
312
+ * const app = createCliApp({
313
+ * onUnknownCommand: (path, raiseError) => {
314
+ * // will throw an error suggesting a list
315
+ * // of valid commands if could find some
316
+ * useCommandLookupHelp()
317
+ * // fallback to a regular error handler
318
+ * raiseError()
319
+ * },
320
+ * })
321
+ * ```
322
+ *
323
+ * @param lookupDepth depth of search in backwards
324
+ * @example
325
+ *
326
+ * For provided command `run test:drive dir`
327
+ * - lookup1: `run test:drive dir` (deep = 0)
328
+ * - lookup2: `run test:drive` (deep = 1)
329
+ * - lookup3: `run test` (deep = 2)
330
+ * - lookup4: `run` (deep = 3)
331
+ * ...
332
+ */
333
+ function useCommandLookupHelp(lookupDepth = 3) {
334
+ const parts = useCliContext()
335
+ .store('event')
336
+ .get('pathParams')
337
+ .map((p) => (p + ' ').split(':').map((s, i) => (i ? ':' + s : s)))
338
+ .flat();
339
+ const cliHelp = useCliHelp().getCliHelp();
340
+ const cmd = cliHelp.getCliName();
341
+ let data;
342
+ for (let i = 0; i < Math.min(parts.length, lookupDepth + 1); i++) {
343
+ const pathParams = parts
344
+ .slice(0, i ? -i : parts.length)
345
+ .join('')
346
+ .trim();
347
+ try {
348
+ data = cliHelp.match(pathParams);
349
+ break;
350
+ }
351
+ catch (e) {
352
+ const variants = cliHelp.lookup(pathParams);
353
+ if (variants.length) {
354
+ throw new Error(`Wrong command, did you mean:\n${variants
355
+ .slice(0, 7)
356
+ .map((c) => ` $ ${cmd} ${c.main.command}`)
357
+ .join('\n')}`);
358
+ }
359
+ }
360
+ }
361
+ if (data) {
362
+ const { main, children } = data;
363
+ if (main.args && Object.keys(main.args).length) {
364
+ throw new Error(`Arguments expected: ${Object.keys(main.args)
365
+ .map((l) => `<${l}>`)
366
+ .join(', ')}`);
367
+ }
368
+ else if (children && children.length) {
369
+ throw new Error(`Wrong command, did you mean:\n${children
370
+ .slice(0, 7)
371
+ .map((c) => ` $ ${cmd} ${c.command}`)
372
+ .join('\n')}`);
373
+ }
374
+ }
401
375
  }
402
376
 
403
- /**
404
- * Get CLI Options
405
- *
406
- * @returns an object with CLI options
407
- */
408
- function useCliOptions() {
409
- const { store } = useCliContext();
410
- const flags = store('flags');
411
- if (!flags.value) {
412
- const event = store('event');
413
- flags.value = minimist(event.value.argv, event.get('opts'));
414
- }
415
- return flags.value;
416
- }
417
- /**
418
- * Getter for Cli Option value
419
- *
420
- * @param name name of the option
421
- * @returns value of a CLI option
422
- */
423
- function useCliOption(name) {
424
- var _a;
425
- try {
426
- const options = ((_a = useCliHelp().getEntry()) === null || _a === void 0 ? void 0 : _a.options) || [];
427
- const opt = options.find(o => o.keys.includes(name));
428
- if (opt) {
429
- for (const key of opt.keys) {
430
- if (useCliOptions()[key]) {
431
- return useCliOptions()[key];
432
- }
433
- }
434
- }
435
- }
436
- catch (e) {
437
- //
438
- }
439
- return useCliOptions()[name];
377
+ /**
378
+ * Get CLI Options
379
+ *
380
+ * @returns an object with CLI options
381
+ */
382
+ function useCliOptions() {
383
+ const { store } = useCliContext();
384
+ const flags = store('flags');
385
+ if (!flags.value) {
386
+ const event = store('event');
387
+ flags.value = minimist(event.value.argv, event.get('opts'));
388
+ }
389
+ return flags.value;
390
+ }
391
+ /**
392
+ * Getter for Cli Option value
393
+ *
394
+ * @param name name of the option
395
+ * @returns value of a CLI option
396
+ */
397
+ function useCliOption(name) {
398
+ try {
399
+ const options = useCliHelp().getEntry()?.options || [];
400
+ const opt = options.find(o => o.keys.includes(name));
401
+ if (opt) {
402
+ for (const key of opt.keys) {
403
+ if (useCliOptions()[key]) {
404
+ return useCliOptions()[key];
405
+ }
406
+ }
407
+ }
408
+ }
409
+ catch (e) {
410
+ //
411
+ }
412
+ return useCliOptions()[name];
440
413
  }
441
414
 
442
415
  exports.WooksCli = WooksCli;