@oclif/core 2.0.1 → 2.0.2-beta.10

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 (91) hide show
  1. package/README.md +5 -5
  2. package/lib/args.d.ts +39 -0
  3. package/lib/args.js +62 -0
  4. package/lib/cli-ux/action/base.d.ts +1 -1
  5. package/lib/cli-ux/action/pride-spinner.js +0 -1
  6. package/lib/cli-ux/action/spinner.js +10 -11
  7. package/lib/cli-ux/action/spinners.d.ts +251 -0
  8. package/lib/cli-ux/action/spinners.js +2 -1
  9. package/lib/cli-ux/config.d.ts +1 -1
  10. package/lib/cli-ux/config.js +7 -5
  11. package/lib/cli-ux/index.d.ts +51 -29
  12. package/lib/cli-ux/index.js +111 -69
  13. package/lib/cli-ux/list.js +3 -4
  14. package/lib/cli-ux/prompt.js +9 -8
  15. package/lib/cli-ux/styled/header.js +1 -1
  16. package/lib/cli-ux/styled/index.d.ts +7 -0
  17. package/lib/cli-ux/styled/index.js +15 -0
  18. package/lib/cli-ux/styled/json.d.ts +1 -1
  19. package/lib/cli-ux/styled/json.js +2 -3
  20. package/lib/cli-ux/styled/object.js +1 -1
  21. package/lib/cli-ux/styled/progress.d.ts +2 -1
  22. package/lib/cli-ux/styled/progress.js +3 -7
  23. package/lib/cli-ux/styled/table.js +1 -3
  24. package/lib/cli-ux/styled/tree.js +0 -1
  25. package/lib/cli-ux/wait.d.ts +1 -1
  26. package/lib/cli-ux/wait.js +0 -1
  27. package/lib/command.d.ts +78 -27
  28. package/lib/command.js +51 -43
  29. package/lib/config/config.d.ts +20 -17
  30. package/lib/config/config.js +86 -28
  31. package/lib/config/index.js +0 -5
  32. package/lib/config/plugin.d.ts +3 -2
  33. package/lib/config/plugin.js +10 -14
  34. package/lib/config/util.js +2 -2
  35. package/lib/errors/index.js +0 -1
  36. package/lib/errors/logger.js +2 -4
  37. package/lib/flags.d.ts +46 -18
  38. package/lib/flags.js +71 -29
  39. package/lib/help/command.d.ts +12 -12
  40. package/lib/help/command.js +6 -6
  41. package/lib/help/docopts.d.ts +3 -3
  42. package/lib/help/docopts.js +3 -3
  43. package/lib/help/formatter.d.ts +4 -3
  44. package/lib/help/index.d.ts +10 -14
  45. package/lib/help/index.js +0 -5
  46. package/lib/help/util.d.ts +1 -2
  47. package/lib/help/util.js +2 -1
  48. package/lib/index.d.ts +6 -5
  49. package/lib/index.js +10 -8
  50. package/lib/interfaces/args.d.ts +22 -0
  51. package/lib/interfaces/{command.js → args.js} +0 -0
  52. package/lib/interfaces/config.d.ts +1 -2
  53. package/lib/interfaces/flags.d.ts +2 -2
  54. package/lib/interfaces/hooks.d.ts +12 -1
  55. package/lib/interfaces/index.d.ts +2 -2
  56. package/lib/interfaces/manifest.d.ts +2 -2
  57. package/lib/interfaces/parser.d.ts +97 -82
  58. package/lib/interfaces/pjson.d.ts +2 -0
  59. package/lib/interfaces/plugin.d.ts +2 -1
  60. package/lib/main.d.ts +54 -1
  61. package/lib/main.js +71 -7
  62. package/lib/parser/errors.d.ts +15 -8
  63. package/lib/parser/errors.js +17 -14
  64. package/lib/parser/help.d.ts +1 -1
  65. package/lib/parser/help.js +4 -9
  66. package/lib/parser/index.d.ts +2 -9
  67. package/lib/parser/index.js +5 -26
  68. package/lib/parser/parse.d.ts +4 -11
  69. package/lib/parser/parse.js +107 -72
  70. package/lib/parser/validate.d.ts +1 -1
  71. package/lib/parser/validate.js +6 -3
  72. package/lib/util.d.ts +20 -0
  73. package/lib/util.js +57 -1
  74. package/package.json +8 -8
  75. package/lib/cli-ux/deps.d.ts +0 -22
  76. package/lib/cli-ux/deps.js +0 -47
  77. package/lib/cli-ux/open.d.ts +0 -6
  78. package/lib/cli-ux/open.js +0 -69
  79. package/lib/help/_test-help-class.d.ts +0 -6
  80. package/lib/help/_test-help-class.js +0 -19
  81. package/lib/interfaces/command.d.ts +0 -110
  82. package/lib/parser/args.d.ts +0 -5
  83. package/lib/parser/args.js +0 -11
  84. package/lib/parser/deps.d.ts +0 -4
  85. package/lib/parser/deps.js +0 -17
  86. package/lib/parser/flags.d.ts +0 -60
  87. package/lib/parser/flags.js +0 -107
  88. package/lib/parser/list.d.ts +0 -2
  89. package/lib/parser/list.js +0 -29
  90. package/lib/parser/util.d.ts +0 -7
  91. package/lib/parser/util.js +0 -50
@@ -1,43 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.custom = exports.option = exports.build = exports.string = exports.file = exports.directory = exports.url = exports.integer = exports.boolean = exports.parse = exports.flagUsages = exports.flags = exports.args = void 0;
4
- const args = require("./args");
5
- exports.args = args;
6
- const deps_1 = require("./deps");
7
- const flags = require("./flags");
8
- exports.flags = flags;
3
+ exports.parse = exports.flagUsages = void 0;
9
4
  const parse_1 = require("./parse");
5
+ const validate_1 = require("./validate");
10
6
  var help_1 = require("./help");
11
7
  Object.defineProperty(exports, "flagUsages", { enumerable: true, get: function () { return help_1.flagUsages; } });
12
- // eslint-disable-next-line new-cap
13
- const m = (0, deps_1.default)()
14
- // eslint-disable-next-line node/no-missing-require
15
- .add('validate', () => require('./validate').validate);
16
8
  async function parse(argv, options) {
17
9
  const input = {
18
10
  argv,
19
11
  context: options.context,
20
- args: (options.args || []).map((a) => args.newArg(a)),
21
12
  '--': options['--'],
22
- flags: {
23
- color: flags.defaultFlags.color,
24
- ...options.flags,
25
- },
13
+ flags: (options.flags ?? {}),
14
+ args: (options.args ?? {}),
26
15
  strict: options.strict !== false,
27
16
  };
28
17
  const parser = new parse_1.Parser(input);
29
18
  const output = await parser.parse();
30
- await m.validate({ input, output });
19
+ await (0, validate_1.validate)({ input, output });
31
20
  return output;
32
21
  }
33
22
  exports.parse = parse;
34
- var flags_1 = require("./flags");
35
- Object.defineProperty(exports, "boolean", { enumerable: true, get: function () { return flags_1.boolean; } });
36
- Object.defineProperty(exports, "integer", { enumerable: true, get: function () { return flags_1.integer; } });
37
- Object.defineProperty(exports, "url", { enumerable: true, get: function () { return flags_1.url; } });
38
- Object.defineProperty(exports, "directory", { enumerable: true, get: function () { return flags_1.directory; } });
39
- Object.defineProperty(exports, "file", { enumerable: true, get: function () { return flags_1.file; } });
40
- Object.defineProperty(exports, "string", { enumerable: true, get: function () { return flags_1.string; } });
41
- Object.defineProperty(exports, "build", { enumerable: true, get: function () { return flags_1.build; } });
42
- Object.defineProperty(exports, "option", { enumerable: true, get: function () { return flags_1.option; } });
43
- Object.defineProperty(exports, "custom", { enumerable: true, get: function () { return flags_1.custom; } });
@@ -1,5 +1,5 @@
1
- import { ParserInput, OutputFlags, ParsingToken, OutputArgs } from '../interfaces';
2
- export declare class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags']>, TArgs extends OutputArgs> {
1
+ import { OutputArgs, OutputFlags, ParserInput, ParserOutput } from '../interfaces/parser';
2
+ export declare class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags']>, BFlags extends OutputFlags<T['flags']>, TArgs extends OutputArgs<T['args']>> {
3
3
  private readonly input;
4
4
  private readonly argv;
5
5
  private readonly raw;
@@ -9,17 +9,10 @@ export declare class Parser<T extends ParserInput, TFlags extends OutputFlags<T[
9
9
  private readonly metaData;
10
10
  private currentFlag?;
11
11
  constructor(input: T);
12
- parse(): Promise<{
13
- args: TArgs;
14
- argv: any[];
15
- flags: TFlags;
16
- raw: ParsingToken[];
17
- metadata: any;
18
- }>;
19
- private _args;
12
+ parse(): Promise<ParserOutput<TFlags, BFlags, TArgs>>;
20
13
  private _flags;
21
14
  private _validateOptions;
22
- private _argv;
15
+ private _args;
23
16
  private _debugOutput;
24
17
  private _debugInput;
25
18
  private get _argTokens();
@@ -1,14 +1,10 @@
1
1
  "use strict";
2
- // tslint:disable interface-over-type-literal
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.Parser = void 0;
5
- const deps_1 = require("./deps");
6
- // eslint-disable-next-line new-cap
7
- const m = (0, deps_1.default)()
8
- // eslint-disable-next-line node/no-missing-require
9
- .add('errors', () => require('./errors'))
10
- // eslint-disable-next-line node/no-missing-require
11
- .add('util', () => require('./util'));
4
+ /* eslint-disable no-await-in-loop */
5
+ const errors_1 = require("./errors");
6
+ const readline = require("readline");
7
+ const util_1 = require("../util");
12
8
  let debug;
13
9
  try {
14
10
  // eslint-disable-next-line no-negated-condition
@@ -18,26 +14,49 @@ catch {
18
14
  debug = () => { };
19
15
  }
20
16
  const readStdin = async () => {
21
- const { stdin } = process;
22
- let result;
23
- if (stdin.isTTY || stdin.isTTY === undefined)
24
- return result;
25
- result = '';
26
- stdin.setEncoding('utf8');
27
- for await (const chunk of stdin) {
28
- result += chunk;
29
- }
30
- return result;
17
+ const { stdin, stdout } = process;
18
+ debug('stdin.isTTY', stdin.isTTY);
19
+ if (stdin.isTTY)
20
+ return null;
21
+ // process.stdin.isTTY is true whenever it's running in a terminal.
22
+ // process.stdin.isTTY is undefined when it's running in a pipe, e.g. echo 'foo' | my-cli command
23
+ // process.stdin.isTTY is undefined when it's running in a spawned process, even if there's no pipe.
24
+ // This means that reading from stdin could hang indefinitely while waiting for a non-existent pipe.
25
+ // Because of this, we have to set a timeout to prevent the process from hanging.
26
+ return new Promise(resolve => {
27
+ let result = '';
28
+ const ac = new AbortController();
29
+ const signal = ac.signal;
30
+ const timeout = setTimeout(() => ac.abort(), 100);
31
+ const rl = readline.createInterface({
32
+ input: stdin,
33
+ output: stdout,
34
+ terminal: false,
35
+ });
36
+ rl.on('line', line => {
37
+ result += line;
38
+ });
39
+ rl.once('close', () => {
40
+ clearTimeout(timeout);
41
+ debug('resolved from stdin', result);
42
+ resolve(result);
43
+ });
44
+ signal.addEventListener('abort', () => {
45
+ debug('stdin aborted');
46
+ clearTimeout(timeout);
47
+ rl.close();
48
+ resolve(null);
49
+ }, { once: true });
50
+ });
31
51
  };
32
52
  class Parser {
33
53
  constructor(input) {
34
54
  this.input = input;
35
55
  this.raw = [];
36
- const { pickBy } = m.util;
37
56
  this.context = input.context || {};
38
57
  this.argv = [...input.argv];
39
58
  this._setNames();
40
- this.booleanFlags = pickBy(input.flags, f => f.type === 'boolean');
59
+ this.booleanFlags = (0, util_1.pickBy)(input.flags, f => f.type === 'boolean');
41
60
  this.flagAliases = Object.fromEntries(Object.values(input.flags).flatMap(flag => {
42
61
  return (flag.aliases ?? []).map(a => [a, flag]);
43
62
  }));
@@ -86,7 +105,7 @@ class Parser {
86
105
  this.currentFlag = flag;
87
106
  const input = long || arg.length < 3 ? this.argv.shift() : arg.slice(arg[2] === '=' ? 3 : 2);
88
107
  if (typeof input !== 'string') {
89
- throw new m.errors.CLIError(`Flag --${name} expects a value`);
108
+ throw new errors_1.CLIError(`Flag --${name} expects a value`);
90
109
  }
91
110
  this.raw.push({ type: 'flag', flag: flag.name, input });
92
111
  }
@@ -100,6 +119,9 @@ class Parser {
100
119
  return true;
101
120
  };
102
121
  let parsingFlags = true;
122
+ const nonExistentFlags = [];
123
+ let dashdash = false;
124
+ const originalArgv = [...this.argv];
103
125
  while (this.argv.length > 0) {
104
126
  const input = this.argv.shift();
105
127
  if (parsingFlags && input.startsWith('-') && input !== '-') {
@@ -111,45 +133,48 @@ class Parser {
111
133
  if (parseFlag(input)) {
112
134
  continue;
113
135
  }
114
- // not actually a flag if it reaches here so parse as an arg
136
+ if (input === '--') {
137
+ dashdash = true;
138
+ continue;
139
+ }
140
+ if (this.input['--'] !== false) {
141
+ // At this point we have a value that begins with '-' or '--'
142
+ // but doesn't match up to a flag definition. So we assume that
143
+ // this is a misspelled flag or a non-existent flag,
144
+ // e.g. --hekp instead of --help
145
+ nonExistentFlags.push(input);
146
+ continue;
147
+ }
115
148
  }
116
149
  if (parsingFlags && this.currentFlag && this.currentFlag.multiple) {
117
150
  this.raw.push({ type: 'flag', flag: this.currentFlag.name, input });
118
151
  continue;
119
152
  }
120
153
  // not a flag, parse as arg
121
- const arg = this.input.args[this._argTokens.length];
122
- if (arg)
123
- arg.input = input;
124
- this.raw.push({ type: 'arg', input });
154
+ const arg = Object.keys(this.input.args)[this._argTokens.length];
155
+ this.raw.push({ type: 'arg', arg, input });
125
156
  }
126
- const argv = await this._argv();
127
- const args = this._args(argv);
157
+ const { argv, args } = await this._args();
128
158
  const flags = await this._flags();
129
159
  this._debugOutput(argv, args, flags);
160
+ const unsortedArgv = (dashdash ? [...argv, ...nonExistentFlags, '--'] : [...argv, ...nonExistentFlags]);
130
161
  return {
131
- args,
132
- argv,
162
+ argv: unsortedArgv.sort((a, b) => originalArgv.indexOf(a) - originalArgv.indexOf(b)),
133
163
  flags,
164
+ args: args,
134
165
  raw: this.raw,
135
166
  metadata: this.metaData,
167
+ nonExistentFlags,
136
168
  };
137
169
  }
138
- _args(argv) {
139
- const args = {};
140
- for (let i = 0; i < this.input.args.length; i++) {
141
- const arg = this.input.args[i];
142
- args[arg.name] = argv[i];
143
- }
144
- return args;
145
- }
170
+ // eslint-disable-next-line complexity
146
171
  async _flags() {
147
172
  const flags = {};
148
173
  this.metaData.flags = {};
149
174
  for (const token of this._flagTokens) {
150
175
  const flag = this.input.flags[token.flag];
151
176
  if (!flag)
152
- throw new m.errors.CLIError(`Unexpected flag ${token.flag}`);
177
+ throw new errors_1.CLIError(`Unexpected flag ${token.flag}`);
153
178
  if (flag.type === 'boolean') {
154
179
  if (token.input === `--no-${flag.name}`) {
155
180
  flags[token.flag] = false;
@@ -157,20 +182,25 @@ class Parser {
157
182
  else {
158
183
  flags[token.flag] = true;
159
184
  }
160
- // eslint-disable-next-line no-await-in-loop
161
185
  flags[token.flag] = await flag.parse(flags[token.flag], this.context, flag);
162
186
  }
163
187
  else {
164
188
  const input = token.input;
165
189
  this._validateOptions(flag, input);
166
- // eslint-disable-next-line no-await-in-loop
167
- const value = flag.parse ? await flag.parse(input, this.context, flag) : input;
168
- if (flag.multiple) {
190
+ if (flag.delimiter && flag.multiple) {
191
+ const values = await Promise.all(input.split(flag.delimiter).map(async (v) => flag.parse ? flag.parse(v.trim(), this.context, flag) : v.trim()));
169
192
  flags[token.flag] = flags[token.flag] || [];
170
- flags[token.flag].push(...(Array.isArray(value) ? value : [value]));
193
+ flags[token.flag].push(...values);
171
194
  }
172
195
  else {
173
- flags[token.flag] = value;
196
+ const value = flag.parse ? await flag.parse(input, this.context, flag) : input;
197
+ if (flag.multiple) {
198
+ flags[token.flag] = flags[token.flag] || [];
199
+ flags[token.flag].push(value);
200
+ }
201
+ else {
202
+ flags[token.flag] = value;
203
+ }
174
204
  }
175
205
  }
176
206
  }
@@ -183,18 +213,16 @@ class Parser {
183
213
  if (flag.type === 'option') {
184
214
  if (input) {
185
215
  this._validateOptions(flag, input);
186
- // eslint-disable-next-line no-await-in-loop
187
216
  flags[k] = await flag.parse(input, this.context, flag);
188
217
  }
189
218
  }
190
219
  else if (flag.type === 'boolean') {
191
220
  // eslint-disable-next-line no-negated-condition
192
- flags[k] = input !== undefined ? ['true', 'TRUE', '1', 'yes', 'YES', 'y', 'Y'].includes(input) : false;
221
+ flags[k] = input !== undefined ? (0, util_1.isTruthy)(input) : false;
193
222
  }
194
223
  }
195
224
  if (!(k in flags) && flag.default !== undefined) {
196
225
  this.metaData.flags[k] = { setFromDefault: true };
197
- // eslint-disable-next-line no-await-in-loop
198
226
  const defaultValue = (typeof flag.default === 'function' ? await flag.default({ options: flag, flags, ...this.context }) : flag.default);
199
227
  flags[k] = defaultValue;
200
228
  }
@@ -203,48 +231,51 @@ class Parser {
203
231
  }
204
232
  _validateOptions(flag, input) {
205
233
  if (flag.options && !flag.options.includes(input))
206
- throw new m.errors.FlagInvalidOptionError(flag, input);
234
+ throw new errors_1.FlagInvalidOptionError(flag, input);
207
235
  }
208
- async _argv() {
209
- const args = [];
236
+ async _args() {
237
+ const argv = [];
238
+ const args = {};
210
239
  const tokens = this._argTokens;
211
240
  let stdinRead = false;
212
- for (let i = 0; i < Math.max(this.input.args.length, tokens.length); i++) {
213
- const token = tokens[i];
214
- const arg = this.input.args[i];
241
+ for (const [name, arg] of Object.entries(this.input.args)) {
242
+ const token = tokens.find(t => t.arg === name);
215
243
  if (token) {
216
- if (arg) {
217
- if (arg.options && !arg.options.includes(token.input)) {
218
- throw new m.errors.ArgInvalidOptionError(arg, token.input);
219
- }
220
- // eslint-disable-next-line no-await-in-loop
221
- args[i] = await arg.parse(token.input);
222
- }
223
- else {
224
- args[i] = token.input;
244
+ if (arg.options && !arg.options.includes(token.input)) {
245
+ throw new errors_1.ArgInvalidOptionError(arg, token.input);
225
246
  }
247
+ const parsed = await arg.parse(token.input, this.context, arg);
248
+ argv.push(parsed);
249
+ args[token.arg] = parsed;
226
250
  }
227
251
  else if (!arg.ignoreStdin && !stdinRead) {
228
- // eslint-disable-next-line no-await-in-loop
229
252
  let stdin = await readStdin();
230
253
  if (stdin) {
231
254
  stdin = stdin.trim();
232
- args[i] = stdin;
255
+ const parsed = await arg.parse(stdin, this.context, arg);
256
+ argv.push(parsed);
257
+ args[name] = parsed;
233
258
  }
234
259
  stdinRead = true;
235
260
  }
236
- if (!args[i] && arg?.default !== undefined) {
261
+ if (!args[name] && (arg.default || arg.default === false)) {
237
262
  if (typeof arg.default === 'function') {
238
- // eslint-disable-next-line no-await-in-loop
239
263
  const f = await arg.default();
240
- args[i] = f;
264
+ argv.push(f);
265
+ args[name] = f;
241
266
  }
242
267
  else {
243
- args[i] = arg.default;
268
+ argv.push(arg.default);
269
+ args[name] = arg.default;
244
270
  }
245
271
  }
246
272
  }
247
- return args;
273
+ for (const token of tokens) {
274
+ if (args[token.arg])
275
+ continue;
276
+ argv.push(token.input);
277
+ }
278
+ return { argv, args: args };
248
279
  }
249
280
  _debugOutput(args, flags, argv) {
250
281
  if (argv.length > 0) {
@@ -259,8 +290,9 @@ class Parser {
259
290
  }
260
291
  _debugInput() {
261
292
  debug('input: %s', this.argv.join(' '));
262
- if (this.input.args.length > 0) {
263
- debug('available args: %s', this.input.args.map(a => a.name).join(' '));
293
+ const args = Object.keys(this.input.args);
294
+ if (args.length > 0) {
295
+ debug('available args: %s', args.join(' '));
264
296
  }
265
297
  if (Object.keys(this.input.flags).length === 0)
266
298
  return;
@@ -278,6 +310,9 @@ class Parser {
278
310
  for (const k of Object.keys(this.input.flags)) {
279
311
  this.input.flags[k].name = k;
280
312
  }
313
+ for (const k of Object.keys(this.input.args)) {
314
+ this.input.args[k].name = k;
315
+ }
281
316
  }
282
317
  }
283
318
  exports.Parser = Parser;
@@ -1,4 +1,4 @@
1
- import { ParserInput, ParserOutput } from '../interfaces';
1
+ import { ParserInput, ParserOutput } from '../interfaces/parser';
2
2
  export declare function validate(parse: {
3
3
  input: ParserInput;
4
4
  output: ParserOutput;
@@ -5,14 +5,17 @@ const errors_1 = require("./errors");
5
5
  const util_1 = require("../config/util");
6
6
  async function validate(parse) {
7
7
  function validateArgs() {
8
- const maxArgs = parse.input.args.length;
8
+ if (parse.output.nonExistentFlags?.length > 0) {
9
+ throw new errors_1.NonExistentFlagsError({ parse, flags: parse.output.nonExistentFlags });
10
+ }
11
+ const maxArgs = Object.keys(parse.input.args).length;
9
12
  if (parse.input.strict && parse.output.argv.length > maxArgs) {
10
13
  const extras = parse.output.argv.slice(maxArgs);
11
14
  throw new errors_1.UnexpectedArgsError({ parse, args: extras });
12
15
  }
13
16
  const missingRequiredArgs = [];
14
17
  let hasOptional = false;
15
- for (const [index, arg] of parse.input.args.entries()) {
18
+ for (const [name, arg] of Object.entries(parse.input.args)) {
16
19
  if (!arg.required) {
17
20
  hasOptional = true;
18
21
  }
@@ -21,7 +24,7 @@ async function validate(parse) {
21
24
  // optionals should follow required, not before
22
25
  throw new errors_1.InvalidArgsSpecError({ parse, args: parse.input.args });
23
26
  }
24
- if (arg.required && !parse.output.argv[index] && parse.output.argv[index] !== 0) {
27
+ if (arg.required && !parse.output.args[name] && parse.output.args[name] !== 0) {
25
28
  missingRequiredArgs.push(arg);
26
29
  }
27
30
  }
package/lib/util.d.ts CHANGED
@@ -1,3 +1,8 @@
1
+ import { Command } from './command';
2
+ import { ArgInput } from './interfaces/parser';
3
+ export declare function pickBy<T extends {
4
+ [s: string]: T[keyof T];
5
+ } | ArrayLike<T[keyof T]>>(obj: T, fn: (i: T[keyof T]) => boolean): Partial<T>;
1
6
  export declare function compact<T>(a: (T | undefined)[]): T[];
2
7
  export declare function uniqBy<T>(arr: T[], fn: (cur: T) => any): T[];
3
8
  type SortTypes = string | number | undefined | boolean;
@@ -7,4 +12,19 @@ export declare function isProd(): boolean;
7
12
  export declare function maxBy<T>(arr: T[], fn: (i: T) => number): T | undefined;
8
13
  export declare function sumBy<T>(arr: T[], fn: (i: T) => number): number;
9
14
  export declare function capitalize(s: string): string;
15
+ export declare const dirExists: (input: string) => Promise<string>;
16
+ export declare const fileExists: (input: string) => Promise<string>;
17
+ export declare function isTruthy(input: string): boolean;
18
+ export declare function isNotFalsy(input: string): boolean;
19
+ export declare function requireJson<T>(...pathParts: string[]): T;
20
+ /**
21
+ * Ensure that the provided args are an object. This is for backwards compatibility with v1 commands which
22
+ * defined args as an array.
23
+ *
24
+ * @param args Either an array of args or an object of args
25
+ * @returns ArgInput
26
+ */
27
+ export declare function ensureArgObject(args?: any[] | ArgInput | {
28
+ [name: string]: Command.Arg.Cached;
29
+ }): ArgInput;
10
30
  export {};
package/lib/util.js CHANGED
@@ -1,6 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.capitalize = exports.sumBy = exports.maxBy = exports.isProd = exports.castArray = exports.sortBy = exports.uniqBy = exports.compact = void 0;
3
+ exports.ensureArgObject = exports.requireJson = exports.isNotFalsy = exports.isTruthy = exports.fileExists = exports.dirExists = exports.capitalize = exports.sumBy = exports.maxBy = exports.isProd = exports.castArray = exports.sortBy = exports.uniqBy = exports.compact = exports.pickBy = void 0;
4
+ const fs = require("fs");
5
+ const path_1 = require("path");
6
+ function pickBy(obj, fn) {
7
+ return Object.entries(obj)
8
+ .reduce((o, [k, v]) => {
9
+ if (fn(v))
10
+ o[k] = v;
11
+ return o;
12
+ }, {});
13
+ }
14
+ exports.pickBy = pickBy;
4
15
  function compact(a) {
5
16
  return a.filter((a) => Boolean(a));
6
17
  }
@@ -62,3 +73,48 @@ function capitalize(s) {
62
73
  return s ? s.charAt(0).toUpperCase() + s.slice(1).toLowerCase() : '';
63
74
  }
64
75
  exports.capitalize = capitalize;
76
+ const dirExists = async (input) => {
77
+ if (!fs.existsSync(input)) {
78
+ throw new Error(`No directory found at ${input}`);
79
+ }
80
+ if (!(await fs.promises.stat(input)).isDirectory()) {
81
+ throw new Error(`${input} exists but is not a directory`);
82
+ }
83
+ return input;
84
+ };
85
+ exports.dirExists = dirExists;
86
+ const fileExists = async (input) => {
87
+ if (!fs.existsSync(input)) {
88
+ throw new Error(`No file found at ${input}`);
89
+ }
90
+ if (!(await fs.promises.stat(input)).isFile()) {
91
+ throw new Error(`${input} exists but is not a file`);
92
+ }
93
+ return input;
94
+ };
95
+ exports.fileExists = fileExists;
96
+ function isTruthy(input) {
97
+ return ['true', '1', 'yes', 'y'].includes(input.toLowerCase());
98
+ }
99
+ exports.isTruthy = isTruthy;
100
+ function isNotFalsy(input) {
101
+ return !['false', '0', 'no', 'n'].includes(input.toLowerCase());
102
+ }
103
+ exports.isNotFalsy = isNotFalsy;
104
+ function requireJson(...pathParts) {
105
+ return JSON.parse(fs.readFileSync((0, path_1.join)(...pathParts), 'utf8'));
106
+ }
107
+ exports.requireJson = requireJson;
108
+ /**
109
+ * Ensure that the provided args are an object. This is for backwards compatibility with v1 commands which
110
+ * defined args as an array.
111
+ *
112
+ * @param args Either an array of args or an object of args
113
+ * @returns ArgInput
114
+ */
115
+ function ensureArgObject(args) {
116
+ return (Array.isArray(args) ? (args ?? []).reduce((x, y) => {
117
+ return { ...x, [y.name]: y };
118
+ }, {}) : args ?? {});
119
+ }
120
+ exports.ensureArgObject = ensureArgObject;
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "@oclif/core",
3
3
  "description": "base library for oclif CLIs",
4
- "version": "2.0.1",
4
+ "version": "2.0.2-beta.10",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/core/issues",
7
7
  "dependencies": {
8
- "@oclif/linewrap": "^1.0.0",
9
- "@oclif/screen": "^3.0.4",
8
+ "@types/cli-progress": "^3.11.0",
10
9
  "ansi-escapes": "^4.3.2",
11
10
  "ansi-styles": "^4.3.0",
12
11
  "cardinal": "^2.1.1",
@@ -32,31 +31,32 @@
32
31
  "supports-hyperlinks": "^2.2.0",
33
32
  "tslib": "^2.4.1",
34
33
  "widest-line": "^3.1.0",
34
+ "wordwrap": "^1.0.0",
35
35
  "wrap-ansi": "^7.0.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@commitlint/config-conventional": "^12.1.4",
39
39
  "@oclif/plugin-help": "^5.1.22",
40
40
  "@oclif/plugin-plugins": "^2.1.12",
41
- "@oclif/test": "^2.2.19",
41
+ "@oclif/test": "^2.2.20",
42
42
  "@types/ansi-styles": "^3.2.1",
43
43
  "@types/chai": "^4.3.4",
44
44
  "@types/chai-as-promised": "^7.1.5",
45
45
  "@types/clean-stack": "^2.1.1",
46
- "@types/cli-progress": "^3.9.2",
47
46
  "@types/ejs": "^3.1.0",
48
47
  "@types/fs-extra": "^9.0.13",
49
48
  "@types/indent-string": "^4.0.1",
50
49
  "@types/js-yaml": "^3.12.7",
51
50
  "@types/mocha": "^8.2.3",
52
51
  "@types/nock": "^11.1.0",
53
- "@types/node": "^15.14.9",
52
+ "@types/node": "^16",
54
53
  "@types/node-notifier": "^8.0.2",
55
54
  "@types/proxyquire": "^1.3.28",
56
55
  "@types/semver": "^7.3.13",
57
56
  "@types/shelljs": "^0.8.11",
58
57
  "@types/strip-ansi": "^5.2.1",
59
58
  "@types/supports-color": "^8.1.1",
59
+ "@types/wordwrap": "^1.0.1",
60
60
  "@types/wrap-ansi": "^3.0.0",
61
61
  "chai": "^4.3.7",
62
62
  "chai-as-promised": "^7.1.1",
@@ -64,11 +64,11 @@
64
64
  "eslint": "^7.32.0",
65
65
  "eslint-config-oclif": "^4.0.0",
66
66
  "eslint-config-oclif-typescript": "^1.0.2",
67
- "fancy-test": "^1.4.10",
67
+ "fancy-test": "^2.0.12",
68
68
  "globby": "^11.1.0",
69
69
  "husky": "6",
70
70
  "mocha": "^8.4.0",
71
- "nock": "^13.2.4",
71
+ "nock": "^13.3.0",
72
72
  "proxyquire": "^2.1.3",
73
73
  "shelljs": "^0.8.5",
74
74
  "shx": "^0.3.4",
@@ -1,22 +0,0 @@
1
- declare const _default: {
2
- readonly stripAnsi: (string: string) => string;
3
- readonly ansiStyles: {
4
- readonly modifier: import("ansi-styles").Modifier;
5
- readonly color: import("ansi-styles").ForegroundColor & import("ansi-styles").ColorBase;
6
- readonly bgColor: import("ansi-styles").BackgroundColor & import("ansi-styles").ColorBase;
7
- readonly codes: ReadonlyMap<number, number>;
8
- } & import("ansi-styles").BackgroundColor & import("ansi-styles").ForegroundColor & import("ansi-styles").Modifier;
9
- readonly ansiEscapes: any;
10
- readonly passwordPrompt: any;
11
- readonly screen: typeof import("@oclif/screen");
12
- readonly open: typeof import("./open").default;
13
- readonly prompt: typeof import("./prompt");
14
- readonly styledObject: typeof import("./styled/object").default;
15
- readonly styledHeader: typeof import("./styled/header").default;
16
- readonly styledJSON: typeof import("./styled/json").default;
17
- readonly table: typeof import("./styled/table").table;
18
- readonly tree: typeof import("./styled/tree").default;
19
- readonly wait: (ms?: number) => Promise<unknown>;
20
- readonly progress: typeof import("./styled/progress").default;
21
- };
22
- export default _default;
@@ -1,47 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- /* eslint-disable node/no-missing-require */
4
- exports.default = {
5
- get stripAnsi() {
6
- return require('strip-ansi');
7
- },
8
- get ansiStyles() {
9
- return require('ansi-styles');
10
- },
11
- get ansiEscapes() {
12
- return require('ansi-escapes');
13
- },
14
- get passwordPrompt() {
15
- return require('password-prompt');
16
- },
17
- get screen() {
18
- return require('@oclif/screen');
19
- },
20
- get open() {
21
- return require('./open').default;
22
- },
23
- get prompt() {
24
- return require('./prompt');
25
- },
26
- get styledObject() {
27
- return require('./styled/object').default;
28
- },
29
- get styledHeader() {
30
- return require('./styled/header').default;
31
- },
32
- get styledJSON() {
33
- return require('./styled/json').default;
34
- },
35
- get table() {
36
- return require('./styled/table').table;
37
- },
38
- get tree() {
39
- return require('./styled/tree').default;
40
- },
41
- get wait() {
42
- return require('./wait').default;
43
- },
44
- get progress() {
45
- return require('./styled/progress').default;
46
- },
47
- };