@automattic/vip 2.9.5 → 2.11.2

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 (115) hide show
  1. package/CONTRIBUTING.md +2 -11
  2. package/README.md +26 -0
  3. package/dist/bin/vip-dev-env-create.js +9 -1
  4. package/dist/bin/vip-dev-env-destroy.js +7 -7
  5. package/dist/bin/vip-dev-env-exec.js +7 -1
  6. package/dist/bin/vip-dev-env-import-media.js +7 -1
  7. package/dist/bin/vip-dev-env-import-sql.js +7 -1
  8. package/dist/bin/vip-dev-env-info.js +10 -1
  9. package/dist/bin/vip-dev-env-list.js +10 -1
  10. package/dist/bin/vip-dev-env-start.js +14 -3
  11. package/dist/bin/vip-dev-env-stop.js +7 -1
  12. package/dist/bin/vip-dev-env-update.js +8 -2
  13. package/dist/bin/vip-import-sql.js +7 -1
  14. package/dist/lib/analytics/clients/pendo.js +92 -0
  15. package/dist/lib/analytics/index.js +8 -3
  16. package/dist/lib/dev-environment/dev-environment-cli.js +56 -1
  17. package/dist/lib/dev-environment/dev-environment-core.js +4 -2
  18. package/dist/lib/dev-environment/dev-environment-lando.js +35 -3
  19. package/dist/lib/tracker.js +15 -7
  20. package/npm-shrinkwrap.json +1 -1
  21. package/package/dist/bin/vip-app-list.js +73 -0
  22. package/package/dist/bin/vip-app.js +76 -0
  23. package/package/dist/bin/vip-config-envvar-delete.js +97 -0
  24. package/package/dist/bin/vip-config-envvar-get-all.js +94 -0
  25. package/package/dist/bin/vip-config-envvar-get.js +79 -0
  26. package/package/dist/bin/vip-config-envvar-list.js +91 -0
  27. package/package/dist/bin/vip-config-envvar-set.js +123 -0
  28. package/package/dist/bin/vip-config-envvar.js +23 -0
  29. package/package/dist/bin/vip-config.js +20 -0
  30. package/package/dist/bin/vip-dev-env-create.js +105 -0
  31. package/package/dist/bin/vip-dev-env-destroy.js +56 -0
  32. package/package/dist/bin/vip-dev-env-exec.js +67 -0
  33. package/package/dist/bin/vip-dev-env-import-media.js +51 -0
  34. package/package/dist/bin/vip-dev-env-import-sql.js +83 -0
  35. package/package/dist/bin/vip-dev-env-import.js +32 -0
  36. package/package/dist/bin/vip-dev-env-info.js +61 -0
  37. package/package/dist/bin/vip-dev-env-list.js +46 -0
  38. package/package/dist/bin/vip-dev-env-start.js +77 -0
  39. package/package/dist/bin/vip-dev-env-stop.js +52 -0
  40. package/package/dist/bin/vip-dev-env-update.js +89 -0
  41. package/package/dist/bin/vip-dev-env.js +23 -0
  42. package/package/dist/bin/vip-import-media-abort.js +132 -0
  43. package/package/dist/bin/vip-import-media-status.js +84 -0
  44. package/package/dist/bin/vip-import-media.js +168 -0
  45. package/package/dist/bin/vip-import-sql-status.js +83 -0
  46. package/package/dist/bin/vip-import-sql.js +580 -0
  47. package/package/dist/bin/vip-import-validate-files.js +191 -0
  48. package/package/dist/bin/vip-import-validate-sql.js +34 -0
  49. package/package/dist/bin/vip-import.js +20 -0
  50. package/package/dist/bin/vip-logs.js +232 -0
  51. package/package/dist/bin/vip-search-replace.js +71 -0
  52. package/package/dist/bin/vip-sync.js +191 -0
  53. package/package/dist/bin/vip-whoami.js +67 -0
  54. package/package/dist/bin/vip-wp.js +555 -0
  55. package/package/dist/bin/vip.js +149 -0
  56. package/package/dist/lib/analytics/clients/client.js +1 -0
  57. package/package/dist/lib/analytics/clients/pendo.js +92 -0
  58. package/package/dist/lib/analytics/clients/stub.js +19 -0
  59. package/package/dist/lib/analytics/clients/tracks.js +128 -0
  60. package/package/dist/lib/analytics/index.js +45 -0
  61. package/package/dist/lib/api/app.js +70 -0
  62. package/package/dist/lib/api/feature-flags.js +39 -0
  63. package/package/dist/lib/api/user.js +58 -0
  64. package/package/dist/lib/api.js +136 -0
  65. package/package/dist/lib/app-logs/app-logs.js +70 -0
  66. package/package/dist/lib/cli/apiConfig.js +90 -0
  67. package/package/dist/lib/cli/command.js +606 -0
  68. package/package/dist/lib/cli/envAlias.js +60 -0
  69. package/package/dist/lib/cli/exit.js +33 -0
  70. package/package/dist/lib/cli/format.js +213 -0
  71. package/package/dist/lib/cli/pager.js +52 -0
  72. package/package/dist/lib/cli/progress.js +208 -0
  73. package/package/dist/lib/cli/prompt.js +37 -0
  74. package/package/dist/lib/cli/repo.js +77 -0
  75. package/package/dist/lib/client-file-uploader.js +602 -0
  76. package/package/dist/lib/constants/dev-environment.js +42 -0
  77. package/package/dist/lib/constants/file-size.js +14 -0
  78. package/package/dist/lib/dev-environment/dev-environment-cli.js +508 -0
  79. package/package/dist/lib/dev-environment/dev-environment-core.js +620 -0
  80. package/package/dist/lib/dev-environment/dev-environment-lando.js +330 -0
  81. package/package/dist/lib/dev-environment/types.js +1 -0
  82. package/package/dist/lib/env.js +36 -0
  83. package/package/dist/lib/envvar/api-delete.js +56 -0
  84. package/package/dist/lib/envvar/api-get-all.js +59 -0
  85. package/package/dist/lib/envvar/api-get.js +24 -0
  86. package/package/dist/lib/envvar/api-list.js +60 -0
  87. package/package/dist/lib/envvar/api-set.js +58 -0
  88. package/package/dist/lib/envvar/api.js +104 -0
  89. package/package/dist/lib/envvar/input.js +55 -0
  90. package/package/dist/lib/envvar/logging.js +33 -0
  91. package/package/dist/lib/envvar/read-file.js +43 -0
  92. package/package/dist/lib/http/socks-proxy-agent.js +25 -0
  93. package/package/dist/lib/keychain/browser.js +35 -0
  94. package/package/dist/lib/keychain/insecure.js +63 -0
  95. package/package/dist/lib/keychain/keychain.js +1 -0
  96. package/package/dist/lib/keychain/secure.js +36 -0
  97. package/package/dist/lib/keychain.js +36 -0
  98. package/package/dist/lib/media-import/media-file-import.js +34 -0
  99. package/package/dist/lib/media-import/progress.js +86 -0
  100. package/package/dist/lib/media-import/status.js +335 -0
  101. package/package/dist/lib/rollbar.js +35 -0
  102. package/package/dist/lib/search-and-replace.js +203 -0
  103. package/package/dist/lib/site-import/db-file-import.js +46 -0
  104. package/package/dist/lib/site-import/status.js +444 -0
  105. package/package/dist/lib/token.js +132 -0
  106. package/package/dist/lib/tracker.js +96 -0
  107. package/package/dist/lib/validations/is-multi-site-sql-dump.js +59 -0
  108. package/package/dist/lib/validations/is-multi-site.js +99 -0
  109. package/package/dist/lib/validations/line-by-line.js +92 -0
  110. package/package/dist/lib/validations/site-type.js +66 -0
  111. package/package/dist/lib/validations/sql.js +371 -0
  112. package/package/dist/lib/vip-import-validate-files.js +548 -0
  113. package/package/vip.iml +11 -0
  114. package/package.json +1 -1
  115. package/vip.iml +11 -0
@@ -0,0 +1,444 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.importSqlCheckStatus = importSqlCheckStatus;
7
+ exports.default = void 0;
8
+
9
+ var _chalk = _interopRequireDefault(require("chalk"));
10
+
11
+ var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
12
+
13
+ var _debug = _interopRequireDefault(require("debug"));
14
+
15
+ var _api = _interopRequireDefault(require("../api"));
16
+
17
+ var _dbFileImport = require("./db-file-import");
18
+
19
+ var _progress = require("../cli/progress");
20
+
21
+ var exit = _interopRequireWildcard(require("../cli/exit"));
22
+
23
+ var _format = require("../cli/format");
24
+
25
+ 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); }
26
+
27
+ 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; }
28
+
29
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
30
+
31
+ /**
32
+ *
33
+ * @format
34
+ */
35
+
36
+ /**
37
+ * External dependencies
38
+ */
39
+
40
+ /**
41
+ * Internal dependencies
42
+ */
43
+ const debug = (0, _debug.default)('vip:lib/site-import/status');
44
+ const IMPORT_SQL_PROGRESS_POLL_INTERVAL = 5000;
45
+ const IMPORT_SQL_PROGRESS_QUERY = (0, _graphqlTag.default)`
46
+ query App($appId: Int, $envId: Int) {
47
+ app(id: $appId) {
48
+ environments(id: $envId) {
49
+ id
50
+ isK8sResident
51
+ launched
52
+ jobs(types: "sql_import") {
53
+ id
54
+ type
55
+ completedAt
56
+ createdAt
57
+ progress {
58
+ status
59
+ steps {
60
+ id
61
+ name
62
+ status
63
+ }
64
+ }
65
+ }
66
+ importStatus {
67
+ dbOperationInProgress
68
+ importInProgress
69
+ progress {
70
+ started_at
71
+ steps {
72
+ name
73
+ started_at
74
+ finished_at
75
+ result
76
+ output
77
+ }
78
+ finished_at
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ `;
85
+
86
+ async function getStatus(api, appId, envId) {
87
+ const response = await api.query({
88
+ query: IMPORT_SQL_PROGRESS_QUERY,
89
+ variables: {
90
+ appId,
91
+ envId
92
+ },
93
+ fetchPolicy: 'network-only'
94
+ });
95
+ const {
96
+ data: {
97
+ app: {
98
+ environments
99
+ }
100
+ }
101
+ } = response;
102
+
103
+ if (!(environments !== null && environments !== void 0 && environments.length)) {
104
+ throw new Error('Unable to determine import status from environment');
105
+ }
106
+
107
+ const [environment] = environments;
108
+ const {
109
+ importStatus,
110
+ jobs,
111
+ launched
112
+ } = environment;
113
+
114
+ if (!environment.isK8sResident && !(jobs !== null && jobs !== void 0 && jobs.length)) {
115
+ return {};
116
+ }
117
+
118
+ const [importJob] = jobs;
119
+ return {
120
+ importStatus,
121
+ importJob,
122
+ launched
123
+ };
124
+ }
125
+
126
+ function getErrorMessage(importFailed, launched = false) {
127
+ debug({
128
+ importFailed
129
+ });
130
+ const rollbackMessage = launched ? '' : `Your site is ${_chalk.default.blue('automatically being rolled back')} to the last backup prior to your import job.
131
+ `;
132
+ let message = importFailed.error;
133
+
134
+ if (importFailed.inImportProgress) {
135
+ switch (importFailed.stepName) {
136
+ case 'import_preflights':
137
+ message += `
138
+ This error occurred prior to the mysql batch script processing of your SQL file.
139
+
140
+ Your site content was not altered.
141
+
142
+ If this error persists, please contact support.
143
+ `;
144
+ break;
145
+
146
+ case 'importing_db':
147
+ message += `
148
+ This error occurred during the mysql batch script processing of your SQL file.
149
+
150
+ ${rollbackMessage}`;
151
+
152
+ if (importFailed.commandOutput) {
153
+ const commandOutput = [].concat(importFailed.commandOutput).join(';');
154
+ message += `
155
+ Please inspect your input file and make the appropriate corrections before trying again.
156
+ The server said:
157
+ > ${_chalk.default.red(commandOutput)}
158
+ `;
159
+ } else {
160
+ message += 'Please contact support and include this message along with your sql file.';
161
+ }
162
+
163
+ break;
164
+
165
+ case 'validating_db':
166
+ message += `\nThis error occurred during the post-import validation of the imported data.
167
+
168
+ ${rollbackMessage}
169
+ `;
170
+
171
+ if (importFailed.commandOutput) {
172
+ const commandOutput = [].concat(importFailed.commandOutput).join(';');
173
+ message += `
174
+ Please inspect your input file and make the appropriate corrections before trying again.
175
+ The server said:
176
+ > ${_chalk.default.red(commandOutput)}
177
+ `;
178
+ } else {
179
+ message += 'Please contact support and include this message along with your sql file.';
180
+ }
181
+
182
+ break;
183
+
184
+ default:
185
+ }
186
+ }
187
+
188
+ return message;
189
+ }
190
+
191
+ async function importSqlCheckStatus({
192
+ app,
193
+ env,
194
+ progressTracker
195
+ }) {
196
+ // Stop printing so we can pass our callback
197
+ progressTracker.stopPrinting(); // NO `console.log` in this function (until results are final)! It will break the progress printing.
198
+
199
+ const api = await (0, _api.default)();
200
+
201
+ if (!(0, _dbFileImport.currentUserCanImportForApp)(app)) {
202
+ throw new Error('The currently authenticated account does not have permission to view SQL import status.');
203
+ }
204
+
205
+ let createdAt;
206
+ let completedAt;
207
+ let overallStatus = 'Checking...';
208
+
209
+ const setProgressTrackerSuffix = () => {
210
+ const sprite = (0, _format.getGlyphForStatus)(overallStatus, progressTracker.runningSprite);
211
+ const formattedCreatedAt = createdAt ? `${new Date(createdAt).toLocaleString()} (${createdAt})` : 'TBD';
212
+ const formattedCompletedAt = createdAt && completedAt ? `${new Date(completedAt).toLocaleString()} (${completedAt})` : 'TBD';
213
+ const exitPrompt = '(Press ^C to hide progress. The import will continue in the background.)';
214
+ let statusMessage;
215
+
216
+ switch (overallStatus) {
217
+ case 'success':
218
+ statusMessage = `Success ${sprite} imported data should be visible on your site ${env.primaryDomain.name}.`;
219
+ break;
220
+
221
+ case 'running':
222
+ if (progressTracker.allStepsSucceeded()) {
223
+ statusMessage = `Finishing up... ${sprite} `;
224
+ break;
225
+ }
226
+
227
+ // Intentionally no break to get default case:
228
+
229
+ default:
230
+ statusMessage = `${(0, _format.capitalize)(overallStatus)} ${sprite}`;
231
+ }
232
+
233
+ const maybeExitPrompt = `${overallStatus === 'running' ? exitPrompt : ''}`;
234
+ const jobCreateCompleteTimestamps = `
235
+ SQL Import Started: ${formattedCreatedAt}
236
+ SQL Import Completed: ${formattedCompletedAt}`;
237
+ const maybeTimestamps = ['running', 'success', 'failed'].includes(overallStatus) ? jobCreateCompleteTimestamps : '';
238
+ const suffix = `
239
+ =============================================================
240
+ Status: ${statusMessage}
241
+ Site: ${app.name} (${(0, _format.formatEnvironment)(env.type)})${maybeTimestamps}
242
+ =============================================================
243
+ ${maybeExitPrompt}
244
+ `;
245
+ progressTracker.suffix = suffix;
246
+ };
247
+
248
+ const setSuffixAndPrint = () => {
249
+ setProgressTrackerSuffix();
250
+ progressTracker.print();
251
+ };
252
+
253
+ progressTracker.startPrinting(setSuffixAndPrint);
254
+
255
+ const getResults = () => new Promise((resolve, reject) => {
256
+ const checkStatus = async () => {
257
+ var _importJob$progress$s, _importJob$progress, _importJob$progress$s2, _importJob$progress2;
258
+
259
+ let status;
260
+
261
+ try {
262
+ status = await getStatus(api, app.id, env.id);
263
+ } catch (error) {
264
+ return reject({
265
+ error
266
+ });
267
+ }
268
+
269
+ const {
270
+ importStatus,
271
+ launched
272
+ } = status;
273
+ let {
274
+ importJob
275
+ } = status;
276
+ let jobStatus,
277
+ jobSteps = [];
278
+
279
+ if (env.isK8sResident) {
280
+ // in the future the API may provide this in k8s jobs so account for that.
281
+ // Until then we need to create the importJob from the status object.
282
+ if (!importJob) {
283
+ var _importStatus$progres, _importStatus$progres2;
284
+
285
+ importJob = {};
286
+ const statusSteps = importStatus === null || importStatus === void 0 ? void 0 : (_importStatus$progres = importStatus.progress) === null || _importStatus$progres === void 0 ? void 0 : _importStatus$progres.steps; // if the progress meta isn't filled out yet, wait until it is.
287
+
288
+ if (!statusSteps) {
289
+ return setTimeout(checkStatus, IMPORT_SQL_PROGRESS_POLL_INTERVAL);
290
+ }
291
+
292
+ jobSteps = statusSteps.map(step => {
293
+ return {
294
+ id: step.name,
295
+ name: (0, _format.capitalize)(step.name.replace(/_/g, ' ')),
296
+ status: step.result
297
+ };
298
+ });
299
+
300
+ if (statusSteps.some(({
301
+ result
302
+ }) => result === 'failed') && !statusSteps.find(({
303
+ name,
304
+ result
305
+ }) => name === 'restore_db' && !result)) {
306
+ jobStatus = 'error';
307
+ } else if (statusSteps.every(({
308
+ result
309
+ }) => result === 'success')) {
310
+ jobStatus = 'success';
311
+ importJob.completedAt = new Date(Math.max(...statusSteps.map(step => step.finished_at), 0) * 1000).toUTCString();
312
+ }
313
+
314
+ if (importStatus !== null && importStatus !== void 0 && (_importStatus$progres2 = importStatus.progress) !== null && _importStatus$progres2 !== void 0 && _importStatus$progres2.started_at) {
315
+ importJob.createdAt = new Date(importStatus.progress.started_at * 1000).toUTCString();
316
+ }
317
+
318
+ importJob.progress = {
319
+ status: jobStatus,
320
+ steps: jobSteps
321
+ };
322
+ }
323
+ } else if (!importJob) {
324
+ return resolve('No import job found');
325
+ }
326
+
327
+ jobStatus = (_importJob$progress$s = (_importJob$progress = importJob.progress) === null || _importJob$progress === void 0 ? void 0 : _importJob$progress.status) !== null && _importJob$progress$s !== void 0 ? _importJob$progress$s : 'unknown';
328
+ jobSteps = (_importJob$progress$s2 = (_importJob$progress2 = importJob.progress) === null || _importJob$progress2 === void 0 ? void 0 : _importJob$progress2.steps) !== null && _importJob$progress$s2 !== void 0 ? _importJob$progress$s2 : [];
329
+ createdAt = importJob.createdAt;
330
+ completedAt = importJob.completedAt;
331
+ const {
332
+ dbOperationInProgress,
333
+ importInProgress,
334
+ progress: importStepProgress
335
+ } = importStatus;
336
+ debug({
337
+ jobStatus,
338
+ completedAt,
339
+ createdAt,
340
+ dbOperationInProgress,
341
+ importInProgress,
342
+ importStepProgress
343
+ });
344
+ let jobCreationTime;
345
+
346
+ try {
347
+ jobCreationTime = new Date(createdAt).getTime();
348
+ } catch (err) {
349
+ debug('Unable to parse createdAt to a Date');
350
+ }
351
+
352
+ let failedImportStep;
353
+
354
+ if (jobCreationTime && (importStepProgress === null || importStepProgress === void 0 ? void 0 : importStepProgress.started_at) * 1000 >= jobCreationTime) {
355
+ // The contents of the `import_progress` meta are pertinent to the most recent import job
356
+ failedImportStep = importStepProgress.steps.find(step => (step === null || step === void 0 ? void 0 : step.result) === 'failed' && 1000 * (step === null || step === void 0 ? void 0 : step.started_at) > new Date(createdAt).getTime());
357
+ }
358
+
359
+ if (!jobSteps.length) {
360
+ return reject({
361
+ error: 'Could not enumerate the import job steps',
362
+ launched
363
+ });
364
+ }
365
+
366
+ if (failedImportStep) {
367
+ // The server marks the step as a success as per the host action, demote it to 'failed'
368
+ const _jobSteps = [...jobSteps];
369
+
370
+ const failedJobStepIndex = _jobSteps.findIndex(({
371
+ id
372
+ }) => id === 'import');
373
+
374
+ _jobSteps[failedJobStepIndex] = { ..._jobSteps[failedJobStepIndex],
375
+ status: 'failed'
376
+ };
377
+ progressTracker.setStepsFromServer(_jobSteps);
378
+ overallStatus = 'failed';
379
+ setSuffixAndPrint();
380
+ return reject({
381
+ inImportProgress: true,
382
+ commandOutput: failedImportStep.output,
383
+ error: 'Import step failed',
384
+ stepName: failedImportStep.name,
385
+ errorText: failedImportStep.error,
386
+ launched
387
+ });
388
+ }
389
+
390
+ progressTracker.setStepsFromServer(jobSteps);
391
+ setSuffixAndPrint();
392
+
393
+ if (jobStatus === 'error') {
394
+ return reject({
395
+ error: 'Import job failed',
396
+ steps: jobSteps,
397
+ launched
398
+ });
399
+ }
400
+
401
+ if (jobStatus !== 'running' && completedAt) {
402
+ return resolve(importJob);
403
+ }
404
+
405
+ overallStatus = 'running';
406
+ setTimeout(checkStatus, IMPORT_SQL_PROGRESS_POLL_INTERVAL);
407
+ }; // Kick off the check
408
+
409
+
410
+ checkStatus();
411
+ });
412
+
413
+ try {
414
+ const results = await getResults();
415
+
416
+ if (typeof results === 'string') {
417
+ overallStatus = results;
418
+ } else {
419
+ var _results$progress;
420
+
421
+ overallStatus = (results === null || results === void 0 ? void 0 : (_results$progress = results.progress) === null || _results$progress === void 0 ? void 0 : _results$progress.status) || 'unknown'; // This shouldn't be 'unknown'...what should we do here?
422
+ }
423
+
424
+ progressTracker.stopPrinting();
425
+ setProgressTrackerSuffix(); // Print one final time
426
+
427
+ progressTracker.print({
428
+ clearAfter: true
429
+ }); // This type of result is not an importing error. e.g. no import job was found
430
+
431
+ process.exit(0);
432
+ } catch (importFailed) {
433
+ progressTracker.stopPrinting();
434
+ progressTracker.print({
435
+ clearAfter: true
436
+ });
437
+ exit.withError(getErrorMessage(importFailed, importFailed.launched));
438
+ }
439
+ }
440
+
441
+ var _default = {
442
+ importSqlCheckStatus
443
+ };
444
+ exports.default = _default;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.SERVICE = void 0;
7
+
8
+ var _jwtDecode = _interopRequireDefault(require("jwt-decode"));
9
+
10
+ var _uuid2 = require("uuid");
11
+
12
+ var _keychain = _interopRequireDefault(require("./keychain"));
13
+
14
+ var _api = require("./api");
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
18
+ /**
19
+ * External dependencies
20
+ */
21
+
22
+ /**
23
+ * Internal dependencies
24
+ */
25
+ // Config
26
+ const SERVICE = 'vip-go-cli';
27
+ exports.SERVICE = SERVICE;
28
+
29
+ class Token {
30
+ constructor(token) {
31
+ if (!token) {
32
+ return;
33
+ }
34
+
35
+ token = token.trim();
36
+
37
+ if (!token.length) {
38
+ return;
39
+ }
40
+
41
+ const decodedToken = (0, _jwtDecode.default)(token);
42
+ this.raw = token;
43
+
44
+ if (decodedToken.id) {
45
+ this.id = decodedToken.id;
46
+ }
47
+
48
+ if (decodedToken.iat) {
49
+ this.iat = new Date(decodedToken.iat * 1000);
50
+ }
51
+
52
+ if (decodedToken.exp) {
53
+ this.exp = new Date(decodedToken.exp * 1000);
54
+ }
55
+ }
56
+
57
+ valid() {
58
+ if (!this.id) {
59
+ return false;
60
+ }
61
+
62
+ if (!this.iat) {
63
+ return false;
64
+ }
65
+
66
+ const now = new Date();
67
+
68
+ if (!this.exp) {
69
+ return now > this.iat;
70
+ }
71
+
72
+ return now > this.iat && now < this.exp;
73
+ }
74
+
75
+ expired() {
76
+ if (!this.exp) {
77
+ return false;
78
+ }
79
+
80
+ const now = new Date();
81
+ return now > this.exp;
82
+ }
83
+
84
+ static async uuid() {
85
+ const service = Token.getServiceName('-uuid');
86
+
87
+ let _uuid = await _keychain.default.getPassword(service);
88
+
89
+ if (!_uuid) {
90
+ _uuid = (0, _uuid2.v4)();
91
+ await _keychain.default.setPassword(service, _uuid);
92
+ }
93
+
94
+ return _uuid;
95
+ }
96
+
97
+ static async setUuid(_uuid) {
98
+ const service = Token.getServiceName('-uuid');
99
+ await _keychain.default.setPassword(service, _uuid);
100
+ }
101
+
102
+ static async set(token) {
103
+ const service = Token.getServiceName();
104
+ return _keychain.default.setPassword(service, token);
105
+ }
106
+
107
+ static async get() {
108
+ const service = Token.getServiceName();
109
+ const token = await _keychain.default.getPassword(service);
110
+ return new Token(token);
111
+ }
112
+
113
+ static async purge() {
114
+ const service = Token.getServiceName();
115
+ return _keychain.default.deletePassword(service);
116
+ }
117
+
118
+ static getServiceName(modifier = '') {
119
+ let service = SERVICE;
120
+
121
+ if (_api.PRODUCTION_API_HOST !== _api.API_HOST) {
122
+ const sanitized = _api.API_HOST.replace(/[^a-z0-9]/gi, '-');
123
+
124
+ service = `${SERVICE}:${sanitized}`;
125
+ }
126
+
127
+ return `${service}${modifier}`;
128
+ }
129
+
130
+ }
131
+
132
+ exports.default = Token;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.trackEvent = trackEvent;
7
+ exports.aliasUser = aliasUser;
8
+ exports.trackEventWithEnv = trackEventWithEnv;
9
+
10
+ var _index = _interopRequireDefault(require("./analytics/index"));
11
+
12
+ var _tracks = _interopRequireDefault(require("./analytics/clients/tracks"));
13
+
14
+ var _pendo = _interopRequireDefault(require("./analytics/clients/pendo"));
15
+
16
+ var _token = _interopRequireDefault(require("./token"));
17
+
18
+ var _config = _interopRequireDefault(require("../../config/config.json"));
19
+
20
+ var _env = _interopRequireDefault(require("./env"));
21
+
22
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
+
24
+ /**
25
+ * External dependencies
26
+ */
27
+ const debug = require('debug')('@automattic/vip:analytics');
28
+ /**
29
+ * Internal dependencies
30
+ */
31
+
32
+
33
+ let analytics = null;
34
+
35
+ async function init() {
36
+ const uuid = await _token.default.uuid();
37
+ const clients = [];
38
+ const tracksUserType = _config.default.tracksUserType;
39
+ const tracksEventPrefix = _config.default.tracksEventPrefix;
40
+
41
+ if (tracksUserType && tracksEventPrefix) {
42
+ clients.push(new _tracks.default(uuid, tracksUserType, tracksEventPrefix, _env.default));
43
+ clients.push(new _pendo.default({
44
+ env: _env.default,
45
+ eventPrefix: tracksEventPrefix,
46
+ userId: uuid
47
+ }));
48
+ }
49
+
50
+ analytics = new _index.default({
51
+ clients
52
+ });
53
+ return analytics;
54
+ }
55
+
56
+ async function getInstance() {
57
+ if (analytics) {
58
+ return analytics;
59
+ }
60
+
61
+ analytics = await init();
62
+ return analytics;
63
+ }
64
+
65
+ async function trackEvent(...args) {
66
+ try {
67
+ await _token.default.uuid();
68
+ const client = await getInstance();
69
+ return await client.trackEvent(...args);
70
+ } catch (err) {
71
+ debug('trackEvent() failed', err);
72
+ }
73
+ }
74
+
75
+ async function aliasUser(vipUserId) {
76
+ try {
77
+ if (vipUserId) {
78
+ await trackEvent('_alias_user', {
79
+ ui: vipUserId,
80
+ _ut: _config.default.tracksUserType,
81
+ anonid: _token.default.uuid()
82
+ });
83
+
84
+ _token.default.setUuid(vipUserId);
85
+ }
86
+ } catch (err) {
87
+ debug('aliasUser() failed', err);
88
+ }
89
+ }
90
+
91
+ async function trackEventWithEnv(appId, envId, eventName, eventProps = {}) {
92
+ return trackEvent(eventName, { ...eventProps,
93
+ app_id: appId,
94
+ env_id: envId
95
+ });
96
+ }