@automattic/vip 2.7.0 → 2.8.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.
package/README.md CHANGED
@@ -27,6 +27,29 @@ By default, we record information about the usage of this tool using an in-house
27
27
 
28
28
  ## Changelog
29
29
 
30
+ ### 2.8.2 (27 January 2021)
31
+ - #961 Fixes md5 calculation failing when search-replace is used
32
+ - #959 Fixes md5 calculation for SQL Imports on VIPd
33
+
34
+ https://github.com/Automattic/vip/releases/tag/v2.8.2
35
+
36
+ ### 2.8.0 (25 January 2021)
37
+ - #952 FORNO-1047: Fix SQL Import for compressed files
38
+ - #955 Add Error prefix for "Failed to fetch logs" msg
39
+ - #946 Add support for the site logs tailing feature
40
+ - #953 [dev-env] Updated list of available wordpress images for dev-env
41
+ - #933 Update dependency debug to v4.3.3
42
+
43
+ https://github.com/Automattic/vip/releases/tag/v2.8.0
44
+
45
+ ### 2.7.1 (10 January 2021)
46
+ - #950 Switch to npm-shrinkwrap
47
+ - #947 [dev-env] List all dev env alias
48
+ - #944 Add `vip whoami` command
49
+ - #942 Envvar: Show message when there is an attempt to change the New Relic key.
50
+
51
+ https://github.com/Automattic/vip/releases/tag/v2.7.1
52
+
30
53
  ### 2.7.0 (07 December 2021)
31
54
  - #941 [dev-env] Bump lando CLI dependency
32
55
  - #938 Hide roll back message after SQL Import failure for launched sites
@@ -36,7 +36,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
36
36
  /**
37
37
  * Internal dependencies
38
38
  */
39
- const baseUsage = 'vip config envvar set'; // Command examples
39
+ const baseUsage = 'vip config envvar set';
40
+ const NEW_RELIC_ENVVAR_KEY = 'NEW_RELIC_LICENSE_KEY'; // Command examples
40
41
 
41
42
  const examples = [{
42
43
  usage: `${baseUsage} MY_VARIABLE`,
@@ -63,6 +64,12 @@ async function setEnvVarCommand(arg, opt) {
63
64
  process.exit(1);
64
65
  }
65
66
 
67
+ if (NEW_RELIC_ENVVAR_KEY === name) {
68
+ await (0, _tracker.trackEvent)('envvar_set_newrelic_key', trackingParams);
69
+ console.log(_chalk.default.bold.red('Setting the New Relic key is not permitted.'), 'If you want to set your own New Relic key, please contact our support team through the usual channels.');
70
+ process.exit(1);
71
+ }
72
+
66
73
  let value;
67
74
 
68
75
  if (opt.fromFile) {
@@ -0,0 +1,37 @@
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
+
19
+ var _devEnvironmentCore = require("../lib/dev-environment/dev-environment-core");
20
+
21
+ var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
22
+
23
+ var _devEnvironment = require("../lib/constants/dev-environment");
24
+
25
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
+
27
+ const examples = [{
28
+ usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} list`,
29
+ description: 'Return information about all local dev environments'
30
+ }];
31
+ (0, _command.default)().examples(examples).argv(process.argv, async () => {
32
+ try {
33
+ await (0, _devEnvironmentCore.printAllEnvironmentsInfo)();
34
+ } catch (error) {
35
+ (0, _devEnvironmentCli.handleCLIException)(error);
36
+ }
37
+ });
@@ -20,4 +20,4 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
20
20
 
21
21
  (0, _command.default)({
22
22
  requiredArgs: 1
23
- }).command('create', 'Create a new local dev environment').command('update', 'Update an already created local dev environment').command('start', 'Start a local dev environment').command('stop', 'Stop a local dev environment').command('destroy', 'Remove containers, networks, volumes and configuration files of a local dev environment').command('info', 'Provides basic info about one or multiple local dev environments').command('exec', 'Execute an operation on a dev environment').command('import', 'Import data into a local WordPress environment').argv(process.argv);
23
+ }).command('create', 'Create a new local dev environment').command('update', 'Update an already created local dev environment').command('start', 'Start a local dev environment').command('stop', 'Stop a local dev environment').command('destroy', 'Remove containers, networks, volumes and configuration files of a local dev environment').command('info', 'Provides basic info about one or multiple local dev environments').command('list', 'Provides basic info about all local dev environments').command('exec', 'Execute an operation on a dev environment').command('import', 'Import data into a local WordPress environment').argv(process.argv);
@@ -54,6 +54,8 @@ var _progress = require("../lib/cli/progress");
54
54
 
55
55
  var _isMultiSite = require("../lib/validations/is-multi-site");
56
56
 
57
+ var _path = _interopRequireDefault(require("path"));
58
+
57
59
  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); }
58
60
 
59
61
  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; }
@@ -367,9 +369,11 @@ const displayPlaybook = ({
367
369
 
368
370
  const {
369
371
  app,
370
- env,
371
- searchReplace,
372
- skipValidate
372
+ env
373
+ } = opts;
374
+ let {
375
+ skipValidate,
376
+ searchReplace
373
377
  } = opts;
374
378
  const {
375
379
  id: envId,
@@ -377,6 +381,14 @@ const displayPlaybook = ({
377
381
  } = env;
378
382
  const [fileName] = arg;
379
383
  const isMultiSite = await (0, _isMultiSite.isMultiSiteInSiteMeta)(appId, envId);
384
+ const fileMeta = await (0, _clientFileUploader.getFileMeta)(fileName);
385
+
386
+ if (fileMeta.isCompressed) {
387
+ console.log(_chalk.default.yellowBright('You are importing a compressed file. Validation and search-replace operation will be skipped.'));
388
+ skipValidate = true;
389
+ searchReplace = undefined;
390
+ }
391
+
380
392
  debug('Options: ', opts);
381
393
  debug('Args: ', arg);
382
394
 
@@ -478,17 +490,19 @@ Processing the SQL import for your environment...
478
490
  progressTracker.setUploadPercentage(percentage);
479
491
  };
480
492
 
493
+ fileMeta.fileName = fileNameToUpload;
494
+
481
495
  try {
482
496
  const {
483
497
  fileMeta: {
484
- basename,
485
- md5
498
+ basename
486
499
  },
500
+ md5,
487
501
  result
488
502
  } = await (0, _clientFileUploader.uploadImportSqlFileToS3)({
489
503
  app,
490
504
  env,
491
- fileName: fileNameToUpload,
505
+ fileMeta,
492
506
  progressCallback
493
507
  });
494
508
  startImportVariables.input = {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Internal dependencies
4
+ * External dependencies
5
5
  */
6
6
  "use strict";
7
7
 
@@ -9,9 +9,12 @@ Object.defineProperty(exports, "__esModule", {
9
9
  value: true
10
10
  });
11
11
  exports.getLogs = getLogs;
12
+ exports.followLogs = followLogs;
12
13
  exports.validateInputs = validateInputs;
13
14
  exports.appQuery = void 0;
14
15
 
16
+ var _chalk = _interopRequireDefault(require("chalk"));
17
+
15
18
  var _command = _interopRequireDefault(require("../lib/cli/command"));
16
19
 
17
20
  var _rollbar = require("../lib/rollbar");
@@ -30,26 +33,28 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
30
33
 
31
34
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
32
35
 
33
- const LIMIT_MAX = 5000;
36
+ /**
37
+ * Internal dependencies
38
+ */
34
39
  const LIMIT_MIN = 1;
40
+ const LIMIT_MAX = 5000;
35
41
  const ALLOWED_TYPES = ['app', 'batch'];
36
42
  const ALLOWED_FORMATS = ['csv', 'json', 'text'];
43
+ const DEFAULT_POLLING_DELAY_IN_SECONDS = 30;
44
+ const MIN_POLLING_DELAY_IN_SECONDS = 5;
45
+ const MAX_POLLING_DELAY_IN_SECONDS = 300;
37
46
 
38
47
  async function getLogs(arg, opt) {
39
48
  validateInputs(opt.type, opt.limit, opt.format);
40
- const trackingParams = {
41
- command: 'vip logs',
42
- org_id: opt.app.organization.id,
43
- app_id: opt.app.id,
44
- env_id: opt.env.id,
45
- type: opt.type,
46
- limit: opt.limit,
47
- format: opt.format
48
- };
49
+ const trackingParams = getBaseTrackingParams(opt);
49
50
  await (0, _tracker.trackEvent)('logs_command_execute', trackingParams);
50
- let logs = [];
51
+ let logs;
51
52
 
52
53
  try {
54
+ if (opt.follow) {
55
+ return await followLogs(opt);
56
+ }
57
+
53
58
  logs = await logsLib.getRecentLogs(opt.app.id, opt.env.id, opt.type, opt.limit);
54
59
  } catch (error) {
55
60
  _rollbar.rollbar.error(error);
@@ -61,15 +66,91 @@ async function getLogs(arg, opt) {
61
66
  }
62
67
 
63
68
  await (0, _tracker.trackEvent)('logs_command_success', { ...trackingParams,
64
- logs_output: logs.length
69
+ total: logs.nodes.length
65
70
  });
66
71
 
67
- if (!logs.length) {
72
+ if (!logs.nodes.length) {
68
73
  console.error('No logs found');
69
74
  return;
70
- } // Strip out __typename
75
+ }
76
+
77
+ printLogs(logs.nodes, opt.format);
78
+ }
79
+
80
+ async function followLogs(opt) {
81
+ let after = null;
82
+ let isFirstRequest = true; // How many times have we polled?
83
+
84
+ let requestNumber = 0;
85
+ const trackingParams = getBaseTrackingParams(opt); // Set an initial default delay
86
+
87
+ let delay = DEFAULT_POLLING_DELAY_IN_SECONDS;
88
+
89
+ while (true) {
90
+ const limit = isFirstRequest ? opt.limit : LIMIT_MAX;
91
+ requestNumber++;
92
+ trackingParams.request_number = requestNumber;
93
+ trackingParams.request_delay = delay;
94
+ trackingParams.limit = limit;
95
+ let logs;
71
96
 
97
+ try {
98
+ var _logs;
99
+
100
+ logs = await logsLib.getRecentLogs(opt.app.id, opt.env.id, opt.type, limit, after);
101
+ await (0, _tracker.trackEvent)('logs_command_follow_success', { ...trackingParams,
102
+ total: (_logs = logs) === null || _logs === void 0 ? void 0 : _logs.nodes.length
103
+ });
104
+ } catch (error) {
105
+ await (0, _tracker.trackEvent)('logs_command_follow_error', { ...trackingParams,
106
+ error: error.message
107
+ }); // If the first request fails we don't want to retry (it's probably not recoverable)
108
+
109
+ if (isFirstRequest) {
110
+ console.error(`${_chalk.default.red('Error:')} Failed to fetch logs.`);
111
+ break;
112
+ } // Increase the delay on errors to avoid overloading the server, up to a max of 5 minutes
113
+
114
+
115
+ delay += DEFAULT_POLLING_DELAY_IN_SECONDS;
116
+ delay = Math.min(delay, MAX_POLLING_DELAY_IN_SECONDS);
117
+ console.error(`${_chalk.default.red('Error:')} Failed to fetch logs. Trying again in ${delay} seconds.`);
118
+
119
+ _rollbar.rollbar.error(error);
120
+ }
121
+
122
+ if (logs) {
123
+ var _logs2, _logs3, _logs4;
124
+
125
+ if ((_logs2 = logs) !== null && _logs2 !== void 0 && _logs2.nodes.length) {
126
+ printLogs(logs.nodes, opt.format);
127
+ }
128
+
129
+ after = (_logs3 = logs) === null || _logs3 === void 0 ? void 0 : _logs3.nextCursor;
130
+ isFirstRequest = false; // Keep a sane lower limit of MIN_POLLING_DELAY_IN_SECONDS just in case something goes wrong in the server-side
131
+
132
+ delay = Math.max(((_logs4 = logs) === null || _logs4 === void 0 ? void 0 : _logs4.pollingDelaySeconds) || DEFAULT_POLLING_DELAY_IN_SECONDS, MIN_POLLING_DELAY_IN_SECONDS);
133
+ }
134
+
135
+ await new Promise(resolve => setTimeout(resolve, delay * 1000));
136
+ }
137
+ }
138
+
139
+ function getBaseTrackingParams(opt) {
140
+ return {
141
+ command: 'vip logs',
142
+ org_id: opt.app.organization.id,
143
+ app_id: opt.app.id,
144
+ env_id: opt.env.id,
145
+ type: opt.type,
146
+ limit: opt.limit,
147
+ follow: opt.follow || false,
148
+ format: opt.format
149
+ };
150
+ }
72
151
 
152
+ function printLogs(logs, format) {
153
+ // Strip out __typename
73
154
  logs = logs.map(log => {
74
155
  const {
75
156
  timestamp,
@@ -82,7 +163,7 @@ async function getLogs(arg, opt) {
82
163
  });
83
164
  let output = '';
84
165
 
85
- if (opt.format && 'text' === opt.format) {
166
+ if (format && 'text' === format) {
86
167
  const rows = [];
87
168
 
88
169
  for (const {
@@ -93,7 +174,7 @@ async function getLogs(arg, opt) {
93
174
  output = rows.join('\n');
94
175
  }
95
176
  } else {
96
- output = (0, _format.formatData)(logs, opt.format);
177
+ output = (0, _format.formatData)(logs, format);
97
178
  }
98
179
 
99
180
  console.log(output);
@@ -108,8 +189,8 @@ function validateInputs(type, limit, format) {
108
189
  exit.withError(`Invalid format: ${format}. The supported formats are: ${ALLOWED_FORMATS.join(', ')}.`);
109
190
  }
110
191
 
111
- if (!Number.isInteger(limit) || limit < LIMIT_MIN || limit > LIMIT_MAX) {
112
- exit.withError(`Invalid limit: ${limit}. It should be a number between ${LIMIT_MIN} and ${LIMIT_MAX}.`);
192
+ if (!Number.isInteger(limit) || limit < LIMIT_MIN || limit > logsLib.LIMIT_MAX) {
193
+ exit.withError(`Invalid limit: ${limit}. It should be a number between ${LIMIT_MIN} and ${logsLib.LIMIT_MAX}.`);
113
194
  }
114
195
  }
115
196
 
@@ -133,7 +214,7 @@ exports.appQuery = appQuery;
133
214
  appQuery,
134
215
  envContext: true,
135
216
  module: 'logs'
136
- }).option('type', 'The type of logs to be returned: "app" or "batch"', 'app').option('limit', 'The maximum number of log lines', 500).option('format', 'Output the log lines in CSV or JSON format', 'text').examples([{
217
+ }).option('type', 'The type of logs to be returned: "app" or "batch"', 'app').option('limit', 'The maximum number of log lines', 500).option('follow', 'Keep fetching new logs as they are generated').option('format', 'Output the log lines in CSV or JSON format', 'text').examples([{
137
218
  usage: 'vip @mysite.production logs',
138
219
  description: 'Get the most recent app logs'
139
220
  }, {
@@ -0,0 +1,67 @@
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
+ Object.defineProperty(exports, "__esModule", {
18
+ value: true
19
+ });
20
+ exports.whoamiCommand = whoamiCommand;
21
+
22
+ var _user = require("../lib/api/user");
23
+
24
+ var _command = _interopRequireDefault(require("../lib/cli/command"));
25
+
26
+ var _tracker = require("../lib/tracker");
27
+
28
+ var exit = _interopRequireWildcard(require("../lib/cli/exit"));
29
+
30
+ 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); }
31
+
32
+ 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; }
33
+
34
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
35
+
36
+ async function whoamiCommand() {
37
+ const trackingParams = {
38
+ command: 'vip whoami'
39
+ };
40
+ await (0, _tracker.trackEvent)('whoami_command_execute', trackingParams);
41
+ let currentUser = {};
42
+
43
+ try {
44
+ currentUser = await (0, _user.getCurrentUserInfo)();
45
+ } catch (err) {
46
+ await (0, _tracker.trackEvent)('whoami_command_error', { ...trackingParams,
47
+ error: err.message
48
+ });
49
+ exit.withError(`Failed to fetch information about the currently logged-in user error: ${err.message}`);
50
+ }
51
+
52
+ await (0, _tracker.trackEvent)('whoami_command_success', trackingParams);
53
+ const output = [`- Howdy ${currentUser.displayName}!`, `- Your user ID is ${currentUser.id}`];
54
+
55
+ if (currentUser.isVIP) {
56
+ output.push('- Your account has VIP Staff permissions');
57
+ }
58
+
59
+ console.log(output.join('\n'));
60
+ }
61
+
62
+ (0, _command.default)({
63
+ usage: 'vip whoami'
64
+ }).examples([{
65
+ usage: 'vip whoami',
66
+ description: 'Display details about the currently logged-in user.'
67
+ }]).argv(process.argv, whoamiCommand);
package/dist/bin/vip.js CHANGED
@@ -48,7 +48,7 @@ const runCmd = async function () {
48
48
  await _token.default.purge();
49
49
  await (0, _tracker.trackEvent)('logout_command_execute');
50
50
  console.log('You are successfully logged out.');
51
- }).command('app', 'List and modify 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('wp', 'Run WP CLI commands against an environment');
51
+ }).command('app', 'List and modify 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('wp', 'Run WP CLI commands against an environment');
52
52
  cmd.argv(process.argv);
53
53
  };
54
54
 
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getCurrentUserInfo = getCurrentUserInfo;
7
+
8
+ var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
9
+
10
+ var _api = _interopRequireDefault(require("../api"));
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+
14
+ /**
15
+ *
16
+ * @format
17
+ */
18
+
19
+ /**
20
+ * External dependencies
21
+ */
22
+
23
+ /**
24
+ * Internal dependencies
25
+ */
26
+ const QUERY_CURRENT_USER = (0, _graphqlTag.default)`
27
+ query Me {
28
+ me {
29
+ id
30
+ displayName
31
+ isVIP
32
+ organizationRoles {
33
+ nodes {
34
+ organizationId
35
+ roleId
36
+ }
37
+ }
38
+ }
39
+ }
40
+ `;
41
+
42
+ async function getCurrentUserInfo() {
43
+ const api = await (0, _api.default)();
44
+ const response = await api.query({
45
+ query: QUERY_CURRENT_USER
46
+ });
47
+ const {
48
+ data: {
49
+ me
50
+ }
51
+ } = response;
52
+
53
+ if (!me) {
54
+ throw new Error('The API did not return any information about the user.');
55
+ }
56
+
57
+ return me;
58
+ }
package/dist/lib/api.js CHANGED
@@ -52,7 +52,9 @@ function disableGlobalGraphQLErrorHandling() {
52
52
  globalGraphQLErrorHandlingEnabled = false;
53
53
  }
54
54
 
55
- async function API() {
55
+ async function API({
56
+ exitOnError = true
57
+ } = {}) {
56
58
  const authToken = await _token.default.get();
57
59
  const headers = {
58
60
  'User-Agent': _env.default.userAgent,
@@ -71,7 +73,10 @@ async function API() {
71
73
  graphQLErrors.forEach(error => {
72
74
  console.error(_chalk.default.red('Error:'), error.message);
73
75
  });
74
- process.exit();
76
+
77
+ if (exitOnError) {
78
+ process.exit();
79
+ }
75
80
  }
76
81
  });
77
82
  const withToken = (0, _context.setContext)(async () => {
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getRecentLogs = getRecentLogs;
7
+ exports.LIMIT_MAX = void 0;
7
8
 
8
9
  var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
9
10
 
@@ -23,38 +24,45 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
23
24
  /**
24
25
  * Internal dependencies
25
26
  */
27
+ const LIMIT_MAX = 5000;
28
+ exports.LIMIT_MAX = LIMIT_MAX;
26
29
  const QUERY_ENVIRONMENT_LOGS = (0, _graphqlTag.default)`
27
- query GetAppLogs( $appId: Int, $envId: Int, $type: AppEnvironmentLogType, $limit: Int ) {
30
+ query GetAppLogs( $appId: Int, $envId: Int, $type: AppEnvironmentLogType, $limit: Int, $after: String ) {
28
31
  app( id: $appId ) {
29
32
  environments( id: $envId ) {
30
33
  id
31
- logs( type: $type, limit: $limit ) {
34
+ logs( type: $type, limit: $limit, after: $after ) {
32
35
  nodes {
33
36
  timestamp
34
37
  message
35
38
  }
39
+ nextCursor
40
+ pollingDelaySeconds
36
41
  }
37
42
  }
38
43
  }
39
44
  }
40
45
  `;
41
46
 
42
- async function getRecentLogs(appId, envId, type, limit) {
43
- var _response$data, _response$data$app, _response$data$app$en, _response$data$app$en2;
47
+ async function getRecentLogs(appId, envId, type, limit, after) {
48
+ var _response$data, _response$data$app, _response$data$app$en;
44
49
 
45
- const api = await (0, _api.default)();
50
+ const api = await (0, _api.default)({
51
+ exitOnError: false
52
+ });
46
53
  const response = await api.query({
47
54
  query: QUERY_ENVIRONMENT_LOGS,
48
55
  variables: {
49
56
  appId,
50
57
  envId,
51
58
  type,
52
- limit
59
+ limit,
60
+ after
53
61
  }
54
62
  });
55
- const logs = response === null || response === void 0 ? void 0 : (_response$data = response.data) === null || _response$data === void 0 ? void 0 : (_response$data$app = _response$data.app) === null || _response$data$app === void 0 ? void 0 : (_response$data$app$en = _response$data$app.environments[0]) === null || _response$data$app$en === void 0 ? void 0 : (_response$data$app$en2 = _response$data$app$en.logs) === null || _response$data$app$en2 === void 0 ? void 0 : _response$data$app$en2.nodes;
63
+ const logs = response === null || response === void 0 ? void 0 : (_response$data = response.data) === null || _response$data === void 0 ? void 0 : (_response$data$app = _response$data.app) === null || _response$data$app === void 0 ? void 0 : (_response$data$app$en = _response$data$app.environments[0]) === null || _response$data$app$en === void 0 ? void 0 : _response$data$app$en.logs;
56
64
 
57
- if (!logs) {
65
+ if (!(logs !== null && logs !== void 0 && logs.nodes)) {
58
66
  throw new Error('Unable to query logs');
59
67
  }
60
68
 
@@ -105,15 +105,11 @@ async function getFileMeta(fileName) {
105
105
  const mimeType = await detectCompressedMimeType(fileName); // TODO Only allow a subset of Mime Types...?
106
106
 
107
107
  const isCompressed = ['application/zip', 'application/gzip'].includes(mimeType);
108
- debug('Calculating file md5 checksum...');
109
- const md5 = await getFileMD5Hash(fileName);
110
- debug(`Calculated file md5 checksum: ${md5}\n`);
111
108
  resolve({
112
109
  basename,
113
110
  fileName,
114
111
  fileSize,
115
- isCompressed,
116
- md5
112
+ isCompressed
117
113
  });
118
114
  });
119
115
  }
@@ -121,10 +117,9 @@ async function getFileMeta(fileName) {
121
117
  async function uploadImportSqlFileToS3({
122
118
  app,
123
119
  env,
124
- fileName,
120
+ fileMeta,
125
121
  progressCallback
126
122
  }) {
127
- const fileMeta = await getFileMeta(fileName);
128
123
  let tmpDir;
129
124
 
130
125
  try {
@@ -152,6 +147,9 @@ async function uploadImportSqlFileToS3({
152
147
  debug(`** Compression resulted in a ${calculation} smaller file 📦 **\n`);
153
148
  }
154
149
 
150
+ debug('Calculating file md5 checksum...');
151
+ const md5 = await getFileMD5Hash(fileMeta.fileName);
152
+ debug(`Calculated file md5 checksum: ${md5}\n`);
155
153
  const result = fileMeta.fileSize < MULTIPART_THRESHOLD ? await uploadUsingPutObject({
156
154
  app,
157
155
  env,
@@ -165,6 +163,7 @@ async function uploadImportSqlFileToS3({
165
163
  });
166
164
  return {
167
165
  fileMeta,
166
+ md5,
168
167
  result
169
168
  };
170
169
  }
@@ -370,5 +370,5 @@ function addDevEnvConfigurationOptions(command) {
370
370
  }
371
371
 
372
372
  function getWordpressImageTags() {
373
- return ['5.8.1', '5.8', '5.7.3', '5.7.2'];
373
+ return ['5.9', '5.8.3', '5.8.2', '5.8.1', '5.8', '5.7.3', '5.7.2'];
374
374
  }