@oclif/core 3.0.0-beta.13 → 3.0.0-beta.14

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 (76) hide show
  1. package/README.md +3 -1
  2. package/lib/args.d.ts +1 -1
  3. package/lib/args.js +13 -15
  4. package/lib/cli-ux/action/base.d.ts +1 -1
  5. package/lib/cli-ux/action/base.js +20 -15
  6. package/lib/cli-ux/action/simple.js +10 -8
  7. package/lib/cli-ux/action/spinner.js +11 -10
  8. package/lib/cli-ux/config.js +8 -7
  9. package/lib/cli-ux/flush.js +2 -3
  10. package/lib/cli-ux/index.d.ts +10 -28
  11. package/lib/cli-ux/index.js +26 -45
  12. package/lib/cli-ux/list.js +1 -1
  13. package/lib/cli-ux/prompt.js +24 -19
  14. package/lib/cli-ux/styled/index.d.ts +5 -6
  15. package/lib/cli-ux/styled/index.js +11 -11
  16. package/lib/cli-ux/styled/json.js +3 -2
  17. package/lib/cli-ux/styled/object.js +6 -8
  18. package/lib/cli-ux/styled/table.js +36 -45
  19. package/lib/cli-ux/wait.js +3 -5
  20. package/lib/command.d.ts +7 -5
  21. package/lib/command.js +35 -28
  22. package/lib/config/config.d.ts +2 -2
  23. package/lib/config/config.js +57 -43
  24. package/lib/config/plugin-loader.js +25 -11
  25. package/lib/config/plugin.d.ts +1 -1
  26. package/lib/config/plugin.js +66 -56
  27. package/lib/config/ts-node.d.ts +2 -1
  28. package/lib/config/ts-node.js +41 -34
  29. package/lib/config/util.d.ts +1 -5
  30. package/lib/config/util.js +5 -46
  31. package/lib/errors/config.js +1 -1
  32. package/lib/errors/errors/cli.d.ts +1 -1
  33. package/lib/errors/errors/cli.js +14 -13
  34. package/lib/errors/errors/exit.d.ts +0 -3
  35. package/lib/errors/errors/module-load.d.ts +0 -3
  36. package/lib/errors/errors/pretty-print.js +9 -8
  37. package/lib/errors/handle.d.ts +12 -2
  38. package/lib/errors/handle.js +23 -14
  39. package/lib/errors/index.d.ts +2 -2
  40. package/lib/errors/index.js +20 -19
  41. package/lib/errors/logger.js +4 -4
  42. package/lib/execute.d.ts +5 -5
  43. package/lib/execute.js +6 -5
  44. package/lib/flags.d.ts +102 -31
  45. package/lib/flags.js +75 -42
  46. package/lib/help/command.d.ts +2 -0
  47. package/lib/help/command.js +32 -32
  48. package/lib/help/docopts.js +2 -9
  49. package/lib/help/formatter.d.ts +1 -1
  50. package/lib/help/formatter.js +17 -17
  51. package/lib/help/index.d.ts +2 -2
  52. package/lib/help/index.js +22 -21
  53. package/lib/help/root.js +2 -2
  54. package/lib/help/util.d.ts +1 -1
  55. package/lib/help/util.js +9 -9
  56. package/lib/index.d.ts +19 -20
  57. package/lib/index.js +38 -42
  58. package/lib/interfaces/config.d.ts +5 -4
  59. package/lib/interfaces/errors.d.ts +1 -1
  60. package/lib/interfaces/parser.d.ts +168 -45
  61. package/lib/interfaces/plugin.d.ts +1 -0
  62. package/lib/main.d.ts +1 -1
  63. package/lib/main.js +16 -16
  64. package/lib/module-loader.d.ts +67 -77
  65. package/lib/module-loader.js +179 -149
  66. package/lib/parser/errors.d.ts +2 -2
  67. package/lib/parser/errors.js +4 -3
  68. package/lib/parser/help.js +3 -2
  69. package/lib/parser/parse.d.ts +3 -0
  70. package/lib/parser/parse.js +56 -52
  71. package/lib/parser/validate.js +9 -5
  72. package/lib/performance.d.ts +6 -2
  73. package/lib/performance.js +23 -12
  74. package/lib/util.d.ts +25 -1
  75. package/lib/util.js +93 -29
  76. package/package.json +10 -15
@@ -3,15 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Parser = void 0;
4
4
  /* eslint-disable no-await-in-loop */
5
5
  const errors_1 = require("./errors");
6
- const readline = require("readline");
7
6
  const util_1 = require("../util");
7
+ const node_readline_1 = require("node:readline");
8
8
  let debug;
9
9
  try {
10
- // eslint-disable-next-line no-negated-condition
11
- debug = process.env.CLI_FLAGS_DEBUG !== '1' ? () => { } : require('debug')('../parser');
10
+ debug = process.env.CLI_FLAGS_DEBUG === '1' ? require('debug')('../parser') : () => {
11
+ // noop
12
+ };
12
13
  }
13
14
  catch {
14
- debug = () => { };
15
+ debug = () => {
16
+ // noop
17
+ };
15
18
  }
16
19
  const readStdin = async () => {
17
20
  const { stdin, stdout } = process;
@@ -25,9 +28,9 @@ const readStdin = async () => {
25
28
  return new Promise(resolve => {
26
29
  let result = '';
27
30
  const ac = new AbortController();
28
- const signal = ac.signal;
31
+ const { signal } = ac;
29
32
  const timeout = setTimeout(() => ac.abort(), 100);
30
- const rl = readline.createInterface({
33
+ const rl = (0, node_readline_1.createInterface)({
31
34
  input: stdin,
32
35
  output: stdout,
33
36
  terminal: false,
@@ -51,6 +54,11 @@ const readStdin = async () => {
51
54
  function isNegativeNumber(input) {
52
55
  return /^-\d/g.test(input);
53
56
  }
57
+ const validateOptions = (flag, input) => {
58
+ if (flag.options && !flag.options.includes(input))
59
+ throw new errors_1.FlagInvalidOptionError(flag, input);
60
+ return input;
61
+ };
54
62
  class Parser {
55
63
  constructor(input) {
56
64
  this.input = input;
@@ -59,40 +67,12 @@ class Parser {
59
67
  this.argv = [...input.argv];
60
68
  this._setNames();
61
69
  this.booleanFlags = (0, util_1.pickBy)(input.flags, f => f.type === 'boolean');
62
- this.flagAliases = Object.fromEntries(Object.values(input.flags).flatMap(flag => {
63
- return (flag.aliases ?? []).map(a => [a, flag]);
64
- }));
70
+ this.flagAliases = Object.fromEntries(Object.values(input.flags).flatMap(flag => ([...flag.aliases ?? [], ...flag.charAliases ?? []]).map(a => [a, flag])));
65
71
  }
66
72
  async parse() {
67
73
  this._debugInput();
68
- const findLongFlag = (arg) => {
69
- const name = arg.slice(2);
70
- if (this.input.flags[name]) {
71
- return name;
72
- }
73
- if (this.flagAliases[name]) {
74
- return this.flagAliases[name].name;
75
- }
76
- if (arg.startsWith('--no-')) {
77
- const flag = this.booleanFlags[arg.slice(5)];
78
- if (flag && flag.allowNo)
79
- return flag.name;
80
- }
81
- };
82
- const findShortFlag = ([_, char]) => {
83
- if (this.flagAliases[char]) {
84
- return this.flagAliases[char].name;
85
- }
86
- return Object.keys(this.input.flags).find(k => (this.input.flags[k].char === char && char !== undefined && this.input.flags[k].char !== undefined));
87
- };
88
- const findFlag = (arg) => {
89
- const isLong = arg.startsWith('--');
90
- const short = isLong ? false : arg.startsWith('-');
91
- const name = isLong ? findLongFlag(arg) : (short ? findShortFlag(arg) : undefined);
92
- return { name, isLong };
93
- };
94
74
  const parseFlag = (arg) => {
95
- const { name, isLong } = findFlag(arg);
75
+ const { name, isLong } = this.findFlag(arg);
96
76
  if (!name) {
97
77
  const i = arg.indexOf('=');
98
78
  if (i !== -1) {
@@ -108,13 +88,16 @@ class Parser {
108
88
  }
109
89
  const flag = this.input.flags[name];
110
90
  if (flag.type === 'option') {
91
+ if (!flag.multiple && this.raw.some(o => o.type === 'flag' && o.flag === name)) {
92
+ throw new errors_1.CLIError(`Flag --${name} can only be specified once`);
93
+ }
111
94
  this.currentFlag = flag;
112
95
  const input = isLong || arg.length < 3 ? this.argv.shift() : arg.slice(arg[2] === '=' ? 3 : 2);
113
96
  // if the value ends up being one of the command's flags, the user didn't provide an input
114
- if ((typeof input !== 'string') || findFlag(input).name) {
97
+ if ((typeof input !== 'string') || this.findFlag(input).name) {
115
98
  throw new errors_1.CLIError(`Flag --${name} expects a value`);
116
99
  }
117
- this.raw.push({ type: 'flag', flag: flag.name, input: input });
100
+ this.raw.push({ type: 'flag', flag: flag.name, input });
118
101
  }
119
102
  else {
120
103
  this.raw.push({ type: 'flag', flag: flag.name, input: arg });
@@ -174,11 +157,6 @@ class Parser {
174
157
  };
175
158
  }
176
159
  async _flags() {
177
- const validateOptions = (flag, input) => {
178
- if (flag.options && !flag.options.includes(input))
179
- throw new errors_1.FlagInvalidOptionError(flag, input);
180
- return input;
181
- };
182
160
  const parseFlagOrThrowError = async (input, flag, context, token) => {
183
161
  if (!flag.parse)
184
162
  return input;
@@ -252,17 +230,18 @@ class Parser {
252
230
  if (fws.inputFlag.flag.type === 'boolean') {
253
231
  return {
254
232
  ...fws,
255
- valueFunction: async (i) => Promise.resolve((0, util_1.isTruthy)(process.env[i.inputFlag.flag.env] ?? 'false')),
233
+ valueFunction: async (i) => (0, util_1.isTruthy)(process.env[i.inputFlag.flag.env] ?? 'false'),
256
234
  };
257
235
  }
258
236
  }
259
237
  // no input, but flag has default value
238
+ // eslint-disable-next-line no-constant-binary-expression, valid-typeof
260
239
  if (typeof fws.inputFlag.flag.default !== undefined) {
261
240
  return {
262
241
  ...fws, metadata: { setFromDefault: true },
263
- valueFunction: typeof fws.inputFlag.flag.default === 'function' ?
264
- (i, allFlags = {}) => fws.inputFlag.flag.default({ options: i.inputFlag.flag, flags: allFlags }) :
265
- async () => fws.inputFlag.flag.default,
242
+ valueFunction: typeof fws.inputFlag.flag.default === 'function'
243
+ ? (i, allFlags = {}) => fws.inputFlag.flag.default({ options: i.inputFlag.flag, flags: allFlags })
244
+ : async () => fws.inputFlag.flag.default,
266
245
  };
267
246
  }
268
247
  // base case (no value function)
@@ -271,11 +250,11 @@ class Parser {
271
250
  const addHelpFunction = (fws) => {
272
251
  if (fws.inputFlag.flag.type === 'option' && fws.inputFlag.flag.defaultHelp) {
273
252
  return {
274
- ...fws, helpFunction: typeof fws.inputFlag.flag.defaultHelp === 'function' ?
253
+ ...fws, helpFunction: typeof fws.inputFlag.flag.defaultHelp === 'function'
275
254
  // @ts-expect-error flag type isn't specific enough to know defaultHelp will definitely be there
276
- (i, flags, ...context) => i.inputFlag.flag.defaultHelp({ options: i.inputFlag, flags }, ...context) :
255
+ ? (i, flags, ...context) => i.inputFlag.flag.defaultHelp({ options: i.inputFlag, flags }, ...context)
277
256
  // @ts-expect-error flag type isn't specific enough to know defaultHelp will definitely be there
278
- (i) => i.inputFlag.flag.defaultHelp,
257
+ : (i) => i.inputFlag.flag.defaultHelp,
279
258
  };
280
259
  }
281
260
  return fws;
@@ -318,7 +297,6 @@ class Parser {
318
297
  .map(async (fws) => (fws.metadata?.setFromDefault ? { ...fws, value: await fws.valueFunction?.(fws, valueReference) } : fws)));
319
298
  const finalFlags = (flagsWithAllValues.some(fws => typeof fws.helpFunction === 'function')) ? await addDefaultHelp(flagsWithAllValues) : flagsWithAllValues;
320
299
  return {
321
- // @ts-ignore original version returned an any. Not sure how to get to the return type for `flags` prop
322
300
  flags: fwsArrayToObject(finalFlags),
323
301
  metadata: { flags: Object.fromEntries(finalFlags.filter(fws => fws.metadata).map(fws => [fws.inputFlag.name, fws.metadata])) },
324
302
  };
@@ -367,7 +345,7 @@ class Parser {
367
345
  continue;
368
346
  argv.push(token.input);
369
347
  }
370
- return { argv, args: args };
348
+ return { argv, args };
371
349
  }
372
350
  _debugOutput(args, flags, argv) {
373
351
  if (argv.length > 0) {
@@ -415,5 +393,31 @@ class Parser {
415
393
  }
416
394
  return flagTokenMap;
417
395
  }
396
+ findLongFlag(arg) {
397
+ const name = arg.slice(2);
398
+ if (this.input.flags[name]) {
399
+ return name;
400
+ }
401
+ if (this.flagAliases[name]) {
402
+ return this.flagAliases[name].name;
403
+ }
404
+ if (arg.startsWith('--no-')) {
405
+ const flag = this.booleanFlags[arg.slice(5)];
406
+ if (flag && flag.allowNo)
407
+ return flag.name;
408
+ }
409
+ }
410
+ findShortFlag([_, char]) {
411
+ if (this.flagAliases[char]) {
412
+ return this.flagAliases[char].name;
413
+ }
414
+ return Object.keys(this.input.flags).find(k => (this.input.flags[k].char === char && char !== undefined && this.input.flags[k].char !== undefined));
415
+ }
416
+ findFlag(arg) {
417
+ const isLong = arg.startsWith('--');
418
+ const short = isLong ? false : arg.startsWith('-');
419
+ const name = isLong ? this.findLongFlag(arg) : (short ? this.findShortFlag(arg) : undefined);
420
+ return { name, isLong };
421
+ }
418
422
  }
419
423
  exports.Parser = Parser;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validate = void 0;
4
4
  const errors_1 = require("./errors");
5
- const util_1 = require("../config/util");
5
+ const util_1 = require("../util");
6
6
  async function validate(parse) {
7
7
  let cachedResolvedFlags;
8
8
  function validateArgs() {
@@ -139,14 +139,18 @@ async function validate(parse) {
139
139
  function validateRelationships(name, flag) {
140
140
  return ((flag.relationships ?? []).map(relationship => {
141
141
  switch (relationship.type) {
142
- case 'all':
142
+ case 'all': {
143
143
  return validateDependsOn(name, relationship.flags);
144
- case 'some':
144
+ }
145
+ case 'some': {
145
146
  return validateSome(name, relationship.flags);
146
- case 'none':
147
+ }
148
+ case 'none': {
147
149
  return validateExclusive(name, relationship.flags);
148
- default:
150
+ }
151
+ default: {
149
152
  throw new Error(`Unknown relationship type: ${relationship.type}`);
153
+ }
150
154
  }
151
155
  }));
152
156
  }
@@ -12,7 +12,11 @@ type PerfHighlights = {
12
12
  runTime: number;
13
13
  initTime: number;
14
14
  commandLoadTime: number;
15
- pluginLoadTimes: Record<string, number>;
15
+ commandRunTime: number;
16
+ pluginLoadTimes: Record<string, {
17
+ duration: number;
18
+ details: Details;
19
+ }>;
16
20
  corePluginsLoadTime: number;
17
21
  userPluginsLoadTime: number;
18
22
  linkedPluginsLoadTime: number;
@@ -32,7 +36,7 @@ declare class Marker {
32
36
  stop(): void;
33
37
  measure(): void;
34
38
  }
35
- export default class Performance {
39
+ export declare class Performance {
36
40
  private static markers;
37
41
  private static _results;
38
42
  private static _highlights;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const perf_hooks_1 = require("perf_hooks");
3
+ exports.Performance = void 0;
4
+ const node_perf_hooks_1 = require("node:perf_hooks");
4
5
  const settings_1 = require("./settings");
5
6
  class Marker {
6
7
  constructor(name, details = {}) {
@@ -14,17 +15,17 @@ class Marker {
14
15
  this.module = module;
15
16
  this.method = method;
16
17
  this.scope = scope;
17
- perf_hooks_1.performance.mark(this.startMarker);
18
+ node_perf_hooks_1.performance.mark(this.startMarker);
18
19
  }
19
20
  addDetails(details) {
20
21
  this.details = { ...this.details, ...details };
21
22
  }
22
23
  stop() {
23
24
  this.stopped = true;
24
- perf_hooks_1.performance.mark(this.stopMarker);
25
+ node_perf_hooks_1.performance.mark(this.stopMarker);
25
26
  }
26
27
  measure() {
27
- perf_hooks_1.performance.measure(this.name, this.startMarker, this.stopMarker);
28
+ node_perf_hooks_1.performance.measure(this.name, this.startMarker, this.stopMarker);
28
29
  }
29
30
  }
30
31
  class Performance {
@@ -79,7 +80,7 @@ class Performance {
79
80
  marker.stop();
80
81
  }
81
82
  return new Promise(resolve => {
82
- const perfObserver = new perf_hooks_1.PerformanceObserver(items => {
83
+ const perfObserver = new node_perf_hooks_1.PerformanceObserver(items => {
83
84
  for (const entry of items.getEntries()) {
84
85
  if (Performance.markers[entry.name]) {
85
86
  const marker = Performance.markers[entry.name];
@@ -98,7 +99,7 @@ class Performance {
98
99
  const pluginLoadTimes = Object.fromEntries(Performance.results
99
100
  .filter(({ name }) => name.startsWith('plugin.load#'))
100
101
  .sort((a, b) => b.duration - a.duration)
101
- .map(({ scope, duration }) => [scope, duration]));
102
+ .map(({ scope, duration, details }) => [scope, { duration, details }]));
102
103
  const hookRunTimes = Performance.results
103
104
  .filter(({ name }) => name.startsWith('config.runHook#'))
104
105
  .reduce((acc, perfResult) => {
@@ -120,10 +121,12 @@ class Performance {
120
121
  .filter(({ name }) => name.startsWith('config.loadPlugins#'))
121
122
  .sort((a, b) => b.duration - a.duration)
122
123
  .map(({ scope, duration }) => [scope, duration]));
124
+ const commandRunTime = Performance.results.find(({ name }) => name.startsWith('config.runCommand#'))?.duration ?? 0;
123
125
  Performance._highlights = {
124
126
  configLoadTime: Performance.getResult('config.load')?.duration ?? 0,
125
127
  runTime: Performance.getResult('main.run')?.duration ?? 0,
126
128
  initTime: Performance.getResult('main.run#init')?.duration ?? 0,
129
+ commandRunTime,
127
130
  commandLoadTime,
128
131
  pluginLoadTimes,
129
132
  hookRunTimes,
@@ -142,7 +145,7 @@ class Performance {
142
145
  // ignore
143
146
  }
144
147
  }
145
- perf_hooks_1.performance.clearMarks();
148
+ node_perf_hooks_1.performance.clearMarks();
146
149
  });
147
150
  }
148
151
  /**
@@ -153,16 +156,22 @@ class Performance {
153
156
  if (!Performance.enabled)
154
157
  return;
155
158
  const debug = require('debug')('perf');
159
+ debug('Total Time: %sms', Performance.highlights.runTime.toFixed(4));
156
160
  debug('Init Time: %sms', Performance.highlights.initTime.toFixed(4));
157
161
  debug('Config Load Time: %sms', Performance.highlights.configLoadTime.toFixed(4));
158
- debug('Command Load Time: %sms', Performance.highlights.commandLoadTime.toFixed(4));
159
- debug('Execution Time: %sms', Performance.highlights.runTime.toFixed(4));
162
+ debug(' Plugins Load Time: %sms', Performance.getResult('config.loadAllPlugins')?.duration.toFixed(4) ?? 0);
163
+ debug(' Commands Load Time: %sms', Performance.getResult('config.loadAllCommands')?.duration.toFixed(4) ?? 0);
160
164
  debug('Core Plugin Load Time: %sms', Performance.highlights.corePluginsLoadTime.toFixed(4));
161
165
  debug('User Plugin Load Time: %sms', Performance.highlights.userPluginsLoadTime.toFixed(4));
162
166
  debug('Linked Plugin Load Time: %sms', Performance.highlights.linkedPluginsLoadTime.toFixed(4));
163
167
  debug('Plugin Load Times:');
164
- for (const [plugin, duration] of Object.entries(Performance.highlights.pluginLoadTimes)) {
165
- debug(` ${plugin}: ${duration.toFixed(4)}ms`);
168
+ for (const [plugin, result] of Object.entries(Performance.highlights.pluginLoadTimes)) {
169
+ if (result.details.hasManifest) {
170
+ debug(` ${plugin}: ${result.duration.toFixed(4)}ms`);
171
+ }
172
+ else {
173
+ debug(` ${plugin}: ${result.duration.toFixed(4)}ms (no manifest!)`);
174
+ }
166
175
  }
167
176
  debug('Hook Run Times:');
168
177
  for (const [event, runTimes] of Object.entries(Performance.highlights.hookRunTimes)) {
@@ -171,8 +180,10 @@ class Performance {
171
180
  debug(` ${plugin}: ${duration.toFixed(4)}ms`);
172
181
  }
173
182
  }
183
+ debug('Command Load Time: %sms', Performance.highlights.commandLoadTime.toFixed(4));
184
+ debug('Command Run Time: %sms', Performance.highlights.commandRunTime.toFixed(4));
174
185
  }
175
186
  }
176
- exports.default = Performance;
187
+ exports.Performance = Performance;
177
188
  Performance.markers = {};
178
189
  Performance._results = [];
package/lib/util.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { Command } from './command';
1
+ /// <reference types="node" />
2
2
  import { ArgInput } from './interfaces/parser';
3
+ import { Command } from './command';
3
4
  export declare function pickBy<T extends {
4
5
  [s: string]: T[keyof T];
5
6
  } | ArrayLike<T[keyof T]>>(obj: T, fn: (i: T[keyof T]) => boolean): Partial<T>;
@@ -13,6 +14,7 @@ export declare function isProd(): boolean;
13
14
  export declare function maxBy<T>(arr: T[], fn: (i: T) => number): T | undefined;
14
15
  export declare function sumBy<T>(arr: T[], fn: (i: T) => number): number;
15
16
  export declare function capitalize(s: string): string;
17
+ export declare function exists(path: string): Promise<boolean>;
16
18
  export declare const dirExists: (input: string) => Promise<string>;
17
19
  export declare const fileExists: (input: string) => Promise<string>;
18
20
  export declare function isTruthy(input: string): boolean;
@@ -28,4 +30,26 @@ export declare function requireJson<T>(...pathParts: string[]): T;
28
30
  export declare function ensureArgObject(args?: any[] | ArgInput | {
29
31
  [name: string]: Command.Arg.Cached;
30
32
  }): ArgInput;
33
+ export declare function uniq<T>(arr: T[]): T[];
34
+ /**
35
+ * Call os.homedir() and return the result
36
+ *
37
+ * Wrapping this allows us to stub these in tests since os.homedir() is
38
+ * non-configurable and non-writable.
39
+ *
40
+ * @returns The user's home directory
41
+ */
42
+ export declare function getHomeDir(): string;
43
+ /**
44
+ * Call os.platform() and return the result
45
+ *
46
+ * Wrapping this allows us to stub these in tests since os.platform() is
47
+ * non-configurable and non-writable.
48
+ *
49
+ * @returns The process' platform
50
+ */
51
+ export declare function getPlatform(): NodeJS.Platform;
52
+ export declare function readJson<T = unknown>(path: string): Promise<T>;
53
+ export declare function readJsonSync(path: string, parse: false): string;
54
+ export declare function readJsonSync<T = unknown>(path: string, parse?: true): T;
31
55
  export {};
package/lib/util.js CHANGED
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
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.last = exports.uniqBy = exports.compact = exports.pickBy = void 0;
4
- const fs = require("fs");
5
- const path_1 = require("path");
3
+ exports.readJsonSync = exports.readJson = exports.getPlatform = exports.getHomeDir = exports.uniq = exports.ensureArgObject = exports.requireJson = exports.isNotFalsy = exports.isTruthy = exports.fileExists = exports.dirExists = exports.exists = exports.capitalize = exports.sumBy = exports.maxBy = exports.isProd = exports.castArray = exports.sortBy = exports.last = exports.uniqBy = exports.compact = exports.pickBy = void 0;
4
+ const promises_1 = require("node:fs/promises");
5
+ const node_os_1 = require("node:os");
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ const debug = require('debug');
6
9
  function pickBy(obj, fn) {
7
10
  return Object.entries(obj)
8
11
  .reduce((o, [k, v]) => {
@@ -13,6 +16,7 @@ function pickBy(obj, fn) {
13
16
  }
14
17
  exports.pickBy = pickBy;
15
18
  function compact(a) {
19
+ // eslint-disable-next-line unicorn/prefer-native-coercion-functions
16
20
  return a.filter((a) => Boolean(a));
17
21
  }
18
22
  exports.compact = compact;
@@ -26,27 +30,27 @@ exports.uniqBy = uniqBy;
26
30
  function last(arr) {
27
31
  if (!arr)
28
32
  return;
29
- return arr.slice(-1)[0];
33
+ return arr.at(-1);
30
34
  }
31
35
  exports.last = last;
32
- function sortBy(arr, fn) {
33
- function compare(a, b) {
34
- a = a === undefined ? 0 : a;
35
- b = b === undefined ? 0 : b;
36
- if (Array.isArray(a) && Array.isArray(b)) {
37
- if (a.length === 0 && b.length === 0)
38
- return 0;
39
- const diff = compare(a[0], b[0]);
40
- if (diff !== 0)
41
- return diff;
42
- return compare(a.slice(1), b.slice(1));
43
- }
44
- if (a < b)
45
- return -1;
46
- if (a > b)
47
- return 1;
48
- return 0;
36
+ function compare(a, b) {
37
+ a = a === undefined ? 0 : a;
38
+ b = b === undefined ? 0 : b;
39
+ if (Array.isArray(a) && Array.isArray(b)) {
40
+ if (a.length === 0 && b.length === 0)
41
+ return 0;
42
+ const diff = compare(a[0], b[0]);
43
+ if (diff !== 0)
44
+ return diff;
45
+ return compare(a.slice(1), b.slice(1));
49
46
  }
47
+ if (a < b)
48
+ return -1;
49
+ if (a > b)
50
+ return 1;
51
+ return 0;
52
+ }
53
+ function sortBy(arr, fn) {
50
54
  return arr.sort((a, b) => compare(fn(a), fn(b)));
51
55
  }
52
56
  exports.sortBy = sortBy;
@@ -79,21 +83,33 @@ function capitalize(s) {
79
83
  return s ? s.charAt(0).toUpperCase() + s.slice(1).toLowerCase() : '';
80
84
  }
81
85
  exports.capitalize = capitalize;
86
+ async function exists(path) {
87
+ try {
88
+ await (0, promises_1.access)(path);
89
+ return true;
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ }
95
+ exports.exists = exists;
82
96
  const dirExists = async (input) => {
83
- if (!fs.existsSync(input)) {
97
+ if (!await exists(input)) {
84
98
  throw new Error(`No directory found at ${input}`);
85
99
  }
86
- if (!(await fs.promises.stat(input)).isDirectory()) {
100
+ const fileStat = await (0, promises_1.stat)(input);
101
+ if (!fileStat.isDirectory()) {
87
102
  throw new Error(`${input} exists but is not a directory`);
88
103
  }
89
104
  return input;
90
105
  };
91
106
  exports.dirExists = dirExists;
92
107
  const fileExists = async (input) => {
93
- if (!fs.existsSync(input)) {
108
+ if (!await exists(input)) {
94
109
  throw new Error(`No file found at ${input}`);
95
110
  }
96
- if (!(await fs.promises.stat(input)).isFile()) {
111
+ const fileStat = await (0, promises_1.stat)(input);
112
+ if (!fileStat.isFile()) {
97
113
  throw new Error(`${input} exists but is not a file`);
98
114
  }
99
115
  return input;
@@ -108,7 +124,7 @@ function isNotFalsy(input) {
108
124
  }
109
125
  exports.isNotFalsy = isNotFalsy;
110
126
  function requireJson(...pathParts) {
111
- return JSON.parse(fs.readFileSync((0, path_1.join)(...pathParts), 'utf8'));
127
+ return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(...pathParts), 'utf8'));
112
128
  }
113
129
  exports.requireJson = requireJson;
114
130
  /**
@@ -119,8 +135,56 @@ exports.requireJson = requireJson;
119
135
  * @returns ArgInput
120
136
  */
121
137
  function ensureArgObject(args) {
122
- return (Array.isArray(args) ? (args ?? []).reduce((x, y) => {
123
- return { ...x, [y.name]: y };
124
- }, {}) : args ?? {});
138
+ return (Array.isArray(args) ? (args ?? []).reduce((x, y) => ({ ...x, [y.name]: y }), {}) : args ?? {});
125
139
  }
126
140
  exports.ensureArgObject = ensureArgObject;
141
+ function uniq(arr) {
142
+ return [...new Set(arr)].sort();
143
+ }
144
+ exports.uniq = uniq;
145
+ /**
146
+ * Call os.homedir() and return the result
147
+ *
148
+ * Wrapping this allows us to stub these in tests since os.homedir() is
149
+ * non-configurable and non-writable.
150
+ *
151
+ * @returns The user's home directory
152
+ */
153
+ function getHomeDir() {
154
+ return (0, node_os_1.homedir)();
155
+ }
156
+ exports.getHomeDir = getHomeDir;
157
+ /**
158
+ * Call os.platform() and return the result
159
+ *
160
+ * Wrapping this allows us to stub these in tests since os.platform() is
161
+ * non-configurable and non-writable.
162
+ *
163
+ * @returns The process' platform
164
+ */
165
+ function getPlatform() {
166
+ return (0, node_os_1.platform)();
167
+ }
168
+ exports.getPlatform = getPlatform;
169
+ function readJson(path) {
170
+ debug('config')('readJson %s', path);
171
+ return new Promise((resolve, reject) => {
172
+ (0, node_fs_1.readFile)(path, 'utf8', (err, d) => {
173
+ try {
174
+ if (err)
175
+ reject(err);
176
+ else
177
+ resolve(JSON.parse(d));
178
+ }
179
+ catch (error) {
180
+ reject(error);
181
+ }
182
+ });
183
+ });
184
+ }
185
+ exports.readJson = readJson;
186
+ function readJsonSync(path, parse = true) {
187
+ const contents = (0, node_fs_1.readFileSync)(path, 'utf8');
188
+ return parse ? JSON.parse(contents) : contents;
189
+ }
190
+ exports.readJsonSync = readJsonSync;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oclif/core",
3
3
  "description": "base library for oclif CLIs",
4
- "version": "3.0.0-beta.13",
4
+ "version": "3.0.0-beta.14",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/core/issues",
7
7
  "dependencies": {
@@ -45,15 +45,12 @@
45
45
  "@types/chai-as-promised": "^7.1.5",
46
46
  "@types/clean-stack": "^2.1.1",
47
47
  "@types/ejs": "^3.1.2",
48
- "@types/glob": "^8.1.0",
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": "^16",
52
+ "@types/node": "^18",
54
53
  "@types/node-notifier": "^8.0.2",
55
- "@types/proxyquire": "^1.3.28",
56
- "@types/shelljs": "^0.8.12",
57
54
  "@types/slice-ansi": "^4.0.0",
58
55
  "@types/strip-ansi": "^5.2.1",
59
56
  "@types/supports-color": "^8.1.1",
@@ -64,23 +61,21 @@
64
61
  "chai-as-promised": "^7.1.1",
65
62
  "commitlint": "^12.1.4",
66
63
  "cross-env": "^7.0.3",
67
- "eslint": "^7.32.0",
68
- "eslint-config-oclif": "^4.0.0",
69
- "eslint-config-oclif-typescript": "^1.0.3",
70
- "fancy-test": "^2.0.16",
64
+ "eslint": "^8.49.0",
65
+ "eslint-config-oclif": "^5.0.0",
66
+ "eslint-config-oclif-typescript": "^2.0.1",
67
+ "fancy-test": "^3.0.0-beta.2",
71
68
  "globby": "^11.1.0",
72
69
  "husky": "6",
73
70
  "mocha": "^10.2.0",
74
71
  "nock": "^13.3.0",
75
- "proxyquire": "^2.1.3",
76
- "shelljs": "^0.8.5",
77
72
  "shx": "^0.3.4",
78
73
  "sinon": "^11.1.2",
79
- "tsd": "^0.25.0",
80
- "typescript": "^4.9.5"
74
+ "tsd": "^0.29.0",
75
+ "typescript": "^5"
81
76
  },
82
77
  "engines": {
83
- "node": ">=16.0.0"
78
+ "node": ">=18.0.0"
84
79
  },
85
80
  "files": [
86
81
  "/lib",
@@ -109,7 +104,7 @@
109
104
  "build": "shx rm -rf lib && tsc",
110
105
  "commitlint": "commitlint",
111
106
  "compile": "tsc",
112
- "lint": "eslint . --ext .ts --config .eslintrc",
107
+ "lint": "eslint . --ext .ts",
113
108
  "posttest": "yarn lint",
114
109
  "prepack": "yarn run build",
115
110
  "pretest": "yarn build --noEmit && tsc -p test --noEmit --skipLibCheck",