@percy/cli 1.0.0-beta.71 → 1.0.0-beta.75

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
@@ -37,6 +37,7 @@ integrations, Percy API communication, DOM serialization, asset discovery, etc.
37
37
  - [`@percy/config`](./packages/config#readme) - loads Percy configuration files
38
38
  - [`@percy/logger`](./packages/logger#readme) - common logger used throughout the CLI
39
39
  - [`@percy/sdk-utils`](./packages/sdk-utils#readme) - shared helpers for JavaScript SDKs
40
+ - [`@percy/cli-command`](./packages/cli-command#readme) - Percy CLI command framework
40
41
 
41
42
  ## Issues
42
43
 
@@ -56,7 +57,7 @@ use the following scripts for various development tasks:
56
57
  - `yarn build:watch` - build and watch all packages in parallel
57
58
  - `yarn clean` - clean up build and coverage output
58
59
  - `yarn lint` - lint all packages
59
- - `yarn readme` - generate oclif readme usage
60
+ - `yarn readme` - generate cli commands readme usage
60
61
  - `yarn test` - run all tests, one package after another
61
62
  - `yarn test:coverage` - run all tests with coverage, one package after another
62
63
 
package/bin/run CHANGED
@@ -1,5 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- require('@percy/cli').run()
4
- .then(require('@oclif/command/flush'))
5
- .catch(require('@oclif/errors/handle'))
3
+ if (parseInt(process.version.split('.')[0].substring(1), 10) < 12) {
4
+ console.error(`Node ${process.version} is not supported. Percy only ` + (
5
+ 'supports the current LTS version of Node. Please upgrade to Node 12+'));
6
+ process.exit(1);
7
+ }
8
+
9
+ let { checkForUpdate, percy } = require('../dist/index.js');
10
+
11
+ (async function() {
12
+ await checkForUpdate();
13
+ await percy(process.argv.slice(2));
14
+ })();
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.importCommands = importCommands;
7
+
8
+ var _os = _interopRequireDefault(require("os"));
9
+
10
+ var _fs = _interopRequireDefault(require("fs"));
11
+
12
+ var _path = _interopRequireDefault(require("path"));
13
+
14
+ var _module = require("module");
15
+
16
+ var _logger = _interopRequireDefault(require("@percy/logger"));
17
+
18
+ var _cliCommand = require("@percy/cli-command");
19
+
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+
22
+ 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); }
23
+
24
+ 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; }
25
+
26
+ // Helper to simplify reducing async functions
27
+ async function reduceAsync(iter, reducer, accum = []) {
28
+ for (let i of iter) accum = await reducer(accum, i);
29
+
30
+ return accum;
31
+ } // Helper to read and reduce files within a directory
32
+
33
+
34
+ function reduceFiles(dir, reducer) {
35
+ return reduceAsync(_fs.default.readdirSync(dir, {
36
+ withFileTypes: true
37
+ }), reducer);
38
+ } // Returns the paths of potential percy packages found within node_modules
39
+
40
+
41
+ function findModulePackages(dir) {
42
+ try {
43
+ // not given node_modules or a directory that contains node_modules, look up
44
+ if (_path.default.basename(dir) !== 'node_modules') {
45
+ let modulesPath = _path.default.join(dir, 'node_modules');
46
+
47
+ let next = _fs.default.existsSync(modulesPath) ? modulesPath : _path.default.dirname(dir);
48
+ if (next === dir || next === _os.default.homedir()) return [];
49
+ return findModulePackages(next);
50
+ } // given node modules, look for percy packages
51
+
52
+
53
+ return reduceFiles(dir, async (roots, file) => {
54
+ let rootPath = _path.default.join(dir, file.name);
55
+
56
+ if (file.name === '@percy') {
57
+ return roots.concat(await reduceFiles(rootPath, (dirs, f) => // specifically protect against files to allow linked directories
58
+ f.isFile() ? dirs : dirs.concat(_path.default.join(rootPath, f.name)), []));
59
+ } else if (file.name.startsWith('percy-cli-')) {
60
+ return roots.concat(rootPath);
61
+ } else {
62
+ return roots;
63
+ }
64
+ }, []);
65
+ } catch (error) {
66
+ (0, _logger.default)('cli:plugins').debug(error);
67
+ return [];
68
+ }
69
+ } // Used by `findPnpPackages` to filter Percy CLI plugins
70
+
71
+
72
+ const PERCY_PKG_REG = /^(@percy\/|percy-cli-)/; // Returns the paths of potential percy packages found within yarn's pnp system
73
+
74
+ function findPnpPackages(dir) {
75
+ var _pkgInfo$packageDepen;
76
+
77
+ let pnpapi = _module.findPnpApi === null || _module.findPnpApi === void 0 ? void 0 : (0, _module.findPnpApi)(`${dir}/`);
78
+ let pkgLoc = pnpapi === null || pnpapi === void 0 ? void 0 : pnpapi.findPackageLocator(`${dir}/`);
79
+ let pkgInfo = pkgLoc && (pnpapi === null || pnpapi === void 0 ? void 0 : pnpapi.getPackageInformation(pkgLoc));
80
+ let pkgDeps = (_pkgInfo$packageDepen = pkgInfo === null || pkgInfo === void 0 ? void 0 : pkgInfo.packageDependencies.entries()) !== null && _pkgInfo$packageDepen !== void 0 ? _pkgInfo$packageDepen : [];
81
+ return Array.from(pkgDeps).reduce((roots, [name, ref]) => {
82
+ if (!ref || !PERCY_PKG_REG.test(name)) return roots;
83
+ let depLoc = pnpapi.getLocator(name, ref);
84
+ let depInfo = pnpapi.getPackageInformation(depLoc);
85
+ return roots.concat(depInfo.packageLocation);
86
+ }, []);
87
+ } // Helper to import and wrap legacy percy commands for reverse compatibility
88
+
89
+
90
+ function importLegacyCommands(commandsPath) {
91
+ return reduceFiles(commandsPath, async (cmds, file) => {
92
+ let {
93
+ name
94
+ } = _path.default.parse(file.name);
95
+
96
+ let filepath = _path.default.join(commandsPath, name);
97
+
98
+ if (file.isDirectory()) {
99
+ // recursively import nested commands and find the index command
100
+ let commands = await importLegacyCommands(filepath);
101
+ let index = commands.findIndex(cmd => cmd.name === 'index'); // modify or create an index command to hold nested commands
102
+
103
+ index = ~index ? commands.splice(index, 1)[0] : (0, _cliCommand.command)();
104
+ Object.defineProperty(index, 'name', {
105
+ value: name
106
+ });
107
+ index.definition.commands = commands;
108
+ return cmds.concat(index);
109
+ } else {
110
+ // find and wrap the command exported by the module
111
+ let exports = Object.values(await Promise.resolve(`${filepath}`).then(s => _interopRequireWildcard(require(s))));
112
+ let cmd = exports.find(e => {
113
+ var _e$prototype;
114
+
115
+ return typeof (e === null || e === void 0 ? void 0 : (_e$prototype = e.prototype) === null || _e$prototype === void 0 ? void 0 : _e$prototype.run) === 'function';
116
+ });
117
+ return cmd ? cmds.concat((0, _cliCommand.legacyCommand)(name, cmd)) : cmds;
118
+ }
119
+ });
120
+ } // Imports and returns compatibile CLI commands from various sources
121
+
122
+
123
+ async function importCommands() {
124
+ // start with a set to get built-in deduplication
125
+ let cmdPkgs = await reduceAsync(new Set([// find included dependencies
126
+ _path.default.join(__dirname, '..'), // find potential sibling packages
127
+ _path.default.join(__dirname, '..', '..'), // find any current project dependencies
128
+ process.cwd()]), async (roots, dir) => {
129
+ roots.push(...(await findModulePackages(dir)));
130
+ roots.push(...(await findPnpPackages(dir)));
131
+ return roots;
132
+ }); // reduce found packages to functions which import cli commands
133
+
134
+ let cmdImports = await reduceAsync(cmdPkgs, async (pkgs, pkgPath) => {
135
+ var _pkg$oclif, _pkg$PercyCli;
136
+
137
+ let pkg = require(_path.default.join(pkgPath, 'package.json')); // do not include self
138
+
139
+
140
+ if (pkg.name === '@percy/cli') return pkgs; // support legacy oclif percy commands
141
+
142
+ if (((_pkg$oclif = pkg.oclif) === null || _pkg$oclif === void 0 ? void 0 : _pkg$oclif.bin) === 'percy') {
143
+ pkgs.set(pkg.name, async () => {
144
+ var _pkg$oclif$hooks;
145
+
146
+ if ((_pkg$oclif$hooks = pkg.oclif.hooks) !== null && _pkg$oclif$hooks !== void 0 && _pkg$oclif$hooks.init) {
147
+ let initPath = _path.default.join(pkgPath, pkg.oclif.hooks.init);
148
+
149
+ let init = await Promise.resolve(`${initPath}`).then(s => _interopRequireWildcard(require(s)));
150
+ await init.default();
151
+ }
152
+
153
+ if (pkg.oclif.commands) {
154
+ let commandsPath = _path.default.join(pkgPath, pkg.oclif.commands);
155
+
156
+ return importLegacyCommands(commandsPath);
157
+ }
158
+
159
+ return [];
160
+ });
161
+ } // overwrite any found package of the same name
162
+
163
+
164
+ if ((_pkg$PercyCli = pkg['@percy/cli']) !== null && _pkg$PercyCli !== void 0 && _pkg$PercyCli.commands) {
165
+ pkgs.set(pkg.name, () => Promise.all(pkg['@percy/cli'].commands.map(async cmdPath => {
166
+ let module = await Promise.resolve(`${_path.default.join(pkgPath, cmdPath)}`).then(s => _interopRequireWildcard(require(s)));
167
+ return module.default;
168
+ })));
169
+ }
170
+
171
+ return pkgs;
172
+ }, new Map()); // actually import found commands
173
+
174
+ let cmds = await reduceAsync(cmdImports.values(), async (cmds, importCmds) => cmds.concat(await importCmds())); // sort standalone commands before command topics
175
+
176
+ return cmds.sort((a, b) => {
177
+ if (a.callback && !b.callback) return -1;
178
+ if (b.callback && !a.callback) return 1;
179
+ return a.name.localeCompare(b.name);
180
+ });
181
+ }
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "checkForUpdate", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _update.checkForUpdate;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "default", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _percy.default;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "percy", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _percy.percy;
22
+ }
23
+ });
24
+
25
+ var _percy = _interopRequireWildcard(require("./percy"));
26
+
27
+ var _update = require("./update");
28
+
29
+ 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); }
30
+
31
+ 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/percy.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.percy = exports.default = void 0;
7
+
8
+ var _cliCommand = _interopRequireDefault(require("@percy/cli-command"));
9
+
10
+ var _commands = require("./commands");
11
+
12
+ var _package = _interopRequireDefault(require("../package.json"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ const percy = (0, _cliCommand.default)('percy', {
17
+ version: `${_package.default.name} ${_package.default.version}`,
18
+ commands: () => (0, _commands.importCommands)(),
19
+ exitOnError: true
20
+ });
21
+ exports.percy = percy;
22
+ var _default = percy;
23
+ exports.default = _default;
package/dist/update.js ADDED
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.checkForUpdate = checkForUpdate;
7
+ exports.default = void 0;
8
+
9
+ var _fs = _interopRequireDefault(require("fs"));
10
+
11
+ var _path = _interopRequireDefault(require("path"));
12
+
13
+ var _logger = _interopRequireDefault(require("@percy/logger"));
14
+
15
+ var _util = require("@percy/logger/dist/util");
16
+
17
+ var _package = _interopRequireDefault(require("../package.json"));
18
+
19
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
+
21
+ 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); }
22
+
23
+ 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; }
24
+
25
+ // filepath where the cache will be read and written to
26
+ const CACHE_FILE = _path.default.join(__dirname, '..', '.releases'); // max age the cache should be used for (3 days)
27
+
28
+
29
+ const CACHE_MAX_AGE = 3 * 24 * 60 * 60 * 1000; // Safely read from CACHE_FILE and return an object containing `data` mirroring what was previously
30
+ // written using `writeToCache(data)`. An empty object is returned when older than CACHE_MAX_AGE,
31
+ // and an `error` will be present if one was encountered.
32
+
33
+ function readFromCache() {
34
+ let cached = {};
35
+
36
+ try {
37
+ if (_fs.default.existsSync(CACHE_FILE)) {
38
+ let {
39
+ createdAt,
40
+ data
41
+ } = JSON.parse(_fs.default.readFileSync(CACHE_FILE));
42
+ if (Date.now() - createdAt < CACHE_MAX_AGE) cached.data = data;
43
+ }
44
+ } catch (error) {
45
+ let log = (0, _logger.default)('cli:update:cache');
46
+ log.debug('Unable to read from cache');
47
+ log.debug(cached.error = error);
48
+ }
49
+
50
+ return cached;
51
+ } // Safely write data to CACHE_FILE with the current timestamp.
52
+
53
+
54
+ function writeToCache(data) {
55
+ try {
56
+ _fs.default.writeFileSync(CACHE_FILE, JSON.stringify({
57
+ createdAt: Date.now(),
58
+ data
59
+ }));
60
+ } catch (error) {
61
+ let log = (0, _logger.default)('cli:update:cache');
62
+ log.debug('Unable to write to cache');
63
+ log.debug(error);
64
+ }
65
+ } // Fetch and return release information for @percy/cli.
66
+
67
+
68
+ async function fetchReleases() {
69
+ let {
70
+ request
71
+ } = await Promise.resolve().then(() => _interopRequireWildcard(require('@percy/client/dist/request'))); // fetch releases from the github api without retries
72
+
73
+ let api = 'https://api.github.com/repos/percy/cli/releases';
74
+ let data = await request(api, {
75
+ headers: {
76
+ 'User-Agent': _package.default.name
77
+ },
78
+ retries: 0
79
+ }); // return relevant information
80
+
81
+ return data.map(r => ({
82
+ tag: r.tag_name,
83
+ prerelease: r.prerelease
84
+ }));
85
+ } // Check for updates by comparing latest releases with the current version. The result of the check
86
+ // is cached to speed up subsequent CLI usage.
87
+
88
+
89
+ async function checkForUpdate() {
90
+ let {
91
+ data: releases,
92
+ error: cacheError
93
+ } = readFromCache();
94
+ let log = (0, _logger.default)('cli:update');
95
+
96
+ try {
97
+ // request new release information if needed
98
+ if (!releases) {
99
+ releases = await fetchReleases();
100
+ if (!cacheError) writeToCache(releases, log);
101
+ } // check the current package version against released versions
102
+
103
+
104
+ let versions = releases.map(r => r.tag.substr(1));
105
+ let age = versions.indexOf(_package.default.version); // a new version is available
106
+
107
+ if (age !== 0) {
108
+ let range = `${_util.colors.red(_package.default.version)} -> ${_util.colors.green(versions[0])}`;
109
+ log.stderr.write('\n');
110
+ log.warn(`${age > 0 && age < 10 ? 'A new version of @percy/cli is available!' : 'Heads up! The current version of @percy/cli is more than 10 releases behind!'} ${range}`);
111
+ log.stderr.write('\n');
112
+ }
113
+ } catch (err) {
114
+ log.debug('Unable to check for updates');
115
+ log.debug(err);
116
+ }
117
+ }
118
+
119
+ var _default = checkForUpdate;
120
+ exports.default = _default;
package/package.json CHANGED
@@ -1,50 +1,41 @@
1
1
  {
2
2
  "name": "@percy/cli",
3
- "version": "1.0.0-beta.71",
3
+ "version": "1.0.0-beta.75",
4
4
  "license": "MIT",
5
- "main": "index.js",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/percy/cli",
8
+ "directory": "packages/cli"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "main": "dist/index.js",
6
14
  "bin": {
7
15
  "percy": "bin/run"
8
16
  },
9
17
  "files": [
10
18
  "bin",
11
- "index.js",
12
- "oclif.manifest.json"
19
+ "dist"
13
20
  ],
14
21
  "engines": {
15
22
  "node": ">=12"
16
23
  },
17
24
  "scripts": {
25
+ "build": "node ../../scripts/build",
18
26
  "lint": "eslint --ignore-path ../../.gitignore .",
19
27
  "test": "node ../../scripts/test",
20
28
  "test:coverage": "yarn test --coverage"
21
29
  },
22
- "publishConfig": {
23
- "access": "public"
24
- },
25
- "oclif": {
26
- "bin": "percy",
27
- "plugins": [
28
- "@percy/cli-config",
29
- "@percy/cli-exec",
30
- "@percy/cli-build",
31
- "@percy/cli-snapshot",
32
- "@percy/cli-upload",
33
- "@oclif/plugin-help"
34
- ]
35
- },
36
30
  "dependencies": {
37
- "@oclif/plugin-help": "^3.2.0",
38
- "@percy/cli-build": "1.0.0-beta.71",
39
- "@percy/cli-config": "1.0.0-beta.71",
40
- "@percy/cli-exec": "1.0.0-beta.71",
41
- "@percy/cli-snapshot": "1.0.0-beta.71",
42
- "@percy/cli-upload": "1.0.0-beta.71"
43
- },
44
- "repository": {
45
- "type": "git",
46
- "url": "https://github.com/percy/cli",
47
- "directory": "packages/cli"
31
+ "@percy/cli-build": "1.0.0-beta.75",
32
+ "@percy/cli-command": "1.0.0-beta.75",
33
+ "@percy/cli-config": "1.0.0-beta.75",
34
+ "@percy/cli-exec": "1.0.0-beta.75",
35
+ "@percy/cli-snapshot": "1.0.0-beta.75",
36
+ "@percy/cli-upload": "1.0.0-beta.75",
37
+ "@percy/client": "1.0.0-beta.75",
38
+ "@percy/logger": "1.0.0-beta.75"
48
39
  },
49
- "gitHead": "364d1df717fb19a26ccb024458df6e78a9c11f99"
40
+ "gitHead": "3b778a9c0b72dcbf113910227f1a073a2714042a"
50
41
  }
package/index.js DELETED
@@ -1,69 +0,0 @@
1
- /* istanbul ignore if: hard to test without actually using an unsupported version */
2
- if (parseInt(process.version.split('.')[0].substring(1), 10) < 12) {
3
- console.error(`Node ${process.version} is not supported. Percy only supports the current LTS of Node. Please upgrade to Node v12+`);
4
- process.exit(1);
5
- }
6
-
7
- const { promises: fs } = require('fs');
8
- const path = require('path');
9
-
10
- // find plugins in a directory, matching a pattern, ignoring registered plugins
11
- function findPlugins(dir, pattern, registered) {
12
- let segments = pattern.split('/');
13
- let regexp = new RegExp(`^${segments.pop().replace('*', '.*')}`);
14
- dir = path.join(dir, ...segments);
15
-
16
- return fs.readdir(dir).then(f => f.reduce((plugins, dirname) => {
17
- // exclude CLI's own directory and any directory not matching the pattern
18
- if (dirname === 'cli' || !regexp.test(dirname)) return plugins;
19
-
20
- try {
21
- let { name, oclif } = require(`${dir}/${dirname}/package.json`);
22
-
23
- // plugin's package.json have a percy oclif binary defined
24
- if (!registered.includes(name) && oclif && oclif.bin === 'percy') {
25
- return plugins.concat(name);
26
- }
27
- } catch {
28
- // ignore directories without a package.json
29
- }
30
-
31
- return plugins;
32
- }, []), () => []);
33
- }
34
-
35
- // automatically register/unregister plugins by altering the CLI's package.json within node_modules
36
- async function autoRegisterPlugins() {
37
- let nodeModules = path.resolve(__dirname, '../..');
38
- let pkgPath = path.resolve(__dirname, 'package.json');
39
- let pkg = require(pkgPath);
40
-
41
- // if not installed within node_modules, look within own node_modules
42
- /* istanbul ignore else: always true during tests */
43
- if (path.basename(nodeModules) !== 'node_modules') {
44
- nodeModules = path.resolve(__dirname, 'node_modules');
45
- }
46
-
47
- // ensure registered plugins can be resolved
48
- let registered = pkg.oclif.plugins.filter(plugin => {
49
- if (pkg.dependencies[plugin]) return true;
50
- try { return !!require.resolve(plugin); } catch {}
51
- return false;
52
- });
53
-
54
- // find unregistered plugins
55
- let unregistered = await Promise.all([
56
- findPlugins(nodeModules, '@percy/*', registered),
57
- findPlugins(nodeModules, 'percy-cli-*', registered)
58
- ]).then(p => Array.from(new Set(p.flat())));
59
-
60
- // if any unregistered or unresolved registered, modify plugin registry
61
- if (unregistered.length || registered.length !== pkg.oclif.plugins.length) {
62
- pkg.oclif.plugins = registered.concat(unregistered);
63
- await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
64
- }
65
- }
66
-
67
- // auto register plugins before running oclif
68
- module.exports.run = () => autoRegisterPlugins()
69
- .then(() => require('@oclif/command').run());