@automattic/vip 2.28.3 → 2.29.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ## Changelog
2
2
 
3
+ ### 2.29.0
4
+
5
+ - #1362 feature(dev-env): Add vip export sql command
6
+ - #1357 chore(deps): Update semver from 7.5.0 to 7.5.1
7
+ - #1360 chore(dev-deps): Update flow-bin from 0.205.1 to 0.206.0
8
+ - #1365 chore(deps): Fix CVE-2023-32695
9
+ - #1356 fix(dev-env): Handle `--media-redirect-domain` in `vip dev-env update`
10
+ - #1361 chore(dev-deps): Update packages related to linting
11
+ - #1364 fix(dev-env): Fix "Cannot read properties of undefined" in `preProcessInstanceData()`
12
+ - #1363 fix(dev-env): Add error handling to readEnvironmentData()
13
+ - #1317 Auto-login support
14
+
3
15
  ### 2.28.3
4
16
 
5
17
  - #1352 chore(deps): Update node-fetch from 2.6.9 to 2.6.11
@@ -53,6 +53,9 @@ services:
53
53
  XDEBUG: <%= xdebug ? 'enable' : 'disable' %>
54
54
  <% if ( xdebugConfig ) { %>
55
55
  XDEBUG_CONFIG: "<%= xdebugConfig %>"
56
+ <% } %>
57
+ <% if ( autologinKey ) { %>
58
+ VIP_DEV_AUTOLOGIN_KEY: "<%= autologinKey %>"
56
59
  <% } %>
57
60
  LANDO_NO_USER_PERMS: 'enable'
58
61
  LANDO_NEEDS_EXEC: 1
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ *
5
+ * @format
6
+ */
7
+
8
+ /**
9
+ * External dependencies
10
+ */
11
+
12
+ /**
13
+ * Internal dependencies
14
+ */
15
+ "use strict";
16
+
17
+ var _command = _interopRequireDefault(require("../lib/cli/command"));
18
+ var _exportSql = require("../commands/export-sql");
19
+ var _tracker = require("../lib/tracker");
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+ const examples = [{
22
+ usage: 'vip export sql @mysite.develop',
23
+ description: 'Export SQL file from your site and save it to the current directory'
24
+ }, {
25
+ usage: 'vip export sql @mysite.develop --output=~/Desktop/export.sql.gz',
26
+ description: 'The output file can be specified with the --output flag'
27
+ }];
28
+ const appQuery = `
29
+ id,
30
+ name,
31
+ type,
32
+ organization { id, name },
33
+ environments{
34
+ id
35
+ appId
36
+ type
37
+ name
38
+ primaryDomain { name }
39
+ }
40
+ `;
41
+ (0, _command.default)({
42
+ appContext: true,
43
+ appQuery,
44
+ envContext: true,
45
+ module: 'export-sql',
46
+ requiredArgs: 0,
47
+ usage: 'vip export sql'
48
+ }).option('output', 'Specify the location where you want to save the export file').examples(examples).argv(process.argv, async (arg, {
49
+ app,
50
+ env,
51
+ output
52
+ }) => {
53
+ const trackerFn = (0, _tracker.makeCommandTracker)('export_sql', {
54
+ app: app.id,
55
+ env: env.uniqueLabel
56
+ });
57
+ await trackerFn('execute');
58
+ const exportCommand = new _exportSql.ExportSQLCommand(app, env, output, trackerFn);
59
+ await exportCommand.run();
60
+ await trackerFn('success');
61
+ });
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * External dependencies
5
+ */
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ "use strict";
11
+
12
+ var _command = _interopRequireDefault(require("../lib/cli/command"));
13
+ var _tracker = require("../lib/tracker");
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+ (0, _command.default)().command('sql', 'Export the contents of your database to an SQL file').example('vip export sql @mysite.develop', 'Export the contents of your database to an SQL file').argv(process.argv, async () => {
16
+ await (0, _tracker.trackEvent)('vip_export_command_execute');
17
+ });
package/dist/bin/vip.js CHANGED
@@ -33,7 +33,7 @@ const runCmd = async function () {
33
33
  cmd.command('logout', 'Logout from your current session', async () => {
34
34
  await (0, _logout.default)();
35
35
  console.log('You are successfully logged out.');
36
- }).command('app', 'List and modify your VIP applications').command('cache', 'Manage page cache for your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-environment').command('import', 'Import media or SQL files into your VIP applications').command('logs', 'Get logs from your VIP applications').command('search-replace', 'Perform search and replace tasks on files').command('sync', 'Sync production to a development environment').command('whoami', 'Display details about the currently logged-in user').command('validate', 'Validate your VIP application and environment').command('wp', 'Run WP CLI commands against an environment');
36
+ }).command('app', 'List and modify your VIP applications').command('cache', 'Manage page cache for your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-environment').command('export', 'Export data from your VIP application').command('import', 'Import media or SQL files into your VIP applications').command('logs', 'Get logs from your VIP applications').command('search-replace', 'Perform search and replace tasks on files').command('sync', 'Sync production to a development environment').command('whoami', 'Display details about the currently logged-in user').command('validate', 'Validate your VIP application and environment').command('wp', 'Run WP CLI commands against an environment');
37
37
  cmd.argv(process.argv);
38
38
  };
39
39
  function doesArgvHaveAtLeastOneParam(argv, params) {
@@ -8,7 +8,7 @@ var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
8
8
  var _fs = _interopRequireDefault(require("fs"));
9
9
  var _https = _interopRequireDefault(require("https"));
10
10
  var _path = _interopRequireDefault(require("path"));
11
- var _api = _interopRequireDefault(require("../lib/api"));
11
+ var _api = _interopRequireWildcard(require("../lib/api"));
12
12
  var _format = require("../lib/cli/format");
13
13
  var _progress = require("../lib/cli/progress");
14
14
  var exit = _interopRequireWildcard(require("../lib/cli/exit"));
@@ -162,8 +162,10 @@ async function generateDownloadLink(appId, envId, backupId) {
162
162
  * @throws {Error} Throws an error if the job creation fails
163
163
  */
164
164
  async function createExportJob(appId, envId, backupId) {
165
+ // Disable global error handling so that we can handle errors ourselves
166
+ (0, _api.disableGlobalGraphQLErrorHandling)();
165
167
  const api = await (0, _api.default)();
166
- const response = await api.mutate({
168
+ await api.mutate({
167
169
  mutation: CREATE_EXPORT_JOB_MUTATION,
168
170
  variables: {
169
171
  input: {
@@ -173,16 +175,9 @@ async function createExportJob(appId, envId, backupId) {
173
175
  }
174
176
  }
175
177
  });
176
- const {
177
- data: {
178
- startDBBackupCopy: {
179
- success
180
- }
181
- }
182
- } = response;
183
- if (!success) {
184
- throw new Error();
185
- }
178
+
179
+ // Re-enable global error handling
180
+ (0, _api.enableGlobalGraphQLErrorHandling)();
186
181
  }
187
182
 
188
183
  /**
@@ -195,18 +190,18 @@ class ExportSQLCommand {
195
190
  DOWNLOAD_LINK: 'downloadLink',
196
191
  DOWNLOAD: 'download'
197
192
  };
198
-
199
193
  /**
200
194
  * Creates an instance of SQLExportCommand
201
195
  *
202
- * @param {any} app The application object
203
- * @param {any} env The environment object
204
- * @param {string} outputFile The output file path
196
+ * @param {any} app The application object
197
+ * @param {any} env The environment object
198
+ * @param {string} outputFile The output file path
199
+ * @param {Function} trackerFn The progress tracker function
205
200
  */
206
- constructor(app, env, outputFile) {
201
+ constructor(app, env, outputFile, trackerFn = () => {}) {
207
202
  this.app = app;
208
203
  this.env = env;
209
- this.outputFile = outputFile;
204
+ this.outputFile = typeof outputFile === 'string' ? (0, _utils.getAbsolutePath)(outputFile) : null;
210
205
  this.progressTracker = new _progress.ProgressTracker([{
211
206
  id: this.steps.PREPARE,
212
207
  name: 'Preparing'
@@ -220,6 +215,7 @@ class ExportSQLCommand {
220
215
  id: this.steps.DOWNLOAD,
221
216
  name: 'Downloading file'
222
217
  }]);
218
+ this.track = trackerFn;
223
219
  }
224
220
 
225
221
  /**
@@ -264,6 +260,8 @@ class ExportSQLCommand {
264
260
  return new Promise((resolve, reject) => {
265
261
  _https.default.get(url, response => {
266
262
  response.pipe(file);
263
+ const total = parseInt(response.headers['content-length'], 10);
264
+ let current = 0;
267
265
  file.on('finish', () => {
268
266
  file.close();
269
267
  resolve(_path.default.resolve(file.path));
@@ -272,6 +270,10 @@ class ExportSQLCommand {
272
270
  _fs.default.unlink(filename);
273
271
  reject(err);
274
272
  });
273
+ response.on('data', chunk => {
274
+ current += chunk.length;
275
+ this.progressTracker.setProgress(`- ${(100 * current / total).toFixed(2)}% (${(0, _format.formatBytes)(current)}/${(0, _format.formatBytes)(total)})`);
276
+ });
275
277
  });
276
278
  });
277
279
  }
@@ -314,26 +316,44 @@ class ExportSQLCommand {
314
316
  * @return {Promise} A promise which resolves to void
315
317
  */
316
318
  async run() {
319
+ if (this.outputFile) {
320
+ try {
321
+ _fs.default.accessSync(_path.default.parse(this.outputFile).dir, _fs.default.constants.W_OK);
322
+ } catch (err) {
323
+ await this.track('cannot_write_to_path', {
324
+ errorMessage: `Cannot write to the specified path: ${err === null || err === void 0 ? void 0 : err.message}`
325
+ });
326
+ exit.withError(`Cannot write to the specified path: ${err === null || err === void 0 ? void 0 : err.message}`);
327
+ }
328
+ }
317
329
  console.log(`Fetching the latest backup for ${this.app.name}`);
318
330
  const {
319
331
  latestBackup
320
332
  } = await fetchLatestBackupAndJobStatus(this.app.id, this.env.id);
321
333
  if (!latestBackup) {
334
+ await this.track('no_backup_found_error', {
335
+ errorMessage: 'No backup found for the site'
336
+ });
322
337
  exit.withError(`No backup found for site ${this.app.name}`);
323
338
  } else {
324
339
  console.log(`${(0, _format.getGlyphForStatus)('success')} Latest backup found with timestamp ${latestBackup.createdAt}`);
325
340
  }
326
-
327
- // See if there is an existing export job for the latest backup
328
- if (!(await this.getExportJob())) {
341
+ if (await this.getExportJob()) {
342
+ console.log(`Attaching to an existing export for the backup with timestamp ${latestBackup.createdAt}`);
343
+ } else {
329
344
  console.log(`Creating a new export for the backup with timestamp ${latestBackup.createdAt}`);
330
345
  try {
331
346
  await createExportJob(this.app.id, this.env.id, latestBackup.id);
332
347
  } catch (err) {
348
+ // Todo: match error code instead of message substring
349
+ if (err !== null && err !== void 0 && err.message.includes('Backup Copy already in progress')) {
350
+ await this.track('export_job_already_running_error', {
351
+ errorMessage: err === null || err === void 0 ? void 0 : err.message
352
+ });
353
+ exit.withError('There is an export job already running for this site: ' + `https://dashboard.wpvip.com/apps/${this.app.id}/${this.env.uniqueLabel}/data/database/backups\n` + 'Currently, we allow only one export job at a time, per site. Please try again later.');
354
+ }
333
355
  exit.withError(`Error creating export job: ${err === null || err === void 0 ? void 0 : err.message}`);
334
356
  }
335
- } else {
336
- console.log(`Attaching to an existing export for the backup with timestamp ${latestBackup.createdAt}`);
337
357
  }
338
358
  this.progressTracker.stepRunning(this.steps.PREPARE);
339
359
  this.progressTracker.startPrinting();
@@ -353,6 +373,9 @@ class ExportSQLCommand {
353
373
  } catch (err) {
354
374
  this.progressTracker.stepFailed(this.steps.DOWNLOAD);
355
375
  this.stopProgressTracker();
376
+ await this.track('download_failed_error', {
377
+ errorMessage: err === null || err === void 0 ? void 0 : err.message
378
+ });
356
379
  exit.withError(`Error downloading exported file: ${err === null || err === void 0 ? void 0 : err.message}`);
357
380
  }
358
381
  }
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.RunningSprite = exports.RUNNING_SPRITE_GLYPHS = void 0;
7
7
  exports.capitalize = capitalize;
8
+ exports.formatBytes = void 0;
8
9
  exports.formatData = formatData;
9
10
  exports.formatEnvironment = formatEnvironment;
10
11
  exports.formatSearchReplaceValues = void 0;
@@ -182,4 +183,17 @@ const formatSearchReplaceValues = (values, message) => {
182
183
  });
183
184
  return formattedOutput;
184
185
  };
185
- exports.formatSearchReplaceValues = formatSearchReplaceValues;
186
+
187
+ // Format bytes into kilobytes, megabytes, etc based on the size
188
+ exports.formatSearchReplaceValues = formatSearchReplaceValues;
189
+ const formatBytes = (bytes, decimals = 2) => {
190
+ if (0 === bytes) {
191
+ return '0 Bytes';
192
+ }
193
+ const kk = 1024;
194
+ const dm = decimals < 0 ? 0 : decimals;
195
+ const sizes = ['bytes', 'KB', 'MB', 'GB', 'TB'];
196
+ const idx = Math.floor(Math.log(bytes) / Math.log(kk));
197
+ return parseFloat((bytes / Math.pow(kk, idx)).toFixed(dm)) + ' ' + sizes[idx];
198
+ };
199
+ exports.formatBytes = formatBytes;
@@ -59,6 +59,16 @@ class ProgressTracker {
59
59
  percentage
60
60
  });
61
61
  }
62
+ setProgress(progress) {
63
+ const step = this.getCurrentStep();
64
+ if (!step) {
65
+ return;
66
+ }
67
+ this.stepsFromCaller.set(step.id, {
68
+ ...step,
69
+ progress
70
+ });
71
+ }
62
72
  setStepsFromServer(steps) {
63
73
  const formattedSteps = steps.map(({
64
74
  name,
@@ -90,6 +100,15 @@ class ProgressTracker {
90
100
  status
91
101
  }) => status === 'pending');
92
102
  }
103
+ getCurrentStep() {
104
+ if (this.allStepsSucceeded()) {
105
+ return undefined;
106
+ }
107
+ const steps = [...this.getSteps().values()];
108
+ return steps.find(({
109
+ status
110
+ }) => status === 'running');
111
+ }
93
112
  stepRunning(stepId) {
94
113
  this.setStatusForStepId(stepId, 'running');
95
114
  }
@@ -152,7 +171,8 @@ class ProgressTracker {
152
171
  name,
153
172
  id,
154
173
  percentage,
155
- status
174
+ status,
175
+ progress
156
176
  }) => {
157
177
  const statusIcon = (0, _format.getGlyphForStatus)(status, this.runningSprite);
158
178
  let suffix = '';
@@ -160,6 +180,8 @@ class ProgressTracker {
160
180
  if (status === 'running' && percentage) {
161
181
  suffix = percentage;
162
182
  }
183
+ } else if (progress) {
184
+ suffix = progress;
163
185
  }
164
186
  return `${accumulator}${statusIcon} ${name} ${suffix}\n`;
165
187
  }, '');
@@ -29,11 +29,11 @@ exports.DEV_ENVIRONMENT_WORDPRESS_CACHE_KEY = DEV_ENVIRONMENT_WORDPRESS_CACHE_KE
29
29
  const DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL = 86400; // once per day
30
30
  exports.DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL = DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL;
31
31
  const DEV_ENVIRONMENT_PHP_VERSIONS = {
32
+ '8.0': 'ghcr.io/automattic/vip-container-images/php-fpm:8.0',
32
33
  // eslint-disable-next-line quote-props
33
34
  '8.2': 'ghcr.io/automattic/vip-container-images/php-fpm:8.2',
34
35
  // eslint-disable-next-line quote-props
35
36
  '8.1': 'ghcr.io/automattic/vip-container-images/php-fpm:8.1',
36
- '8.0': 'ghcr.io/automattic/vip-container-images/php-fpm:8.0',
37
37
  // eslint-disable-next-line quote-props -- flow does not support non-string keys
38
38
  '7.4': 'ghcr.io/automattic/vip-container-images/php-fpm:7.4'
39
39
  };
@@ -67,7 +67,8 @@ async function sanitizeConfiguration(configuration) {
67
67
  const genericConfigurationError = `Configuration file ${_chalk.default.grey(CONFIGURATION_FILE_NAME)} is available but ` + `couldn't be loaded. Ensure there is a ${_chalk.default.cyan('configuration-version')} and ${_chalk.default.cyan('slug')} ` + `configured. For example:\n\n${_chalk.default.grey(getConfigurationFileExample())}`;
68
68
  if (Array.isArray(configuration) || typeof configuration !== 'object') {
69
69
  throw new Error(genericConfigurationError);
70
- } else if (configuration['configuration-version'] === undefined || configuration.slug === undefined) {
70
+ }
71
+ if (configuration['configuration-version'] === undefined || configuration.slug === undefined) {
71
72
  throw new Error(genericConfigurationError);
72
73
  }
73
74
  const validVersions = getAllConfigurationFileVersions().map(version => _chalk.default.cyan(version)).join(', ');
@@ -92,7 +93,8 @@ async function sanitizeConfiguration(configuration) {
92
93
  elasticsearch: stringToBooleanIfDefined(configuration.elasticsearch),
93
94
  phpmyadmin: stringToBooleanIfDefined(configuration.phpmyadmin),
94
95
  xdebug: stringToBooleanIfDefined(configuration.xdebug),
95
- mailpit: stringToBooleanIfDefined((_configuration$mailpi = configuration.mailpit) !== null && _configuration$mailpi !== void 0 ? _configuration$mailpi : configuration.mailhog)
96
+ mailpit: stringToBooleanIfDefined((_configuration$mailpi = configuration.mailpit) !== null && _configuration$mailpi !== void 0 ? _configuration$mailpi : configuration.mailhog),
97
+ 'media-redirect-domain': configuration['media-redirect-domain']
96
98
  };
97
99
 
98
100
  // Remove undefined values
@@ -116,7 +118,8 @@ function mergeConfigurationFileOptions(preselectedOptions, configurationFileOpti
116
118
  phpmyadmin: configurationFileOptions.phpmyadmin,
117
119
  xdebug: configurationFileOptions.xdebug,
118
120
  xdebugConfig: configurationFileOptions['xdebug-config'],
119
- mailpit: (_configurationFileOpt = configurationFileOptions.mailpit) !== null && _configurationFileOpt !== void 0 ? _configurationFileOpt : configurationFileOptions.mailhog
121
+ mailpit: (_configurationFileOpt = configurationFileOptions.mailpit) !== null && _configurationFileOpt !== void 0 ? _configurationFileOpt : configurationFileOptions.mailhog,
122
+ mediaRedirectDomain: configurationFileOptions['media-redirect-domain']
120
123
  };
121
124
  const mergedOptions = {};
122
125
  Object.keys(configurationFileInstanceOptions).forEach(key => {
@@ -34,6 +34,7 @@ var _path = _interopRequireDefault(require("path"));
34
34
  var _chalk = _interopRequireDefault(require("chalk"));
35
35
  var _enquirer = require("enquirer");
36
36
  var _copyDir = _interopRequireDefault(require("copy-dir"));
37
+ var _uuid = require("uuid");
37
38
  var _devEnvironmentLando = require("./dev-environment-lando");
38
39
  var _searchAndReplace = require("../search-and-replace");
39
40
  var _devEnvironmentCli = require("./dev-environment-cli");
@@ -129,7 +130,7 @@ function preProcessInstanceData(instanceData) {
129
130
  newInstanceData.mediaRedirectDomain = `https://${instanceData.mediaRedirectDomain}`;
130
131
  }
131
132
  newInstanceData.elasticsearch = instanceData.elasticsearch || false;
132
- newInstanceData.php = instanceData.php || _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS.default;
133
+ newInstanceData.php = instanceData.php || _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS[Object.keys(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS)[0]];
133
134
  if (newInstanceData.php.startsWith('image:')) {
134
135
  newInstanceData.php = newInstanceData.php.slice('image:'.length);
135
136
  }
@@ -156,6 +157,9 @@ function preProcessInstanceData(instanceData) {
156
157
  if (!newInstanceData.mariadb) {
157
158
  newInstanceData.mariadb = undefined;
158
159
  }
160
+
161
+ // newInstanceData
162
+ newInstanceData.autologinKey = (0, _uuid.v4)();
159
163
  return newInstanceData;
160
164
  }
161
165
  async function destroyEnvironment(lando, slug, removeFiles) {
@@ -224,9 +228,12 @@ async function printEnvironmentInfo(lando, slug, options) {
224
228
  if (!environmentExists) {
225
229
  throw new _userError.default(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
226
230
  }
227
- const appInfo = await (0, _devEnvironmentLando.landoInfo)(lando, instancePath, !!options.suppressWarnings);
231
+ const environmentData = readEnvironmentData(slug);
232
+ const appInfo = await (0, _devEnvironmentLando.landoInfo)(lando, instancePath, {
233
+ suppressWarnings: !!options.suppressWarnings,
234
+ autologinKey: environmentData.autologinKey
235
+ });
228
236
  if (options.extended) {
229
- const environmentData = readEnvironmentData(slug);
230
237
  appInfo.title = environmentData.wpTitle;
231
238
  appInfo.multisite = !!environmentData.multisite;
232
239
  appInfo.php = environmentData.php.split(':')[1];
@@ -260,8 +267,18 @@ function readEnvironmentData(slug) {
260
267
  debug('Will try to get instance data for environment', slug);
261
268
  const instancePath = getEnvironmentPath(slug);
262
269
  const instanceDataTargetPath = _path.default.join(instancePath, instanceDataFileName);
263
- const instanceDataString = _fs.default.readFileSync(instanceDataTargetPath, 'utf8');
264
- const instanceData = JSON.parse(instanceDataString);
270
+ let instanceDataString;
271
+ let instanceData;
272
+ try {
273
+ instanceDataString = _fs.default.readFileSync(instanceDataTargetPath, 'utf8');
274
+ } catch (err) {
275
+ throw new _userError.default(`There was an error reading file "${instanceDataTargetPath}": ${err.message}.`);
276
+ }
277
+ try {
278
+ instanceData = JSON.parse(instanceDataString);
279
+ } catch (err) {
280
+ throw new _userError.default(`There was an error parsing file "${instanceDataTargetPath}": ${err.message}. You may need to recreate the environment.`);
281
+ }
265
282
 
266
283
  /**
267
284
  ***********************************
@@ -222,6 +222,7 @@ async function landoRebuild(lando, instancePath) {
222
222
  try {
223
223
  debug('Will rebuild lando app on path:', instancePath);
224
224
  const app = await getLandoApplication(lando, instancePath);
225
+ app.events.on('post-uninstall', async () => removeDevToolsVolumes(lando, app));
225
226
  await ensureNoOrphantProxyContainer(lando);
226
227
  await app.rebuild();
227
228
  } finally {
@@ -279,7 +280,7 @@ async function landoDestroy(lando, instancePath) {
279
280
  debug('landoDestroy() took %d ms', duration);
280
281
  }
281
282
  }
282
- async function landoInfo(lando, instancePath, suppressWarnings) {
283
+ async function landoInfo(lando, instancePath, options = {}) {
283
284
  const started = new Date();
284
285
  try {
285
286
  var _app$info$find;
@@ -308,12 +309,15 @@ async function landoInfo(lando, instancePath, suppressWarnings) {
308
309
 
309
310
  // Add login information
310
311
  if (frontEndUrl) {
311
- const loginUrl = `${frontEndUrl}wp-admin/`;
312
+ let loginUrl = `${frontEndUrl}wp-admin/`;
313
+ if (options.autologinKey) {
314
+ loginUrl += `?vip-dev-autologin=${options.autologinKey}`;
315
+ }
312
316
  appInfo['Login URL'] = loginUrl;
313
317
  appInfo['Default username'] = 'vipgo';
314
318
  appInfo['Default password'] = 'password';
315
319
  }
316
- if (!suppressWarnings && hasWarnings) {
320
+ if (!options.suppressWarnings && hasWarnings) {
317
321
  let message = _chalk.default.bold.yellow('The following services have failed health checks:\n');
318
322
  Object.keys(health).forEach(service => {
319
323
  if (!health[service]) {
@@ -455,6 +459,44 @@ async function landoShell(lando, instancePath, service, user, command) {
455
459
  });
456
460
  }
457
461
 
462
+ /**
463
+ * Dev-tools volumes can get stale and is not updated when the new version of dev-tools
464
+ * image is installed. Removing it during rebuild ensures the content is freshly populated
465
+ * on startup.
466
+ *
467
+ * @param {Lando} lando
468
+ * @param {App} app
469
+ */
470
+ async function removeDevToolsVolumes(lando, app) {
471
+ debug('Attempting to removing dev-tools volumes');
472
+ const scanResult = await lando.engine.docker.listVolumes();
473
+ const devToolsVolumeNames = ((scanResult === null || scanResult === void 0 ? void 0 : scanResult.Volumes) || []).map(volume => volume.Name).filter(volumeName => new RegExp(`${app.project}.*devtools`).test(volumeName));
474
+ debug('Will remove', devToolsVolumeNames);
475
+ const removalPromises = devToolsVolumeNames.map(volumeName => removeVolume(lando, volumeName));
476
+ await Promise.all(removalPromises);
477
+ }
478
+
479
+ /**
480
+ * Remove volume
481
+ *
482
+ * @param {Lando} lando
483
+ * @param {string} volumeName
484
+ */
485
+ async function removeVolume(lando, volumeName) {
486
+ debug(`Removing devtools volume ${volumeName}`);
487
+ const devToolsVolume = await lando.engine.docker.getVolume(volumeName);
488
+ if (!devToolsVolume) {
489
+ debug(`Volume ${volumeName} not found`);
490
+ return;
491
+ }
492
+ try {
493
+ await devToolsVolume.remove();
494
+ debug(`${volumeName} volume removed`);
495
+ } catch (err) {
496
+ debug(`Failed to remove volume ${volumeName}`, err);
497
+ }
498
+ }
499
+
458
500
  /**
459
501
  * Sometimes the proxy network seems to disapper leaving only orphant stopped proxy container.
460
502
  * It seems to happen while restarting/powering off computer. This container would then failed
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.aliasUser = aliasUser;
7
+ exports.makeCommandTracker = makeCommandTracker;
7
8
  exports.trackEvent = trackEvent;
8
9
  exports.trackEventWithEnv = trackEventWithEnv;
9
10
  var _index = _interopRequireDefault(require("./analytics/index"));
@@ -77,4 +78,13 @@ async function trackEventWithEnv(appId, envId, eventName, eventProps = {}) {
77
78
  app_id: appId,
78
79
  env_id: envId
79
80
  });
81
+ }
82
+ function makeCommandTracker(command, trackingInfo = {}) {
83
+ const trackerFn = async (type, data = {}) => {
84
+ await trackEvent(`${command}_command_${type}`, {
85
+ ...trackingInfo,
86
+ ...data
87
+ });
88
+ };
89
+ return trackerFn;
80
90
  }
package/dist/lib/utils.js CHANGED
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.getAbsolutePath = getAbsolutePath;
6
7
  exports.makeTempDir = makeTempDir;
7
8
  exports.pollUntil = pollUntil;
8
9
  var _fs = _interopRequireDefault(require("fs"));
@@ -66,4 +67,21 @@ function makeTempDir(prefix = 'vip-cli') {
66
67
  debug(`Removed temporary directory: ${tempDir}`);
67
68
  });
68
69
  return tempDir;
70
+ }
71
+
72
+ /**
73
+ * Get absolute path to a file
74
+ *
75
+ * @param {string} filePath Path to the file
76
+ *
77
+ * @return {string} Absolute path to the file
78
+ */
79
+ function getAbsolutePath(filePath) {
80
+ if (filePath.startsWith('/')) {
81
+ return filePath;
82
+ }
83
+ if (filePath.startsWith('~')) {
84
+ return filePath.replace('~', _os.default.homedir());
85
+ }
86
+ return _path.default.join(process.cwd(), filePath);
69
87
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "2.28.3",
3
+ "version": "2.29.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@automattic/vip",
9
- "version": "2.28.3",
9
+ "version": "2.29.0",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
@@ -34,7 +34,7 @@
34
34
  "opn": "5.5.0",
35
35
  "proxy-from-env": "^1.1.0",
36
36
  "rollbar": "2.22.0",
37
- "semver": "7.5.0",
37
+ "semver": "7.5.1",
38
38
  "shelljs": "^0.8.5",
39
39
  "single-line-log": "1.1.2",
40
40
  "socket.io-client": "^4.5.3",
@@ -75,6 +75,7 @@
75
75
  "vip-dev-env-start": "dist/bin/vip-dev-env-start.js",
76
76
  "vip-dev-env-stop": "dist/bin/vip-dev-env-stop.js",
77
77
  "vip-dev-env-update": "dist/bin/vip-dev-env-update.js",
78
+ "vip-export-sql": "dist/bin/vip-export-sql.js",
78
79
  "vip-import": "dist/bin/vip-import.js",
79
80
  "vip-import-media": "dist/bin/vip-import-media.js",
80
81
  "vip-import-media-abort": "dist/bin/vip-import-media-abort.js",
@@ -107,7 +108,7 @@
107
108
  "dockerode": "^3.3.4",
108
109
  "eslint": "^8.35.0",
109
110
  "eslint-plugin-flowtype": "^8.0.3",
110
- "flow-bin": "^0.205.1",
111
+ "flow-bin": "^0.206.0",
111
112
  "jest": "^29.5.0",
112
113
  "jest-environment-jsdom": "^29.5.0",
113
114
  "nock": "13.3.1",
@@ -170,9 +171,9 @@
170
171
  }
171
172
  },
172
173
  "node_modules/@automattic/eslint-plugin-wpvip": {
173
- "version": "0.5.3",
174
- "resolved": "https://registry.npmjs.org/@automattic/eslint-plugin-wpvip/-/eslint-plugin-wpvip-0.5.3.tgz",
175
- "integrity": "sha512-BPsuN6LqZMpShuuOyyiaxl7DLjlyk41XBs5wqhD1qeULNnWctGkTa8SiX9Ev88NRMtR/evApIAFIDMTQzxXV8Q==",
174
+ "version": "0.5.5",
175
+ "resolved": "https://registry.npmjs.org/@automattic/eslint-plugin-wpvip/-/eslint-plugin-wpvip-0.5.5.tgz",
176
+ "integrity": "sha512-smvN/Ce+d4nt29pYI9aS5+W297zPDLtmT/jZLIrXPPY09YJrXhzLXMmMLHjURGosJBHVMWLzux1TaOXQbaoyHQ==",
176
177
  "dev": true,
177
178
  "dependencies": {
178
179
  "@babel/eslint-parser": "7.21.3",
@@ -2398,9 +2399,9 @@
2398
2399
  }
2399
2400
  },
2400
2401
  "node_modules/@eslint/js": {
2401
- "version": "8.40.0",
2402
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz",
2403
- "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==",
2402
+ "version": "8.41.0",
2403
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz",
2404
+ "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==",
2404
2405
  "dev": true,
2405
2406
  "engines": {
2406
2407
  "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -3308,9 +3309,9 @@
3308
3309
  }
3309
3310
  },
3310
3311
  "node_modules/@pkgr/utils/node_modules/tslib": {
3311
- "version": "2.5.0",
3312
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
3313
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
3312
+ "version": "2.5.2",
3313
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
3314
+ "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==",
3314
3315
  "dev": true
3315
3316
  },
3316
3317
  "node_modules/@rushstack/eslint-patch": {
@@ -6606,15 +6607,15 @@
6606
6607
  }
6607
6608
  },
6608
6609
  "node_modules/eslint": {
6609
- "version": "8.40.0",
6610
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz",
6611
- "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==",
6610
+ "version": "8.41.0",
6611
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz",
6612
+ "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==",
6612
6613
  "dev": true,
6613
6614
  "dependencies": {
6614
6615
  "@eslint-community/eslint-utils": "^4.2.0",
6615
6616
  "@eslint-community/regexpp": "^4.4.0",
6616
6617
  "@eslint/eslintrc": "^2.0.3",
6617
- "@eslint/js": "8.40.0",
6618
+ "@eslint/js": "8.41.0",
6618
6619
  "@humanwhocodes/config-array": "^0.11.8",
6619
6620
  "@humanwhocodes/module-importer": "^1.0.1",
6620
6621
  "@nodelib/fs.walk": "^1.2.8",
@@ -6634,13 +6635,12 @@
6634
6635
  "find-up": "^5.0.0",
6635
6636
  "glob-parent": "^6.0.2",
6636
6637
  "globals": "^13.19.0",
6637
- "grapheme-splitter": "^1.0.4",
6638
+ "graphemer": "^1.4.0",
6638
6639
  "ignore": "^5.2.0",
6639
6640
  "import-fresh": "^3.0.0",
6640
6641
  "imurmurhash": "^0.1.4",
6641
6642
  "is-glob": "^4.0.0",
6642
6643
  "is-path-inside": "^3.0.3",
6643
- "js-sdsl": "^4.1.4",
6644
6644
  "js-yaml": "^4.1.0",
6645
6645
  "json-stable-stringify-without-jsonify": "^1.0.1",
6646
6646
  "levn": "^0.4.1",
@@ -7919,9 +7919,9 @@
7919
7919
  "dev": true
7920
7920
  },
7921
7921
  "node_modules/flow-bin": {
7922
- "version": "0.205.1",
7923
- "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.205.1.tgz",
7924
- "integrity": "sha512-pGQ/ZFr9hnbhRmc+K3K1Ui9BwDivlesNEd2mZbm5pCnxEUvbbj9nXHlTD4s4qO0k+LBKYLMZzQwBVYyRUE380g==",
7922
+ "version": "0.206.0",
7923
+ "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.206.0.tgz",
7924
+ "integrity": "sha512-cZTEs/OEWcbxfvb8BP+Fw0Cep5wrEyEzQHGpXyjVpQXrAraRA5wZUXvTf1C5YHufQaAYY9YkKY5WAr461JvmOA==",
7925
7925
  "dev": true,
7926
7926
  "bin": {
7927
7927
  "flow": "cli.js"
@@ -8370,6 +8370,12 @@
8370
8370
  "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
8371
8371
  "dev": true
8372
8372
  },
8373
+ "node_modules/graphemer": {
8374
+ "version": "1.4.0",
8375
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
8376
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
8377
+ "dev": true
8378
+ },
8373
8379
  "node_modules/graphql": {
8374
8380
  "version": "15.5.1",
8375
8381
  "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.1.tgz",
@@ -8393,9 +8399,9 @@
8393
8399
  }
8394
8400
  },
8395
8401
  "node_modules/graphql-tag/node_modules/tslib": {
8396
- "version": "2.5.0",
8397
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
8398
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
8402
+ "version": "2.5.2",
8403
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
8404
+ "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA=="
8399
8405
  },
8400
8406
  "node_modules/has": {
8401
8407
  "version": "1.0.3",
@@ -10681,16 +10687,6 @@
10681
10687
  "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
10682
10688
  "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
10683
10689
  },
10684
- "node_modules/js-sdsl": {
10685
- "version": "4.2.0",
10686
- "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz",
10687
- "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==",
10688
- "dev": true,
10689
- "funding": {
10690
- "type": "opencollective",
10691
- "url": "https://opencollective.com/js-sdsl"
10692
- }
10693
- },
10694
10690
  "node_modules/js-tokens": {
10695
10691
  "version": "4.0.0",
10696
10692
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -13311,9 +13307,9 @@
13311
13307
  }
13312
13308
  },
13313
13309
  "node_modules/semver": {
13314
- "version": "7.5.0",
13315
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz",
13316
- "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==",
13310
+ "version": "7.5.1",
13311
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
13312
+ "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
13317
13313
  "dependencies": {
13318
13314
  "lru-cache": "^6.0.0"
13319
13315
  },
@@ -13673,9 +13669,9 @@
13673
13669
  }
13674
13670
  },
13675
13671
  "node_modules/socket.io-parser": {
13676
- "version": "4.2.1",
13677
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
13678
- "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
13672
+ "version": "4.2.3",
13673
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
13674
+ "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
13679
13675
  "dependencies": {
13680
13676
  "@socket.io/component-emitter": "~3.1.0",
13681
13677
  "debug": "~4.3.1"
@@ -14135,9 +14131,9 @@
14135
14131
  }
14136
14132
  },
14137
14133
  "node_modules/synckit/node_modules/tslib": {
14138
- "version": "2.5.0",
14139
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
14140
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
14134
+ "version": "2.5.2",
14135
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
14136
+ "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==",
14141
14137
  "dev": true
14142
14138
  },
14143
14139
  "node_modules/table-layout": {
@@ -15495,9 +15491,9 @@
15495
15491
  }
15496
15492
  },
15497
15493
  "@automattic/eslint-plugin-wpvip": {
15498
- "version": "0.5.3",
15499
- "resolved": "https://registry.npmjs.org/@automattic/eslint-plugin-wpvip/-/eslint-plugin-wpvip-0.5.3.tgz",
15500
- "integrity": "sha512-BPsuN6LqZMpShuuOyyiaxl7DLjlyk41XBs5wqhD1qeULNnWctGkTa8SiX9Ev88NRMtR/evApIAFIDMTQzxXV8Q==",
15494
+ "version": "0.5.5",
15495
+ "resolved": "https://registry.npmjs.org/@automattic/eslint-plugin-wpvip/-/eslint-plugin-wpvip-0.5.5.tgz",
15496
+ "integrity": "sha512-smvN/Ce+d4nt29pYI9aS5+W297zPDLtmT/jZLIrXPPY09YJrXhzLXMmMLHjURGosJBHVMWLzux1TaOXQbaoyHQ==",
15501
15497
  "dev": true,
15502
15498
  "requires": {
15503
15499
  "@babel/eslint-parser": "7.21.3",
@@ -17051,9 +17047,9 @@
17051
17047
  }
17052
17048
  },
17053
17049
  "@eslint/js": {
17054
- "version": "8.40.0",
17055
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz",
17056
- "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==",
17050
+ "version": "8.41.0",
17051
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz",
17052
+ "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==",
17057
17053
  "dev": true
17058
17054
  },
17059
17055
  "@graphql-typed-document-node/core": {
@@ -17756,9 +17752,9 @@
17756
17752
  "dev": true
17757
17753
  },
17758
17754
  "tslib": {
17759
- "version": "2.5.0",
17760
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
17761
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
17755
+ "version": "2.5.2",
17756
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
17757
+ "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==",
17762
17758
  "dev": true
17763
17759
  }
17764
17760
  }
@@ -20294,15 +20290,15 @@
20294
20290
  }
20295
20291
  },
20296
20292
  "eslint": {
20297
- "version": "8.40.0",
20298
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz",
20299
- "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==",
20293
+ "version": "8.41.0",
20294
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz",
20295
+ "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==",
20300
20296
  "dev": true,
20301
20297
  "requires": {
20302
20298
  "@eslint-community/eslint-utils": "^4.2.0",
20303
20299
  "@eslint-community/regexpp": "^4.4.0",
20304
20300
  "@eslint/eslintrc": "^2.0.3",
20305
- "@eslint/js": "8.40.0",
20301
+ "@eslint/js": "8.41.0",
20306
20302
  "@humanwhocodes/config-array": "^0.11.8",
20307
20303
  "@humanwhocodes/module-importer": "^1.0.1",
20308
20304
  "@nodelib/fs.walk": "^1.2.8",
@@ -20322,13 +20318,12 @@
20322
20318
  "find-up": "^5.0.0",
20323
20319
  "glob-parent": "^6.0.2",
20324
20320
  "globals": "^13.19.0",
20325
- "grapheme-splitter": "^1.0.4",
20321
+ "graphemer": "^1.4.0",
20326
20322
  "ignore": "^5.2.0",
20327
20323
  "import-fresh": "^3.0.0",
20328
20324
  "imurmurhash": "^0.1.4",
20329
20325
  "is-glob": "^4.0.0",
20330
20326
  "is-path-inside": "^3.0.3",
20331
- "js-sdsl": "^4.1.4",
20332
20327
  "js-yaml": "^4.1.0",
20333
20328
  "json-stable-stringify-without-jsonify": "^1.0.1",
20334
20329
  "levn": "^0.4.1",
@@ -21286,9 +21281,9 @@
21286
21281
  "dev": true
21287
21282
  },
21288
21283
  "flow-bin": {
21289
- "version": "0.205.1",
21290
- "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.205.1.tgz",
21291
- "integrity": "sha512-pGQ/ZFr9hnbhRmc+K3K1Ui9BwDivlesNEd2mZbm5pCnxEUvbbj9nXHlTD4s4qO0k+LBKYLMZzQwBVYyRUE380g==",
21284
+ "version": "0.206.0",
21285
+ "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.206.0.tgz",
21286
+ "integrity": "sha512-cZTEs/OEWcbxfvb8BP+Fw0Cep5wrEyEzQHGpXyjVpQXrAraRA5wZUXvTf1C5YHufQaAYY9YkKY5WAr461JvmOA==",
21292
21287
  "dev": true
21293
21288
  },
21294
21289
  "follow-redirects": {
@@ -21623,6 +21618,12 @@
21623
21618
  "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
21624
21619
  "dev": true
21625
21620
  },
21621
+ "graphemer": {
21622
+ "version": "1.4.0",
21623
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
21624
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
21625
+ "dev": true
21626
+ },
21626
21627
  "graphql": {
21627
21628
  "version": "15.5.1",
21628
21629
  "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.1.tgz",
@@ -21637,9 +21638,9 @@
21637
21638
  },
21638
21639
  "dependencies": {
21639
21640
  "tslib": {
21640
- "version": "2.5.0",
21641
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
21642
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
21641
+ "version": "2.5.2",
21642
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
21643
+ "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA=="
21643
21644
  }
21644
21645
  }
21645
21646
  },
@@ -23305,12 +23306,6 @@
23305
23306
  "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
23306
23307
  "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
23307
23308
  },
23308
- "js-sdsl": {
23309
- "version": "4.2.0",
23310
- "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz",
23311
- "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==",
23312
- "dev": true
23313
- },
23314
23309
  "js-tokens": {
23315
23310
  "version": "4.0.0",
23316
23311
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -25332,9 +25327,9 @@
25332
25327
  }
25333
25328
  },
25334
25329
  "semver": {
25335
- "version": "7.5.0",
25336
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz",
25337
- "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==",
25330
+ "version": "7.5.1",
25331
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
25332
+ "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
25338
25333
  "requires": {
25339
25334
  "lru-cache": "^6.0.0"
25340
25335
  },
@@ -25613,9 +25608,9 @@
25613
25608
  }
25614
25609
  },
25615
25610
  "socket.io-parser": {
25616
- "version": "4.2.1",
25617
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
25618
- "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
25611
+ "version": "4.2.3",
25612
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
25613
+ "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
25619
25614
  "requires": {
25620
25615
  "@socket.io/component-emitter": "~3.1.0",
25621
25616
  "debug": "~4.3.1"
@@ -25974,9 +25969,9 @@
25974
25969
  },
25975
25970
  "dependencies": {
25976
25971
  "tslib": {
25977
- "version": "2.5.0",
25978
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
25979
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
25972
+ "version": "2.5.2",
25973
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
25974
+ "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==",
25980
25975
  "dev": true
25981
25976
  }
25982
25977
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "2.28.3",
3
+ "version": "2.29.0",
4
4
  "description": "The VIP Javascript library & CLI",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -33,6 +33,8 @@
33
33
  "vip-dev-env-start": "dist/bin/vip-dev-env-start.js",
34
34
  "vip-dev-env-stop": "dist/bin/vip-dev-env-stop.js",
35
35
  "vip-dev-env-logs": "dist/bin/vip-dev-env-logs.js",
36
+ "vip-export": "dist/bin/vip-export.js",
37
+ "vip-export-sql": "dist/bin/vip-export-sql.js",
36
38
  "vip-import": "dist/bin/vip-import.js",
37
39
  "vip-import-media": "dist/bin/vip-import-media.js",
38
40
  "vip-import-media-abort": "dist/bin/vip-import-media-abort.js",
@@ -102,7 +104,7 @@
102
104
  "dockerode": "^3.3.4",
103
105
  "eslint": "^8.35.0",
104
106
  "eslint-plugin-flowtype": "^8.0.3",
105
- "flow-bin": "^0.205.1",
107
+ "flow-bin": "^0.206.0",
106
108
  "jest": "^29.5.0",
107
109
  "jest-environment-jsdom": "^29.5.0",
108
110
  "nock": "13.3.1",
@@ -135,7 +137,7 @@
135
137
  "opn": "5.5.0",
136
138
  "proxy-from-env": "^1.1.0",
137
139
  "rollbar": "2.22.0",
138
- "semver": "7.5.0",
140
+ "semver": "7.5.1",
139
141
  "shelljs": "^0.8.5",
140
142
  "single-line-log": "1.1.2",
141
143
  "socket.io-client": "^4.5.3",