@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,620 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.startEnvironment = startEnvironment;
7
+ exports.stopEnvironment = stopEnvironment;
8
+ exports.createEnvironment = createEnvironment;
9
+ exports.updateEnvironment = updateEnvironment;
10
+ exports.destroyEnvironment = destroyEnvironment;
11
+ exports.printAllEnvironmentsInfo = printAllEnvironmentsInfo;
12
+ exports.printEnvironmentInfo = printEnvironmentInfo;
13
+ exports.exec = exec;
14
+ exports.doesEnvironmentExist = doesEnvironmentExist;
15
+ exports.readEnvironmentData = readEnvironmentData;
16
+ exports.getEnvironmentPath = getEnvironmentPath;
17
+ exports.getApplicationInformation = getApplicationInformation;
18
+ exports.resolveImportPath = resolveImportPath;
19
+ exports.importMediaPath = importMediaPath;
20
+ exports.fetchVersionList = fetchVersionList;
21
+ exports.getVersionList = getVersionList;
22
+
23
+ var _debug = _interopRequireDefault(require("debug"));
24
+
25
+ var _xdgBasedir = _interopRequireDefault(require("xdg-basedir"));
26
+
27
+ var _nodeFetch = _interopRequireDefault(require("node-fetch"));
28
+
29
+ var _os = _interopRequireDefault(require("os"));
30
+
31
+ var _fs = _interopRequireDefault(require("fs"));
32
+
33
+ var _ejs = _interopRequireDefault(require("ejs"));
34
+
35
+ var _path = _interopRequireDefault(require("path"));
36
+
37
+ var _chalk = _interopRequireDefault(require("chalk"));
38
+
39
+ var _enquirer = require("enquirer");
40
+
41
+ var _copyDir = _interopRequireDefault(require("copy-dir"));
42
+
43
+ var _devEnvironmentLando = require("./dev-environment-lando");
44
+
45
+ var _searchAndReplace = require("../search-and-replace");
46
+
47
+ var _devEnvironmentCli = require("./dev-environment-cli");
48
+
49
+ var _app = _interopRequireDefault(require("../api/app"));
50
+
51
+ var _devEnvironment = require("../constants/dev-environment");
52
+
53
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
54
+
55
+ /**
56
+ *
57
+ * @format
58
+ */
59
+
60
+ /**
61
+ * External dependencies
62
+ */
63
+
64
+ /**
65
+ * Internal dependencies
66
+ */
67
+ const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
68
+
69
+ const landoFileTemplatePath = _path.default.join(__dirname, '..', '..', '..', 'assets', 'dev-env.lando.template.yml.ejs');
70
+
71
+ const nginxFileTemplatePath = _path.default.join(__dirname, '..', '..', '..', 'assets', 'dev-env.nginx.template.conf.ejs');
72
+
73
+ const landoFileName = '.lando.yml';
74
+ const nginxFileName = 'extra.conf';
75
+ const instanceDataFileName = 'instance_data.json';
76
+ const homeDirPathInsideContainers = '/user';
77
+ const uploadPathString = 'uploads';
78
+ const nginxPathString = 'nginx';
79
+
80
+ async function startEnvironment(slug, options) {
81
+ debug('Will start an environment', slug);
82
+ const instancePath = getEnvironmentPath(slug);
83
+ debug('Instance path for', slug, 'is:', instancePath);
84
+
85
+ const environmentExists = _fs.default.existsSync(instancePath);
86
+
87
+ if (!environmentExists) {
88
+ throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
89
+ }
90
+
91
+ const updated = await updateWordPressImage(slug);
92
+
93
+ if (options.skipRebuild && !updated) {
94
+ await (0, _devEnvironmentLando.landoStart)(instancePath);
95
+ } else {
96
+ await (0, _devEnvironmentLando.landoRebuild)(instancePath);
97
+ }
98
+
99
+ await printEnvironmentInfo(slug);
100
+ }
101
+
102
+ async function stopEnvironment(slug) {
103
+ debug('Will stop an environment', slug);
104
+ const instancePath = getEnvironmentPath(slug);
105
+ debug('Instance path for', slug, 'is:', instancePath);
106
+
107
+ const environmentExists = _fs.default.existsSync(instancePath);
108
+
109
+ if (!environmentExists) {
110
+ throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
111
+ }
112
+
113
+ await (0, _devEnvironmentLando.landoStop)(instancePath);
114
+ }
115
+
116
+ async function createEnvironment(instanceData) {
117
+ const slug = instanceData.siteSlug;
118
+ debug('Will create an environment', slug, 'with instanceData: ', instanceData);
119
+ const instancePath = getEnvironmentPath(slug);
120
+ debug('Instance path for', slug, 'is:', instancePath);
121
+
122
+ const alreadyExists = _fs.default.existsSync(instancePath);
123
+
124
+ if (alreadyExists) {
125
+ throw new Error('Environment already exists.');
126
+ }
127
+
128
+ const preProcessedInstanceData = preProcessInstanceData(instanceData);
129
+ await prepareLandoEnv(preProcessedInstanceData, instancePath);
130
+ }
131
+
132
+ async function updateEnvironment(instanceData) {
133
+ const slug = instanceData.siteSlug;
134
+ debug('Will update an environment', slug, 'with instanceData: ', instanceData);
135
+ const instancePath = getEnvironmentPath(slug);
136
+ debug('Instance path for', slug, 'is:', instancePath);
137
+
138
+ const alreadyExists = _fs.default.existsSync(instancePath);
139
+
140
+ if (!alreadyExists) {
141
+ throw new Error('Environment doesn\'t exist.');
142
+ }
143
+
144
+ const preProcessedInstanceData = preProcessInstanceData(instanceData);
145
+ await prepareLandoEnv(preProcessedInstanceData, instancePath);
146
+ }
147
+
148
+ function preProcessInstanceData(instanceData) {
149
+ const newInstanceData = { ...instanceData
150
+ };
151
+
152
+ if (instanceData.mediaRedirectDomain && !instanceData.mediaRedirectDomain.match(/^http/)) {
153
+ // We need to make sure the redirect is an absolute path
154
+ newInstanceData.mediaRedirectDomain = `https://${instanceData.mediaRedirectDomain}`;
155
+ }
156
+
157
+ newInstanceData.enterpriseSearchEnabled = instanceData.enterpriseSearchEnabled || false;
158
+ newInstanceData.php = instanceData.php || _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS.default;
159
+ return newInstanceData;
160
+ }
161
+
162
+ async function destroyEnvironment(slug, removeFiles) {
163
+ debug('Will destroy an environment', slug);
164
+ const instancePath = getEnvironmentPath(slug);
165
+ debug('Instance path for', slug, 'is:', instancePath);
166
+
167
+ const environmentExists = _fs.default.existsSync(instancePath);
168
+
169
+ if (!environmentExists) {
170
+ throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
171
+ }
172
+
173
+ const landoFilePath = _path.default.join(instancePath, landoFileName);
174
+
175
+ if (_fs.default.existsSync(landoFilePath)) {
176
+ debug('Lando file exists, will lando destroy.');
177
+ await (0, _devEnvironmentLando.landoDestroy)(instancePath);
178
+ } else {
179
+ debug("Lando file doesn't exist, skipping lando destroy.");
180
+ }
181
+
182
+ if (removeFiles) {
183
+ await _fs.default.promises.rm(instancePath, {
184
+ recursive: true
185
+ });
186
+ console.log(`${_chalk.default.green('✓')} Environment files deleted successfully.`);
187
+ }
188
+ }
189
+
190
+ async function printAllEnvironmentsInfo() {
191
+ const allEnvNames = getAllEnvironmentNames();
192
+ debug('Will print info for all environments. Names found: ', allEnvNames);
193
+ console.log('Found ' + _chalk.default.bold(allEnvNames.length) + ' environments' + (allEnvNames.length ? ':' : '.'));
194
+
195
+ for (const envName of allEnvNames) {
196
+ console.log('\n');
197
+ await printEnvironmentInfo(envName);
198
+ }
199
+ }
200
+
201
+ async function printEnvironmentInfo(slug) {
202
+ debug('Will get info for an environment', slug);
203
+ const instancePath = getEnvironmentPath(slug);
204
+ debug('Instance path for', slug, 'is:', instancePath);
205
+
206
+ const environmentExists = _fs.default.existsSync(instancePath);
207
+
208
+ if (!environmentExists) {
209
+ throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
210
+ }
211
+
212
+ const appInfo = await (0, _devEnvironmentLando.landoInfo)(instancePath);
213
+ (0, _devEnvironmentCli.printTable)(appInfo);
214
+ }
215
+
216
+ async function exec(slug, args) {
217
+ debug('Will run a wp command on env', slug, 'with args', args);
218
+ const instancePath = getEnvironmentPath(slug);
219
+ debug('Instance path for', slug, 'is:', instancePath);
220
+
221
+ const environmentExists = _fs.default.existsSync(instancePath);
222
+
223
+ if (!environmentExists) {
224
+ throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
225
+ }
226
+
227
+ const command = args.shift();
228
+ let commandArgs = [...args];
229
+
230
+ if ('add-site' === command) {
231
+ commandArgs = [...args.map(argument => argument.replace('--new-site-', '--'))];
232
+ }
233
+
234
+ await (0, _devEnvironmentLando.landoExec)(instancePath, command, commandArgs);
235
+ }
236
+
237
+ function doesEnvironmentExist(slug) {
238
+ debug('Will check for environment', slug);
239
+ const instancePath = getEnvironmentPath(slug);
240
+ debug('Instance path for', slug, 'is:', instancePath);
241
+ return _fs.default.existsSync(instancePath);
242
+ }
243
+
244
+ function readEnvironmentData(slug) {
245
+ debug('Will try to get instance data for environment', slug);
246
+ const instancePath = getEnvironmentPath(slug);
247
+
248
+ const instanceDataTargetPath = _path.default.join(instancePath, instanceDataFileName);
249
+
250
+ const instanceDataString = _fs.default.readFileSync(instanceDataTargetPath, 'utf8');
251
+
252
+ return JSON.parse(instanceDataString);
253
+ }
254
+
255
+ async function prepareLandoEnv(instanceData, instancePath) {
256
+ const landoFile = await _ejs.default.renderFile(landoFileTemplatePath, instanceData);
257
+ const nginxFile = await _ejs.default.renderFile(nginxFileTemplatePath, instanceData);
258
+ const instanceDataFile = JSON.stringify(instanceData);
259
+
260
+ const landoFileTargetPath = _path.default.join(instancePath, landoFileName);
261
+
262
+ const nginxFolderPath = _path.default.join(instancePath, nginxPathString);
263
+
264
+ const nginxFileTargetPath = _path.default.join(nginxFolderPath, nginxFileName);
265
+
266
+ const instanceDataTargetPath = _path.default.join(instancePath, instanceDataFileName);
267
+
268
+ _fs.default.mkdirSync(instancePath, {
269
+ recursive: true
270
+ });
271
+
272
+ _fs.default.mkdirSync(nginxFolderPath, {
273
+ recursive: true
274
+ });
275
+
276
+ _fs.default.writeFileSync(landoFileTargetPath, landoFile);
277
+
278
+ _fs.default.writeFileSync(nginxFileTargetPath, nginxFile);
279
+
280
+ _fs.default.writeFileSync(instanceDataTargetPath, instanceDataFile);
281
+
282
+ debug(`Lando file created in ${landoFileTargetPath}`);
283
+ debug(`Nginx file created in ${nginxFileTargetPath}`);
284
+ debug(`Instance data file created in ${instanceDataTargetPath}`);
285
+ }
286
+
287
+ function getAllEnvironmentNames() {
288
+ const mainEnvironmentPath = _xdgBasedir.default.data || _os.default.tmpdir();
289
+
290
+ const baseDir = _path.default.join(mainEnvironmentPath, 'vip', 'dev-environment');
291
+
292
+ const doWeHaveAnyEnvironment = _fs.default.existsSync(baseDir);
293
+
294
+ let envNames = [];
295
+
296
+ if (doWeHaveAnyEnvironment) {
297
+ const files = _fs.default.readdirSync(baseDir);
298
+
299
+ envNames = files.filter(file => {
300
+ const fullPath = _path.default.join(baseDir, file);
301
+
302
+ return _fs.default.lstatSync(fullPath).isDirectory();
303
+ });
304
+ }
305
+
306
+ return envNames;
307
+ }
308
+
309
+ function getEnvironmentPath(name) {
310
+ if (!name) {
311
+ throw new Error('Name was not provided');
312
+ }
313
+
314
+ const mainEnvironmentPath = _xdgBasedir.default.data || _os.default.tmpdir();
315
+
316
+ return _path.default.join(mainEnvironmentPath, 'vip', 'dev-environment', name + '');
317
+ }
318
+
319
+ async function getApplicationInformation(appId, envType) {
320
+ // $FlowFixMe: gql template is not supported by flow
321
+ const fieldsQuery = `
322
+ id,
323
+ name,
324
+ repository {
325
+ htmlUrl,
326
+ fullName
327
+ },
328
+ environments {
329
+ id,
330
+ name,
331
+ type,
332
+ branch,
333
+ isMultisite,
334
+ primaryDomain {
335
+ name
336
+ }
337
+ }`;
338
+ const queryResult = await (0, _app.default)(appId, fieldsQuery);
339
+ const appData = {};
340
+
341
+ if (queryResult) {
342
+ var _queryResult$reposito;
343
+
344
+ appData.id = queryResult.id;
345
+ appData.name = queryResult.name;
346
+ appData.repository = (_queryResult$reposito = queryResult.repository) === null || _queryResult$reposito === void 0 ? void 0 : _queryResult$reposito.htmlUrl;
347
+ const environments = queryResult.environments || [];
348
+ let envData;
349
+
350
+ if (envType) {
351
+ envData = environments.find(candidateEnv => candidateEnv.type === envType);
352
+ } else if (1 === environments.length) {
353
+ envData = environments[0];
354
+ } else {
355
+ const choices = environments.map(candidateEnv => candidateEnv.type);
356
+ const {
357
+ env
358
+ } = await (0, _enquirer.prompt)({
359
+ type: 'select',
360
+ name: 'env',
361
+ message: 'Which environment?',
362
+ choices
363
+ });
364
+ envData = environments.find(candidateEnv => candidateEnv.type === env);
365
+ }
366
+
367
+ if (envData) {
368
+ var _envData$primaryDomai;
369
+
370
+ appData.environment = {
371
+ name: envData.name,
372
+ branch: envData.branch,
373
+ type: envData.type,
374
+ isMultisite: envData.isMultisite,
375
+ primaryDomain: ((_envData$primaryDomai = envData.primaryDomain) === null || _envData$primaryDomai === void 0 ? void 0 : _envData$primaryDomai.name) || ''
376
+ };
377
+ }
378
+ }
379
+
380
+ return appData;
381
+ }
382
+
383
+ async function resolveImportPath(slug, fileName, searchReplace, inPlace) {
384
+ let resolvedPath = (0, _devEnvironmentCli.resolvePath)(fileName);
385
+
386
+ if (!_fs.default.existsSync(resolvedPath)) {
387
+ throw new Error('The provided file does not exist or it is not valid (see "--help" for examples)');
388
+ } // Run Search and Replace if the --search-replace flag was provided
389
+
390
+
391
+ if (searchReplace && searchReplace.length) {
392
+ const {
393
+ outputFileName
394
+ } = await (0, _searchAndReplace.searchAndReplace)(resolvedPath, searchReplace, {
395
+ isImport: true,
396
+ output: true,
397
+ inPlace
398
+ });
399
+
400
+ if (typeof outputFileName !== 'string') {
401
+ throw new Error('Unable to determine location of the intermediate search & replace file.');
402
+ }
403
+
404
+ const environmentPath = getEnvironmentPath(slug);
405
+
406
+ const baseName = _path.default.basename(outputFileName);
407
+
408
+ resolvedPath = _path.default.join(environmentPath, baseName);
409
+
410
+ _fs.default.renameSync(outputFileName, resolvedPath);
411
+ }
412
+ /**
413
+ * Docker container does not have acces to the host filesystem.
414
+ * However lando maps os.homedir() to /user in the container. So if we replace the path in the same way
415
+ * in the Docker container will get the file from within the mapped volume under /user.
416
+ */
417
+
418
+
419
+ let inContainerPath = resolvedPath.replace(_os.default.homedir(), homeDirPathInsideContainers);
420
+
421
+ if (_path.default.sep === '\\') {
422
+ // Because the file path generated for windows will have \ instead of / we need to replace that as well so that the path inside the container (unix) still works.
423
+ inContainerPath = inContainerPath.replace(/\\/g, '/');
424
+ }
425
+
426
+ debug(`Import file path ${resolvedPath} will be mapped to ${inContainerPath}`);
427
+ return {
428
+ resolvedPath,
429
+ inContainerPath
430
+ };
431
+ }
432
+
433
+ async function importMediaPath(slug, filePath) {
434
+ const resolvedPath = (0, _devEnvironmentCli.resolvePath)(filePath);
435
+
436
+ if (!_fs.default.existsSync(resolvedPath) || !_fs.default.lstatSync(resolvedPath).isDirectory()) {
437
+ throw new Error('The provided path does not exist or it is not valid (see "--help" for examples)');
438
+ }
439
+
440
+ const files = _fs.default.readdirSync(resolvedPath);
441
+
442
+ if (files.indexOf(uploadPathString) > -1) {
443
+ const confirm = await (0, _enquirer.prompt)({
444
+ type: 'confirm',
445
+ name: 'continue',
446
+ message: 'The provided path contains an uploads folder inside. Do you want to continue?'
447
+ });
448
+
449
+ if (!confirm.continue) {
450
+ return;
451
+ }
452
+ }
453
+
454
+ const environmentPath = getEnvironmentPath(slug);
455
+
456
+ const uploadsPath = _path.default.join(environmentPath, uploadPathString);
457
+
458
+ console.log(`${_chalk.default.yellow('-')} Started copying files`);
459
+
460
+ _copyDir.default.sync(resolvedPath, uploadsPath);
461
+
462
+ console.log(`${_chalk.default.green('✓')} Files successfully copied to ${uploadsPath}.`);
463
+ }
464
+ /**
465
+ * Uses the WordPress versions manifest on github.com
466
+ * Informs the user several things:
467
+ * - If the WordPress image their env uses is no longer available
468
+ * - If there is a newer version of the WordPress version currently used
469
+ * - A choice to use a different image
470
+ *
471
+ * @param {Object=} slug slug
472
+ * @return {boolean} boolean
473
+ */
474
+
475
+
476
+ async function updateWordPressImage(slug) {
477
+ const versions = await getVersionList();
478
+ let message, envData, currentWordPressTag; // Get the current environment configuration
479
+
480
+ try {
481
+ envData = readEnvironmentData(slug);
482
+ currentWordPressTag = envData.wordpress.tag;
483
+ } catch (error) {
484
+ // This can throw an exception if the env is build with older vip version
485
+ if ('ENOENT' === error.code) {
486
+ message = 'Environment was created before update was supported.\n\n';
487
+ message += 'To update environment please destroy it and create a new one.';
488
+ } else {
489
+ message = `An error prevented reading the configuration of: ${slug}\n\n ${error}`;
490
+ }
491
+
492
+ (0, _devEnvironmentCli.handleCLIException)(new Error(message));
493
+ return false;
494
+ } // sort
495
+
496
+
497
+ versions.sort((before, after) => before.tag < after.tag ? 1 : -1); // Newest WordPress Image but that is not trunk
498
+
499
+ const newestWordPressImage = versions.find(({
500
+ tag
501
+ }) => tag !== 'trunk');
502
+ console.log('The most recent WordPress version available is: ' + _chalk.default.green(newestWordPressImage.tag)); // If the currently used version is the most up to date: exit.
503
+
504
+ if (currentWordPressTag === newestWordPressImage.tag) {
505
+ console.log('Environment WordPress version is: ' + _chalk.default.green(currentWordPressTag) + ' ... 😎 nice! ');
506
+ return false;
507
+ } // Determine if there is an image available for the current WordPress version
508
+
509
+
510
+ const match = versions.find(({
511
+ tag
512
+ }) => tag === currentWordPressTag); // If there is no available image for the currently installed version, give user a path to change
513
+
514
+ if (typeof match === 'undefined') {
515
+ console.log(`Installed WordPress: ${currentWordPressTag} has no available container image in repository. `);
516
+ console.log('You must select a new WordPress image to continue... ');
517
+ } else {
518
+ console.log('Environment WordPress version is: ' + _chalk.default.yellow(`${match.tag} (${match.ref})`));
519
+
520
+ if (envData.wordpress.doNotUpgrade || false) {
521
+ return false;
522
+ }
523
+ } // Prompt the user to select a new WordPress Version
524
+
525
+
526
+ const confirm = await (0, _enquirer.prompt)({
527
+ type: 'select',
528
+ name: 'upgrade',
529
+ message: 'Would You like to change the WordPress version? ',
530
+ choices: ['yes', 'no', "no (don't ask anymore)"]
531
+ }); // If the user takes the new WP version path
532
+
533
+ if (confirm.upgrade === 'yes') {
534
+ console.log('Upgrading from: ' + _chalk.default.yellow(currentWordPressTag) + ' to:'); // Select a new image
535
+
536
+ const choice = await (0, _devEnvironmentCli.promptForComponent)('wordpress');
537
+ const version = versions.find(({
538
+ tag
539
+ }) => tag.trim() === choice.tag.trim()); // Write new data and stage for rebuild
540
+
541
+ envData.wordpress.tag = version.tag;
542
+ envData.wordpress.ref = version.ref;
543
+ await updateEnvironment(envData);
544
+ return true;
545
+ }
546
+
547
+ if (confirm.upgrade === "no (don't ask anymore)") {
548
+ envData.wordpress.doNotUpgrade = true;
549
+ console.log("We won't ask about upgrading this environment anymore.");
550
+ console.log('To manually upgrade please run:' + `${_chalk.default.yellow(`vip dev-env update --slug=${slug}`)}`);
551
+ await updateEnvironment(envData);
552
+ }
553
+
554
+ return false;
555
+ }
556
+ /**
557
+ * Makes a web call to raw.githubusercontent.com
558
+ */
559
+
560
+
561
+ async function fetchVersionList() {
562
+ const url = `https://${_devEnvironment.DEV_ENVIRONMENT_RAW_GITHUB_HOST}${_devEnvironment.DEV_ENVIRONMENT_WORDPRESS_VERSIONS_URI}`;
563
+ return (0, _nodeFetch.default)(url).then(res => res.text());
564
+ }
565
+ /**
566
+ * Encapsulates the logic for determining if a file is expired by an arbitrary TTL
567
+ * @param {string} cacheFile uri of cache file
568
+ * @param {number} ttl time to live in seconds
569
+ * @returns {boolean} version list expired true/false
570
+ */
571
+
572
+
573
+ function isVersionListExpired(cacheFile, ttl) {
574
+ const stats = _fs.default.statSync(cacheFile);
575
+
576
+ const expire = new Date(stats.mtime);
577
+ expire.setSeconds(expire.getSeconds() + ttl);
578
+ return +new Date() > expire;
579
+ }
580
+ /**
581
+ * Uses a cache file to keep the version list in tow until it is ultimately outdated
582
+ */
583
+
584
+
585
+ async function getVersionList() {
586
+ let res;
587
+
588
+ const mainEnvironmentPath = _xdgBasedir.default.data || _os.default.tmpdir();
589
+
590
+ const cacheFile = _path.default.join(mainEnvironmentPath, 'vip', _devEnvironment.DEV_ENVIRONMENT_WORDPRESS_CACHE_KEY); // Handle from cache
591
+
592
+
593
+ try {
594
+ // If the cache doesn't exist, create it
595
+ if (!_fs.default.existsSync(cacheFile)) {
596
+ res = await fetchVersionList();
597
+
598
+ _fs.default.writeFileSync(cacheFile, res);
599
+ } // If the cache is expired, refresh it
600
+
601
+
602
+ if (isVersionListExpired(cacheFile, _devEnvironment.DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL)) {
603
+ res = await fetchVersionList();
604
+
605
+ _fs.default.writeFileSync(cacheFile, res);
606
+ }
607
+ } catch (err) {
608
+ // Soft error handling here, since it's still possible to use a previously cached file.
609
+ console.log(_chalk.default.yellow('fetchWordPressVersionList failed to retrieve an updated version list'));
610
+ debug(err);
611
+ } // Try to parse the cached file if it exists.
612
+
613
+
614
+ try {
615
+ return JSON.parse(_fs.default.readFileSync(cacheFile));
616
+ } catch (err) {
617
+ debug(err);
618
+ return [];
619
+ }
620
+ }