@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.
Files changed (123) hide show
  1. package/CONTRIBUTING.md +7 -2
  2. package/README.md +27 -0
  3. package/config/{config.json → config.publish.json} +0 -0
  4. package/dist/bin/vip-dev-env-create.js +1 -0
  5. package/dist/bin/vip-dev-env-destroy.js +1 -0
  6. package/dist/bin/vip-dev-env-exec.js +1 -0
  7. package/dist/bin/vip-dev-env-import-media.js +1 -0
  8. package/dist/bin/vip-dev-env-import-sql.js +1 -0
  9. package/dist/bin/vip-dev-env-info.js +1 -0
  10. package/dist/bin/vip-dev-env-list.js +1 -0
  11. package/dist/bin/vip-dev-env-start.js +4 -3
  12. package/dist/bin/vip-dev-env-stop.js +7 -1
  13. package/dist/bin/vip-dev-env-update.js +1 -0
  14. package/dist/bin/vip-import-sql.js +7 -1
  15. package/dist/bin/vip-wp.js +2 -2
  16. package/dist/bin/vip.js +1 -1
  17. package/dist/lib/analytics/clients/pendo.js +92 -0
  18. package/dist/lib/analytics/clients/stub.js +1 -1
  19. package/dist/lib/analytics/clients/tracks.js +0 -5
  20. package/dist/lib/analytics/index.js +21 -4
  21. package/dist/lib/api.js +2 -2
  22. package/dist/lib/cli/config.js +30 -0
  23. package/dist/lib/dev-environment/dev-environment-cli.js +25 -2
  24. package/dist/lib/dev-environment/dev-environment-lando.js +17 -0
  25. package/dist/lib/http/proxy-agent.js +94 -0
  26. package/dist/lib/rollbar.js +1 -1
  27. package/dist/lib/tracker.js +13 -4
  28. package/npm-shrinkwrap.json +319 -133
  29. package/package/dist/bin/vip-app-list.js +73 -0
  30. package/package/dist/bin/vip-app.js +76 -0
  31. package/package/dist/bin/vip-config-envvar-delete.js +97 -0
  32. package/package/dist/bin/vip-config-envvar-get-all.js +94 -0
  33. package/package/dist/bin/vip-config-envvar-get.js +79 -0
  34. package/package/dist/bin/vip-config-envvar-list.js +91 -0
  35. package/package/dist/bin/vip-config-envvar-set.js +123 -0
  36. package/package/dist/bin/vip-config-envvar.js +23 -0
  37. package/package/dist/bin/vip-config.js +20 -0
  38. package/package/dist/bin/vip-dev-env-create.js +105 -0
  39. package/package/dist/bin/vip-dev-env-destroy.js +56 -0
  40. package/package/dist/bin/vip-dev-env-exec.js +67 -0
  41. package/package/dist/bin/vip-dev-env-import-media.js +51 -0
  42. package/package/dist/bin/vip-dev-env-import-sql.js +83 -0
  43. package/package/dist/bin/vip-dev-env-import.js +32 -0
  44. package/package/dist/bin/vip-dev-env-info.js +61 -0
  45. package/package/dist/bin/vip-dev-env-list.js +46 -0
  46. package/package/dist/bin/vip-dev-env-start.js +77 -0
  47. package/package/dist/bin/vip-dev-env-stop.js +52 -0
  48. package/package/dist/bin/vip-dev-env-update.js +89 -0
  49. package/package/dist/bin/vip-dev-env.js +23 -0
  50. package/package/dist/bin/vip-import-media-abort.js +132 -0
  51. package/package/dist/bin/vip-import-media-status.js +84 -0
  52. package/package/dist/bin/vip-import-media.js +168 -0
  53. package/package/dist/bin/vip-import-sql-status.js +83 -0
  54. package/package/dist/bin/vip-import-sql.js +580 -0
  55. package/package/dist/bin/vip-import-validate-files.js +191 -0
  56. package/package/dist/bin/vip-import-validate-sql.js +34 -0
  57. package/package/dist/bin/vip-import.js +20 -0
  58. package/package/dist/bin/vip-logs.js +232 -0
  59. package/package/dist/bin/vip-search-replace.js +71 -0
  60. package/package/dist/bin/vip-sync.js +191 -0
  61. package/package/dist/bin/vip-whoami.js +67 -0
  62. package/package/dist/bin/vip-wp.js +555 -0
  63. package/package/dist/bin/vip.js +149 -0
  64. package/package/dist/lib/analytics/clients/client.js +1 -0
  65. package/package/dist/lib/analytics/clients/pendo.js +92 -0
  66. package/package/dist/lib/analytics/clients/stub.js +19 -0
  67. package/package/dist/lib/analytics/clients/tracks.js +128 -0
  68. package/package/dist/lib/analytics/index.js +45 -0
  69. package/package/dist/lib/api/app.js +70 -0
  70. package/package/dist/lib/api/feature-flags.js +39 -0
  71. package/package/dist/lib/api/user.js +58 -0
  72. package/package/dist/lib/api.js +136 -0
  73. package/package/dist/lib/app-logs/app-logs.js +70 -0
  74. package/package/dist/lib/cli/apiConfig.js +90 -0
  75. package/package/dist/lib/cli/command.js +606 -0
  76. package/package/dist/lib/cli/envAlias.js +60 -0
  77. package/package/dist/lib/cli/exit.js +33 -0
  78. package/package/dist/lib/cli/format.js +213 -0
  79. package/package/dist/lib/cli/pager.js +52 -0
  80. package/package/dist/lib/cli/progress.js +208 -0
  81. package/package/dist/lib/cli/prompt.js +37 -0
  82. package/package/dist/lib/cli/repo.js +77 -0
  83. package/package/dist/lib/client-file-uploader.js +602 -0
  84. package/package/dist/lib/constants/dev-environment.js +42 -0
  85. package/package/dist/lib/constants/file-size.js +14 -0
  86. package/package/dist/lib/dev-environment/dev-environment-cli.js +508 -0
  87. package/package/dist/lib/dev-environment/dev-environment-core.js +620 -0
  88. package/package/dist/lib/dev-environment/dev-environment-lando.js +330 -0
  89. package/package/dist/lib/dev-environment/types.js +1 -0
  90. package/package/dist/lib/env.js +36 -0
  91. package/package/dist/lib/envvar/api-delete.js +56 -0
  92. package/package/dist/lib/envvar/api-get-all.js +59 -0
  93. package/package/dist/lib/envvar/api-get.js +24 -0
  94. package/package/dist/lib/envvar/api-list.js +60 -0
  95. package/package/dist/lib/envvar/api-set.js +58 -0
  96. package/package/dist/lib/envvar/api.js +104 -0
  97. package/package/dist/lib/envvar/input.js +55 -0
  98. package/package/dist/lib/envvar/logging.js +33 -0
  99. package/package/dist/lib/envvar/read-file.js +43 -0
  100. package/{dist → package/dist}/lib/http/socks-proxy-agent.js +0 -0
  101. package/package/dist/lib/keychain/browser.js +35 -0
  102. package/package/dist/lib/keychain/insecure.js +63 -0
  103. package/package/dist/lib/keychain/keychain.js +1 -0
  104. package/package/dist/lib/keychain/secure.js +36 -0
  105. package/package/dist/lib/keychain.js +36 -0
  106. package/package/dist/lib/media-import/media-file-import.js +34 -0
  107. package/package/dist/lib/media-import/progress.js +86 -0
  108. package/package/dist/lib/media-import/status.js +335 -0
  109. package/package/dist/lib/rollbar.js +35 -0
  110. package/package/dist/lib/search-and-replace.js +203 -0
  111. package/package/dist/lib/site-import/db-file-import.js +46 -0
  112. package/package/dist/lib/site-import/status.js +444 -0
  113. package/package/dist/lib/token.js +132 -0
  114. package/package/dist/lib/tracker.js +96 -0
  115. package/package/dist/lib/validations/is-multi-site-sql-dump.js +59 -0
  116. package/package/dist/lib/validations/is-multi-site.js +99 -0
  117. package/package/dist/lib/validations/line-by-line.js +92 -0
  118. package/package/dist/lib/validations/site-type.js +66 -0
  119. package/package/dist/lib/validations/sql.js +371 -0
  120. package/package/dist/lib/vip-import-validate-files.js +548 -0
  121. package/package/vip.iml +11 -0
  122. package/package.json +12 -9
  123. 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";