@automattic/vip 2.21.0 → 2.23.0
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/CHANGELOG.md +23 -0
- package/assets/dev-env.lando.template.yml.ejs +1 -1
- package/automattic-vip-2.23.0.tgz +0 -0
- package/dist/bin/vip-app-list.js +0 -12
- package/dist/bin/vip-app.js +6 -13
- package/dist/bin/vip-cache-purge-url.js +4 -19
- package/dist/bin/vip-cache.js +0 -2
- package/dist/bin/vip-config-envvar-delete.js +4 -19
- package/dist/bin/vip-config-envvar-get-all.js +6 -19
- package/dist/bin/vip-config-envvar-get.js +4 -15
- package/dist/bin/vip-config-envvar-list.js +8 -20
- package/dist/bin/vip-config-envvar-set.js +4 -23
- package/dist/bin/vip-config-envvar.js +0 -2
- package/dist/bin/vip-config-software-get.js +0 -17
- package/dist/bin/vip-config-software-update.js +6 -22
- package/dist/bin/vip-config-software.js +0 -2
- package/dist/bin/vip-config.js +0 -2
- package/dist/bin/vip-dev-env-create.js +0 -18
- package/dist/bin/vip-dev-env-destroy.js +0 -9
- package/dist/bin/vip-dev-env-exec.js +0 -12
- package/dist/bin/vip-dev-env-import-media.js +0 -7
- package/dist/bin/vip-dev-env-import-sql.js +2 -17
- package/dist/bin/vip-dev-env-import.js +0 -3
- package/dist/bin/vip-dev-env-info.js +0 -10
- package/dist/bin/vip-dev-env-list.js +0 -7
- package/dist/bin/vip-dev-env-start.js +4 -14
- package/dist/bin/vip-dev-env-stop.js +0 -9
- package/dist/bin/vip-dev-env-update.js +0 -11
- package/dist/bin/vip-dev-env.js +0 -2
- package/dist/bin/vip-import-media-abort.js +0 -18
- package/dist/bin/vip-import-media-status.js +0 -12
- package/dist/bin/vip-import-media.js +6 -23
- package/dist/bin/vip-import-sql-status.js +0 -12
- package/dist/bin/vip-import-sql.js +40 -103
- package/dist/bin/vip-import-validate-files.js +21 -42
- package/dist/bin/vip-import-validate-sql.js +0 -8
- package/dist/bin/vip-import.js +0 -3
- package/dist/bin/vip-logs.js +20 -50
- package/dist/bin/vip-search-replace.js +8 -14
- package/dist/bin/vip-sync.js +2 -25
- package/dist/bin/vip-validate-preflight.js +427 -0
- package/dist/bin/vip-validate.js +19 -0
- package/dist/bin/vip-whoami.js +2 -14
- package/dist/bin/vip-wp.js +39 -89
- package/dist/bin/vip.js +5 -35
- package/dist/lib/analytics/clients/pendo.js +9 -18
- package/dist/lib/analytics/clients/stub.js +1 -3
- package/dist/lib/analytics/clients/tracks.js +11 -20
- package/dist/lib/analytics/index.js +4 -11
- package/dist/lib/api/app.js +1 -11
- package/dist/lib/api/cache-purge.js +4 -7
- package/dist/lib/api/feature-flags.js +1 -4
- package/dist/lib/api/http.js +9 -15
- package/dist/lib/api/user.js +1 -7
- package/dist/lib/api.js +17 -19
- package/dist/lib/app-logs/app-logs.js +2 -9
- package/dist/lib/app.js +2 -5
- package/dist/lib/cli/apiConfig.js +4 -19
- package/dist/lib/cli/command.js +43 -133
- package/dist/lib/cli/config.js +1 -5
- package/dist/lib/cli/envAlias.js +14 -15
- package/dist/lib/cli/exit.js +4 -6
- package/dist/lib/cli/format.js +8 -50
- package/dist/lib/cli/progress.js +13 -42
- package/dist/lib/cli/prompt.js +1 -5
- package/dist/lib/cli/repo.js +7 -20
- package/dist/lib/client-file-uploader.js +44 -97
- package/dist/lib/config/software.js +2 -52
- package/dist/lib/constants/dev-environment.js +1 -2
- package/dist/lib/constants/file-size.js +1 -1
- package/dist/lib/constants/vipgo.js +1 -1
- package/dist/lib/dev-environment/dev-environment-cli.js +68 -155
- package/dist/lib/dev-environment/dev-environment-core.js +73 -194
- package/dist/lib/dev-environment/dev-environment-lando.js +16 -71
- package/dist/lib/env.js +1 -4
- package/dist/lib/envvar/api-delete.js +1 -4
- package/dist/lib/envvar/api-get-all.js +1 -4
- package/dist/lib/envvar/api-get.js +1 -2
- package/dist/lib/envvar/api-list.js +3 -4
- package/dist/lib/envvar/api-set.js +1 -4
- package/dist/lib/envvar/api.js +5 -16
- package/dist/lib/envvar/input.js +1 -8
- package/dist/lib/envvar/logging.js +2 -6
- package/dist/lib/envvar/read-file.js +1 -3
- package/dist/lib/http/proxy-agent.js +17 -22
- package/dist/lib/keychain/browser.js +1 -4
- package/dist/lib/keychain/insecure.js +1 -10
- package/dist/lib/keychain/secure.js +1 -8
- package/dist/lib/keychain.js +4 -8
- package/dist/lib/logout.js +0 -6
- package/dist/lib/media-import/media-file-import.js +3 -7
- package/dist/lib/media-import/progress.js +6 -17
- package/dist/lib/media-import/status.js +14 -65
- package/dist/lib/read-file.js +1 -6
- package/dist/lib/rollbar.js +1 -7
- package/dist/lib/search-and-replace.js +9 -41
- package/dist/lib/site-import/db-file-import.js +3 -9
- package/dist/lib/site-import/status.js +17 -74
- package/dist/lib/token.js +1 -33
- package/dist/lib/tracker.js +4 -20
- package/dist/lib/user-error.js +0 -2
- package/dist/lib/validations/is-multi-site-sql-dump.js +4 -12
- package/dist/lib/validations/is-multi-site.js +5 -21
- package/dist/lib/validations/is-multisite-domain-mapped.js +5 -31
- package/dist/lib/validations/line-by-line.js +4 -16
- package/dist/lib/validations/site-type.js +10 -19
- package/dist/lib/validations/sql.js +11 -76
- package/dist/lib/validations/utils.js +1 -6
- package/dist/lib/vip-import-validate-files.js +82 -109
- package/npm-shrinkwrap.json +2407 -1800
- package/package.json +18 -15
|
@@ -15,53 +15,29 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
15
15
|
});
|
|
16
16
|
exports.gates = gates;
|
|
17
17
|
exports.validateAndGetTableNames = validateAndGetTableNames;
|
|
18
|
-
|
|
19
18
|
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
20
|
-
|
|
21
19
|
var _cliColumns = _interopRequireDefault(require("cli-columns"));
|
|
22
|
-
|
|
23
20
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
24
|
-
|
|
25
21
|
var _debug = _interopRequireDefault(require("debug"));
|
|
26
|
-
|
|
27
22
|
var _enquirer = require("enquirer");
|
|
28
|
-
|
|
29
23
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
30
|
-
|
|
31
24
|
var _dbFileImport = require("../lib/site-import/db-file-import");
|
|
32
|
-
|
|
33
25
|
var _status = require("../lib/site-import/status");
|
|
34
|
-
|
|
35
26
|
var _clientFileUploader = require("../lib/client-file-uploader");
|
|
36
|
-
|
|
37
27
|
var _tracker = require("../lib/tracker");
|
|
38
|
-
|
|
39
28
|
var _sql = require("../lib/validations/sql");
|
|
40
|
-
|
|
41
29
|
var _siteType = require("../lib/validations/site-type");
|
|
42
|
-
|
|
43
30
|
var _searchAndReplace = require("../lib/search-and-replace");
|
|
44
|
-
|
|
45
31
|
var _api = _interopRequireDefault(require("../lib/api"));
|
|
46
|
-
|
|
47
32
|
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
48
|
-
|
|
49
33
|
var _lineByLine = require("../lib/validations/line-by-line");
|
|
50
|
-
|
|
51
34
|
var _format = require("../lib/cli/format");
|
|
52
|
-
|
|
53
35
|
var _progress = require("../lib/cli/progress");
|
|
54
|
-
|
|
55
36
|
var _isMultiSite = require("../lib/validations/is-multi-site");
|
|
56
|
-
|
|
57
37
|
var _rollbar = require("../lib/rollbar");
|
|
58
|
-
|
|
59
38
|
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
39
|
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
40
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
64
|
-
|
|
65
41
|
/**
|
|
66
42
|
* Internal dependencies
|
|
67
43
|
*/
|
|
@@ -114,29 +90,24 @@ const SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS = [{
|
|
|
114
90
|
id: 'queue_import',
|
|
115
91
|
name: 'Queueing Import'
|
|
116
92
|
}];
|
|
117
|
-
|
|
118
93
|
async function gates(app, env, fileName) {
|
|
119
94
|
const {
|
|
120
95
|
id: envId,
|
|
121
96
|
appId
|
|
122
97
|
} = env;
|
|
123
|
-
|
|
124
98
|
const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
|
|
125
|
-
|
|
126
99
|
if (!(0, _dbFileImport.currentUserCanImportForApp)(app)) {
|
|
127
100
|
await track('import_sql_command_error', {
|
|
128
101
|
error_type: 'unauthorized'
|
|
129
102
|
});
|
|
130
103
|
exit.withError('The currently authenticated account does not have permission to perform a SQL import.');
|
|
131
104
|
}
|
|
132
|
-
|
|
133
105
|
if (!(0, _dbFileImport.isSupportedApp)(app)) {
|
|
134
106
|
await track('import_sql_command_error', {
|
|
135
107
|
error_type: 'unsupported-app'
|
|
136
108
|
});
|
|
137
109
|
exit.withError('The type of application you specified does not currently support SQL imports.');
|
|
138
110
|
}
|
|
139
|
-
|
|
140
111
|
try {
|
|
141
112
|
await (0, _clientFileUploader.checkFileAccess)(fileName);
|
|
142
113
|
} catch (err) {
|
|
@@ -145,25 +116,20 @@ async function gates(app, env, fileName) {
|
|
|
145
116
|
});
|
|
146
117
|
exit.withError(`File '${fileName}' does not exist or is not readable.`);
|
|
147
118
|
}
|
|
148
|
-
|
|
149
119
|
if (!(await (0, _clientFileUploader.isFile)(fileName))) {
|
|
150
120
|
await track('import_sql_command_error', {
|
|
151
121
|
error_type: 'sqlfile-notfile'
|
|
152
122
|
});
|
|
153
123
|
exit.withError(`Path '${fileName}' is not a file.`);
|
|
154
124
|
}
|
|
155
|
-
|
|
156
125
|
const fileSize = await (0, _clientFileUploader.getFileSize)(fileName);
|
|
157
|
-
|
|
158
126
|
if (!fileSize) {
|
|
159
127
|
await track('import_sql_command_error', {
|
|
160
128
|
error_type: 'sqlfile-empty'
|
|
161
129
|
});
|
|
162
130
|
exit.withError(`File '${fileName}' is empty.`);
|
|
163
131
|
}
|
|
164
|
-
|
|
165
132
|
const maxFileSize = env !== null && env !== void 0 && env.launched ? _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED : _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT;
|
|
166
|
-
|
|
167
133
|
if (fileSize > maxFileSize) {
|
|
168
134
|
await track('import_sql_command_error', {
|
|
169
135
|
error_type: 'sqlfile-toobig',
|
|
@@ -172,59 +138,59 @@ async function gates(app, env, fileName) {
|
|
|
172
138
|
});
|
|
173
139
|
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
140
|
}
|
|
175
|
-
|
|
176
141
|
if (!(env !== null && env !== void 0 && env.importStatus)) {
|
|
177
142
|
await track('import_sql_command_error', {
|
|
178
143
|
error_type: 'empty-import-status'
|
|
179
144
|
});
|
|
180
145
|
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
146
|
}
|
|
182
|
-
|
|
183
147
|
const {
|
|
184
148
|
importStatus: {
|
|
185
149
|
dbOperationInProgress,
|
|
186
150
|
importInProgress
|
|
187
151
|
}
|
|
188
152
|
} = env;
|
|
189
|
-
|
|
190
153
|
if (importInProgress) {
|
|
191
154
|
await track('import_sql_command_error', {
|
|
192
155
|
error_type: 'existing-import'
|
|
193
156
|
});
|
|
194
157
|
exit.withError('There is already an import in progress.\n\nYou can view the status with command:\n vip import sql status');
|
|
195
158
|
}
|
|
196
|
-
|
|
197
159
|
if (dbOperationInProgress) {
|
|
198
160
|
await track('import_sql_command_error', {
|
|
199
161
|
error_type: 'existing-dbop'
|
|
200
162
|
});
|
|
201
163
|
exit.withError('There is already a database operation in progress. Please try again later.');
|
|
202
164
|
}
|
|
203
|
-
}
|
|
204
|
-
|
|
165
|
+
}
|
|
205
166
|
|
|
206
|
-
|
|
167
|
+
// Command examples for the `vip import sql` help prompt
|
|
168
|
+
const examples = [
|
|
169
|
+
// `sql` subcommand
|
|
207
170
|
{
|
|
208
171
|
usage: 'vip import sql @mysite.develop <file.sql>',
|
|
209
172
|
description: 'Import the given SQL file to your site'
|
|
210
|
-
},
|
|
173
|
+
},
|
|
174
|
+
// `search-replace` flag
|
|
211
175
|
{
|
|
212
176
|
usage: 'vip import sql @mysite.develop <file.sql> --search-replace="from,to"',
|
|
213
177
|
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
|
-
},
|
|
178
|
+
},
|
|
179
|
+
// `in-place` flag
|
|
215
180
|
{
|
|
216
181
|
usage: 'vip import sql @mysite.develop <file.sql> --search-replace="from,to" --in-place',
|
|
217
182
|
description: 'Search and Replace on the input <file.sql>, then import the replaced file to your site'
|
|
218
|
-
},
|
|
183
|
+
},
|
|
184
|
+
// `output` flag
|
|
219
185
|
{
|
|
220
186
|
usage: 'vip import sql @mysite.develop <file.sql> --search-replace="from,to" --output="<output.sql>"',
|
|
221
187
|
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
|
-
},
|
|
188
|
+
},
|
|
189
|
+
// `sql status` subcommand
|
|
223
190
|
{
|
|
224
191
|
usage: 'vip import sql status @mysite.develop',
|
|
225
192
|
description: 'Check the status of the most recent import. If an import is running, this will poll until it is complete.'
|
|
226
193
|
}];
|
|
227
|
-
|
|
228
194
|
const promptToContinue = async ({
|
|
229
195
|
launched,
|
|
230
196
|
formattedEnvironment,
|
|
@@ -238,13 +204,11 @@ const promptToContinue = async ({
|
|
|
238
204
|
name: 'confirmedDomain',
|
|
239
205
|
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
206
|
});
|
|
241
|
-
|
|
242
207
|
if (promptResponse.confirmedDomain !== promptToMatch) {
|
|
243
208
|
await track('import_sql_unexpected_tables');
|
|
244
209
|
exit.withError('The input did not match the expected environment label. Import aborted.');
|
|
245
210
|
}
|
|
246
211
|
};
|
|
247
|
-
|
|
248
212
|
async function validateAndGetTableNames({
|
|
249
213
|
skipValidate,
|
|
250
214
|
appId,
|
|
@@ -253,12 +217,10 @@ async function validateAndGetTableNames({
|
|
|
253
217
|
searchReplace
|
|
254
218
|
}) {
|
|
255
219
|
const validations = [_sql.staticSqlValidations, _siteType.siteTypeValidations];
|
|
256
|
-
|
|
257
220
|
if (skipValidate) {
|
|
258
221
|
console.log('Skipping SQL file validation.');
|
|
259
222
|
return [];
|
|
260
223
|
}
|
|
261
|
-
|
|
262
224
|
try {
|
|
263
225
|
await (0, _lineByLine.fileLineValidations)(appId, envId, fileNameToUpload, validations, searchReplace);
|
|
264
226
|
} catch (validateErr) {
|
|
@@ -266,12 +228,10 @@ async function validateAndGetTableNames({
|
|
|
266
228
|
exit.withError(`${validateErr.message}\n
|
|
267
229
|
If you are confident the file does not contain unsupported statements, you can retry the command with the ${_chalk.default.yellow('--skip-validate')} option.
|
|
268
230
|
`);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
|
|
231
|
+
}
|
|
232
|
+
// this can only be called after static validation of the SQL file
|
|
272
233
|
return (0, _sql.getTableNames)();
|
|
273
234
|
}
|
|
274
|
-
|
|
275
235
|
const displayPlaybook = ({
|
|
276
236
|
launched,
|
|
277
237
|
tableNames,
|
|
@@ -279,6 +239,7 @@ const displayPlaybook = ({
|
|
|
279
239
|
fileName,
|
|
280
240
|
domain,
|
|
281
241
|
formattedEnvironment,
|
|
242
|
+
unformattedEnvironment,
|
|
282
243
|
isMultiSite,
|
|
283
244
|
app
|
|
284
245
|
}) => {
|
|
@@ -286,38 +247,31 @@ const displayPlaybook = ({
|
|
|
286
247
|
console.log(` importing: ${_chalk.default.blueBright(fileName)}`);
|
|
287
248
|
console.log(` to: ${_chalk.default.cyan(domain)}`);
|
|
288
249
|
console.log(` site: ${app.name} (${formattedEnvironment})`);
|
|
289
|
-
|
|
290
250
|
if (searchReplace !== null && searchReplace !== void 0 && searchReplace.length) {
|
|
291
251
|
const output = (from, to) => {
|
|
292
252
|
const message = ` s-r: ${_chalk.default.blue(from)} -> ${_chalk.default.blue(to)}`;
|
|
293
253
|
console.log(message);
|
|
294
254
|
};
|
|
295
|
-
|
|
296
255
|
(0, _format.formatSearchReplaceValues)(searchReplace, output);
|
|
297
256
|
}
|
|
298
|
-
|
|
299
257
|
let siteArray = [];
|
|
300
|
-
|
|
301
258
|
if (isMultiSite) {
|
|
302
|
-
var _app$environments
|
|
303
|
-
|
|
259
|
+
var _app$environments, _selectedEnvironmentO;
|
|
304
260
|
// eslint-disable-next-line no-multi-spaces
|
|
305
261
|
console.log(` multisite: ${isMultiSite.toString()}`);
|
|
306
|
-
|
|
262
|
+
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);
|
|
263
|
+
siteArray = selectedEnvironmentObj === null || selectedEnvironmentObj === void 0 ? void 0 : (_selectedEnvironmentO = selectedEnvironmentObj.wpSites) === null || _selectedEnvironmentO === void 0 ? void 0 : _selectedEnvironmentO.nodes;
|
|
307
264
|
}
|
|
308
|
-
|
|
309
265
|
if (!tableNames.length) {
|
|
310
266
|
debug('Validation was skipped, no playbook information will be displayed');
|
|
311
267
|
} else {
|
|
312
268
|
// output the table names
|
|
313
269
|
console.log();
|
|
314
|
-
|
|
315
270
|
if (!isMultiSite) {
|
|
316
271
|
console.log('Below are a list of Tables that will be imported by this process:');
|
|
317
272
|
console.log((0, _cliColumns.default)(tableNames));
|
|
318
273
|
} else {
|
|
319
274
|
var _siteArray;
|
|
320
|
-
|
|
321
275
|
// we have siteArray from the API, use it and the table names together
|
|
322
276
|
if (siteArray === 'undefined' || !siteArray) {
|
|
323
277
|
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.'));
|
|
@@ -325,16 +279,13 @@ const displayPlaybook = ({
|
|
|
325
279
|
} else if (!((_siteArray = siteArray) !== null && _siteArray !== void 0 && _siteArray.length)) {
|
|
326
280
|
throw new Error('There were no sites in your multisite installation');
|
|
327
281
|
}
|
|
328
|
-
|
|
329
282
|
const multiSiteBreakdown = siteArray.map(wpSite => {
|
|
330
283
|
let siteRegex;
|
|
331
|
-
|
|
332
284
|
if (wpSite.id === 1) {
|
|
333
|
-
siteRegex =
|
|
285
|
+
siteRegex = /^wp_[a-z]+/i;
|
|
334
286
|
} else {
|
|
335
|
-
siteRegex = new RegExp(
|
|
287
|
+
siteRegex = new RegExp(`^wp_${wpSite.id}_[a-z]+`, 'i');
|
|
336
288
|
}
|
|
337
|
-
|
|
338
289
|
const tableNamesInGroup = tableNames.filter(name => siteRegex.test(name));
|
|
339
290
|
return {
|
|
340
291
|
id: wpSite.id,
|
|
@@ -342,11 +293,9 @@ const displayPlaybook = ({
|
|
|
342
293
|
tables: tableNamesInGroup
|
|
343
294
|
};
|
|
344
295
|
});
|
|
345
|
-
|
|
346
296
|
if (launched) {
|
|
347
297
|
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.'));
|
|
348
298
|
}
|
|
349
|
-
|
|
350
299
|
console.log(_chalk.default.yellow('The following sites will be affected by the import:'));
|
|
351
300
|
multiSiteBreakdown.map(siteObject => {
|
|
352
301
|
console.log();
|
|
@@ -356,7 +305,6 @@ const displayPlaybook = ({
|
|
|
356
305
|
}
|
|
357
306
|
}
|
|
358
307
|
};
|
|
359
|
-
|
|
360
308
|
(0, _command.default)({
|
|
361
309
|
appContext: true,
|
|
362
310
|
appQuery,
|
|
@@ -365,7 +313,6 @@ const displayPlaybook = ({
|
|
|
365
313
|
module: 'import-sql'
|
|
366
314
|
}).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) => {
|
|
367
315
|
var _env$primaryDomain;
|
|
368
|
-
|
|
369
316
|
const {
|
|
370
317
|
app,
|
|
371
318
|
env
|
|
@@ -381,35 +328,35 @@ const displayPlaybook = ({
|
|
|
381
328
|
const [fileName] = arg;
|
|
382
329
|
const isMultiSite = await (0, _isMultiSite.isMultiSiteInSiteMeta)(appId, envId);
|
|
383
330
|
let fileMeta = await (0, _clientFileUploader.getFileMeta)(fileName);
|
|
384
|
-
|
|
385
331
|
if (fileMeta.isCompressed) {
|
|
386
332
|
console.log(_chalk.default.yellowBright('You are importing a compressed file. Validation and search-replace operation will be skipped.'));
|
|
387
333
|
skipValidate = true;
|
|
388
334
|
searchReplace = undefined;
|
|
389
335
|
}
|
|
390
|
-
|
|
391
336
|
debug('Options: ', opts);
|
|
392
337
|
debug('Args: ', arg);
|
|
393
|
-
|
|
394
338
|
const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
|
|
339
|
+
await track('import_sql_command_execute');
|
|
395
340
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
await gates(app, env, fileName); // Log summary of import details
|
|
341
|
+
// // halt operation of the import based on some rules
|
|
342
|
+
await gates(app, env, fileName);
|
|
399
343
|
|
|
344
|
+
// Log summary of import details
|
|
400
345
|
const domain = env !== null && env !== void 0 && (_env$primaryDomain = env.primaryDomain) !== null && _env$primaryDomain !== void 0 && _env$primaryDomain.name ? env.primaryDomain.name : `#${env.id}`;
|
|
401
346
|
const formattedEnvironment = (0, _format.formatEnvironment)(opts.env.type);
|
|
402
347
|
const launched = opts.env.launched;
|
|
403
|
-
let fileNameToUpload = fileName;
|
|
348
|
+
let fileNameToUpload = fileName;
|
|
404
349
|
|
|
350
|
+
// SQL file validations
|
|
405
351
|
const tableNames = await validateAndGetTableNames({
|
|
406
352
|
skipValidate,
|
|
407
353
|
appId,
|
|
408
354
|
envId,
|
|
409
355
|
fileNameToUpload,
|
|
410
356
|
searchReplace
|
|
411
|
-
});
|
|
357
|
+
});
|
|
412
358
|
|
|
359
|
+
// display playbook of what will happen during execution
|
|
413
360
|
displayPlaybook({
|
|
414
361
|
launched,
|
|
415
362
|
tableNames,
|
|
@@ -417,16 +364,19 @@ const displayPlaybook = ({
|
|
|
417
364
|
fileName,
|
|
418
365
|
domain,
|
|
419
366
|
formattedEnvironment,
|
|
367
|
+
unformattedEnvironment: opts.env.type,
|
|
420
368
|
isMultiSite,
|
|
421
369
|
app
|
|
422
|
-
});
|
|
370
|
+
});
|
|
423
371
|
|
|
372
|
+
// PROMPT TO PROCEED WITH THE IMPORT
|
|
424
373
|
await promptToContinue({
|
|
425
374
|
launched,
|
|
426
375
|
formattedEnvironment,
|
|
427
376
|
track,
|
|
428
377
|
domain
|
|
429
378
|
});
|
|
379
|
+
|
|
430
380
|
/**
|
|
431
381
|
* =========== WARNING =============
|
|
432
382
|
*
|
|
@@ -436,10 +386,8 @@ const displayPlaybook = ({
|
|
|
436
386
|
*
|
|
437
387
|
* =========== WARNING =============
|
|
438
388
|
*/
|
|
439
|
-
|
|
440
389
|
const progressTracker = new _progress.ProgressTracker(SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS);
|
|
441
390
|
let status = 'running';
|
|
442
|
-
|
|
443
391
|
const setProgressTrackerPrefixAndSuffix = () => {
|
|
444
392
|
progressTracker.prefix = `
|
|
445
393
|
=============================================================
|
|
@@ -455,14 +403,12 @@ Processing the SQL import for your environment...
|
|
|
455
403
|
progressTracker.print({
|
|
456
404
|
clearAfter: true
|
|
457
405
|
});
|
|
458
|
-
|
|
459
406
|
_rollbar.rollbar.error(failureError);
|
|
460
|
-
|
|
461
407
|
exit.withError(failureError);
|
|
462
408
|
};
|
|
409
|
+
progressTracker.startPrinting(setProgressTrackerPrefixAndSuffix);
|
|
463
410
|
|
|
464
|
-
|
|
465
|
-
|
|
411
|
+
// Run Search and Replace if the --search-replace flag was provided
|
|
466
412
|
if (searchReplace && searchReplace.length) {
|
|
467
413
|
progressTracker.stepRunning('replace');
|
|
468
414
|
const {
|
|
@@ -472,30 +418,25 @@ Processing the SQL import for your environment...
|
|
|
472
418
|
inPlace: opts.inPlace,
|
|
473
419
|
output: true
|
|
474
420
|
});
|
|
475
|
-
|
|
476
421
|
if (typeof outputFileName !== 'string') {
|
|
477
422
|
progressTracker.stepFailed('replace');
|
|
478
423
|
return failWithError('Unable to determine location of the intermediate search & replace file.');
|
|
479
424
|
}
|
|
480
|
-
|
|
481
425
|
fileNameToUpload = outputFileName;
|
|
482
426
|
fileMeta = await (0, _clientFileUploader.getFileMeta)(fileNameToUpload);
|
|
483
427
|
progressTracker.stepSuccess('replace');
|
|
484
428
|
} else {
|
|
485
429
|
progressTracker.stepSkipped('replace');
|
|
486
430
|
}
|
|
431
|
+
progressTracker.stepRunning('upload');
|
|
487
432
|
|
|
488
|
-
|
|
489
|
-
|
|
433
|
+
// Call the Public API
|
|
490
434
|
const api = await (0, _api.default)();
|
|
491
435
|
const startImportVariables = {};
|
|
492
|
-
|
|
493
436
|
const progressCallback = percentage => {
|
|
494
437
|
progressTracker.setUploadPercentage(percentage);
|
|
495
438
|
};
|
|
496
|
-
|
|
497
439
|
fileMeta.fileName = fileNameToUpload;
|
|
498
|
-
|
|
499
440
|
try {
|
|
500
441
|
const {
|
|
501
442
|
fileMeta: {
|
|
@@ -516,15 +457,13 @@ Processing the SQL import for your environment...
|
|
|
516
457
|
md5: md5,
|
|
517
458
|
searchReplace: []
|
|
518
459
|
};
|
|
519
|
-
|
|
520
460
|
if (searchReplace) {
|
|
521
461
|
let pairs = searchReplace;
|
|
522
|
-
|
|
523
462
|
if (!Array.isArray(pairs)) {
|
|
524
463
|
pairs = [searchReplace];
|
|
525
|
-
}
|
|
526
|
-
|
|
464
|
+
}
|
|
527
465
|
|
|
466
|
+
// determine all the replacements required
|
|
528
467
|
const replacementsArr = pairs.map(pair => pair.split(',').map(str => str.trim()));
|
|
529
468
|
startImportVariables.input.searchReplace = replacementsArr.map(arr => {
|
|
530
469
|
return {
|
|
@@ -533,7 +472,6 @@ Processing the SQL import for your environment...
|
|
|
533
472
|
};
|
|
534
473
|
});
|
|
535
474
|
}
|
|
536
|
-
|
|
537
475
|
debug({
|
|
538
476
|
basename,
|
|
539
477
|
md5,
|
|
@@ -550,9 +488,9 @@ Processing the SQL import for your environment...
|
|
|
550
488
|
});
|
|
551
489
|
progressTracker.stepFailed('upload');
|
|
552
490
|
return failWithError(uploadError);
|
|
553
|
-
}
|
|
554
|
-
|
|
491
|
+
}
|
|
555
492
|
|
|
493
|
+
// Start the import
|
|
556
494
|
try {
|
|
557
495
|
const startImportResults = await api.mutate({
|
|
558
496
|
mutation: START_IMPORT_MUTATION,
|
|
@@ -570,7 +508,6 @@ Processing the SQL import for your environment...
|
|
|
570
508
|
progressTracker.stepFailed('queue_import');
|
|
571
509
|
return failWithError(`StartImport call failed: ${gqlErr}`);
|
|
572
510
|
}
|
|
573
|
-
|
|
574
511
|
progressTracker.stepSuccess('queue_import');
|
|
575
512
|
await (0, _status.importSqlCheckStatus)({
|
|
576
513
|
app,
|
|
@@ -6,23 +6,14 @@
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
8
|
var _url = _interopRequireDefault(require("url"));
|
|
9
|
-
|
|
10
9
|
var _path = _interopRequireDefault(require("path"));
|
|
11
|
-
|
|
12
10
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
13
|
-
|
|
14
11
|
var _fs = _interopRequireDefault(require("fs"));
|
|
15
|
-
|
|
16
12
|
var _util = require("util");
|
|
17
|
-
|
|
18
13
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
19
|
-
|
|
20
14
|
var _vipImportValidateFiles = require("../lib/vip-import-validate-files");
|
|
21
|
-
|
|
22
15
|
var _tracker = require("../lib/tracker");
|
|
23
|
-
|
|
24
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
|
-
|
|
26
17
|
/**
|
|
27
18
|
* Internal dependencies
|
|
28
19
|
*/
|
|
@@ -38,14 +29,12 @@ const stat = (0, _util.promisify)(_fs.default.stat);
|
|
|
38
29
|
*
|
|
39
30
|
* Manipulating the file path/name to extract the folder name
|
|
40
31
|
*/
|
|
41
|
-
|
|
42
32
|
const folder = arg.join(); // File comes in as an array as part of the args- turn it into a string
|
|
43
|
-
|
|
44
33
|
arg = _url.default.parse(folder); // Then parse the file to its URL parts
|
|
45
|
-
|
|
46
34
|
const filePath = arg.path; // Extract the path of the file
|
|
47
35
|
|
|
48
36
|
let folderValidation;
|
|
37
|
+
|
|
49
38
|
/**
|
|
50
39
|
* Folder structure validation
|
|
51
40
|
*
|
|
@@ -53,19 +42,18 @@ const stat = (0, _util.promisify)(_fs.default.stat);
|
|
|
53
42
|
*
|
|
54
43
|
* Recommended structure: `uploads/year/month` (Single sites)
|
|
55
44
|
*/
|
|
56
|
-
|
|
57
45
|
const nestedFiles = (0, _vipImportValidateFiles.findNestedDirectories)(filePath);
|
|
58
46
|
const {
|
|
59
47
|
files,
|
|
60
48
|
folderStructureObj
|
|
61
49
|
} = nestedFiles; // Destructure
|
|
62
|
-
// Check if there are any nested directories within the given folder
|
|
63
50
|
|
|
51
|
+
// Check if there are any nested directories within the given folder
|
|
64
52
|
const nestedDirectories = Object.keys(folderStructureObj);
|
|
65
|
-
|
|
66
53
|
if (nestedDirectories && nestedDirectories.length > 0) {
|
|
67
54
|
folderValidation = (0, _vipImportValidateFiles.folderStructureValidation)(nestedDirectories);
|
|
68
55
|
}
|
|
56
|
+
|
|
69
57
|
/**
|
|
70
58
|
* Individual file validations
|
|
71
59
|
*
|
|
@@ -73,56 +61,52 @@ const stat = (0, _util.promisify)(_fs.default.stat);
|
|
|
73
61
|
* - Filename validation
|
|
74
62
|
* - Intermediate image validation
|
|
75
63
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
64
|
if (!files || !files.length || files.length <= 0) {
|
|
79
65
|
console.error(_chalk.default.red('✕ Error:'), 'Media files directory cannot be empty');
|
|
80
66
|
}
|
|
67
|
+
|
|
81
68
|
/**
|
|
82
69
|
* Media file extension validation
|
|
83
70
|
*
|
|
84
71
|
* Ensure that prohibited media file types are not used
|
|
85
72
|
*/
|
|
86
|
-
// Collect invalid files for error logging
|
|
87
|
-
|
|
88
73
|
|
|
74
|
+
// Collect invalid files for error logging
|
|
89
75
|
let intermediateImagesTotal = 0;
|
|
90
76
|
const errorFileTypes = [];
|
|
91
77
|
const errorFileNames = [];
|
|
92
|
-
const intermediateImages = {};
|
|
78
|
+
const intermediateImages = {};
|
|
93
79
|
|
|
80
|
+
// Iterate through each file to isolate the extension name
|
|
94
81
|
for (const file of files) {
|
|
95
82
|
// Check if file is a directory
|
|
96
83
|
const stats = await stat(file);
|
|
97
84
|
const isFolder = stats.isDirectory();
|
|
98
|
-
|
|
99
85
|
const extension = _path.default.extname(file); // Extract the extension of the file
|
|
100
|
-
|
|
101
|
-
|
|
102
86
|
const ext = extension.substr(1); // We only want the ext name minus the period (e.g- .jpg -> jpg)
|
|
103
|
-
|
|
104
87
|
const extLowerCase = ext.toLowerCase(); // Change any uppercase extensions to lowercase
|
|
88
|
+
|
|
105
89
|
// Check for any invalid file extensions
|
|
106
90
|
// Returns true if ext is valid; false if invalid
|
|
91
|
+
const validExtensions = _vipImportValidateFiles.acceptedExtensions.includes(extLowerCase);
|
|
107
92
|
|
|
108
|
-
|
|
93
|
+
// Collect files that have no extension, have invalid extensions,
|
|
109
94
|
// or are directories for error logging
|
|
110
|
-
|
|
111
|
-
|
|
112
95
|
if (!extension || !validExtensions || isFolder) {
|
|
113
96
|
errorFileTypes.push(file);
|
|
114
97
|
}
|
|
98
|
+
|
|
115
99
|
/**
|
|
116
100
|
* Filename validation
|
|
117
101
|
*
|
|
118
102
|
* Ensure that filenames don't contain prohibited characters
|
|
119
103
|
*/
|
|
120
|
-
// Collect files that have invalid file names for error logging
|
|
121
|
-
|
|
122
104
|
|
|
105
|
+
// Collect files that have invalid file names for error logging
|
|
123
106
|
if ((0, _vipImportValidateFiles.isFileSanitized)(file)) {
|
|
124
107
|
errorFileNames.push(file);
|
|
125
108
|
}
|
|
109
|
+
|
|
126
110
|
/**
|
|
127
111
|
* Intermediate image validation
|
|
128
112
|
*
|
|
@@ -131,14 +115,12 @@ const stat = (0, _util.promisify)(_fs.default.stat);
|
|
|
131
115
|
* Intermediate images are copies of images that are resized, so you may have multiples of the same image.
|
|
132
116
|
* You can resize an image directly on VIP so intermediate images are not necessary.
|
|
133
117
|
*/
|
|
118
|
+
const original = (0, _vipImportValidateFiles.doesImageHaveExistingSource)(file);
|
|
134
119
|
|
|
135
|
-
|
|
136
|
-
const original = (0, _vipImportValidateFiles.doesImageHaveExistingSource)(file); // If an image is an intermediate image, increment the total number and
|
|
120
|
+
// If an image is an intermediate image, increment the total number and
|
|
137
121
|
// populate key/value pairs of the original image and intermediate image(s)
|
|
138
|
-
|
|
139
122
|
if (original) {
|
|
140
123
|
intermediateImagesTotal++;
|
|
141
|
-
|
|
142
124
|
if (intermediateImages[original]) {
|
|
143
125
|
// Key: original image, value: intermediate image(s)
|
|
144
126
|
intermediateImages[original] = `${intermediateImages[original]}, ${file}`;
|
|
@@ -147,24 +129,21 @@ const stat = (0, _util.promisify)(_fs.default.stat);
|
|
|
147
129
|
}
|
|
148
130
|
}
|
|
149
131
|
}
|
|
132
|
+
|
|
150
133
|
/**
|
|
151
134
|
* Error logging
|
|
152
135
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
155
136
|
if (errorFileTypes.length > 0) {
|
|
156
137
|
(0, _vipImportValidateFiles.logErrorsForInvalidFileTypes)(errorFileTypes);
|
|
157
138
|
}
|
|
158
|
-
|
|
159
139
|
if (errorFileNames.length > 0) {
|
|
160
140
|
(0, _vipImportValidateFiles.logErrorsForInvalidFilenames)(errorFileNames);
|
|
161
141
|
}
|
|
162
|
-
|
|
163
142
|
if (Object.keys(intermediateImages).length > 0) {
|
|
164
143
|
(0, _vipImportValidateFiles.logErrorsForIntermediateImages)(intermediateImages);
|
|
165
|
-
}
|
|
166
|
-
|
|
144
|
+
}
|
|
167
145
|
|
|
146
|
+
// Log a summary of all errors
|
|
168
147
|
(0, _vipImportValidateFiles.summaryLogs)({
|
|
169
148
|
folderErrorsLength: folderValidation.length,
|
|
170
149
|
intImagesErrorsLength: intermediateImagesTotal,
|
|
@@ -172,11 +151,11 @@ const stat = (0, _util.promisify)(_fs.default.stat);
|
|
|
172
151
|
filenameErrorsLength: errorFileNames.length,
|
|
173
152
|
totalFiles: files.length,
|
|
174
153
|
totalFolders: nestedDirectories.length
|
|
175
|
-
});
|
|
176
|
-
// Props (object keys) need to be in Snake case vs. camelCase
|
|
154
|
+
});
|
|
177
155
|
|
|
156
|
+
// Tracks events to track activity
|
|
157
|
+
// Props (object keys) need to be in Snake case vs. camelCase
|
|
178
158
|
/* eslint-disable camelcase */
|
|
179
|
-
|
|
180
159
|
const allErrors = {
|
|
181
160
|
folder_errors_length: folderValidation.length,
|
|
182
161
|
int_images_errors_length: intermediateImagesTotal,
|