@automattic/vip 4.0.8 → 4.0.10

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.
@@ -20,6 +20,7 @@ var _proxyAgent = require("../lib/http/proxy-agent");
20
20
  var _token = _interopRequireDefault(require("../lib/token"));
21
21
  var _tracker = require("../lib/tracker");
22
22
  var _helpers = require("../lib/wp/helpers");
23
+ var _readline2 = require("../lib/wp/readline");
23
24
  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); }
24
25
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
25
26
  const debug = (0, _debug.default)('@automattic/vip:wp');
@@ -107,8 +108,8 @@ const bindStreamEvents = ({
107
108
  subShellRl.close();
108
109
  process.exit();
109
110
  }
110
- subShellRl.resume();
111
- subShellRl.prompt();
111
+ (0, _readline2.safeResume)(subShellRl);
112
+ (0, _readline2.safePrompt)(subShellRl);
112
113
  });
113
114
  };
114
115
  const getTokenForCommand = async (appId, envId, command) => {
@@ -233,7 +234,7 @@ const bindReconnectEvents = ({
233
234
  });
234
235
 
235
236
  // Resume readline interface
236
- subShellRl.resume();
237
+ (0, _readline2.safeResume)(subShellRl);
237
238
  });
238
239
  currentJob.socket.on('retry', async () => {
239
240
  debug('socket: retry');
@@ -391,6 +392,7 @@ const examples = [{
391
392
  const commandState = (0, _helpers.initState)();
392
393
  let seenWP = false;
393
394
  const subShellRl = _readline.default.createInterface(subShellSettings);
395
+ (0, _readline2.trackReadline)(subShellRl);
394
396
  subShellRl.on('line', async line => {
395
397
  if (commandRunning) {
396
398
  return;
@@ -398,7 +400,7 @@ const examples = [{
398
400
 
399
401
  // Handle plain return / newline
400
402
  if (!line) {
401
- subShellRl.prompt();
403
+ (0, _readline2.safePrompt)(subShellRl);
402
404
  return;
403
405
  }
404
406
 
@@ -411,7 +413,7 @@ const examples = [{
411
413
  if (userCmdCancelled) {
412
414
  seenWP = false;
413
415
  (0, _helpers.resetState)(commandState);
414
- subShellRl.prompt();
416
+ (0, _readline2.safePrompt)(subShellRl);
415
417
  return;
416
418
  }
417
419
  if (!seenWP && line.trimStart().startsWith('wp ')) {
@@ -426,10 +428,10 @@ const examples = [{
426
428
  } else {
427
429
  (0, _helpers.resetState)(commandState);
428
430
  console.log(_chalk.default.red('Error:'), 'invalid command, please pass a valid WP-CLI command.');
429
- subShellRl.prompt();
431
+ (0, _readline2.safePrompt)(subShellRl);
430
432
  return;
431
433
  }
432
- subShellRl.pause();
434
+ (0, _readline2.safePause)(subShellRl);
433
435
  let result;
434
436
  const wpCliCmd = commandState.command.replace(/^wp\s+/, '');
435
437
  seenWP = false;
@@ -450,7 +452,7 @@ const examples = [{
450
452
  subShellRl.close();
451
453
  process.exit(1);
452
454
  }
453
- subShellRl.prompt();
455
+ (0, _readline2.safePrompt)(subShellRl);
454
456
  return;
455
457
  }
456
458
  const {
@@ -522,9 +524,9 @@ const examples = [{
522
524
  });
523
525
  if (!isSubShell) {
524
526
  mutableStdout.muted = true;
525
- subShellRl.write(`wp ${cmd}\n`);
527
+ (0, _readline2.safeWrite)(subShellRl, `wp ${cmd}\n`);
526
528
  mutableStdout.muted = false;
527
529
  return;
528
530
  }
529
- subShellRl.prompt();
531
+ (0, _readline2.safePrompt)(subShellRl);
530
532
  });
@@ -86,21 +86,16 @@ const getSqlFileStreamFromCompressedFile = async filePath => {
86
86
  }
87
87
  throw new Error('Not a supported compressed file');
88
88
  };
89
+
90
+ // Replaces the byte-size value that mydumper embeds in chunk header comments (e.g. `-- tablename 1234`)
91
+ // with -1. mydumper exports the original file size in those headers, but since we modify the dump,
92
+ // the size is no longer accurate — setting it to -1 tells mydumper to ignore it.
93
+ // Lines starting with `-- metadata` are left untouched as they use the same format but are not chunk headers.
89
94
  const fixMyDumperTransform = () => {
90
- const regex = /^-- ([^ ]+) \d+$/;
95
+ const regex = /^-- (?!metadata)([^ ]+) \d+$/gm;
91
96
  return new _nodeStream.Transform({
92
97
  transform(chunk, _encoding, callback) {
93
- const chunkString = chunk.toString();
94
- const lineEnding = chunkString.includes('\r\n') ? '\r\n' : '\n';
95
- const lines = chunk.toString().split(lineEnding).map(line => {
96
- const match = regex.exec(line);
97
- if (!match) {
98
- return line;
99
- }
100
- const tablePart = match[1];
101
- return `-- ${tablePart} -1`;
102
- });
103
- callback(null, lines.join(lineEnding));
98
+ callback(null, chunk.toString().replace(regex, '-- $1 -1'));
104
99
  }
105
100
  });
106
101
  };
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.default = void 0;
4
+ exports.Insecure = void 0;
5
5
  var _configstore = _interopRequireDefault(require("configstore"));
6
6
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
7
  class Insecure {
@@ -40,4 +40,4 @@ class Insecure {
40
40
  }
41
41
  }
42
42
  }
43
- exports.default = Insecure;
43
+ exports.Insecure = Insecure;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.default = void 0;
4
+ exports.Secure = void 0;
5
5
  var _keytar = _interopRequireDefault(require("@github/keytar"));
6
6
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
7
  class Secure {
@@ -16,4 +16,4 @@ class Secure {
16
16
  return _keytar.default.deletePassword(service, service);
17
17
  }
18
18
  }
19
- exports.default = Secure;
19
+ exports.Secure = Secure;
@@ -1,22 +1,27 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.default = void 0;
4
+ exports.getKeychain = getKeychain;
5
5
  var _debug = _interopRequireDefault(require("debug"));
6
- var _insecure = _interopRequireDefault(require("./keychain/insecure"));
6
+ var _insecure = require("./keychain/insecure");
7
7
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
8
  let keychain;
9
9
  const debug = (0, _debug.default)('@automattic/vip:keychain');
10
- try {
11
- // Try using Secure keychain ("keytar") first
12
- // eslint-disable-next-line @typescript-eslint/no-require-imports
13
- const Secure = require('./keychain/secure').default;
14
- keychain = new Secure();
15
- } catch (error) {
16
- debug('Cannot use Secure keychain; falling back to Insecure keychain (Details: %o)', error);
17
-
18
- // Fallback to Insecure keychain if we can't
19
- keychain = new _insecure.default('vip-go-cli');
20
- }
21
- const exportedKeychain = keychain;
22
- var _default = exports.default = exportedKeychain;
10
+ async function getKeychain() {
11
+ if (typeof keychain === 'undefined') {
12
+ try {
13
+ const {
14
+ Secure
15
+ } = await import('./keychain/secure.js');
16
+ const kc = new Secure();
17
+ // We don't know if the secure keychain is actually usable until we try to communicate with it.
18
+ await kc.getPassword('non-existent-password-fraude-perit-virtus');
19
+ debug('Using Secure keychain');
20
+ keychain = kc;
21
+ } catch (error) {
22
+ debug('Cannot use Secure keychain; falling back to Insecure keychain (Details: %o)', error);
23
+ keychain = new _insecure.Insecure('vip-go-cli');
24
+ }
25
+ }
26
+ return keychain;
27
+ }
package/dist/lib/token.js CHANGED
@@ -5,8 +5,7 @@ exports.default = exports.SERVICE = void 0;
5
5
  var _jwtDecode = require("jwt-decode");
6
6
  var _nodeCrypto = require("node:crypto");
7
7
  var _api = require("./api");
8
- var _keychain = _interopRequireDefault(require("./keychain"));
9
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
+ var _keychain = require("./keychain");
10
9
  // Config
11
10
  const SERVICE = exports.SERVICE = 'vip-go-cli';
12
11
  class Token {
@@ -62,29 +61,34 @@ class Token {
62
61
  }
63
62
  static async uuid() {
64
63
  const service = Token.getServiceName('-uuid');
65
- let _uuid = await _keychain.default.getPassword(service);
64
+ const keychain = await (0, _keychain.getKeychain)();
65
+ let _uuid = await keychain.getPassword(service);
66
66
  if (!_uuid) {
67
67
  _uuid = (0, _nodeCrypto.randomUUID)();
68
- await _keychain.default.setPassword(service, _uuid);
68
+ await keychain.setPassword(service, _uuid);
69
69
  }
70
70
  return _uuid;
71
71
  }
72
72
  static async setUuid(_uuid) {
73
73
  const service = Token.getServiceName('-uuid');
74
- await _keychain.default.setPassword(service, _uuid);
74
+ const keychain = await (0, _keychain.getKeychain)();
75
+ await keychain.setPassword(service, _uuid);
75
76
  }
76
- static set(token) {
77
+ static async set(token) {
77
78
  const service = Token.getServiceName();
78
- return _keychain.default.setPassword(service, token);
79
+ const keychain = await (0, _keychain.getKeychain)();
80
+ return keychain.setPassword(service, token);
79
81
  }
80
82
  static async get() {
81
83
  const service = Token.getServiceName();
82
- const token = (await _keychain.default.getPassword(service)) ?? '';
83
- return new Token(token);
84
+ const keychain = await (0, _keychain.getKeychain)();
85
+ const token = await keychain.getPassword(service);
86
+ return new Token(token ?? '');
84
87
  }
85
- static purge() {
88
+ static async purge() {
86
89
  const service = Token.getServiceName();
87
- return _keychain.default.deletePassword(service);
90
+ const keychain = await (0, _keychain.getKeychain)();
91
+ return keychain.deletePassword(service);
88
92
  }
89
93
  static getServiceName(modifier = '') {
90
94
  let service = SERVICE;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.isReadlineClosed = isReadlineClosed;
5
+ exports.safePause = safePause;
6
+ exports.safePrompt = safePrompt;
7
+ exports.safeResume = safeResume;
8
+ exports.safeWrite = safeWrite;
9
+ exports.trackReadline = trackReadline;
10
+ /**
11
+ * Safe wrappers around `readline.Interface` lifecycle methods.
12
+ *
13
+ * On Node.js >= 24, calling `resume()`, `pause()`, `prompt()`, or `write()` on a
14
+ * readline interface that has already been closed throws
15
+ * `Error [ERR_USE_AFTER_CLOSE]: readline was closed`. On Node 20/22 the same
16
+ * calls are silent no-ops.
17
+ *
18
+ * `vip wp` drives non-interactive, one-shot commands through a readline
19
+ * interface bound to `process.stdin`. When stdin is redirected from
20
+ * `/dev/null` (no TTY, e.g. CI or container runs) the interface receives EOF
21
+ * immediately and closes, while the command keeps streaming output. On a
22
+ * websocket reconnect during a long-running command the reconnect handler then
23
+ * calls `resume()` on the already-closed interface, crashing the process on
24
+ * Node 24.
25
+ *
26
+ * These helpers guard every such call so the interface is only driven while it
27
+ * is still open. Closure is tracked through the documented `'close'` event
28
+ * rather than any internal interface property, so the behaviour does not depend
29
+ * on Node.js implementation details.
30
+ *
31
+ * Register an interface with {@link trackReadline} once, right after it is
32
+ * created, so the `'close'` listener is attached before the interface can
33
+ * close. Calls made through the `safe*` helpers on an untracked-but-open
34
+ * interface still work; tracking only adds the closed-state guard.
35
+ *
36
+ * @see https://nodejs.org/api/readline.html#event-close
37
+ */
38
+
39
+ const closedInterfaces = new WeakSet();
40
+
41
+ /**
42
+ * Begin tracking a readline interface so its closed state can be detected.
43
+ *
44
+ * Attaches a one-time `'close'` listener that records the interface as closed.
45
+ * Safe to call more than once for the same interface.
46
+ *
47
+ * @param rl The readline interface to track.
48
+ * @returns The same interface, for convenient chaining.
49
+ */
50
+ function trackReadline(rl) {
51
+ rl.once('close', () => {
52
+ closedInterfaces.add(rl);
53
+ });
54
+ return rl;
55
+ }
56
+
57
+ /**
58
+ * Whether a tracked readline interface has already emitted `'close'`.
59
+ *
60
+ * @param rl The readline interface to inspect.
61
+ * @returns `true` if the interface has been closed, otherwise `false`.
62
+ */
63
+ function isReadlineClosed(rl) {
64
+ return closedInterfaces.has(rl);
65
+ }
66
+
67
+ /**
68
+ * Resume the readline interface unless it has already been closed.
69
+ *
70
+ * @param rl The readline interface to resume.
71
+ */
72
+ function safeResume(rl) {
73
+ if (!isReadlineClosed(rl)) {
74
+ rl.resume();
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Pause the readline interface unless it has already been closed.
80
+ *
81
+ * @param rl The readline interface to pause.
82
+ */
83
+ function safePause(rl) {
84
+ if (!isReadlineClosed(rl)) {
85
+ rl.pause();
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Display the prompt unless the readline interface has already been closed.
91
+ *
92
+ * @param rl The readline interface to prompt on.
93
+ * @param preserveCursor When `true`, prevents the cursor from being reset to 0.
94
+ */
95
+ function safePrompt(rl, preserveCursor) {
96
+ if (!isReadlineClosed(rl)) {
97
+ rl.prompt(preserveCursor);
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Write data into the readline interface unless it has already been closed.
103
+ *
104
+ * @param rl The readline interface to write to.
105
+ * @param data The data to write.
106
+ * @param key An optional key sequence, mirroring `Interface#write`.
107
+ */
108
+ function safeWrite(rl, data, key) {
109
+ if (!isReadlineClosed(rl)) {
110
+ rl.write(data, key);
111
+ }
112
+ }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "4.0.8",
3
+ "version": "4.0.10",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@automattic/vip",
9
- "version": "4.0.8",
9
+ "version": "4.0.10",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
@@ -41,7 +41,7 @@
41
41
  "socks-proxy-agent": "^10.0.0",
42
42
  "ssh2": "1.17.0",
43
43
  "tar": "^7.4.0",
44
- "undici": "^7.0.0",
44
+ "undici": "^8.5.0",
45
45
  "update-notifier": "7.3.1",
46
46
  "xml2js": "^0.6.2"
47
47
  },
@@ -137,7 +137,7 @@
137
137
  "typescript": "^6.0.2"
138
138
  },
139
139
  "engines": {
140
- "node": "^20.19.0 || ^22.12.0 || >=23.0.0",
140
+ "node": ">=22.19.0",
141
141
  "npm": ">=8"
142
142
  },
143
143
  "optionalDependencies": {
@@ -11418,9 +11418,9 @@
11418
11418
  "license": "MIT"
11419
11419
  },
11420
11420
  "node_modules/js-yaml": {
11421
- "version": "5.0.0",
11422
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.0.0.tgz",
11423
- "integrity": "sha512-GSvaPUbk1U+FMZ7rJzF+F8e5YVtu7KnD40et/5rBXXRBv2jCO9L3qCewvIDDdudC0QycTFlf6EAA+h3kxBsuUw==",
11421
+ "version": "5.2.0",
11422
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.0.tgz",
11423
+ "integrity": "sha512-YeLUMlvR4Ou1B119LIaM0r65JvbOBooJDc9yEu0dClb/uSC5P4FrLU8OCCz/HXWvtPoIrR0dRzABTjo1sTN9Bw==",
11424
11424
  "funding": [
11425
11425
  {
11426
11426
  "type": "github",
@@ -14172,9 +14172,9 @@
14172
14172
  }
14173
14173
  },
14174
14174
  "node_modules/tar": {
14175
- "version": "7.5.16",
14176
- "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz",
14177
- "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==",
14175
+ "version": "7.5.19",
14176
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.19.tgz",
14177
+ "integrity": "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw==",
14178
14178
  "license": "BlueOak-1.0.0",
14179
14179
  "dependencies": {
14180
14180
  "@isaacs/fs-minipass": "^4.0.0",
@@ -14624,12 +14624,12 @@
14624
14624
  }
14625
14625
  },
14626
14626
  "node_modules/undici": {
14627
- "version": "7.25.0",
14628
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz",
14629
- "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==",
14627
+ "version": "8.5.0",
14628
+ "resolved": "https://registry.npmjs.org/undici/-/undici-8.5.0.tgz",
14629
+ "integrity": "sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg==",
14630
14630
  "license": "MIT",
14631
14631
  "engines": {
14632
- "node": ">=20.18.1"
14632
+ "node": ">=22.19.0"
14633
14633
  }
14634
14634
  },
14635
14635
  "node_modules/undici-types": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "4.0.8",
3
+ "version": "4.0.10",
4
4
  "description": "The VIP Javascript library & CLI",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -107,7 +107,7 @@
107
107
  ],
108
108
  "license": "MIT",
109
109
  "engines": {
110
- "node": "^20.19.0 || ^22.12.0 || >=23.0.0",
110
+ "node": ">=22.19.0",
111
111
  "npm": ">=8"
112
112
  },
113
113
  "bugs": {
@@ -172,7 +172,7 @@
172
172
  "socks-proxy-agent": "^10.0.0",
173
173
  "ssh2": "1.17.0",
174
174
  "tar": "^7.4.0",
175
- "undici": "^7.0.0",
175
+ "undici": "^8.5.0",
176
176
  "update-notifier": "7.3.1",
177
177
  "xml2js": "^0.6.2"
178
178
  },