@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,555 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
9
|
+
|
|
10
|
+
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
11
|
+
|
|
12
|
+
var _socket = _interopRequireDefault(require("socket.io-client"));
|
|
13
|
+
|
|
14
|
+
var _socket2 = _interopRequireDefault(require("socket.io-stream"));
|
|
15
|
+
|
|
16
|
+
var _readline = _interopRequireDefault(require("readline"));
|
|
17
|
+
|
|
18
|
+
var _stream = require("stream");
|
|
19
|
+
|
|
20
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
21
|
+
|
|
22
|
+
var _api = _interopRequireWildcard(require("../lib/api"));
|
|
23
|
+
|
|
24
|
+
var _command = _interopRequireWildcard(require("../lib/cli/command"));
|
|
25
|
+
|
|
26
|
+
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
27
|
+
|
|
28
|
+
var _format = require("../lib/cli/format");
|
|
29
|
+
|
|
30
|
+
var _prompt = require("../lib/cli/prompt");
|
|
31
|
+
|
|
32
|
+
var _tracker = require("../lib/tracker");
|
|
33
|
+
|
|
34
|
+
var _token = _interopRequireDefault(require("../lib/token"));
|
|
35
|
+
|
|
36
|
+
var _rollbar = require("../lib/rollbar");
|
|
37
|
+
|
|
38
|
+
var _socksProxyAgent = _interopRequireDefault(require("../lib/http/socks-proxy-agent"));
|
|
39
|
+
|
|
40
|
+
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); }
|
|
41
|
+
|
|
42
|
+
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; }
|
|
43
|
+
|
|
44
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Internal dependencies
|
|
48
|
+
*/
|
|
49
|
+
const debug = (0, _debug.default)('@automattic/vip:wp');
|
|
50
|
+
const appQuery = `id, name,
|
|
51
|
+
organization {
|
|
52
|
+
id
|
|
53
|
+
name
|
|
54
|
+
}
|
|
55
|
+
environments {
|
|
56
|
+
id
|
|
57
|
+
appId
|
|
58
|
+
type
|
|
59
|
+
name
|
|
60
|
+
primaryDomain {
|
|
61
|
+
name
|
|
62
|
+
}
|
|
63
|
+
}`;
|
|
64
|
+
const NON_TTY_COLUMNS = 100;
|
|
65
|
+
const NON_TTY_ROWS = 15;
|
|
66
|
+
const cancelCommandChar = '\x03';
|
|
67
|
+
let currentJob = null;
|
|
68
|
+
let currentOffset = 0;
|
|
69
|
+
let commandRunning = false;
|
|
70
|
+
|
|
71
|
+
const pipeStreamsToProcess = ({
|
|
72
|
+
stdin,
|
|
73
|
+
stdout: outStream
|
|
74
|
+
}) => {
|
|
75
|
+
process.stdin.pipe(stdin);
|
|
76
|
+
outStream.pipe(process.stdout);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const unpipeStreamsFromProcess = ({
|
|
80
|
+
stdin,
|
|
81
|
+
stdout: outStream
|
|
82
|
+
}) => {
|
|
83
|
+
process.stdin.unpipe(stdin);
|
|
84
|
+
outStream.unpipe(process.stdout);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const bindStreamEvents = ({
|
|
88
|
+
subShellRl,
|
|
89
|
+
commonTrackingParams,
|
|
90
|
+
isSubShell,
|
|
91
|
+
stdoutStream
|
|
92
|
+
}) => {
|
|
93
|
+
stdoutStream.on('error', err => {
|
|
94
|
+
commandRunning = false; // TODO handle this better
|
|
95
|
+
|
|
96
|
+
console.error('Error: ' + err.message);
|
|
97
|
+
});
|
|
98
|
+
stdoutStream.on('end', async () => {
|
|
99
|
+
subShellRl.clearLine();
|
|
100
|
+
commandRunning = false;
|
|
101
|
+
await (0, _tracker.trackEvent)('wpcli_command_end', commonTrackingParams); // Tell socket.io to stop trying to connect
|
|
102
|
+
|
|
103
|
+
currentJob.socket.close();
|
|
104
|
+
unpipeStreamsFromProcess({
|
|
105
|
+
stdin: currentJob.stdinStream,
|
|
106
|
+
stdout: currentJob.stdoutStream
|
|
107
|
+
}); // Reset offset
|
|
108
|
+
|
|
109
|
+
currentOffset = 0;
|
|
110
|
+
|
|
111
|
+
if (!isSubShell) {
|
|
112
|
+
subShellRl.close();
|
|
113
|
+
process.exit();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
subShellRl.resume();
|
|
118
|
+
subShellRl.prompt();
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const getTokenForCommand = async (appId, envId, command) => {
|
|
123
|
+
const api = await (0, _api.default)();
|
|
124
|
+
return api.mutate({
|
|
125
|
+
// $FlowFixMe: gql template is not supported by flow
|
|
126
|
+
mutation: (0, _graphqlTag.default)`
|
|
127
|
+
mutation TriggerWPCLICommandMutation($input: AppEnvironmentTriggerWPCLICommandInput ){
|
|
128
|
+
triggerWPCLICommandOnAppEnvironment( input: $input ) {
|
|
129
|
+
inputToken
|
|
130
|
+
command {
|
|
131
|
+
guid
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
`,
|
|
136
|
+
variables: {
|
|
137
|
+
input: {
|
|
138
|
+
id: appId,
|
|
139
|
+
environmentId: envId,
|
|
140
|
+
command
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}; // eslint-disable-next-line no-unused-vars
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
const cancelCommand = async guid => {
|
|
148
|
+
const api = await (0, _api.default)();
|
|
149
|
+
return api.mutate({
|
|
150
|
+
// $FlowFixMe: gql template is not supported by flow
|
|
151
|
+
mutation: (0, _graphqlTag.default)`
|
|
152
|
+
mutation cancelWPCLICommand($input: CancelWPCLICommandInput ){
|
|
153
|
+
cancelWPCLICommand( input: $input ) {
|
|
154
|
+
command {
|
|
155
|
+
id
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
`,
|
|
160
|
+
variables: {
|
|
161
|
+
input: {
|
|
162
|
+
guid: guid
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const launchCommandAndGetStreams = async ({
|
|
169
|
+
socket,
|
|
170
|
+
guid,
|
|
171
|
+
inputToken,
|
|
172
|
+
offset = 0
|
|
173
|
+
}) => {
|
|
174
|
+
const stdoutStream = _socket2.default.createStream();
|
|
175
|
+
|
|
176
|
+
const stdinStream = _socket2.default.createStream();
|
|
177
|
+
|
|
178
|
+
stdoutStream.on('data', data => {
|
|
179
|
+
currentOffset = data.length + currentOffset;
|
|
180
|
+
}); // TODO handle all arguments
|
|
181
|
+
// TODO handle disconnect - does IOStream correctly buffer stdin?
|
|
182
|
+
// TODO stderr - currently server doesn't support it, so errors don't terminate process
|
|
183
|
+
|
|
184
|
+
const data = {
|
|
185
|
+
guid,
|
|
186
|
+
inputToken,
|
|
187
|
+
columns: process.stdout.columns || NON_TTY_COLUMNS,
|
|
188
|
+
rows: process.stdout.rows || NON_TTY_ROWS,
|
|
189
|
+
offset
|
|
190
|
+
};
|
|
191
|
+
(0, _socket2.default)(socket).emit('cmd', data, stdinStream, stdoutStream);
|
|
192
|
+
socket.on('unauthorized', err => {
|
|
193
|
+
console.log('There was an error with the authentication:', err.message);
|
|
194
|
+
});
|
|
195
|
+
socket.on('cancel', message => {
|
|
196
|
+
socket.close();
|
|
197
|
+
exit.withError(`Cancel received from server: ${message}`);
|
|
198
|
+
});
|
|
199
|
+
(0, _socket2.default)(socket).on('error', err => {
|
|
200
|
+
// This returns the error so it can be catched by the socket.on('error')
|
|
201
|
+
_rollbar.rollbar.error(err);
|
|
202
|
+
|
|
203
|
+
return err;
|
|
204
|
+
});
|
|
205
|
+
socket.on('error', err => {
|
|
206
|
+
if (err === 'Rate limit exceeded') {
|
|
207
|
+
console.log(_chalk.default.red('\nError:'), 'Rate limit exceeded: Please wait a moment and try again.');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
_rollbar.rollbar.error(err);
|
|
212
|
+
|
|
213
|
+
console.log(err);
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
stdinStream,
|
|
217
|
+
stdoutStream,
|
|
218
|
+
socket
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const bindReconnectEvents = ({
|
|
223
|
+
cliCommand,
|
|
224
|
+
inputToken,
|
|
225
|
+
subShellRl,
|
|
226
|
+
commonTrackingParams,
|
|
227
|
+
isSubShell
|
|
228
|
+
}) => {
|
|
229
|
+
currentJob.socket.io.removeAllListeners('reconnect');
|
|
230
|
+
currentJob.socket.io.removeAllListeners('reconnect_attempt');
|
|
231
|
+
currentJob.socket.removeAllListeners('retry');
|
|
232
|
+
currentJob.socket.io.on('reconnect', async () => {
|
|
233
|
+
debug('socket.io: reconnect');
|
|
234
|
+
|
|
235
|
+
_rollbar.rollbar.info('WP-CLI socket.io.on( \'reconnect\' )', {
|
|
236
|
+
custom: {
|
|
237
|
+
code: 'wp-cli-on-reconnect',
|
|
238
|
+
commandGuid: cliCommand.guid
|
|
239
|
+
}
|
|
240
|
+
}); // Close old streams
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
unpipeStreamsFromProcess({
|
|
244
|
+
stdin: currentJob.stdinStream,
|
|
245
|
+
stdout: currentJob.stdoutStream
|
|
246
|
+
});
|
|
247
|
+
(0, _tracker.trackEvent)('wpcli_command_reconnect', commonTrackingParams);
|
|
248
|
+
currentJob = await launchCommandAndGetStreams({
|
|
249
|
+
socket: currentJob.socket,
|
|
250
|
+
guid: cliCommand.guid,
|
|
251
|
+
inputToken: inputToken,
|
|
252
|
+
offset: currentOffset
|
|
253
|
+
}); // Rebind new streams
|
|
254
|
+
|
|
255
|
+
pipeStreamsToProcess({
|
|
256
|
+
stdin: currentJob.stdinStream,
|
|
257
|
+
stdout: currentJob.stdoutStream
|
|
258
|
+
});
|
|
259
|
+
bindStreamEvents({
|
|
260
|
+
subShellRl,
|
|
261
|
+
isSubShell,
|
|
262
|
+
commonTrackingParams,
|
|
263
|
+
stdoutStream: currentJob.stdoutStream
|
|
264
|
+
});
|
|
265
|
+
bindReconnectEvents({
|
|
266
|
+
cliCommand,
|
|
267
|
+
inputToken,
|
|
268
|
+
subShellRl,
|
|
269
|
+
commonTrackingParams,
|
|
270
|
+
isSubShell
|
|
271
|
+
}); // Resume readline interface
|
|
272
|
+
|
|
273
|
+
subShellRl.resume();
|
|
274
|
+
});
|
|
275
|
+
currentJob.socket.on('retry', async () => {
|
|
276
|
+
debug('socket: retry');
|
|
277
|
+
|
|
278
|
+
_rollbar.rollbar.info('WP-CLI socket.io.on( \'retry\' )', {
|
|
279
|
+
custom: {
|
|
280
|
+
code: 'wp-cli-on-retry',
|
|
281
|
+
commandGuid: cliCommand.guid
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
setTimeout(() => {
|
|
286
|
+
currentJob.socket.io.engine.close();
|
|
287
|
+
}, 5000);
|
|
288
|
+
});
|
|
289
|
+
currentJob.socket.on('exit', async ({
|
|
290
|
+
exitCode,
|
|
291
|
+
message
|
|
292
|
+
}) => {
|
|
293
|
+
debug('socket: exit. Code: %d. Message: %s', exitCode, message);
|
|
294
|
+
|
|
295
|
+
if (message) {
|
|
296
|
+
console.log(message);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
currentJob.stdinStream.destroy();
|
|
300
|
+
currentJob.stdoutStream.destroy();
|
|
301
|
+
currentJob.socket.close();
|
|
302
|
+
process.exit(exitCode);
|
|
303
|
+
});
|
|
304
|
+
currentJob.socket.io.on('reconnect_attempt', attempt => {
|
|
305
|
+
console.error('There was an error connecting to the server. Retrying...');
|
|
306
|
+
|
|
307
|
+
if (attempt > 1) {
|
|
308
|
+
return;
|
|
309
|
+
} // create a new input stream so that we can still catch things like SIGINT while reconnecting
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
if (currentJob.stdinStream) {
|
|
313
|
+
process.stdin.unpipe(currentJob.stdinStream);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
process.stdin.pipe(_socket2.default.createStream());
|
|
317
|
+
currentJob.stdoutStream = _socket2.default.createStream();
|
|
318
|
+
bindStreamEvents({
|
|
319
|
+
subShellRl,
|
|
320
|
+
isSubShell,
|
|
321
|
+
commonTrackingParams,
|
|
322
|
+
stdoutStream: currentJob.stdoutStream
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
(0, _command.default)({
|
|
328
|
+
wildcardCommand: true,
|
|
329
|
+
appContext: true,
|
|
330
|
+
envContext: true,
|
|
331
|
+
appQuery
|
|
332
|
+
}).option('yes', 'Run the command in production without a confirmation prompt').argv(process.argv, async (args, opts) => {
|
|
333
|
+
const isSubShell = 0 === args.length; // Have to re-quote anything that needs it before we pass it on
|
|
334
|
+
|
|
335
|
+
const quotedArgs = (0, _format.requoteArgs)(args);
|
|
336
|
+
const cmd = quotedArgs.join(' '); // Store only the first 2 parts of command to avoid recording secrets. Can be tweaked
|
|
337
|
+
|
|
338
|
+
const commandForAnalytics = quotedArgs.slice(0, 2).join(' ');
|
|
339
|
+
const {
|
|
340
|
+
id: appId,
|
|
341
|
+
name: appName,
|
|
342
|
+
organization: {
|
|
343
|
+
id: orgId
|
|
344
|
+
}
|
|
345
|
+
} = opts.app;
|
|
346
|
+
const {
|
|
347
|
+
id: envId,
|
|
348
|
+
type: envName
|
|
349
|
+
} = opts.env;
|
|
350
|
+
/* eslint-disable camelcase */
|
|
351
|
+
|
|
352
|
+
const commonTrackingParams = {
|
|
353
|
+
command: commandForAnalytics,
|
|
354
|
+
app_id: appId,
|
|
355
|
+
env_id: envId,
|
|
356
|
+
org_id: orgId,
|
|
357
|
+
method: isSubShell ? 'subshell' : 'shell'
|
|
358
|
+
};
|
|
359
|
+
/* eslint-enable camelcase */
|
|
360
|
+
|
|
361
|
+
(0, _tracker.trackEvent)('wpcli_command_execute', commonTrackingParams);
|
|
362
|
+
|
|
363
|
+
if (isSubShell) {
|
|
364
|
+
// Reset the cursor (can get messed up with enquirer)
|
|
365
|
+
process.stdout.write('\u001b[?25h');
|
|
366
|
+
console.log(`Welcome to the WP CLI shell for the ${(0, _format.formatEnvironment)(envName)} environment of ${_chalk.default.green(appName)} (${opts.env.primaryDomain.name})!`);
|
|
367
|
+
} else if (envName === 'production') {
|
|
368
|
+
const yes = opts.yes || (await (0, _prompt.confirm)([{
|
|
369
|
+
key: 'command',
|
|
370
|
+
value: `wp ${cmd}`
|
|
371
|
+
}], `Are you sure you want to run this command on ${(0, _format.formatEnvironment)(envName)} for site ${appName}?`));
|
|
372
|
+
|
|
373
|
+
if (!yes) {
|
|
374
|
+
(0, _tracker.trackEvent)('wpcli_confirm_cancel', commonTrackingParams);
|
|
375
|
+
console.log('Command cancelled');
|
|
376
|
+
process.exit();
|
|
377
|
+
}
|
|
378
|
+
} // We'll handle our own errors, thank you
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
(0, _api.disableGlobalGraphQLErrorHandling)();
|
|
382
|
+
const promptIdentifier = `${appName}.${(0, _command.getEnvIdentifier)(opts.env)}`;
|
|
383
|
+
let countSIGINT = 0;
|
|
384
|
+
const mutableStdout = new _stream.Writable({
|
|
385
|
+
write: function (chunk, encoding, callback) {
|
|
386
|
+
if (!this.muted) {
|
|
387
|
+
process.stdout.write(chunk, encoding);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
callback();
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
mutableStdout.muted = false;
|
|
394
|
+
const subShellSettings = {
|
|
395
|
+
input: process.stdin,
|
|
396
|
+
output: mutableStdout,
|
|
397
|
+
terminal: true,
|
|
398
|
+
prompt: '',
|
|
399
|
+
historySize: 0
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
if (isSubShell) {
|
|
403
|
+
subShellSettings.prompt = (0, _chalk.default)`{bold.yellowBright ${promptIdentifier}:}{blue ~}$ `;
|
|
404
|
+
subShellSettings.historySize = 200;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const subShellRl = _readline.default.createInterface(subShellSettings);
|
|
408
|
+
|
|
409
|
+
subShellRl.on('line', async line => {
|
|
410
|
+
if (commandRunning) {
|
|
411
|
+
return;
|
|
412
|
+
} // Handle plain return / newline
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
if (!line) {
|
|
416
|
+
subShellRl.prompt();
|
|
417
|
+
return;
|
|
418
|
+
} // Check for exit, like SSH (handles both `exit` and `exit;`)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
if (line.startsWith('exit')) {
|
|
422
|
+
subShellRl.close();
|
|
423
|
+
process.exit();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const startsWithWp = line.startsWith('wp ');
|
|
427
|
+
const empty = 0 === line.length;
|
|
428
|
+
const userCmdCancelled = line === cancelCommandChar;
|
|
429
|
+
|
|
430
|
+
if ((empty || !startsWithWp) && !userCmdCancelled) {
|
|
431
|
+
console.log(_chalk.default.red('Error:'), 'invalid command, please pass a valid WP CLI command.');
|
|
432
|
+
subShellRl.prompt();
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
subShellRl.pause();
|
|
437
|
+
let result;
|
|
438
|
+
|
|
439
|
+
try {
|
|
440
|
+
result = await getTokenForCommand(appId, envId, line.replace('wp ', ''));
|
|
441
|
+
} catch (error) {
|
|
442
|
+
// If this was a GraphQL error, print that to the message to the line
|
|
443
|
+
if (error.graphQLErrors) {
|
|
444
|
+
error.graphQLErrors.forEach(err => {
|
|
445
|
+
console.log(_chalk.default.red('Error:'), err.message);
|
|
446
|
+
});
|
|
447
|
+
} else {
|
|
448
|
+
// Else, other type of error, just dump it
|
|
449
|
+
_rollbar.rollbar.error(error);
|
|
450
|
+
|
|
451
|
+
console.log(error);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (!isSubShell) {
|
|
455
|
+
subShellRl.close();
|
|
456
|
+
process.exit(1);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
subShellRl.prompt();
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const {
|
|
464
|
+
data: {
|
|
465
|
+
triggerWPCLICommandOnAppEnvironment: {
|
|
466
|
+
command: cliCommand,
|
|
467
|
+
inputToken
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
} = result;
|
|
471
|
+
|
|
472
|
+
if (line.includes("'")) {
|
|
473
|
+
_rollbar.rollbar.info('WP-CLI Command containing single quotes', {
|
|
474
|
+
custom: {
|
|
475
|
+
code: 'wp-cli-single-quotes',
|
|
476
|
+
commandGuid: cliCommand.guid
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const token = await _token.default.get();
|
|
482
|
+
const socket = (0, _socket.default)(`${_api.API_HOST}/wp-cli`, {
|
|
483
|
+
transportOptions: {
|
|
484
|
+
polling: {
|
|
485
|
+
extraHeaders: {
|
|
486
|
+
Authorization: `Bearer ${token.raw}`
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
agent: (0, _socksProxyAgent.default)()
|
|
491
|
+
});
|
|
492
|
+
currentJob = await launchCommandAndGetStreams({
|
|
493
|
+
socket,
|
|
494
|
+
guid: cliCommand.guid,
|
|
495
|
+
inputToken: inputToken
|
|
496
|
+
});
|
|
497
|
+
pipeStreamsToProcess({
|
|
498
|
+
stdin: currentJob.stdinStream,
|
|
499
|
+
stdout: currentJob.stdoutStream
|
|
500
|
+
});
|
|
501
|
+
commandRunning = true;
|
|
502
|
+
bindStreamEvents({
|
|
503
|
+
subShellRl,
|
|
504
|
+
commonTrackingParams,
|
|
505
|
+
isSubShell,
|
|
506
|
+
stdoutStream: currentJob.stdoutStream
|
|
507
|
+
});
|
|
508
|
+
bindReconnectEvents({
|
|
509
|
+
cliCommand,
|
|
510
|
+
inputToken,
|
|
511
|
+
subShellRl,
|
|
512
|
+
commonTrackingParams,
|
|
513
|
+
isSubShell
|
|
514
|
+
});
|
|
515
|
+
}); // Fix to re-add the \n character that readline strips when terminal == true
|
|
516
|
+
|
|
517
|
+
process.stdin.on('data', data => {
|
|
518
|
+
// only run this in interactive mode for prompts from WP commands
|
|
519
|
+
if (commandRunning && 0 === Buffer.compare(data, Buffer.from('\r'))) {
|
|
520
|
+
if (currentJob && currentJob.stdinStream) {
|
|
521
|
+
currentJob.stdinStream.write('\n');
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
subShellRl.on('SIGINT', async () => {
|
|
526
|
+
// if we have a 2nd SIGINT, exit immediately
|
|
527
|
+
if (countSIGINT >= 1) {
|
|
528
|
+
process.exit();
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
countSIGINT += 1; // write out CTRL-C/SIGINT
|
|
532
|
+
|
|
533
|
+
process.stdin.write(cancelCommandChar);
|
|
534
|
+
|
|
535
|
+
if (currentJob && currentJob.stdoutStream) {
|
|
536
|
+
currentJob.stdoutStream.end();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
await (0, _tracker.trackEvent)('wpcli_cancel_command', commonTrackingParams);
|
|
540
|
+
console.log('Command cancelled by user'); // if no command running (.e.g. interactive shell, exit only after doing cleanup)
|
|
541
|
+
|
|
542
|
+
if (commandRunning === false) {
|
|
543
|
+
process.exit();
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
if (!isSubShell) {
|
|
548
|
+
mutableStdout.muted = true;
|
|
549
|
+
subShellRl.write(`wp ${cmd}\n`);
|
|
550
|
+
mutableStdout.muted = false;
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
subShellRl.prompt();
|
|
555
|
+
});
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
var _opn = _interopRequireDefault(require("opn"));
|
|
9
|
+
|
|
10
|
+
var _enquirer = require("enquirer");
|
|
11
|
+
|
|
12
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
13
|
+
|
|
14
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
15
|
+
|
|
16
|
+
var _config = _interopRequireDefault(require("../../config/config.json"));
|
|
17
|
+
|
|
18
|
+
var _command = _interopRequireWildcard(require("../lib/cli/command"));
|
|
19
|
+
|
|
20
|
+
var _token = _interopRequireDefault(require("../lib/token"));
|
|
21
|
+
|
|
22
|
+
var _tracker = require("../lib/tracker");
|
|
23
|
+
|
|
24
|
+
var _rollbar = require("../lib/rollbar");
|
|
25
|
+
|
|
26
|
+
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); }
|
|
27
|
+
|
|
28
|
+
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; }
|
|
29
|
+
|
|
30
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Internal dependencies
|
|
34
|
+
*/
|
|
35
|
+
const debug = (0, _debug.default)('@automattic/vip:bin:vip');
|
|
36
|
+
|
|
37
|
+
if (_config.default && _config.default.environment !== 'production') {
|
|
38
|
+
debug(`${_chalk.default.bgYellow('WARNING:')} RUNNING DEV VERSION OF @automattic/vip`);
|
|
39
|
+
debug('You should `npm link` your locally checked out copy of this repo as part of your development setup.');
|
|
40
|
+
} // Config
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const tokenURL = 'https://dashboard.wpvip.com/me/cli/token';
|
|
44
|
+
|
|
45
|
+
const runCmd = async function () {
|
|
46
|
+
const cmd = (0, _command.default)();
|
|
47
|
+
cmd.command('logout', 'Logout from your current session', async () => {
|
|
48
|
+
await _token.default.purge();
|
|
49
|
+
await (0, _tracker.trackEvent)('logout_command_execute');
|
|
50
|
+
console.log('You are successfully logged out.');
|
|
51
|
+
}).command('app', 'List and modify your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-environment').command('import', 'Import media or SQL files into your VIP applications').command('logs', 'Get logs from your VIP applications').command('search-replace', 'Perform search and replace tasks on files').command('sync', 'Sync production to a development environment').command('whoami', 'Display details about the currently logged-in user').command('wp', 'Run WP CLI commands against an environment');
|
|
52
|
+
cmd.argv(process.argv);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const rootCmd = async function () {
|
|
56
|
+
let token = await _token.default.get();
|
|
57
|
+
const isHelpCommand = process.argv.some(arg => arg === 'help' || arg === '-h' || arg === '--help');
|
|
58
|
+
const isLogoutCommand = process.argv.some(arg => arg === 'logout');
|
|
59
|
+
const isDevEnvCommandWithoutEnv = process.argv.some(arg => arg === 'dev-env') && !(0, _command.containsAppEnvArgument)(process.argv);
|
|
60
|
+
debug('Argv:', process.argv);
|
|
61
|
+
|
|
62
|
+
if (isLogoutCommand || isHelpCommand || isDevEnvCommandWithoutEnv || token && token.valid()) {
|
|
63
|
+
runCmd();
|
|
64
|
+
} else {
|
|
65
|
+
console.log();
|
|
66
|
+
console.log(' Welcome to');
|
|
67
|
+
console.log(' _ __ ________ ________ ____');
|
|
68
|
+
console.log(' | | / // _/ __ \ / ____/ / / _/');
|
|
69
|
+
console.log(' | | / / / // /_/ /______/ / / / / / ');
|
|
70
|
+
console.log(' | |/ /_/ // ____//_____/ /___/ /____/ / ');
|
|
71
|
+
console.log(' |___//___/_/ \____/_____/___/ ');
|
|
72
|
+
console.log();
|
|
73
|
+
console.log(' VIP CLI is your tool for interacting with and managing your VIP applications.');
|
|
74
|
+
console.log();
|
|
75
|
+
console.log(` To get started, we need an access token for your VIP account. We'll open ${tokenURL} in your web browser; follow the instructions there to continue.`);
|
|
76
|
+
console.log();
|
|
77
|
+
await (0, _tracker.trackEvent)('login_command_execute');
|
|
78
|
+
const answer = await (0, _enquirer.prompt)({
|
|
79
|
+
type: 'confirm',
|
|
80
|
+
name: 'continue',
|
|
81
|
+
message: 'Ready?'
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (!answer.continue) {
|
|
85
|
+
await (0, _tracker.trackEvent)('login_command_browser_cancelled');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
(0, _opn.default)(tokenURL, {
|
|
90
|
+
wait: false
|
|
91
|
+
});
|
|
92
|
+
await (0, _tracker.trackEvent)('login_command_browser_opened');
|
|
93
|
+
const {
|
|
94
|
+
token: tokenInput
|
|
95
|
+
} = await (0, _enquirer.prompt)({
|
|
96
|
+
type: 'password',
|
|
97
|
+
name: 'token',
|
|
98
|
+
message: 'Access Token:'
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
token = new _token.default(tokenInput);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.log('The token provided is malformed. Please check the token and try again.');
|
|
105
|
+
|
|
106
|
+
_rollbar.rollbar.error(err);
|
|
107
|
+
|
|
108
|
+
await (0, _tracker.trackEvent)('login_command_token_submit_error', {
|
|
109
|
+
error: err.message
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (token.expired()) {
|
|
115
|
+
console.log('The token provided is expired. Please log in again to refresh the token.');
|
|
116
|
+
await (0, _tracker.trackEvent)('login_command_token_submit_error', {
|
|
117
|
+
error: 'expired'
|
|
118
|
+
});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!token.valid()) {
|
|
123
|
+
console.log('The provided token is not valid. Please log in again to refresh the token.');
|
|
124
|
+
await (0, _tracker.trackEvent)('login_command_token_submit_error', {
|
|
125
|
+
error: 'invalid'
|
|
126
|
+
});
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
_token.default.set(token.raw);
|
|
132
|
+
} catch (err) {
|
|
133
|
+
await (0, _tracker.trackEvent)('login_command_token_submit_error', {
|
|
134
|
+
error: err.message
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
_rollbar.rollbar.error(err);
|
|
138
|
+
|
|
139
|
+
throw err;
|
|
140
|
+
} // De-anonymize user for tracking
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
await (0, _tracker.aliasUser)(token.id);
|
|
144
|
+
await (0, _tracker.trackEvent)('login_command_token_submit_success');
|
|
145
|
+
runCmd();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
rootCmd();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|