@automattic/vip 2.14.0 → 2.15.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/README.md +9 -0
- package/assets/dev-env.lando.template.yml.ejs +0 -4
- package/dist/bin/vip-dev-env-import-sql.js +1 -1
- package/dist/bin/vip-import-sql.js +6 -4
- package/dist/lib/constants/dev-environment.js +6 -7
- package/dist/lib/dev-environment/dev-environment-cli.js +1 -1
- package/dist/lib/site-import/db-file-import.js +1 -1
- package/dist/lib/validations/is-multisite-domain-mapped.js +161 -0
- package/dist/lib/validations/line-by-line.js +3 -2
- package/dist/lib/validations/site-type.js +18 -1
- package/dist/lib/validations/utils.js +45 -0
- package/npm-shrinkwrap.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,15 @@ By default, we record information about the usage of this tool using an in-house
|
|
|
26
26
|
|
|
27
27
|
## Changelog
|
|
28
28
|
|
|
29
|
+
### 2.15.0 (3 Aug 2022)
|
|
30
|
+
|
|
31
|
+
- #1067 FORNO-1244: SQL Import: Increase max import size for launched sites to 1GB
|
|
32
|
+
- #1064 FORNO-1254: SQL Import: Add multisite primary domain validation
|
|
33
|
+
- #1062 [dev-env] Change wizard wording
|
|
34
|
+
- #1065 [dev-env] Update default software versions for PHP and Elasticsearch
|
|
35
|
+
- #1063 [dev-env] Remove redundant healthchecks
|
|
36
|
+
- #1061 [dev-env] Fix duplicate shortcuts
|
|
37
|
+
|
|
29
38
|
### 2.14.0 (19 Jul 2022)
|
|
30
39
|
|
|
31
40
|
- #1059 Update engines to show support for npm > 6
|
|
@@ -68,8 +68,6 @@ services:
|
|
|
68
68
|
command: docker-entrypoint.sh mysqld
|
|
69
69
|
ports:
|
|
70
70
|
- ":3306"
|
|
71
|
-
healthcheck:
|
|
72
|
-
test: 'mysql -uroot --silent --execute "SHOW DATABASES;"'
|
|
73
71
|
environment:
|
|
74
72
|
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 'true'
|
|
75
73
|
volumes:
|
|
@@ -106,8 +104,6 @@ services:
|
|
|
106
104
|
discovery.type: 'single-node'
|
|
107
105
|
ports:
|
|
108
106
|
- ":9200"
|
|
109
|
-
healthcheck:
|
|
110
|
-
test: "curl --noproxy '*' -XGET localhost:9200"
|
|
111
107
|
volumes:
|
|
112
108
|
- search_data:/usr/share/elasticsearch/data
|
|
113
109
|
volumes:
|
|
@@ -44,7 +44,7 @@ const examples = [{
|
|
|
44
44
|
}];
|
|
45
45
|
(0, _command.default)({
|
|
46
46
|
requiredArgs: 1
|
|
47
|
-
}).option('slug', 'Custom name of the dev environment').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('skip-validate', 'Do not perform file validation.').examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
|
|
47
|
+
}).option('slug', 'Custom name of the dev environment').option(['r', 'search-replace'], 'Perform Search and Replace on the specified SQL file').option('in-place', 'Search and Replace explicitly on the given input file').option('skip-validate', 'Do not perform file validation.').examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
|
|
48
48
|
await (0, _devEnvironmentCli.validateDependencies)();
|
|
49
49
|
const [fileName] = unmatchedArgs;
|
|
50
50
|
const {
|
|
@@ -249,7 +249,8 @@ async function validateAndGetTableNames({
|
|
|
249
249
|
skipValidate,
|
|
250
250
|
appId,
|
|
251
251
|
envId,
|
|
252
|
-
fileNameToUpload
|
|
252
|
+
fileNameToUpload,
|
|
253
|
+
searchReplace
|
|
253
254
|
}) {
|
|
254
255
|
const validations = [_sql.staticSqlValidations, _siteType.siteTypeValidations];
|
|
255
256
|
|
|
@@ -259,10 +260,10 @@ async function validateAndGetTableNames({
|
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
try {
|
|
262
|
-
await (0, _lineByLine.fileLineValidations)(appId, envId, fileNameToUpload, validations);
|
|
263
|
+
await (0, _lineByLine.fileLineValidations)(appId, envId, fileNameToUpload, validations, searchReplace);
|
|
263
264
|
} catch (validateErr) {
|
|
264
265
|
console.log('');
|
|
265
|
-
exit.withError(`${validateErr.message}
|
|
266
|
+
exit.withError(`${validateErr.message}\n
|
|
266
267
|
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
|
`);
|
|
268
269
|
} // this can only be called after static validation of the SQL file
|
|
@@ -407,7 +408,8 @@ const displayPlaybook = ({
|
|
|
407
408
|
skipValidate,
|
|
408
409
|
appId,
|
|
409
410
|
envId,
|
|
410
|
-
fileNameToUpload
|
|
411
|
+
fileNameToUpload,
|
|
412
|
+
searchReplace
|
|
411
413
|
}); // display playbook of what will happen during execution
|
|
412
414
|
|
|
413
415
|
displayPlaybook({
|
|
@@ -11,9 +11,9 @@ exports.DEV_ENVIRONMENT_FULL_COMMAND = DEV_ENVIRONMENT_FULL_COMMAND;
|
|
|
11
11
|
const DEV_ENVIRONMENT_DEFAULTS = {
|
|
12
12
|
title: 'VIP Dev',
|
|
13
13
|
multisite: false,
|
|
14
|
-
elasticsearchVersion: '7.
|
|
14
|
+
elasticsearchVersion: '7.17.2',
|
|
15
15
|
mariadbVersion: '10.3',
|
|
16
|
-
|
|
16
|
+
phpVersion: '8.0'
|
|
17
17
|
};
|
|
18
18
|
exports.DEV_ENVIRONMENT_DEFAULTS = DEV_ENVIRONMENT_DEFAULTS;
|
|
19
19
|
const DEV_ENVIRONMENT_PROMPT_INTRO = 'This is a wizard to help you set up your local dev environment.\n\n' + 'Sensible default values were pre-selected for convenience. ' + 'You may also choose to create multiple environments with different settings using the --slug option.\n\n';
|
|
@@ -32,11 +32,10 @@ const DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL = 86400; // once per day
|
|
|
32
32
|
|
|
33
33
|
exports.DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL = DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL;
|
|
34
34
|
const DEV_ENVIRONMENT_PHP_VERSIONS = {
|
|
35
|
-
default: 'ghcr.io/automattic/vip-container-images/php-fpm:7.4',
|
|
36
|
-
// eslint-disable-next-line quote-props -- flow does nit support non-string keys
|
|
37
|
-
'7.4': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:7.4',
|
|
38
|
-
'8.0': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:8.0',
|
|
39
35
|
// eslint-disable-next-line quote-props
|
|
40
|
-
'8.1': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:8.1'
|
|
36
|
+
'8.1': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:8.1',
|
|
37
|
+
'8.0': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:8.0',
|
|
38
|
+
// eslint-disable-next-line quote-props -- flow does nit support non-string keys
|
|
39
|
+
'7.4': 'ghcr.io/automattic/vip-container-images/php-fpm-alt:7.4'
|
|
41
40
|
};
|
|
42
41
|
exports.DEV_ENVIRONMENT_PHP_VERSIONS = DEV_ENVIRONMENT_PHP_VERSIONS;
|
|
@@ -248,7 +248,7 @@ async function promptForArguments(preselectedOptions, defaultOptions) {
|
|
|
248
248
|
instanceData[component] = result;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
instanceData.enterpriseSearchEnabled = await promptForBoolean('Enable Enterprise Search?', defaultOptions.enterpriseSearchEnabled);
|
|
251
|
+
instanceData.enterpriseSearchEnabled = await promptForBoolean('Enable Elasticsearch (needed by Enterprise Search)?', defaultOptions.enterpriseSearchEnabled);
|
|
252
252
|
|
|
253
253
|
if (instanceData.enterpriseSearchEnabled) {
|
|
254
254
|
instanceData.statsd = preselectedOptions.statsd || defaultOptions.statsd || false;
|
|
@@ -18,7 +18,7 @@ var _fileSize = require("../constants/file-size");
|
|
|
18
18
|
*/
|
|
19
19
|
const SQL_IMPORT_FILE_SIZE_LIMIT = 100 * _fileSize.GB_IN_BYTES;
|
|
20
20
|
exports.SQL_IMPORT_FILE_SIZE_LIMIT = SQL_IMPORT_FILE_SIZE_LIMIT;
|
|
21
|
-
const SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED =
|
|
21
|
+
const SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED = 1 * _fileSize.GB_IN_BYTES;
|
|
22
22
|
exports.SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED = SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED;
|
|
23
23
|
|
|
24
24
|
function currentUserCanImportForApp(app) {
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isMultisitePrimaryDomainMapped = isMultisitePrimaryDomainMapped;
|
|
7
|
+
exports.getPrimaryDomain = exports.maybeSearchReplacePrimaryDomain = exports.getPrimaryDomainFromSQL = void 0;
|
|
8
|
+
|
|
9
|
+
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
10
|
+
|
|
11
|
+
var _api = _interopRequireDefault(require("../api"));
|
|
12
|
+
|
|
13
|
+
var _tracker = require("../tracker");
|
|
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
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Extracts the domain for site with ID 1 from an INSERT INTO `wp_site` SQL statement
|
|
38
|
+
*
|
|
39
|
+
* @param {array} statements An array of SQL statements
|
|
40
|
+
* @returns {string} The domain
|
|
41
|
+
*/
|
|
42
|
+
const getPrimaryDomainFromSQL = statements => {
|
|
43
|
+
var _statements$;
|
|
44
|
+
|
|
45
|
+
if (!statements.length) {
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const SQL_WP_SITE_DOMAINS_REGEX = /\(1,'(.*?)'/s;
|
|
50
|
+
const matches = (_statements$ = statements[0]) === null || _statements$ === void 0 ? void 0 : _statements$.join('').replace(/\s/g, '').match(SQL_WP_SITE_DOMAINS_REGEX);
|
|
51
|
+
return matches ? matches[1] : '';
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Apply search-replacements to a domain
|
|
55
|
+
*
|
|
56
|
+
* @param {string} domain The domain to apply replacements to
|
|
57
|
+
* @param {(string|array)} searchReplace The search-replace pairs
|
|
58
|
+
* @returns {string} The processed domain
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
exports.getPrimaryDomainFromSQL = getPrimaryDomainFromSQL;
|
|
63
|
+
|
|
64
|
+
const maybeSearchReplacePrimaryDomain = function (domain, searchReplace) {
|
|
65
|
+
if (searchReplace) {
|
|
66
|
+
var _primaryDomainReplace;
|
|
67
|
+
|
|
68
|
+
let pairs = searchReplace;
|
|
69
|
+
|
|
70
|
+
if (!Array.isArray(pairs)) {
|
|
71
|
+
pairs = [searchReplace];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const domainReplacements = pairs.map(pair => pair.split(','));
|
|
75
|
+
const primaryDomainReplacement = domainReplacements.find(pair => pair[0] === domain);
|
|
76
|
+
return (_primaryDomainReplace = primaryDomainReplacement === null || primaryDomainReplacement === void 0 ? void 0 : primaryDomainReplacement[1]) !== null && _primaryDomainReplace !== void 0 ? _primaryDomainReplace : domain;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return domain;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Get the primary domain as it will be imported
|
|
83
|
+
*
|
|
84
|
+
* @param {array} statements An array of SQL statements
|
|
85
|
+
* @param {(string|array)} searchReplace The search-replace pairs
|
|
86
|
+
* @returns {string} The replaced domain, or the domain as found in the SQL dump
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
exports.maybeSearchReplacePrimaryDomain = maybeSearchReplacePrimaryDomain;
|
|
91
|
+
|
|
92
|
+
const getPrimaryDomain = function (statements, searchReplace) {
|
|
93
|
+
const domainFromSQL = getPrimaryDomainFromSQL(statements);
|
|
94
|
+
return maybeSearchReplacePrimaryDomain(domainFromSQL, searchReplace);
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Gets the mapped domains and checks if the primary domain from the provided SQL dump is one of them
|
|
98
|
+
*
|
|
99
|
+
* @param {number} appId The ID of the app in GOOP
|
|
100
|
+
* @param {number} envId The ID of the enviroment in GOOP
|
|
101
|
+
* @param {string} primaryDomain The primary domain found in the provided SQL file
|
|
102
|
+
* @returns {boolean} Whether the primary domain is mapped
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
exports.getPrimaryDomain = getPrimaryDomain;
|
|
107
|
+
|
|
108
|
+
async function isMultisitePrimaryDomainMapped(appId, envId, primaryDomain) {
|
|
109
|
+
var _res, _res$data, _res$data$app, _environments$, _environments$$domain, _environments$$domain2;
|
|
110
|
+
|
|
111
|
+
const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
|
|
112
|
+
|
|
113
|
+
const api = await (0, _api.default)();
|
|
114
|
+
let res;
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
res = await api.query({
|
|
118
|
+
query: (0, _graphqlTag.default)`
|
|
119
|
+
query AppMappedDomains($appId: Int, $envId: Int) {
|
|
120
|
+
app(id: $appId) {
|
|
121
|
+
id
|
|
122
|
+
name
|
|
123
|
+
environments(id: $envId) {
|
|
124
|
+
uniqueLabel
|
|
125
|
+
isMultisite
|
|
126
|
+
domains {
|
|
127
|
+
nodes {
|
|
128
|
+
name
|
|
129
|
+
isPrimary
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
`,
|
|
136
|
+
variables: {
|
|
137
|
+
appId,
|
|
138
|
+
envId
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
} catch (GraphQlError) {
|
|
142
|
+
await track('import_sql_command_error', {
|
|
143
|
+
error_type: 'GraphQL-MappedDomain-Check-failed',
|
|
144
|
+
gql_err: GraphQlError
|
|
145
|
+
});
|
|
146
|
+
exit.withError(`StartImport call failed: ${GraphQlError}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
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)) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const environments = res.data.app.environments;
|
|
154
|
+
|
|
155
|
+
if (!environments.length) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const mappedDomains = (_environments$ = environments[0]) === null || _environments$ === void 0 ? void 0 : (_environments$$domain = _environments$.domains) === null || _environments$$domain === void 0 ? void 0 : (_environments$$domain2 = _environments$$domain.nodes) === null || _environments$$domain2 === void 0 ? void 0 : _environments$$domain2.map(domain => domain.name);
|
|
160
|
+
return mappedDomains.includes(primaryDomain);
|
|
161
|
+
}
|
|
@@ -64,7 +64,7 @@ async function getReadInterface(filename) {
|
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
async function fileLineValidations(appId, envId, fileName, validations) {
|
|
67
|
+
async function fileLineValidations(appId, envId, fileName, validations, searchReplace) {
|
|
68
68
|
const isImport = true;
|
|
69
69
|
const readInterface = await getReadInterface(fileName);
|
|
70
70
|
debug('Validations: ', validations);
|
|
@@ -85,7 +85,8 @@ async function fileLineValidations(appId, envId, fileName, validations) {
|
|
|
85
85
|
fileName,
|
|
86
86
|
isImport,
|
|
87
87
|
appId,
|
|
88
|
-
envId
|
|
88
|
+
envId,
|
|
89
|
+
searchReplace
|
|
89
90
|
});
|
|
90
91
|
}
|
|
91
92
|
}));
|
|
@@ -13,6 +13,10 @@ var _isMultiSiteSqlDump = require("./is-multi-site-sql-dump");
|
|
|
13
13
|
|
|
14
14
|
var _isMultiSite = require("./is-multi-site");
|
|
15
15
|
|
|
16
|
+
var _isMultisiteDomainMapped = require("./is-multisite-domain-mapped");
|
|
17
|
+
|
|
18
|
+
var _utils = require("./utils");
|
|
19
|
+
|
|
16
20
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
21
|
|
|
18
22
|
/**
|
|
@@ -29,9 +33,12 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
29
33
|
*/
|
|
30
34
|
const debug = (0, _debug.default)('vip:vip-import-sql');
|
|
31
35
|
let isMultiSiteSqlDump = false;
|
|
36
|
+
let wpSiteInsertStatement;
|
|
37
|
+
const getWpSiteInsertStatement = (0, _utils.getMultilineStatement)(/INSERT INTO `wp_site`/s);
|
|
32
38
|
const siteTypeValidations = {
|
|
33
39
|
execute: line => {
|
|
34
40
|
const lineIsMultiSite = (0, _isMultiSiteSqlDump.sqlDumpLineIsMultiSite)(line);
|
|
41
|
+
wpSiteInsertStatement = getWpSiteInsertStatement(line);
|
|
35
42
|
|
|
36
43
|
if (lineIsMultiSite) {
|
|
37
44
|
isMultiSiteSqlDump = true;
|
|
@@ -39,9 +46,12 @@ const siteTypeValidations = {
|
|
|
39
46
|
},
|
|
40
47
|
postLineExecutionProcessing: async ({
|
|
41
48
|
appId,
|
|
42
|
-
envId
|
|
49
|
+
envId,
|
|
50
|
+
searchReplace
|
|
43
51
|
}) => {
|
|
44
52
|
const isMultiSite = await (0, _isMultiSite.isMultiSiteInSiteMeta)(appId, envId);
|
|
53
|
+
const primaryDomainFromSQL = (0, _isMultisiteDomainMapped.getPrimaryDomain)(wpSiteInsertStatement, searchReplace);
|
|
54
|
+
const isPrimaryDomainMapped = primaryDomainFromSQL && (await (0, _isMultisiteDomainMapped.isMultisitePrimaryDomainMapped)(appId, envId, primaryDomainFromSQL));
|
|
45
55
|
|
|
46
56
|
const track = _tracker.trackEventWithEnv.bind(null, appId, envId);
|
|
47
57
|
|
|
@@ -61,6 +71,13 @@ const siteTypeValidations = {
|
|
|
61
71
|
});
|
|
62
72
|
throw new Error('You have requested a subsite SQL import but have not provided a subsite compatiable SQL dump.');
|
|
63
73
|
}
|
|
74
|
+
|
|
75
|
+
if (isMultiSite && !isPrimaryDomainMapped) {
|
|
76
|
+
await track('import_sql_command_error', {
|
|
77
|
+
error_type: 'multisite-import-where-primary-domain-unmapped'
|
|
78
|
+
});
|
|
79
|
+
throw new Error('This import would set the network\'s main site domain to ' + primaryDomainFromSQL + ', however this domain is not mapped to the target environment. Please replace this domain in your ' + 'import file, or map it to the environment.');
|
|
80
|
+
}
|
|
64
81
|
}
|
|
65
82
|
};
|
|
66
83
|
exports.siteTypeValidations = siteTypeValidations;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getMultilineStatement = getMultilineStatement;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get SQL statements matching a supplied pattern from a file stream
|
|
10
|
+
*
|
|
11
|
+
* @param {RegExp} statementRegex A RegExp pattern representing the start of the statement to capture
|
|
12
|
+
* @returns {function} A function which processes individual lines to capture the matching statements
|
|
13
|
+
*/
|
|
14
|
+
function getMultilineStatement(statementRegex) {
|
|
15
|
+
const matchingStatements = [];
|
|
16
|
+
let isCapturing = false;
|
|
17
|
+
let index = 0;
|
|
18
|
+
/**
|
|
19
|
+
* Processes each line of the file stream and builds an array of statements which start with the supplied pattern
|
|
20
|
+
*
|
|
21
|
+
* @param {string} line A line from the file stream
|
|
22
|
+
* @returns {array} An array of matching statements where each statement is presented as an array of lines
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
return line => {
|
|
26
|
+
const shouldStartCapture = statementRegex.test(line);
|
|
27
|
+
const shouldEndCapture = (shouldStartCapture || isCapturing) && /;$/.test(line);
|
|
28
|
+
|
|
29
|
+
if (shouldStartCapture) {
|
|
30
|
+
isCapturing = true;
|
|
31
|
+
matchingStatements[index] = [];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (isCapturing) {
|
|
35
|
+
matchingStatements[index].push(line);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (shouldEndCapture) {
|
|
39
|
+
isCapturing = false;
|
|
40
|
+
index++;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return matchingStatements;
|
|
44
|
+
};
|
|
45
|
+
}
|
package/npm-shrinkwrap.json
CHANGED