@automattic/vip 2.11.0 → 2.11.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.
Files changed (99) hide show
  1. package/README.md +8 -0
  2. package/config/config.json +2 -2
  3. package/npm-shrinkwrap.json +1 -1
  4. package/package/dist/bin/vip-app-list.js +73 -0
  5. package/package/dist/bin/vip-app.js +76 -0
  6. package/package/dist/bin/vip-config-envvar-delete.js +97 -0
  7. package/package/dist/bin/vip-config-envvar-get-all.js +94 -0
  8. package/package/dist/bin/vip-config-envvar-get.js +79 -0
  9. package/package/dist/bin/vip-config-envvar-list.js +91 -0
  10. package/package/dist/bin/vip-config-envvar-set.js +123 -0
  11. package/package/dist/bin/vip-config-envvar.js +23 -0
  12. package/package/dist/bin/vip-config.js +20 -0
  13. package/package/dist/bin/vip-dev-env-create.js +105 -0
  14. package/package/dist/bin/vip-dev-env-destroy.js +56 -0
  15. package/package/dist/bin/vip-dev-env-exec.js +67 -0
  16. package/package/dist/bin/vip-dev-env-import-media.js +51 -0
  17. package/package/dist/bin/vip-dev-env-import-sql.js +83 -0
  18. package/package/dist/bin/vip-dev-env-import.js +32 -0
  19. package/package/dist/bin/vip-dev-env-info.js +61 -0
  20. package/package/dist/bin/vip-dev-env-list.js +46 -0
  21. package/package/dist/bin/vip-dev-env-start.js +77 -0
  22. package/package/dist/bin/vip-dev-env-stop.js +52 -0
  23. package/package/dist/bin/vip-dev-env-update.js +89 -0
  24. package/package/dist/bin/vip-dev-env.js +23 -0
  25. package/package/dist/bin/vip-import-media-abort.js +132 -0
  26. package/package/dist/bin/vip-import-media-status.js +84 -0
  27. package/package/dist/bin/vip-import-media.js +168 -0
  28. package/package/dist/bin/vip-import-sql-status.js +83 -0
  29. package/package/dist/bin/vip-import-sql.js +580 -0
  30. package/package/dist/bin/vip-import-validate-files.js +191 -0
  31. package/package/dist/bin/vip-import-validate-sql.js +34 -0
  32. package/package/dist/bin/vip-import.js +20 -0
  33. package/package/dist/bin/vip-logs.js +232 -0
  34. package/package/dist/bin/vip-search-replace.js +71 -0
  35. package/package/dist/bin/vip-sync.js +191 -0
  36. package/package/dist/bin/vip-whoami.js +67 -0
  37. package/package/dist/bin/vip-wp.js +555 -0
  38. package/package/dist/bin/vip.js +149 -0
  39. package/package/dist/lib/analytics/clients/client.js +1 -0
  40. package/package/dist/lib/analytics/clients/pendo.js +92 -0
  41. package/package/dist/lib/analytics/clients/stub.js +19 -0
  42. package/package/dist/lib/analytics/clients/tracks.js +128 -0
  43. package/package/dist/lib/analytics/index.js +45 -0
  44. package/package/dist/lib/api/app.js +70 -0
  45. package/package/dist/lib/api/feature-flags.js +39 -0
  46. package/package/dist/lib/api/user.js +58 -0
  47. package/package/dist/lib/api.js +136 -0
  48. package/package/dist/lib/app-logs/app-logs.js +70 -0
  49. package/package/dist/lib/cli/apiConfig.js +90 -0
  50. package/package/dist/lib/cli/command.js +606 -0
  51. package/package/dist/lib/cli/envAlias.js +60 -0
  52. package/package/dist/lib/cli/exit.js +33 -0
  53. package/package/dist/lib/cli/format.js +213 -0
  54. package/package/dist/lib/cli/pager.js +52 -0
  55. package/package/dist/lib/cli/progress.js +208 -0
  56. package/package/dist/lib/cli/prompt.js +37 -0
  57. package/package/dist/lib/cli/repo.js +77 -0
  58. package/package/dist/lib/client-file-uploader.js +602 -0
  59. package/package/dist/lib/constants/dev-environment.js +42 -0
  60. package/package/dist/lib/constants/file-size.js +14 -0
  61. package/package/dist/lib/dev-environment/dev-environment-cli.js +508 -0
  62. package/package/dist/lib/dev-environment/dev-environment-core.js +620 -0
  63. package/package/dist/lib/dev-environment/dev-environment-lando.js +330 -0
  64. package/package/dist/lib/dev-environment/types.js +1 -0
  65. package/package/dist/lib/env.js +36 -0
  66. package/package/dist/lib/envvar/api-delete.js +56 -0
  67. package/package/dist/lib/envvar/api-get-all.js +59 -0
  68. package/package/dist/lib/envvar/api-get.js +24 -0
  69. package/package/dist/lib/envvar/api-list.js +60 -0
  70. package/package/dist/lib/envvar/api-set.js +58 -0
  71. package/package/dist/lib/envvar/api.js +104 -0
  72. package/package/dist/lib/envvar/input.js +55 -0
  73. package/package/dist/lib/envvar/logging.js +33 -0
  74. package/package/dist/lib/envvar/read-file.js +43 -0
  75. package/package/dist/lib/http/socks-proxy-agent.js +25 -0
  76. package/package/dist/lib/keychain/browser.js +35 -0
  77. package/package/dist/lib/keychain/insecure.js +63 -0
  78. package/package/dist/lib/keychain/keychain.js +1 -0
  79. package/package/dist/lib/keychain/secure.js +36 -0
  80. package/package/dist/lib/keychain.js +36 -0
  81. package/package/dist/lib/media-import/media-file-import.js +34 -0
  82. package/package/dist/lib/media-import/progress.js +86 -0
  83. package/package/dist/lib/media-import/status.js +335 -0
  84. package/package/dist/lib/rollbar.js +35 -0
  85. package/package/dist/lib/search-and-replace.js +203 -0
  86. package/package/dist/lib/site-import/db-file-import.js +46 -0
  87. package/package/dist/lib/site-import/status.js +444 -0
  88. package/package/dist/lib/token.js +132 -0
  89. package/package/dist/lib/tracker.js +96 -0
  90. package/package/dist/lib/validations/is-multi-site-sql-dump.js +59 -0
  91. package/package/dist/lib/validations/is-multi-site.js +99 -0
  92. package/package/dist/lib/validations/line-by-line.js +92 -0
  93. package/package/dist/lib/validations/site-type.js +66 -0
  94. package/package/dist/lib/validations/sql.js +371 -0
  95. package/package/dist/lib/vip-import-validate-files.js +548 -0
  96. package/package/vip.iml +11 -0
  97. package/package.json +1 -1
  98. package/vip.iml +11 -0
  99. package/automattic-vip-2.11.0.tgz +0 -0
@@ -0,0 +1,580 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ *
5
+ * @format
6
+ */
7
+
8
+ /**
9
+ * External dependencies
10
+ */
11
+ "use strict";
12
+
13
+ Object.defineProperty(exports, "__esModule", {
14
+ value: true
15
+ });
16
+ exports.gates = gates;
17
+ exports.validateAndGetTableNames = validateAndGetTableNames;
18
+
19
+ var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
20
+
21
+ var _cliColumns = _interopRequireDefault(require("cli-columns"));
22
+
23
+ var _chalk = _interopRequireDefault(require("chalk"));
24
+
25
+ var _debug = _interopRequireDefault(require("debug"));
26
+
27
+ var _enquirer = require("enquirer");
28
+
29
+ var _command = _interopRequireDefault(require("../lib/cli/command"));
30
+
31
+ var _dbFileImport = require("../lib/site-import/db-file-import");
32
+
33
+ var _status = require("../lib/site-import/status");
34
+
35
+ var _clientFileUploader = require("../lib/client-file-uploader");
36
+
37
+ var _tracker = require("../lib/tracker");
38
+
39
+ var _sql = require("../lib/validations/sql");
40
+
41
+ var _siteType = require("../lib/validations/site-type");
42
+
43
+ var _searchAndReplace = require("../lib/search-and-replace");
44
+
45
+ var _api = _interopRequireDefault(require("../lib/api"));
46
+
47
+ var exit = _interopRequireWildcard(require("../lib/cli/exit"));
48
+
49
+ var _lineByLine = require("../lib/validations/line-by-line");
50
+
51
+ var _format = require("../lib/cli/format");
52
+
53
+ var _progress = require("../lib/cli/progress");
54
+
55
+ var _isMultiSite = require("../lib/validations/is-multi-site");
56
+
57
+ var _rollbar = require("../lib/rollbar");
58
+
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); }
60
+
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; }
62
+
63
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
64
+
65
+ /**
66
+ * Internal dependencies
67
+ */
68
+ const appQuery = `
69
+ id,
70
+ name,
71
+ type,
72
+ organization { id, name },
73
+ environments{
74
+ id
75
+ appId
76
+ type
77
+ name
78
+ launched
79
+ isK8sResident
80
+ syncProgress { status }
81
+ primaryDomain { name }
82
+ importStatus {
83
+ dbOperationInProgress
84
+ importInProgress
85
+ }
86
+ wpSites {
87
+ nodes {
88
+ homeUrl
89
+ id
90
+ }
91
+ }
92
+ }
93
+ `;
94
+ const START_IMPORT_MUTATION = (0, _graphqlTag.default)`
95
+ mutation StartImport($input: AppEnvironmentImportInput) {
96
+ startImport(input: $input) {
97
+ app {
98
+ id
99
+ name
100
+ }
101
+ message
102
+ success
103
+ }
104
+ }
105
+ `;
106
+ const debug = (0, _debug.default)('@automattic/vip:bin:vip-import-sql');
107
+ const SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS = [{
108
+ id: 'replace',
109
+ name: 'Performing Search and Replace'
110
+ }, {
111
+ id: 'upload',
112
+ name: 'Uploading file'
113
+ }, {
114
+ id: 'queue_import',
115
+ name: 'Queueing Import'
116
+ }];
117
+
118
+ async function gates(app, env, fileName) {
119
+ const {
120
+ id: envId,
121
+ appId
122
+ } = env;
123
+
124
+ const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
125
+
126
+ if (!(0, _dbFileImport.currentUserCanImportForApp)(app)) {
127
+ await track('import_sql_command_error', {
128
+ error_type: 'unauthorized'
129
+ });
130
+ exit.withError('The currently authenticated account does not have permission to perform a SQL import.');
131
+ }
132
+
133
+ if (!(0, _dbFileImport.isSupportedApp)(app)) {
134
+ await track('import_sql_command_error', {
135
+ error_type: 'unsupported-app'
136
+ });
137
+ exit.withError('The type of application you specified does not currently support SQL imports.');
138
+ }
139
+
140
+ try {
141
+ await (0, _clientFileUploader.checkFileAccess)(fileName);
142
+ } catch (err) {
143
+ await track('import_sql_command_error', {
144
+ error_type: 'sqlfile-unreadable'
145
+ });
146
+ exit.withError(`File '${fileName}' does not exist or is not readable.`);
147
+ }
148
+
149
+ if (!(await (0, _clientFileUploader.isFile)(fileName))) {
150
+ await track('import_sql_command_error', {
151
+ error_type: 'sqlfile-notfile'
152
+ });
153
+ exit.withError(`Path '${fileName}' is not a file.`);
154
+ }
155
+
156
+ const fileSize = await (0, _clientFileUploader.getFileSize)(fileName);
157
+
158
+ if (!fileSize) {
159
+ await track('import_sql_command_error', {
160
+ error_type: 'sqlfile-empty'
161
+ });
162
+ exit.withError(`File '${fileName}' is empty.`);
163
+ }
164
+
165
+ const maxFileSize = env !== null && env !== void 0 && env.launched ? _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED : _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT;
166
+
167
+ if (fileSize > maxFileSize) {
168
+ await track('import_sql_command_error', {
169
+ error_type: 'sqlfile-toobig',
170
+ file_size: fileSize,
171
+ launched: !!(env !== null && env !== void 0 && env.launched)
172
+ });
173
+ exit.withError(`The sql import file size (${fileSize} bytes) exceeds the limit (${maxFileSize} bytes).` + (env.launched ? ' Note: This limit is lower for launched environments to maintain site stability.' : '') + '\n\nPlease split it into multiple files or contact support for assistance.');
174
+ }
175
+
176
+ if (!(env !== null && env !== void 0 && env.importStatus)) {
177
+ await track('import_sql_command_error', {
178
+ error_type: 'empty-import-status'
179
+ });
180
+ exit.withError('Could not determine the import status for this environment. Check the app/environment and if the problem persists, contact support for assistance');
181
+ }
182
+
183
+ const {
184
+ importStatus: {
185
+ dbOperationInProgress,
186
+ importInProgress
187
+ }
188
+ } = env;
189
+
190
+ if (importInProgress) {
191
+ await track('import_sql_command_error', {
192
+ error_type: 'existing-import'
193
+ });
194
+ exit.withError('There is already an import in progress.\n\nYou can view the status with command:\n vip import sql status');
195
+ }
196
+
197
+ if (dbOperationInProgress) {
198
+ await track('import_sql_command_error', {
199
+ error_type: 'existing-dbop'
200
+ });
201
+ exit.withError('There is already a database operation in progress. Please try again later.');
202
+ }
203
+ } // Command examples for the `vip import sql` help prompt
204
+
205
+
206
+ const examples = [// `sql` subcommand
207
+ {
208
+ usage: 'vip import sql @mysite.develop <file.sql>',
209
+ description: 'Import the given SQL file to your site'
210
+ }, // `search-replace` flag
211
+ {
212
+ usage: 'vip import sql @mysite.develop <file.sql> --search-replace="from,to"',
213
+ description: 'Perform a Search and Replace, then import the replaced file to your site.\n' + ' * Ensure there are no spaces between your search-replace parameters'
214
+ }, // `in-place` flag
215
+ {
216
+ usage: 'vip import sql @mysite.develop <file.sql> --search-replace="from,to" --in-place',
217
+ description: 'Search and Replace on the input <file.sql>, then import the replaced file to your site'
218
+ }, // `output` flag
219
+ {
220
+ usage: 'vip import sql @mysite.develop <file.sql> --search-replace="from,to" --output="<output.sql>"',
221
+ description: 'Output the performed Search and Replace to the specified output file, then import the replaced file to your site\n' + ' * Has no effect when the `in-place` flag is used'
222
+ }, // `sql status` subcommand
223
+ {
224
+ usage: 'vip import sql status @mysite.develop',
225
+ description: 'Check the status of the most recent import. If an import is running, this will poll until it is complete.'
226
+ }];
227
+
228
+ const promptToContinue = async ({
229
+ launched,
230
+ formattedEnvironment,
231
+ track,
232
+ domain
233
+ }) => {
234
+ console.log();
235
+ const promptToMatch = domain.toUpperCase();
236
+ const promptResponse = await (0, _enquirer.prompt)({
237
+ type: 'input',
238
+ name: 'confirmedDomain',
239
+ message: `You are about to import the above tables into a ${launched ? 'launched' : 'un-launched'} ${formattedEnvironment} site ${_chalk.default.yellow(domain)}.\nType '${_chalk.default.yellow(promptToMatch)}' (without the quotes) to continue:\n`
240
+ });
241
+
242
+ if (promptResponse.confirmedDomain !== promptToMatch) {
243
+ await track('import_sql_unexpected_tables');
244
+ exit.withError('The input did not match the expected environment label. Import aborted.');
245
+ }
246
+ };
247
+
248
+ async function validateAndGetTableNames({
249
+ skipValidate,
250
+ appId,
251
+ envId,
252
+ fileNameToUpload
253
+ }) {
254
+ const validations = [_sql.staticSqlValidations, _siteType.siteTypeValidations];
255
+
256
+ if (skipValidate) {
257
+ console.log('Skipping SQL file validation.');
258
+ return [];
259
+ }
260
+
261
+ try {
262
+ await (0, _lineByLine.fileLineValidations)(appId, envId, fileNameToUpload, validations);
263
+ } catch (validateErr) {
264
+ console.log('');
265
+ exit.withError(`${validateErr.message}
266
+ If you are confident the file does not contain unsupported statements, you can retry the command with the ${_chalk.default.yellow('--skip-validate')} option.
267
+ `);
268
+ } // this can only be called after static validation of the SQL file
269
+
270
+
271
+ return (0, _sql.getTableNames)();
272
+ }
273
+
274
+ const displayPlaybook = ({
275
+ launched,
276
+ tableNames,
277
+ searchReplace,
278
+ fileName,
279
+ domain,
280
+ formattedEnvironment,
281
+ isMultiSite,
282
+ app
283
+ }) => {
284
+ console.log();
285
+ console.log(` importing: ${_chalk.default.blueBright(fileName)}`);
286
+ console.log(` to: ${_chalk.default.cyan(domain)}`);
287
+ console.log(` site: ${app.name} (${formattedEnvironment})`);
288
+
289
+ if (searchReplace !== null && searchReplace !== void 0 && searchReplace.length) {
290
+ const output = (from, to) => {
291
+ const message = ` s-r: ${_chalk.default.blue(from)} -> ${_chalk.default.blue(to)}`;
292
+ console.log(message);
293
+ };
294
+
295
+ (0, _format.formatSearchReplaceValues)(searchReplace, output);
296
+ }
297
+
298
+ let siteArray = [];
299
+
300
+ if (isMultiSite) {
301
+ var _app$environments$, _app$environments$$wp;
302
+
303
+ // eslint-disable-next-line no-multi-spaces
304
+ console.log(` multisite: ${isMultiSite.toString()}`);
305
+ siteArray = app === null || app === void 0 ? void 0 : (_app$environments$ = app.environments[0]) === null || _app$environments$ === void 0 ? void 0 : (_app$environments$$wp = _app$environments$.wpSites) === null || _app$environments$$wp === void 0 ? void 0 : _app$environments$$wp.nodes;
306
+ }
307
+
308
+ if (!tableNames.length) {
309
+ debug('Validation was skipped, no playbook information will be displayed');
310
+ } else {
311
+ // output the table names
312
+ console.log();
313
+
314
+ if (!isMultiSite) {
315
+ console.log('Below are a list of Tables that will be imported by this process:');
316
+ console.log((0, _cliColumns.default)(tableNames));
317
+ } else {
318
+ var _siteArray;
319
+
320
+ // we have siteArray from the API, use it and the table names together
321
+ if (siteArray === 'undefined' || !siteArray) {
322
+ console.log(_chalk.default.yellowBright('Unable to determine the subsites affected by this import, please proceed only if you are confident on the contents in the import file.'));
323
+ return;
324
+ } else if (!((_siteArray = siteArray) !== null && _siteArray !== void 0 && _siteArray.length)) {
325
+ throw new Error('There were no sites in your multisite installation');
326
+ }
327
+
328
+ const multiSiteBreakdown = siteArray.map(wpSite => {
329
+ let siteRegex;
330
+
331
+ if (wpSite.id === 1) {
332
+ siteRegex = /wp_[a-z]+/i;
333
+ } else {
334
+ siteRegex = new RegExp(`wp_${wpSite.id}_[a-z]+`, 'i');
335
+ }
336
+
337
+ const tableNamesInGroup = tableNames.filter(name => siteRegex.test(name));
338
+ return {
339
+ id: wpSite.id,
340
+ url: wpSite.homeUrl,
341
+ tables: tableNamesInGroup
342
+ };
343
+ });
344
+
345
+ if (launched) {
346
+ console.log(_chalk.default.yellowBright('You are updating tables in a launched multi site installation. Sites in the same network may have their performance impacted by this operation.'));
347
+ }
348
+
349
+ console.log(_chalk.default.yellow('The following sites will be affected by the import:'));
350
+ multiSiteBreakdown.map(siteObject => {
351
+ console.log();
352
+ console.log(_chalk.default.blueBright(`Blog with ID ${siteObject.id} and URL ${siteObject.url} will import the following tables:`));
353
+ console.log((0, _cliColumns.default)(siteObject.tables));
354
+ });
355
+ }
356
+ }
357
+ };
358
+
359
+ (0, _command.default)({
360
+ appContext: true,
361
+ appQuery,
362
+ envContext: true,
363
+ requiredArgs: 1,
364
+ module: 'import-sql',
365
+ requireConfirm: 'Are you sure you want to import the contents of the provided SQL file?',
366
+ skipConfirmPrompt: true
367
+ }).command('status', 'Check the status of the current running import').option('skip-validate', 'Do not perform pre-upload file validation. If unsupported entries are present, the import is likely to fail').option('search-replace', 'Perform Search and Replace on the specified SQL file').option('in-place', 'Search and Replace explicitly on the given input file').option('output', 'Specify the replacement output file for Search and Replace', 'process.stdout').examples(examples).argv(process.argv, async (arg, opts) => {
368
+ var _env$primaryDomain;
369
+
370
+ const {
371
+ app,
372
+ env
373
+ } = opts;
374
+ let {
375
+ skipValidate,
376
+ searchReplace
377
+ } = opts;
378
+ const {
379
+ id: envId,
380
+ appId
381
+ } = env;
382
+ const [fileName] = arg;
383
+ const isMultiSite = await (0, _isMultiSite.isMultiSiteInSiteMeta)(appId, envId);
384
+ let 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
+
392
+ debug('Options: ', opts);
393
+ debug('Args: ', arg);
394
+
395
+ const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
396
+
397
+ await track('import_sql_command_execute'); // // halt operation of the import based on some rules
398
+
399
+ await gates(app, env, fileName); // Log summary of import details
400
+
401
+ const domain = env !== null && env !== void 0 && (_env$primaryDomain = env.primaryDomain) !== null && _env$primaryDomain !== void 0 && _env$primaryDomain.name ? env.primaryDomain.name : `#${env.id}`;
402
+ const formattedEnvironment = (0, _format.formatEnvironment)(opts.env.type);
403
+ const launched = opts.env.launched;
404
+ let fileNameToUpload = fileName; // SQL file validations
405
+
406
+ const tableNames = await validateAndGetTableNames({
407
+ skipValidate,
408
+ appId,
409
+ envId,
410
+ fileNameToUpload
411
+ }); // display playbook of what will happen during execution
412
+
413
+ displayPlaybook({
414
+ launched,
415
+ tableNames,
416
+ searchReplace,
417
+ fileName,
418
+ domain,
419
+ formattedEnvironment,
420
+ isMultiSite,
421
+ app
422
+ }); // PROMPT TO PROCEED WITH THE IMPORT
423
+
424
+ await promptToContinue({
425
+ launched,
426
+ formattedEnvironment,
427
+ track,
428
+ domain
429
+ });
430
+ /**
431
+ * =========== WARNING =============
432
+ *
433
+ * NO `console.log` after this point!
434
+ * Yes, even inside called functions.
435
+ * It will break the progress printing.
436
+ *
437
+ * =========== WARNING =============
438
+ */
439
+
440
+ const progressTracker = new _progress.ProgressTracker(SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS);
441
+ let status = 'running';
442
+
443
+ const setProgressTrackerPrefixAndSuffix = () => {
444
+ progressTracker.prefix = `
445
+ =============================================================
446
+ Processing the SQL import for your environment...
447
+ `;
448
+ progressTracker.suffix = `\n${(0, _format.getGlyphForStatus)(status, progressTracker.runningSprite)} ${status === 'running' ? 'Loading remaining steps' : ''}`; // TODO: maybe use progress tracker status
449
+ };
450
+
451
+ const failWithError = failureError => {
452
+ status = 'failed';
453
+ setProgressTrackerPrefixAndSuffix();
454
+ progressTracker.stopPrinting();
455
+ progressTracker.print({
456
+ clearAfter: true
457
+ });
458
+
459
+ _rollbar.rollbar.error(failureError);
460
+
461
+ exit.withError(failureError);
462
+ };
463
+
464
+ progressTracker.startPrinting(setProgressTrackerPrefixAndSuffix); // Run Search and Replace if the --search-replace flag was provided
465
+
466
+ if (searchReplace && searchReplace.length) {
467
+ progressTracker.stepRunning('replace');
468
+ const {
469
+ outputFileName
470
+ } = await (0, _searchAndReplace.searchAndReplace)(fileName, searchReplace, {
471
+ isImport: true,
472
+ inPlace: opts.inPlace,
473
+ output: true
474
+ });
475
+
476
+ if (typeof outputFileName !== 'string') {
477
+ progressTracker.stepFailed('replace');
478
+ return failWithError('Unable to determine location of the intermediate search & replace file.');
479
+ }
480
+
481
+ fileNameToUpload = outputFileName;
482
+ fileMeta = await (0, _clientFileUploader.getFileMeta)(fileNameToUpload);
483
+ progressTracker.stepSuccess('replace');
484
+ } else {
485
+ progressTracker.stepSkipped('replace');
486
+ }
487
+
488
+ progressTracker.stepRunning('upload'); // Call the Public API
489
+
490
+ const api = await (0, _api.default)();
491
+ const startImportVariables = {};
492
+
493
+ const progressCallback = percentage => {
494
+ progressTracker.setUploadPercentage(percentage);
495
+ };
496
+
497
+ fileMeta.fileName = fileNameToUpload;
498
+
499
+ try {
500
+ const {
501
+ fileMeta: {
502
+ basename
503
+ },
504
+ md5,
505
+ result
506
+ } = await (0, _clientFileUploader.uploadImportSqlFileToS3)({
507
+ app,
508
+ env,
509
+ fileMeta,
510
+ progressCallback
511
+ });
512
+ startImportVariables.input = {
513
+ id: app.id,
514
+ environmentId: env.id,
515
+ basename: basename,
516
+ md5: md5,
517
+ searchReplace: []
518
+ };
519
+
520
+ if (searchReplace) {
521
+ let pairs = searchReplace;
522
+
523
+ if (!Array.isArray(pairs)) {
524
+ pairs = [searchReplace];
525
+ } // determine all the replacements required
526
+
527
+
528
+ const replacementsArr = pairs.map(pair => pair.split(',').map(str => str.trim()));
529
+ startImportVariables.input.searchReplace = replacementsArr.map(arr => {
530
+ return {
531
+ from: arr[0],
532
+ to: arr[1]
533
+ };
534
+ });
535
+ }
536
+
537
+ debug({
538
+ basename,
539
+ md5,
540
+ result,
541
+ startImportVariables
542
+ });
543
+ debug('Upload complete. Initiating the import.');
544
+ progressTracker.stepSuccess('upload');
545
+ await track('import_sql_upload_complete');
546
+ } catch (uploadError) {
547
+ await track('import_sql_command_error', {
548
+ error_type: 'upload_failed',
549
+ upload_error: uploadError
550
+ });
551
+ progressTracker.stepFailed('upload');
552
+ return failWithError(uploadError);
553
+ } // Start the import
554
+
555
+
556
+ try {
557
+ const startImportResults = await api.mutate({
558
+ mutation: START_IMPORT_MUTATION,
559
+ variables: startImportVariables
560
+ });
561
+ debug({
562
+ startImportResults
563
+ });
564
+ } catch (gqlErr) {
565
+ progressTracker.stepFailed('queue_import');
566
+ await track('import_sql_command_error', {
567
+ error_type: 'StartImport-failed',
568
+ gql_err: gqlErr
569
+ });
570
+ progressTracker.stepFailed('queue_import');
571
+ return failWithError(`StartImport call failed: ${gqlErr}`);
572
+ }
573
+
574
+ progressTracker.stepSuccess('queue_import');
575
+ await (0, _status.importSqlCheckStatus)({
576
+ app,
577
+ env,
578
+ progressTracker
579
+ });
580
+ });