@automattic/vip 4.1.0 → 4.1.1

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.
@@ -16,10 +16,14 @@ var _downloadFile = require("../lib/http/download-file");
16
16
  var _liveBackupCopy = _interopRequireWildcard(require("../lib/live-backup-copy"));
17
17
  var liveBackupCopy = _liveBackupCopy;
18
18
  var _retry = require("../lib/retry");
19
+ var _userError = _interopRequireDefault(require("../lib/user-error"));
19
20
  var _utils = require("../lib/utils");
20
21
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
21
22
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
22
23
  const EXPORT_SQL_PROGRESS_POLL_INTERVAL = 1000;
24
+
25
+ // Maximum allowed size for a live backup copy configuration file (500 KB).
26
+ const MAX_LIVE_BACKUP_CONFIG_SIZE_BYTES = 500 * 1024;
23
27
  const BACKUP_AND_JOB_STATUS_QUERY = (0, _graphqlTag.default)`
24
28
  query AppBackupAndJobStatus($appId: Int!, $envId: Int!) {
25
29
  app(id: $appId) {
@@ -455,10 +459,10 @@ class ExportSQLCommand {
455
459
  }
456
460
  async generateLiveBackupCopy() {
457
461
  if (!this.liveBackupCopyCLIOptions) {
458
- throw new Error('Configuration file is required for live backup copy.');
462
+ throw new _userError.default('Configuration file is required for live backup copy.');
459
463
  }
460
464
  if (!this.app.id || !this.env.id) {
461
- throw new Error('App ID and Environment ID are required to start live backup copy.');
465
+ throw new _userError.default('App ID and Environment ID are required to start live backup copy.');
462
466
  }
463
467
  const config = this.getLiveBackupConfigFromCLIOptions();
464
468
  try {
@@ -478,7 +482,7 @@ class ExportSQLCommand {
478
482
  this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK, [this.generateDownloadURLOutputString(result.url)]);
479
483
  return result;
480
484
  } catch (err) {
481
- const message = err instanceof Error ? err.message : 'Unknown error';
485
+ const message = (0, _utils.parseApiError)(err) ?? 'Unknown error';
482
486
  await this.track('error', {
483
487
  error_type: 'live_backup_copy',
484
488
  error_message: message,
@@ -512,17 +516,23 @@ class ExportSQLCommand {
512
516
  };
513
517
  }
514
518
  loadLiveBackupCopyConfig(configFile) {
515
- if (!_fs.default.existsSync(configFile)) {
516
- throw new Error(`Configuration file not found: ${configFile}`);
517
- }
518
519
  try {
519
- return JSON.parse(_fs.default.readFileSync(configFile, 'utf-8'));
520
+ // Read the file once to avoid a check-then-use race condition.
521
+ const fileContents = _fs.default.readFileSync(configFile, 'utf-8');
522
+ const size = Buffer.byteLength(fileContents);
523
+ if (size > MAX_LIVE_BACKUP_CONFIG_SIZE_BYTES) {
524
+ throw new _userError.default(`Configuration file is too large (${(0, _format.formatBytes)(size)}); the maximum allowed size is ${(0, _format.formatBytes)(MAX_LIVE_BACKUP_CONFIG_SIZE_BYTES)}. For large or complex exports, use the \`--wpcli-command\` option instead.`);
525
+ }
526
+ return JSON.parse(fileContents);
520
527
  } catch (err) {
528
+ if (err instanceof _userError.default) {
529
+ throw err;
530
+ }
521
531
  const errMessage = err instanceof Error ? err.message : 'Unknown error';
522
532
  if (err instanceof SyntaxError) {
523
- throw new Error(`Invalid JSON in configuration file: ${configFile} - ${errMessage}`);
533
+ throw new _userError.default(`Invalid JSON in configuration file: ${configFile} - ${errMessage}`);
524
534
  }
525
- throw new Error(`Error reading configuration file: ${configFile} - ${errMessage}`);
535
+ throw new _userError.default(`Error reading configuration file: ${configFile} - ${errMessage}`);
526
536
  }
527
537
  }
528
538
  }
package/dist/lib/utils.js CHANGED
@@ -79,19 +79,49 @@ function getAbsolutePath(filePath) {
79
79
  }
80
80
 
81
81
  /**
82
- * Parse error object and return probable error.
82
+ * Extract a message from a raw HTTP response body (Apollo's `ServerError.bodyText`).
83
83
  *
84
- * @param {Error} Error object
84
+ * The body may be either `{"status":"error","message":"..."}` (e.g. a 413 whose
85
+ * top-level message is only `Received status code 413`) or a GraphQL
86
+ * `{"errors":[{"message":"..."}]}` payload.
87
+ */
88
+ function parseJSONBodyErrorMessage(bodyText) {
89
+ try {
90
+ const body = JSON.parse(bodyText);
91
+ if (body?.errors?.[0]?.message) {
92
+ return body.errors[0].message;
93
+ }
94
+ if (body?.message) {
95
+ return body.message;
96
+ }
97
+ } catch {
98
+ // Body wasn't JSON; nothing to extract.
99
+ }
100
+ return null;
101
+ }
102
+ /**
103
+ * Parse error object and return probable error.
85
104
  *
86
- * @return {string|null} Error string when error was found, otherwise null.
105
+ * Accepts either a known API error shape or an `unknown` value (e.g. a caught
106
+ * error), so callers do not need to cast before passing it in.
87
107
  */
88
- function parseApiError(err) {
108
+ function parseApiError(error) {
109
+ const err = error;
89
110
  if (err?.networkError?.message) {
90
111
  return err?.networkError?.message;
91
112
  }
92
113
  if (err?.graphQLErrors?.[0]?.message) {
93
114
  return err.graphQLErrors[0].message;
94
115
  }
116
+
117
+ // Apollo's `ServerError` exposes the raw HTTP response body as `bodyText`,
118
+ // which often holds a more specific message than the generic top-level one.
119
+ if (typeof err?.bodyText === 'string') {
120
+ const bodyTextMessage = parseJSONBodyErrorMessage(err.bodyText);
121
+ if (bodyTextMessage) {
122
+ return bodyTextMessage;
123
+ }
124
+ }
95
125
  if (err?.message) {
96
126
  return err?.message;
97
127
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "4.1.0",
3
+ "version": "4.1.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@automattic/vip",
9
- "version": "4.1.0",
9
+ "version": "4.1.1",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
@@ -69,6 +69,10 @@
69
69
  "vip-config-software-update": "dist/bin/vip-config-software-update.js",
70
70
  "vip-db": "dist/bin/vip-db.js",
71
71
  "vip-db-phpmyadmin": "dist/bin/vip-db-phpmyadmin.js",
72
+ "vip-defensive-mode": "dist/bin/vip-defensive-mode.js",
73
+ "vip-defensive-mode-configure": "dist/bin/vip-defensive-mode-configure.js",
74
+ "vip-defensive-mode-disable": "dist/bin/vip-defensive-mode-disable.js",
75
+ "vip-defensive-mode-enable": "dist/bin/vip-defensive-mode-enable.js",
72
76
  "vip-dev-env": "dist/bin/vip-dev-env.js",
73
77
  "vip-dev-env-create": "dist/bin/vip-dev-env-create.js",
74
78
  "vip-dev-env-destroy": "dist/bin/vip-dev-env-destroy.js",
@@ -5667,16 +5671,42 @@
5667
5671
  }
5668
5672
  },
5669
5673
  "node_modules/axios": {
5670
- "version": "1.15.2",
5671
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz",
5672
- "integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==",
5674
+ "version": "1.18.1",
5675
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz",
5676
+ "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==",
5673
5677
  "license": "MIT",
5674
5678
  "dependencies": {
5675
- "follow-redirects": "^1.15.11",
5679
+ "follow-redirects": "^1.16.0",
5676
5680
  "form-data": "^4.0.5",
5681
+ "https-proxy-agent": "^5.0.1",
5677
5682
  "proxy-from-env": "^2.1.0"
5678
5683
  }
5679
5684
  },
5685
+ "node_modules/axios/node_modules/agent-base": {
5686
+ "version": "6.0.2",
5687
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
5688
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
5689
+ "license": "MIT",
5690
+ "dependencies": {
5691
+ "debug": "4"
5692
+ },
5693
+ "engines": {
5694
+ "node": ">= 6.0.0"
5695
+ }
5696
+ },
5697
+ "node_modules/axios/node_modules/https-proxy-agent": {
5698
+ "version": "5.0.1",
5699
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
5700
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
5701
+ "license": "MIT",
5702
+ "dependencies": {
5703
+ "agent-base": "6",
5704
+ "debug": "4"
5705
+ },
5706
+ "engines": {
5707
+ "node": ">= 6"
5708
+ }
5709
+ },
5680
5710
  "node_modules/axobject-query": {
5681
5711
  "version": "4.1.0",
5682
5712
  "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
@@ -7034,15 +7064,15 @@
7034
7064
  }
7035
7065
  },
7036
7066
  "node_modules/engine.io-client": {
7037
- "version": "6.6.5",
7038
- "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.5.tgz",
7039
- "integrity": "sha512-QCwxUDULPlXv8F6tqMMKx5dNkTe6OaBYRMPYeXKBlyOoKvAmE0ac6pW7fFhSscJ/5SI7666/U/B+MElbsrJlIg==",
7067
+ "version": "6.6.6",
7068
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.6.tgz",
7069
+ "integrity": "sha512-iY6QdftLQ9pyiPoX082bpf/u1UewnOaJrtJIF9T0++QB34lZrj0uP+Q/bj8AlUsAxqhnkTV2BS8SBZSxOmoV5Q==",
7040
7070
  "license": "MIT",
7041
7071
  "dependencies": {
7042
7072
  "@socket.io/component-emitter": "~3.1.0",
7043
7073
  "debug": "~4.4.1",
7044
7074
  "engine.io-parser": "~5.2.1",
7045
- "ws": "~8.20.1",
7075
+ "ws": "~8.21.0",
7046
7076
  "xmlhttprequest-ssl": "~2.1.1"
7047
7077
  }
7048
7078
  },
@@ -8527,16 +8557,16 @@
8527
8557
  }
8528
8558
  },
8529
8559
  "node_modules/form-data": {
8530
- "version": "4.0.5",
8531
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
8532
- "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
8560
+ "version": "4.0.6",
8561
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
8562
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
8533
8563
  "license": "MIT",
8534
8564
  "dependencies": {
8535
8565
  "asynckit": "^0.4.0",
8536
8566
  "combined-stream": "^1.0.8",
8537
8567
  "es-set-tostringtag": "^2.1.0",
8538
- "hasown": "^2.0.2",
8539
- "mime-types": "^2.1.12"
8568
+ "hasown": "^2.0.4",
8569
+ "mime-types": "^2.1.35"
8540
8570
  },
8541
8571
  "engines": {
8542
8572
  "node": ">= 6"
@@ -8988,9 +9018,9 @@
8988
9018
  }
8989
9019
  },
8990
9020
  "node_modules/hasown": {
8991
- "version": "2.0.2",
8992
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
8993
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
9021
+ "version": "2.0.4",
9022
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
9023
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
8994
9024
  "license": "MIT",
8995
9025
  "dependencies": {
8996
9026
  "function-bind": "^1.1.2"
@@ -11418,9 +11448,9 @@
11418
11448
  "license": "MIT"
11419
11449
  },
11420
11450
  "node_modules/js-yaml": {
11421
- "version": "5.2.1",
11422
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.1.tgz",
11423
- "integrity": "sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==",
11451
+ "version": "5.2.2",
11452
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.2.tgz",
11453
+ "integrity": "sha512-dayzUzKkJ1MkuUtZglSebU43utNXH0OWQByK9rKOOuYIO8M5TV1y+n8ALMdG0rdzBnfNkOmZEqrURepb0ejqBw==",
11424
11454
  "funding": [
11425
11455
  {
11426
11456
  "type": "github",
@@ -14172,9 +14202,9 @@
14172
14202
  }
14173
14203
  },
14174
14204
  "node_modules/tar": {
14175
- "version": "7.5.19",
14176
- "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.19.tgz",
14177
- "integrity": "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw==",
14205
+ "version": "7.5.22",
14206
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz",
14207
+ "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==",
14178
14208
  "license": "BlueOak-1.0.0",
14179
14209
  "dependencies": {
14180
14210
  "@isaacs/fs-minipass": "^4.0.0",
@@ -15309,9 +15339,9 @@
15309
15339
  }
15310
15340
  },
15311
15341
  "node_modules/ws": {
15312
- "version": "8.20.1",
15313
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
15314
- "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
15342
+ "version": "8.21.0",
15343
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
15344
+ "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
15315
15345
  "license": "MIT",
15316
15346
  "engines": {
15317
15347
  "node": ">=10.0.0"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "4.1.0",
3
+ "version": "4.1.1",
4
4
  "description": "The VIP Javascript library & CLI",
5
5
  "main": "index.js",
6
6
  "bin": {