@automattic/vip 3.18.0 → 3.19.1
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/dist/bin/vip-app.js +6 -2
- package/dist/bin/vip-import-media.js +1 -1
- package/dist/bin/vip-import-sql.js +4 -4
- package/dist/bin/vip-import-validate-files.js +1 -4
- package/dist/bin/vip-wp.js +18 -7
- package/dist/bin/vip.js +1 -1
- package/dist/commands/backup-db.js +2 -5
- package/dist/commands/dev-env-sync-sql.js +13 -4
- package/dist/commands/phpmyadmin.js +4 -7
- package/dist/commands/wp-ssh.js +3 -5
- package/dist/lib/analytics/clients/tracks.js +0 -1
- package/dist/lib/analytics/index.js +0 -1
- package/dist/lib/backup-storage-availability/backup-storage-availability.js +0 -1
- package/dist/lib/cli/command.js +9 -11
- package/dist/lib/cli/config.js +30 -11
- package/dist/lib/cli/format.js +4 -8
- package/dist/lib/config/software.js +2 -1
- package/dist/lib/custom-deploy/custom-deploy.js +2 -2
- package/dist/lib/database.js +6 -6
- package/dist/lib/dev-environment/dev-environment-cli.js +5 -3
- package/dist/lib/dev-environment/dev-environment-core.js +2 -4
- package/dist/lib/dev-environment/dev-environment-database.js +4 -0
- package/dist/lib/dev-environment/dev-environment-lando.js +3 -2
- package/dist/lib/keychain/insecure.js +0 -1
- package/dist/lib/keychain.js +5 -4
- package/dist/lib/media-import/config.js +1 -1
- package/dist/lib/site-import/status.js +2 -7
- package/dist/lib/validations/is-multisite-domain-mapped.js +3 -2
- package/dist/lib/validations/line-by-line.js +2 -2
- package/docs/CHANGELOG.md +55 -0
- package/npm-shrinkwrap.json +3650 -4015
- package/package.json +12 -15
- package/dist/bin/vip-validate-preflight.js +0 -481
- package/dist/bin/vip-validate.js +0 -11
package/dist/bin/vip-app.js
CHANGED
|
@@ -43,9 +43,13 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
43
43
|
await (0, _tracker.trackEvent)('app_command_success');
|
|
44
44
|
|
|
45
45
|
// Clone the read-only response object so we can modify it
|
|
46
|
-
const clonedResponse =
|
|
46
|
+
const clonedResponse = {
|
|
47
|
+
...res
|
|
48
|
+
};
|
|
47
49
|
clonedResponse.environments = clonedResponse.environments.map(env => {
|
|
48
|
-
const clonedEnv =
|
|
50
|
+
const clonedEnv = {
|
|
51
|
+
...env
|
|
52
|
+
};
|
|
49
53
|
clonedEnv.name = (0, _command.getEnvIdentifier)(env);
|
|
50
54
|
|
|
51
55
|
// Use the short version of git commit hash
|
|
@@ -103,8 +103,8 @@ function isValidMd5(md5) {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
|
-
* @param {AppForImport} app
|
|
107
|
-
* @param {EnvForImport} env
|
|
106
|
+
* @param {import('../lib/site-import/db-file-import').AppForImport} app
|
|
107
|
+
* @param {import('../lib/site-import/db-file-import').EnvForImport} env
|
|
108
108
|
* @param {string} fileNameOrURL
|
|
109
109
|
* @param {boolean} isUrl
|
|
110
110
|
* @param {string|null} md5
|
|
@@ -147,7 +147,7 @@ async function gates(app, env, fileNameOrURL, isUrl = false, md5 = null) {
|
|
|
147
147
|
}
|
|
148
148
|
try {
|
|
149
149
|
await (0, _clientFileUploader.checkFileAccess)(fileName);
|
|
150
|
-
} catch
|
|
150
|
+
} catch {
|
|
151
151
|
await track('import_sql_command_error', {
|
|
152
152
|
error_type: 'sqlfile-unreadable'
|
|
153
153
|
});
|
|
@@ -367,7 +367,7 @@ const displayPlaybook = ({
|
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
};
|
|
370
|
-
|
|
370
|
+
(0, _command.default)({
|
|
371
371
|
appContext: true,
|
|
372
372
|
appQuery,
|
|
373
373
|
envContext: true,
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
exports.__esModule = true;
|
|
9
9
|
exports.vipImportValidateFilesCmd = vipImportValidateFilesCmd;
|
|
10
10
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
11
|
-
var _url = _interopRequireDefault(require("url"));
|
|
12
11
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
13
12
|
var _config = require("../lib/media-import/config");
|
|
14
13
|
var _tracker = require("../lib/tracker");
|
|
@@ -24,9 +23,7 @@ async function vipImportValidateFilesCmd(arg = []) {
|
|
|
24
23
|
*
|
|
25
24
|
* Manipulating the file path/name to extract the folder name
|
|
26
25
|
*/
|
|
27
|
-
const
|
|
28
|
-
arg = _url.default.parse(folder); // Then parse the file to its URL parts
|
|
29
|
-
const filePath = arg.path; // Extract the path of the file
|
|
26
|
+
const filePath = arg.join(); // File comes in as an array as part of the args- turn it into a string
|
|
30
27
|
|
|
31
28
|
if (!(await (0, _vipImportValidateFiles.isDirectory)(filePath))) {
|
|
32
29
|
console.error(_chalk.default.red('✕ Error:'), 'The given path is not a directory. Provide a valid directory path.');
|
package/dist/bin/vip-wp.js
CHANGED
|
@@ -103,7 +103,6 @@ const bindStreamEvents = ({
|
|
|
103
103
|
if (!isSubShell) {
|
|
104
104
|
subShellRl.close();
|
|
105
105
|
process.exit();
|
|
106
|
-
return;
|
|
107
106
|
}
|
|
108
107
|
subShellRl.resume();
|
|
109
108
|
subShellRl.prompt();
|
|
@@ -131,6 +130,14 @@ const getTokenForCommand = async (appId, envId, command) => {
|
|
|
131
130
|
}
|
|
132
131
|
});
|
|
133
132
|
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Returns the error so it can be caught by the `socket.on('error')`.
|
|
136
|
+
*
|
|
137
|
+
* @param {Error} err
|
|
138
|
+
* @returns {Error}
|
|
139
|
+
*/
|
|
140
|
+
const onSocketError = err => err;
|
|
134
141
|
const launchCommandAndGetStreams = async ({
|
|
135
142
|
socket,
|
|
136
143
|
guid,
|
|
@@ -162,10 +169,7 @@ const launchCommandAndGetStreams = async ({
|
|
|
162
169
|
socket.close();
|
|
163
170
|
exit.withError(`Cancel received from server: ${message}`);
|
|
164
171
|
});
|
|
165
|
-
(0, _socket2.default)(socket).on('error',
|
|
166
|
-
// This returns the error so it can be catched by the socket.on('error')
|
|
167
|
-
return err;
|
|
168
|
-
});
|
|
172
|
+
(0, _socket2.default)(socket).off('error', onSocketError).on('error', onSocketError);
|
|
169
173
|
socket.on('error', err => {
|
|
170
174
|
if (err === 'Rate limit exceeded') {
|
|
171
175
|
console.log(_chalk.default.red('\nError:'), 'Rate limit exceeded: Please wait a moment and try again.');
|
|
@@ -262,10 +266,17 @@ const bindReconnectEvents = ({
|
|
|
262
266
|
|
|
263
267
|
// create a new input stream so that we can still catch things like SIGINT while reconnecting
|
|
264
268
|
if (currentJob.stdinStream) {
|
|
265
|
-
|
|
269
|
+
unpipeStreamsFromProcess({
|
|
270
|
+
stdin: currentJob.stdinStream,
|
|
271
|
+
stdout: currentJob.stdoutStream
|
|
272
|
+
});
|
|
266
273
|
}
|
|
267
|
-
|
|
274
|
+
currentJob.stdinStream = _socket2.default.createStream();
|
|
268
275
|
currentJob.stdoutStream = _socket2.default.createStream();
|
|
276
|
+
pipeStreamsToProcess({
|
|
277
|
+
stdin: currentJob.stdinStream,
|
|
278
|
+
stdout: currentJob.stdoutStream
|
|
279
|
+
});
|
|
269
280
|
bindStreamEvents({
|
|
270
281
|
subShellRl,
|
|
271
282
|
isSubShell,
|
package/dist/bin/vip.js
CHANGED
|
@@ -21,7 +21,7 @@ const tokenURL = 'https://dashboard.wpvip.com/me/cli/token';
|
|
|
21
21
|
const customDeployToken = process.env.WPVIP_DEPLOY_TOKEN;
|
|
22
22
|
const runCmd = async function () {
|
|
23
23
|
const cmd = (0, _command.default)();
|
|
24
|
-
cmd.command('logout', 'Log out the current authenticated VIP-CLI user.').command('app', 'Interact with applications that the current authenticated VIP-CLI user has permission to access.').command('backup', 'Generate a backup of an environment.').command('cache', 'Manage page cache for an environment.').command('config', 'Manage environment configurations.').command('dev-env', 'Create and manage VIP Local Development Environments.').command('export', 'Export a copy of data associated with an environment.').command('import', 'Import media or SQL database files to an environment.').command('logs', 'Retrieve Runtime Logs from an environment.').command('search-replace', 'Search for a string in a local SQL file and replace it with a new string.').command('slowlogs', 'Retrieve MySQL slow query logs from an environment.').command('db', "Access an environment's database.").command('sync', 'Sync the database from production to a non-production environment.').command('whoami', 'Retrieve details about the current authenticated VIP-CLI user.').command('
|
|
24
|
+
cmd.command('logout', 'Log out the current authenticated VIP-CLI user.').command('app', 'Interact with applications that the current authenticated VIP-CLI user has permission to access.').command('backup', 'Generate a backup of an environment.').command('cache', 'Manage page cache for an environment.').command('config', 'Manage environment configurations.').command('dev-env', 'Create and manage VIP Local Development Environments.').command('export', 'Export a copy of data associated with an environment.').command('import', 'Import media or SQL database files to an environment.').command('logs', 'Retrieve Runtime Logs from an environment.').command('search-replace', 'Search for a string in a local SQL file and replace it with a new string.').command('slowlogs', 'Retrieve MySQL slow query logs from an environment.').command('db', "Access an environment's database.").command('sync', 'Sync the database from production to a non-production environment.').command('whoami', 'Retrieve details about the current authenticated VIP-CLI user.').command('wp', 'Execute a WP-CLI command against an environment.');
|
|
25
25
|
cmd.argv(process.argv);
|
|
26
26
|
};
|
|
27
27
|
|
|
@@ -80,8 +80,6 @@ async function createBackupJob(appId, envId) {
|
|
|
80
80
|
|
|
81
81
|
// Library for a possible command in the future: vip backup db @app.env
|
|
82
82
|
class BackupDBCommand {
|
|
83
|
-
app;
|
|
84
|
-
env;
|
|
85
83
|
job;
|
|
86
84
|
jobStatus;
|
|
87
85
|
jobAge;
|
|
@@ -91,11 +89,11 @@ class BackupDBCommand {
|
|
|
91
89
|
PREPARE: 'prepare',
|
|
92
90
|
GENERATE: 'generate'
|
|
93
91
|
};
|
|
94
|
-
track;
|
|
95
92
|
progressTracker;
|
|
96
|
-
constructor(app, env,
|
|
93
|
+
constructor(app, env, track = async () => {}) {
|
|
97
94
|
this.app = app;
|
|
98
95
|
this.env = env;
|
|
96
|
+
this.track = track;
|
|
99
97
|
this.progressTracker = new _progress.ProgressTracker([{
|
|
100
98
|
id: this.steps.PREPARE,
|
|
101
99
|
name: 'Preparing for backup generation'
|
|
@@ -103,7 +101,6 @@ class BackupDBCommand {
|
|
|
103
101
|
id: this.steps.GENERATE,
|
|
104
102
|
name: 'Generating backup'
|
|
105
103
|
}]);
|
|
106
|
-
this.track = trackerFn;
|
|
107
104
|
}
|
|
108
105
|
log(msg) {
|
|
109
106
|
if (this.silent) {
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
exports.__esModule = true;
|
|
5
5
|
exports.DevEnvSyncSQLCommand = void 0;
|
|
6
|
+
exports.findSiteHomeUrl = findSiteHomeUrl;
|
|
6
7
|
var _vipSearchReplace = require("@automattic/vip-search-replace");
|
|
7
8
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
9
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
8
10
|
var _fs = _interopRequireDefault(require("fs"));
|
|
9
11
|
var _promises = require("node:stream/promises");
|
|
10
12
|
var _devEnvImportSql = require("./dev-env-import-sql");
|
|
@@ -17,6 +19,8 @@ var _utils = require("../lib/utils");
|
|
|
17
19
|
var _lineByLine = require("../lib/validations/line-by-line");
|
|
18
20
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
19
21
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
|
+
const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
|
|
23
|
+
|
|
20
24
|
/**
|
|
21
25
|
* Replaces the domain in the given URL
|
|
22
26
|
*
|
|
@@ -44,11 +48,11 @@ function stripProtocol(url) {
|
|
|
44
48
|
* @return Site home url. null if not found
|
|
45
49
|
*/
|
|
46
50
|
function findSiteHomeUrl(sql) {
|
|
47
|
-
const regex =
|
|
48
|
-
const url =
|
|
51
|
+
const regex = /(['"])(?:siteurl|home)\1,\s*\1([Hh][Tt][Tt][Pp][Ss]?:\/\/.+?)\1/;
|
|
52
|
+
const url = regex.exec(sql)?.[2] ?? '';
|
|
49
53
|
try {
|
|
50
|
-
new URL(url);
|
|
51
|
-
return url;
|
|
54
|
+
const parsed = new URL(url);
|
|
55
|
+
return parsed.hostname ? url : null;
|
|
52
56
|
} catch {
|
|
53
57
|
return null;
|
|
54
58
|
}
|
|
@@ -174,6 +178,10 @@ class DevEnvSyncSQLCommand {
|
|
|
174
178
|
if (!networkSites) return;
|
|
175
179
|
const primaryUrl = networkSites.find(site => site?.blogId === 1)?.homeUrl;
|
|
176
180
|
const primaryDomain = primaryUrl ? new URL(primaryUrl).hostname : '';
|
|
181
|
+
debug('Network sites: %j, primary URL: %s, primary domain: %s', networkSites.map(site => ({
|
|
182
|
+
blogId: site?.blogId,
|
|
183
|
+
homeUrl: site?.homeUrl
|
|
184
|
+
})), primaryUrl, primaryDomain);
|
|
177
185
|
for (const site of networkSites) {
|
|
178
186
|
if (!site?.blogId || site.blogId === 1) continue;
|
|
179
187
|
const url = site?.homeUrl;
|
|
@@ -285,6 +293,7 @@ DROP PROCEDURE vip_sync_update_blog_domains;
|
|
|
285
293
|
try {
|
|
286
294
|
console.log('Extracting site urls from the SQL file...');
|
|
287
295
|
this.siteUrls = await extractSiteUrls(this.sqlFile);
|
|
296
|
+
debug('Extracted site URLs: %j', this.siteUrls);
|
|
288
297
|
} catch (err) {
|
|
289
298
|
const error = err;
|
|
290
299
|
await this.track('error', {
|
|
@@ -106,19 +106,16 @@ async function getPhpMyAdminStatus(appId, envId) {
|
|
|
106
106
|
return resp?.data?.app?.environments?.[0]?.phpMyAdminStatus?.status;
|
|
107
107
|
}
|
|
108
108
|
class PhpMyAdminCommand {
|
|
109
|
-
app;
|
|
110
|
-
env;
|
|
111
109
|
silent;
|
|
112
|
-
track;
|
|
113
110
|
steps = {
|
|
114
111
|
ENABLE: 'enable',
|
|
115
112
|
GENERATE: 'generate'
|
|
116
113
|
};
|
|
117
114
|
progressTracker;
|
|
118
|
-
constructor(app, env,
|
|
115
|
+
constructor(app, env, track = async () => {}) {
|
|
119
116
|
this.app = app;
|
|
120
117
|
this.env = env;
|
|
121
|
-
this.track =
|
|
118
|
+
this.track = track;
|
|
122
119
|
this.progressTracker = new _progress.ProgressTracker([{
|
|
123
120
|
id: this.steps.ENABLE,
|
|
124
121
|
name: 'Enabling PHPMyAdmin for this environment'
|
|
@@ -141,12 +138,12 @@ class PhpMyAdminCommand {
|
|
|
141
138
|
const {
|
|
142
139
|
default: open
|
|
143
140
|
} = await import('open');
|
|
144
|
-
|
|
141
|
+
return open(url, {
|
|
145
142
|
wait: false
|
|
146
143
|
});
|
|
147
144
|
}
|
|
148
145
|
async getStatus() {
|
|
149
|
-
return
|
|
146
|
+
return getPhpMyAdminStatus(this.app.id, this.env.id);
|
|
150
147
|
}
|
|
151
148
|
async maybeEnablePhpMyAdmin() {
|
|
152
149
|
const status = await this.getStatus();
|
package/dist/commands/wp-ssh.js
CHANGED
|
@@ -49,15 +49,13 @@ class NonZeroExitCodeError extends Error {
|
|
|
49
49
|
}
|
|
50
50
|
exports.NonZeroExitCodeError = NonZeroExitCodeError;
|
|
51
51
|
class WPCliCommandOverSSH {
|
|
52
|
-
app;
|
|
53
|
-
env;
|
|
54
52
|
track;
|
|
55
53
|
constructor(app, env) {
|
|
56
54
|
this.app = app;
|
|
57
55
|
this.env = env;
|
|
58
56
|
this.track = (0, _tracker.makeCommandTracker)('wp', {
|
|
59
|
-
app:
|
|
60
|
-
env:
|
|
57
|
+
app: app.id,
|
|
58
|
+
env: env.id,
|
|
61
59
|
execution_type: 'ssh'
|
|
62
60
|
});
|
|
63
61
|
}
|
|
@@ -188,7 +186,7 @@ class WPCliCommandOverSSH {
|
|
|
188
186
|
async getSSHAuthForCommand(command, extraTrackingInfo) {
|
|
189
187
|
const api = (0, _api.default)();
|
|
190
188
|
try {
|
|
191
|
-
return api.mutate({
|
|
189
|
+
return await api.mutate({
|
|
192
190
|
mutation: TRIGGER_WP_CLI_COMMAND_MUTATION,
|
|
193
191
|
variables: {
|
|
194
192
|
input: {
|
|
@@ -18,7 +18,6 @@ const validEventOrPropNamePattern = /^[a-z_][a-z0-9_]*$/;
|
|
|
18
18
|
// TODO: add batch support (can include multiples in `events` array)
|
|
19
19
|
|
|
20
20
|
class Tracks {
|
|
21
|
-
eventPrefix;
|
|
22
21
|
userAgent;
|
|
23
22
|
baseParams;
|
|
24
23
|
static ENDPOINT = 'https://public-api.wordpress.com/rest/v1.1/tracks/record';
|
|
@@ -13,7 +13,6 @@ var _format = require("../cli/format");
|
|
|
13
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
14
|
const oneGiBInBytes = 1024 * 1024 * 1024;
|
|
15
15
|
class BackupStorageAvailability {
|
|
16
|
-
archiveSize;
|
|
17
16
|
constructor(archiveSize) {
|
|
18
17
|
this.archiveSize = archiveSize;
|
|
19
18
|
}
|
package/dist/lib/cli/command.js
CHANGED
|
@@ -316,21 +316,19 @@ _args.default.argv = async function (argv, cb) {
|
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
// Negotiate flag values
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
break;
|
|
319
|
+
if (_opts.module === 'import-media') {
|
|
320
|
+
if ([true, 'true', 'yes'].includes(options.saveErrorLog)) {
|
|
321
|
+
options.saveErrorLog = 'true';
|
|
322
|
+
} else if ([false, 'false', 'no'].includes(options.saveErrorLog)) {
|
|
323
|
+
options.saveErrorLog = 'false';
|
|
324
|
+
} else {
|
|
325
|
+
options.saveErrorLog = 'prompt';
|
|
326
|
+
}
|
|
329
327
|
}
|
|
330
328
|
|
|
331
329
|
// Prompt for confirmation if necessary
|
|
332
330
|
if (_opts.requireConfirm && !options.force) {
|
|
333
|
-
/** @type {Tuple[]} */
|
|
331
|
+
/** @type {import('./format').Tuple[]} */
|
|
334
332
|
const info = [];
|
|
335
333
|
if (options.app) {
|
|
336
334
|
info.push({
|
package/dist/lib/cli/config.js
CHANGED
|
@@ -2,19 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.default = void 0;
|
|
5
|
+
exports.loadConfigFile = loadConfigFile;
|
|
5
6
|
var _debug = _interopRequireDefault(require("debug"));
|
|
7
|
+
var _nodeFs = require("node:fs");
|
|
8
|
+
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
6
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
// I don't like using synchronous versions, but until we migrate to ESM, we have to.
|
|
11
|
+
|
|
7
12
|
const debug = (0, _debug.default)('@automattic/vip:lib:cli:config');
|
|
8
|
-
|
|
9
|
-
|
|
13
|
+
function loadConfigFile() {
|
|
14
|
+
const paths = [
|
|
10
15
|
// Get `local` config first; this will only exist in dev as it's npmignore-d.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
_nodePath.default.join(__dirname, '../../../config/config.local.json'), _nodePath.default.join(__dirname, '../../../config/config.publish.json')];
|
|
17
|
+
for (const filePath of paths) {
|
|
18
|
+
try {
|
|
19
|
+
const data = (0, _nodeFs.readFileSync)(filePath, 'utf-8');
|
|
20
|
+
debug(`Found config file at ${filePath}`);
|
|
21
|
+
return JSON.parse(data);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
if (!(err instanceof Error) || !('code' in err) || err.code !== 'ENOENT') {
|
|
24
|
+
debug(`Error reading config file at ${filePath}:`, err);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const configFromFile = loadConfigFile();
|
|
31
|
+
if (null === configFromFile) {
|
|
32
|
+
// This should not happen because `config/config.publish.json` is always present.
|
|
33
|
+
console.error('FATAL ERROR: Could not find a valid configuration file');
|
|
34
|
+
process.exit(1);
|
|
19
35
|
}
|
|
20
|
-
|
|
36
|
+
|
|
37
|
+
// Without this, TypeScript will export `configFromFile` as `Config | null`
|
|
38
|
+
const exportedConfig = configFromFile;
|
|
39
|
+
var _default = exports.default = exportedConfig;
|
package/dist/lib/cli/format.js
CHANGED
|
@@ -91,14 +91,10 @@ function keyValue(values) {
|
|
|
91
91
|
value
|
|
92
92
|
} of values) {
|
|
93
93
|
let formattedValue;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
break;
|
|
99
|
-
default:
|
|
100
|
-
formattedValue = value;
|
|
101
|
-
break;
|
|
94
|
+
if (key.toLowerCase() === 'environment') {
|
|
95
|
+
formattedValue = formatEnvironment(value);
|
|
96
|
+
} else {
|
|
97
|
+
formattedValue = value;
|
|
102
98
|
}
|
|
103
99
|
lines.push(`+ ${key}: ${formattedValue}`);
|
|
104
100
|
}
|
|
@@ -315,7 +315,8 @@ const formatSoftwareSettings = (softwareSetting, includes, format) => {
|
|
|
315
315
|
if (includes.includes('available_versions')) {
|
|
316
316
|
result.available_versions = _optionsForVersion(softwareSetting).filter(option => !option.deprecated).map(option => option.value);
|
|
317
317
|
if (format !== 'json') {
|
|
318
|
-
result.available_versions
|
|
318
|
+
result.available_versions.sort((lhs, rhs) => lhs.localeCompare(rhs));
|
|
319
|
+
result.available_versions = result.available_versions.join(',');
|
|
319
320
|
}
|
|
320
321
|
}
|
|
321
322
|
return result;
|
|
@@ -48,7 +48,7 @@ async function validateCustomDeployKey(app, env) {
|
|
|
48
48
|
throw new Error('Not found');
|
|
49
49
|
}
|
|
50
50
|
return result.data?.validateCustomDeployAccess;
|
|
51
|
-
} catch
|
|
51
|
+
} catch {
|
|
52
52
|
exit.withError(`Unauthorized: Invalid or non-existent custom deploy key for environment.`);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -93,7 +93,7 @@ async function validateFile(appId, envId, fileMeta) {
|
|
|
93
93
|
}
|
|
94
94
|
try {
|
|
95
95
|
await (0, _clientFileUploader.checkFileAccess)(fileName);
|
|
96
|
-
} catch
|
|
96
|
+
} catch {
|
|
97
97
|
await track('deploy_app_command_error', {
|
|
98
98
|
error_type: 'appfile-unreadable'
|
|
99
99
|
});
|
package/dist/lib/database.js
CHANGED
|
@@ -28,15 +28,15 @@ const getSqlDumpDetails = async filePath => {
|
|
|
28
28
|
crlfDelay: Infinity
|
|
29
29
|
});
|
|
30
30
|
let isMyDumper = false;
|
|
31
|
-
let sourceDB
|
|
31
|
+
let sourceDB;
|
|
32
32
|
let currentLineNumber = 0;
|
|
33
33
|
for await (const line of readLine) {
|
|
34
34
|
if (line === '') {
|
|
35
35
|
continue;
|
|
36
36
|
}
|
|
37
|
-
const metadataMatch =
|
|
38
|
-
const sourceDBMatch =
|
|
39
|
-
const sourceDBName = sourceDBMatch[1];
|
|
37
|
+
const metadataMatch = /^-- metadata.header /.exec(line);
|
|
38
|
+
const sourceDBMatch = /^-- (.*)-schema-create.sql/.exec(line);
|
|
39
|
+
const sourceDBName = sourceDBMatch?.[1];
|
|
40
40
|
if (metadataMatch && !isMyDumper) {
|
|
41
41
|
isMyDumper = true;
|
|
42
42
|
}
|
|
@@ -87,13 +87,13 @@ const getSqlFileStreamFromCompressedFile = async filePath => {
|
|
|
87
87
|
throw new Error('Not a supported compressed file');
|
|
88
88
|
};
|
|
89
89
|
const fixMyDumperTransform = () => {
|
|
90
|
+
const regex = /^-- ([^ ]+) \d+$/;
|
|
90
91
|
return new _nodeStream.Transform({
|
|
91
92
|
transform(chunk, _encoding, callback) {
|
|
92
93
|
const chunkString = chunk.toString();
|
|
93
94
|
const lineEnding = chunkString.includes('\r\n') ? '\r\n' : '\n';
|
|
94
|
-
const regex = /^-- ([^ ]+) [0-9]+$/;
|
|
95
95
|
const lines = chunk.toString().split(lineEnding).map(line => {
|
|
96
|
-
const match =
|
|
96
|
+
const match = regex.exec(line);
|
|
97
97
|
if (!match) {
|
|
98
98
|
return line;
|
|
99
99
|
}
|
|
@@ -300,11 +300,13 @@ async function processWordPress(preselectedValue, defaultValue) {
|
|
|
300
300
|
if (versions.length) {
|
|
301
301
|
versions.sort((before, after) => before.tag < after.tag ? 1 : -1);
|
|
302
302
|
const match = versions.find(({
|
|
303
|
+
prerelease,
|
|
303
304
|
tag
|
|
304
|
-
}) => tag === result.tag);
|
|
305
|
-
if (
|
|
305
|
+
}) => result.tag === 'latest' ? !prerelease : tag === result.tag);
|
|
306
|
+
if (match === undefined) {
|
|
306
307
|
throw new _userError.default(`Unknown or unsupported WordPress version: ${result.tag}.`);
|
|
307
308
|
}
|
|
309
|
+
result.tag = match.tag;
|
|
308
310
|
}
|
|
309
311
|
debug(result);
|
|
310
312
|
return result;
|
|
@@ -677,7 +679,7 @@ function processVersionOption(value) {
|
|
|
677
679
|
const phpVersionsSupported = Object.keys(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS).join(', ');
|
|
678
680
|
function addDevEnvConfigurationOptions(command) {
|
|
679
681
|
// We leave the third parameter to undefined on some because the defaults are handled in preProcessInstanceData()
|
|
680
|
-
return command.option('wordpress', 'Manage the version of WordPress. Accepts a string value for major versions (6.x). Defaults to the
|
|
682
|
+
return command.option('wordpress', 'Manage the version of WordPress. Accepts a string value for major versions (6.x) or "latest". Defaults to the recommended version of WordPress for development.', undefined, processVersionOption).option(['u', 'mu-plugins'], 'Manage the source for VIP MU plugins. Accepts "demo" (default) for a read-only image of the staging branch, or a path to a built copy of VIP MU plugins on the local machine.').option('app-code', 'Manage the source for application code. Accepts "demo" (default) for a read-only image of WordPress VIP skeleton application code, or a path to a VIP formatted application repo on the local machine.').option('phpmyadmin', 'Enable or disable phpMyAdmin, disabled by default. Accepts "y" (default value) to enable or "n" to disable. When enabled, refer to the value of "PHPMYADMIN URLS" in the information output for a local environment for the URL to access phpMyAdmin.', undefined, processBooleanOption).option('xdebug', 'Enable or disable XDebug, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption).option('xdebug_config', 'Override some default configuration settings for Xdebug. Accepts a string value that is assigned to the XDEBUG_CONFIG environment variable.').option('elasticsearch', 'Enable or disable Elasticsearch (required by Enterprise Search), disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption).option(['r', 'media-redirect-domain'], 'Configure media files to be proxied from a VIP Platform environment. Accepts a string value for the primary domain of the VIP Platform environment or "n" to disable the media proxy.', undefined, processMediaRedirectDomainOption).option('php', `Manage the version of PHP. Accepts a string value for minor versions: ${phpVersionsSupported}`, undefined, processVersionOption).option('cron', 'Enable or disable cron, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption).option(['A', 'mailpit'], 'Enable or disable Mailpit, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption).option(['H', 'photon'], 'Enable or disable Photon, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption);
|
|
681
683
|
}
|
|
682
684
|
|
|
683
685
|
/**
|
|
@@ -155,8 +155,6 @@ function preProcessInstanceData(instanceData) {
|
|
|
155
155
|
// We need to make sure the redirect is an absolute path
|
|
156
156
|
newInstanceData.mediaRedirectDomain = `https://${instanceData.mediaRedirectDomain}`;
|
|
157
157
|
}
|
|
158
|
-
|
|
159
|
-
// isNaN supports only number in TypeScript, actually, because isNaN('123') returns false despite being a string
|
|
160
158
|
if (isNaN(instanceData.wordpress.tag)) {
|
|
161
159
|
newInstanceData.wordpress.tag = 'trunk';
|
|
162
160
|
}
|
|
@@ -712,7 +710,8 @@ async function isVersionListExpired(cacheFile, ttl) {
|
|
|
712
710
|
} = await _nodeFs.default.promises.stat(cacheFile);
|
|
713
711
|
expire.setSeconds(expire.getSeconds() + ttl);
|
|
714
712
|
return Number(new Date()) > Number(expire);
|
|
715
|
-
} catch (
|
|
713
|
+
} catch (error) {
|
|
714
|
+
debug(`Error checking version list expiration for cache file ${cacheFile}:`, error);
|
|
716
715
|
return true;
|
|
717
716
|
}
|
|
718
717
|
}
|
|
@@ -844,7 +843,6 @@ function getVSCodeWorkspacePath(slug) {
|
|
|
844
843
|
function generatePHPStormWorkspace(slug) {
|
|
845
844
|
debug('Generating PHPStorm Workspace');
|
|
846
845
|
const location = getEnvironmentPath(slug);
|
|
847
|
-
// const location = location;
|
|
848
846
|
const instanceData = readEnvironmentData(slug);
|
|
849
847
|
const pathMappings = generatePathMappings(location, instanceData);
|
|
850
848
|
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.reIndexSearch = exports.generatePassword = exports.flushCache = exports.executeQuery = exports.dataCleanup = exports.addAdminUser = void 0;
|
|
5
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
5
6
|
var _nodeCrypto = require("node:crypto");
|
|
6
7
|
var _devEnvironmentCore = require("./dev-environment-core");
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
|
|
7
10
|
const generatePassword = () => {
|
|
8
11
|
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_';
|
|
9
12
|
const passwordLength = 12;
|
|
@@ -36,6 +39,7 @@ const dataCleanup = async (lando, slug, quiet) => {
|
|
|
36
39
|
} catch (error) {
|
|
37
40
|
// This must not be a fatal error
|
|
38
41
|
console.log('WARNING: data cleanup failed.');
|
|
42
|
+
debug('Error during data cleanup:', error);
|
|
39
43
|
}
|
|
40
44
|
};
|
|
41
45
|
exports.dataCleanup = dataCleanup;
|
|
@@ -112,7 +112,8 @@ async function regenerateLandofile(lando, instancePath) {
|
|
|
112
112
|
const backup = `${landoFile}.${now}`;
|
|
113
113
|
await (0, _promises2.rename)(landoFile, backup);
|
|
114
114
|
console.warn(_chalk.default.yellow('Backed up %s to %s'), landoFile, backup);
|
|
115
|
-
} catch (
|
|
115
|
+
} catch (error) {
|
|
116
|
+
debug(`Failed to backup lando file ${landoFile}:`, error);
|
|
116
117
|
// Rename failed - possibly the file does not exist. Silently ignoring.
|
|
117
118
|
}
|
|
118
119
|
const slug = _nodePath.default.basename(instancePath);
|
|
@@ -409,7 +410,7 @@ async function tryResolveDomains(urls) {
|
|
|
409
410
|
const domains = [...new Set(urls.filter(url => url.toLowerCase().startsWith('http')).map(url => {
|
|
410
411
|
try {
|
|
411
412
|
return new URL(url).hostname;
|
|
412
|
-
} catch
|
|
413
|
+
} catch {
|
|
413
414
|
return undefined;
|
|
414
415
|
}
|
|
415
416
|
}).filter(domain => domain !== undefined))];
|
package/dist/lib/keychain.js
CHANGED
|
@@ -5,17 +5,18 @@ exports.default = void 0;
|
|
|
5
5
|
var _debug = _interopRequireDefault(require("debug"));
|
|
6
6
|
var _insecure = _interopRequireDefault(require("./keychain/insecure"));
|
|
7
7
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
-
let
|
|
8
|
+
let keychain;
|
|
9
9
|
const debug = (0, _debug.default)('@automattic/vip:keychain');
|
|
10
10
|
try {
|
|
11
11
|
// Try using Secure keychain ("keytar") first
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
13
13
|
const Secure = require('./keychain/secure');
|
|
14
|
-
|
|
14
|
+
keychain = new Secure();
|
|
15
15
|
} catch (error) {
|
|
16
16
|
debug('Cannot use Secure keychain; falling back to Insecure keychain (Details: %o)', error);
|
|
17
17
|
|
|
18
18
|
// Fallback to Insecure keychain if we can't
|
|
19
|
-
|
|
19
|
+
keychain = new _insecure.default('vip-go-cli');
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const exportedKeychain = keychain;
|
|
22
|
+
var _default = exports.default = exportedKeychain;
|