@automattic/vip 2.32.1 → 2.32.3

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 (48) hide show
  1. package/.prettierignore +0 -2
  2. package/CHANGELOG.md +26 -0
  3. package/CONTRIBUTING.md +41 -17
  4. package/assets/dev-env.lando.template.yml.ejs +10 -2
  5. package/dist/bin/vip-dev-env-exec.js +1 -7
  6. package/dist/bin/vip-dev-env-shell.js +0 -4
  7. package/dist/bin/vip-dev-env-start.js +1 -1
  8. package/dist/bin/vip-dev-env-sync-sql.js +8 -6
  9. package/dist/bin/vip-dev-env-update.js +1 -2
  10. package/dist/bin/vip-import-sql.js +2 -2
  11. package/dist/bin/vip-logout.js +23 -0
  12. package/dist/bin/vip-slowlogs.js +192 -0
  13. package/dist/bin/vip-validate-preflight.js +8 -10
  14. package/dist/bin/vip-whoami.js +1 -2
  15. package/dist/bin/vip.js +1 -5
  16. package/dist/commands/backup-db.js +29 -30
  17. package/dist/lib/api/app.js +2 -2
  18. package/dist/lib/api/cache-purge.js +2 -2
  19. package/dist/lib/api/http.js +3 -3
  20. package/dist/lib/app-logs/app-logs.js +2 -2
  21. package/dist/lib/app-slowlogs/app-slowlogs.js +63 -0
  22. package/dist/lib/app-slowlogs/types.js +1 -0
  23. package/dist/lib/cli/apiConfig.js +1 -1
  24. package/dist/lib/client-file-uploader.js +19 -4
  25. package/dist/lib/config/software.js +4 -4
  26. package/dist/lib/constants/dev-environment.js +7 -3
  27. package/dist/lib/dev-environment/dev-environment-cli.js +110 -117
  28. package/dist/lib/dev-environment/dev-environment-configuration-file.js +34 -36
  29. package/dist/lib/dev-environment/dev-environment-core.js +36 -19
  30. package/dist/lib/dev-environment/dev-environment-lando.js +80 -72
  31. package/dist/lib/dev-environment/docker-utils.js +8 -9
  32. package/dist/lib/envvar/api-get-all.js +2 -2
  33. package/dist/lib/envvar/api-list.js +3 -6
  34. package/dist/lib/envvar/input.js +1 -2
  35. package/dist/lib/site-import/status.js +5 -5
  36. package/dist/lib/token.js +3 -6
  37. package/dist/lib/types/graphql/rate-limit-exceeded-error.js +1 -0
  38. package/dist/lib/validations/is-multi-site-sql-dump.js +0 -1
  39. package/dist/lib/validations/is-multi-site.js +14 -12
  40. package/dist/lib/validations/is-multisite-domain-mapped.js +5 -10
  41. package/dist/lib/validations/line-by-line.js +9 -13
  42. package/dist/lib/validations/site-type.js +2 -7
  43. package/dist/lib/validations/sql.js +14 -19
  44. package/dist/lib/validations/utils.js +1 -1
  45. package/helpers/generate-docs.js +151 -0
  46. package/npm-shrinkwrap.json +920 -933
  47. package/package.json +15 -10
  48. package/tsconfig.json +16 -6
package/.prettierignore CHANGED
@@ -1,6 +1,4 @@
1
- *.generated.d.ts
2
1
  /CHANGELOG.md
3
2
  /__fixtures__/
4
3
  /dist/
5
4
  /flow-typed/
6
- /src/graphqlTypes.d.ts
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  ## Changelog
2
2
 
3
+ ### 2.32.3
4
+
5
+ - #1456 Fix DB engine validation regex
6
+ - #1455 Fix SQL import command
7
+ - #1454 chore(deps): update lando to 5efb9eb
8
+ - #1453 Refactor logout
9
+ - #1425 Add Slowlogs command
10
+ - #1341 feat(dev-env): Add a concept of init-only containers
11
+ - #1344 fix(dev-env): Do not run URL scan unless really need to
12
+ - #1414 [dev-env] Tweak error handling dev-env sync
13
+ - #1452 chore(dev-deps): update TypeScript-related packages
14
+ - #1420 feat(dev-env): Adds automigration logic to dev-env
15
+ - #1451 chore(dev-deps): update testing tools
16
+ - #1448 chore(dev-deps): update babel packages to 7.22.9
17
+ - #1421 refactor: Convert dev-environment to TypeScript
18
+ - #1450 refactor: convert `validations` to TS
19
+
20
+ ### 2.32.2
21
+
22
+ - #1443 On-demand Database Backup: Use a less error-prone way of detecting if we're rate limited
23
+ - #1434 Add more clarifying steps for making a release
24
+ - #1435 Remove enums from GraphQL codegen and make sure that prettier actually runs
25
+ - #1433 Redeploy codegen for GraphQL queries
26
+ - #1432 Revert "Add codegen for GraphQL queries (#1429)"
27
+ - #1304 Generate docs
28
+
3
29
  ### 2.32.1
4
30
 
5
31
  - #1445 chore(deps): update vulnerable dependencies to fix ReDoS in semver
package/CONTRIBUTING.md CHANGED
@@ -97,26 +97,23 @@ We use a custom pre-publish [script](https://github.com/Automattic/vip/blob/trun
97
97
 
98
98
  Further checks can be added to this flow as needed.
99
99
 
100
- ### Pre-publish Tasks
101
-
102
- As part of the publish flow, we run the `prepareConfig:publish` task on `prepack`. This copies over "production" config values to your working copy to make sure the release includes those instead of development values.
103
-
104
- We use `prepack` because:
105
-
106
- - `prepareConfig:local` runs on `npm build` and we want to make sure those values are overriden.
107
- - This is the latest npm event that we can run on before publishing. (Note: we tried `prepublishOnly` but files added during that step [don't get included in the build](https://github.com/Automattic/vip/commit/c7dabe1b0f73ec9e6e8c05ccff0c41281e4cd5e8)).
108
-
109
100
  ### New Releases
110
101
 
111
102
  Prepare the release by making sure that:
112
103
 
113
104
  1. All relevant PRs have been merged.
114
105
  1. The release has been tested across macOS, Windows, and Linux.
115
- 1. The [changelog](https://github.com/Automattic/vip/blob/trunk/CHANGELOG.md) has been updated on `trunk`.
116
- 1. All tests pass and your working directory is clean (we have pre-publish checks to catch this, just-in-case).
106
+ 1. All tests pass and your working directory is clean (we have pre-publish checks to catch this,
107
+ just-in-case).
108
+ 1. Make sure not to merge anymore changes into `develop` while all the release steps below are in
109
+ progress.
117
110
 
118
111
  #### Changelog Generator Hint:
119
112
 
113
+ In the first step, you'll need to generate a changelog.
114
+
115
+ Run the following and copy the output somewhere.
116
+
120
117
  ```
121
118
  export LAST_RELEASE_DATE=2021-08-25T13:40:00+02
122
119
  gh pr list --search "is:merged sort:updated-desc closed:>$LAST_RELEASE_DATE" | sed -e 's/\s\+\S\+\tMERGED.*$//' -e 's/^/- #/'
@@ -124,15 +121,28 @@ gh pr list --search "is:merged sort:updated-desc closed:>$LAST_RELEASE_DATE" | s
124
121
 
125
122
  Then, let's publish:
126
123
 
127
- 1. Make sure trunk branch is up to date `git pull`
124
+ 1. Create a pull request that adds the next version's changelog into `develop`. Use the Changelog
125
+ Generate Hint above to generate the changelog, and refer to previous releases to ensure that your
126
+ format matches.
127
+ 1. Create a pull request that merges `develop` to `trunk`.
128
+ 1. Merge it after approval.
129
+ 1. Make sure trunk branch is up-to-date `git pull`.
130
+ 1. Make sure to clean all of your repositories of extra files. Run a dangerous, destructive
131
+ command `git clean -xfd` to do so.
132
+ 1. Run `npm install`.
128
133
  1. Set the version (via `npm version minor` or `npm version major` or `npm version patch`)
129
134
  1. For most regular releases, this will be `npm version minor`.
130
135
  1. Push the tag to GitHub (`git push --tags`)
131
136
  1. Push the trunk branch `git push`
132
137
  1. Make sure you're part of the Automattic organization in npm
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.
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).
135
- 1. Push `trunk` changes (mostly the version bump) to `develop` (`git checkout develop && git merge trunk` )
138
+ 1. Publish the release to npm (`npm publish --access public`) the script will do some extra checks (
139
+ node version, branch, etc) to ensure everything is correct. If all looks good, the new version
140
+ will be published and you can proceed.
141
+ 1. Edit [the release on GitHub](https://github.com/Automattic/vip/releases) to include a description
142
+ of the changes and publish (this can just copy the details from the changelog).
143
+ 1. Push `trunk` changes (mostly the version bump)
144
+ to `develop` (`git checkout develop && git merge trunk` ). There's no need to use a pull request
145
+ to do so.
136
146
 
137
147
  Once released, it's worth running `npm i -g @automattic/vip` to install / upgrade the released version to make sure everything looks good.
138
148
 
@@ -161,6 +171,20 @@ Then, repeat for any additional versions that we need to patch.
161
171
 
162
172
  ### go-search-replace binaries
163
173
 
164
- Some unit tests require some go-search-replace executable binary files to run. Binaries files for several OS architectures can be downloaded from https://github.com/Automattic/go-search-replace/releases/
174
+ Some unit tests require some go-search-replace executable binary files to run. Binaries files for
175
+ several OS architectures can be downloaded
176
+ from https://github.com/Automattic/go-search-replace/releases/
177
+
178
+ If, for some reason, you need to compile these binaries yourself, please follow instructions
179
+ at https://github.com/Automattic/go-search-replace
180
+
181
+ ### Generating the types
182
+
183
+ If you're an employee of Automattic, you can follow these steps to regenerate the GraphQL types
184
+ used.
165
185
 
166
- If, for some reason, you need to compile these binaries yourself, please follow instructions at https://github.com/Automattic/go-search-replace
186
+ 1. Get a hold of `schema.gql` and paste it in project root - this is the schema of the endpoint that
187
+ we communicate with.
188
+ 2. Run `npm run typescript:codegen:install-dependencies` - this will install the codegen
189
+ dependencies without updating `package.json`
190
+ 3. Run `npm run typescript:codegen:generate` - this will regenerate the types
@@ -17,7 +17,7 @@ services:
17
17
  type: compose
18
18
  services:
19
19
  image: ghcr.io/automattic/vip-container-images/dev-tools:0.9
20
- command: sleep infinity
20
+ command: exit 0
21
21
  volumes:
22
22
  - devtools:/dev-tools
23
23
  - scripts:/scripts
@@ -28,6 +28,7 @@ services:
28
28
  volumes:
29
29
  devtools: {}
30
30
  scripts:
31
+ initOnly: true
31
32
 
32
33
  nginx:
33
34
  type: compose
@@ -154,6 +155,7 @@ services:
154
155
  type: compose
155
156
  services:
156
157
  image: ghcr.io/automattic/vip-container-images/wordpress:<%= wordpress.tag %>
158
+ # command: /usr/local/bin/entrypoint.sh
157
159
  command: sh -c "rsync -a --chown=www-data:www-data /wp/ /shared/; sleep infinity"
158
160
  volumes:
159
161
  - ./wordpress:/shared
@@ -162,6 +164,10 @@ services:
162
164
  target: /scripts
163
165
  volume:
164
166
  nocopy: true
167
+ # environment:
168
+ # LANDO_NO_SCRIPTS: 1
169
+ # LANDO_NEEDS_EXEC: 1
170
+ # initOnly: true
165
171
 
166
172
  <% if ( muPlugins.mode == 'image' ) { %>
167
173
  vip-mu-plugins:
@@ -181,6 +187,7 @@ services:
181
187
  LANDO_NEEDS_EXEC: 1
182
188
  volumes:
183
189
  mu-plugins: {}
190
+ initOnly: true
184
191
  <% } %>
185
192
 
186
193
  <% if ( appCode.mode == 'image' ) { %>
@@ -188,7 +195,7 @@ services:
188
195
  type: compose
189
196
  services:
190
197
  image: ghcr.io/automattic/vip-container-images/skeleton:latest
191
- command: sleep infinity
198
+ command: exit 0
192
199
  volumes:
193
200
  - clientcode_clientmuPlugins:/clientcode/client-mu-plugins
194
201
  - clientcode_images:/clientcode/images
@@ -205,6 +212,7 @@ services:
205
212
  clientcode_private: {}
206
213
  clientcode_themes: {}
207
214
  clientcode_vipconfig: {}
215
+ initOnly: true
208
216
  <% } %>
209
217
 
210
218
  <% if ( mailpit ) { %>
@@ -30,13 +30,7 @@ const examples = [{
30
30
  }];
31
31
  (0, _command.default)({
32
32
  wildcardCommand: true
33
- }).option('slug', 'Custom name of the dev environment').option('force', 'Disabling validations before task execution', undefined, value => {
34
- var _value$toLowerCase;
35
- return 'false' !== (value === null || value === void 0 ? void 0 : (_value$toLowerCase = value.toLowerCase) === null || _value$toLowerCase === void 0 ? void 0 : _value$toLowerCase.call(value));
36
- }).option('quiet', 'Suppress output', undefined, value => {
37
- var _value$toLowerCase2;
38
- return 'false' !== (value === null || value === void 0 ? void 0 : (_value$toLowerCase2 = value.toLowerCase) === null || _value$toLowerCase2 === void 0 ? void 0 : _value$toLowerCase2.call(value));
39
- }).examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
33
+ }).option('slug', 'Custom name of the dev environment').option('force', 'Disable validations before task execution', undefined, _devEnvironmentCli.processBooleanOption).option('quiet', 'Suppress output', undefined, _devEnvironmentCli.processBooleanOption).examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
40
34
  const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
41
35
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
42
36
  await (0, _devEnvironmentCli.validateDependencies)(lando, slug, opt.quiet);
@@ -18,14 +18,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
18
18
  */
19
19
  const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
20
20
  const userMap = {
21
- devtools: 'www-data',
22
21
  nginx: 'www-data',
23
22
  php: 'www-data',
24
23
  database: 'mysql',
25
24
  memcached: 'memcache',
26
- wordpress: 'www-data',
27
- 'vip-mu-plugins': 'www-data',
28
- 'demo-app-code': 'www-data',
29
25
  elasticsearch: 'elasticsearch',
30
26
  phpmyadmin: 'www-data',
31
27
  mailhog: 'mailhog',
@@ -73,7 +73,7 @@ const examples = [{
73
73
  await (0, _devEnvironmentCli.handleCLIException)(error, 'dev_env_start_command_error', trackingInfo);
74
74
  process.exitCode = 1;
75
75
  }
76
- await (0, _devEnvironmentCli.postStart)(slug, {
76
+ (0, _devEnvironmentCli.postStart)(slug, {
77
77
  openVSCode: !!opt.vscode
78
78
  });
79
79
  });
@@ -21,6 +21,7 @@ var _userError = _interopRequireDefault(require("../lib/user-error"));
21
21
  var _devEnvSyncSql = require("../commands/dev-env-sync-sql");
22
22
  var _devEnvironment = require("../lib/constants/dev-environment");
23
23
  var _tracker = require("../lib/tracker");
24
+ var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
24
25
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
26
  const examples = [{
26
27
  usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} sync sql @my-test.develop --slug=my_site`,
@@ -54,11 +55,12 @@ const appQuery = `
54
55
  envContext: true,
55
56
  requiredArgs: 0,
56
57
  module: 'dev-env-sync-sql'
57
- }).option('slug', 'Custom name of the dev environment').examples(examples).argv(process.argv, async (arg, {
58
- app,
59
- env,
60
- slug
61
- }) => {
58
+ }).option('slug', 'Custom name of the dev environment').option('force', 'Disable validations before running sync', undefined, _devEnvironmentCli.processBooleanOption).examples(examples).argv(process.argv, async (arg, opt) => {
59
+ const {
60
+ app,
61
+ env
62
+ } = opt;
63
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
62
64
  const trackerFn = (0, _tracker.makeCommandTracker)('dev_env_sync_sql', {
63
65
  app: app.id,
64
66
  env: env.uniqueLabel,
@@ -68,7 +70,7 @@ const appQuery = `
68
70
  await trackerFn('execute');
69
71
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
70
72
  const envPath = (0, _devEnvironmentCore.getEnvironmentPath)(slug);
71
- if (!(await (0, _devEnvironmentLando.isEnvUp)(lando, envPath))) {
73
+ if (!(await (0, _devEnvironmentLando.isEnvUp)(lando, envPath)) && !opt.force) {
72
74
  await trackerFn('env_not_running_error', {
73
75
  errorMessage: 'Environment was not running'
74
76
  });
@@ -39,7 +39,6 @@ cmd.argv(process.argv, async (arg, opt) => {
39
39
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
40
40
  await (0, _tracker.trackEvent)('dev_env_update_command_execute', trackingInfo);
41
41
  try {
42
- var _currentInstanceData$;
43
42
  const environmentAlreadyExists = await (0, _devEnvironmentCore.doesEnvironmentExist)((0, _devEnvironmentCore.getEnvironmentPath)(slug));
44
43
  if (!environmentAlreadyExists) {
45
44
  throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
@@ -63,7 +62,7 @@ cmd.argv(process.argv, async (arg, opt) => {
63
62
  mariadb: currentInstanceData.mariadb,
64
63
  phpmyadmin: currentInstanceData.phpmyadmin,
65
64
  xdebug: currentInstanceData.xdebug,
66
- mailpit: (_currentInstanceData$ = currentInstanceData.mailpit) !== null && _currentInstanceData$ !== void 0 ? _currentInstanceData$ : currentInstanceData.mailhog,
65
+ mailpit: currentInstanceData.mailpit ?? currentInstanceData.mailhog,
67
66
  photon: currentInstanceData.photon,
68
67
  mediaRedirectDomain: currentInstanceData.mediaRedirectDomain,
69
68
  multisite: false,
@@ -271,8 +271,8 @@ const displayPlaybook = ({
271
271
  var _app$environments, _selectedEnvironmentO;
272
272
  // eslint-disable-next-line no-multi-spaces
273
273
  console.log(` multisite: ${isMultiSite.toString()}`);
274
- const selectedEnvironmentObj = app === null || app === void 0 ? void 0 : (_app$environments = app.environments) === null || _app$environments === void 0 ? void 0 : _app$environments.find(env => unformattedEnvironment === env.type);
275
- siteArray = selectedEnvironmentObj === null || selectedEnvironmentObj === void 0 ? void 0 : (_selectedEnvironmentO = selectedEnvironmentObj.wpSites) === null || _selectedEnvironmentO === void 0 ? void 0 : _selectedEnvironmentO.nodes;
274
+ const selectedEnvironmentObj = app === null || app === void 0 || (_app$environments = app.environments) === null || _app$environments === void 0 ? void 0 : _app$environments.find(env => unformattedEnvironment === env.type);
275
+ siteArray = selectedEnvironmentObj === null || selectedEnvironmentObj === void 0 || (_selectedEnvironmentO = selectedEnvironmentObj.wpSites) === null || _selectedEnvironmentO === void 0 ? void 0 : _selectedEnvironmentO.nodes;
276
276
  }
277
277
  if (!tableNames.length) {
278
278
  debug('Validation was skipped, no playbook information will be displayed');
@@ -0,0 +1,23 @@
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 _logout = _interopRequireDefault(require("../lib/logout"));
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+ void (0, _command.default)({
16
+ usage: 'vip logout'
17
+ }).examples([{
18
+ usage: 'vip logout',
19
+ description: 'Logs out current user.'
20
+ }]).argv(process.argv, async () => {
21
+ await (0, _logout.default)();
22
+ console.log('You are successfully logged out.');
23
+ });
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * External dependencies
4
+ */
5
+ "use strict";
6
+
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ exports.appQuery = void 0;
11
+ exports.followLogs = followLogs;
12
+ exports.getSlowlogs = getSlowlogs;
13
+ exports.validateInputs = validateInputs;
14
+ var _chalk = _interopRequireDefault(require("chalk"));
15
+ var _promises = require("timers/promises");
16
+ var _command = _interopRequireDefault(require("../lib/cli/command"));
17
+ var _tracker = require("../lib/tracker");
18
+ var slowlogsLib = _interopRequireWildcard(require("../lib/app-slowlogs/app-slowlogs"));
19
+ var exit = _interopRequireWildcard(require("../lib/cli/exit"));
20
+ var _format = require("../lib/cli/format");
21
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
22
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
23
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
+ /**
25
+ * Internal dependencies
26
+ */
27
+ const LIMIT_MIN = 1;
28
+ const LIMIT_MAX = 500;
29
+ const ALLOWED_FORMATS = ['csv', 'json', 'text'];
30
+ const DEFAULT_POLLING_DELAY_IN_SECONDS = 30;
31
+ const MIN_POLLING_DELAY_IN_SECONDS = 5;
32
+ const MAX_POLLING_DELAY_IN_SECONDS = 300;
33
+ async function getSlowlogs(arg, opt) {
34
+ validateInputs(opt.limit, opt.format);
35
+ const trackingParams = getBaseTrackingParams(opt);
36
+ await (0, _tracker.trackEvent)('slowlogs_command_execute', trackingParams);
37
+ let slowlogs;
38
+ try {
39
+ slowlogs = await slowlogsLib.getRecentSlowlogs(opt.app.id, opt.env.id, opt.limit);
40
+ } catch (error) {
41
+ const err = error;
42
+ await (0, _tracker.trackEvent)('slowlogs_command_error', {
43
+ ...trackingParams,
44
+ error: err.message
45
+ });
46
+ return exit.withError(err.message);
47
+ }
48
+ await (0, _tracker.trackEvent)('slowlogs_command_success', {
49
+ ...trackingParams,
50
+ total: slowlogs.nodes.length
51
+ });
52
+ if (!slowlogs.nodes.length) {
53
+ console.error('No logs found');
54
+ return;
55
+ }
56
+ printSlowlogs(slowlogs.nodes, opt.format);
57
+ }
58
+ async function followLogs(opt) {
59
+ let after = null;
60
+ let isFirstRequest = true;
61
+ // How many times have we polled?
62
+ let requestNumber = 0;
63
+ const trackingParams = getBaseTrackingParams(opt);
64
+
65
+ // Set an initial default delay
66
+ let delay = DEFAULT_POLLING_DELAY_IN_SECONDS;
67
+
68
+ // eslint-disable-next-line no-constant-condition, @typescript-eslint/no-unnecessary-condition
69
+ while (true) {
70
+ const limit = isFirstRequest ? opt.limit : LIMIT_MAX;
71
+ requestNumber++;
72
+ trackingParams.request_number = requestNumber;
73
+ trackingParams.request_delay = delay;
74
+ trackingParams.limit = limit;
75
+ let slowlogs;
76
+ try {
77
+ // eslint-disable-next-line no-await-in-loop
78
+ slowlogs = await slowlogsLib.getRecentSlowlogs(opt.app.id, opt.env.id, limit, after);
79
+
80
+ // eslint-disable-next-line no-await-in-loop
81
+ await (0, _tracker.trackEvent)('slowlogs_command_follow_success', {
82
+ ...trackingParams,
83
+ total: slowlogs.nodes.length
84
+ });
85
+ } catch (error) {
86
+ const err = error;
87
+ // eslint-disable-next-line no-await-in-loop
88
+ await (0, _tracker.trackEvent)('slowlogs_command_follow_error', {
89
+ ...trackingParams,
90
+ error: err.message
91
+ });
92
+
93
+ // If the first request fails we don't want to retry (it's probably not recoverable)
94
+ if (isFirstRequest) {
95
+ console.error(`${_chalk.default.red('Error:')} Failed to fetch slowlogs.`);
96
+ break;
97
+ }
98
+ // Increase the delay on errors to avoid overloading the server, up to a max of 5 minutes
99
+ delay += DEFAULT_POLLING_DELAY_IN_SECONDS;
100
+ delay = Math.min(delay, MAX_POLLING_DELAY_IN_SECONDS);
101
+ console.error(`${_chalk.default.red('Error:')} Failed to fetch slowlogs. Trying again in ${delay} seconds.`);
102
+ }
103
+ if (slowlogs) {
104
+ if (slowlogs.nodes.length) {
105
+ printSlowlogs(slowlogs.nodes, opt.format);
106
+ }
107
+ after = slowlogs.nextCursor;
108
+ isFirstRequest = false;
109
+
110
+ // Keep a sane lower limit of MIN_POLLING_DELAY_IN_SECONDS just in case something goes wrong in the server-side
111
+ delay = Math.max(slowlogs.pollingDelaySeconds || DEFAULT_POLLING_DELAY_IN_SECONDS, MIN_POLLING_DELAY_IN_SECONDS);
112
+ }
113
+
114
+ // eslint-disable-next-line no-await-in-loop
115
+ await (0, _promises.setTimeout)(delay * 1000);
116
+ }
117
+ }
118
+ function getBaseTrackingParams(opt) {
119
+ return {
120
+ command: 'vip slowlogs',
121
+ org_id: opt.app.organization.id,
122
+ app_id: opt.app.id,
123
+ env_id: opt.env.id,
124
+ limit: opt.limit,
125
+ follow: opt.follow ?? false,
126
+ format: opt.format
127
+ };
128
+ }
129
+ function printSlowlogs(slowlogs, format) {
130
+ // Strip out __typename
131
+ slowlogs = slowlogs.map(log => {
132
+ const {
133
+ timestamp,
134
+ rowsSent,
135
+ rowsExamined,
136
+ queryTime,
137
+ requestUri,
138
+ query
139
+ } = log;
140
+ return {
141
+ timestamp,
142
+ rowsSent,
143
+ rowsExamined,
144
+ queryTime,
145
+ requestUri,
146
+ query
147
+ };
148
+ });
149
+ console.log((0, _format.formatData)(slowlogs, format));
150
+ }
151
+ function validateInputs(limit, format) {
152
+ if (!ALLOWED_FORMATS.includes(format)) {
153
+ exit.withError(`Invalid format: ${format}. The supported formats are: ${ALLOWED_FORMATS.join(', ')}.`);
154
+ }
155
+ if (!Number.isInteger(limit) || limit < LIMIT_MIN || limit > slowlogsLib.LIMIT_MAX) {
156
+ exit.withError(`Invalid limit: ${limit}. It should be a number between ${LIMIT_MIN} and ${slowlogsLib.LIMIT_MAX}.`);
157
+ }
158
+ }
159
+ const appQuery = `
160
+ id
161
+ name
162
+ environments {
163
+ id
164
+ appId
165
+ name
166
+ type
167
+ }
168
+ organization {
169
+ id
170
+ name
171
+ }
172
+ `;
173
+ exports.appQuery = appQuery;
174
+ void (0, _command.default)({
175
+ appContext: true,
176
+ appQuery,
177
+ envContext: true,
178
+ format: true,
179
+ module: 'slowlogs'
180
+ }).option('limit', 'The maximum number of log lines', 500).option('format', 'Output the log lines in CSV or JSON format', 'text').examples([{
181
+ description: 'Get the most recent app slowlogs',
182
+ usage: 'vip @mysite.production slowlogs'
183
+ }, {
184
+ usage: 'vip @mysite.production slowlogs --limit 100',
185
+ description: 'Get the most recent 100 slowlog entries'
186
+ }, {
187
+ usage: 'vip @mysite.production slowlogs --limit 100 --format csv',
188
+ description: 'Get the most recent 100 slowlog entries formatted as comma-separated values (CSV)'
189
+ }, {
190
+ usage: 'vip @mysite.production slowlogs --limit 100 --format json',
191
+ description: 'Get the most recent 100 slowlog entries formatted as JSON'
192
+ }]).argv(process.argv, getSlowlogs);
@@ -111,10 +111,10 @@ async function getBuildConfiguration(application, environment) {
111
111
  }
112
112
  }
113
113
  async function vipValidatePreflightCommand(arg, opt) {
114
- var _opt$env$appId, _opt$env, _opt$env$id, _opt$env2, _opt$app$repo, _opt$app, _opt$env3, _opt$env3$environment;
114
+ var _opt$env, _opt$env2, _opt$app, _opt$env3;
115
115
  harmoniaArgs = await validateArgs(opt);
116
- const appId = (_opt$env$appId = (_opt$env = opt.env) === null || _opt$env === void 0 ? void 0 : _opt$env.appId) !== null && _opt$env$appId !== void 0 ? _opt$env$appId : 0;
117
- const envId = (_opt$env$id = (_opt$env2 = opt.env) === null || _opt$env2 === void 0 ? void 0 : _opt$env2.id) !== null && _opt$env$id !== void 0 ? _opt$env$id : 0;
116
+ const appId = ((_opt$env = opt.env) === null || _opt$env === void 0 ? void 0 : _opt$env.appId) ?? 0;
117
+ const envId = ((_opt$env2 = opt.env) === null || _opt$env2 === void 0 ? void 0 : _opt$env2.id) ?? 0;
118
118
  const baseTrackingParams = {
119
119
  env_id: envId,
120
120
  app_id: appId,
@@ -144,7 +144,7 @@ async function vipValidatePreflightCommand(arg, opt) {
144
144
  const siteOptions = new _vipGoPreflightChecks.SiteConfig({
145
145
  siteID: envId,
146
146
  nodejsVersion: harmoniaArgs.nodejsVersion,
147
- repository: (_opt$app$repo = (_opt$app = opt.app) === null || _opt$app === void 0 ? void 0 : _opt$app.repo) !== null && _opt$app$repo !== void 0 ? _opt$app$repo : 'no-repo',
147
+ repository: ((_opt$app = opt.app) === null || _opt$app === void 0 ? void 0 : _opt$app.repo) ?? 'no-repo',
148
148
  baseURL: 'http://localhost:' + harmoniaArgs.port,
149
149
  dockerBuildEnvs: harmoniaArgs.nodeBuildDockerEnv,
150
150
  topRequests: [],
@@ -167,7 +167,7 @@ async function vipValidatePreflightCommand(arg, opt) {
167
167
  return exit.withError(`Could not find a 'package.json' in the current folder (${opt.path}).`);
168
168
  }
169
169
  const customEnvVars = {};
170
- if (((_opt$env3 = opt.env) === null || _opt$env3 === void 0 ? void 0 : (_opt$env3$environment = _opt$env3.environmentVariables) === null || _opt$env3$environment === void 0 ? void 0 : _opt$env3$environment.nodes.length) > 0) {
170
+ if (((_opt$env3 = opt.env) === null || _opt$env3 === void 0 || (_opt$env3 = _opt$env3.environmentVariables) === null || _opt$env3 === void 0 ? void 0 : _opt$env3.nodes.length) > 0) {
171
171
  opt.env.environmentVariables.nodes.forEach(envVar => {
172
172
  customEnvVars[envVar.name] = envVar.value;
173
173
  });
@@ -368,7 +368,6 @@ async function handleResults(harmonia, results) {
368
368
  process.exit(0);
369
369
  }
370
370
  async function validateArgs(opt) {
371
- var _opt$wait, _opt$port;
372
371
  const args = {};
373
372
 
374
373
  // Verbose
@@ -387,12 +386,11 @@ async function validateArgs(opt) {
387
386
  outputJson = true;
388
387
  }
389
388
  if (opt.app) {
390
- var _opt$nodeVersion;
391
389
  // Get build information from API and store it in the env object
392
390
  const buildConfig = await getBuildConfiguration(opt.app, opt.env);
393
391
  args.app_id = opt.app.id;
394
392
  args.env_id = opt.env.id;
395
- args.nodejsVersion = (_opt$nodeVersion = opt.nodeVersion) !== null && _opt$nodeVersion !== void 0 ? _opt$nodeVersion : buildConfig.nodeJSVersion;
393
+ args.nodejsVersion = opt.nodeVersion ?? buildConfig.nodeJSVersion;
396
394
  args.buildType = buildConfig.buildType;
397
395
  args.npmToken = buildConfig.npmToken;
398
396
  args.nodeBuildDockerEnv = buildConfig.nodeBuildDockerEnv;
@@ -419,8 +417,8 @@ async function validateArgs(opt) {
419
417
  args.nodejsVersion = opt.nodeVersion;
420
418
  }
421
419
  }
422
- args.wait = (_opt$wait = opt.wait) !== null && _opt$wait !== void 0 ? _opt$wait : 3000;
423
- args.port = (_opt$port = opt.port) !== null && _opt$port !== void 0 ? _opt$port : Math.floor(Math.random() * 1000) + 3001; // Get a PORT from 3001 and 3999
420
+ args.wait = opt.wait ?? 3000;
421
+ args.port = opt.port ?? Math.floor(Math.random() * 1000) + 3001; // Get a PORT from 3001 and 3999
424
422
 
425
423
  return args;
426
424
  }
@@ -21,7 +21,6 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
21
21
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
22
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
23
  async function whoamiCommand() {
24
- var _currentUser$displayN, _currentUser$id;
25
24
  const trackingParams = {
26
25
  command: 'vip whoami'
27
26
  };
@@ -38,7 +37,7 @@ async function whoamiCommand() {
38
37
  exit.withError(`Failed to fetch information about the currently logged-in user error: ${error.message}`);
39
38
  }
40
39
  await (0, _tracker.trackEvent)('whoami_command_success', trackingParams);
41
- const output = [`- Howdy ${(_currentUser$displayN = currentUser.displayName) !== null && _currentUser$displayN !== void 0 ? _currentUser$displayN : 'user'}!`, `- Your user ID is ${(_currentUser$id = currentUser.id) !== null && _currentUser$id !== void 0 ? _currentUser$id : ' not found'}`];
40
+ const output = [`- Howdy ${currentUser.displayName ?? 'user'}!`, `- Your user ID is ${currentUser.id ?? ' not found'}`];
42
41
  if (currentUser.isVIP) {
43
42
  output.push('- Your account has VIP Staff permissions');
44
43
  }
package/dist/bin/vip.js CHANGED
@@ -12,7 +12,6 @@ var _config = _interopRequireDefault(require("../lib/cli/config"));
12
12
  var _command = _interopRequireWildcard(require("../lib/cli/command"));
13
13
  var _token2 = _interopRequireDefault(require("../lib/token"));
14
14
  var _tracker = require("../lib/tracker");
15
- var _logout = _interopRequireDefault(require("../lib/logout"));
16
15
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
16
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
18
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -29,10 +28,7 @@ if (_config.default && _config.default.environment !== 'production') {
29
28
  const tokenURL = 'https://dashboard.wpvip.com/me/cli/token';
30
29
  const runCmd = async function () {
31
30
  const cmd = (0, _command.default)();
32
- cmd.command('logout', 'Logout from your current session', async () => {
33
- await (0, _logout.default)();
34
- console.log('You are successfully logged out.');
35
- }).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');
31
+ cmd.command('logout', 'Logout from your current session').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('slowlogs', 'Get slowlogs from your VIP applications').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
32
  cmd.argv(process.argv);
37
33
  };
38
34
  function doesArgvHaveAtLeastOneParam(argv, params) {