@oclif/core 3.0.0-beta.2 → 3.0.0-beta.21

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 (112) hide show
  1. package/README.md +10 -6
  2. package/flush.js +1 -1
  3. package/handle.js +1 -1
  4. package/lib/args.d.ts +1 -1
  5. package/lib/args.js +17 -18
  6. package/lib/cli-ux/action/base.d.ts +3 -5
  7. package/lib/cli-ux/action/base.js +32 -26
  8. package/lib/cli-ux/action/simple.js +13 -18
  9. package/lib/cli-ux/action/spinner.d.ts +4 -2
  10. package/lib/cli-ux/action/spinner.js +27 -19
  11. package/lib/cli-ux/action/spinners.js +1 -1
  12. package/lib/cli-ux/action/types.d.ts +5 -0
  13. package/lib/cli-ux/action/types.js +2 -0
  14. package/lib/cli-ux/config.d.ts +0 -1
  15. package/lib/cli-ux/config.js +17 -21
  16. package/lib/cli-ux/exit.d.ts +1 -1
  17. package/lib/cli-ux/exit.js +4 -1
  18. package/lib/cli-ux/flush.d.ts +1 -0
  19. package/lib/cli-ux/flush.js +28 -0
  20. package/lib/cli-ux/index.d.ts +10 -30
  21. package/lib/cli-ux/index.js +32 -75
  22. package/lib/cli-ux/list.js +3 -3
  23. package/lib/cli-ux/prompt.js +32 -22
  24. package/lib/cli-ux/stream.js +1 -0
  25. package/lib/cli-ux/styled/index.d.ts +5 -6
  26. package/lib/cli-ux/styled/index.js +11 -11
  27. package/lib/cli-ux/styled/json.js +8 -5
  28. package/lib/cli-ux/styled/object.js +7 -9
  29. package/lib/cli-ux/styled/table.d.ts +4 -4
  30. package/lib/cli-ux/styled/table.js +61 -64
  31. package/lib/cli-ux/styled/tree.js +1 -3
  32. package/lib/cli-ux/wait.js +3 -5
  33. package/lib/command.d.ts +15 -19
  34. package/lib/command.js +117 -96
  35. package/lib/config/config.d.ts +16 -23
  36. package/lib/config/config.js +180 -334
  37. package/lib/config/index.d.ts +1 -1
  38. package/lib/config/index.js +1 -2
  39. package/lib/config/plugin-loader.d.ts +30 -0
  40. package/lib/config/plugin-loader.js +145 -0
  41. package/lib/config/plugin.d.ts +6 -11
  42. package/lib/config/plugin.js +112 -78
  43. package/lib/config/ts-node.d.ts +2 -1
  44. package/lib/config/ts-node.js +64 -51
  45. package/lib/config/util.d.ts +1 -11
  46. package/lib/config/util.js +6 -59
  47. package/lib/errors/config.js +1 -1
  48. package/lib/errors/errors/cli.d.ts +1 -1
  49. package/lib/errors/errors/cli.js +18 -14
  50. package/lib/errors/errors/exit.d.ts +0 -3
  51. package/lib/errors/errors/exit.js +1 -1
  52. package/lib/errors/errors/module-load.d.ts +0 -3
  53. package/lib/errors/errors/module-load.js +1 -1
  54. package/lib/errors/errors/pretty-print.js +11 -9
  55. package/lib/errors/handle.d.ts +12 -2
  56. package/lib/errors/handle.js +28 -18
  57. package/lib/errors/index.d.ts +2 -2
  58. package/lib/errors/index.js +20 -19
  59. package/lib/errors/logger.js +9 -8
  60. package/lib/execute.d.ts +49 -0
  61. package/lib/execute.js +63 -0
  62. package/lib/flags.d.ts +102 -31
  63. package/lib/flags.js +81 -46
  64. package/lib/help/command.d.ts +2 -0
  65. package/lib/help/command.js +68 -53
  66. package/lib/help/docopts.js +9 -13
  67. package/lib/help/formatter.d.ts +1 -1
  68. package/lib/help/formatter.js +35 -24
  69. package/lib/help/index.d.ts +7 -3
  70. package/lib/help/index.js +77 -55
  71. package/lib/help/root.js +7 -9
  72. package/lib/help/util.d.ts +1 -7
  73. package/lib/help/util.js +8 -28
  74. package/lib/index.d.ts +19 -18
  75. package/lib/index.js +36 -48
  76. package/lib/interfaces/config.d.ts +30 -30
  77. package/lib/interfaces/errors.d.ts +1 -1
  78. package/lib/interfaces/hooks.d.ts +3 -3
  79. package/lib/interfaces/index.d.ts +14 -14
  80. package/lib/interfaces/parser.d.ts +188 -116
  81. package/lib/interfaces/pjson.d.ts +2 -1
  82. package/lib/interfaces/plugin.d.ts +10 -1
  83. package/lib/main.d.ts +0 -48
  84. package/lib/main.js +11 -66
  85. package/lib/module-loader.d.ts +68 -79
  86. package/lib/module-loader.js +183 -150
  87. package/lib/parser/errors.d.ts +3 -3
  88. package/lib/parser/errors.js +17 -10
  89. package/lib/parser/help.js +5 -5
  90. package/lib/parser/parse.d.ts +3 -0
  91. package/lib/parser/parse.js +114 -115
  92. package/lib/parser/validate.js +45 -25
  93. package/lib/performance.d.ts +5 -1
  94. package/lib/performance.js +40 -19
  95. package/lib/util/aggregate-flags.d.ts +2 -0
  96. package/lib/util/aggregate-flags.js +13 -0
  97. package/lib/util/cache-command.d.ts +3 -0
  98. package/lib/util/cache-command.js +109 -0
  99. package/lib/util/cache-default-value.d.ts +2 -0
  100. package/lib/util/cache-default-value.js +28 -0
  101. package/lib/util/ensure-arg-object.d.ts +12 -0
  102. package/lib/util/ensure-arg-object.js +14 -0
  103. package/lib/util/fs.d.ts +7 -0
  104. package/lib/util/fs.js +54 -0
  105. package/lib/util/os.d.ts +19 -0
  106. package/lib/util/os.js +28 -0
  107. package/lib/{util.d.ts → util/util.d.ts} +6 -15
  108. package/lib/util/util.js +98 -0
  109. package/package.json +32 -34
  110. package/lib/cli-ux/action/pride-spinner.d.ts +0 -4
  111. package/lib/cli-ux/action/pride-spinner.js +0 -30
  112. package/lib/util.js +0 -126
@@ -1,33 +1,34 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.memoizedWarn = exports.warn = exports.error = exports.exit = exports.config = exports.Logger = exports.CLIError = exports.ModuleLoadError = exports.ExitError = exports.handle = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const cli_1 = require("./errors/cli");
6
+ const pretty_print_1 = tslib_1.__importStar(require("./errors/pretty-print"));
7
+ const exit_1 = require("./errors/exit");
8
+ const config_1 = require("./config");
4
9
  var handle_1 = require("./handle");
5
10
  Object.defineProperty(exports, "handle", { enumerable: true, get: function () { return handle_1.handle; } });
6
- var exit_1 = require("./errors/exit");
7
- Object.defineProperty(exports, "ExitError", { enumerable: true, get: function () { return exit_1.ExitError; } });
11
+ var exit_2 = require("./errors/exit");
12
+ Object.defineProperty(exports, "ExitError", { enumerable: true, get: function () { return exit_2.ExitError; } });
8
13
  var module_load_1 = require("./errors/module-load");
9
14
  Object.defineProperty(exports, "ModuleLoadError", { enumerable: true, get: function () { return module_load_1.ModuleLoadError; } });
10
- var cli_1 = require("./errors/cli");
11
- Object.defineProperty(exports, "CLIError", { enumerable: true, get: function () { return cli_1.CLIError; } });
15
+ var cli_2 = require("./errors/cli");
16
+ Object.defineProperty(exports, "CLIError", { enumerable: true, get: function () { return cli_2.CLIError; } });
12
17
  var logger_1 = require("./logger");
13
18
  Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
14
- var config_1 = require("./config");
15
- Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_1.config; } });
16
- const config_2 = require("./config");
17
- const cli_2 = require("./errors/cli");
18
- const exit_2 = require("./errors/exit");
19
- const pretty_print_1 = require("./errors/pretty-print");
19
+ var config_2 = require("./config");
20
+ Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_2.config; } });
20
21
  function exit(code = 0) {
21
- throw new exit_2.ExitError(code);
22
+ throw new exit_1.ExitError(code);
22
23
  }
23
24
  exports.exit = exit;
24
25
  function error(input, options = {}) {
25
26
  let err;
26
27
  if (typeof input === 'string') {
27
- err = new cli_2.CLIError(input, options);
28
+ err = new cli_1.CLIError(input, options);
28
29
  }
29
30
  else if (input instanceof Error) {
30
- err = (0, cli_2.addOclifExitCode)(input, options);
31
+ err = (0, cli_1.addOclifExitCode)(input, options);
31
32
  }
32
33
  else {
33
34
  throw new TypeError('first argument must be a string or instance of Error');
@@ -36,8 +37,8 @@ function error(input, options = {}) {
36
37
  if (options.exit === false) {
37
38
  const message = (0, pretty_print_1.default)(err);
38
39
  console.error(message);
39
- if (config_2.config.errorLogger)
40
- config_2.config.errorLogger.log(err?.stack ?? '');
40
+ if (config_1.config.errorLogger)
41
+ config_1.config.errorLogger.log(err?.stack ?? '');
41
42
  }
42
43
  else
43
44
  throw err;
@@ -46,18 +47,18 @@ exports.error = error;
46
47
  function warn(input) {
47
48
  let err;
48
49
  if (typeof input === 'string') {
49
- err = new cli_2.CLIError.Warn(input);
50
+ err = new cli_1.CLIError.Warn(input);
50
51
  }
51
52
  else if (input instanceof Error) {
52
- err = (0, cli_2.addOclifExitCode)(input);
53
+ err = (0, cli_1.addOclifExitCode)(input);
53
54
  }
54
55
  else {
55
56
  throw new TypeError('first argument must be a string or instance of Error');
56
57
  }
57
58
  const message = (0, pretty_print_1.default)(err);
58
59
  console.error(message);
59
- if (config_2.config.errorLogger)
60
- config_2.config.errorLogger.log(err?.stack ?? '');
60
+ if (config_1.config.errorLogger)
61
+ config_1.config.errorLogger.log(err?.stack ?? '');
61
62
  }
62
63
  exports.warn = warn;
63
64
  const WARNINGS = new Set();
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Logger = void 0;
4
- const fs = require("fs-extra");
5
- const path = require("path");
4
+ const promises_1 = require("node:fs/promises");
5
+ const node_path_1 = require("node:path");
6
6
  const stripAnsi = require("strip-ansi");
7
7
  const timestamp = () => new Date().toISOString();
8
8
  let timer;
9
- const wait = (ms) => new Promise(resolve => {
9
+ const wait = (ms) => new Promise((resolve) => {
10
10
  if (timer)
11
11
  timer.unref();
12
12
  timer = setTimeout(() => resolve(null), ms);
@@ -17,14 +17,15 @@ function chomp(s) {
17
17
  return s;
18
18
  }
19
19
  class Logger {
20
+ file;
21
+ flushing = Promise.resolve();
22
+ buffer = [];
20
23
  constructor(file) {
21
24
  this.file = file;
22
- this.flushing = Promise.resolve();
23
- this.buffer = [];
24
25
  }
25
26
  log(msg) {
26
27
  msg = stripAnsi(chomp(msg));
27
- const lines = msg.split('\n').map(l => `${timestamp()} ${l}`.trimEnd());
28
+ const lines = msg.split('\n').map((l) => `${timestamp()} ${l}`.trimEnd());
28
29
  this.buffer.push(...lines);
29
30
  this.flush(50).catch(console.error);
30
31
  }
@@ -35,8 +36,8 @@ class Logger {
35
36
  return;
36
37
  const mylines = this.buffer;
37
38
  this.buffer = [];
38
- await fs.mkdirp(path.dirname(this.file));
39
- await fs.appendFile(this.file, mylines.join('\n') + '\n');
39
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(this.file), { recursive: true });
40
+ await (0, promises_1.appendFile)(this.file, mylines.join('\n') + '\n');
40
41
  });
41
42
  await this.flushing;
42
43
  }
@@ -0,0 +1,49 @@
1
+ import { LoadOptions } from './interfaces';
2
+ /**
3
+ * Load and run oclif CLI
4
+ *
5
+ * @param options - options to load the CLI
6
+ * @returns Promise<void>
7
+ *
8
+ * @example For ESM dev.js
9
+ * ```
10
+ * #!/usr/bin/env ts-node
11
+ * void (async () => {
12
+ * const oclif = await import('@oclif/core')
13
+ * await oclif.execute({development: true, dir: import.meta.url})
14
+ * })()
15
+ * ```
16
+ *
17
+ * @example For ESM run.js
18
+ * ```
19
+ * #!/usr/bin/env node
20
+ * void (async () => {
21
+ * const oclif = await import('@oclif/core')
22
+ * await oclif.execute({dir: import.meta.url})
23
+ * })()
24
+ * ```
25
+ *
26
+ * @example For CJS dev.js
27
+ * ```
28
+ * #!/usr/bin/env ts-node
29
+ * void (async () => {
30
+ * const oclif = await import('@oclif/core')
31
+ * await oclif.execute({development: true, dir: __dirname})
32
+ * })()
33
+ * ```
34
+ *
35
+ * @example For CJS run.js
36
+ * ```
37
+ * #!/usr/bin/env node
38
+ * void (async () => {
39
+ * const oclif = await import('@oclif/core')
40
+ * await oclif.execute({dir: __dirname})
41
+ * })()
42
+ * ```
43
+ */
44
+ export declare function execute(options: {
45
+ dir: string;
46
+ args?: string[];
47
+ loadOptions?: LoadOptions;
48
+ development?: boolean;
49
+ }): Promise<unknown>;
package/lib/execute.js ADDED
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.execute = void 0;
4
+ const flush_1 = require("./cli-ux/flush");
5
+ const handle_1 = require("./errors/handle");
6
+ const main_1 = require("./main");
7
+ const settings_1 = require("./settings");
8
+ /**
9
+ * Load and run oclif CLI
10
+ *
11
+ * @param options - options to load the CLI
12
+ * @returns Promise<void>
13
+ *
14
+ * @example For ESM dev.js
15
+ * ```
16
+ * #!/usr/bin/env ts-node
17
+ * void (async () => {
18
+ * const oclif = await import('@oclif/core')
19
+ * await oclif.execute({development: true, dir: import.meta.url})
20
+ * })()
21
+ * ```
22
+ *
23
+ * @example For ESM run.js
24
+ * ```
25
+ * #!/usr/bin/env node
26
+ * void (async () => {
27
+ * const oclif = await import('@oclif/core')
28
+ * await oclif.execute({dir: import.meta.url})
29
+ * })()
30
+ * ```
31
+ *
32
+ * @example For CJS dev.js
33
+ * ```
34
+ * #!/usr/bin/env ts-node
35
+ * void (async () => {
36
+ * const oclif = await import('@oclif/core')
37
+ * await oclif.execute({development: true, dir: __dirname})
38
+ * })()
39
+ * ```
40
+ *
41
+ * @example For CJS run.js
42
+ * ```
43
+ * #!/usr/bin/env node
44
+ * void (async () => {
45
+ * const oclif = await import('@oclif/core')
46
+ * await oclif.execute({dir: __dirname})
47
+ * })()
48
+ * ```
49
+ */
50
+ async function execute(options) {
51
+ if (options.development) {
52
+ // In dev mode -> use ts-node and dev plugins
53
+ process.env.NODE_ENV = 'development';
54
+ settings_1.settings.debug = true;
55
+ }
56
+ return (0, main_1.run)(options.args ?? process.argv.slice(2), options.loadOptions ?? options.dir)
57
+ .then(async (result) => {
58
+ (0, flush_1.flush)();
59
+ return result;
60
+ })
61
+ .catch(async (error) => (0, handle_1.handle)(error));
62
+ }
63
+ exports.execute = execute;
package/lib/flags.d.ts CHANGED
@@ -1,49 +1,120 @@
1
1
  /// <reference types="node" />
2
- import { URL } from 'url';
3
- import { BooleanFlag } from './interfaces';
4
- import { FlagDefinition, OptionFlagDefaults, FlagParser } from './interfaces/parser';
5
- /**
6
- * Create a custom flag.
7
- *
8
- * @example
9
- * type Id = string
10
- * type IdOpts = { startsWith: string; length: number };
11
- *
12
- * export const myFlag = custom<Id, IdOpts>({
13
- * parse: async (input, opts) => {
14
- * if (input.startsWith(opts.startsWith) && input.length === opts.length) {
15
- * return input
16
- * }
17
- *
18
- * throw new Error('Invalid id')
19
- * },
20
- * })
21
- */
22
- export declare function custom<T, P = Record<string, unknown>>(defaults: {
23
- parse: FlagParser<T, string, P>;
24
- multiple: true;
25
- } & Partial<OptionFlagDefaults<T, P, true>>): FlagDefinition<T, P>;
26
- export declare function custom<T, P = Record<string, unknown>>(defaults: {
27
- parse: FlagParser<T, string, P>;
28
- } & Partial<OptionFlagDefaults<T, P>>): FlagDefinition<T, P>;
29
- export declare function custom<T = string, P = Record<string, unknown>>(defaults: Partial<OptionFlagDefaults<T, P>>): FlagDefinition<T, P>;
2
+ import { BooleanFlag, CustomOptions, FlagDefinition, OptionFlag } from './interfaces';
3
+ import { URL } from 'node:url';
4
+ type NotArray<T> = T extends Array<any> ? never : T;
5
+ export declare function custom<T = string, P extends CustomOptions = CustomOptions>(defaults: Partial<OptionFlag<T[], P>> & {
6
+ multiple: true;
7
+ } & ({
8
+ required: true;
9
+ } | {
10
+ default: OptionFlag<T[], P>['default'];
11
+ })): FlagDefinition<T, P, {
12
+ multiple: true;
13
+ requiredOrDefaulted: true;
14
+ }>;
15
+ export declare function custom<T = string, P extends CustomOptions = CustomOptions>(defaults: Partial<OptionFlag<NotArray<T>, P>> & {
16
+ multiple?: false | undefined;
17
+ } & ({
18
+ required: true;
19
+ } | {
20
+ default: OptionFlag<NotArray<T>, P>['default'];
21
+ })): FlagDefinition<T, P, {
22
+ multiple: false;
23
+ requiredOrDefaulted: true;
24
+ }>;
25
+ export declare function custom<T = string, P extends CustomOptions = CustomOptions>(defaults: Partial<OptionFlag<NotArray<T>, P>> & {
26
+ default?: OptionFlag<NotArray<T>, P>['default'] | undefined;
27
+ multiple?: false | undefined;
28
+ required?: false | undefined;
29
+ }): FlagDefinition<T, P, {
30
+ multiple: false;
31
+ requiredOrDefaulted: false;
32
+ }>;
33
+ export declare function custom<T = string, P extends CustomOptions = CustomOptions>(defaults: Partial<OptionFlag<T[], P>> & {
34
+ multiple: true;
35
+ default?: OptionFlag<T[], P>['default'] | undefined;
36
+ required?: false | undefined;
37
+ }): FlagDefinition<T, P, {
38
+ multiple: true;
39
+ requiredOrDefaulted: false;
40
+ }>;
41
+ export declare function custom<T = string, P extends CustomOptions = CustomOptions>(): FlagDefinition<T, P, {
42
+ multiple: false;
43
+ requiredOrDefaulted: false;
44
+ }>;
30
45
  export declare function boolean<T = boolean>(options?: Partial<BooleanFlag<T>>): BooleanFlag<T>;
31
46
  export declare const integer: FlagDefinition<number, {
32
47
  min?: number | undefined;
33
48
  max?: number | undefined;
49
+ }, {
50
+ multiple: false;
51
+ requiredOrDefaulted: false;
34
52
  }>;
35
53
  export declare const directory: FlagDefinition<string, {
36
54
  exists?: boolean | undefined;
55
+ }, {
56
+ multiple: false;
57
+ requiredOrDefaulted: false;
37
58
  }>;
38
59
  export declare const file: FlagDefinition<string, {
39
60
  exists?: boolean | undefined;
61
+ }, {
62
+ multiple: false;
63
+ requiredOrDefaulted: false;
40
64
  }>;
41
65
  /**
42
66
  * Initializes a string as a URL. Throws an error
43
67
  * if the string is not a valid URL.
44
68
  */
45
- export declare const url: FlagDefinition<URL, Record<string, unknown>>;
46
- declare const stringFlag: FlagDefinition<string, Record<string, unknown>>;
47
- export { stringFlag as string };
69
+ export declare const url: FlagDefinition<URL, CustomOptions, {
70
+ multiple: false;
71
+ requiredOrDefaulted: false;
72
+ }>;
73
+ export declare const string: FlagDefinition<string, CustomOptions, {
74
+ multiple: false;
75
+ requiredOrDefaulted: false;
76
+ }>;
48
77
  export declare const version: (opts?: Partial<BooleanFlag<boolean>>) => BooleanFlag<void>;
49
78
  export declare const help: (opts?: Partial<BooleanFlag<boolean>>) => BooleanFlag<void>;
79
+ type ElementType<T extends ReadonlyArray<unknown>> = T[number];
80
+ export declare function option<T extends readonly string[], P extends CustomOptions>(defaults: Partial<OptionFlag<ElementType<T>[], P>> & {
81
+ options: T;
82
+ multiple: true;
83
+ } & ({
84
+ required: true;
85
+ } | {
86
+ default: OptionFlag<ElementType<T>[], P>['default'] | undefined;
87
+ })): FlagDefinition<(typeof defaults.options)[number], P, {
88
+ multiple: true;
89
+ requiredOrDefaulted: true;
90
+ }>;
91
+ export declare function option<T extends readonly string[], P extends CustomOptions>(defaults: Partial<OptionFlag<ElementType<T>, P>> & {
92
+ options: T;
93
+ multiple?: false | undefined;
94
+ } & ({
95
+ required: true;
96
+ } | {
97
+ default: OptionFlag<ElementType<T>, P>['default'];
98
+ })): FlagDefinition<(typeof defaults.options)[number], P, {
99
+ multiple: false;
100
+ requiredOrDefaulted: true;
101
+ }>;
102
+ export declare function option<T extends readonly string[], P extends CustomOptions>(defaults: Partial<OptionFlag<ElementType<T>, P>> & {
103
+ options: T;
104
+ default?: OptionFlag<ElementType<T>, P>['default'] | undefined;
105
+ multiple?: false | undefined;
106
+ required?: false | undefined;
107
+ }): FlagDefinition<(typeof defaults.options)[number], P, {
108
+ multiple: false;
109
+ requiredOrDefaulted: false;
110
+ }>;
111
+ export declare function option<T extends readonly string[], P extends CustomOptions>(defaults: Partial<OptionFlag<ElementType<T>[], P>> & {
112
+ options: T;
113
+ multiple: true;
114
+ default?: OptionFlag<ElementType<T>[], P>['default'] | undefined;
115
+ required?: false | undefined;
116
+ }): FlagDefinition<(typeof defaults.options)[number], P, {
117
+ multiple: true;
118
+ requiredOrDefaulted: false;
119
+ }>;
120
+ export {};
package/lib/flags.js CHANGED
@@ -1,20 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.help = exports.version = exports.string = exports.url = exports.file = exports.directory = exports.integer = exports.boolean = exports.custom = void 0;
4
- const url_1 = require("url");
3
+ exports.option = exports.help = exports.version = exports.string = exports.url = exports.file = exports.directory = exports.integer = exports.boolean = exports.custom = void 0;
4
+ const fs_1 = require("./util/fs");
5
+ const errors_1 = require("./errors");
6
+ const node_url_1 = require("node:url");
5
7
  const help_1 = require("./help");
6
- const util_1 = require("./util");
8
+ /**
9
+ * Create a custom flag.
10
+ *
11
+ * @example
12
+ * type Id = string
13
+ * type IdOpts = { startsWith: string; length: number };
14
+ *
15
+ * export const myFlag = custom<Id, IdOpts>({
16
+ * parse: async (input, opts) => {
17
+ * if (input.startsWith(opts.startsWith) && input.length === opts.length) {
18
+ * return input
19
+ * }
20
+ *
21
+ * throw new Error('Invalid id')
22
+ * },
23
+ * })
24
+ */
7
25
  function custom(defaults) {
8
- return (options = {}) => {
9
- return {
10
- parse: async (input, _ctx, _opts) => input,
11
- ...defaults,
12
- ...options,
13
- input: [],
14
- multiple: Boolean(options.multiple === undefined ? defaults.multiple : options.multiple),
15
- type: 'option',
16
- };
17
- };
26
+ return (options = {}) => ({
27
+ parse: async (input, _ctx, _opts) => input,
28
+ ...defaults,
29
+ ...options,
30
+ input: [],
31
+ multiple: Boolean(options.multiple === undefined ? defaults?.multiple ?? false : options.multiple),
32
+ type: 'option',
33
+ });
18
34
  }
19
35
  exports.custom = custom;
20
36
  function boolean(options = {}) {
@@ -27,28 +43,28 @@ function boolean(options = {}) {
27
43
  }
28
44
  exports.boolean = boolean;
29
45
  exports.integer = custom({
30
- parse: async (input, _, opts) => {
46
+ async parse(input, _, opts) {
31
47
  if (!/^-?\d+$/.test(input))
32
- throw new Error(`Expected an integer but received: ${input}`);
48
+ throw new errors_1.CLIError(`Expected an integer but received: ${input}`);
33
49
  const num = Number.parseInt(input, 10);
34
50
  if (opts.min !== undefined && num < opts.min)
35
- throw new Error(`Expected an integer greater than or equal to ${opts.min} but received: ${input}`);
51
+ throw new errors_1.CLIError(`Expected an integer greater than or equal to ${opts.min} but received: ${input}`);
36
52
  if (opts.max !== undefined && num > opts.max)
37
- throw new Error(`Expected an integer less than or equal to ${opts.max} but received: ${input}`);
53
+ throw new errors_1.CLIError(`Expected an integer less than or equal to ${opts.max} but received: ${input}`);
38
54
  return num;
39
55
  },
40
56
  });
41
57
  exports.directory = custom({
42
- parse: async (input, _, opts) => {
58
+ async parse(input, _, opts) {
43
59
  if (opts.exists)
44
- return (0, util_1.dirExists)(input);
60
+ return (0, fs_1.dirExists)(input);
45
61
  return input;
46
62
  },
47
63
  });
48
64
  exports.file = custom({
49
- parse: async (input, _, opts) => {
65
+ async parse(input, _, opts) {
50
66
  if (opts.exists)
51
- return (0, util_1.fileExists)(input);
67
+ return (0, fs_1.fileExists)(input);
52
68
  return input;
53
69
  },
54
70
  });
@@ -57,36 +73,55 @@ exports.file = custom({
57
73
  * if the string is not a valid URL.
58
74
  */
59
75
  exports.url = custom({
60
- parse: async (input) => {
76
+ async parse(input) {
61
77
  try {
62
- return new url_1.URL(input);
78
+ return new node_url_1.URL(input);
63
79
  }
64
80
  catch {
65
- throw new Error(`Expected a valid url but received: ${input}`);
81
+ throw new errors_1.CLIError(`Expected a valid url but received: ${input}`);
66
82
  }
67
83
  },
68
84
  });
69
- const stringFlag = custom({});
70
- exports.string = stringFlag;
71
- const version = (opts = {}) => {
72
- return boolean({
73
- description: 'Show CLI version.',
74
- ...opts,
75
- parse: async (_, ctx) => {
76
- ctx.log(ctx.config.userAgent);
77
- ctx.exit(0);
78
- },
79
- });
80
- };
85
+ exports.string = custom();
86
+ const version = (opts = {}) => boolean({
87
+ description: 'Show CLI version.',
88
+ ...opts,
89
+ async parse(_, ctx) {
90
+ ctx.log(ctx.config.userAgent);
91
+ ctx.exit(0);
92
+ },
93
+ });
81
94
  exports.version = version;
82
- const help = (opts = {}) => {
83
- return boolean({
84
- description: 'Show CLI help.',
85
- ...opts,
86
- parse: async (_, cmd) => {
87
- new help_1.Help(cmd.config).showHelp(cmd.id ? [cmd.id, ...cmd.argv] : cmd.argv);
88
- cmd.exit(0);
89
- },
90
- });
91
- };
95
+ const help = (opts = {}) => boolean({
96
+ description: 'Show CLI help.',
97
+ ...opts,
98
+ async parse(_, cmd) {
99
+ const Help = await (0, help_1.loadHelpClass)(cmd.config);
100
+ await new Help(cmd.config, cmd.config.pjson.helpOptions).showHelp(cmd.id ? [cmd.id, ...cmd.argv] : cmd.argv);
101
+ cmd.exit(0);
102
+ },
103
+ });
92
104
  exports.help = help;
105
+ /**
106
+ * Create a custom flag that infers the flag type from the provided options.
107
+ *
108
+ * @example
109
+ * export default class MyCommand extends Command {
110
+ * static flags = {
111
+ * name: Flags.option({
112
+ * options: ['foo', 'bar'] as const,
113
+ * })(),
114
+ * }
115
+ * }
116
+ */
117
+ function option(defaults) {
118
+ return (options = {}) => ({
119
+ parse: async (input, _ctx, _opts) => input,
120
+ ...defaults,
121
+ ...options,
122
+ input: [],
123
+ multiple: Boolean(options.multiple === undefined ? defaults.multiple : options.multiple),
124
+ type: 'option',
125
+ });
126
+ }
127
+ exports.option = option;
@@ -27,5 +27,7 @@ export declare class CommandHelp extends HelpFormatter {
27
27
  protected flagHelpLabel(flag: Command.Flag.Any, showOptions?: boolean): string;
28
28
  protected flags(flags: Array<Command.Flag.Any>): [string, string | undefined][] | undefined;
29
29
  protected flagsDescriptions(flags: Array<Command.Flag.Any>): string | undefined;
30
+ private formatIfCommand;
31
+ private isCommand;
30
32
  }
31
33
  export default CommandHelp;