@automattic/vip 2.32.1 → 2.32.3

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 (48) hide show
  1. package/.prettierignore +0 -2
  2. package/CHANGELOG.md +26 -0
  3. package/CONTRIBUTING.md +41 -17
  4. package/assets/dev-env.lando.template.yml.ejs +10 -2
  5. package/dist/bin/vip-dev-env-exec.js +1 -7
  6. package/dist/bin/vip-dev-env-shell.js +0 -4
  7. package/dist/bin/vip-dev-env-start.js +1 -1
  8. package/dist/bin/vip-dev-env-sync-sql.js +8 -6
  9. package/dist/bin/vip-dev-env-update.js +1 -2
  10. package/dist/bin/vip-import-sql.js +2 -2
  11. package/dist/bin/vip-logout.js +23 -0
  12. package/dist/bin/vip-slowlogs.js +192 -0
  13. package/dist/bin/vip-validate-preflight.js +8 -10
  14. package/dist/bin/vip-whoami.js +1 -2
  15. package/dist/bin/vip.js +1 -5
  16. package/dist/commands/backup-db.js +29 -30
  17. package/dist/lib/api/app.js +2 -2
  18. package/dist/lib/api/cache-purge.js +2 -2
  19. package/dist/lib/api/http.js +3 -3
  20. package/dist/lib/app-logs/app-logs.js +2 -2
  21. package/dist/lib/app-slowlogs/app-slowlogs.js +63 -0
  22. package/dist/lib/app-slowlogs/types.js +1 -0
  23. package/dist/lib/cli/apiConfig.js +1 -1
  24. package/dist/lib/client-file-uploader.js +19 -4
  25. package/dist/lib/config/software.js +4 -4
  26. package/dist/lib/constants/dev-environment.js +7 -3
  27. package/dist/lib/dev-environment/dev-environment-cli.js +110 -117
  28. package/dist/lib/dev-environment/dev-environment-configuration-file.js +34 -36
  29. package/dist/lib/dev-environment/dev-environment-core.js +36 -19
  30. package/dist/lib/dev-environment/dev-environment-lando.js +80 -72
  31. package/dist/lib/dev-environment/docker-utils.js +8 -9
  32. package/dist/lib/envvar/api-get-all.js +2 -2
  33. package/dist/lib/envvar/api-list.js +3 -6
  34. package/dist/lib/envvar/input.js +1 -2
  35. package/dist/lib/site-import/status.js +5 -5
  36. package/dist/lib/token.js +3 -6
  37. package/dist/lib/types/graphql/rate-limit-exceeded-error.js +1 -0
  38. package/dist/lib/validations/is-multi-site-sql-dump.js +0 -1
  39. package/dist/lib/validations/is-multi-site.js +14 -12
  40. package/dist/lib/validations/is-multisite-domain-mapped.js +5 -10
  41. package/dist/lib/validations/line-by-line.js +9 -13
  42. package/dist/lib/validations/site-type.js +2 -7
  43. package/dist/lib/validations/sql.js +14 -19
  44. package/dist/lib/validations/utils.js +1 -1
  45. package/helpers/generate-docs.js +151 -0
  46. package/npm-shrinkwrap.json +920 -933
  47. package/package.json +15 -10
  48. package/tsconfig.json +16 -6
@@ -218,7 +218,7 @@ ${maybeExitPrompt}
218
218
  progressTracker.startPrinting(setSuffixAndPrint);
219
219
  const getResults = () => new Promise((resolve, reject) => {
220
220
  const checkStatus = async () => {
221
- var _importJob$progress$s, _importJob$progress, _importJob$progress$s2, _importJob$progress2;
221
+ var _importJob$progress, _importJob$progress2;
222
222
  let status;
223
223
  try {
224
224
  status = await getStatus(api, app.id, env.id);
@@ -242,7 +242,7 @@ ${maybeExitPrompt}
242
242
  if (!importJob) {
243
243
  var _importStatus$progres, _importStatus$progres2;
244
244
  importJob = {};
245
- const statusSteps = importStatus === null || importStatus === void 0 ? void 0 : (_importStatus$progres = importStatus.progress) === null || _importStatus$progres === void 0 ? void 0 : _importStatus$progres.steps;
245
+ const statusSteps = importStatus === null || importStatus === void 0 || (_importStatus$progres = importStatus.progress) === null || _importStatus$progres === void 0 ? void 0 : _importStatus$progres.steps;
246
246
 
247
247
  // if the progress meta isn't filled out yet, wait until it is.
248
248
  if (!statusSteps) {
@@ -280,8 +280,8 @@ ${maybeExitPrompt}
280
280
  } else if (!importJob) {
281
281
  return resolve('No import job found');
282
282
  }
283
- jobStatus = (_importJob$progress$s = (_importJob$progress = importJob.progress) === null || _importJob$progress === void 0 ? void 0 : _importJob$progress.status) !== null && _importJob$progress$s !== void 0 ? _importJob$progress$s : 'unknown';
284
- jobSteps = (_importJob$progress$s2 = (_importJob$progress2 = importJob.progress) === null || _importJob$progress2 === void 0 ? void 0 : _importJob$progress2.steps) !== null && _importJob$progress$s2 !== void 0 ? _importJob$progress$s2 : [];
283
+ jobStatus = ((_importJob$progress = importJob.progress) === null || _importJob$progress === void 0 ? void 0 : _importJob$progress.status) ?? 'unknown';
284
+ jobSteps = ((_importJob$progress2 = importJob.progress) === null || _importJob$progress2 === void 0 ? void 0 : _importJob$progress2.steps) ?? [];
285
285
  createdAt = importJob.createdAt;
286
286
  completedAt = importJob.completedAt;
287
287
  const {
@@ -361,7 +361,7 @@ ${maybeExitPrompt}
361
361
  overallStatus = results;
362
362
  } else {
363
363
  var _results$progress;
364
- overallStatus = (results === null || results === void 0 ? void 0 : (_results$progress = results.progress) === null || _results$progress === void 0 ? void 0 : _results$progress.status) || 'unknown';
364
+ overallStatus = (results === null || results === void 0 || (_results$progress = results.progress) === null || _results$progress === void 0 ? void 0 : _results$progress.status) || 'unknown';
365
365
  // This shouldn't be 'unknown'...what should we do here?
366
366
  }
367
367
 
package/dist/lib/token.js CHANGED
@@ -62,12 +62,10 @@ class Token {
62
62
  return now > this.exp;
63
63
  }
64
64
  get id() {
65
- var _this$_id;
66
- return (_this$_id = this._id) !== null && _this$_id !== void 0 ? _this$_id : NaN;
65
+ return this._id ?? NaN;
67
66
  }
68
67
  get raw() {
69
- var _this$_raw;
70
- return (_this$_raw = this._raw) !== null && _this$_raw !== void 0 ? _this$_raw : '';
68
+ return this._raw ?? '';
71
69
  }
72
70
  static async uuid() {
73
71
  const service = Token.getServiceName('-uuid');
@@ -87,9 +85,8 @@ class Token {
87
85
  return _keychain.default.setPassword(service, token);
88
86
  }
89
87
  static async get() {
90
- var _await$keychain$getPa;
91
88
  const service = Token.getServiceName();
92
- const token = (_await$keychain$getPa = await _keychain.default.getPassword(service)) !== null && _await$keychain$getPa !== void 0 ? _await$keychain$getPa : '';
89
+ const token = (await _keychain.default.getPassword(service)) ?? '';
93
90
  return new Token(token);
94
91
  }
95
92
  static purge() {
@@ -0,0 +1 @@
1
+ "use strict";
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.sqlDumpLineIsMultiSite = sqlDumpLineIsMultiSite;
7
- // @format
8
7
  const SQL_CREATE_TABLE_IS_MULTISITE_REGEX = /^CREATE TABLE `?(wp_\d+_[a-z0-9_]*|wp_blogs)/i;
9
8
  const SQL_CONTAINS_MULTISITE_WP_USERS_REGEX = /`spam` tinyint\(2\)|`deleted` tinyint\(2\)/i;
10
9
  function sqlDumpLineIsMultiSite(line) {
@@ -11,11 +11,6 @@ var exit = _interopRequireWildcard(require("../../lib/cli/exit"));
11
11
  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); }
12
12
  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; }
13
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
- /**
15
- *
16
- * @format
17
- */
18
-
19
14
  /**
20
15
  * External dependencies
21
16
  */
@@ -26,10 +21,16 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
26
21
 
27
22
  const isMultiSite = new WeakMap();
28
23
  async function isMultiSiteInSiteMeta(appId, envId) {
29
- var _res, _res$data, _res$data$app;
24
+ var _res$data$app;
25
+ const args = {
26
+ 0: appId,
27
+ 1: envId
28
+ };
29
+
30
30
  // if we've already been through this, avoid doing it again within the same process
31
- if (isMultiSite.has(arguments) && 'boolean' === typeof isMultiSite.get(arguments)) {
32
- return Boolean(isMultiSite.get(arguments));
31
+ const ret = isMultiSite.get(args);
32
+ if ('boolean' === typeof ret) {
33
+ return ret;
33
34
  }
34
35
  const api = await (0, _api.default)();
35
36
  let res;
@@ -63,18 +64,19 @@ async function isMultiSiteInSiteMeta(appId, envId) {
63
64
  error_type: 'GraphQL-MultiSite-Check-failed',
64
65
  gql_err: GraphQlError
65
66
  });
67
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
66
68
  exit.withError(`StartImport call failed: ${GraphQlError}`);
67
69
  }
68
- if (Array.isArray((_res = res) === null || _res === void 0 ? void 0 : (_res$data = _res.data) === null || _res$data === void 0 ? void 0 : (_res$data$app = _res$data.app) === null || _res$data$app === void 0 ? void 0 : _res$data$app.environments)) {
70
+ if (Array.isArray((_res$data$app = res.data.app) === null || _res$data$app === void 0 ? void 0 : _res$data$app.environments)) {
69
71
  const environments = res.data.app.environments;
70
72
  if (!environments.length) {
71
- isMultiSite.set(arguments, false);
73
+ isMultiSite.set(args, false);
72
74
  return false;
73
75
  }
74
76
  // we asked for one result with one appId and one envId, so...
75
77
  const thisEnv = environments[0];
76
- if (thisEnv.isMultiSite || thisEnv.isSubdirectoryMultisite) {
77
- isMultiSite.set(arguments, true);
78
+ if (thisEnv.isMultisite || thisEnv.isSubdirectoryMultisite) {
79
+ isMultiSite.set(args, true);
78
80
  return true;
79
81
  }
80
82
  }
@@ -13,11 +13,6 @@ var exit = _interopRequireWildcard(require("../../lib/cli/exit"));
13
13
  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); }
14
14
  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; }
15
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
- /**
17
- *
18
- * @format
19
- */
20
-
21
16
  /**
22
17
  * External dependencies
23
18
  */
@@ -52,11 +47,10 @@ const getPrimaryDomainFromSQL = statements => {
52
47
  exports.getPrimaryDomainFromSQL = getPrimaryDomainFromSQL;
53
48
  const maybeSearchReplacePrimaryDomain = function (domain, searchReplace) {
54
49
  if (searchReplace) {
55
- var _primaryDomainReplace;
56
50
  const pairs = Array.isArray(searchReplace) ? searchReplace : [searchReplace];
57
51
  const domainReplacements = pairs.map(pair => pair.split(','));
58
52
  const primaryDomainReplacement = domainReplacements.find(pair => pair[0] === domain);
59
- return (_primaryDomainReplace = primaryDomainReplacement === null || primaryDomainReplacement === void 0 ? void 0 : primaryDomainReplacement[1]) !== null && _primaryDomainReplace !== void 0 ? _primaryDomainReplace : domain;
53
+ return (primaryDomainReplacement === null || primaryDomainReplacement === void 0 ? void 0 : primaryDomainReplacement[1]) ?? domain;
60
54
  }
61
55
  return domain;
62
56
  };
@@ -84,7 +78,7 @@ const getPrimaryDomain = function (statements, searchReplace) {
84
78
  */
85
79
  exports.getPrimaryDomain = getPrimaryDomain;
86
80
  async function isMultisitePrimaryDomainMapped(appId, envId, primaryDomain) {
87
- var _res, _res$data, _res$data$app, _environments$, _environments$$domain, _environments$$domain2;
81
+ var _res$data$app, _environments$;
88
82
  const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
89
83
  const api = await (0, _api.default)();
90
84
  let res;
@@ -118,15 +112,16 @@ async function isMultisitePrimaryDomainMapped(appId, envId, primaryDomain) {
118
112
  error_type: 'GraphQL-MappedDomain-Check-failed',
119
113
  gql_err: GraphQlError
120
114
  });
115
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
121
116
  exit.withError(`StartImport call failed: ${GraphQlError}`);
122
117
  }
123
- if (!Array.isArray((_res = res) === null || _res === void 0 ? void 0 : (_res$data = _res.data) === null || _res$data === void 0 ? void 0 : (_res$data$app = _res$data.app) === null || _res$data$app === void 0 ? void 0 : _res$data$app.environments)) {
118
+ if (!Array.isArray((_res$data$app = res.data.app) === null || _res$data$app === void 0 ? void 0 : _res$data$app.environments)) {
124
119
  return false;
125
120
  }
126
121
  const environments = res.data.app.environments;
127
122
  if (!environments.length) {
128
123
  return false;
129
124
  }
130
- const mappedDomains = (_environments$ = environments[0]) === null || _environments$ === void 0 ? void 0 : (_environments$$domain = _environments$.domains) === null || _environments$$domain === void 0 ? void 0 : (_environments$$domain2 = _environments$$domain.nodes) === null || _environments$$domain2 === void 0 ? void 0 : _environments$$domain2.map(domain => domain.name);
125
+ const mappedDomains = ((_environments$ = environments[0]) === null || _environments$ === void 0 || (_environments$ = _environments$.domains) === null || _environments$ === void 0 || (_environments$ = _environments$.nodes) === null || _environments$ === void 0 ? void 0 : _environments$.map(domain => domain === null || domain === void 0 ? void 0 : domain.name)) ?? [];
131
126
  return mappedDomains.includes(primaryDomain);
132
127
  }
@@ -5,18 +5,14 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.fileLineValidations = fileLineValidations;
7
7
  exports.getReadInterface = getReadInterface;
8
- var _readline = _interopRequireDefault(require("readline"));
9
- var _fs = _interopRequireDefault(require("fs"));
8
+ var _nodeReadline = require("node:readline");
9
+ var _nodeFs = require("node:fs");
10
+ var _promises = require("node:fs/promises");
10
11
  var _debug = _interopRequireDefault(require("debug"));
11
12
  var exit = _interopRequireWildcard(require("../../lib/cli/exit"));
12
13
  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); }
13
14
  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; }
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
- /**
16
- *
17
- * @format
18
- */
19
-
20
16
  /**
21
17
  * External dependencies
22
18
  */
@@ -29,16 +25,15 @@ const debug = (0, _debug.default)('vip:validations:line-by-line');
29
25
  async function getReadInterface(filename) {
30
26
  let fd;
31
27
  try {
32
- fd = await _fs.default.promises.open(filename);
28
+ fd = await (0, _promises.open)(filename);
33
29
  } catch (err) {
34
30
  exit.withError('The file at the provided path is either missing or not readable. Please check the input and try again.');
35
31
  }
36
- return _readline.default.createInterface({
37
- input: _fs.default.createReadStream('', {
32
+ return (0, _nodeReadline.createInterface)({
33
+ input: (0, _nodeFs.createReadStream)('', {
38
34
  fd
39
35
  }),
40
- output: null,
41
- console: false
36
+ output: undefined
42
37
  });
43
38
  }
44
39
  async function fileLineValidations(appId, envId, fileName, validations, searchReplace) {
@@ -57,7 +52,7 @@ async function fileLineValidations(appId, envId, fileName, validations, searchRe
57
52
  // Block until the processing completes
58
53
  await new Promise(resolve => readInterface.on('close', resolve));
59
54
  readInterface.close();
60
- return Promise.all(validations.map(async validation => {
55
+ return Promise.all(validations.map(validation => {
61
56
  if (Object.prototype.hasOwnProperty.call(validation, 'postLineExecutionProcessing') && typeof validation.postLineExecutionProcessing === 'function') {
62
57
  return validation.postLineExecutionProcessing({
63
58
  fileName,
@@ -67,5 +62,6 @@ async function fileLineValidations(appId, envId, fileName, validations, searchRe
67
62
  searchReplace
68
63
  });
69
64
  }
65
+ return Promise.resolve();
70
66
  }));
71
67
  }
@@ -11,11 +11,6 @@ var _isMultiSite = require("../../lib/validations/is-multi-site");
11
11
  var _isMultisiteDomainMapped = require("../../lib/validations/is-multisite-domain-mapped");
12
12
  var _utils = require("../../lib/validations/utils");
13
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
- /**
15
- *
16
- * @format
17
- */
18
-
19
14
  /**
20
15
  * External dependencies
21
16
  */
@@ -41,7 +36,7 @@ const siteTypeValidations = {
41
36
  envId,
42
37
  searchReplace
43
38
  }) => {
44
- const isMultiSite = await (0, _isMultiSite.isMultiSiteInSiteMeta)(appId, envId);
39
+ const isMultiSite = await (0, _isMultiSite.isMultiSiteInSiteMeta)(appId ?? 0, envId ?? 0);
45
40
  const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
46
41
  debug(`\nAppId: ${appId} is ${isMultiSite ? 'a multisite.' : 'not a multisite'}`);
47
42
  debug(`The SQL dump provided is ${isMultiSiteSqlDump ? 'from a multisite.' : 'not from a multisite'}\n`);
@@ -67,7 +62,7 @@ const siteTypeValidations = {
67
62
  // Check if primary domain is mapped only if it exists
68
63
  // Also saves on a call to Parker by checking ahead
69
64
  if (primaryDomainExists) {
70
- const isPrimaryDomainMapped = await (0, _isMultisiteDomainMapped.isMultisitePrimaryDomainMapped)(appId, envId, primaryDomainFromSQL);
65
+ const isPrimaryDomainMapped = await (0, _isMultisiteDomainMapped.isMultisitePrimaryDomainMapped)(appId ?? 0, envId ?? 0, primaryDomainFromSQL);
71
66
 
72
67
  // If site is multisite AND the primary domain is exists AND the primary is unmapped
73
68
  // then throw an error
@@ -12,11 +12,6 @@ var _lineByLine = require("../../lib/validations/line-by-line");
12
12
  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); }
13
13
  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; }
14
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
- /**
16
- *
17
- * @format
18
- */
19
-
20
15
  /**
21
16
  * External dependencies
22
17
  */
@@ -25,8 +20,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
25
20
  * Internal dependencies
26
21
  */
27
22
 
28
- // eslint-disable-next-line no-duplicate-imports
29
-
30
23
  let problemsFound = 0;
31
24
  let lineNum = 1;
32
25
  const tableNames = [];
@@ -48,16 +41,16 @@ const generalCheckFormatter = check => {
48
41
  problemsFound += 1;
49
42
  }
50
43
  for (const problem of validProblems) {
51
- const text = `${problem.text || check.message} on line ${problem.lineNumber || ''}.`;
44
+ const text = `${problem.text ?? check.message} on line ${problem.lineNumber ?? ''}.`;
52
45
  if (problem.warning) {
53
46
  errors.push({
54
47
  warning: formatWarning(text),
55
- recommendation: formatRecommendation(problem.recomendation || check.recommendation)
48
+ recommendation: formatRecommendation(problem.recomendation ?? check.recommendation)
56
49
  });
57
50
  } else {
58
51
  errors.push({
59
52
  error: formatError(text),
60
- recommendation: formatRecommendation(problem.recomendation || check.recommendation)
53
+ recommendation: formatRecommendation(problem.recomendation ?? check.recommendation)
61
54
  });
62
55
  }
63
56
  }
@@ -112,7 +105,9 @@ const requiredCheckFormatter = (check, type, isImport) => {
112
105
  const infoCheckFormatter = check => {
113
106
  const infos = [];
114
107
  check.results.forEach(item => {
115
- infos.push(item.text);
108
+ if (item.text) {
109
+ infos.push(item.text);
110
+ }
116
111
  });
117
112
  return {
118
113
  errors: [],
@@ -124,8 +119,8 @@ function checkTablePrefixes(results, errors, infos) {
124
119
  const notWPTables = [];
125
120
  const wpMultisiteTables = [];
126
121
  results.forEach(result => {
127
- const tableName = result.text || '';
128
- if (RegExp(/^wp_(\d+_)/).exec(tableName)) {
122
+ const tableName = result.text ?? '';
123
+ if (/^wp_(\d+_)/.exec(tableName)) {
129
124
  wpMultisiteTables.push(tableName);
130
125
  } else if (tableName.startsWith('wp_')) {
131
126
  wpTables.push(tableName);
@@ -287,7 +282,7 @@ const checks = {
287
282
  recommendation: "Use search-replace to change environment's domain"
288
283
  },
289
284
  engineInnoDB: {
290
- matcher: / ENGINE=(?!(InnoDB))/i,
285
+ matcher: /\sENGINE\s?=(?!(\s?InnoDB))/i,
291
286
  matchHandler: lineNumber => ({
292
287
  lineNumber
293
288
  }),
@@ -325,7 +320,7 @@ const postValidation = async options => {
325
320
  for (const [type, check] of checkEntries) {
326
321
  const formattedOutput = check.outputFormatter(check, type, options.isImport);
327
322
  for (const error of formattedOutput.errors) {
328
- if (error.warning) {
323
+ if ('warning' in error) {
329
324
  formattedWarnings.push(error);
330
325
  } else {
331
326
  formattedErrors.push(error);
@@ -391,7 +386,7 @@ const getTableNames = () => {
391
386
  };
392
387
  exports.getTableNames = getTableNames;
393
388
  const checkForTableName = line => {
394
- const matches = line.match(/(?<=^CREATE\sTABLE\s)`?(?:(wp_[\d+_]?\w+))`?/);
389
+ const matches = /(?<=^CREATE\sTABLE\s)`?(?:(wp_[\d+_]?\w+))`?/.exec(line);
395
390
  if (matches) {
396
391
  const tableName = matches[1];
397
392
  // we should only have one match if we have any since we're looking at the start of the string
@@ -411,7 +406,7 @@ const perLineValidations = (line, options = DEFAULT_VALIDATION_OPTIONS) => {
411
406
  const checkKeys = Object.keys(checks).filter(checkItem => !options.skipChecks.includes(checkItem));
412
407
  for (const checkKey of checkKeys) {
413
408
  const check = checks[checkKey];
414
- const results = line.match(check.matcher);
409
+ const results = line.match(check.matcher); // NOSONAR
415
410
  const extraCheckParams = options.extraCheckParams[checkKey];
416
411
  if (results) {
417
412
  check.results.push(check.matchHandler(lineNum, results, extraCheckParams));
@@ -424,8 +419,8 @@ const postLineExecutionProcessing = async ({
424
419
  skipChecks
425
420
  }) => {
426
421
  await postValidation({
427
- isImport: isImport || false,
428
- skipChecks: skipChecks || DEV_ENV_SPECIFIC_CHECKS,
422
+ isImport: isImport ?? false,
423
+ skipChecks: skipChecks ?? DEV_ENV_SPECIFIC_CHECKS,
429
424
  extraCheckParams: {}
430
425
  });
431
426
  };
@@ -23,7 +23,7 @@ function getMultilineStatement(statementRegex) {
23
23
  */
24
24
  return line => {
25
25
  const shouldStartCapture = statementRegex.test(line);
26
- const shouldEndCapture = (shouldStartCapture || isCapturing) && /;$/.test(line);
26
+ const shouldEndCapture = (shouldStartCapture || isCapturing) && line.endsWith(';');
27
27
  if (shouldStartCapture) {
28
28
  isCapturing = true;
29
29
  matchingStatements[index] = [];
@@ -0,0 +1,151 @@
1
+ const { spawn } = require( 'child_process' );
2
+ const { once } = require( 'events' );
3
+
4
+ async function runCommand( subcommands ) {
5
+ const childProcess = spawn( 'vip', subcommands );
6
+
7
+ let output = '';
8
+
9
+ for await ( const data of childProcess.stdout ) {
10
+ output += data.toString();
11
+ }
12
+ for await ( const data of childProcess.stderr ) {
13
+ output += data.toString();
14
+ }
15
+
16
+ const [ exitCode ] = await once( childProcess, 'exit' );
17
+
18
+ if ( exitCode !== 0 ) {
19
+ console.log( 'o', output );
20
+ throw new Error( `Script exited with code ${ exitCode }` );
21
+ }
22
+
23
+ return output.trim();
24
+ }
25
+
26
+ const USAGE_REGEXP = /Usage: (.*)/;
27
+ const COMMAND_REGEXP = /(\S+)\s+(.*)/;
28
+ const OPTION_REGEXP = /(-\S, --\S+)\s+(.*)/;
29
+
30
+ const SECTION_COMMAND = 'commands';
31
+ const SECTION_OPTIONS = 'options';
32
+ const SECTION_EXAMPLES = 'examples';
33
+
34
+ const parseOutput = output => {
35
+ const result = {};
36
+
37
+ const lines = output.split( '\n' );
38
+ let currentSection = '';
39
+
40
+ for ( let lineIx = 0; lineIx < lines.length; lineIx++ ) {
41
+ const line = lines[ lineIx ].trim();
42
+ if ( ! line ) {
43
+ continue;
44
+ }
45
+ if ( line.startsWith( 'Usage:' ) ) {
46
+ result.usage = line.match( USAGE_REGEXP )[ 1 ];
47
+ continue;
48
+ }
49
+
50
+ if ( line.startsWith( 'Commands:' ) ) {
51
+ result.commands = [];
52
+ currentSection = SECTION_COMMAND;
53
+ continue;
54
+ }
55
+ if ( line.startsWith( 'Options:' ) ) {
56
+ result.options = [];
57
+ currentSection = SECTION_OPTIONS;
58
+ continue;
59
+ }
60
+ if ( line.startsWith( 'Examples:' ) ) {
61
+ result.examples = [];
62
+ result.examplesRaw = '';
63
+ currentSection = SECTION_EXAMPLES;
64
+ continue;
65
+ }
66
+
67
+ if ( currentSection === SECTION_COMMAND ) {
68
+ const [ , command, description ] = line.match( COMMAND_REGEXP );
69
+ result.commands.push( {
70
+ command,
71
+ description,
72
+ } );
73
+ continue;
74
+ }
75
+ if ( currentSection === SECTION_OPTIONS ) {
76
+ if ( line.match( OPTION_REGEXP ) ) {
77
+ const [ , option, description ] = line.match( OPTION_REGEXP );
78
+ result.options.push( {
79
+ option,
80
+ description,
81
+ } );
82
+ } else {
83
+ console.log( 'Unknown option', line );
84
+ }
85
+ continue;
86
+ }
87
+ if ( currentSection === SECTION_EXAMPLES ) {
88
+ let description = '';
89
+ while ( ! lines[ lineIx ].trim().startsWith( '$' ) ) {
90
+ const descriptionLine = lines[ lineIx ].trim();
91
+ if ( description ) {
92
+ description += '\n';
93
+ }
94
+ if ( result.examplesRaw ) {
95
+ result.examplesRaw += '\n';
96
+ }
97
+ result.examplesRaw += descriptionLine;
98
+ description += descriptionLine;
99
+ lineIx++;
100
+ }
101
+ const usage = lines[ lineIx ] && lines[ lineIx ].trim();
102
+ result.examplesRaw += '\n' + usage;
103
+ result.examples.push( {
104
+ description,
105
+ usage,
106
+ } );
107
+ }
108
+ }
109
+
110
+ return result;
111
+ };
112
+
113
+ const processCommand = async subcommands => {
114
+ const fullCommand = subcommands.join( ' ' );
115
+ console.error( 'Processing', fullCommand, '...' );
116
+
117
+ const output = await runCommand( subcommands.concat( [ '--help' ] ) );
118
+ const parsedOutput = parseOutput( output );
119
+
120
+ const commandCount = parsedOutput.commands?.length || 0;
121
+ const commandOutputs = [];
122
+ for ( let commandIx = 0; commandIx < commandCount; commandIx++ ) {
123
+ const element = parsedOutput.commands[ commandIx ];
124
+ // otherwise the parallel run will randomly fail on too many requests
125
+ // eslint-disable-next-line no-await-in-loop
126
+ commandOutputs.push( await processCommand( subcommands.concat( [ element.command ] ) ) );
127
+ }
128
+ console.error( `Processed ${ fullCommand } -> ${ commandOutputs.length } subcommands` );
129
+ for ( let commandIx = 0; commandIx < commandCount; commandIx++ ) {
130
+ const element = parsedOutput.commands[ commandIx ];
131
+ const commandOutput = commandOutputs[ commandIx ];
132
+ commandOutput.name = element.command;
133
+ commandOutput.description = element.description;
134
+ parsedOutput.commands[ commandIx ] = commandOutput;
135
+ }
136
+
137
+ return parsedOutput;
138
+ };
139
+
140
+ const main = async () => {
141
+ const version = await runCommand( [ '--version' ] );
142
+
143
+ console.error( 'triggering command processing...' );
144
+ const result = await processCommand( [] );
145
+ console.error( 'command processing done' );
146
+ result.version = version;
147
+
148
+ console.log( JSON.stringify( result, null, 2 ) );
149
+ };
150
+
151
+ main();