@scandipwa/magento-scripts 1.14.1-alpha.10 → 1.14.1-alpha.11

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 (81) hide show
  1. package/lib/commands/logs.js +1 -0
  2. package/lib/commands/start.js +18 -5
  3. package/lib/config/dependencies-for-platforms.js +12 -2
  4. package/lib/config/docker.js +4 -3
  5. package/lib/config/get-port-config.js +2 -1
  6. package/lib/config/index.js +2 -1
  7. package/lib/config/php/extensions/libsodium.js +2 -1
  8. package/lib/config/scandipwa-versions.js +2 -2
  9. package/lib/config/system-config.js +34 -5
  10. package/lib/errors/known-error.js +15 -0
  11. package/lib/errors/unknown-error.js +15 -0
  12. package/lib/tasks/cli/create-bashrc-config.js +2 -1
  13. package/lib/tasks/composer/index.js +5 -3
  14. package/lib/tasks/composer/local-auth-json.js +4 -2
  15. package/lib/tasks/docker/network.js +2 -1
  16. package/lib/tasks/file-system/create-nginx-config.js +2 -1
  17. package/lib/tasks/file-system/create-php-config.js +2 -1
  18. package/lib/tasks/file-system/create-php-fpm-config.js +2 -1
  19. package/lib/tasks/file-system/create-php-storm-config.js +6 -5
  20. package/lib/tasks/file-system/create-ssl-terminator-config.js +5 -3
  21. package/lib/tasks/file-system/create-varnish-config.js +2 -23
  22. package/lib/tasks/file-system/create-vscode-config.js +3 -2
  23. package/lib/tasks/magento/enable-magento-composer-plugins.js +3 -2
  24. package/lib/tasks/magento/install-magento.js +7 -5
  25. package/lib/tasks/magento/setup-magento/flush-redis-config.js +2 -1
  26. package/lib/tasks/magento/setup-magento/index.js +3 -1
  27. package/lib/tasks/magento/setup-magento/install-magento.js +2 -1
  28. package/lib/tasks/magento/setup-magento/upgrade-magento.js +11 -1
  29. package/lib/tasks/magento/setup-magento/waiting-for-varnish.js +41 -0
  30. package/lib/tasks/mysql/connect-to-mysql.js +2 -1
  31. package/lib/tasks/mysql/import-dump-to-mysql.js +4 -2
  32. package/lib/tasks/mysql/import-remote-db/index.js +2 -1
  33. package/lib/tasks/mysql/import-remote-db/ssh/index.js +2 -1
  34. package/lib/tasks/mysql/import-remote-db/ssh/regular-server.js +2 -1
  35. package/lib/tasks/php/bundled-extensions.js +28 -0
  36. package/lib/tasks/php/compile-options.js +18 -48
  37. package/lib/tasks/php/compile.js +4 -3
  38. package/lib/tasks/php/configure.js +7 -66
  39. package/lib/tasks/php/extensions/index.js +71 -0
  40. package/lib/tasks/php/index.js +7 -6
  41. package/lib/tasks/php/update-phpbrew.js +2 -1
  42. package/lib/tasks/php/validate-php.js +67 -0
  43. package/lib/tasks/php-fpm/start-php-fpm.js +2 -1
  44. package/lib/tasks/requirements/composer.js +5 -3
  45. package/lib/tasks/requirements/dependency/arch.js +2 -1
  46. package/lib/tasks/requirements/dependency/centos.js +2 -1
  47. package/lib/tasks/requirements/dependency/fedora.js +2 -1
  48. package/lib/tasks/requirements/docker/index.js +5 -4
  49. package/lib/tasks/requirements/docker/install.js +2 -1
  50. package/lib/tasks/requirements/docker/running-status.js +3 -2
  51. package/lib/tasks/requirements/docker/version.js +2 -1
  52. package/lib/tasks/requirements/node-version.js +2 -1
  53. package/lib/tasks/requirements/php-version.js +5 -3
  54. package/lib/tasks/requirements/phpbrew/index.js +2 -1
  55. package/lib/tasks/requirements/phpbrew/install.js +2 -1
  56. package/lib/tasks/requirements/phpbrew/version.js +2 -1
  57. package/lib/tasks/requirements/platform.js +3 -2
  58. package/lib/tasks/start.js +3 -1
  59. package/lib/tasks/theme/build-theme.js +2 -1
  60. package/lib/tasks/theme/install-theme.js +2 -1
  61. package/lib/tasks/theme/retrieve-theme-data.js +2 -1
  62. package/lib/tasks/theme/setup-persisted-query.js +2 -1
  63. package/lib/tasks/theme/setup-themes.js +2 -1
  64. package/lib/tasks/theme/symlink-theme.js +2 -1
  65. package/lib/util/analytics.js +337 -0
  66. package/lib/util/config-file-validator.js +2 -1
  67. package/lib/util/config-php-json.js +3 -2
  68. package/lib/util/env-php-json.js +3 -2
  69. package/lib/util/get-installed-magento-version.js +3 -2
  70. package/lib/util/get-jsonfile-data.js +2 -1
  71. package/lib/util/install-dependencies-task.js +4 -4
  72. package/lib/util/instance-metadata.js +2 -1
  73. package/lib/util/ip.js +45 -1
  74. package/lib/util/magento-task.js +20 -9
  75. package/lib/util/request.js +0 -0
  76. package/lib/util/resolve-configuration-with-overrides.js +2 -1
  77. package/lib/util/run-composer.js +3 -2
  78. package/lib/util/run-magento.js +3 -2
  79. package/lib/util/run-php.js +3 -2
  80. package/lib/util/wait-for-it.js +3 -2
  81. package/package.json +4 -3
@@ -11,6 +11,7 @@ const updateEnvPHP = require('../../php/update-env-php');
11
11
  const increaseAdminSessionLifetime = require('./increase-admin-session-lifetime');
12
12
  const magentoTask = require('../../../util/magento-task');
13
13
  const urnHighlighter = require('./urn-highlighter');
14
+ const waitingForVarnish = require('./waiting-for-varnish');
14
15
 
15
16
  /**
16
17
  * @type {({ onlyInstallMagento: boolean }) => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
@@ -48,7 +49,8 @@ const setupMagento = (options = {}) => ({
48
49
  disableMaintenanceMode(),
49
50
  disable2fa(),
50
51
  urnHighlighter(),
51
- magentoTask('cache:flush')
52
+ magentoTask('cache:flush'),
53
+ waitingForVarnish()
52
54
  ], {
53
55
  concurrent: false,
54
56
  exitOnError: true,
@@ -1,4 +1,5 @@
1
1
  const semver = require('semver');
2
+ const UnknownError = require('../../../errors/unknown-error');
2
3
  const runMagentoCommand = require('../../../util/run-magento');
3
4
 
4
5
  /**
@@ -86,7 +87,7 @@ const installMagento = ({ isDbEmpty = false } = {}) => ({
86
87
 
87
88
  if (!installed) {
88
89
  const errorMessages = errors.map((e) => e.message).join('\n\n');
89
- throw new Error(`Unable to install Magento!\n${errorMessages}`);
90
+ throw new UnknownError(`Unable to install Magento!\n${errorMessages}`);
90
91
  }
91
92
  },
92
93
  options: {
@@ -1,4 +1,6 @@
1
1
  const magentoTask = require('../../../util/magento-task');
2
+ const logger = require('@scandipwa/scandipwa-dev-utils/logger');
3
+ const KnownError = require('../../../errors/known-error');
2
4
 
3
5
  /**
4
6
  * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
@@ -12,7 +14,15 @@ const upgradeMagento = () => ({
12
14
  return false;
13
15
  },
14
16
  task: (_ctx, task) => task.newListr([
15
- magentoTask('setup:upgrade --no-interaction'),
17
+ magentoTask('setup:upgrade --no-interaction', {
18
+ onError: (e) => {
19
+ throw new KnownError(`Magento setup:upgrade command failed!
20
+ You can try disabling failed module and try again.
21
+ To disable module, open ${logger.style.misc('cli')} and type the following command: ${logger.style.command('m module:disable <module-name>')}
22
+
23
+ Error: ${e}`);
24
+ }
25
+ }),
16
26
  {
17
27
  task: (ctx) => {
18
28
  ctx.isSetupUpgradeNeeded = false;
@@ -0,0 +1,41 @@
1
+ const { request } = require('smol-request');
2
+ const KnownError = require('../../../errors/known-error');
3
+ const sleep = require('../../../util/sleep');
4
+
5
+ /**
6
+ * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
7
+ */
8
+ const waitingForVarnish = () => ({
9
+ title: 'Waiting for Varnish to return code 200',
10
+ skip: (ctx) => !ctx.config.overridenConfiguration.configuration.varnish.enabled,
11
+ task: async (ctx) => {
12
+ let tries = 0;
13
+ while (tries < 10) {
14
+ try {
15
+ const response = await request(`http://localhost:${ctx.ports.sslTerminator}/`, {
16
+ responseType: 'headers'
17
+ });
18
+
19
+ if (response.status !== 200) {
20
+ tries++;
21
+ await sleep(2000);
22
+ } else {
23
+ break;
24
+ }
25
+ } catch (e) {
26
+ tries++;
27
+ await sleep(200);
28
+ }
29
+ }
30
+
31
+ if (tries === 10) {
32
+ throw new KnownError(`After 20 seconds website is still responding with non-200 code, which might indicate issue with setup.
33
+ Or Varnish is still loading...
34
+
35
+ Please check the logs!`);
36
+ }
37
+ },
38
+ exitOnError: false
39
+ });
40
+
41
+ module.exports = waitingForVarnish;
@@ -1,4 +1,5 @@
1
1
  const mysql = require('mysql2/promise');
2
+ const UnknownError = require('../../errors/unknown-error');
2
3
  const { execAsyncSpawn } = require('../../util/exec-async-command');
3
4
  const sleep = require('../../util/sleep');
4
5
 
@@ -44,7 +45,7 @@ Please wait, this will take some time and do not restart the MySQL container unt
44
45
  }
45
46
 
46
47
  if (tries === maxTries) {
47
- throw new Error(`Unable to connect to MySQL server. Check your server configuration!\n\n${ errors.join(' ') }`);
48
+ throw new UnknownError(`Unable to connect to MySQL server. Check your server configuration!\n\n${ errors.join(' ') }`);
48
49
  }
49
50
 
50
51
  task.title = 'MySQL server connected!';
@@ -1,4 +1,6 @@
1
1
  /* eslint-disable max-len */
2
+ const KnownError = require('../../errors/known-error');
3
+ const UnknownError = require('../../errors/unknown-error');
2
4
  const { execAsyncSpawn } = require('../../util/exec-async-command');
3
5
  const pathExists = require('../../util/path-exists');
4
6
 
@@ -9,7 +11,7 @@ const importDumpToMySQL = () => ({
9
11
  title: 'Importing Database Dump To MySQL',
10
12
  task: async (ctx, task) => {
11
13
  if (!await pathExists(ctx.importDb)) {
12
- throw new Error(`Dump file at ${ctx.importDb} does not exist. Please provide correct relative path to the file`);
14
+ throw new KnownError(`Dump file at ${ctx.importDb} does not exist. Please provide correct relative path to the file`);
13
15
  }
14
16
 
15
17
  const { config: { docker }, ports } = ctx;
@@ -42,7 +44,7 @@ const importDumpToMySQL = () => ({
42
44
  }
43
45
  );
44
46
  } catch (e) {
45
- throw new Error(`Unexpected error during dump import.\n\n${e}`);
47
+ throw new UnknownError(`Unexpected error during dump import.\n\n${e}`);
46
48
  }
47
49
 
48
50
  clearInterval(tickInterval);
@@ -1,3 +1,4 @@
1
+ const UnknownError = require('../../../errors/unknown-error');
1
2
  const sshDb = require('./ssh');
2
3
 
3
4
  /**
@@ -30,7 +31,7 @@ It can be a SSH (ssh://<url>) connection or mysql (mysql://<url>) connection.
30
31
  );
31
32
  }
32
33
  default: {
33
- throw new Error(`Unsupported protocol ${protocol}`);
34
+ throw new UnknownError(`Unsupported protocol ${protocol}`);
34
35
  }
35
36
  }
36
37
  }
@@ -3,6 +3,7 @@ const { NodeSSH } = require('node-ssh');
3
3
  const pathExists = require('../../../../util/path-exists');
4
4
  const regularSSHServer = require('./regular-server');
5
5
  const readymageSSH = require('./readymage');
6
+ const KnownError = require('../../../../errors/known-error');
6
7
 
7
8
  /**
8
9
  * @type {() => import('listr2').ListrTask<import('../../../../../typings/context').ListrContext>}
@@ -25,7 +26,7 @@ const sshDb = () => ({
25
26
  });
26
27
 
27
28
  if (!(await pathExists(privateKey))) {
28
- throw new Error(`Private key not found: ${privateKey}`);
29
+ throw new KnownError(`Private key not found: ${privateKey}`);
29
30
  }
30
31
 
31
32
  ctx.privateKey = privateKey;
@@ -2,6 +2,7 @@ const mergeFiles = require('merge-files');
2
2
  const { orderTables, customerTables } = require('../../magento-tables');
3
3
  const { execAsyncSpawn } = require('../../../../util/exec-async-command');
4
4
  const mysqlDumpCommandWithOptions = require('./mysqldump-command');
5
+ const KnownError = require('../../../../errors/known-error');
5
6
  /**
6
7
  * @type {() => import('listr2').ListrTask<import('../../../../../typings/context').ListrContext & { ssh: import('node-ssh').NodeSSH }>}
7
8
  */
@@ -30,7 +31,7 @@ Do not enter "--result-file" option, we need to control that part.
30
31
  });
31
32
 
32
33
  if (dumpCommand.includes('--result-file')) {
33
- throw new Error('--result-file option is not allowed in user input command');
34
+ throw new KnownError('--result-file option is not allowed in user input command');
34
35
  }
35
36
 
36
37
  if (!withCustomersData) {
@@ -0,0 +1,28 @@
1
+ const bundledExtensions = [
2
+ 'bz2',
3
+ 'bcmath',
4
+ 'ctype',
5
+ 'curl',
6
+ 'intl',
7
+ 'dom',
8
+ 'filter',
9
+ 'hash',
10
+ 'sockets',
11
+ 'iconv',
12
+ 'json',
13
+ 'mbstring',
14
+ 'openssl',
15
+ 'xml',
16
+ 'mysql',
17
+ 'pdo',
18
+ 'soap',
19
+ 'xmlrpc',
20
+ 'xml',
21
+ 'zip',
22
+ 'fpm',
23
+ 'gd'
24
+ ];
25
+
26
+ module.exports = {
27
+ bundledExtensions
28
+ };
@@ -1,30 +1,16 @@
1
+ const { bundledExtensions } = require('./bundled-extensions');
2
+
3
+ const darwinVariants = [
4
+ 'openssl=$(brew --prefix openssl@1.1)', // ="$(brew --prefix openssl@1.1)"
5
+ 'curl=$(brew --prefix curl)',
6
+ 'intl=$(brew --prefix icu4c)',
7
+ 'bz2="$(brew --prefix bzip2)"'
8
+ ];
9
+
1
10
  const compileOptions = {
2
11
  linux: {
3
12
  cpuCount: '$(nproc)',
4
- variants: [
5
- '+bz2',
6
- '+bcmath',
7
- '+ctype',
8
- '+curl',
9
- '+intl',
10
- '+dom',
11
- '+filter',
12
- '+hash',
13
- '+sockets',
14
- '+iconv',
15
- '+json',
16
- '+mbstring',
17
- '+openssl',
18
- '+xml',
19
- '+mysql',
20
- '+pdo',
21
- '+soap',
22
- '+xmlrpc',
23
- '+xml',
24
- '+zip',
25
- '+fpm',
26
- '+gd'
27
- ],
13
+ variants: bundledExtensions.map((ext) => `+${ext}`),
28
14
  extraOptions: [
29
15
  '--with-freetype-dir=/usr/include/freetype2',
30
16
  '--with-openssl=/usr/',
@@ -39,30 +25,14 @@ const compileOptions = {
39
25
  },
40
26
  darwin: {
41
27
  cpuCount: '$(sysctl -n hw.ncpu)',
42
- variants: [
43
- '+neutral',
44
- '+bz2="$(brew --prefix bzip2)"',
45
- '+bcmath',
46
- '+ctype',
47
- '+curl=$(brew --prefix curl)',
48
- '+intl=$(brew --prefix icu4c)',
49
- '+dom',
50
- '+filter',
51
- '+hash',
52
- '+iconv',
53
- '+json',
54
- '+mbstring',
55
- '+openssl=$(brew --prefix openssl@1.1)', // ="$(brew --prefix openssl@1.1)"
56
- '+xml',
57
- '+mysql',
58
- '+pdo',
59
- '+soap',
60
- '+xmlrpc',
61
- '+xml',
62
- '+zip',
63
- '+fpm',
64
- '+gd'
65
- ],
28
+ variants: bundledExtensions.map((ext) => {
29
+ const darwinVariant = darwinVariants.find((dv) => dv.startsWith(ext));
30
+ if (darwinVariant) {
31
+ return `+${darwinVariant}`;
32
+ }
33
+
34
+ return `+${ext}`;
35
+ }),
66
36
  extraOptions: [
67
37
  '--with-zlib-dir=$(brew --prefix zlib)',
68
38
  '--with-iconv=$(brew --prefix libiconv)',
@@ -2,11 +2,12 @@ const systeminformation = require('systeminformation');
2
2
  const logger = require('@scandipwa/scandipwa-dev-utils/logger');
3
3
  const { execAsyncSpawn } = require('../../util/exec-async-command');
4
4
  const compileOptions = require('./compile-options');
5
+ const UnknownError = require('../../errors/unknown-error');
5
6
 
6
7
  /**
7
8
  * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
8
9
  */
9
- const compile = () => ({
10
+ const compilePHP = () => ({
10
11
  title: 'Compiling PHP',
11
12
  task: async ({ config: { php } }, task) => {
12
13
  const platformCompileOptions = compileOptions[process.platform];
@@ -31,7 +32,7 @@ const compile = () => ({
31
32
  }
32
33
  );
33
34
  } catch (e) {
34
- throw new Error(
35
+ throw new UnknownError(
35
36
  `Failed to compile the required PHP version.
36
37
  Tried compiling the PHP version ${ logger.style.misc(php.version) }.
37
38
  Use your favorite search engine to resolve the issue.
@@ -44,4 +45,4 @@ const compile = () => ({
44
45
  }
45
46
  });
46
47
 
47
- module.exports = compile;
48
+ module.exports = compilePHP;
@@ -1,76 +1,17 @@
1
1
  /* eslint-disable max-len */
2
- const path = require('path');
3
- const fs = require('fs');
4
- const { execAsyncSpawn } = require('../../util/exec-async-command');
5
- const pathExists = require('../../util/path-exists');
6
2
  const enableExtension = require('./extensions/enable');
7
3
  const installExtension = require('./extensions/install');
8
4
  const disableExtension = require('./extensions/disable');
9
- const phpbrewConfig = require('../../config/phpbrew');
10
-
11
- /**
12
- * Get enabled extensions list with versions
13
- * @param {import('../../../typings/context').ListrContext['config']} param0
14
- * @returns {Promise<{[key: string]: string}}>}
15
- */
16
- const getEnabledExtensions = async ({ php }) => {
17
- const output = await execAsyncSpawn(
18
- `${ php.binPath } -c ${php.iniPath} -r 'foreach (get_loaded_extensions() as $extension) echo "$extension:" . phpversion($extension) . "\n";'`
19
- );
20
-
21
- return output
22
- .split('\n')
23
- .map((m) => {
24
- // eslint-disable-next-line no-unused-vars
25
- const [_, moduleName, moduleVersion] = m.match(/(.+):(.+)/i);
26
-
27
- return [moduleName, moduleVersion];
28
- })
29
- .reduce((acc, [name, version]) => ({ ...acc, [name]: version }), {});
30
- };
31
-
32
- /**
33
- * Get disabled extensions list
34
- * @param {import('../../../typings/context').ListrContext['config']} param0
35
- * @returns {Promise<string[]>}
36
- */
37
- const getDisabledExtensions = async ({ php }) => {
38
- const extensionsIniDirectory = path.join(phpbrewConfig.phpPath, `php-${php.version}`, 'var', 'db');
39
-
40
- if (!await pathExists(extensionsIniDirectory)) {
41
- return [];
42
- }
43
-
44
- const extensionIniList = await fs.promises.readdir(
45
- extensionsIniDirectory,
46
- {
47
- encoding: 'utf-8',
48
- withFileTypes: true
49
- }
50
- );
51
-
52
- return extensionIniList.filter((f) => f.isFile() && f.name.endsWith('.disabled')).map((f) => f.name.replace('.disabled', ''));
53
- };
54
-
55
- /**
56
- * Get installed extensions
57
- * @param {import('../../../typings/context').ListrContext['config']} param0
58
- * @returns {Promise<string[]>}
59
- */
60
- const getInstalledExtensions = async ({ php }) => {
61
- const extensionDirectory = path.join(phpbrewConfig.buildPath, `php-${php.version}`, 'ext');
62
-
63
- const availableExtensions = await fs.promises.readdir(extensionDirectory, {
64
- encoding: 'utf-8'
65
- });
66
-
67
- return availableExtensions;
68
- };
5
+ const {
6
+ getEnabledExtensions,
7
+ getInstalledExtensions,
8
+ getDisabledExtensions
9
+ } = require('./extensions');
69
10
 
70
11
  /**
71
12
  * @returns {import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
72
13
  */
73
- const configure = () => ({
14
+ const configurePHP = () => ({
74
15
  title: 'Configuring PHP extensions',
75
16
  task: async ({ config, debug }, task) => {
76
17
  const { php, php: { disabledExtensions = [] } } = config;
@@ -145,4 +86,4 @@ const configure = () => ({
145
86
  }
146
87
  });
147
88
 
148
- module.exports = configure;
89
+ module.exports = configurePHP;
@@ -0,0 +1,71 @@
1
+ /* eslint-disable max-len */
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ const { execAsyncSpawn } = require('../../../util/exec-async-command');
5
+ const pathExists = require('../../../util/path-exists');
6
+ const phpbrewConfig = require('../../../config/phpbrew');
7
+
8
+ /**
9
+ * Get enabled extensions list with versions
10
+ * @param {import('../../../../typings/context').ListrContext['config']} param0
11
+ * @returns {Promise<{[key: string]: string}}>}
12
+ */
13
+ const getEnabledExtensions = async ({ php }) => {
14
+ const output = await execAsyncSpawn(
15
+ `${ php.binPath } -c ${php.iniPath} -r 'foreach (get_loaded_extensions() as $extension) echo "$extension:" . phpversion($extension) . "\n";'`
16
+ );
17
+
18
+ return output
19
+ .split('\n')
20
+ .map((m) => {
21
+ // eslint-disable-next-line no-unused-vars
22
+ const [_, moduleName, moduleVersion] = m.match(/(.+):(.+)/i);
23
+
24
+ return [moduleName, moduleVersion];
25
+ })
26
+ .reduce((acc, [name, version]) => ({ ...acc, [name]: version }), {});
27
+ };
28
+
29
+ /**
30
+ * Get disabled extensions list
31
+ * @param {import('../../../../typings/context').ListrContext['config']} param0
32
+ * @returns {Promise<string[]>}
33
+ */
34
+ const getDisabledExtensions = async ({ php }) => {
35
+ const extensionsIniDirectory = path.join(phpbrewConfig.phpPath, `php-${php.version}`, 'var', 'db');
36
+
37
+ if (!await pathExists(extensionsIniDirectory)) {
38
+ return [];
39
+ }
40
+
41
+ const extensionIniList = await fs.promises.readdir(
42
+ extensionsIniDirectory,
43
+ {
44
+ encoding: 'utf-8',
45
+ withFileTypes: true
46
+ }
47
+ );
48
+
49
+ return extensionIniList.filter((f) => f.isFile() && f.name.endsWith('.disabled')).map((f) => f.name.replace('.disabled', ''));
50
+ };
51
+
52
+ /**
53
+ * Get installed extensions
54
+ * @param {import('../../../../typings/context').ListrContext['config']} param0
55
+ * @returns {Promise<string[]>}
56
+ */
57
+ const getInstalledExtensions = async ({ php }) => {
58
+ const extensionDirectory = path.join(phpbrewConfig.buildPath, `php-${php.version}`, 'ext');
59
+
60
+ const availableExtensions = await fs.promises.readdir(extensionDirectory, {
61
+ encoding: 'utf-8'
62
+ });
63
+
64
+ return availableExtensions;
65
+ };
66
+
67
+ module.exports = {
68
+ getEnabledExtensions,
69
+ getDisabledExtensions,
70
+ getInstalledExtensions
71
+ };
@@ -2,10 +2,11 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const logger = require('@scandipwa/scandipwa-dev-utils/logger');
4
4
  const pathExists = require('../../util/path-exists');
5
- const compile = require('./compile');
6
- const configure = require('./configure');
5
+ const compilePhp = require('./compile');
6
+ const configurePhp = require('./configure');
7
7
  const updatePhpBrew = require('./update-phpbrew');
8
8
  const phpbrewConfig = require('../../config/phpbrew');
9
+ const UnknownError = require('../../errors/unknown-error');
9
10
 
10
11
  /**
11
12
  * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
@@ -52,7 +53,7 @@ const installPhp = () => ({
52
53
  return;
53
54
  }
54
55
  } catch (e) {
55
- throw new Error(
56
+ throw new UnknownError(
56
57
  `Failed to extract the list of installed PHP versions.
57
58
  Possibly, you forgot to setup PHPBrew?
58
59
  Follow these instruction: ${ logger.style.link('https://phpbrew.github.io/phpbrew/#setting-up') }
@@ -63,7 +64,7 @@ const installPhp = () => ({
63
64
  // eslint-disable-next-line consistent-return
64
65
  return task.newListr([
65
66
  updatePhpBrew(),
66
- compile()
67
+ compilePhp()
67
68
  ], {
68
69
  concurrent: false,
69
70
  exitOnError: true
@@ -73,6 +74,6 @@ const installPhp = () => ({
73
74
 
74
75
  module.exports = {
75
76
  installPhp,
76
- compilePhp: compile,
77
- configurePhp: configure
77
+ compilePhp,
78
+ configurePhp
78
79
  };
@@ -1,3 +1,4 @@
1
+ const UnknownError = require('../../errors/unknown-error');
1
2
  const { execAsyncSpawn } = require('../../util/exec-async-command');
2
3
 
3
4
  /**
@@ -20,7 +21,7 @@ const updatePhpBrew = () => ({
20
21
  }
21
22
  });
22
23
  } catch (e) {
23
- throw new Error(`Unexpected error while updating phpbrew known php versions\n\n${e}`);
24
+ throw new UnknownError(`Unexpected error while updating phpbrew known php versions\n\n${e}`);
24
25
  }
25
26
  },
26
27
  options: {
@@ -0,0 +1,67 @@
1
+ const logger = require('@scandipwa/scandipwa-dev-utils/logger');
2
+ const { bundledExtensions } = require('./bundled-extensions');
3
+ const configurePHP = require('./configure');
4
+ const { getEnabledExtensions } = require('./extensions');
5
+ const { installPhp } = require('./index');
6
+
7
+ /**
8
+ * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
9
+ */
10
+ const validatePHPInstallation = () => ({
11
+ title: 'Validating PHP installation',
12
+ task: async (ctx, task) => {
13
+ const enabledExtensions = await getEnabledExtensions(ctx.config);
14
+ const enabledExtensionsKeys = Object.keys(enabledExtensions);
15
+
16
+ enabledExtensionsKeys.push('fpm');
17
+
18
+ if (enabledExtensionsKeys.some((ext) => ext.includes('mysql'))) {
19
+ enabledExtensionsKeys.push('mysql');
20
+ }
21
+
22
+ const missingBundledExtensions = bundledExtensions.filter(
23
+ (ext) => !enabledExtensionsKeys.some(
24
+ (ex) => ex.toLowerCase() === ext.toLowerCase()
25
+ )
26
+ );
27
+
28
+ if (missingBundledExtensions.length > 0) {
29
+ const selectedOption = await task.prompt({
30
+ type: 'Select',
31
+ message: `Your PHP version compiled by PHPBrew is missing important extensions that are bundled by default by ${logger.style.misc('magento-scripts')}
32
+ Maybe you ran PHPBrew by yourself?
33
+
34
+ Please, consider recompiling PHP using ${logger.style.misc('magento-scripts')}.
35
+
36
+ ${logger.style.command('npm start -- --recompile-php')}
37
+ `,
38
+ choices: [
39
+ {
40
+ name: 'recompile-php',
41
+ message: `I want ${logger.style.misc('magento-scripts')} to recompile PHP`
42
+ },
43
+ {
44
+ name: 'skip',
45
+ message: 'I am sure that it is okay and want to continue with this setup'
46
+ }
47
+ ]
48
+ });
49
+
50
+ if (selectedOption === 'skip') {
51
+ task.skip('User skipped PHP recompilation');
52
+ return;
53
+ }
54
+
55
+ ctx.recompilePhp = true;
56
+
57
+ return task.newListr([
58
+ installPhp(),
59
+ configurePHP()
60
+ ], {
61
+ concurrent: false
62
+ });
63
+ }
64
+ }
65
+ });
66
+
67
+ module.exports = validatePHPInstallation;
@@ -2,6 +2,7 @@ const { execAsyncSpawn } = require('../../util/exec-async-command');
2
2
  const getPhpConfig = require('../../config/php-config');
3
3
  const { getBaseConfig } = require('../../config/index');
4
4
  const getProcessId = require('./get-process-id');
5
+ const UnknownError = require('../../errors/unknown-error');
5
6
 
6
7
  /**
7
8
  * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
@@ -35,7 +36,7 @@ const startPhpFpm = () => ({
35
36
  }
36
37
  );
37
38
  } catch (e) {
38
- throw new Error(`Error during PHP-FPM start\n\n${e}`);
39
+ throw new UnknownError(`Error during PHP-FPM start\n\n${e}`);
39
40
  }
40
41
  },
41
42
  options: {
@@ -3,6 +3,8 @@ const fs = require('fs');
3
3
  const os = require('os');
4
4
  const logger = require('@scandipwa/scandipwa-dev-utils/logger');
5
5
  const pathExists = require('../../util/path-exists');
6
+ const KnownError = require('../../errors/known-error');
7
+ const UnknownError = require('../../errors/unknown-error');
6
8
 
7
9
  const authJsonPath = path.join(process.cwd(), 'auth.json');
8
10
  const shellName = process.env.SHELL.split('/').pop();
@@ -112,7 +114,7 @@ ${ logger.style.misc('Password') } (${ logger.style.misc('Private key') }):`,
112
114
  break;
113
115
  }
114
116
  default: {
115
- throw new Error(
117
+ throw new KnownError(
116
118
  `Unfortunately we cannot automatically add credentials for your shell ${process.env.SHELL}!
117
119
 
118
120
  You will need to that manually!
@@ -195,7 +197,7 @@ Would you like to load them now?`
195
197
 
196
198
  process.env.COMPOSER_AUTH = composerAuthFileContent;
197
199
  } catch (e) {
198
- throw new Error(
200
+ throw new UnknownError(
199
201
  `We found an error in your ${ logger.style.file('./auth.json') } file.
200
202
 
201
203
  Make sure that this file contains a valid JSON!
@@ -211,7 +213,7 @@ Error message that we got: ${e}`
211
213
  try {
212
214
  composerAuthContent = JSON.parse(process.env.COMPOSER_AUTH);
213
215
  } catch (e) {
214
- throw new Error(
216
+ throw new UnknownError(
215
217
  `We found an error in your ${ logger.style.misc('$COMPOSER_AUTH') } environment variable.
216
218
 
217
219
  Make sure that this variable contains a valid JSON!