@automattic/vip 2.21.0 → 2.23.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 (111) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/assets/dev-env.lando.template.yml.ejs +1 -1
  3. package/automattic-vip-2.23.0.tgz +0 -0
  4. package/dist/bin/vip-app-list.js +0 -12
  5. package/dist/bin/vip-app.js +6 -13
  6. package/dist/bin/vip-cache-purge-url.js +4 -19
  7. package/dist/bin/vip-cache.js +0 -2
  8. package/dist/bin/vip-config-envvar-delete.js +4 -19
  9. package/dist/bin/vip-config-envvar-get-all.js +6 -19
  10. package/dist/bin/vip-config-envvar-get.js +4 -15
  11. package/dist/bin/vip-config-envvar-list.js +8 -20
  12. package/dist/bin/vip-config-envvar-set.js +4 -23
  13. package/dist/bin/vip-config-envvar.js +0 -2
  14. package/dist/bin/vip-config-software-get.js +0 -17
  15. package/dist/bin/vip-config-software-update.js +6 -22
  16. package/dist/bin/vip-config-software.js +0 -2
  17. package/dist/bin/vip-config.js +0 -2
  18. package/dist/bin/vip-dev-env-create.js +0 -18
  19. package/dist/bin/vip-dev-env-destroy.js +0 -9
  20. package/dist/bin/vip-dev-env-exec.js +0 -12
  21. package/dist/bin/vip-dev-env-import-media.js +0 -7
  22. package/dist/bin/vip-dev-env-import-sql.js +2 -17
  23. package/dist/bin/vip-dev-env-import.js +0 -3
  24. package/dist/bin/vip-dev-env-info.js +0 -10
  25. package/dist/bin/vip-dev-env-list.js +0 -7
  26. package/dist/bin/vip-dev-env-start.js +4 -14
  27. package/dist/bin/vip-dev-env-stop.js +0 -9
  28. package/dist/bin/vip-dev-env-update.js +0 -11
  29. package/dist/bin/vip-dev-env.js +0 -2
  30. package/dist/bin/vip-import-media-abort.js +0 -18
  31. package/dist/bin/vip-import-media-status.js +0 -12
  32. package/dist/bin/vip-import-media.js +6 -23
  33. package/dist/bin/vip-import-sql-status.js +0 -12
  34. package/dist/bin/vip-import-sql.js +40 -103
  35. package/dist/bin/vip-import-validate-files.js +21 -42
  36. package/dist/bin/vip-import-validate-sql.js +0 -8
  37. package/dist/bin/vip-import.js +0 -3
  38. package/dist/bin/vip-logs.js +20 -50
  39. package/dist/bin/vip-search-replace.js +8 -14
  40. package/dist/bin/vip-sync.js +2 -25
  41. package/dist/bin/vip-validate-preflight.js +427 -0
  42. package/dist/bin/vip-validate.js +19 -0
  43. package/dist/bin/vip-whoami.js +2 -14
  44. package/dist/bin/vip-wp.js +39 -89
  45. package/dist/bin/vip.js +5 -35
  46. package/dist/lib/analytics/clients/pendo.js +9 -18
  47. package/dist/lib/analytics/clients/stub.js +1 -3
  48. package/dist/lib/analytics/clients/tracks.js +11 -20
  49. package/dist/lib/analytics/index.js +4 -11
  50. package/dist/lib/api/app.js +1 -11
  51. package/dist/lib/api/cache-purge.js +4 -7
  52. package/dist/lib/api/feature-flags.js +1 -4
  53. package/dist/lib/api/http.js +9 -15
  54. package/dist/lib/api/user.js +1 -7
  55. package/dist/lib/api.js +17 -19
  56. package/dist/lib/app-logs/app-logs.js +2 -9
  57. package/dist/lib/app.js +2 -5
  58. package/dist/lib/cli/apiConfig.js +4 -19
  59. package/dist/lib/cli/command.js +43 -133
  60. package/dist/lib/cli/config.js +1 -5
  61. package/dist/lib/cli/envAlias.js +14 -15
  62. package/dist/lib/cli/exit.js +4 -6
  63. package/dist/lib/cli/format.js +8 -50
  64. package/dist/lib/cli/progress.js +13 -42
  65. package/dist/lib/cli/prompt.js +1 -5
  66. package/dist/lib/cli/repo.js +7 -20
  67. package/dist/lib/client-file-uploader.js +44 -97
  68. package/dist/lib/config/software.js +2 -52
  69. package/dist/lib/constants/dev-environment.js +1 -2
  70. package/dist/lib/constants/file-size.js +1 -1
  71. package/dist/lib/constants/vipgo.js +1 -1
  72. package/dist/lib/dev-environment/dev-environment-cli.js +68 -155
  73. package/dist/lib/dev-environment/dev-environment-core.js +73 -194
  74. package/dist/lib/dev-environment/dev-environment-lando.js +16 -71
  75. package/dist/lib/env.js +1 -4
  76. package/dist/lib/envvar/api-delete.js +1 -4
  77. package/dist/lib/envvar/api-get-all.js +1 -4
  78. package/dist/lib/envvar/api-get.js +1 -2
  79. package/dist/lib/envvar/api-list.js +3 -4
  80. package/dist/lib/envvar/api-set.js +1 -4
  81. package/dist/lib/envvar/api.js +5 -16
  82. package/dist/lib/envvar/input.js +1 -8
  83. package/dist/lib/envvar/logging.js +2 -6
  84. package/dist/lib/envvar/read-file.js +1 -3
  85. package/dist/lib/http/proxy-agent.js +17 -22
  86. package/dist/lib/keychain/browser.js +1 -4
  87. package/dist/lib/keychain/insecure.js +1 -10
  88. package/dist/lib/keychain/secure.js +1 -8
  89. package/dist/lib/keychain.js +4 -8
  90. package/dist/lib/logout.js +0 -6
  91. package/dist/lib/media-import/media-file-import.js +3 -7
  92. package/dist/lib/media-import/progress.js +6 -17
  93. package/dist/lib/media-import/status.js +14 -65
  94. package/dist/lib/read-file.js +1 -6
  95. package/dist/lib/rollbar.js +1 -7
  96. package/dist/lib/search-and-replace.js +9 -41
  97. package/dist/lib/site-import/db-file-import.js +3 -9
  98. package/dist/lib/site-import/status.js +17 -74
  99. package/dist/lib/token.js +1 -33
  100. package/dist/lib/tracker.js +4 -20
  101. package/dist/lib/user-error.js +0 -2
  102. package/dist/lib/validations/is-multi-site-sql-dump.js +4 -12
  103. package/dist/lib/validations/is-multi-site.js +5 -21
  104. package/dist/lib/validations/is-multisite-domain-mapped.js +5 -31
  105. package/dist/lib/validations/line-by-line.js +4 -16
  106. package/dist/lib/validations/site-type.js +10 -19
  107. package/dist/lib/validations/sql.js +11 -76
  108. package/dist/lib/validations/utils.js +1 -6
  109. package/dist/lib/vip-import-validate-files.js +82 -109
  110. package/npm-shrinkwrap.json +2407 -1800
  111. package/package.json +18 -15
@@ -3,52 +3,38 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.handleCLIException = handleCLIException;
6
+ exports.addDevEnvConfigurationOptions = addDevEnvConfigurationOptions;
7
+ exports.getEnvTrackingInfo = getEnvTrackingInfo;
7
8
  exports.getEnvironmentName = getEnvironmentName;
8
9
  exports.getEnvironmentStartCommand = getEnvironmentStartCommand;
10
+ exports.getOptionsFromAppInfo = getOptionsFromAppInfo;
11
+ exports.getTagChoices = getTagChoices;
12
+ exports.handleCLIException = handleCLIException;
9
13
  exports.printTable = printTable;
14
+ exports.processBooleanOption = processBooleanOption;
10
15
  exports.processComponentOptionInput = processComponentOptionInput;
11
- exports.getOptionsFromAppInfo = getOptionsFromAppInfo;
12
16
  exports.promptForArguments = promptForArguments;
13
- exports.resolvePath = resolvePath;
14
- exports.promptForText = promptForText;
15
17
  exports.promptForBoolean = promptForBoolean;
16
- exports.promptForPhpVersion = promptForPhpVersion;
17
18
  exports.promptForComponent = promptForComponent;
18
- exports.processBooleanOption = processBooleanOption;
19
- exports.addDevEnvConfigurationOptions = addDevEnvConfigurationOptions;
20
- exports.getTagChoices = getTagChoices;
21
- exports.getEnvTrackingInfo = getEnvTrackingInfo;
19
+ exports.promptForPhpVersion = promptForPhpVersion;
20
+ exports.promptForText = promptForText;
21
+ exports.resolvePath = resolvePath;
22
22
  exports.validateDependencies = void 0;
23
-
24
23
  var _chalk = _interopRequireDefault(require("chalk"));
25
-
26
24
  var _formatters = _interopRequireDefault(require("lando/lib/formatters"));
27
-
28
25
  var _enquirer = require("enquirer");
29
-
30
26
  var _debug = _interopRequireDefault(require("debug"));
31
-
32
27
  var _fs = _interopRequireDefault(require("fs"));
33
-
34
28
  var _path = _interopRequireDefault(require("path"));
35
-
36
29
  var _os = _interopRequireDefault(require("os"));
37
-
30
+ var _dns = _interopRequireDefault(require("dns"));
38
31
  var _progress = require("../cli/progress");
39
-
40
32
  var _tracker = require("../tracker");
41
-
42
33
  var _devEnvironment = require("../constants/dev-environment");
43
-
44
34
  var _devEnvironmentCore = require("./dev-environment-core");
45
-
46
35
  var _devEnvironmentLando = require("./dev-environment-lando");
47
-
48
36
  var _userError = _interopRequireDefault(require("../user-error"));
49
-
50
37
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
51
-
52
38
  /**
53
39
  *
54
40
  * @format
@@ -61,29 +47,30 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
61
47
  /**
62
48
  * Internal dependencies
63
49
  */
50
+
64
51
  const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
65
52
  const DEFAULT_SLUG = 'vip-local';
66
53
 
54
+ // Forward declaratrion to avoid no-use-before-define
55
+
67
56
  async function handleCLIException(exception, trackKey, trackBaseInfo = {}) {
68
57
  const errorPrefix = _chalk.default.red('Error:');
69
-
70
58
  if (exception instanceof _userError.default) {
71
59
  // User errors are handled in global error handler
72
60
  throw exception;
73
61
  } else if (_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND === exception.message) {
74
62
  const createCommand = _chalk.default.bold(_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND + ' create');
75
-
76
63
  const message = `Environment doesn't exist.\n\n\nTo create a new environment run:\n\n${createCommand}\n`;
77
64
  console.log(errorPrefix, message);
78
65
  } else {
79
- let message = exception.message; // if the message has already ERROR prefix we should drop it as we are adding our own cool red Error-prefix
80
-
66
+ let message = exception.message;
67
+ // if the message has already ERROR prefix we should drop it as we are adding our own cool red Error-prefix
81
68
  message = message.replace('ERROR: ', '');
82
69
  console.log(errorPrefix, message);
83
-
84
70
  if (trackKey) {
85
71
  try {
86
- const errorTrackingInfo = { ...trackBaseInfo,
72
+ const errorTrackingInfo = {
73
+ ...trackBaseInfo,
87
74
  failure: message,
88
75
  stack: exception.stack
89
76
  };
@@ -92,41 +79,30 @@ async function handleCLIException(exception, trackKey, trackBaseInfo = {}) {
92
79
  console.log(errorPrefix, `Failed to record track event ${trackKey}`, trackException.message);
93
80
  }
94
81
  }
95
-
96
82
  if (!process.env.DEBUG) {
97
83
  console.log(`\nPlease re-run the command with "--debug ${_chalk.default.bold('@automattic/vip:bin:dev-environment')}" appended to it and provide the stack trace on the support ticket.`);
98
84
  console.log(_chalk.default.bold('\nExample:\n'));
99
85
  console.log('vip dev-env <command> <arguments> --debug @automattic/vip:bin:dev-environment \n');
100
86
  }
101
-
102
87
  debug(exception);
103
88
  }
104
89
  }
105
-
106
- const verifyDNSResolution = slug => {
107
- const dns = require('dns');
108
-
90
+ const verifyDNSResolution = async slug => {
109
91
  const expectedIP = '127.0.0.1';
110
92
  const testDomain = `${slug}.vipdev.lndo.site`;
111
93
  const advice = `Please add following line to hosts file on your system:\n${expectedIP} ${testDomain}`;
112
94
  debug(`Verifying DNS resolution for ${testDomain}`);
113
- return new Promise((resolve, reject) => {
114
- dns.lookup(testDomain, (error, address) => {
115
- debug(`Got DNS response ${address}`);
116
-
117
- if (error) {
118
- reject(new _userError.default(`DNS resolution for ${testDomain} failed. ${advice}`));
119
- }
120
-
121
- if (address !== expectedIP) {
122
- reject(new _userError.default(`DNS resolution for ${testDomain} returned unexpected IP ${address}. Expected value is ${expectedIP}. ${advice}`));
123
- }
124
-
125
- resolve();
126
- });
127
- });
95
+ let address;
96
+ try {
97
+ address = await _dns.default.promises.lookup(testDomain, 4);
98
+ debug(`Got DNS response ${address.address}`);
99
+ } catch (error) {
100
+ throw new _userError.default(`DNS resolution for ${testDomain} failed. ${advice}`);
101
+ }
102
+ if (address.address !== expectedIP) {
103
+ throw new _userError.default(`DNS resolution for ${testDomain} returned unexpected IP ${address.address}. Expected value is ${expectedIP}. ${advice}`);
104
+ }
128
105
  };
129
-
130
106
  const VALIDATION_STEPS = [{
131
107
  id: 'docker',
132
108
  name: 'Check for docker installation'
@@ -140,29 +116,24 @@ const VALIDATION_STEPS = [{
140
116
  id: 'dns',
141
117
  name: 'Check DNS resolution'
142
118
  }];
143
-
144
119
  const validateDependencies = async slug => {
145
120
  const progressTracker = new _progress.ProgressTracker(VALIDATION_STEPS);
146
121
  console.log('Running validation steps...');
147
122
  progressTracker.startPrinting();
148
123
  progressTracker.stepRunning('docker');
149
-
150
124
  try {
151
125
  await (0, _devEnvironmentLando.validateDockerInstalled)();
152
126
  } catch (exception) {
153
127
  throw new _userError.default(exception.message);
154
128
  }
155
-
156
129
  progressTracker.stepSuccess('docker');
157
130
  progressTracker.stepSuccess('compose');
158
131
  progressTracker.print();
159
-
160
132
  try {
161
133
  await (0, _devEnvironmentLando.validateDockerAccess)();
162
134
  } catch (exception) {
163
135
  throw new _userError.default(exception.message);
164
136
  }
165
-
166
137
  progressTracker.stepSuccess('access');
167
138
  progressTracker.print();
168
139
  await verifyDNSResolution(slug);
@@ -170,67 +141,52 @@ const validateDependencies = async slug => {
170
141
  progressTracker.print();
171
142
  progressTracker.stopPrinting();
172
143
  };
173
-
174
144
  exports.validateDependencies = validateDependencies;
175
-
176
145
  function getEnvironmentName(options) {
177
146
  if (options.slug) {
178
147
  return options.slug;
179
148
  }
180
-
181
149
  if (options.app) {
182
150
  const envSuffix = options.env ? `-${options.env}` : '';
183
151
  const appName = options.app + envSuffix;
184
-
185
152
  if (options.allowAppEnv) {
186
153
  return appName;
187
154
  }
188
-
189
155
  const message = `This command does not support @app.env notation. Use '--slug=${appName}' to target the local environment.`;
190
156
  throw new _userError.default(message);
191
157
  }
192
-
193
158
  return DEFAULT_SLUG;
194
159
  }
195
-
196
160
  function getEnvironmentStartCommand(slug) {
197
161
  if (!slug || slug === DEFAULT_SLUG) {
198
162
  return `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start`;
199
163
  }
200
-
201
164
  return `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start --slug ${slug}`;
202
165
  }
203
-
204
166
  function printTable(data) {
205
167
  const formattedData = _formatters.default.formatData(data, {
206
168
  format: 'table'
207
169
  }, {
208
170
  border: false
209
171
  });
210
-
211
172
  console.log(formattedData);
212
173
  }
213
-
214
174
  function processComponentOptionInput(passedParam, allowLocal) {
215
175
  // cast to string
216
176
  const param = passedParam + '';
217
-
218
177
  if (allowLocal && param.includes('/')) {
219
178
  return {
220
179
  mode: 'local',
221
180
  dir: param
222
181
  };
223
182
  }
224
-
225
183
  return {
226
184
  mode: 'image',
227
185
  tag: param
228
186
  };
229
187
  }
230
-
231
188
  function getOptionsFromAppInfo(appInfo) {
232
189
  var _appInfo$environment, _appInfo$environment2, _appInfo$environment3, _appInfo$environment4, _appInfo$environment5;
233
-
234
190
  return {
235
191
  title: ((_appInfo$environment = appInfo.environment) === null || _appInfo$environment === void 0 ? void 0 : _appInfo$environment.name) || appInfo.name || '',
236
192
  multisite: !!(appInfo !== null && appInfo !== void 0 && (_appInfo$environment2 = appInfo.environment) !== null && _appInfo$environment2 !== void 0 && _appInfo$environment2.isMultisite),
@@ -239,34 +195,30 @@ function getOptionsFromAppInfo(appInfo) {
239
195
  wordpress: ((_appInfo$environment5 = appInfo.environment) === null || _appInfo$environment5 === void 0 ? void 0 : _appInfo$environment5.wordpress) || ''
240
196
  };
241
197
  }
198
+
242
199
  /**
243
200
  * Prompt for arguments
244
201
  * @param {InstanceOptions} preselectedOptions - options to be used without prompt
245
202
  * @param {InstanceOptions} defaultOptions - options to be used as default values for prompt
246
- * @param {boolean} supressPrompts - supress prompts and use default values where needed
203
+ * @param {boolean} suppressPrompts - supress prompts and use default values where needed
247
204
  * @returns {any} instance data
248
205
  */
249
-
250
-
251
- async function promptForArguments(preselectedOptions, defaultOptions, supressPrompts = false) {
206
+ async function promptForArguments(preselectedOptions, defaultOptions, suppressPrompts = false) {
252
207
  debug('Provided preselected', preselectedOptions, 'and default', defaultOptions);
253
-
254
- if (supressPrompts) {
255
- preselectedOptions = { ...defaultOptions,
208
+ if (suppressPrompts) {
209
+ preselectedOptions = {
210
+ ...defaultOptions,
256
211
  ...preselectedOptions
257
212
  };
258
213
  } else {
259
214
  console.log(_devEnvironment.DEV_ENVIRONMENT_PROMPT_INTRO);
260
215
  }
261
-
262
216
  let multisiteText = 'Multisite';
263
217
  let multisiteDefault = _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.multisite;
264
-
265
218
  if (defaultOptions.title) {
266
219
  multisiteText += ` (${defaultOptions.title} ${defaultOptions.multisite ? 'IS' : 'is NOT'} multisite)`;
267
220
  multisiteDefault = defaultOptions.multisite;
268
221
  }
269
-
270
222
  const instanceData = {
271
223
  wpTitle: preselectedOptions.title || (await promptForText('WordPress site title', defaultOptions.title || _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.title)),
272
224
  multisite: 'multisite' in preselectedOptions ? preselectedOptions.multisite : await promptForBoolean(multisiteText, !!multisiteDefault),
@@ -275,7 +227,8 @@ async function promptForArguments(preselectedOptions, defaultOptions, supressPro
275
227
  mariadb: preselectedOptions.mariadb || defaultOptions.mariadb || _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.mariadbVersion,
276
228
  mediaRedirectDomain: preselectedOptions.mediaRedirectDomain || '',
277
229
  wordpress: {
278
- mode: 'image'
230
+ mode: 'image',
231
+ tag: ''
279
232
  },
280
233
  muPlugins: {
281
234
  mode: 'image'
@@ -293,46 +246,35 @@ async function promptForArguments(preselectedOptions, defaultOptions, supressPro
293
246
  xdebug: 'XDebug',
294
247
  phpmyadmin: 'phpMyAdmin'
295
248
  };
296
-
297
249
  if (!instanceData.mediaRedirectDomain && defaultOptions.mediaRedirectDomain) {
298
250
  const mediaRedirectPromptText = `Would you like to redirect to ${defaultOptions.mediaRedirectDomain} for missing media files?`;
299
251
  const setMediaRedirectDomain = await promptForBoolean(mediaRedirectPromptText, true);
300
-
301
252
  if (setMediaRedirectDomain) {
302
253
  var _defaultOptions$media;
303
-
304
254
  instanceData.mediaRedirectDomain = (_defaultOptions$media = defaultOptions.mediaRedirectDomain) !== null && _defaultOptions$media !== void 0 ? _defaultOptions$media : '';
305
255
  }
306
256
  }
307
-
308
257
  for (const component of _devEnvironment.DEV_ENVIRONMENT_COMPONENTS) {
309
258
  var _preselectedOptions$c, _defaultOptions$compo;
310
-
311
259
  const option = ((_preselectedOptions$c = preselectedOptions[component]) !== null && _preselectedOptions$c !== void 0 ? _preselectedOptions$c : '').toString();
312
260
  const defaultValue = ((_defaultOptions$compo = defaultOptions[component]) !== null && _defaultOptions$compo !== void 0 ? _defaultOptions$compo : '').toString();
313
261
  const result = await processComponent(component, option, defaultValue);
314
-
315
262
  if (null === result) {
316
263
  throw new Error('processComponent() returned null');
317
264
  }
318
-
319
265
  instanceData[component] = result;
320
266
  }
321
-
322
267
  debug(`Processing elasticsearch with preselected "${preselectedOptions.elasticsearch}"`);
323
-
324
268
  if ('elasticsearch' in preselectedOptions) {
325
269
  instanceData.elasticsearch = !!preselectedOptions.elasticsearch;
326
270
  } else {
327
- instanceData.elasticsearch = await promptForBoolean('Enable Elasticsearch (needed by Enterprise Search)?', defaultOptions.elasticsearch);
271
+ instanceData.elasticsearch = await promptForBoolean('Enable Elasticsearch (needed by Enterprise Search)?', !!defaultOptions.elasticsearch);
328
272
  }
329
-
330
273
  if (instanceData.elasticsearch) {
331
274
  instanceData.statsd = preselectedOptions.statsd || defaultOptions.statsd || false;
332
275
  } else {
333
276
  instanceData.statsd = false;
334
277
  }
335
-
336
278
  for (const service of ['phpmyadmin', 'xdebug']) {
337
279
  if (service in instanceData) {
338
280
  if (service in preselectedOptions) {
@@ -342,33 +284,27 @@ async function promptForArguments(preselectedOptions, defaultOptions, supressPro
342
284
  }
343
285
  }
344
286
  }
345
-
346
287
  debug('Instance data after prompts', instanceData);
347
288
  return instanceData;
348
289
  }
349
-
350
290
  async function processComponent(component, preselectedValue, defaultValue) {
351
291
  debug(`processing a component '${component}', with preselected/deafault - ${preselectedValue}/${defaultValue}`);
352
292
  let result = null;
353
293
  const allowLocal = component !== 'wordpress';
354
294
  const defaultObject = defaultValue ? processComponentOptionInput(defaultValue, allowLocal) : null;
355
-
356
295
  if (preselectedValue) {
357
296
  result = processComponentOptionInput(preselectedValue, allowLocal);
358
297
  } else {
359
298
  result = await promptForComponent(component, allowLocal, defaultObject);
360
299
  }
361
-
362
300
  while ('local' === ((_result = result) === null || _result === void 0 ? void 0 : _result.mode)) {
363
301
  var _result;
364
-
365
302
  const resolvedPath = resolvePath(result.dir || '');
366
303
  result.dir = resolvedPath;
367
304
  const {
368
305
  result: isPathValid,
369
306
  message
370
307
  } = validateLocalPath(component, resolvedPath);
371
-
372
308
  if (isPathValid) {
373
309
  break;
374
310
  } else {
@@ -376,10 +312,8 @@ async function processComponent(component, preselectedValue, defaultValue) {
376
312
  result = await promptForComponent(component, allowLocal, defaultObject);
377
313
  }
378
314
  }
379
-
380
315
  return result;
381
316
  }
382
-
383
317
  function validateLocalPath(component, providedPath) {
384
318
  if (!isNonEmptyDirectory(providedPath)) {
385
319
  const message = `Provided path "${providedPath}" does not point to a valid or existing directory.`;
@@ -388,19 +322,15 @@ function validateLocalPath(component, providedPath) {
388
322
  message
389
323
  };
390
324
  }
391
-
392
325
  if (component === 'appCode') {
393
326
  const files = ['languages', 'plugins', 'themes', 'private', 'images', 'client-mu-plugins', 'vip-config'];
394
327
  const missingFiles = [];
395
-
396
328
  for (const file of files) {
397
329
  const filePath = _path.default.resolve(providedPath, file);
398
-
399
330
  if (!_fs.default.existsSync(filePath)) {
400
331
  missingFiles.push(file);
401
332
  }
402
333
  }
403
-
404
334
  if (missingFiles.length > 0) {
405
335
  // eslint-disable-next-line max-len
406
336
  const message = `Provided path "${providedPath}" is missing following files/folders: ${missingFiles.join(', ')}. Learn more: https://docs.wpvip.com/technical-references/vip-codebase/#1-wordpress`;
@@ -410,36 +340,29 @@ function validateLocalPath(component, providedPath) {
410
340
  };
411
341
  }
412
342
  }
413
-
414
343
  return {
415
344
  result: true,
416
345
  message: ''
417
346
  };
418
347
  }
419
-
420
348
  function isNonEmptyDirectory(directoryPath) {
421
349
  const isDirectory = directoryPath && _fs.default.existsSync(directoryPath) && _fs.default.lstatSync(directoryPath).isDirectory();
422
-
423
350
  const isEmpty = isDirectory ? _fs.default.readdirSync(directoryPath).length === 0 : true;
424
351
  return !isEmpty && isDirectory;
425
352
  }
426
-
427
353
  function resolvePath(input) {
428
354
  // Resolve does not do ~ reliably
429
- const resolvedPath = input.replace(/^~/, _os.default.homedir()); // And resolve to handle relative paths
430
-
355
+ const resolvedPath = input.replace(/^~/, _os.default.homedir());
356
+ // And resolve to handle relative paths
431
357
  return _path.default.resolve(resolvedPath);
432
358
  }
433
-
434
359
  async function promptForText(message, initial) {
435
360
  const nonEmptyValidator = value => {
436
361
  if ((value || '').trim()) {
437
362
  return true;
438
363
  }
439
-
440
364
  return 'value needs to be provided';
441
365
  };
442
-
443
366
  const result = await (0, _enquirer.prompt)({
444
367
  type: 'input',
445
368
  name: 'input',
@@ -449,7 +372,6 @@ async function promptForText(message, initial) {
449
372
  });
450
373
  return ((result === null || result === void 0 ? void 0 : result.input) || '').trim();
451
374
  }
452
-
453
375
  async function promptForBoolean(message, initial) {
454
376
  const confirm = new _enquirer.Confirm({
455
377
  message,
@@ -457,27 +379,22 @@ async function promptForBoolean(message, initial) {
457
379
  });
458
380
  return confirm.run();
459
381
  }
460
-
461
382
  function resolvePhpVersion(version) {
462
383
  debug(`Resolving PHP version '${version}'`);
463
-
464
384
  if (typeof version === 'string' && version.startsWith('image:')) {
465
385
  return version;
466
386
  }
467
-
468
387
  const versions = Object.keys(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS);
469
- const images = Object.values(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS); // eslint-disable-next-line eqeqeq -- use loose comparison because commander resolves '8.0' to '8'
388
+ const images = Object.values(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS);
470
389
 
390
+ // eslint-disable-next-line eqeqeq -- use loose comparison because commander resolves '8.0' to '8'
471
391
  const index = versions.findIndex(value => value == version);
472
-
473
392
  if (index === -1) {
474
393
  const image = images.find(value => value === version);
475
394
  return image !== null && image !== void 0 ? image : images[0];
476
395
  }
477
-
478
396
  return images[index];
479
397
  }
480
-
481
398
  async function promptForPhpVersion(initialValue) {
482
399
  debug(`Prompting for PHP version, preselected option is ${initialValue}`);
483
400
  const choices = Object.keys(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS);
@@ -491,7 +408,6 @@ async function promptForPhpVersion(initialValue) {
491
408
  const answer = await select.run();
492
409
  return resolvePhpVersion(answer);
493
410
  }
494
-
495
411
  const componentDisplayNames = {
496
412
  wordpress: 'WordPress',
497
413
  muPlugins: 'vip-go-mu-plugins',
@@ -502,36 +418,31 @@ const componentDemoyNames = {
502
418
  appCode: 'vip-go-skeleton'
503
419
  };
504
420
 
421
+ // eslint-disable-next-line no-redeclare
505
422
  async function promptForComponent(component, allowLocal, defaultObject) {
506
423
  debug(`Prompting for ${component} with default:`, defaultObject);
507
424
  const componentDisplayName = componentDisplayNames[component] || component;
508
425
  const componentDemoName = componentDemoyNames[component] || component;
509
426
  const modChoices = [];
510
-
511
427
  if (allowLocal) {
512
428
  modChoices.push({
513
429
  message: `Custom - Path to a locally cloned ${componentDisplayName} directory`,
514
430
  value: 'local'
515
431
  });
516
432
  }
517
-
518
433
  modChoices.push({
519
434
  message: `Demo - Automatically fetched ${componentDemoName}`,
520
435
  value: 'image'
521
436
  });
522
437
  let initialMode = 'image';
523
-
524
438
  if ('appCode' === component) {
525
439
  initialMode = 'local';
526
440
  }
527
-
528
441
  if (defaultObject !== null && defaultObject !== void 0 && defaultObject.mode) {
529
442
  initialMode = defaultObject.mode;
530
443
  }
531
-
532
444
  let modeResult = initialMode;
533
445
  const selectMode = modChoices.length > 1;
534
-
535
446
  if (selectMode) {
536
447
  const initialModeIndex = modChoices.findIndex(choice => choice.value === initialMode);
537
448
  const select = new _enquirer.Select({
@@ -541,18 +452,16 @@ async function promptForComponent(component, allowLocal, defaultObject) {
541
452
  });
542
453
  modeResult = await select.run();
543
454
  }
544
-
545
455
  const messagePrefix = selectMode ? '\t' : `${componentDisplayName} - `;
546
-
547
456
  if ('local' === modeResult) {
548
457
  const directoryPath = await promptForText(`${messagePrefix}What is a path to your local ${componentDisplayName}`, (defaultObject === null || defaultObject === void 0 ? void 0 : defaultObject.dir) || '');
549
458
  return {
550
459
  mode: modeResult,
551
460
  dir: directoryPath
552
461
  };
553
- } // image with selection
554
-
462
+ }
555
463
 
464
+ // image with selection
556
465
  if (component === 'wordpress') {
557
466
  const message = `${messagePrefix}Which version would you like`;
558
467
  const tagChoices = await getTagChoices();
@@ -563,55 +472,63 @@ async function promptForComponent(component, allowLocal, defaultObject) {
563
472
  });
564
473
  const option = await selectTag.run();
565
474
  return {
566
- mode: modeResult,
475
+ mode: 'image',
567
476
  tag: option
568
477
  };
569
- } // image
570
-
478
+ }
571
479
 
480
+ // image
572
481
  return {
573
482
  mode: modeResult
574
483
  };
575
484
  }
576
-
577
485
  const FALSE_OPTIONS = ['false', 'no', 'n', '0'];
578
-
579
486
  function processBooleanOption(value) {
580
487
  var _value$toLowerCase;
581
-
582
488
  if (!value) {
583
489
  return false;
584
490
  }
585
-
586
491
  return !FALSE_OPTIONS.includes((_value$toLowerCase = value.toLowerCase) === null || _value$toLowerCase === void 0 ? void 0 : _value$toLowerCase.call(value));
587
492
  }
588
-
589
493
  function addDevEnvConfigurationOptions(command) {
590
494
  return command.option('wordpress', 'Use a specific WordPress version').option(['u', 'mu-plugins'], 'Use a specific mu-plugins changeset or local directory').option('app-code', 'Use the application code from a local directory or use "demo" for VIP skeleton code').option('statsd', 'Enable statsd component. By default it is disabled', undefined, processBooleanOption).option('phpmyadmin', 'Enable PHPMyAdmin component. By default it is disabled', undefined, processBooleanOption).option('xdebug', 'Enable XDebug. By default it is disabled', undefined, processBooleanOption).option('xdebug_config', 'Extra configuration to pass to xdebug via XDEBUG_CONFIG environment variable').option('elasticsearch', 'Enable Elasticsearch (needed by Enterprise Search)', undefined, processBooleanOption).option('mariadb', 'Explicitly choose MariaDB version to use').option(['r', 'media-redirect-domain'], 'Domain to redirect for missing media files. This can be used to still have images without the need to import them locally.').option('php', 'Explicitly choose PHP version to use');
591
495
  }
496
+
592
497
  /**
593
498
  * Provides the list of tag choices for selection
594
499
  */
595
-
596
-
597
500
  async function getTagChoices() {
598
- const versions = await (0, _devEnvironmentCore.getVersionList)();
599
-
501
+ let versions = await (0, _devEnvironmentCore.getVersionList)();
600
502
  if (versions.length < 1) {
601
- return ['5.9', '5.8', '5.7', '5.6', '5.5'];
503
+ versions = [{
504
+ ref: '5.9.5',
505
+ tag: '5.9',
506
+ cacheable: true,
507
+ locked: true,
508
+ prerelease: false
509
+ }, {
510
+ ref: '5.8.6',
511
+ tag: '5.8',
512
+ cacheable: true,
513
+ locked: true,
514
+ prerelease: false
515
+ }, {
516
+ ref: '5.7.8',
517
+ tag: '5.7',
518
+ cacheable: true,
519
+ locked: true,
520
+ prerelease: false
521
+ }];
602
522
  }
603
-
604
523
  return versions.map(version => {
605
524
  let mapping;
606
525
  const tagFormatted = version.tag.padEnd(8 - version.tag.length);
607
526
  const prerelease = version.prerelease ? '(Pre-Release)' : '';
608
-
609
527
  if (version.tag !== version.ref) {
610
528
  mapping = `→ ${prerelease} ${version.ref}`;
611
529
  } else {
612
530
  mapping = '';
613
531
  }
614
-
615
532
  return {
616
533
  name: version.tag,
617
534
  message: `${tagFormatted} ${mapping}`,
@@ -619,23 +536,19 @@ async function getTagChoices() {
619
536
  };
620
537
  });
621
538
  }
622
-
623
539
  function getEnvTrackingInfo(slug) {
624
540
  try {
625
541
  var _result$php;
626
-
627
542
  const envData = (0, _devEnvironmentCore.readEnvironmentData)(slug);
628
543
  const result = {
629
544
  slug
630
545
  };
631
-
632
546
  for (const key of Object.keys(envData)) {
633
547
  // track doesnt like camelCase
634
548
  const snakeCasedKey = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
635
549
  const value = _devEnvironment.DEV_ENVIRONMENT_COMPONENTS.includes(key) ? JSON.stringify(envData[key]) : envData[key];
636
550
  result[snakeCasedKey] = value;
637
551
  }
638
-
639
552
  result.php = (_result$php = result.php) === null || _result$php === void 0 ? void 0 : _result$php.replace(/.*:/, '');
640
553
  return result;
641
554
  } catch (err) {