@automattic/vip 2.10.0 → 2.12.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/CONTRIBUTING.md +7 -2
- package/README.md +27 -0
- package/config/{config.json → config.publish.json} +0 -0
- package/dist/bin/vip-dev-env-create.js +1 -0
- package/dist/bin/vip-dev-env-destroy.js +1 -0
- package/dist/bin/vip-dev-env-exec.js +1 -0
- package/dist/bin/vip-dev-env-import-media.js +1 -0
- package/dist/bin/vip-dev-env-import-sql.js +1 -0
- package/dist/bin/vip-dev-env-info.js +1 -0
- package/dist/bin/vip-dev-env-list.js +1 -0
- package/dist/bin/vip-dev-env-start.js +4 -3
- package/dist/bin/vip-dev-env-stop.js +7 -1
- package/dist/bin/vip-dev-env-update.js +1 -0
- package/dist/bin/vip-import-sql.js +7 -1
- package/dist/bin/vip-wp.js +2 -2
- package/dist/bin/vip.js +1 -1
- package/dist/lib/analytics/clients/pendo.js +92 -0
- package/dist/lib/analytics/clients/stub.js +1 -1
- package/dist/lib/analytics/clients/tracks.js +0 -5
- package/dist/lib/analytics/index.js +21 -4
- package/dist/lib/api.js +2 -2
- package/dist/lib/cli/config.js +30 -0
- package/dist/lib/dev-environment/dev-environment-cli.js +25 -2
- package/dist/lib/dev-environment/dev-environment-lando.js +17 -0
- package/dist/lib/http/proxy-agent.js +94 -0
- package/dist/lib/rollbar.js +1 -1
- package/dist/lib/tracker.js +13 -4
- package/npm-shrinkwrap.json +319 -133
- package/package/dist/bin/vip-app-list.js +73 -0
- package/package/dist/bin/vip-app.js +76 -0
- package/package/dist/bin/vip-config-envvar-delete.js +97 -0
- package/package/dist/bin/vip-config-envvar-get-all.js +94 -0
- package/package/dist/bin/vip-config-envvar-get.js +79 -0
- package/package/dist/bin/vip-config-envvar-list.js +91 -0
- package/package/dist/bin/vip-config-envvar-set.js +123 -0
- package/package/dist/bin/vip-config-envvar.js +23 -0
- package/package/dist/bin/vip-config.js +20 -0
- package/package/dist/bin/vip-dev-env-create.js +105 -0
- package/package/dist/bin/vip-dev-env-destroy.js +56 -0
- package/package/dist/bin/vip-dev-env-exec.js +67 -0
- package/package/dist/bin/vip-dev-env-import-media.js +51 -0
- package/package/dist/bin/vip-dev-env-import-sql.js +83 -0
- package/package/dist/bin/vip-dev-env-import.js +32 -0
- package/package/dist/bin/vip-dev-env-info.js +61 -0
- package/package/dist/bin/vip-dev-env-list.js +46 -0
- package/package/dist/bin/vip-dev-env-start.js +77 -0
- package/package/dist/bin/vip-dev-env-stop.js +52 -0
- package/package/dist/bin/vip-dev-env-update.js +89 -0
- package/package/dist/bin/vip-dev-env.js +23 -0
- package/package/dist/bin/vip-import-media-abort.js +132 -0
- package/package/dist/bin/vip-import-media-status.js +84 -0
- package/package/dist/bin/vip-import-media.js +168 -0
- package/package/dist/bin/vip-import-sql-status.js +83 -0
- package/package/dist/bin/vip-import-sql.js +580 -0
- package/package/dist/bin/vip-import-validate-files.js +191 -0
- package/package/dist/bin/vip-import-validate-sql.js +34 -0
- package/package/dist/bin/vip-import.js +20 -0
- package/package/dist/bin/vip-logs.js +232 -0
- package/package/dist/bin/vip-search-replace.js +71 -0
- package/package/dist/bin/vip-sync.js +191 -0
- package/package/dist/bin/vip-whoami.js +67 -0
- package/package/dist/bin/vip-wp.js +555 -0
- package/package/dist/bin/vip.js +149 -0
- package/package/dist/lib/analytics/clients/client.js +1 -0
- package/package/dist/lib/analytics/clients/pendo.js +92 -0
- package/package/dist/lib/analytics/clients/stub.js +19 -0
- package/package/dist/lib/analytics/clients/tracks.js +128 -0
- package/package/dist/lib/analytics/index.js +45 -0
- package/package/dist/lib/api/app.js +70 -0
- package/package/dist/lib/api/feature-flags.js +39 -0
- package/package/dist/lib/api/user.js +58 -0
- package/package/dist/lib/api.js +136 -0
- package/package/dist/lib/app-logs/app-logs.js +70 -0
- package/package/dist/lib/cli/apiConfig.js +90 -0
- package/package/dist/lib/cli/command.js +606 -0
- package/package/dist/lib/cli/envAlias.js +60 -0
- package/package/dist/lib/cli/exit.js +33 -0
- package/package/dist/lib/cli/format.js +213 -0
- package/package/dist/lib/cli/pager.js +52 -0
- package/package/dist/lib/cli/progress.js +208 -0
- package/package/dist/lib/cli/prompt.js +37 -0
- package/package/dist/lib/cli/repo.js +77 -0
- package/package/dist/lib/client-file-uploader.js +602 -0
- package/package/dist/lib/constants/dev-environment.js +42 -0
- package/package/dist/lib/constants/file-size.js +14 -0
- package/package/dist/lib/dev-environment/dev-environment-cli.js +508 -0
- package/package/dist/lib/dev-environment/dev-environment-core.js +620 -0
- package/package/dist/lib/dev-environment/dev-environment-lando.js +330 -0
- package/package/dist/lib/dev-environment/types.js +1 -0
- package/package/dist/lib/env.js +36 -0
- package/package/dist/lib/envvar/api-delete.js +56 -0
- package/package/dist/lib/envvar/api-get-all.js +59 -0
- package/package/dist/lib/envvar/api-get.js +24 -0
- package/package/dist/lib/envvar/api-list.js +60 -0
- package/package/dist/lib/envvar/api-set.js +58 -0
- package/package/dist/lib/envvar/api.js +104 -0
- package/package/dist/lib/envvar/input.js +55 -0
- package/package/dist/lib/envvar/logging.js +33 -0
- package/package/dist/lib/envvar/read-file.js +43 -0
- package/{dist → package/dist}/lib/http/socks-proxy-agent.js +0 -0
- package/package/dist/lib/keychain/browser.js +35 -0
- package/package/dist/lib/keychain/insecure.js +63 -0
- package/package/dist/lib/keychain/keychain.js +1 -0
- package/package/dist/lib/keychain/secure.js +36 -0
- package/package/dist/lib/keychain.js +36 -0
- package/package/dist/lib/media-import/media-file-import.js +34 -0
- package/package/dist/lib/media-import/progress.js +86 -0
- package/package/dist/lib/media-import/status.js +335 -0
- package/package/dist/lib/rollbar.js +35 -0
- package/package/dist/lib/search-and-replace.js +203 -0
- package/package/dist/lib/site-import/db-file-import.js +46 -0
- package/package/dist/lib/site-import/status.js +444 -0
- package/package/dist/lib/token.js +132 -0
- package/package/dist/lib/tracker.js +96 -0
- package/package/dist/lib/validations/is-multi-site-sql-dump.js +59 -0
- package/package/dist/lib/validations/is-multi-site.js +99 -0
- package/package/dist/lib/validations/line-by-line.js +92 -0
- package/package/dist/lib/validations/site-type.js +66 -0
- package/package/dist/lib/validations/sql.js +371 -0
- package/package/dist/lib/vip-import-validate-files.js +548 -0
- package/package/vip.iml +11 -0
- package/package.json +12 -9
- package/helpers/prepare-config.js +0 -19
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.sqlDumpLineIsMultiSite = sqlDumpLineIsMultiSite;
|
|
7
|
+
exports.isMultiSiteDumpFile = isMultiSiteDumpFile;
|
|
8
|
+
|
|
9
|
+
var _lineByLine = require("./line-by-line");
|
|
10
|
+
|
|
11
|
+
var exit = _interopRequireWildcard(require("../cli/exit"));
|
|
12
|
+
|
|
13
|
+
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); }
|
|
14
|
+
|
|
15
|
+
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; }
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @format
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* External dependencies
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Internal dependencies
|
|
28
|
+
*/
|
|
29
|
+
const SQL_CREATE_TABLE_IS_MULTISITE_REGEX = /^CREATE TABLE `?(wp_\d+_[a-z0-9_]*|wp_blogs)/i;
|
|
30
|
+
const SQL_CONTAINS_MULTISITE_WP_USERS_REGEX = /\`spam\` tinyint\(2\)|\`deleted\` tinyint\(2\)/i;
|
|
31
|
+
|
|
32
|
+
function sqlDumpLineIsMultiSite(line) {
|
|
33
|
+
// determine if we're on a CREATE TABLE statement line what has eg. wp_\d_options OR wp_blogs
|
|
34
|
+
// also check if we're on a line that defines the additional two columns found on the wp_users table for multisites
|
|
35
|
+
if (SQL_CREATE_TABLE_IS_MULTISITE_REGEX.test(line) || SQL_CONTAINS_MULTISITE_WP_USERS_REGEX.test(line)) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isMultiSiteDumpFile(fileName) {
|
|
43
|
+
return new Promise(async resolve => {
|
|
44
|
+
const readInterface = await (0, _lineByLine.getReadInterface)(fileName);
|
|
45
|
+
readInterface.on('line', line => {
|
|
46
|
+
const result = sqlDumpLineIsMultiSite(line);
|
|
47
|
+
|
|
48
|
+
if (true === result) {
|
|
49
|
+
resolve(true);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
readInterface.on('error', () => {
|
|
53
|
+
exit.withError('An error was encountered while reading your SQL dump file. Please verify the file contents.');
|
|
54
|
+
}); // Block until the processing completes
|
|
55
|
+
|
|
56
|
+
await new Promise(resolveBlock => readInterface.on('close', resolveBlock));
|
|
57
|
+
resolve(false);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isMultiSiteInSiteMeta = isMultiSiteInSiteMeta;
|
|
7
|
+
|
|
8
|
+
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
9
|
+
|
|
10
|
+
var _api = _interopRequireDefault(require("../api"));
|
|
11
|
+
|
|
12
|
+
var _tracker = require("../tracker");
|
|
13
|
+
|
|
14
|
+
var exit = _interopRequireWildcard(require("../cli/exit"));
|
|
15
|
+
|
|
16
|
+
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
|
+
|
|
18
|
+
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; }
|
|
19
|
+
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @format
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* External dependencies
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Internal dependencies
|
|
33
|
+
*/
|
|
34
|
+
const isMultiSite = new WeakMap();
|
|
35
|
+
|
|
36
|
+
async function isMultiSiteInSiteMeta(appId, envId) {
|
|
37
|
+
var _res, _res$data, _res$data$app;
|
|
38
|
+
|
|
39
|
+
const track = _tracker.trackEventWithEnv.bind(null, appId, envId); // if we've already been through this, avoid doing it again within the same process
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if (isMultiSite.has(arguments) && 'boolean' === typeof isMultiSite.get(arguments)) {
|
|
43
|
+
return Boolean(isMultiSite.get(arguments));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const api = await (0, _api.default)();
|
|
47
|
+
let res;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
res = await api.query({
|
|
51
|
+
query: (0, _graphqlTag.default)`
|
|
52
|
+
query AppMultiSiteCheck($appId: Int, $envId: Int) {
|
|
53
|
+
app(id: $appId) {
|
|
54
|
+
id
|
|
55
|
+
name
|
|
56
|
+
repo
|
|
57
|
+
environments(id: $envId) {
|
|
58
|
+
id
|
|
59
|
+
appId
|
|
60
|
+
name
|
|
61
|
+
type
|
|
62
|
+
isMultisite
|
|
63
|
+
isSubdirectoryMultisite
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`,
|
|
68
|
+
variables: {
|
|
69
|
+
appId,
|
|
70
|
+
envId
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
} catch (GraphQlError) {
|
|
74
|
+
await track('import_sql_command_error', {
|
|
75
|
+
error_type: 'GraphQL-MultiSite-Check-failed',
|
|
76
|
+
gql_err: GraphQlError
|
|
77
|
+
});
|
|
78
|
+
exit.withError(`StartImport call failed: ${GraphQlError}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (Array.isArray((_res = res) === null || _res === void 0 ? void 0 : (_res$data = _res.data) === null || _res$data === void 0 ? void 0 : (_res$data$app = _res$data.app) === null || _res$data$app === void 0 ? void 0 : _res$data$app.environments)) {
|
|
82
|
+
const environments = res.data.app.environments;
|
|
83
|
+
|
|
84
|
+
if (!environments.length) {
|
|
85
|
+
isMultiSite.set(arguments, false);
|
|
86
|
+
return false;
|
|
87
|
+
} // we asked for one result with one appId and one envId, so...
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
const thisEnv = environments[0];
|
|
91
|
+
|
|
92
|
+
if (thisEnv.isMultiSite || thisEnv.isSubdirectoryMultisite) {
|
|
93
|
+
isMultiSite.set(arguments, true);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getReadInterface = getReadInterface;
|
|
7
|
+
exports.fileLineValidations = fileLineValidations;
|
|
8
|
+
|
|
9
|
+
var _readline = _interopRequireDefault(require("readline"));
|
|
10
|
+
|
|
11
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
12
|
+
|
|
13
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
14
|
+
|
|
15
|
+
var exit = _interopRequireWildcard(require("../cli/exit"));
|
|
16
|
+
|
|
17
|
+
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); }
|
|
18
|
+
|
|
19
|
+
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; }
|
|
20
|
+
|
|
21
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @format
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* External dependencies
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Internal dependencies
|
|
34
|
+
*/
|
|
35
|
+
const debug = (0, _debug.default)('vip:validations:line-by-line');
|
|
36
|
+
|
|
37
|
+
function openFile(filename, flags = 'r', mode = 666) {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
_fs.default.open(filename, flags, mode, (err, fd) => {
|
|
40
|
+
if (err) {
|
|
41
|
+
return reject(err);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
resolve(fd);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function getReadInterface(filename) {
|
|
50
|
+
let fd;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
fd = await openFile(filename);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
exit.withError('The file at the provided path is either missing or not readable. Please check the input and try again.');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return _readline.default.createInterface({
|
|
59
|
+
input: _fs.default.createReadStream('', {
|
|
60
|
+
fd
|
|
61
|
+
}),
|
|
62
|
+
output: null,
|
|
63
|
+
console: false
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function fileLineValidations(appId, envId, fileName, validations) {
|
|
68
|
+
const isImport = true;
|
|
69
|
+
const readInterface = await getReadInterface(fileName);
|
|
70
|
+
debug('Validations: ', validations);
|
|
71
|
+
readInterface.on('line', line => {
|
|
72
|
+
validations.map(validation => {
|
|
73
|
+
validation.execute(line);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
readInterface.on('error', err => {
|
|
77
|
+
throw new Error(` Error validating input file: ${err.toString()}`);
|
|
78
|
+
}); // Block until the processing completes
|
|
79
|
+
|
|
80
|
+
await new Promise(resolve => readInterface.on('close', resolve));
|
|
81
|
+
readInterface.close();
|
|
82
|
+
return Promise.all(validations.map(async validation => {
|
|
83
|
+
if (validation.hasOwnProperty('postLineExecutionProcessing') && typeof validation.postLineExecutionProcessing === 'function') {
|
|
84
|
+
return validation.postLineExecutionProcessing({
|
|
85
|
+
fileName,
|
|
86
|
+
isImport,
|
|
87
|
+
appId,
|
|
88
|
+
envId
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.siteTypeValidations = void 0;
|
|
7
|
+
|
|
8
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
9
|
+
|
|
10
|
+
var _tracker = require("../tracker");
|
|
11
|
+
|
|
12
|
+
var _isMultiSiteSqlDump = require("./is-multi-site-sql-dump");
|
|
13
|
+
|
|
14
|
+
var _isMultiSite = require("./is-multi-site");
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @format
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* External dependencies
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Internal dependencies
|
|
29
|
+
*/
|
|
30
|
+
const debug = (0, _debug.default)('vip:vip-import-sql');
|
|
31
|
+
let isMultiSiteSqlDump = false;
|
|
32
|
+
const siteTypeValidations = {
|
|
33
|
+
execute: line => {
|
|
34
|
+
const lineIsMultiSite = (0, _isMultiSiteSqlDump.sqlDumpLineIsMultiSite)(line);
|
|
35
|
+
|
|
36
|
+
if (lineIsMultiSite) {
|
|
37
|
+
isMultiSiteSqlDump = true;
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
postLineExecutionProcessing: async ({
|
|
41
|
+
appId,
|
|
42
|
+
envId
|
|
43
|
+
}) => {
|
|
44
|
+
const isMultiSite = await (0, _isMultiSite.isMultiSiteInSiteMeta)(appId, envId);
|
|
45
|
+
|
|
46
|
+
const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
|
|
47
|
+
|
|
48
|
+
debug(`\nAppId: ${appId} is ${isMultiSite ? 'a multisite.' : 'not a multisite'}`);
|
|
49
|
+
debug(`The SQL dump provided is ${isMultiSiteSqlDump ? 'from a multisite.' : 'not from a multisite'}\n`);
|
|
50
|
+
|
|
51
|
+
if (!isMultiSite && isMultiSiteSqlDump) {
|
|
52
|
+
await track('import_sql_command_error', {
|
|
53
|
+
error_type: 'not-multisite-with-multisite-sql-dump'
|
|
54
|
+
});
|
|
55
|
+
throw new Error('You have provided a multisite SQL dump file for import into a single site (non-multisite).');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (isMultiSite && !isMultiSiteSqlDump) {
|
|
59
|
+
await track('import_sql_command_error', {
|
|
60
|
+
error_type: 'subsite-import-without-subsite-sql-dump'
|
|
61
|
+
});
|
|
62
|
+
throw new Error('You have requested a subsite SQL import but have not provided a subsite compatiable SQL dump.');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
exports.siteTypeValidations = siteTypeValidations;
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.validate = exports.staticSqlValidations = exports.getTableNames = exports.postValidation = void 0;
|
|
7
|
+
|
|
8
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
9
|
+
|
|
10
|
+
var _singleLineLog = require("single-line-log");
|
|
11
|
+
|
|
12
|
+
var exit = _interopRequireWildcard(require("../cli/exit"));
|
|
13
|
+
|
|
14
|
+
var _tracker = require("../tracker");
|
|
15
|
+
|
|
16
|
+
var _lineByLine = require("./line-by-line");
|
|
17
|
+
|
|
18
|
+
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); }
|
|
19
|
+
|
|
20
|
+
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; }
|
|
21
|
+
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @format
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* External dependencies
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Internal dependencies
|
|
35
|
+
*/
|
|
36
|
+
let problemsFound = 0;
|
|
37
|
+
let lineNum = 1;
|
|
38
|
+
const tableNames = [];
|
|
39
|
+
|
|
40
|
+
function formatError(message) {
|
|
41
|
+
return `${_chalk.default.red('SQL Error:')} ${message}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function formatRecommendation(message) {
|
|
45
|
+
return `${_chalk.default.yellow('Recommendation:')} ${message}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const errorCheckFormatter = check => {
|
|
49
|
+
const errors = [];
|
|
50
|
+
const infos = [];
|
|
51
|
+
|
|
52
|
+
if (check.results.length > 0) {
|
|
53
|
+
problemsFound += 1;
|
|
54
|
+
errors.push({
|
|
55
|
+
error: formatError(`${check.message} on line(s) ${check.results.join(', ')}.`),
|
|
56
|
+
recommendation: formatRecommendation(check.recommendation)
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
infos.push(`✅ ${check.message} was found ${check.results.length} times.`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
errors,
|
|
64
|
+
infos
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const requiredCheckFormatter = (check, type, isImport) => {
|
|
69
|
+
const errors = [];
|
|
70
|
+
const infos = [];
|
|
71
|
+
|
|
72
|
+
if (check.results.length > 0) {
|
|
73
|
+
infos.push(`✅ ${check.message} was found ${check.results.length} times.`);
|
|
74
|
+
|
|
75
|
+
if (type === 'createTable') {
|
|
76
|
+
if (!isImport) {
|
|
77
|
+
checkTablePrefixes(check.results, errors, infos);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
problemsFound += 1;
|
|
82
|
+
errors.push({
|
|
83
|
+
error: formatError(`${check.message} was not found.`),
|
|
84
|
+
recommendation: formatRecommendation(check.recommendation)
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
errors,
|
|
90
|
+
infos
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const infoCheckFormatter = check => {
|
|
95
|
+
const infos = [];
|
|
96
|
+
check.results.forEach(item => {
|
|
97
|
+
infos.push(item);
|
|
98
|
+
});
|
|
99
|
+
return {
|
|
100
|
+
errors: [],
|
|
101
|
+
infos
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
function checkTablePrefixes(tables, errors, infos) {
|
|
106
|
+
const wpTables = [],
|
|
107
|
+
notWPTables = [],
|
|
108
|
+
wpMultisiteTables = [];
|
|
109
|
+
tables.forEach(tableName => {
|
|
110
|
+
if (tableName.match(/^wp_(\d+_)/)) {
|
|
111
|
+
wpMultisiteTables.push(tableName);
|
|
112
|
+
} else if (tableName.match(/^wp_/)) {
|
|
113
|
+
wpTables.push(tableName);
|
|
114
|
+
} else if (!tableName.match(/^wp_/)) {
|
|
115
|
+
notWPTables.push(tableName);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (wpTables.length > 0) {
|
|
120
|
+
infos.push(` - wp_ prefix tables found: ${wpTables.length} `);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (notWPTables.length > 0) {
|
|
124
|
+
problemsFound += 1;
|
|
125
|
+
errors.push({
|
|
126
|
+
error: formatError(`tables without wp_ prefix found: ${notWPTables.join(',')}`),
|
|
127
|
+
recommendation: formatRecommendation('Please make sure all table names are prefixed with `wp_`')
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (wpMultisiteTables.length > 0) {
|
|
132
|
+
infos.push(` - wp_n_ prefix tables found: ${wpMultisiteTables.length} `);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const checks = {
|
|
137
|
+
binaryLogging: {
|
|
138
|
+
matcher: /SET @@SESSION.sql_log_bin/i,
|
|
139
|
+
matchHandler: lineNumber => lineNumber,
|
|
140
|
+
outputFormatter: errorCheckFormatter,
|
|
141
|
+
results: [],
|
|
142
|
+
message: 'SET @@SESSION.sql_log_bin statement',
|
|
143
|
+
excerpt: "'SET @@SESSION.sql_log_bin' statement should not be present (case-insensitive)",
|
|
144
|
+
recommendation: 'Remove these lines'
|
|
145
|
+
},
|
|
146
|
+
trigger: {
|
|
147
|
+
// Match `CREATE (DEFINER=`root`@`host`) TRIGGER`
|
|
148
|
+
matcher: /^CREATE (\(?DEFINER=`?(\w*)(`@`)?(\w*\.*%?)*`?\)?)?(| )TRIGGER/i,
|
|
149
|
+
matchHandler: lineNumber => lineNumber,
|
|
150
|
+
outputFormatter: errorCheckFormatter,
|
|
151
|
+
results: [],
|
|
152
|
+
message: 'TRIGGER statement',
|
|
153
|
+
excerpt: "'TRIGGER' statement should not be present (case-sensitive)",
|
|
154
|
+
recommendation: 'Remove these lines'
|
|
155
|
+
},
|
|
156
|
+
dropDB: {
|
|
157
|
+
matcher: /^DROP DATABASE/i,
|
|
158
|
+
matchHandler: lineNumber => lineNumber,
|
|
159
|
+
outputFormatter: errorCheckFormatter,
|
|
160
|
+
results: [],
|
|
161
|
+
message: 'DROP DATABASE statement',
|
|
162
|
+
excerpt: "'DROP DATABASE' should not be present (case-insensitive)",
|
|
163
|
+
recommendation: 'Remove these lines'
|
|
164
|
+
},
|
|
165
|
+
useStatement: {
|
|
166
|
+
matcher: /^USE /i,
|
|
167
|
+
matchHandler: lineNumber => lineNumber,
|
|
168
|
+
outputFormatter: errorCheckFormatter,
|
|
169
|
+
results: [],
|
|
170
|
+
message: 'USE <DATABASE_NAME> statement',
|
|
171
|
+
excerpt: "'USE <DATABASE_NAME>' should not be present (case-insensitive)",
|
|
172
|
+
recommendation: 'Remove these lines'
|
|
173
|
+
},
|
|
174
|
+
alterUser: {
|
|
175
|
+
matcher: /^(ALTER USER|SET PASSWORD)/i,
|
|
176
|
+
matchHandler: lineNumber => lineNumber,
|
|
177
|
+
outputFormatter: errorCheckFormatter,
|
|
178
|
+
results: [],
|
|
179
|
+
message: 'ALTER USER statement',
|
|
180
|
+
excerpt: "'ALTER USER' should not be present (case-insensitive)",
|
|
181
|
+
recommendation: 'Remove these lines'
|
|
182
|
+
},
|
|
183
|
+
dropTable: {
|
|
184
|
+
matcher: /^DROP TABLE IF EXISTS `?([a-z0-9_]*)/i,
|
|
185
|
+
matchHandler: (lineNumber, results) => results[1],
|
|
186
|
+
outputFormatter: requiredCheckFormatter,
|
|
187
|
+
results: [],
|
|
188
|
+
message: 'DROP TABLE',
|
|
189
|
+
excerpt: "'DROP TABLE IF EXISTS' should be present (case-insensitive)",
|
|
190
|
+
recommendation: 'Check import settings to include DROP TABLE statements'
|
|
191
|
+
},
|
|
192
|
+
createTable: {
|
|
193
|
+
matcher: /^CREATE TABLE (?:IF NOT EXISTS )?`?([a-z0-9_]*)/i,
|
|
194
|
+
matchHandler: (lineNumber, results) => results[1],
|
|
195
|
+
outputFormatter: requiredCheckFormatter,
|
|
196
|
+
results: [],
|
|
197
|
+
message: 'CREATE TABLE',
|
|
198
|
+
excerpt: "'CREATE TABLE' should be present (case-insensitive)",
|
|
199
|
+
recommendation: 'Check import settings to include CREATE TABLE statements'
|
|
200
|
+
},
|
|
201
|
+
siteHomeUrl: {
|
|
202
|
+
matcher: "'(siteurl|home)',\\s?'(.*?)'",
|
|
203
|
+
matchHandler: (lineNumber, results) => results[0],
|
|
204
|
+
outputFormatter: infoCheckFormatter,
|
|
205
|
+
results: [],
|
|
206
|
+
message: 'Siteurl/home matches',
|
|
207
|
+
excerpt: 'Siteurl/home options',
|
|
208
|
+
recommendation: ''
|
|
209
|
+
},
|
|
210
|
+
engineInnoDB: {
|
|
211
|
+
matcher: / ENGINE=(?!(InnoDB))/i,
|
|
212
|
+
matchHandler: lineNumber => lineNumber,
|
|
213
|
+
outputFormatter: errorCheckFormatter,
|
|
214
|
+
results: [],
|
|
215
|
+
message: 'ENGINE != InnoDB',
|
|
216
|
+
excerpt: "'ENGINE=InnoDB' should be present (case-insensitive) for all tables",
|
|
217
|
+
recommendation: "Ensure your application works with InnoDB and update your SQL dump to include only 'ENGINE=InnoDB' engine definitions in 'CREATE TABLE' statements. " + "We suggest you search for all 'ENGINE=X' entries and replace them with 'ENGINE=InnoDB'!"
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const postValidation = async (filename, isImport = false) => {
|
|
222
|
+
await (0, _tracker.trackEvent)('import_validate_sql_command_execute', {
|
|
223
|
+
is_import: isImport
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
if (!isImport) {
|
|
227
|
+
(0, _singleLineLog.stdout)(`Finished processing ${lineNum} lines.`);
|
|
228
|
+
console.log('\n');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const errorSummary = {};
|
|
232
|
+
const checkEntries = Object.entries(checks);
|
|
233
|
+
let formattedErrors = [];
|
|
234
|
+
let formattedInfos = [];
|
|
235
|
+
|
|
236
|
+
for (const [type, check] of checkEntries) {
|
|
237
|
+
const formattedOutput = check.outputFormatter(check, type, isImport);
|
|
238
|
+
formattedErrors = formattedErrors.concat(formattedOutput.errors);
|
|
239
|
+
formattedInfos = formattedInfos.concat(formattedOutput.infos);
|
|
240
|
+
errorSummary[type] = check.results.length;
|
|
241
|
+
} // eslint-disable-next-line camelcase
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
errorSummary.problems_found = problemsFound;
|
|
245
|
+
const tableNamesSet = new Set(tableNames);
|
|
246
|
+
|
|
247
|
+
if (tableNames.length > tableNamesSet.size) {
|
|
248
|
+
// there was a duplciate table
|
|
249
|
+
problemsFound++;
|
|
250
|
+
|
|
251
|
+
function findDuplicates(arr) {
|
|
252
|
+
const filtered = arr.filter(item => {
|
|
253
|
+
if (tableNamesSet.has(item)) {
|
|
254
|
+
tableNamesSet.delete(item);
|
|
255
|
+
} else {
|
|
256
|
+
return item;
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
return [...new Set(filtered)];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const duplicates = findDuplicates(tableNames);
|
|
263
|
+
const errorObject = {
|
|
264
|
+
error: formatError('Duplicate table names were found: ' + duplicates.join(',')),
|
|
265
|
+
recommendation: formatRecommendation('Ensure that there are no duplicate tables in your SQL dump')
|
|
266
|
+
};
|
|
267
|
+
formattedErrors = formattedErrors.concat(errorObject);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (problemsFound > 0) {
|
|
271
|
+
await (0, _tracker.trackEvent)('import_validate_sql_command_failure', {
|
|
272
|
+
is_import: isImport,
|
|
273
|
+
error: errorSummary
|
|
274
|
+
});
|
|
275
|
+
const errorOutput = [`SQL validation failed due to ${_chalk.default.red(problemsFound)} error(s)`, ''];
|
|
276
|
+
formattedErrors.forEach(error => {
|
|
277
|
+
errorOutput.push(error.error);
|
|
278
|
+
|
|
279
|
+
if (error.recommendation) {
|
|
280
|
+
errorOutput.push(error.recommendation);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
errorOutput.push('');
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
if (isImport) {
|
|
287
|
+
throw new Error(errorOutput.join('\n'));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
exit.withError(errorOutput.join('\n'));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!isImport) {
|
|
294
|
+
console.log(formattedInfos.join('\n'));
|
|
295
|
+
console.log('');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
await (0, _tracker.trackEvent)('import_validate_sql_command_success', {
|
|
299
|
+
is_import: isImport
|
|
300
|
+
});
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
exports.postValidation = postValidation;
|
|
304
|
+
|
|
305
|
+
const getTableNames = () => {
|
|
306
|
+
return tableNames;
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
exports.getTableNames = getTableNames;
|
|
310
|
+
|
|
311
|
+
const checkForTableName = line => {
|
|
312
|
+
const matches = line.match(/(?<=^CREATE\sTABLE\s)`?(?:(wp_[\d+_]?\w+))`?/);
|
|
313
|
+
|
|
314
|
+
if (matches) {
|
|
315
|
+
const tableName = matches[1]; // we should only have one match if we have any since we're looking at the start of the string
|
|
316
|
+
|
|
317
|
+
tableNames.push(tableName);
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const perLineValidations = (line, runAsImport, skipChecks) => {
|
|
322
|
+
if (lineNum % 500 === 0) {
|
|
323
|
+
runAsImport ? '' : (0, _singleLineLog.stdout)(`Reading line ${lineNum} `);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
checkForTableName(line);
|
|
327
|
+
const checkKeys = Object.keys(checks).filter(checkItem => !skipChecks.includes(checkItem));
|
|
328
|
+
const checkValues = checkKeys.map(checkKey => checks[checkKey]);
|
|
329
|
+
checkValues.forEach(check => {
|
|
330
|
+
const results = line.match(check.matcher);
|
|
331
|
+
|
|
332
|
+
if (results) {
|
|
333
|
+
check.results.push(check.matchHandler(lineNum, results));
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
lineNum += 1;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const execute = (line, isImport = true, skipChecks = ['useStatement']) => {
|
|
340
|
+
perLineValidations(line, isImport, skipChecks);
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const postLineExecutionProcessing = async ({
|
|
344
|
+
fileName,
|
|
345
|
+
isImport
|
|
346
|
+
}) => {
|
|
347
|
+
await postValidation(fileName, isImport);
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const staticSqlValidations = {
|
|
351
|
+
execute,
|
|
352
|
+
postLineExecutionProcessing
|
|
353
|
+
}; // For standalone SQL validations
|
|
354
|
+
|
|
355
|
+
exports.staticSqlValidations = staticSqlValidations;
|
|
356
|
+
|
|
357
|
+
const validate = async (filename, skipChecks = ['useStatement']) => {
|
|
358
|
+
const readInterface = await (0, _lineByLine.getReadInterface)(filename);
|
|
359
|
+
readInterface.on('line', line => {
|
|
360
|
+
execute(line, false, skipChecks);
|
|
361
|
+
}); // Block until the processing completes
|
|
362
|
+
|
|
363
|
+
await new Promise(resolve => readInterface.on('close', resolve));
|
|
364
|
+
readInterface.close();
|
|
365
|
+
await postLineExecutionProcessing({
|
|
366
|
+
filename,
|
|
367
|
+
isImport: false
|
|
368
|
+
});
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
exports.validate = validate;
|