@percy/cli-command 1.0.0-beta.76 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,7 +14,7 @@ The `command` function accepts a name, definition, and callback and returns a ru
14
14
  accepts an array of command-line arguments.
15
15
 
16
16
  ``` js
17
- const { command } = require('@percy/cli-command');
17
+ import command from '@percy/cli-command';
18
18
 
19
19
  // example command runner
20
20
  const example = command('example', {
package/bin/readme CHANGED
@@ -1,23 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { formatHelp } = require('@percy/cli-command/dist/help');
6
-
7
- const CWD = process.cwd();
8
- const README = path.join(CWD, 'README.md');
9
-
10
- const HELP_USAGE = /^(.*)?(usage:.*)$/gis;
11
- const CMDS_TMPL = /(<!-- commands -->)(.*)(<!-- commandsstop -->)/is;
12
-
13
- async function generateReadmeCommands(pkg) {
14
- if (!pkg['@percy/cli']?.commands) return '';
3
+ const fs = await import('fs');
4
+ const path = await import('path');
5
+ const { formatHelp } = await import('../dist/help');
15
6
 
7
+ async function updateReadmeCommands(cwd = process.cwd()) {
8
+ let readmePath = path.join(cwd, 'README.md');
9
+ let pkgPath = path.join(cwd, 'package.json');
16
10
  let sections = [];
17
11
  let toc = [];
18
12
 
13
+ let pkg = JSON.parse(fs.readFileSync(pkgPath));
14
+ if (!pkg['@percy/cli']?.commands) return '';
15
+
19
16
  for (let cmdPath of pkg['@percy/cli'].commands) {
20
- let { default: command } = require(path.join(CWD, cmdPath));
17
+ let cmdURL = url.pathToFileURL(path.join(CWD, cmdPath));
18
+ let { default: command } = await import(cmdURL.href);
21
19
  command = { ...command, parent: { name: 'percy' } };
22
20
 
23
21
  for (let cmd of [command, ...(command.definition.commands || [])]) {
@@ -30,22 +28,15 @@ async function generateReadmeCommands(pkg) {
30
28
  toc.push(`* [${title}](#${slug})`);
31
29
 
32
30
  let help = await formatHelp(cmd);
33
- help = help.replace(HELP_USAGE, '$1```\n$2```');
31
+ help = help.replace(/^(.*)?(usage:.*)$/gis, '$1```\n$2```');
34
32
  sections.push(`### ${title}\n\n${help}\n`);
35
33
  }
36
34
  }
37
35
 
38
- return [
39
- toc.join('\n'),
40
- sections.join('\n')
41
- ].join('\n\n');
42
- }
43
-
44
- async function updatePackageReadme() {
45
- let pkg = require(path.join(CWD, 'package.json'));
46
- let content = fs.readFileSync(README, 'utf8')
47
- .replace(CMDS_TMPL, `$1\n${await generateReadmeCommands(pkg)}$3`)
48
- fs.writeFileSync(README, content);
36
+ fs.writeFileSync(readmePath, fs.readFileSync(readmePath, 'utf-8').replace(
37
+ /(<!-- commands -->)(.*)(<!-- commandsstop -->)/is,
38
+ `$1\n${[toc.join('\n'), sections.join('\n')].join('\n\n')}$3`
39
+ ));
49
40
  }
50
41
 
51
- updatePackageReadme();
42
+ updateReadmeCommands();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/cli-command",
3
- "version": "1.0.0-beta.76",
3
+ "version": "1.0.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -10,15 +10,21 @@
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
13
- "main": "dist/index.js",
14
- "bin": {
15
- "percy-cli-readme": "bin/readme"
16
- },
17
13
  "files": [
18
- "dist"
14
+ "./dist"
19
15
  ],
20
16
  "engines": {
21
- "node": ">=12"
17
+ "node": ">=14"
18
+ },
19
+ "bin": {
20
+ "percy-cli-readme": "./bin/readme"
21
+ },
22
+ "main": "./dist/index.js",
23
+ "type": "module",
24
+ "exports": {
25
+ ".": "./dist/index.js",
26
+ "./utils": "./dist/utils.js",
27
+ "./test/helpers": "./test/helpers.js"
22
28
  },
23
29
  "scripts": {
24
30
  "build": "node ../../scripts/build",
@@ -27,9 +33,9 @@
27
33
  "test:coverage": "yarn test --coverage"
28
34
  },
29
35
  "dependencies": {
30
- "@percy/config": "1.0.0-beta.76",
31
- "@percy/core": "1.0.0-beta.76",
32
- "@percy/logger": "1.0.0-beta.76"
36
+ "@percy/config": "1.0.0",
37
+ "@percy/core": "1.0.0",
38
+ "@percy/logger": "1.0.0"
33
39
  },
34
- "gitHead": "445af68d8e270e2a35fc74e26422ed5d3c91d2ae"
40
+ "gitHead": "6df509421a60144e4f9f5d59dc57a5675372a0b2"
35
41
  }
package/dist/command.js DELETED
@@ -1,240 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.command = command;
7
- exports.default = void 0;
8
-
9
- var _logger = _interopRequireDefault(require("@percy/logger"));
10
-
11
- var _config = _interopRequireDefault(require("@percy/config"));
12
-
13
- var _utils = require("@percy/config/dist/utils");
14
-
15
- var CoreConfig = _interopRequireWildcard(require("@percy/core/dist/config"));
16
-
17
- var builtInFlags = _interopRequireWildcard(require("./flags"));
18
-
19
- var _help = _interopRequireDefault(require("./help"));
20
-
21
- var _parse = _interopRequireDefault(require("./parse"));
22
-
23
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
-
25
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
26
-
27
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
28
-
29
- // Copies a command definition and adds built-in flags and config options.
30
- function withBuiltIns(definition) {
31
- var _def$flags, _def$config$schemas, _def$config$migration;
32
-
33
- let def = { ...definition
34
- };
35
- def.flags = [...((_def$flags = def.flags) !== null && _def$flags !== void 0 ? _def$flags : [])]; // ensure built-ins aren't already overridden
36
-
37
- let addDedupedFlag = flag => {
38
- if (!def.flags.find(f => f.name === flag.name)) {
39
- let short = def.flags.find(f => f.short === flag.short);
40
- def.flags.push(short ? (0, _utils.del)({ ...flag
41
- }, 'short') : flag);
42
- }
43
- }; // add percy specific built-in flags
44
-
45
-
46
- if (def.percy && def.percy !== true) {
47
- builtInFlags.PERCY.forEach(addDedupedFlag); // maybe include percy discovery flags
48
-
49
- if (def.percy.discoveryFlags !== false) {
50
- builtInFlags.DISCOVERY.forEach(addDedupedFlag);
51
- }
52
- } // always add global built-in flags
53
-
54
-
55
- builtInFlags.GLOBAL.forEach(addDedupedFlag); // copy any existing config before adding to it
56
-
57
- def.config = { ...def.config
58
- };
59
- def.config.schemas = [...((_def$config$schemas = def.config.schemas) !== null && _def$config$schemas !== void 0 ? _def$config$schemas : [])];
60
- def.config.migrations = [...((_def$config$migration = def.config.migrations) !== null && _def$config$migration !== void 0 ? _def$config$migration : [])]; // add percy specific built-in config options
61
-
62
- if (def.percy) {
63
- def.config.schemas.unshift(...CoreConfig.schemas);
64
- def.config.migrations.unshift(...CoreConfig.migrations);
65
- }
66
-
67
- return def;
68
- } // Calls the provided callback and handles callback cancelation when process signals are
69
- // triggered. If the provided callback returns a generator, it will automatically run and throw
70
- // an error when canceled to be able to gracefully handle it's own cancelation.
71
-
72
-
73
- async function handleProcessSignals(callback) {
74
- let signals = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP'];
75
- let signalError; // keep track of signal handlers for cleanup
76
-
77
- let signalHandlers = signals.map(signal => {
78
- let handler = () => {
79
- signalError = Object.assign(new Error(signal), {
80
- canceled: true,
81
- exitCode: 0,
82
- signal
83
- });
84
- };
85
-
86
- process.on(signal, handler);
87
- return [signal, handler];
88
- });
89
-
90
- try {
91
- // maybe async function
92
- let gen = await callback(); // run any returned generator
93
-
94
- if (typeof (gen === null || gen === void 0 ? void 0 : gen.next) === 'function' && (typeof gen[Symbol.iterator] === 'function' || typeof gen[Symbol.asyncIterator] === 'function')) {
95
- let result = await gen.next();
96
-
97
- while (!result.done) {
98
- result = signalError ? await gen.throw(signalError) : await gen.next(result.value);
99
- }
100
- }
101
- } finally {
102
- // always cleanup
103
- for (let [signal, handler] of signalHandlers) {
104
- process.off(signal, handler);
105
- }
106
- }
107
- } // Helper to throw an error with an exit code and optional reason message
108
-
109
-
110
- function exit(exitCode, reason = '') {
111
- let err = reason instanceof Error ? reason : new Error(reason);
112
- throw Object.assign(err, {
113
- exitCode
114
- });
115
- } // Runs the parsed command callback with a contextual argument consisting of specific parsed input
116
- // and other common command helpers and properties.
117
-
118
-
119
- async function runCommandWithContext(parsed) {
120
- let {
121
- command,
122
- flags,
123
- args,
124
- argv,
125
- log
126
- } = parsed; // include flags, args, argv, logger, exit helper, and env info
127
-
128
- let context = {
129
- flags,
130
- args,
131
- argv,
132
- log,
133
- exit
134
- };
135
- let env = context.env = process.env;
136
- let def = command.definition; // automatically include a preconfigured percy instance
137
-
138
- if (def.percy) {
139
- let {
140
- Percy
141
- } = await Promise.resolve().then(() => _interopRequireWildcard(require('@percy/core'))); // set defaults and prune preconfiguraton options
142
-
143
- let conf = (0, _utils.del)({
144
- server: false,
145
- ...def.percy
146
- }, 'discoveryFlags');
147
- Object.defineProperty(context, 'percy', {
148
- configurable: true,
149
-
150
- get() {
151
- // percy is disabled, do not return an instance
152
- if (env.PERCY_ENABLE === '0') return; // redefine the context property once configured
153
-
154
- Object.defineProperty(context, 'percy', {
155
- // map and merge percy arguments with config options
156
- value: new Percy([...parsed.operators.entries()].reduce((conf, [opt, value]) => opt.percyrc ? (0, _utils.set)(conf, opt.percyrc, value) : conf, conf))
157
- });
158
- return context.percy;
159
- }
160
-
161
- });
162
- } // wrap and bind the parsed command callback
163
-
164
-
165
- await handleProcessSignals(command.callback.bind(null, context));
166
- } // Returns a command runner function that when run will parse provided command-line options and run
167
- // the parsed command callback. The returned runner will automatically output version and help
168
- // information when requested, and handle any thrown errors exiting when appropriate.
169
-
170
-
171
- function command(name, definition, callback) {
172
- definition = withBuiltIns(definition); // auto register config schemas and migrations
173
-
174
- _config.default.addSchema(definition.config.schemas);
175
-
176
- _config.default.addMigration(definition.config.migrations);
177
-
178
- async function runner(argv = []) {
179
- // reset loglevel for testing
180
- _logger.default.loglevel('info');
181
-
182
- let log = (0, _logger.default)('cli');
183
-
184
- try {
185
- // parse input
186
- let parsed = await (0, _parse.default)(runner, argv);
187
-
188
- if (parsed.version) {
189
- // version requested
190
- log.stdout.write(parsed.command.definition.version + '\n');
191
- } else if (parsed.help || !parsed.command.callback) {
192
- // command help requested
193
- log.stdout.write((await (0, _help.default)(parsed.command)) + '\n');
194
- } else {
195
- // run command callback
196
- await runCommandWithContext(parsed);
197
- }
198
- } catch (err) {
199
- // auto log unhandled error messages
200
- if (err.message && !err.signal) {
201
- if (err.exitCode === 0) log.warn(err.message);else log.error(err);
202
- } // exit when appropriate
203
-
204
-
205
- if (err.exitCode !== 0) {
206
- var _err$exitCode;
207
-
208
- (_err$exitCode = err.exitCode) !== null && _err$exitCode !== void 0 ? _err$exitCode : err.exitCode = 1;
209
- err.message || (err.message = `EEXIT: ${err.exitCode}`);
210
-
211
- if (definition.exitOnError) {
212
- process.exit(err.exitCode);
213
- } // re-throw when not exiting
214
-
215
-
216
- throw err;
217
- }
218
- }
219
- } // define command meta information
220
-
221
-
222
- Object.defineProperties(runner, {
223
- name: {
224
- enumerable: true,
225
- value: name
226
- },
227
- definition: {
228
- enumerable: true,
229
- value: definition
230
- },
231
- callback: {
232
- enumerable: true,
233
- value: callback
234
- }
235
- });
236
- return runner;
237
- }
238
-
239
- var _default = command;
240
- exports.default = _default;
package/dist/flags.js DELETED
@@ -1,99 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.verbose = exports.silent = exports.quiet = exports.networkIdleTimeout = exports.dryRun = exports.disableCache = exports.debug = exports.config = exports.allowedHostnames = exports.PERCY = exports.GLOBAL = exports.DISCOVERY = void 0;
7
-
8
- var _logger = _interopRequireDefault(require("@percy/logger"));
9
-
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
12
- // Global CLI flags
13
- const verbose = {
14
- name: 'verbose',
15
- description: 'Log everything',
16
- exclusive: ['quiet', 'silent'],
17
- parse: () => !!_logger.default.loglevel('debug'),
18
- group: 'Global',
19
- short: 'v'
20
- };
21
- exports.verbose = verbose;
22
- const quiet = {
23
- name: 'quiet',
24
- description: 'Log errors only',
25
- exclusive: ['verbose', 'silent'],
26
- parse: () => !!_logger.default.loglevel('warn'),
27
- group: 'Global',
28
- short: 'q'
29
- };
30
- exports.quiet = quiet;
31
- const silent = {
32
- name: 'silent',
33
- description: 'Log nothing',
34
- exclusive: ['verbose', 'quiet'],
35
- parse: () => !!_logger.default.loglevel('silent'),
36
- group: 'Global',
37
- short: 's'
38
- }; // Common percy and asset discovery flags
39
-
40
- exports.silent = silent;
41
- const config = {
42
- name: 'config',
43
- description: 'Config file path',
44
- percyrc: 'config',
45
- type: 'file',
46
- group: 'Percy',
47
- short: 'c'
48
- };
49
- exports.config = config;
50
- const dryRun = {
51
- name: 'dry-run',
52
- description: 'Print snapshot names only',
53
- percyrc: 'dryRun',
54
- group: 'Percy',
55
- short: 'd'
56
- };
57
- exports.dryRun = dryRun;
58
- const allowedHostnames = {
59
- name: 'allowed-hostname',
60
- description: 'Allowed hostnames to capture in asset discovery',
61
- percyrc: 'discovery.allowedHostnames',
62
- type: 'hostname',
63
- multiple: true,
64
- group: 'Percy',
65
- short: 'h'
66
- };
67
- exports.allowedHostnames = allowedHostnames;
68
- const networkIdleTimeout = {
69
- name: 'network-idle-timeout',
70
- description: 'Asset discovery network idle timeout',
71
- percyrc: 'discovery.networkIdleTimeout',
72
- type: 'ms',
73
- parse: Number,
74
- group: 'Percy',
75
- short: 't'
76
- };
77
- exports.networkIdleTimeout = networkIdleTimeout;
78
- const disableCache = {
79
- name: 'disable-cache',
80
- description: 'Disable asset discovery caches',
81
- percyrc: 'discovery.disableCache',
82
- group: 'Percy'
83
- };
84
- exports.disableCache = disableCache;
85
- const debug = {
86
- name: 'debug',
87
- description: 'Debug asset discovery and do not upload snapshots',
88
- parse: () => !!_logger.default.loglevel('debug'),
89
- percyrc: 'skipUploads',
90
- group: 'Percy'
91
- }; // Group constants
92
-
93
- exports.debug = debug;
94
- const GLOBAL = [verbose, quiet, silent];
95
- exports.GLOBAL = GLOBAL;
96
- const PERCY = [config, dryRun];
97
- exports.PERCY = PERCY;
98
- const DISCOVERY = [allowedHostnames, networkIdleTimeout, disableCache, debug];
99
- exports.DISCOVERY = DISCOVERY;
package/dist/help.js DELETED
@@ -1,262 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- exports.flagUsage = flagUsage;
8
- exports.formatHelp = formatHelp;
9
-
10
- var _logger = _interopRequireDefault(require("@percy/logger"));
11
-
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
-
14
- // Helper to return an argument's description including it's default value.
15
- function argumentDescription(arg) {
16
- let desc = arg.description || '';
17
-
18
- if (arg.default != null) {
19
- desc += ` (default: ${JSON.stringify(arg.default)})`;
20
- }
21
-
22
- return desc.trim();
23
- } // Helper to return an array of visible argument usage-description pairs.
24
-
25
-
26
- async function visibleArguments(command) {
27
- var _command$definition$a;
28
-
29
- let args = (_command$definition$a = command.definition.args) !== null && _command$definition$a !== void 0 ? _command$definition$a : []; // not hidden and not deprecated
30
-
31
- let visible = args.reduce((visible, arg) => {
32
- if (arg.hidden || arg.deprecated) return visible;
33
- visible.push([arg.name, argumentDescription(arg)]);
34
- return visible;
35
- }, []); // do not return any arguments if none have descriptions
36
-
37
- if (!visible.some(([, desc]) => !!desc)) return [];
38
- return visible;
39
- } // Helper to return a command's usage string.
40
-
41
-
42
- function commandUsage(command) {
43
- let {
44
- name,
45
- definition
46
- } = command;
47
- let {
48
- usage,
49
- args,
50
- commands
51
- } = definition;
52
-
53
- if (!command.callback && commands !== null && commands !== void 0 && commands.length) {
54
- // if there are subcommands but no callback show subcommand usage
55
- usage || (usage = '<command>');
56
- } else {
57
- var _args, _args2;
58
-
59
- // show options followed by arguments
60
- args = (_args = args) === null || _args === void 0 ? void 0 : _args.filter(a => !a.hidden && !a.deprecated).map(a => a.required ? `<${a.name}>` : `[${a.name}]`);
61
- usage || (usage = `[options] ${((_args2 = args) === null || _args2 === void 0 ? void 0 : _args2.join(' ')) || ''}`);
62
- }
63
-
64
- return `${name} ${usage}`.trim();
65
- } // Helper to return an array of visible command usage-description pairs.
66
-
67
-
68
- async function visibleCommands(command, help) {
69
- var _command$definition$c;
70
-
71
- let commands = (_command$definition$c = command.definition.commands) !== null && _command$definition$c !== void 0 ? _command$definition$c : [];
72
- if (typeof commands === 'function') commands = await commands();
73
- let visible = [];
74
-
75
- for (let cmd of commands) {
76
- // create parent references and format subcommand names
77
- let name = command.parent ? `${command.name}:${cmd.name}` : cmd.name;
78
- cmd = { ...cmd,
79
- name,
80
- parent: command
81
- }; // commands without callbacks are not visible themselves
82
-
83
- if (cmd.callback) {
84
- let {
85
- description
86
- } = cmd.definition;
87
- visible.push([commandUsage(cmd), description]);
88
- } // include visible subcommands without their implicit help
89
-
90
-
91
- if (cmd.definition.commands) {
92
- visible.push(...(await visibleCommands(cmd, false)));
93
- }
94
- } // include implicit help if there are visible commands
95
-
96
-
97
- if (help !== false && visible.length) {
98
- visible.push(['help [command]', 'Display command help']);
99
- }
100
-
101
- return visible;
102
- } // Helper to return an flags's description including it's default value.
103
-
104
-
105
- function flagDescription(flag) {
106
- let desc = flag.description || ''; // a boolean that defaults to false will be displayed with a --no prefix
107
-
108
- if (flag.type && flag.type !== 'boolean' && flag.default != null) {
109
- desc += ` (default: ${JSON.stringify(flag.default)})`;
110
- }
111
-
112
- return desc.trim();
113
- } // Helper to return a flag's usage string.
114
-
115
-
116
- function flagUsage(flag) {
117
- let {
118
- short,
119
- usage,
120
- type
121
- } = flag;
122
- let term = flag.name ? `--${flag.name}` : '';
123
-
124
- if (type && type !== 'boolean') {
125
- // if there is a default it is not required
126
- usage || (usage = flag.default != null ? `[${type}]` : `<${type}>`);
127
- } else if (flag.default === true) {
128
- // negated booleans have a prefix
129
- term && (term = `--no-${flag.name}`);
130
- } // add short flag usage
131
-
132
-
133
- if (short) term = `-${short}${term ? `, ${term}` : ''}`;
134
- return `${term} ${usage || ''}`.trim();
135
- } // Helper to return an array of visible flag usage-description pairs. A third entry is also included
136
- // with the returned pair representing any group the flag should belong to.
137
-
138
-
139
- async function visibleFlags(command) {
140
- let flags = command.definition.flags; // not hidden and not deprecated
141
-
142
- let visible = flags.reduce((visible, flag) => {
143
- if (flag.hidden || flag.deprecated) return visible;
144
- visible.push([flagUsage(flag), flagDescription(flag), flag.group]);
145
- return visible;
146
- }, []); // maybe hide the implicit help long or short flag (or both)
147
-
148
- let showLongHelpFlag = !flags.some(f => f.name === 'help');
149
- let showShortHelpFlag = !flags.some(f => f.short === 'h');
150
-
151
- if (showLongHelpFlag || showShortHelpFlag) {
152
- let help = {
153
- name: 'help',
154
- short: 'h'
155
- };
156
- if (!showLongHelpFlag) delete help.name;
157
- if (!showShortHelpFlag) delete help.short;
158
- visible.push([flagUsage(help), 'Display command help', 'Global']);
159
- }
160
-
161
- if (command.definition.version) {
162
- // maybe hide the implicit version long or short flag (or both)
163
- let showLongVerFlag = !flags.some(f => f.name === 'version');
164
- let showShortVerFlag = !flags.some(f => f.short === 'V');
165
-
166
- if (showLongVerFlag || showShortVerFlag) {
167
- let ver = {
168
- name: 'version',
169
- short: 'V'
170
- };
171
- if (!showLongVerFlag) delete ver.name;
172
- if (!showShortVerFlag) delete ver.short;
173
- visible.push([flagUsage(ver), 'Display version', 'Global']);
174
- }
175
- }
176
-
177
- return visible;
178
- } // Helper to wrap a string at a length by inserting a newline between every segment.
179
-
180
-
181
- function wrapString(str, len) {
182
- let regex = new RegExp(`.{1,${len - 1}}(\\s|$)|\\S+?(\\s|$)`, 'g');
183
- return str.replace(regex, s => s.replace(/\s*\n?$/, str.endsWith(s) ? '' : '\n'));
184
- } // Helper to format an option usage-description pair into a single string where the description
185
- // wraps within the available space beside the usage string.
186
-
187
-
188
- function formatOptionHelp(option, usageWidth, maxWidth) {
189
- if (!option[1]) return option[0]; // calculate the available description width, at minimum 40
190
-
191
- let descWidth = Math.max(maxWidth - usageWidth, 40); // pad usage up to the description and indent the description
192
-
193
- return option[0].padEnd(usageWidth) + wrapString(option[1], descWidth).replace(/\n+/gm, `$&${' '.repeat(usageWidth)}`);
194
- } // Returns a formatted string displaying help output for the specified command. The help output
195
- // total width is determined by the logger's stdout TTY columns. Help output includes the command
196
- // description, usage, arguments, subcommand usage and descriptions, flag and flag group usage and
197
- // descriptions, and any command examples.
198
-
199
-
200
- async function formatHelp(command) {
201
- var _examples, _examples2;
202
-
203
- let {
204
- name,
205
- parent: top,
206
- definition
207
- } = command;
208
- let {
209
- description,
210
- examples
211
- } = definition;
212
- let output = []; // collect visible items first to determine max usage width
213
-
214
- let args = await visibleArguments(command);
215
- let commands = await visibleCommands(command);
216
- let flags = await visibleFlags(command); // maximum help output total width
217
-
218
- let maxWidth = _logger.default.stdout.columns || 100; // calculate the longest usage width
219
-
220
- let usageWidth = Math.max(args.reduce((max, [usage]) => Math.max(max, usage.length), 0), commands.reduce((max, [usage]) => Math.max(max, usage.length), 0), flags.reduce((max, [usage]) => Math.max(max, usage.length), 0)); // format lists of options and add appropriate indentation
221
-
222
- let formatList = items => items.map(item => Array.isArray(item) ? // indent items and separate columns by 2 spaces each
223
- formatOptionHelp(item, usageWidth + 2, maxWidth - 2) : item).join('\n').replace(/^(?!$)/gm, ' '.repeat(2)); // format the command name to include the topmost command name
224
-
225
-
226
- while ((_top = top) !== null && _top !== void 0 && _top.parent) {
227
- var _top;
228
-
229
- top = top.parent;
230
- }
231
-
232
- if (top) name = `${top.name} ${name}`;
233
- command = { ...command,
234
- name
235
- }; // include command description and own usage
236
-
237
- if (description) output.push(wrapString(description, maxWidth), '');
238
- output.push('Usage:', formatList([`$ ${commandUsage(command)}`]), ''); // include command arguments
239
-
240
- if (args.length) output.push('Arguments:', formatList(args), ''); // include command subcommands
241
-
242
- let commandGroupName = command.parent ? 'Subcommands:' : 'Commands:';
243
- if (commands.length) output.push(commandGroupName, formatList(commands), ''); // separate flags into groups
244
-
245
- let groups = flags.reduce((all, option) => {
246
- let group = option[2] ? `${option[2]} options` : 'Options';
247
- return all.set(group, [...(all.get(group) || []), option]);
248
- }, new Map([['Options', []]])); // include each group of command flags
249
-
250
- for (let [group, flags] of groups.entries()) {
251
- if (flags.length) output.push(`${group}:`, formatList(flags), '');
252
- } // include command examples and replace '$0' with the command name
253
-
254
-
255
- examples = (_examples = examples) === null || _examples === void 0 ? void 0 : _examples.map(ex => ex.replace('$0', `$ ${name}`));
256
- if ((_examples2 = examples) !== null && _examples2 !== void 0 && _examples2.length) output.push('Examples:', formatList(examples), ''); // join each line of output
257
-
258
- return output.join('\n');
259
- }
260
-
261
- var _default = formatHelp;
262
- exports.default = _default;
package/dist/index.js DELETED
@@ -1,37 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "command", {
7
- enumerable: true,
8
- get: function () {
9
- return _command.command;
10
- }
11
- });
12
- Object.defineProperty(exports, "default", {
13
- enumerable: true,
14
- get: function () {
15
- return _command.default;
16
- }
17
- });
18
- Object.defineProperty(exports, "flags", {
19
- enumerable: true,
20
- get: function () {
21
- return _legacy.legacyFlags;
22
- }
23
- });
24
- Object.defineProperty(exports, "legacyCommand", {
25
- enumerable: true,
26
- get: function () {
27
- return _legacy.legacyCommand;
28
- }
29
- });
30
-
31
- var _command = _interopRequireWildcard(require("./command"));
32
-
33
- var _legacy = require("./legacy");
34
-
35
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
36
-
37
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
package/dist/legacy.js DELETED
@@ -1,176 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- exports.legacyCommand = legacyCommand;
8
- exports.legacyFlags = void 0;
9
-
10
- var _command = require("./command");
11
-
12
- var _utils = require("@percy/config/dist/utils");
13
-
14
- // Legacy flags for older commands that inadvertently import a newer @percy/cli-command
15
- const legacyFlags = {
16
- config: {},
17
- logging: {},
18
- discovery: {
19
- __percy__: {}
20
- },
21
- string: def => ({
22
- type: 'string',
23
- ...def
24
- }),
25
- boolean: def => ({
26
- type: 'boolean',
27
- ...def
28
- }),
29
- integer: def => ({
30
- type: 'integer',
31
- ...def
32
- })
33
- }; // Maps a legacy arg that might have alternate properties
34
-
35
- exports.legacyFlags = legacyFlags;
36
-
37
- function legacyArg(legacy) {
38
- let {
39
- name,
40
- ...def
41
- } = legacy; // do not camelcase legacy attribute names
42
-
43
- def.attribute = name; // add name back to mapped options
44
-
45
- return {
46
- name,
47
- ...def
48
- };
49
- } // Maps a legacy flag that might have alternate properties
50
-
51
-
52
- function legacyFlag(name, legacy) {
53
- let {
54
- char: short,
55
- deprecated,
56
- ...def
57
- } = legacy; // generic legacy type looks odd in help output
58
-
59
- if (def.type === 'option') def.type = 'value'; // do not camelcase legacy attribute names
60
-
61
- def.attribute = name; // transform legacy deprecated syntax
62
-
63
- if (deprecated) {
64
- let {
65
- until,
66
- map,
67
- alt
68
- } = deprecated !== true ? deprecated : {};
69
- def.deprecated = [until, map ? `--${map}` : alt];
70
- } // add name and mapped short option
71
-
72
-
73
- return {
74
- name,
75
- short,
76
- ...def
77
- };
78
- } // Maps a legacy class-based command to the new functional syntax
79
-
80
-
81
- function legacyCommand(name, constructor) {
82
- var _constructor$args, _constructor$flags, _constructor$flags$__, _constructor$flags2;
83
-
84
- let runner = (0, _command.command)(name, {
85
- description: constructor.description,
86
- examples: constructor.examples,
87
- // map legacy args and flags
88
- args: (_constructor$args = constructor.args) === null || _constructor$args === void 0 ? void 0 : _constructor$args.map(legacyArg),
89
- flags: Object.entries((_constructor$flags = constructor.flags) !== null && _constructor$flags !== void 0 ? _constructor$flags : []).map(([name, def]) => legacyFlag(name, def)).filter(({
90
- name
91
- }) => name !== '__percy__'),
92
- percy: (_constructor$flags$__ = (_constructor$flags2 = constructor.flags) === null || _constructor$flags2 === void 0 ? void 0 : _constructor$flags2.__percy__) !== null && _constructor$flags$__ !== void 0 ? _constructor$flags$__ : true,
93
- loose: constructor.strict === false,
94
- legacy: true
95
- }, async function* (ctx) {
96
- let instance = new constructor();
97
- let error; // not an instance of the constructor, create one ourself
98
-
99
- if (!(instance instanceof constructor)) {
100
- instance = Object.create(constructor.prototype);
101
- } // alias legacy global flags attribute names when necessary
102
-
103
-
104
- if (ctx.flags.dryRun) ctx.flags['dry-run'] = ctx.flags.dryRun; // legacy percyrc value
105
-
106
- let percyrc = overrides => (0, _utils.merge)([ctx.percy.config, overrides, {
107
- skipUploads: ctx.flags.debug,
108
- dryRun: ctx.flags['dry-run'],
109
- config: false
110
- }], (path, prev, next) => // do not merge arrays
111
- Array.isArray(next) && [path, next]); // augment legacy instance properties
112
-
113
-
114
- Object.defineProperties(instance, {
115
- isPercyEnabled: {
116
- value: () => !!ctx.percy
117
- },
118
- error: {
119
- value: msg => ctx.exit(1, msg)
120
- },
121
- parse: {
122
- value: () => ctx
123
- },
124
- percyrc: {
125
- value: percyrc
126
- },
127
- flags: {
128
- value: ctx.flags
129
- },
130
- args: {
131
- value: ctx.args
132
- },
133
- exit: {
134
- value: ctx.exit
135
- },
136
- log: {
137
- value: ctx.log
138
- }
139
- }); // legacy signal handling
140
-
141
- let signals = ['SIGHUP', 'SIGINT', 'SIGTERM'];
142
-
143
- let cleanup = () => {
144
- var _instance$finally, _instance;
145
-
146
- return (_instance$finally = (_instance = instance).finally) === null || _instance$finally === void 0 ? void 0 : _instance$finally.call(_instance, new Error('SIGTERM'));
147
- };
148
-
149
- for (let e of signals) process.on(e, cleanup); // run and handle legacy command
150
-
151
-
152
- try {
153
- yield instance.run();
154
- } catch (err) {
155
- throw error = err;
156
- } finally {
157
- var _instance$finally2, _instance2;
158
-
159
- await ((_instance$finally2 = (_instance2 = instance).finally) === null || _instance$finally2 === void 0 ? void 0 : _instance$finally2.call(_instance2, error));
160
-
161
- for (let e of signals) process.off(e, cleanup);
162
- }
163
- }); // throw legacy errors for test compatibility
164
-
165
- return Object.defineProperties(args => runner(args).catch(e => {
166
- throw new Error(`EEXIT: ${e.exitCode}`);
167
- }), Object.getOwnPropertyDescriptors(runner));
168
- } // Support the legacy static run method
169
-
170
-
171
- _command.command.run = function run(args) {
172
- return legacyCommand('legacy', this)(args);
173
- };
174
-
175
- var _default = legacyCommand;
176
- exports.default = _default;
package/dist/parse.js DELETED
@@ -1,426 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = exports.ParseError = void 0;
7
- exports.parse = parse;
8
-
9
- var _logger = _interopRequireDefault(require("@percy/logger"));
10
-
11
- var _normalize = require("@percy/config/dist/normalize");
12
-
13
- var _help = require("./help");
14
-
15
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
-
17
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
18
-
19
- // Make it possible to identify parse errors.
20
- class ParseError extends Error {
21
- constructor(...args) {
22
- super(...args);
23
-
24
- _defineProperty(this, "name", this.constructor.name);
25
- }
26
-
27
- } // Helper that makes it possible to throw parse errors without throw or new keywords.
28
-
29
-
30
- exports.ParseError = ParseError;
31
-
32
- function parseError(msg) {
33
- throw new ParseError(msg);
34
- } // Helper to identify a potential command-line option as a flag.
35
-
36
-
37
- function isFlag(option) {
38
- // not a flag if it doesn't start with a dash
39
- if (!option.startsWith('-')) return false; // safe to say it's a flag without a space
40
-
41
- if (!option.includes(' ')) return true; // containing a space with no operator is not a proper flag
42
-
43
- if (!option.includes('=')) return false; // as long as the operator precedes the space, it is a flag
44
-
45
- return option.indexOf('=') < option.indexOf(' ');
46
- } // Parses input to identify a command. Consumes input and adds to parsed output as needed, returning
47
- // true if any defined command was found. A command is only identified via leading unparsed input
48
- // options. If a command is found, parsed output is updated accordingly and the current input option
49
- // is removed from further processing. An implicit help command is also supported.
50
-
51
-
52
- async function maybeParseCommand(input, parsed) {
53
- var _input$0$split, _input$;
54
-
55
- // a flag, no defined commands, or already parsed other options
56
- if (isFlag(input[0]) || !parsed.command.definition.commands || parsed.operators.size || parsed.argv.length) {
57
- return;
58
- } // implicit help
59
-
60
-
61
- if (input[0] === 'help') {
62
- parsed.help = true;
63
- input.shift();
64
- } // nested commands can be a single argument with command names separated by colons (:)
65
-
66
-
67
- let names = (_input$0$split = (_input$ = input[0]) === null || _input$ === void 0 ? void 0 : _input$.split(':')) !== null && _input$0$split !== void 0 ? _input$0$split : [];
68
- let command;
69
-
70
- for (let name of names) {
71
- var _parent$definition$co;
72
-
73
- let parent = command || parsed.command; // find any nested command by name
74
-
75
- command = (_parent$definition$co = parent.definition.commands) === null || _parent$definition$co === void 0 ? void 0 : _parent$definition$co.find(cmd => cmd.name === name);
76
- if (!command) break; // maintain nested names and parent relationships
77
-
78
- name = parent.parent ? `${parent.name}:${command.name}` : command.name;
79
- command = await normalizeCommand(command, {
80
- name,
81
- parent
82
- });
83
- }
84
-
85
- if (command) {
86
- // update parsed properties and discard current input
87
- parsed.log = (0, _logger.default)(`cli:${command.name}`);
88
- parsed.command = command;
89
- input.shift();
90
- } // help was requested, drain remaining input
91
-
92
-
93
- if (parsed.help) {
94
- input.splice(0, input.length);
95
- }
96
-
97
- return parsed.help || !!command;
98
- } // Parses input to identify a flag option. Consumes input and adds to parsed output as needed,
99
- // returning true if any defined flag was found. If a found flag is missing a required argument, the
100
- // next input option will be consumed as that argument. Boolean flags support negation if their
101
- // default value is true, integer flags are automaticaly parsed, and flags that can be provided
102
- // multiple times will be concatenated together. Implicit help and version flags are also supported.
103
-
104
-
105
- async function maybeParseFlag(input, parsed) {
106
- var _value;
107
-
108
- if (!isFlag(input[0])) return; // end of options and arguments, consume remaining input
109
-
110
- if (input[0] === '--') {
111
- let [, ...argv] = input.splice(0, input.length);
112
- parsed.argv.push(...argv);
113
- return true;
114
- } // a short flag was provided
115
-
116
-
117
- let short = input[0][1] !== '-' && input[0][1]; // get any value set with `=` and remove any `=` from short values
118
-
119
- let [name, value] = short ? ['', input[0].substr(2) || null] : input[0].split('=');
120
- value = short && (_value = value) !== null && _value !== void 0 && _value.startsWith('=') ? value.substr(1) : value; // the flag was negated
121
-
122
- let negated = name.startsWith('--no-');
123
- name = name.replace(/^--(no-)?/, ''); // search for the provided short or long flag
124
-
125
- let flag = parsed.command.definition.flags.find(f => {
126
- return short ? f.short === short : f.name === name;
127
- });
128
-
129
- if (flag) {
130
- // discard current input
131
- input.shift();
132
-
133
- if (!flag.type || flag.type === 'boolean') {
134
- // short boolean flags can be provided with other short flags
135
- if (short && value) input.unshift(`-${value}`); // a value was provided to a boolean flag
136
-
137
- if (!short && value) {
138
- parseError(`Unexpected option argument for '${(0, _help.flagUsage)(flag)}'`);
139
- } // a boolean value is based on if it was negated
140
-
141
-
142
- value = !negated;
143
- } else if (value == null) {
144
- // expected a value for a non-boolean flag
145
- if (!input.length || isFlag(input[0])) {
146
- parseError(`Missing option argument for '${(0, _help.flagUsage)(flag)}'`);
147
- } // the value is actually the next input option
148
-
149
-
150
- value = input.shift();
151
- } // parse the value according to flag properties
152
-
153
-
154
- if (flag.type === 'integer') value = parseInt(value, 10);
155
- if (flag.parse) value = await flag.parse(value);
156
-
157
- if (flag.multiple) {
158
- var _parsed$operators$get;
159
-
160
- value = ((_parsed$operators$get = parsed.operators.get(flag)) !== null && _parsed$operators$get !== void 0 ? _parsed$operators$get : []).concat(value);
161
- } // add this flag to the set of parsed operators
162
-
163
-
164
- parsed.operators.set(flag, value);
165
- return true;
166
- } // implicit version and help support
167
-
168
-
169
- if (parsed.command.definition.version && (name === 'version' || short === 'V')) {
170
- parsed.version = true;
171
- } else if (name === 'help' || short === 'h') {
172
- parsed.help = true;
173
- } // help or version was requested, drain remaining input
174
-
175
-
176
- if (parsed.help || parsed.version) {
177
- input.splice(0, input.length);
178
- return true;
179
- }
180
- } // Parses input to identify an argument option. Consumes input and adds to parsed output as needed,
181
- // returning true if any defined argument was found. Arguments are matched according to their
182
- // respective index and command-line position.
183
-
184
-
185
- async function maybeParseArg(input, parsed) {
186
- var _parsed$__args_index_, _parsed$command$defin;
187
-
188
- if (isFlag(input[0])) return; // the argument index needs to be tracked since flag options can precede argument options
189
-
190
- let index = (_parsed$__args_index_ = parsed.__args_index__) !== null && _parsed$__args_index_ !== void 0 ? _parsed$__args_index_ : parsed.__args_index__ = 0; // there are arguments left to parse
191
-
192
- if (index < ((_parsed$command$defin = parsed.command.definition.args) === null || _parsed$command$defin === void 0 ? void 0 : _parsed$command$defin.length)) {
193
- parsed.__args_index__ += 1;
194
- let value = input.shift();
195
- let arg = parsed.command.definition.args[index];
196
- if (arg.parse) value = await arg.parse(value); // add this arg to the set of parsed operators
197
-
198
- parsed.operators.set(arg, value);
199
- return true;
200
- }
201
- } // Parses input to identify unknown options. Consumes input and adds to parsed output as needed,
202
- // returning true when unknown options are found. By default, unknown options result in an error
203
- // unless the command is defined to accept loose options. If `loose` is a string, it will be logged
204
- // as a warning when unknown options are found. When the first unknown option is found, all
205
- // remaining options are also considered unknown.
206
-
207
-
208
- async function maybeParseUnknown(input, parsed) {
209
- let {
210
- loose
211
- } = parsed.command.definition;
212
-
213
- if (!loose) {
214
- // throw a more descriptive error message
215
- let reason = isFlag(input[0]) ? 'Unknown option' : 'Unexpected argument';
216
- parseError(`${reason} '${input[0]}'`);
217
- } else if (typeof loose === 'string') {
218
- // warn when loose is a string
219
- parsed.log.warn(loose);
220
- } // consume all remaining unknown input options
221
-
222
-
223
- let unknown = input.splice(0, input.length);
224
- parsed.argv.push(...unknown);
225
- return true;
226
- } // Parses an option's value defined by an environment variable. Adds to parsed output as needed,
227
- // returning true when the option's value was parsed from the environment. Boolean environment
228
- // variables will be interpreted as true unless "false" or "0", and integer environment variables
229
- // will be parsed automatically.
230
-
231
-
232
- async function maybeParseEnv(option, parsed) {
233
- // no env option, already provided, or no defined env var
234
- if (!option.env || parsed.operators.has(option) || !(option.env in process.env)) {
235
- return;
236
- } // get the value from the process env
237
-
238
-
239
- let value = process.env[option.env];
240
- let flag = parsed.command.definition.flags.includes(option);
241
-
242
- if (flag && (!option.type || option.type === 'boolean')) {
243
- // parse booleans as not "false" or not "0"
244
- value = value !== 'false' && value !== '0';
245
- } else if (option.type === 'integer') {
246
- // parse integer option values
247
- value = parseInt(value, 10);
248
- } // custom parse and add this option to the set of parsed operators
249
-
250
-
251
- if (option.parse) value = await option.parse(value);
252
- parsed.operators.set(option, value);
253
- return true;
254
- } // Helper to find and return a matching flag by name.
255
-
256
-
257
- function findFlag(name, parsed, map) {
258
- if (name.startsWith('--')) name = name.substr(2);
259
- let {
260
- flags
261
- } = parsed.command.definition;
262
- let match = flags.find(f => f.name === name);
263
- return map ? map(match) : match;
264
- } // Throws an error if the provided flag is inclusive of any missing flags.
265
-
266
-
267
- function validateInclusiveFlag(flag, parsed) {
268
- if (!flag.inclusive) return;
269
- let invalid = flag.inclusive.reduce((invalid, name) => findFlag(name, parsed, flag => // invalid options are options that have _not_ been provided
270
- !parsed.operators.has(flag) ? invalid.concat(flag) : invalid), []);
271
-
272
- if (invalid.length) {
273
- // show full flag usage for invalid options
274
- invalid = [flag, ...invalid].map(f => (0, _help.flagUsage)(f)).join("', '");
275
- parseError(`Options must be used together: '${invalid}'`);
276
- }
277
- } // Throws an error if the provided flag is exclusive of other provided flags.
278
-
279
-
280
- function validateExclusiveFlag(flag, parsed) {
281
- if (!flag.exclusive) return;
282
- let invalid = flag.exclusive.reduce((invalid, name) => findFlag(name, parsed, flag => // invalid options are options that _have_ been provided
283
- parsed.operators.has(flag) ? invalid.concat(flag) : invalid), []);
284
-
285
- if (invalid.length) {
286
- // show full flag usage for invalid options
287
- invalid = [flag, ...invalid].map(f => (0, _help.flagUsage)(f)).join("', '");
288
- parseError(`Options cannot be used together: '${invalid}'`);
289
- }
290
- } // Returns the attribute name of an option, which may be contingent on it's parsed value. If an
291
- // option is deprecated and is recommended to be replaced with flag, the attribute name will be
292
- // mapped to the replacement flag's attribute name. If a deprecated option is found in the provided
293
- // operators, a deprecation warning will be logged with any recommendation message.
294
-
295
-
296
- function attributeName(option, parsed) {
297
- var _parsed$operators$get2;
298
-
299
- let {
300
- attribute,
301
- deprecated
302
- } = option;
303
- let value = (_parsed$operators$get2 = parsed.operators.get(option)) !== null && _parsed$operators$get2 !== void 0 ? _parsed$operators$get2 : option.default; // the option's attribute name might be contingent on it's value
304
-
305
- let name = typeof attribute === 'function' ? attribute(value) : attribute; // default the attribute name to the camelcase name or short character
306
-
307
- name || (name = option.name ? (0, _normalize.camelcase)(option.name) : option.short); // deprecated options can be mapped to other options
308
-
309
- if (deprecated) {
310
- var _recommend;
311
-
312
- let [until, recommend] = Array.isArray(deprecated) ? deprecated : [typeof deprecated === 'string' ? deprecated : '']; // recommended replacement flag
313
-
314
- if ((_recommend = recommend) !== null && _recommend !== void 0 && _recommend.startsWith('--')) {
315
- let opt = findFlag(recommend, parsed);
316
- recommend = opt ? `Use '${(0, _help.flagUsage)(opt)}' instead.` : '';
317
- name = opt ? attributeName(opt, parsed) : name;
318
- } // operator was provided, log deprecation warning
319
-
320
-
321
- if (parsed.operators.has(option)) {
322
- // show better usage message for flags
323
- let flag = parsed.command.definition.flags.includes(option);
324
- let usage = flag ? (0, _help.flagUsage)(option) : option.name;
325
- parsed.log.deprecated((`The '${usage}' ${flag ? 'option' : 'argument'} ` + `will be removed in ${until || 'a future release'}. ` + (recommend || '')).trim());
326
- }
327
- }
328
-
329
- return name;
330
- } // Normalizes a command runner into an object of command properties. Optionally derives nested
331
- // commands from any provided definition commands method.
332
-
333
-
334
- async function normalizeCommand(command, properties) {
335
- // shallow copy command definition
336
- let { ...definition
337
- } = command.definition; // evaluate commands if needed
338
-
339
- if (typeof definition.commands === 'function') {
340
- definition.commands = await definition.commands();
341
- } // return shallow copy with additional properties
342
-
343
-
344
- return { ...command,
345
- ...properties,
346
- definition
347
- };
348
- } // Parses and validates command-line arguments according to a command definition.
349
-
350
-
351
- async function parse(command, argv) {
352
- // initial input and output
353
- let input = argv.slice().filter(a => a != null);
354
- let parsed = {
355
- command: await normalizeCommand(command),
356
- operators: new Map(),
357
- log: (0, _logger.default)('cli'),
358
- flags: {},
359
- args: {},
360
- argv: []
361
- }; // while there is input left, parse it
362
-
363
- while (input.length) {
364
- // parse and mutate input and output, looping if an option is found
365
- if (await maybeParseCommand(input, parsed)) continue;
366
- if (await maybeParseFlag(input, parsed)) continue;
367
- if (await maybeParseArg(input, parsed)) continue;
368
- await maybeParseUnknown(input, parsed);
369
- } // help or version requested, skip remaining parse logic
370
-
371
-
372
- if (parsed.help || parsed.version) {
373
- return parsed;
374
- } // validate and map defined flags
375
-
376
-
377
- for (let flag of parsed.command.definition.flags) {
378
- // collect last-minute env info
379
- await maybeParseEnv(flag, parsed);
380
-
381
- if (parsed.operators.has(flag)) {
382
- // validate before setting the parsed attribute
383
- validateInclusiveFlag(flag, parsed);
384
- validateExclusiveFlag(flag, parsed);
385
- let value = parsed.operators.get(flag);
386
- if (flag.validate) await flag.validate(value, parsed);
387
- parsed.flags[attributeName(flag, parsed)] = value;
388
- } else if (flag.default != null) {
389
- // a default value needs to be set, but not parsed
390
- parsed.flags[attributeName(flag, parsed)] = flag.default;
391
- }
392
- } // validate and map defined args
393
-
394
-
395
- for (let arg of (_parsed$command$defin2 = parsed.command.definition.args) !== null && _parsed$command$defin2 !== void 0 ? _parsed$command$defin2 : []) {
396
- var _parsed$command$defin2;
397
-
398
- // collect last-minute env info
399
- await maybeParseEnv(arg, parsed);
400
-
401
- if (parsed.operators.has(arg)) {
402
- var _arg$deprecated, _arg$deprecated$;
403
-
404
- // validate before setting the parsed attribute
405
- let value = parsed.operators.get(arg);
406
- if (arg.validate) await arg.validate(value, parsed); // a deprecated arg might be mapped to a flag
407
-
408
- if ((_arg$deprecated = arg.deprecated) !== null && _arg$deprecated !== void 0 && (_arg$deprecated$ = _arg$deprecated[1]) !== null && _arg$deprecated$ !== void 0 && _arg$deprecated$.startsWith('--') && findFlag(arg.deprecated[1], parsed)) {
409
- parsed.flags[attributeName(arg, parsed)] = value;
410
- } else {
411
- parsed.args[attributeName(arg, parsed)] = value;
412
- }
413
- } else if (arg.required) {
414
- // a required argument was not provided
415
- parseError(`Missing required argument '${arg.name}'`);
416
- } else if (arg.default != null) {
417
- // a default value needs to be set, but not parsed
418
- parsed.args[attributeName(arg, parsed)] = arg.default;
419
- }
420
- }
421
-
422
- return parsed;
423
- }
424
-
425
- var _default = parse;
426
- exports.default = _default;