@automattic/vip 3.22.0 → 3.22.2

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.
@@ -15,6 +15,9 @@ const examples = [{
15
15
  }, {
16
16
  usage: 'vip @example-app.develop export sql --generate-backup',
17
17
  description: 'Generate a fresh database backup for an environment and download an archived copy of that backup.'
18
+ }, {
19
+ usage: 'vip @example-app.develop export sql --skip-download',
20
+ description: 'Skip downloading the database backup file.'
18
21
  }, {
19
22
  usage: 'vip @example-app.develop export sql --table=wp_posts --table=wp_comments',
20
23
  description: 'Generate and download an archived partial database export file that includes only the wp_posts and wp_comments tables.'
@@ -52,7 +55,7 @@ const appQuery = `
52
55
  module: 'export-sql',
53
56
  requiredArgs: 0,
54
57
  usage: 'vip export sql'
55
- }).option('output', 'Download the file to a specific local directory path with a custom file name.').option('table', 'The name of a table to include in the partial database export. Accepts a string value and can be passed more than once with a different value, or add multiple values in a comma-separated list.').option('site-id', 'The ID of a network site to include in the partial database export. Accepts an integer value and can be passed more than once with a different value, or add multiple values in a comma-separated list.').option('wpcli-command', 'Run a custom WP-CLI command that has logic to retrieve specific data for the partial database export.').option('config-file', 'A local configuration file that specifies the data to include in the partial database export. Accepts a relative or absolute path to the file.', undefined).option('generate-backup', 'Generate a fresh database backup and export an archived copy of that backup.').examples(examples).argv(process.argv, async (arg, {
58
+ }).option('output', 'Download the file to a specific local directory path with a custom file name.').option('table', 'The name of a table to include in the partial database export. Accepts a string value and can be passed more than once with a different value, or add multiple values in a comma-separated list.').option('site-id', 'The ID of a network site to include in the partial database export. Accepts an integer value and can be passed more than once with a different value, or add multiple values in a comma-separated list.').option('wpcli-command', 'Run a custom WP-CLI command that has logic to retrieve specific data for the partial database export.').option('config-file', 'A local configuration file that specifies the data to include in the partial database export. Accepts a relative or absolute path to the file.', undefined).option('generate-backup', 'Generate a fresh database backup and export an archived copy of that backup.').option('skip-download', 'Skip downloading the file.').examples(examples).argv(process.argv, async (arg, {
56
59
  app,
57
60
  env,
58
61
  output,
@@ -60,7 +63,8 @@ const appQuery = `
60
63
  table,
61
64
  siteId,
62
65
  wpcliCommand,
63
- generateBackup
66
+ generateBackup,
67
+ skipDownload
64
68
  }) => {
65
69
  const liveBackupCopyCLIOptions = (0, _liveBackupCopy.parseLiveBackupCopyCLIOptions)(configFile, table, siteId, wpcliCommand);
66
70
  const trackerFn = (0, _tracker.makeCommandTracker)('export_sql', {
@@ -73,7 +77,8 @@ const appQuery = `
73
77
  const exportCommand = new _exportSql.ExportSQLCommand(app, env, {
74
78
  outputFile: output,
75
79
  generateBackup,
76
- liveBackupCopyCLIOptions
80
+ liveBackupCopyCLIOptions,
81
+ skipDownload
77
82
  }, trackerFn);
78
83
  await exportCommand.run();
79
84
  await trackerFn('success');
@@ -52,15 +52,15 @@ const debug = (0, _debug.default)('vip:vip-import-media');
52
52
 
53
53
  // Command examples for the `vip import media` help prompt
54
54
  const examples = [{
55
+ usage: 'vip @example-app.production import media /path/to/uploads.zip',
56
+ description: 'Import the archived file "uploads.zip" from the user\'s local machine to a production environment.'
57
+ }, {
55
58
  usage: 'vip @example-app.production import media https://example.com/uploads.tar.gz',
56
59
  description: 'Import the archived file "uploads.tar.gz" from a publicly accessible URL to a production environment.'
57
- }, {
58
- usage: 'vip @example-app.production import media /path/to/uploads.tar.gz',
59
- description: 'Import a local archive file (e.g. .tar.gz, .tgz, .zip) from your machine into a production environment. The file will be uploaded temporarily and then imported.'
60
60
  },
61
61
  // Format error logs
62
62
  {
63
- usage: 'vip @example-app.production import media https://example.com/uploads.tar.gz --overwriteExistingFiles --exportFileErrorsToJson',
63
+ usage: 'vip @example-app.production import media https://example.com/uploads.tgz --overwriteExistingFiles --exportFileErrorsToJson',
64
64
  description: 'Overwrite existing files with the imported files if they have the same file path and name, and format the error log for the import in JSON.'
65
65
  },
66
66
  // `media status` subcommand
@@ -193,6 +193,7 @@ class ExportSQLCommand {
193
193
  track;
194
194
  liveBackupCopyCLIOptions;
195
195
  showMyDumperWarning;
196
+ skipDownload;
196
197
 
197
198
  /**
198
199
  * Creates an instance of SQLExportCommand
@@ -214,12 +215,12 @@ class ExportSQLCommand {
214
215
  }, {
215
216
  id: this.steps.CREATE,
216
217
  name: 'Creating backup copy'
217
- }, {
218
- id: this.steps.CONFIRM_ENOUGH_STORAGE,
219
- name: "Checking if there's enough storage"
220
218
  }, {
221
219
  id: this.steps.DOWNLOAD_LINK,
222
220
  name: 'Requesting download link'
221
+ }, {
222
+ id: this.steps.CONFIRM_ENOUGH_STORAGE,
223
+ name: "Checking if there's enough storage"
223
224
  }, {
224
225
  id: this.steps.DOWNLOAD,
225
226
  name: 'Downloading file'
@@ -227,6 +228,7 @@ class ExportSQLCommand {
227
228
  this.track = trackerFn;
228
229
  this.liveBackupCopyCLIOptions = options.liveBackupCopyCLIOptions;
229
230
  this.showMyDumperWarning = options.showMyDumperWarning === undefined ? true : options.showMyDumperWarning;
231
+ this.skipDownload = options.skipDownload || false;
230
232
  }
231
233
 
232
234
  /**
@@ -348,6 +350,15 @@ class ExportSQLCommand {
348
350
  }
349
351
  size = Number(bytesWrittenMeta.value);
350
352
  }
353
+ const downloadURLString = `\n${_chalk.default.green('Download URL')}:\n${url}\n\n`;
354
+ if (this.skipDownload) {
355
+ this.progressTracker.stepSkipped(this.steps.CONFIRM_ENOUGH_STORAGE);
356
+ this.progressTracker.stepSkipped(this.steps.DOWNLOAD);
357
+ this.progressTracker.print();
358
+ this.progressTracker.stopPrinting();
359
+ console.log(downloadURLString);
360
+ return;
361
+ }
351
362
  const storageConfirmed = await this.progressTracker.handleContinuePrompt(async setPromptShown => {
352
363
  const status = await this.confirmEnoughStorage(Number(size));
353
364
  if (status.isPromptShown) {
@@ -401,19 +412,15 @@ class ExportSQLCommand {
401
412
  });
402
413
  exit.withError(`No backup found for site ${this.app.name}`);
403
414
  }
404
- if (!this.generateBackup) {
405
- console.log(`${(0, _format.getGlyphForStatus)('success')} Latest backup found with timestamp ${latestBackup.createdAt}`);
406
- } else {
407
- console.log(`${(0, _format.getGlyphForStatus)('success')} Backup created with timestamp ${latestBackup.createdAt}`);
408
- }
415
+ const prepareAdditionalInfo = [];
409
416
  const showMyDumperWarning = this.showMyDumperWarning && (latestBackup.sqlDumpTool ?? envSqlDumpTool) === 'mydumper';
410
417
  if (showMyDumperWarning) {
411
- console.warn(_chalk.default.yellow.bold('WARNING:'), _chalk.default.yellow('This is a large or complex database. The backup file for this database is generated with MyDumper. ' + 'The file can only be loaded with MyLoader. ' + 'For more information: https://github.com/mydumper/mydumper'));
418
+ prepareAdditionalInfo.push(`${_chalk.default.yellow.bold('WARNING:')} This is a large or complex database. The backup file for this database is generated with MyDumper. The file can only be loaded with MyLoader. For more information: https://github.com/mydumper/mydumper`);
412
419
  }
413
420
  if (await this.getExportJob()) {
414
- console.log(`Attaching to an existing export for the backup with timestamp ${latestBackup.createdAt}`);
421
+ prepareAdditionalInfo.push(`Attaching to an existing export for the backup with timestamp ${latestBackup.createdAt}`);
415
422
  } else {
416
- console.log(`Exporting database backup with timestamp ${latestBackup.createdAt}`);
423
+ prepareAdditionalInfo.push(`Exporting database backup with timestamp ${latestBackup.createdAt}`);
417
424
  try {
418
425
  await createExportJob(this.app.id, this.env.id, latestBackup.id);
419
426
  } catch (err) {
@@ -437,11 +444,11 @@ class ExportSQLCommand {
437
444
  }
438
445
  }
439
446
  await (0, _utils.pollUntil)(this.getExportJob.bind(this), EXPORT_SQL_PROGRESS_POLL_INTERVAL, this.isPrepared.bind(this));
440
- this.progressTracker.stepSuccess(this.steps.PREPARE);
447
+ this.progressTracker.stepSuccess(this.steps.PREPARE, prepareAdditionalInfo);
441
448
  await (0, _utils.pollUntil)(this.getExportJob.bind(this), EXPORT_SQL_PROGRESS_POLL_INTERVAL, this.isCreated.bind(this));
442
449
  this.progressTracker.stepSuccess(this.steps.CREATE);
443
450
  const url = await generateDownloadLink(this.app.id, this.env.id, latestBackup.id);
444
- this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK);
451
+ this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK, [url]);
445
452
  return url;
446
453
  }
447
454
  async generateLiveBackupCopy() {
@@ -466,7 +473,7 @@ class ExportSQLCommand {
466
473
  copyId
467
474
  });
468
475
  this.progressTracker.stepSuccess(this.steps.CREATE);
469
- this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK);
476
+ this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK, [result.url]);
470
477
  return result;
471
478
  } catch (err) {
472
479
  const message = err instanceof Error ? err.message : 'Unknown error';
@@ -128,17 +128,17 @@ class ProgressTracker {
128
128
  status
129
129
  }) => status === StepStatus.RUNNING);
130
130
  }
131
- stepRunning(stepId) {
132
- this.setStatusForStepId(stepId, StepStatus.RUNNING);
131
+ stepRunning(stepId, additionalInfo = []) {
132
+ this.setStatusForStepId(stepId, StepStatus.RUNNING, additionalInfo);
133
133
  }
134
- stepFailed(stepId) {
135
- this.setStatusForStepId(stepId, StepStatus.FAILED);
134
+ stepFailed(stepId, additionalInfo = []) {
135
+ this.setStatusForStepId(stepId, StepStatus.FAILED, additionalInfo);
136
136
  }
137
- stepSkipped(stepId) {
138
- this.setStatusForStepId(stepId, StepStatus.SKIPPED);
137
+ stepSkipped(stepId, additionalInfo = []) {
138
+ this.setStatusForStepId(stepId, StepStatus.SKIPPED, additionalInfo);
139
139
  }
140
- stepSuccess(stepId) {
141
- this.setStatusForStepId(stepId, StepStatus.SUCCESS);
140
+ stepSuccess(stepId, additionalInfo = []) {
141
+ this.setStatusForStepId(stepId, StepStatus.SUCCESS, additionalInfo);
142
142
  // The stepSuccess helper automatically sets the next step to "running"
143
143
  const nextStep = this.getNextStep();
144
144
  if (nextStep) {
@@ -150,7 +150,7 @@ class ProgressTracker {
150
150
  status
151
151
  }) => status === StepStatus.SUCCESS);
152
152
  }
153
- setStatusForStepId(stepId, status) {
153
+ setStatusForStepId(stepId, status, additionalInfo = []) {
154
154
  const step = this.stepsFromCaller.get(stepId);
155
155
  if (!step) {
156
156
  // Only allowed to update existing steps with this method
@@ -164,7 +164,8 @@ class ProgressTracker {
164
164
  }
165
165
  this.stepsFromCaller.set(stepId, {
166
166
  ...step,
167
- status
167
+ status,
168
+ additionalInfo: Array.isArray(additionalInfo) ? additionalInfo : [additionalInfo]
168
169
  });
169
170
  }
170
171
  startPrinting(prePrintCallback = () => {}) {
@@ -225,7 +226,8 @@ class ProgressTracker {
225
226
  id,
226
227
  percentage,
227
228
  status,
228
- progress
229
+ progress,
230
+ additionalInfo
229
231
  }, stepNumber) => {
230
232
  if (stepNumber < this.displayFromStep) {
231
233
  return accumulator;
@@ -239,6 +241,10 @@ class ProgressTracker {
239
241
  } else if (progress) {
240
242
  suffix = progress;
241
243
  }
244
+ if (additionalInfo && additionalInfo.length > 0) {
245
+ suffix += _nodeOs.EOL;
246
+ suffix += additionalInfo.map(stepInfo => ` - ${stepInfo}`).join(_nodeOs.EOL);
247
+ }
242
248
  return `${accumulator}${statusIcon} ${name} ${suffix}\n`;
243
249
  }, '');
244
250
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "3.22.0",
3
+ "version": "3.22.2",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@automattic/vip",
9
- "version": "3.22.0",
9
+ "version": "3.22.2",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
@@ -29,7 +29,7 @@
29
29
  "https-proxy-agent": "^7.0.6",
30
30
  "js-yaml": "^4.1.0",
31
31
  "jwt-decode": "4.0.0",
32
- "lando": "github:automattic/lando-cli#63669a4a2e16ab9a9683aaa3bcc5bcb2b775d831",
32
+ "lando": "github:automattic/lando-cli#603e9dc490d402a07816560f07b6bfecfc902c5a",
33
33
  "node-fetch": "^3.3.2",
34
34
  "node-stream-zip": "1.15.0",
35
35
  "open": "^11.0.0",
@@ -11061,8 +11061,8 @@
11061
11061
  "node_modules/lando": {
11062
11062
  "name": "@lando/cli",
11063
11063
  "version": "3.6.5",
11064
- "resolved": "git+ssh://git@github.com/automattic/lando-cli.git#63669a4a2e16ab9a9683aaa3bcc5bcb2b775d831",
11065
- "integrity": "sha512-fuPEUyF+garR1TeWHIU4XdHh4yPZDD5YCnI6QyZ6DA8h8ucKl6fHwMnoRs1yxtT/dyu7mhqiDm14dPdks6TWfw==",
11064
+ "resolved": "git+ssh://git@github.com/automattic/lando-cli.git#603e9dc490d402a07816560f07b6bfecfc902c5a",
11065
+ "integrity": "sha512-ql/EFlUe8y8tfgMmeYL2rECgbfDFQ3FiU1JpKmTklhJyast/h0MVYW3oq5tn/pLJjs+r1MQDiDD1I0iCC+3lwA==",
11066
11066
  "license": "GPL-3.0",
11067
11067
  "dependencies": {
11068
11068
  "axios": "^1.12.1",
@@ -11072,7 +11072,7 @@
11072
11072
  "copy-dir": "^1.3.0",
11073
11073
  "dockerode": "^4.0.0",
11074
11074
  "figlet": "^1.8.0",
11075
- "glob": "^10.4.0",
11075
+ "glob": "^10.5.0",
11076
11076
  "js-yaml": "^4.1.0",
11077
11077
  "jsonfile": "^6.1.0",
11078
11078
  "lodash": "^4.17.21",
@@ -21977,9 +21977,9 @@
21977
21977
  "integrity": "sha512-tPhhoGUiEiU/WXR4rt8klIoLdnTtyu+9jVKHd/wauEjYud32jyn63mzKWQweaQrHWxBQtYoVtdcEnYX1LosnFQ=="
21978
21978
  },
21979
21979
  "lando": {
21980
- "version": "git+ssh://git@github.com/automattic/lando-cli.git#63669a4a2e16ab9a9683aaa3bcc5bcb2b775d831",
21981
- "integrity": "sha512-fuPEUyF+garR1TeWHIU4XdHh4yPZDD5YCnI6QyZ6DA8h8ucKl6fHwMnoRs1yxtT/dyu7mhqiDm14dPdks6TWfw==",
21982
- "from": "lando@github:automattic/lando-cli#63669a4a2e16ab9a9683aaa3bcc5bcb2b775d831",
21980
+ "version": "git+ssh://git@github.com/automattic/lando-cli.git#603e9dc490d402a07816560f07b6bfecfc902c5a",
21981
+ "integrity": "sha512-ql/EFlUe8y8tfgMmeYL2rECgbfDFQ3FiU1JpKmTklhJyast/h0MVYW3oq5tn/pLJjs+r1MQDiDD1I0iCC+3lwA==",
21982
+ "from": "lando@github:automattic/lando-cli#603e9dc490d402a07816560f07b6bfecfc902c5a",
21983
21983
  "requires": {
21984
21984
  "axios": "^1.12.1",
21985
21985
  "bluebird": "^3.4.1",
@@ -21988,7 +21988,7 @@
21988
21988
  "copy-dir": "^1.3.0",
21989
21989
  "dockerode": "^4.0.0",
21990
21990
  "figlet": "^1.8.0",
21991
- "glob": "^10.4.0",
21991
+ "glob": "^10.5.0",
21992
21992
  "js-yaml": "^4.1.0",
21993
21993
  "jsonfile": "^6.1.0",
21994
21994
  "lodash": "^4.17.21",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "3.22.0",
3
+ "version": "3.22.2",
4
4
  "description": "The VIP Javascript library & CLI",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -158,7 +158,7 @@
158
158
  "https-proxy-agent": "^7.0.6",
159
159
  "js-yaml": "^4.1.0",
160
160
  "jwt-decode": "4.0.0",
161
- "lando": "github:automattic/lando-cli#63669a4a2e16ab9a9683aaa3bcc5bcb2b775d831",
161
+ "lando": "github:automattic/lando-cli#603e9dc490d402a07816560f07b6bfecfc902c5a",
162
162
  "node-fetch": "^3.3.2",
163
163
  "node-stream-zip": "1.15.0",
164
164
  "open": "^11.0.0",