@automattic/vip 2.31.1-dev → 2.31.1-dev3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/.editorconfig +11 -0
  2. package/.prettierignore +6 -0
  3. package/CONTRIBUTING.md +20 -19
  4. package/dist/bin/vip-app-list.js +12 -10
  5. package/dist/bin/vip-dev-env-start.js +4 -1
  6. package/dist/bin/vip-dev-env-sync-sql.js +1 -1
  7. package/dist/bin/vip-export-sql.js +3 -2
  8. package/dist/bin/vip-import-media-abort.js +3 -3
  9. package/dist/bin/vip-import-media.js +3 -3
  10. package/dist/bin/vip-import-sql.js +2 -1
  11. package/dist/bin/vip-sync.js +27 -13
  12. package/dist/bin/vip-validate-preflight.js +16 -14
  13. package/dist/bin/vip-wp.js +9 -9
  14. package/dist/commands/backup-db.js +30 -26
  15. package/dist/commands/export-sql.js +2 -3
  16. package/dist/lib/api/cache-purge.js +2 -10
  17. package/dist/lib/app-logs/app-logs.js +10 -4
  18. package/dist/lib/cli/format.js +2 -2
  19. package/dist/lib/config/software.js +10 -9
  20. package/dist/lib/constants/dev-environment.js +3 -6
  21. package/dist/lib/dev-environment/dev-environment-cli.js +3 -3
  22. package/dist/lib/dev-environment/dev-environment-core.js +52 -41
  23. package/dist/lib/dev-environment/dev-environment-lando.js +3 -1
  24. package/dist/lib/envvar/api-delete.js +2 -11
  25. package/dist/lib/envvar/api-get-all.js +3 -10
  26. package/dist/lib/envvar/api-list.js +3 -10
  27. package/dist/lib/envvar/api-set.js +2 -12
  28. package/dist/lib/media-import/status.js +18 -18
  29. package/dist/lib/validations/site-type.js +1 -1
  30. package/dist/lib/validations/sql.js +2 -1
  31. package/dist/lib/vip-import-validate-files.js +1 -0
  32. package/helpers/check-version.js +7 -5
  33. package/helpers/prepublishOnly.js +90 -0
  34. package/npm-shrinkwrap.json +238 -3936
  35. package/package.json +12 -12
  36. package/tsconfig.json +5 -9
  37. package/automattic-vip-2.31.1-dev.tgz +0 -0
package/.editorconfig ADDED
@@ -0,0 +1,11 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_style = tab
7
+ insert_final_newline = true
8
+ trim_trailing_whitespace = true
9
+
10
+ [*.json,*.yaml,*.yml]
11
+ indent_style = space
@@ -0,0 +1,6 @@
1
+ *.generated.d.ts
2
+ /CHANGELOG.md
3
+ /__fixtures__/
4
+ /dist/
5
+ /flow-typed/
6
+ /src/graphqlTypes.d.ts
package/CONTRIBUTING.md CHANGED
@@ -35,35 +35,38 @@ Who doesn't like a good console.log for debugging?
35
35
  Well, sometimes it's insufficient, luckily it's not too complicated to use a debugger.
36
36
 
37
37
  1. First, make sure to run the `npm run build:watch`, this will generate source maps
38
- 2. Run the command you want via `node --inspect`, like so: `node --inspect ./dist/bin/vip-dev-env-import-sql.js`
38
+ 2. Run the command you want via `node --inspect`, like so: `node --inspect ./dist/bin/vip-dev-env-import-sql.js`
39
39
  3. Note the port the debugger is listening on:
40
+
40
41
  ```
41
42
  Debugger listening on ws://127.0.0.1:9229/db6c03e9-2585-4a08-a1c6-1fee0295c9ff
42
43
  For help, see: https://nodejs.org/en/docs/inspector
43
44
  ```
45
+
44
46
  4. In your editor of choice attach to the debugger. For VSCode: Hit 'Run and Debug' panel, hit the "gear" icon (open launch.json), make your `Attach` configuration entry to look like so:
45
- Make sure the `port` matches the port from step 3, and the `runtimeExecutable` matches the exact `node` executable you ran. If you use a version manager like `nvm`, its especially important to check this.
47
+ Make sure the `port` matches the port from step 3, and the `runtimeExecutable` matches the exact `node` executable you ran. If you use a version manager like `nvm`, its especially important to check this.
46
48
 
47
49
  ```json
48
- {
49
- "name": "Attach",
50
- "port": 9229,
51
- "request": "attach",
52
- "skipFiles": ["<node_internals>/**"],
53
- "type": "node",
54
- "runtimeExecutable": "/Users/user/.nvm/versions/node/v14.18.2/bin/node"
55
- }
50
+ {
51
+ "name": "Attach",
52
+ "port": 9229,
53
+ "request": "attach",
54
+ "skipFiles": [ "<node_internals>/**" ],
55
+ "type": "node",
56
+ "runtimeExecutable": "/Users/user/.nvm/versions/node/v14.18.2/bin/node"
57
+ }
56
58
  ```
57
59
 
58
60
  5. Set your breakpoints and whatnot, hit the play button.
59
61
  6. Confirm that you attached the debugger to continue command execution
60
62
  7. Squash them bugs 🐛🔨.
61
63
  8. [Optional but recommended] Pay it forward and implement a similar approach to other internal/external tooling.
64
+
62
65
  ### Adding commands
63
66
 
64
- * New command names should use the singular form (e.g. site vs sites).
65
- * Add new commands to `package.json#bin`.
66
- * Run `npm link` so that `arg` knows how to spawn the command locally. (Skipping this step will result in `Error: spawn vip-command ENOENT`.)
67
+ - New command names should use the singular form (e.g. site vs sites).
68
+ - Add new commands to `package.json#bin`.
69
+ - Run `npm link` so that `arg` knows how to spawn the command locally. (Skipping this step will result in `Error: spawn vip-command ENOENT`.)
67
70
 
68
71
  ### Adding libraries
69
72
 
@@ -83,13 +86,14 @@ Our release flow for VIP CLI follows this pattern:
83
86
  - Finally, release your changes as a new minor or major NPM version. Ping in the #vip-platform channel to notify folks of a new release, but please feel free to release your changes without any blockers from the team. Any team member that is part of the Automattic NPM organization can release a new version; if you aren't a member, generic credentials are available in the Secret Store.
84
87
 
85
88
  ### Changelogs
89
+
86
90
  Changelogs allow customers to keep up with all the changes happening across our VIP Platform. Changelogs for VIP CLI are posted to the [VIP Cloud Changelog P2](https://wpvipchangelog.wordpress.com/), along with the repository’s `README.md`.
87
91
 
88
92
  ## Releasing / Publishing
89
93
 
90
94
  ### Pre-publish Checks
91
95
 
92
- We use [`publish-please`](https://github.com/inikulin/publish-please) for some pre-publish confidence checks to avoid common mistakes.
96
+ We use a custom pre-publish [script](https://github.com/Automattic/vip/blob/trunk/hellpers/prepublishOnly.js) that performs some confidence checks to avoid common mistakes.
93
97
 
94
98
  Further checks can be added to this flow as needed.
95
99
 
@@ -126,7 +130,7 @@ Then, let's publish:
126
130
  1. Push the tag to GitHub (`git push --tags`)
127
131
  1. Push the trunk branch `git push`
128
132
  1. Make sure you're part of the Automattic organization in npm
129
- 1. Publish the release to npm (`npm run publish-please --access public`) the script will do some extra checks (npm version, branch, etc) to ensure everything is correct. If all looks good, proceed.
133
+ 1. Publish the release to npm (`npm publish --access public`) the script will do some extra checks (node version, branch, etc) to ensure everything is correct. If all looks good, the new version will be published and you can proceed.
130
134
  1. Edit [the release on GitHub](https://github.com/Automattic/vip/releases) to include a description of the changes and publish (this can just copy the details from the changelog).
131
135
  1. Push `trunk` changes (mostly the version bump) to `develop` (`git checkout develop && git merge trunk` )
132
136
 
@@ -139,10 +143,7 @@ Sometimes, we want to release a version we can test before releasing it to the p
139
143
  In order to do that, please follow this:
140
144
 
141
145
  1. Manually change the version in `package.json` and `package-lock.json` to a dev version. Example: `1.4.0-dev1`
142
- 2. Go to publish-please's config in `.publishrc`
143
- 3. Change the `publishTag` to `next` and `gitTag` to `false` (publish-please will expect the latest commit to have a git tag, but we don't want it in this case)
144
- 4. Commit your changes to `trunk`
145
- 5. Run `npm run publish-please`
146
+ 1. Run `npm publish --tag next` (When `--tag` is specified, we bypass the usual branch protection that doesn't allow you to publish form a brunch other than `trunk`).
146
147
 
147
148
  You can repeat this with every new version until you're happy with your version and ready to a public release. We currently don't support multiple branches for multiple versions. When it's the case, this process needs to be done for every version in every branch.
148
149
 
@@ -21,17 +21,19 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
21
21
  try {
22
22
  response = await api.query({
23
23
  // $FlowFixMe: gql template is not supported by flow
24
- query: (0, _graphqlTag.default)`query Apps( $first: Int, $after: String ) {
25
- apps( first: $first, after: $after ) {
26
- total,
27
- nextCursor
28
- edges {
29
- id,
30
- name,
31
- repo
32
- }
24
+ query: (0, _graphqlTag.default)`
25
+ query Apps($first: Int, $after: String) {
26
+ apps(first: $first, after: $after) {
27
+ total
28
+ nextCursor
29
+ edges {
30
+ id
31
+ name
32
+ repo
33
33
  }
34
- }`,
34
+ }
35
+ }
36
+ `,
35
37
  variables: {
36
38
  first: 100,
37
39
  after: null // TODO make dynamic
@@ -30,8 +30,11 @@ const dockerWindowsPathCmd = 'wsl -d docker-desktop bash -c "sysctl -w vm.max_ma
30
30
  const examples = [{
31
31
  usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start`,
32
32
  description: 'Starts a local dev environment'
33
+ }, {
34
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start --vscode`,
35
+ description: 'Start a local environment and generate a Workspace file for developing in Visual Studio Code'
33
36
  }];
34
- (0, _command.default)().option('slug', 'Custom name of the dev environment').option('skip-rebuild', 'Only start stopped services').option(['w', 'skip-wp-versions-check'], 'Skip propting for wordpress update if non latest').option('vscode', 'Open environment workspace in VSCode').examples(examples).argv(process.argv, async (arg, opt) => {
37
+ (0, _command.default)().option('slug', 'Custom name of the dev environment').option('skip-rebuild', 'Only start stopped services').option(['w', 'skip-wp-versions-check'], 'Skip prompt to update WordPress version if not on latest').option('vscode', 'Generate a Visual Studio Code Workspace file').examples(examples).argv(process.argv, async (arg, opt) => {
35
38
  const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
36
39
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
37
40
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
@@ -24,7 +24,7 @@ var _tracker = require("../lib/tracker");
24
24
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
25
  const examples = [{
26
26
  usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} sync sql @my-test.develop --slug=my_site`,
27
- description: 'Syncs with the `my-test` site\'s `develop` environment database into `my_site`'
27
+ description: "Syncs with the `my-test` site's `develop` environment database into `my_site`"
28
28
  }];
29
29
  const appQuery = `
30
30
  id,
@@ -46,7 +46,7 @@ const appQuery = `
46
46
  module: 'export-sql',
47
47
  requiredArgs: 0,
48
48
  usage: 'vip export sql'
49
- }).option('output', 'Specify the location where you want to save the export file').option('generate-backup', 'Generate a new backup instead of using the available ones').examples(examples).argv(process.argv, async (arg, {
49
+ }).option('output', 'Specify the location where you want to save the export file').option('generate-backup', 'Exports a freshly created database backup instead of using the latest existing one').examples(examples).argv(process.argv, async (arg, {
50
50
  app,
51
51
  env,
52
52
  output,
@@ -54,7 +54,8 @@ const appQuery = `
54
54
  }) => {
55
55
  const trackerFn = (0, _tracker.makeCommandTracker)('export_sql', {
56
56
  app: app.id,
57
- env: env.uniqueLabel
57
+ env: env.uniqueLabel,
58
+ generate_backup: generateBackup
58
59
  });
59
60
  await trackerFn('execute');
60
61
  const exportCommand = new _exportSql.ExportSQLCommand(app, env, {
@@ -41,8 +41,8 @@ const appQuery = `
41
41
  }
42
42
  `;
43
43
  const ABORT_IMPORT_MUTATION = (0, _graphqlTag.default)`
44
- mutation AbortMediaImport( $input: AppEnvironmentAbortMediaImportInput ) {
45
- abortMediaImport( input: $input ) {
44
+ mutation AbortMediaImport($input: AppEnvironmentAbortMediaImportInput) {
45
+ abortMediaImport(input: $input) {
46
46
  applicationId
47
47
  environmentId
48
48
  mediaImportStatusChange {
@@ -60,7 +60,7 @@ const ABORT_IMPORT_MUTATION = (0, _graphqlTag.default)`
60
60
  envContext: true,
61
61
  requiredArgs: 0,
62
62
  requireConfirm: `
63
- ${_chalk.default.red.bold('By running this command, the Media Import running on your App will stop and can\'t be resumed.')}
63
+ ${_chalk.default.red.bold("By running this command, the Media Import running on your App will stop and can't be resumed.")}
64
64
  ${_chalk.default.red.bold('Are you sure you want to abort this Media Import?')}
65
65
  `
66
66
  }).argv(process.argv, async (arg, {
@@ -38,8 +38,8 @@ const appQuery = `
38
38
  }
39
39
  `;
40
40
  const START_IMPORT_MUTATION = (0, _graphqlTag.default)`
41
- mutation StartMediaImport( $input: AppEnvironmentStartMediaImportInput ) {
42
- startMediaImport( input: $input ) {
41
+ mutation StartMediaImport($input: AppEnvironmentStartMediaImportInput) {
42
+ startMediaImport(input: $input) {
43
43
  applicationId
44
44
  environmentId
45
45
  mediaImportStatus {
@@ -83,7 +83,7 @@ function isSupportedUrl(urlToTest) {
83
83
  module: 'import-media',
84
84
  requiredArgs: 1,
85
85
  requireConfirm: `
86
- ${_chalk.default.red.bold('NOTE: If the provided archive\'s directory structure contains an `uploads/` directory,')}
86
+ ${_chalk.default.red.bold("NOTE: If the provided archive's directory structure contains an `uploads/` directory,")}
87
87
  ${_chalk.default.red.bold('only the files present inside that directory will be imported and the rest will be ignored.')}
88
88
  ${_chalk.default.red.bold('If no `uploads/` directory is found, all files will be imported, as is.')}
89
89
 
@@ -296,7 +296,8 @@ const displayPlaybook = ({
296
296
  if (wpSite.id === 1) {
297
297
  siteRegex = /^wp_[a-z]+/i;
298
298
  } else {
299
- siteRegex = new RegExp(`^wp_${wpSite.id}_[a-z]+`, 'i');
299
+ // eslint-disable-next-line security/detect-non-literal-regexp
300
+ siteRegex = new RegExp(`^wp_${parseInt(wpSite.id, 10)}_[a-z]+`, 'i');
300
301
  }
301
302
  const tableNamesInGroup = tableNames.filter(name => siteRegex.test(name));
302
303
  return {
@@ -35,14 +35,14 @@ const appQuery = `id,name,environments{
35
35
  await api.mutate({
36
36
  // $FlowFixMe: gql template is not supported by flow
37
37
  mutation: (0, _graphqlTag.default)`
38
- mutation SyncEnvironmentMutation($input: AppEnvironmentSyncInput){
39
- syncEnvironment(input: $input){
40
- environment{
41
- id
42
- }
43
- }
38
+ mutation SyncEnvironmentMutation($input: AppEnvironmentSyncInput) {
39
+ syncEnvironment(input: $input) {
40
+ environment {
41
+ id
44
42
  }
45
- `,
43
+ }
44
+ }
45
+ `,
46
46
  variables: {
47
47
  input: {
48
48
  id: opts.app.id,
@@ -106,15 +106,29 @@ const appQuery = `id,name,environments{
106
106
  // The rest of the iterations are just for moving the spinner
107
107
  api.query({
108
108
  // $FlowFixMe: gql template is not supported by flow
109
- query: (0, _graphqlTag.default)`query App( $id: Int, $sync: Int ) {
110
- app( id: $id ){
111
- id,name,environments{
112
- id,name,defaultDomain,branch,datacenter,syncProgress( sync: $sync ){
113
- status,sync,steps{name,status}
109
+ query: (0, _graphqlTag.default)`
110
+ query App($id: Int, $sync: Int) {
111
+ app(id: $id) {
112
+ id
113
+ name
114
+ environments {
115
+ id
116
+ name
117
+ defaultDomain
118
+ branch
119
+ datacenter
120
+ syncProgress(sync: $sync) {
121
+ status
122
+ sync
123
+ steps {
124
+ name
125
+ status
126
+ }
114
127
  }
115
128
  }
116
129
  }
117
- }`,
130
+ }
131
+ `,
118
132
  fetchPolicy: 'network-only',
119
133
  variables: {
120
134
  id: opts.app.id,
@@ -68,19 +68,20 @@ async function getBuildConfiguration(application, environment) {
68
68
  // Disable the global GraphQL error handling, so we can catch Unauthorized errors and recommend next steps.
69
69
  (0, _api.disableGlobalGraphQLErrorHandling)();
70
70
  const buildConfigQuery = (0, _graphqlTag.default)`
71
- query BuildConfig( $appId: Int, $envId: Int ) {
72
- app(id: $appId) {
73
- environments(id: $envId) {
74
- id,
75
- buildConfiguration {
76
- buildType
77
- nodeBuildDockerEnv,
78
- nodeJSVersion,
79
- npmToken,
80
- }
81
- }
82
- }
83
- }`;
71
+ query BuildConfig($appId: Int, $envId: Int) {
72
+ app(id: $appId) {
73
+ environments(id: $envId) {
74
+ id
75
+ buildConfiguration {
76
+ buildType
77
+ nodeBuildDockerEnv
78
+ nodeJSVersion
79
+ npmToken
80
+ }
81
+ }
82
+ }
83
+ }
84
+ `;
84
85
  try {
85
86
  const result = await api.query({
86
87
  query: buildConfigQuery,
@@ -122,7 +123,7 @@ async function vipValidatePreflightCommand(arg, opt) {
122
123
  };
123
124
  await (0, _tracker.trackEvent)('validate_preflight_command_execute', baseTrackingParams);
124
125
  logToConsole(' /\\ /\\__ _ _ __ _ __ ___ ___ _ __ (_) __ _ ');
125
- logToConsole(' / /_/ / _` | \'__| \'_ ` _ \\ / _ \\| \'_ \\| |/ _` |');
126
+ logToConsole(" / /_/ / _` | '__| '_ ` _ \\ / _ \\| '_ \\| |/ _` |");
126
127
  logToConsole('/ __ / (_| | | | | | | | | (_) | | | | | (_| |');
127
128
  logToConsole('\\/ /_/ \\__,_|_| |_| |_| |_|\\___/|_| |_|_|\\__,_|');
128
129
  logToConsole('VIP Harmonia - Application testing made easy\n');
@@ -155,6 +156,7 @@ async function vipValidatePreflightCommand(arg, opt) {
155
156
  const packageJSONfile = _path.default.resolve(opt.path, 'package.json');
156
157
  let packageJSON;
157
158
  try {
159
+ // eslint-disable-next-line security/detect-non-literal-require
158
160
  packageJSON = require(packageJSONfile);
159
161
  siteOptions.setPackageJSON(packageJSON);
160
162
  } catch (error) {
@@ -100,15 +100,15 @@ const getTokenForCommand = async (appId, envId, command) => {
100
100
  return api.mutate({
101
101
  // $FlowFixMe: gql template is not supported by flow
102
102
  mutation: (0, _graphqlTag.default)`
103
- mutation TriggerWPCLICommandMutation($input: AppEnvironmentTriggerWPCLICommandInput ){
104
- triggerWPCLICommandOnAppEnvironment( input: $input ) {
105
- inputToken
106
- command {
107
- guid
108
- }
103
+ mutation TriggerWPCLICommandMutation($input: AppEnvironmentTriggerWPCLICommandInput) {
104
+ triggerWPCLICommandOnAppEnvironment(input: $input) {
105
+ inputToken
106
+ command {
107
+ guid
109
108
  }
110
109
  }
111
- `,
110
+ }
111
+ `,
112
112
  variables: {
113
113
  input: {
114
114
  id: appId,
@@ -125,8 +125,8 @@ const cancelCommand = async guid => {
125
125
  return api.mutate({
126
126
  // $FlowFixMe: gql template is not supported by flow
127
127
  mutation: (0, _graphqlTag.default)`
128
- mutation cancelWPCLICommand($input: CancelWPCLICommandInput ){
129
- cancelWPCLICommand( input: $input ) {
128
+ mutation cancelWPCLICommand($input: CancelWPCLICommandInput) {
129
+ cancelWPCLICommand(input: $input) {
130
130
  command {
131
131
  id
132
132
  }
@@ -34,6 +34,8 @@ const CREATE_DB_BACKUP_JOB_MUTATION = (0, _graphqlTag.default)`
34
34
  }
35
35
  }
36
36
  `;
37
+
38
+ // TODO: Replace this with the codegen
37
39
  exports.CREATE_DB_BACKUP_JOB_MUTATION = CREATE_DB_BACKUP_JOB_MUTATION;
38
40
  const DB_BACKUP_JOB_STATUS_QUERY = (0, _graphqlTag.default)`
39
41
  query AppBackupJobStatus($appId: Int!, $envId: Int!) {
@@ -104,12 +106,12 @@ class BackupDBCommand {
104
106
  PREPARE: 'prepare',
105
107
  GENERATE: 'generate'
106
108
  };
107
- constructor(app, env, trackerFn = () => {}) {
109
+ constructor(app, env, trackerFn = async () => {}) {
108
110
  this.app = app;
109
111
  this.env = env;
110
112
  this.progressTracker = new _progress.ProgressTracker([{
111
113
  id: this.steps.PREPARE,
112
- name: 'Preparing'
114
+ name: 'Preparing for backup generation'
113
115
  }, {
114
116
  id: this.steps.GENERATE,
115
117
  name: 'Generating backup'
@@ -117,11 +119,13 @@ class BackupDBCommand {
117
119
  this.track = trackerFn;
118
120
  }
119
121
  log(msg) {
120
- if (this.silent) return;
122
+ if (this.silent) {
123
+ return;
124
+ }
121
125
  console.log(msg);
122
126
  }
123
127
  isDone(job) {
124
- return !job.inProgressLock;
128
+ return !(job !== null && job !== void 0 && job.inProgressLock);
125
129
  }
126
130
 
127
131
  /**
@@ -134,54 +138,53 @@ class BackupDBCommand {
134
138
  this.progressTracker.stopPrinting();
135
139
  }
136
140
  async loadBackupJob() {
137
- var _this$job, _this$job$metadata$fi, _this$job2, _this$job2$progress, _this$job3;
141
+ var _this$job$metadata$fi, _this$job$metadata$fi2, _this$job$progress;
138
142
  this.job = await getBackupJob(this.app.id, this.env.id);
139
- this.backupName = ((_this$job = this.job) === null || _this$job === void 0 ? void 0 : (_this$job$metadata$fi = _this$job.metadata.find(meta => meta.name === 'backupName')) === null || _this$job$metadata$fi === void 0 ? void 0 : _this$job$metadata$fi.value) || 'Unknown';
140
- this.jobStatus = (_this$job2 = this.job) === null || _this$job2 === void 0 ? void 0 : (_this$job2$progress = _this$job2.progress) === null || _this$job2$progress === void 0 ? void 0 : _this$job2$progress.status;
141
- if ((_this$job3 = this.job) !== null && _this$job3 !== void 0 && _this$job3.completedAt) {
142
- this.jobAge = (new Date() - new Date(this.job.completedAt)) / 1000 / 60;
143
+ this.backupName = (_this$job$metadata$fi = (_this$job$metadata$fi2 = this.job.metadata.find(meta => meta.name === 'backupName')) === null || _this$job$metadata$fi2 === void 0 ? void 0 : _this$job$metadata$fi2.value) !== null && _this$job$metadata$fi !== void 0 ? _this$job$metadata$fi : 'Unknown';
144
+ this.jobStatus = (_this$job$progress = this.job.progress) === null || _this$job$progress === void 0 ? void 0 : _this$job$progress.status;
145
+ if (this.job.completedAt) {
146
+ this.jobAge = (new Date().getTime() - new Date(this.job.completedAt).getTime()) / 1000 / 60;
143
147
  } else {
144
148
  this.jobAge = undefined;
145
149
  }
146
150
  return this.job;
147
151
  }
148
152
  async run(silent = false) {
149
- var _this$job4;
153
+ var _this$job;
150
154
  this.silent = silent;
151
- const readMoreMessage = '\nRead more about the limitations around database backups & exports here: https://docs.wpvip.com/technical-references/vip-dashboard/backups/ \n';
152
155
  let noticeMessage = `\n${_chalk.default.yellow('NOTICE: ')}`;
153
- noticeMessage += 'A fresh database backup will be generated only if there hasn\'t one already been created recently, either by our automated system or by a user on your site';
154
- noticeMessage += readMoreMessage;
156
+ noticeMessage += 'If a recent database backup does not exist, a new one will be generated for this environment. ';
157
+ noticeMessage += 'Learn more about this: https://docs.wpvip.com/technical-references/vip-dashboard/backups/#2-download-a-full-database-backup \n';
155
158
  this.log(noticeMessage);
156
159
  await this.loadBackupJob();
157
- if ((_this$job4 = this.job) !== null && _this$job4 !== void 0 && _this$job4.inProgressLock) {
160
+ if ((_this$job = this.job) !== null && _this$job !== void 0 && _this$job.inProgressLock) {
158
161
  this.log('Database backup already in progress...');
159
162
  } else {
160
163
  try {
161
- this.log('Creating a new database backup...');
164
+ this.log('Generating a new database backup...');
162
165
  this.progressTracker.stepRunning(this.steps.PREPARE);
163
166
  this.progressTracker.startPrinting();
164
167
  await createBackupJob(this.app.id, this.env.id);
165
- } catch (err) {
166
- var _err$message;
168
+ } catch (stepErr) {
169
+ const err = stepErr;
167
170
  this.progressTracker.stepFailed(this.steps.PREPARE);
168
171
  this.stopProgressTracker();
169
- if ((_err$message = err.message) !== null && _err$message !== void 0 && _err$message.includes('Database backups limit reached')) {
172
+ if (err.message.includes('Database backups limit reached')) {
170
173
  await this.track('error', {
171
174
  error_type: 'rate_limit_exceeded',
172
175
  error_message: `Couldn't create a new database backup job: ${err === null || err === void 0 ? void 0 : err.message}`,
173
- stack: err === null || err === void 0 ? void 0 : err.stack
176
+ stack: err.stack
174
177
  });
175
- let errMessage = err.message.replace('Database backups limit reached', 'New database backup generation failed because there was already one created recently, either by our automated system or by a user on your site');
176
- errMessage = errMessage.replace('Retry after', '\nTo create a new backup, you can wait until:');
177
- errMessage += `\n\nYou can also export the latest backup using the ${_chalk.default.green('vip @app.env export sql')} command`;
178
- errMessage += readMoreMessage;
178
+ let errMessage = err.message.replace('Database backups limit reached', 'A new database backup was not generated because a recently generated backup already exists.');
179
+ errMessage = errMessage.replace('Retry after', '\nIf you would like to run the same command, you can retry on or after:');
180
+ errMessage += `\nAlternatively, you can export the latest existing database backup by running: ${_chalk.default.green('vip @app.env export sql')}, right away.`;
181
+ errMessage += '\nLearn more about limitations around generating database backups: https://docs.wpvip.com/technical-references/vip-dashboard/backups/#0-limitations \n';
179
182
  exit.withError(errMessage);
180
183
  }
181
184
  await this.track('error', {
182
185
  error_type: 'db_backup_job_creation_failed',
183
186
  error_message: `Database Backup job creation failed: ${err === null || err === void 0 ? void 0 : err.message}`,
184
- stack: err === null || err === void 0 ? void 0 : err.stack
187
+ stack: err.stack
185
188
  });
186
189
  exit.withError(`Couldn't create a new database backup job: ${err === null || err === void 0 ? void 0 : err.message}`);
187
190
  }
@@ -190,7 +193,8 @@ class BackupDBCommand {
190
193
  this.progressTracker.stepRunning(this.steps.GENERATE);
191
194
  try {
192
195
  await (0, _utils.pollUntil)(this.loadBackupJob.bind(this), DB_BACKUP_PROGRESS_POLL_INTERVAL, this.isDone.bind(this));
193
- } catch (err) {
196
+ } catch (e) {
197
+ const err = e;
194
198
  this.progressTracker.stepFailed(this.steps.GENERATE);
195
199
  this.stopProgressTracker();
196
200
  await this.track('error', {
@@ -206,7 +210,7 @@ class BackupDBCommand {
206
210
  if (this.jobStatus !== 'success') {
207
211
  exit.withError('Failed to create a new database backup');
208
212
  } else {
209
- this.log(`New database backup created at ${this.backupName}`);
213
+ this.log('New database backup created');
210
214
  }
211
215
  }
212
216
  }
@@ -32,7 +32,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
32
32
 
33
33
  const EXPORT_SQL_PROGRESS_POLL_INTERVAL = 1000;
34
34
  const BACKUP_AND_JOB_STATUS_QUERY = (0, _graphqlTag.default)`
35
- query AppBackupAndJobStatus( $appId: Int!, $envId: Int! ) {
35
+ query AppBackupAndJobStatus($appId: Int!, $envId: Int!) {
36
36
  app(id: $appId) {
37
37
  id
38
38
  environments(id: $envId) {
@@ -186,7 +186,6 @@ async function createExportJob(appId, envId, backupId) {
186
186
  */
187
187
  class ExportSQLCommand {
188
188
  steps = {
189
- GENERATE: 'generate',
190
189
  PREPARE: 'prepare',
191
190
  CREATE: 'create',
192
191
  DOWNLOAD_LINK: 'downloadLink',
@@ -207,7 +206,7 @@ class ExportSQLCommand {
207
206
  this.generateBackup = options.generateBackup || false;
208
207
  this.progressTracker = new _progress.ProgressTracker([{
209
208
  id: this.steps.PREPARE,
210
- name: 'Preparing'
209
+ name: 'Preparing for backup download'
211
210
  }, {
212
211
  id: this.steps.CREATE,
213
212
  name: 'Creating backup copy'
@@ -19,16 +19,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
19
19
  */
20
20
 
21
21
  const mutation = (0, _graphqlTag.default)`
22
- mutation PurgePageCacheMutation(
23
- $appId: Int!
24
- $envId: Int!
25
- $urls: [String!]!
26
- ) {
27
- purgePageCache( input: {
28
- appId: $appId
29
- environmentId: $envId
30
- urls: $urls
31
- } ) {
22
+ mutation PurgePageCacheMutation($appId: Int!, $envId: Int!, $urls: [String!]!) {
23
+ purgePageCache(input: { appId: $appId, environmentId: $envId, urls: $urls }) {
32
24
  success
33
25
  urls
34
26
  }
@@ -21,11 +21,17 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
21
21
  const LIMIT_MAX = 5000;
22
22
  exports.LIMIT_MAX = LIMIT_MAX;
23
23
  const QUERY_ENVIRONMENT_LOGS = (0, _graphqlTag.default)`
24
- query GetAppLogs( $appId: Int, $envId: Int, $type: AppEnvironmentLogType, $limit: Int, $after: String ) {
25
- app( id: $appId ) {
26
- environments( id: $envId ) {
24
+ query GetAppLogs(
25
+ $appId: Int
26
+ $envId: Int
27
+ $type: AppEnvironmentLogType
28
+ $limit: Int
29
+ $after: String
30
+ ) {
31
+ app(id: $appId) {
32
+ environments(id: $envId) {
27
33
  id
28
- logs( type: $type, limit: $limit, after: $after ) {
34
+ logs(type: $type, limit: $limit, after: $after) {
29
35
  nodes {
30
36
  timestamp
31
37
  message
@@ -94,8 +94,8 @@ function keyValue(values) {
94
94
  value
95
95
  } of values) {
96
96
  let formattedValue;
97
- switch (key.toLowerCase()) {
98
- // NOSONAR
97
+ switch (key.toLowerCase() // NOSONAR
98
+ ) {
99
99
  case 'environment':
100
100
  formattedValue = formatEnvironment(value);
101
101
  break;