@scandipwa/magento-scripts 2.0.0-alpha.9 → 2.0.1

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 (183) hide show
  1. package/lib/commands/cli.js +18 -1
  2. package/lib/commands/logs.js +28 -2
  3. package/lib/commands/start.js +24 -3
  4. package/lib/commands/status.js +19 -1
  5. package/lib/config/config.js +20 -2
  6. package/lib/config/dependencies-for-platforms.js +1 -113
  7. package/lib/config/docker.js +94 -54
  8. package/lib/config/get-project-configuration.js +5 -0
  9. package/lib/config/index.js +10 -3
  10. package/lib/config/magento/required-php-extensions/index.js +1 -1
  11. package/lib/config/php-config.js +4 -3
  12. package/lib/config/port-config.js +3 -1
  13. package/lib/config/services/composer/versions/composer-1.js +13 -0
  14. package/lib/config/services/composer/versions/composer-2.js +8 -0
  15. package/lib/config/services/composer/versions/index.js +4 -0
  16. package/lib/config/services/elasticsearch/versions/elasticsearch-7.10.js +11 -0
  17. package/lib/config/services/elasticsearch/versions/elasticsearch-7.12.js +11 -0
  18. package/lib/config/services/elasticsearch/versions/elasticsearch-7.16.js +11 -0
  19. package/lib/config/services/elasticsearch/versions/elasticsearch-7.17.js +11 -0
  20. package/lib/config/services/elasticsearch/versions/elasticsearch-7.6.js +11 -0
  21. package/lib/config/services/elasticsearch/versions/elasticsearch-7.7.js +11 -0
  22. package/lib/config/services/elasticsearch/versions/elasticsearch-7.9.js +11 -0
  23. package/lib/config/services/elasticsearch/versions/index.js +15 -1
  24. package/lib/config/services/maildev/index.js +7 -0
  25. package/lib/config/services/mariadb/versions/index.js +5 -0
  26. package/lib/config/services/mariadb/versions/mariadb-10.2.js +8 -0
  27. package/lib/config/services/mariadb/versions/mariadb-10.3.js +8 -0
  28. package/lib/config/services/mariadb/versions/mariadb-10.4.js +8 -0
  29. package/lib/config/services/nginx/versions/index.js +3 -0
  30. package/lib/config/services/nginx/versions/nginx-1.18.js +11 -0
  31. package/lib/config/{php → services/php}/base-repo.js +0 -0
  32. package/lib/config/{php → services/php}/extensions/apcu.js +0 -0
  33. package/lib/config/{php → services/php}/extensions/bcmath.js +0 -0
  34. package/lib/config/{php → services/php}/extensions/curl.js +0 -0
  35. package/lib/config/{php → services/php}/extensions/gd.js +0 -0
  36. package/lib/config/{php → services/php}/extensions/index.js +0 -0
  37. package/lib/config/{php → services/php}/extensions/intl.js +0 -0
  38. package/lib/config/{php → services/php}/extensions/opcache.js +0 -0
  39. package/lib/config/{php → services/php}/extensions/pdo_mysql.js +0 -0
  40. package/lib/config/{php → services/php}/extensions/soap.js +0 -0
  41. package/lib/config/{php → services/php}/extensions/sodium.js +0 -0
  42. package/lib/config/{php → services/php}/extensions/xdebug.js +0 -0
  43. package/lib/config/{php → services/php}/extensions/xsl.js +0 -0
  44. package/lib/config/{php → services/php}/extensions/zip.js +0 -0
  45. package/lib/config/{php → services/php}/versions/index.js +0 -0
  46. package/lib/config/{php → services/php}/versions/php-7.2.js +1 -0
  47. package/lib/config/{php → services/php}/versions/php-7.3.js +1 -0
  48. package/lib/config/{php → services/php}/versions/php-7.4.js +1 -0
  49. package/lib/config/{php → services/php}/versions/php-8.1.js +1 -0
  50. package/lib/config/services/redis/index.js +5 -0
  51. package/lib/config/services/redis/redis-5.0.js +8 -0
  52. package/lib/config/services/redis/redis-6.0.js +8 -0
  53. package/lib/config/services/redis/redis-6.2.js +8 -0
  54. package/lib/config/{ssl-terminator → services/ssl-terminator}/index.js +3 -0
  55. package/lib/config/services/varnish/index.js +5 -0
  56. package/lib/config/{varnish → services/varnish}/varnish-6-0.js +5 -3
  57. package/lib/config/{varnish → services/varnish}/varnish-6-6.js +5 -3
  58. package/lib/config/{varnish → services/varnish}/varnish-7-0.js +5 -3
  59. package/lib/config/templates/magentorc.template +12 -5
  60. package/lib/config/templates/nginx.fastcgi_params.template +29 -0
  61. package/lib/config/templates/nginx.template.conf +1 -1
  62. package/lib/config/templates/php-debug.template.ini +31 -0
  63. package/lib/config/templates/php-fpm.template.conf +1 -2
  64. package/lib/config/templates/php.template.ini +5 -201
  65. package/lib/config/templates/ssl-terminator.template.conf +2 -0
  66. package/lib/config/templates/varnish.template.vcl +20 -13
  67. package/lib/config/versions/magento-2.2.10.js +39 -0
  68. package/lib/config/versions/magento-2.3.0.js +15 -19
  69. package/lib/config/versions/magento-2.3.1.js +15 -19
  70. package/lib/config/versions/magento-2.3.2-p1.js +15 -19
  71. package/lib/config/versions/magento-2.3.2-p2.js +15 -19
  72. package/lib/config/versions/magento-2.3.2.js +15 -19
  73. package/lib/config/versions/magento-2.3.3-p1.js +15 -19
  74. package/lib/config/versions/magento-2.3.3.js +15 -19
  75. package/lib/config/versions/magento-2.3.4-p1.js +15 -19
  76. package/lib/config/versions/magento-2.3.4-p2.js +15 -19
  77. package/lib/config/versions/magento-2.3.4.js +15 -19
  78. package/lib/config/versions/magento-2.3.5-p1.js +17 -22
  79. package/lib/config/versions/magento-2.3.5-p2.js +17 -22
  80. package/lib/config/versions/magento-2.3.5.js +17 -22
  81. package/lib/config/versions/magento-2.3.6-p1.js +17 -22
  82. package/lib/config/versions/magento-2.3.6.js +17 -22
  83. package/lib/config/versions/magento-2.3.7-p1.js +17 -22
  84. package/lib/config/versions/magento-2.3.7-p2.js +17 -22
  85. package/lib/config/versions/magento-2.3.7-p3.js +17 -22
  86. package/lib/config/versions/magento-2.3.7-p4.js +17 -22
  87. package/lib/config/versions/magento-2.3.7.js +17 -22
  88. package/lib/config/versions/magento-2.4.0-p1.js +17 -22
  89. package/lib/config/versions/magento-2.4.0.js +17 -22
  90. package/lib/config/versions/magento-2.4.1-p1.js +18 -23
  91. package/lib/config/versions/magento-2.4.1.js +18 -23
  92. package/lib/config/versions/magento-2.4.2-p1.js +18 -23
  93. package/lib/config/versions/magento-2.4.2-p2.js +18 -23
  94. package/lib/config/versions/magento-2.4.2.js +18 -23
  95. package/lib/config/versions/magento-2.4.3-p1.js +18 -23
  96. package/lib/config/versions/magento-2.4.3-p2.js +18 -23
  97. package/lib/config/versions/magento-2.4.3-p3.js +18 -23
  98. package/lib/config/versions/magento-2.4.3.js +18 -23
  99. package/lib/config/versions/magento-2.4.4-p1.js +18 -23
  100. package/lib/config/versions/magento-2.4.4-p2.js +41 -0
  101. package/lib/config/versions/magento-2.4.4.js +18 -23
  102. package/lib/config/versions/magento-2.4.5-p1.js +41 -0
  103. package/lib/config/versions/magento-2.4.5.js +18 -23
  104. package/lib/tasks/cli/create-bashrc-config.js +4 -2
  105. package/lib/tasks/composer/local-auth-json.js +1 -1
  106. package/lib/tasks/database/connect-to-database.js +6 -3
  107. package/lib/tasks/database/create-magento-database.js +5 -2
  108. package/lib/tasks/database/create-magento-user.js +50 -0
  109. package/lib/tasks/database/default-magento-database.js +3 -0
  110. package/lib/tasks/database/default-magento-user.js +7 -0
  111. package/lib/tasks/database/import-dump-to-database.js +3 -2
  112. package/lib/tasks/docker/api.d.ts +25 -1
  113. package/lib/tasks/docker/api.js +31 -1
  114. package/lib/tasks/docker/containers/container-api.d.ts +17 -0
  115. package/lib/tasks/docker/containers/container-api.js +64 -9
  116. package/lib/tasks/docker/containers/tasks.js +44 -13
  117. package/lib/tasks/docker/convert-composer-home-to-composer-cache-volume.js +52 -0
  118. package/lib/tasks/docker/convert-mysql-to-mariadb.js +2 -2
  119. package/lib/tasks/docker/image/image-api.d.ts +44 -0
  120. package/lib/tasks/docker/image/image-api.js +30 -2
  121. package/lib/tasks/docker/index.js +6 -1
  122. package/lib/tasks/docker/network/tasks.js +19 -14
  123. package/lib/tasks/docker/project-image-builder.js +39 -14
  124. package/lib/tasks/docker/system/index.js +5 -0
  125. package/lib/tasks/docker/system/system-api.d.ts +71 -0
  126. package/lib/tasks/docker/system/system-api.js +35 -0
  127. package/lib/tasks/docker/volume/index.js +2 -1
  128. package/lib/tasks/docker/volume/tasks.js +67 -9
  129. package/lib/tasks/docker/volume/volume-api.d.ts +40 -0
  130. package/lib/tasks/docker/volume/volume-api.js +55 -2
  131. package/lib/tasks/execute.js +5 -2
  132. package/lib/tasks/file-system/create-nginx-config.js +3 -5
  133. package/lib/tasks/file-system/create-php-config.js +2 -23
  134. package/lib/tasks/file-system/create-php-debug-config.js +45 -0
  135. package/lib/tasks/file-system/create-php-fpm-config.js +2 -4
  136. package/lib/tasks/file-system/create-phpstorm-config/database-config.js +24 -5
  137. package/lib/tasks/file-system/create-phpstorm-config/eslint-config.js +25 -13
  138. package/lib/tasks/file-system/create-phpstorm-config/exclude-folder-config.js +13 -3
  139. package/lib/tasks/file-system/create-phpstorm-config/index.js +2 -1
  140. package/lib/tasks/file-system/create-phpstorm-config/inspection-tools-config/custom-ruleset-path-config.js +18 -7
  141. package/lib/tasks/file-system/create-phpstorm-config/inspection-tools-config/paths.js +4 -0
  142. package/lib/tasks/file-system/create-ssl-terminator-config.js +23 -8
  143. package/lib/tasks/file-system/create-varnish-config.js +4 -7
  144. package/lib/tasks/file-system/create-vscode-config.js +2 -1
  145. package/lib/tasks/file-system/index.js +3 -2
  146. package/lib/tasks/magento/setup-magento/configure-elasticsearch.js +2 -4
  147. package/lib/tasks/magento/setup-magento/flush-redis-config.js +3 -6
  148. package/lib/tasks/magento/setup-magento/index.js +2 -0
  149. package/lib/tasks/magento/setup-magento/install-magento.js +8 -13
  150. package/lib/tasks/magento/setup-magento/set-base-url.js +2 -1
  151. package/lib/tasks/magento/setup-magento/set-mail-config.js +22 -0
  152. package/lib/tasks/magento/setup-magento/varnish-config.js +4 -9
  153. package/lib/tasks/magento/setup-magento/waiting-for-varnish.js +15 -16
  154. package/lib/tasks/php/php-container.js +1 -1
  155. package/lib/tasks/php/update-env-php.js +4 -6
  156. package/lib/tasks/{prefix → project-config}/index.js +6 -6
  157. package/lib/tasks/requirements/composer-credentials.js +7 -3
  158. package/lib/tasks/requirements/docker/context.js +88 -0
  159. package/lib/tasks/requirements/docker/index.js +111 -19
  160. package/lib/tasks/requirements/docker/install.js +21 -7
  161. package/lib/tasks/requirements/docker/permissions.js +2 -11
  162. package/lib/tasks/requirements/docker/running-status.js +94 -24
  163. package/lib/tasks/requirements/docker/version.js +1 -0
  164. package/lib/tasks/requirements/index.js +0 -2
  165. package/lib/tasks/requirements/php-version.js +4 -2
  166. package/lib/tasks/start.js +27 -8
  167. package/lib/tasks/status/index.js +86 -21
  168. package/lib/tasks/stop.js +2 -0
  169. package/lib/tasks/theme/retrieve-theme-data.js +12 -2
  170. package/lib/util/config-file-validator.js +17 -3
  171. package/lib/util/connection-string.js +62 -0
  172. package/lib/util/execute-in-container.js +7 -8
  173. package/lib/util/instance-metadata.js +14 -2
  174. package/lib/util/systemctl.js +62 -13
  175. package/package.json +2 -2
  176. package/typings/context.d.ts +11 -0
  177. package/typings/index.d.ts +46 -1
  178. package/lib/tasks/requirements/dependency/arch.js +0 -50
  179. package/lib/tasks/requirements/dependency/centos.js +0 -36
  180. package/lib/tasks/requirements/dependency/fedora.js +0 -36
  181. package/lib/tasks/requirements/dependency/index.js +0 -33
  182. package/lib/tasks/requirements/dependency/mac.js +0 -124
  183. package/lib/tasks/requirements/dependency/ubuntu.js +0 -83
@@ -14,6 +14,7 @@ const getDockerVersion = () => ({
14
14
  ctx.dockerServerData = dockerVersion.Server;
15
15
  ctx.dockerClientData = dockerVersion.Client;
16
16
  ctx.dockerVersion = dockerVersion.Server.Version;
17
+ ctx.isDockerDesktop = dockerVersion.Server.Platform.Name.includes('Desktop');
17
18
  } else {
18
19
  throw new UnknownError(`Got unexpected result during Docker version retrieval!\n\n${ dockerVersion }`);
19
20
  }
@@ -19,8 +19,6 @@ const checkRequirements = () => ({
19
19
  checkDocker(),
20
20
  // check for Node.js version
21
21
  checkNodeVersion(),
22
- // check installed PHP version
23
- // checkPHPVersion(),
24
22
  // check for COMPOSER_AUTH or auth.json
25
23
  localAuthJson(),
26
24
  checkComposerCredentials()
@@ -7,8 +7,10 @@ const { runContainerImage } = require('../../util/run-container-image');
7
7
  const checkPHPVersion = () => ({
8
8
  title: 'Checking container PHP version',
9
9
  task: async (ctx, task) => {
10
- const { php } = ctx.config.docker.getContainers(ctx.ports);
11
- const phpVersionResponse = await runContainerImage(php.image, 'php --version');
10
+ const phpVersionResponse = await runContainerImage(
11
+ ctx.config.overridenConfiguration.configuration.php.baseImage,
12
+ 'php --version'
13
+ );
12
14
 
13
15
  const phpVersionResponseResult = phpVersionResponse.match(/PHP\s(\d+\.\d+\.\d+)/i);
14
16
 
@@ -11,7 +11,6 @@ const { prepareFileSystem } = require('./file-system');
11
11
  const { installMagentoProject, setupMagento } = require('./magento');
12
12
  const { pullImages, stopContainers } = require('./docker/containers');
13
13
  const dockerNetwork = require('./docker/network');
14
- const { setPrefix } = require('./prefix');
15
14
  const { connectToDatabase } = require('./database');
16
15
  const { buildProjectImage, buildDebugProjectImage } = require('./docker/project-image-builder');
17
16
  const getProjectConfiguration = require('../config/get-project-configuration');
@@ -28,6 +27,19 @@ const waitingForVarnish = require('./magento/setup-magento/waiting-for-varnish')
28
27
  const checkPHPVersion = require('./requirements/php-version');
29
28
  const volumes = require('./docker/volume/tasks');
30
29
  const convertMySQLDatabaseToMariaDB = require('./docker/convert-mysql-to-mariadb');
30
+ const { cmaGlobalConfig } = require('../config/cma-config');
31
+ const { setProjectConfigTask } = require('./project-config');
32
+ const { convertComposerHomeToComposerCacheVolume } = require('./docker/convert-composer-home-to-composer-cache-volume');
33
+
34
+ /**
35
+ * @type {() => import('listr2').ListrTask<import('../../typings/context').ListrContext>}
36
+ */
37
+ const resetCmaGlobalConfig = () => ({
38
+ skip: (ctx) => !ctx.resetGlobalConfig,
39
+ task: () => {
40
+ cmaGlobalConfig.clear();
41
+ }
42
+ });
31
43
 
32
44
  /**
33
45
  * @type {() => import('listr2').ListrTask<import('../../typings/context').ListrContext>}
@@ -39,7 +51,6 @@ const retrieveProjectConfiguration = () => ({
39
51
  checkConfigurationFile(),
40
52
  getProjectConfiguration(),
41
53
  convertLegacyVolumes(),
42
- convertMySQLDatabaseToMariaDB(),
43
54
  createCacheFolder(),
44
55
  getSystemConfigTask(),
45
56
  getCachedPorts()
@@ -59,7 +70,8 @@ const retrieveProjectConfiguration = () => ({
59
70
  const stopProject = () => ({
60
71
  title: 'Stopping project',
61
72
  task: (ctx, task) => task.newListr([
62
- stopContainers()
73
+ stopContainers(),
74
+ volumes.removeLocalVolumes()
63
75
  ]),
64
76
  options: {
65
77
  showTimer: false
@@ -72,7 +84,7 @@ const stopProject = () => ({
72
84
  const retrieveFreshProjectConfiguration = () => ({
73
85
  title: 'Retrieving fresh project configuration',
74
86
  task: (ctx, task) => task.newListr([
75
- setPrefix(),
87
+ setProjectConfigTask(),
76
88
  getProjectConfiguration(),
77
89
  // get fresh ports
78
90
  getAvailablePorts(),
@@ -93,9 +105,14 @@ const retrieveFreshProjectConfiguration = () => ({
93
105
  const configureProject = () => ({
94
106
  title: 'Configuring project',
95
107
  task: (ctx, task) => task.newListr([
96
- pullImages(),
97
- dockerNetwork.tasks.createNetwork(),
98
- volumes.createVolumes(),
108
+ convertMySQLDatabaseToMariaDB(),
109
+ {
110
+ task: (ctx, task) => task.newListr([
111
+ pullImages(),
112
+ dockerNetwork.tasks.createNetwork()
113
+ ], { concurrent: true })
114
+ },
115
+ checkPHPVersion(),
99
116
  {
100
117
  task: (ctx, task) => task.newListr([
101
118
  buildProjectImage(),
@@ -104,9 +121,10 @@ const configureProject = () => ({
104
121
  concurrent: true
105
122
  })
106
123
  },
107
- checkPHPVersion(),
108
124
  getComposerVersionTask(),
109
125
  prepareFileSystem(),
126
+ volumes.createVolumes(),
127
+ convertComposerHomeToComposerCacheVolume(),
110
128
  installMagentoProject(),
111
129
  enableMagentoComposerPlugins(),
112
130
  startServices(),
@@ -138,6 +156,7 @@ const start = () => ({
138
156
  task: (ctx, task) => {
139
157
  task.title = `Starting project (magento-scripts@${pkg.version})`;
140
158
  return task.newListr([
159
+ resetCmaGlobalConfig(),
141
160
  checkRequirements(),
142
161
  retrieveProjectConfiguration(),
143
162
  stopProject(),
@@ -1,3 +1,4 @@
1
+ /* eslint-disable max-len */
1
2
  const path = require('path');
2
3
  const logger = require('@scandipwa/scandipwa-dev-utils/logger');
3
4
  const { getProjectCreatedAt, getPrefix } = require('../../util/prefix');
@@ -5,9 +6,21 @@ const { getProjectCreatedAt, getPrefix } = require('../../util/prefix');
5
6
  const { version: packageVersion } = require('../../../package.json');
6
7
  const { getArchSync } = require('../../util/arch');
7
8
  const ConsoleBlock = require('../../util/console-block');
8
- const { getComposerVersion } = require('../composer');
9
9
  const { getInstanceMetadata } = require('../../util/instance-metadata');
10
10
 
11
+ const isJSON = (str) => {
12
+ try {
13
+ const result = JSON.parse(str);
14
+ if (typeof result === 'object') {
15
+ return true;
16
+ }
17
+ } catch (e) {
18
+ //
19
+ }
20
+
21
+ return false;
22
+ };
23
+
11
24
  /**
12
25
  * @param {string} port
13
26
  * @return {{ host: string, hostPort: string, containerPort: string }}
@@ -22,19 +35,24 @@ const parsePort = (port) => {
22
35
  };
23
36
  };
24
37
 
38
+ /**
39
+ * @param {import('../../../typings/context').ListrContext & { containers: ReturnType<Awaited<ReturnType<import('../../config/docker')>>['getContainers']> }} ctx
40
+ */
25
41
  const prettyStatus = async (ctx) => {
26
42
  const {
27
43
  config: {
28
- baseConfig
44
+ baseConfig,
45
+ projectConfig
29
46
  },
30
47
  magentoVersion,
31
48
  dockerVersion,
32
49
  platform,
33
50
  platformVersion,
34
- containers
51
+ containers,
52
+ composerVersion,
53
+ systemDFData
35
54
  } = ctx;
36
55
  const projectCreatedAt = getProjectCreatedAt();
37
- const composerVersion = await getComposerVersion(ctx);
38
56
 
39
57
  const prefix = getPrefix();
40
58
 
@@ -45,7 +63,7 @@ const prettyStatus = async (ctx) => {
45
63
  block
46
64
  .addHeader(`magento-scripts version: ${ logger.style.link(packageVersion) }`)
47
65
  .addEmptyLine()
48
- .addLine(`Project: ${logger.style.file(baseConfig.prefix)} ${prefix === folderName ? '(without prefix)' : '(with prefix)'} (with php container)`)
66
+ .addLine(`Project: ${logger.style.file(baseConfig.prefix)} ${prefix === folderName ? '(without prefix)' : '(with prefix)'} (with php container)${ projectConfig.debug ? ' (with debugging)' : '' }`)
49
67
  .addLine(`Project location: ${logger.style.link(process.cwd())}`);
50
68
 
51
69
  if (projectCreatedAt) {
@@ -71,19 +89,25 @@ const prettyStatus = async (ctx) => {
71
89
 
72
90
  let containerStatus;
73
91
 
74
- if (container.status && container.status.Health) {
75
- containerStatus = `✓ ${ logger.style.file(container.status.Health.Status) } and ${ logger.style.file('running') }`;
76
- } else if (container.status) {
77
- containerStatus = logger.style.file(container.status.Status);
92
+ if (container.status && container.status.State && container.status.State.Health) {
93
+ containerStatus = `✓ ${ logger.style.file(container.status.State.Health.Status) } and ${ logger.style.file('running') }`;
94
+ } else if (container.status && container.status.State) {
95
+ containerStatus = logger.style.file(container.status.State.Status);
78
96
  } else {
79
97
  containerStatus = '✖ Not running';
80
98
  }
81
99
 
82
100
  block
83
101
  .addLine(`Status: ${containerStatus}`)
84
- .addLine(`Name: ${logger.style.misc(container.name)}`)
85
- .addLine(`Image: ${logger.style.file(container.image)}`)
86
- .addLine(`Network: ${logger.style.link(container.network)}`);
102
+ .addLine(`Name: ${logger.style.misc(container.name)}`);
103
+
104
+ if (container.status && container.status.Config && container.status.Config.Image) {
105
+ block.addLine(`Image: ${logger.style.file(container.status.Config.Image)}`);
106
+ } else {
107
+ block.addLine(`Image: ${logger.style.file(container.image)}`);
108
+ }
109
+
110
+ block.addLine(`Network: ${logger.style.link(container.network)}`);
87
111
 
88
112
  if (!containerStatus.includes('Not running') && container.forwardedPorts && container.forwardedPorts.length > 0) {
89
113
  block.addLine('Port forwarding:');
@@ -100,11 +124,60 @@ const prettyStatus = async (ctx) => {
100
124
  if (container.env && Object.keys(container.env).length > 0) {
101
125
  block.addLine('Environment variables:');
102
126
  for (const [envName, envValue] of Object.entries(container.env)) {
103
- block.addLine(`${' '.repeat(3)} ${logger.style.misc(envName)}=${logger.style.file(envValue)}`);
127
+ if (isJSON(envValue)) {
128
+ const beautifyJSONLines = JSON.stringify(JSON.parse(envValue), null, 1).split('\n');
129
+
130
+ block.addLine(`${' '.repeat(3)} ${logger.style.misc(envName)}=${logger.style.file(beautifyJSONLines.shift())}`);
131
+
132
+ let currentOpeningBracket = 0;
133
+
134
+ beautifyJSONLines.forEach((line) => {
135
+ block.addLine(`${' '.repeat(2 + currentOpeningBracket)}${logger.style.file(line)}`);
136
+ if (['{', '['].some((openingBracketVariant) => line.includes(openingBracketVariant))) {
137
+ currentOpeningBracket++;
138
+ } else if (['}', ']'].some((closingBracketVariant) => line.includes(closingBracketVariant))) {
139
+ currentOpeningBracket--;
140
+ }
141
+ });
142
+ } else {
143
+ block.addLine(`${' '.repeat(3)} ${logger.style.misc(envName)}=${logger.style.file(envValue)}`);
144
+ }
104
145
  }
105
146
  }
147
+
148
+ if (container.description) {
149
+ block.addLine('Description:');
150
+ container.description.split('\n').forEach((line) => {
151
+ block.addLine(line);
152
+ });
153
+ }
106
154
  });
107
155
 
156
+ block
157
+ .addSeparator('Docker volume data')
158
+ .addEmptyLine();
159
+
160
+ const { volumes } = ctx.config.docker;
161
+
162
+ Object.values(volumes)
163
+ .map((volume) => {
164
+ volume.volumeData = systemDFData.Volumes
165
+ .find((v) => v.Name === volume.name);
166
+
167
+ return volume;
168
+ })
169
+ .forEach((v) => {
170
+ block
171
+ .addLine(`> ${logger.style.misc(v.name)}`);
172
+ if (v.volumeData) {
173
+ block.addLine(`Size: ${logger.style.code(v.volumeData.Size)}`);
174
+ }
175
+
176
+ if (ctx.isDockerDesktop && v.opt && v.opt.device) {
177
+ block.addLine(`Mountpoint: ${logger.style.file(v.opt.device.replace(process.cwd(), '<project location>'))}`);
178
+ }
179
+ });
180
+
108
181
  const instanceMetadata = getInstanceMetadata(ctx);
109
182
 
110
183
  block
@@ -123,14 +196,6 @@ const prettyStatus = async (ctx) => {
123
196
  instanceMetadata.admin.forEach(({ title, text }) => {
124
197
  block.addLine(` ${title}: ${text}`);
125
198
  });
126
- // block
127
- // .addEmptyLine()
128
- // .addSeparator('Magento status')
129
- // .addEmptyLine()
130
- // .addLine(`Web location: ${logger.style.link(`${ssl.enabled ? 'https' : 'http'}://${host}${ports.app === 80 ? '' : `:${ports.app}`}/`)}`)
131
- // .addLine(`Magento Admin panel location: ${logger.style.link(`${ssl.enabled ? 'https' : 'http'}://${host}${ports.app === 80 ? '' : `:${ports.app}`}/${magentoConfiguration.adminuri}`)}`)
132
- // .addLine(`Magento Admin panel credentials: ${logger.style.misc(magentoConfiguration.user)} - ${logger.style.misc(magentoConfiguration.password)}`)
133
- // .addEmptyLine();
134
199
 
135
200
  block.log();
136
201
  };
package/lib/tasks/stop.js CHANGED
@@ -2,6 +2,7 @@ const { stopServices } = require('./docker');
2
2
  const getMagentoVersionConfig = require('../config/get-magento-version-config');
3
3
  const getProjectConfiguration = require('../config/get-project-configuration');
4
4
  const checkConfigurationFile = require('../config/check-configuration-file');
5
+ const getDockerVersion = require('./requirements/docker/version');
5
6
 
6
7
  /**
7
8
  * @type {() => import('listr2').ListrTask<import('../../typings/context').ListrContext>}
@@ -9,6 +10,7 @@ const checkConfigurationFile = require('../config/check-configuration-file');
9
10
  const stop = () => ({
10
11
  title: 'Stopping project',
11
12
  task: async (ctx, task) => task.newListr([
13
+ getDockerVersion(),
12
14
  getMagentoVersionConfig(),
13
15
  checkConfigurationFile(),
14
16
  getProjectConfiguration(),
@@ -1,3 +1,4 @@
1
+ const logger = require('@scandipwa/scandipwa-dev-utils/logger');
1
2
  const path = require('path');
2
3
  const KnownError = require('../../errors/known-error');
3
4
  const getJsonfileData = require('../../util/get-jsonfile-data');
@@ -9,12 +10,21 @@ const pathExists = require('../../util/path-exists');
9
10
  const retrieveThemeData = (themePath) => ({
10
11
  title: 'Checking theme folder',
11
12
  task: async (ctx) => {
12
- let absoluteThemePath = path.join(process.cwd(), themePath);
13
+ let absoluteThemePath = path.resolve(themePath);
14
+
15
+ // validate if theme is located inside magento directory
16
+ if (!absoluteThemePath.includes(process.cwd())) {
17
+ throw new KnownError(`You are trying to link the theme from outside of your Magento project!
18
+
19
+ This is not supported in ${ logger.style.command('magento-scripts') } version 2.
20
+
21
+ Move your theme inside Magento project!`);
22
+ }
13
23
 
14
24
  // check if path not relative
15
25
  if (!(await pathExists(path.join(absoluteThemePath, 'composer.json')))) {
16
26
  // if composer.json is not found, then it's not correct path
17
- // and we need to test if it's alsolute one
27
+ // and we need to test if it's absolute one
18
28
  if (await pathExists(path.join(themePath, 'composer.json'))) {
19
29
  // if so, use it as absolute path
20
30
  absoluteThemePath = themePath;
@@ -53,8 +53,9 @@ const phpExtensionConfiguration = Joi.object()
53
53
  .pattern(
54
54
  Joi.string(),
55
55
  Joi.object({
56
+ name: Joi.string().optional(),
56
57
  alternativeName: Joi.array().items(Joi.string()).optional(),
57
- command: Joi.func().optional(),
58
+ command: Joi.alternatives().try(Joi.func(), Joi.string()).optional(),
58
59
  dependencies: Joi.array().items(Joi.string()).optional(),
59
60
  version: Joi.string().optional()
60
61
  })
@@ -69,6 +70,7 @@ const phpConfigurationSchema = Joi.object({
69
70
  debugImage: Joi.string().optional(),
70
71
  fpmConfigTemplate: Joi.string().optional(),
71
72
  configTemplate: Joi.string().optional().custom(fileExistsValidator),
73
+ debugTemplate: Joi.string().optional().custom(fileExistsValidator),
72
74
  extensions: phpExtensionConfiguration.optional()
73
75
  });
74
76
 
@@ -85,6 +87,7 @@ const nginxConfigurationSchema = Joi.object({
85
87
  */
86
88
  const varnishConfigurationSchema = Joi.object({
87
89
  enabled: Joi.boolean().optional(),
90
+ healthCheck: Joi.boolean().optional(),
88
91
  image: Joi.string().optional(),
89
92
  configTemplate: Joi.string().optional().custom(fileExistsValidator)
90
93
  });
@@ -114,7 +117,17 @@ const composerConfigurationSchema = Joi.object({
114
117
  }
115
118
 
116
119
  return versionValidator(value);
117
- })
120
+ }),
121
+ plugins: Joi.object()
122
+ .pattern(
123
+ Joi.string(),
124
+ Joi.object({
125
+ version: Joi.string().optional(),
126
+ options: Joi.string().optional(),
127
+ enabled: Joi.boolean().optional()
128
+ })
129
+ .unknown()
130
+ )
118
131
  });
119
132
 
120
133
  /**
@@ -128,7 +141,8 @@ const configurationSchema = Joi.object({
128
141
  redis: serviceConfigurationSchema.optional(),
129
142
  composer: composerConfigurationSchema.optional(),
130
143
  varnish: varnishConfigurationSchema.optional(),
131
- sslTerminator: nginxConfigurationSchema.optional()
144
+ sslTerminator: nginxConfigurationSchema.optional(),
145
+ maildev: serviceConfigurationSchema.optional()
132
146
  });
133
147
 
134
148
  /**
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @typedef ParsedConnection
3
+ * @prop {String} protocol
4
+ * @prop {String} [user]
5
+ * @prop {String} [port]
6
+ * @prop {String} host
7
+ * @prop {String} [hostname]
8
+ * @prop {String[]} [segments]
9
+ * @prop {Record<string, string} params
10
+ */
11
+
12
+ /**
13
+ * @param {String} url
14
+ * @returns {ParsedConnection}
15
+ */
16
+ const connectionStringParser = (url) => {
17
+ // eslint-disable-next-line no-useless-escape
18
+ const pattern = /^(?:([^:\/?#\s]+):\/{2})?(?:([^@\/?#\s]+)@)?([^\/?#\s]+)?(?:\/([^?#\s]*))?(?:[?]([^#\s]+))?\S*$/;
19
+ const matches = url.match(pattern);
20
+ const params = {};
21
+ if (matches[5] !== undefined) {
22
+ matches[5].split('&').forEach((x) => {
23
+ const a = x.split('=');
24
+ params[a[0]] = a[1];
25
+ });
26
+ }
27
+
28
+ return {
29
+ protocol: matches[1],
30
+ user: matches[2] !== undefined ? matches[2].split(':')[0] : undefined,
31
+ password: matches[2] !== undefined ? matches[2].split(':')[1] : undefined,
32
+ host: matches[3],
33
+ hostname: matches[3] !== undefined ? matches[3].split(/:(?=\d+$)/)[0] : undefined,
34
+ port: matches[3] !== undefined ? matches[3].split(/:(?=\d+$)/)[1] : undefined,
35
+ segments: matches[4] !== undefined ? matches[4].split('/') : undefined,
36
+ params
37
+ };
38
+ };
39
+
40
+ /**
41
+ * @param {ParsedConnection} options
42
+ * @returns {String}
43
+ */
44
+ const connectionStringBuilder = (options) => {
45
+ const {
46
+ protocol,
47
+ user,
48
+ password,
49
+ host,
50
+ port,
51
+ segments,
52
+ params
53
+ } = options;
54
+
55
+ // eslint-disable-next-line max-len
56
+ return `${protocol}://${(user && password) ? `${user}:${password}@` : ''}${host}${port ? `:${port}` : ''}/${(segments && segments.length > 0) ? segments.join('/') : ''}${new URLSearchParams(params).toString()}`;
57
+ };
58
+
59
+ module.exports = {
60
+ connectionStringParser,
61
+ connectionStringBuilder
62
+ };
@@ -1,17 +1,18 @@
1
- const os = require('os');
2
1
  const { spawn } = require('child_process');
3
2
  const { runCommand } = require('../tasks/docker/containers/container-api');
4
3
 
5
4
  /**
6
- * @param {{ containerName: string, commands: string[] }} param0
5
+ * @param {{ containerName: string, commands: string[], user?: string }} param0
7
6
  */
8
- const executeInContainer = ({ containerName, commands }) => {
7
+ const executeInContainer = ({
8
+ containerName, commands, user
9
+ }) => {
9
10
  if (!process.stdin.isTTY) {
10
11
  process.stderr.write('This app works only in TTY mode');
11
12
  process.exit(1);
12
13
  }
13
14
 
14
- const userArg = os.platform() === 'linux' && `--user=${os.userInfo().uid}:${os.userInfo().gid}`;
15
+ const userArg = user && `--user=${user}`;
15
16
 
16
17
  spawn('docker', [
17
18
  'exec',
@@ -45,12 +46,10 @@ const runInContainer = (options, commands) => {
45
46
  tty: true,
46
47
  detach: false,
47
48
  rm: true,
48
- command: commands.map((command) => command.split(' ')).flat().join(' ')
49
+ command: commands.join(' ')
49
50
  });
50
51
 
51
- const args = runArgs.slice(1).map((command) => command.split(' ')).flat();
52
-
53
- spawn('docker', args, { stdio: [0, 1, 2] });
52
+ spawn('bash', ['-c', runArgs.join(' ')], { stdio: [0, 1, 2] });
54
53
 
55
54
  return new Promise((_resolve) => {
56
55
  // never resolve
@@ -4,6 +4,7 @@ const WEB_LOCAL_LOCATION_TITLE = `Location on ${ logger.style.misc('localhost')
4
4
  const WEB_LOCATION_TITLE = 'Location on the Web';
5
5
  const WEB_ADMIN_LOCATION_TITLE = 'Panel location';
6
6
  const WEB_ADMIN_CREDENTIALS_TITLE = 'Panel credentials';
7
+ const WEB_MAILDEV_LOCATION_TITLE = 'Panel location';
7
8
 
8
9
  const mapDataStyle = ({ title, text }) => ({
9
10
  title,
@@ -13,7 +14,7 @@ const mapDataStyle = ({ title, text }) => ({
13
14
 
14
15
  /**
15
16
  * @param {import("../../typings/context").ListrContext} ctx
16
- * @return {{ frontend: { title: string, text: string }[], admin: { title: string, url: string }[]}}
17
+ * @return {{ frontend: { title: string, text: string }[], admin: { title: string, url: string }[], maildev: { title: string, text: string }[] }}
17
18
  */
18
19
  const getInstanceMetadata = (ctx) => {
19
20
  const {
@@ -34,6 +35,11 @@ const getInstanceMetadata = (ctx) => {
34
35
  */
35
36
  const admin = [];
36
37
 
38
+ /**
39
+ * @type {{ title: string, text: string }[]}
40
+ */
41
+ const maildev = [];
42
+
37
43
  const isNgrok = host.endsWith('ngrok.io');
38
44
 
39
45
  if (isNgrok) {
@@ -64,9 +70,15 @@ const getInstanceMetadata = (ctx) => {
64
70
  text: `${logger.style.misc(magentoConfiguration.user)} - ${logger.style.misc(magentoConfiguration.password)}`
65
71
  });
66
72
 
73
+ maildev.push({
74
+ title: WEB_MAILDEV_LOCATION_TITLE,
75
+ text: `http://${host}:${ports.maildevWeb}/`
76
+ });
77
+
67
78
  return {
68
79
  admin,
69
- frontend: frontend.map(mapDataStyle)
80
+ frontend: frontend.map(mapDataStyle),
81
+ maildev: maildev.map(mapDataStyle)
70
82
  };
71
83
  };
72
84
 
@@ -3,10 +3,10 @@ const { execAsyncSpawn } = require('./exec-async-command');
3
3
  /**
4
4
  * @param {String} cmd
5
5
  * @param {String} serviceName
6
- * @param {{ now: boolean }} options
6
+ * @param {{ now: boolean, user: boolean }} options
7
7
  */
8
8
  const run = (cmd, serviceName, options = {}) => execAsyncSpawn(
9
- `systemctl ${ cmd }${ serviceName ? ` ${ serviceName }` : '' }${ options.now ? ' --now' : ''}`,
9
+ `systemctl ${ options.user ? '--user ' : '' }${ cmd }${ serviceName ? ` ${ serviceName }` : '' }${ options.now ? ' --now' : ''}`,
10
10
  {
11
11
  withCode: true
12
12
  }
@@ -14,29 +14,78 @@ const run = (cmd, serviceName, options = {}) => execAsyncSpawn(
14
14
 
15
15
  const daemonReload = () => run('daemon-reload');
16
16
 
17
- const systemctlControl = (serviceName) => ({
18
- disable: () => run('disable', serviceName),
19
- enable: () => run('enable', serviceName),
20
- enableAndStart: () => run('enable', serviceName, { now: true }),
21
- restart: () => run('restart', serviceName),
22
- start: () => run('start', serviceName),
23
- stop: () => run('stop', serviceName),
24
- isEnabled: async () => {
17
+ /**
18
+ * @param {String} serviceName
19
+ * @param {{ now: boolean, user: boolean }} defaultOptions
20
+ */
21
+ const systemctlControl = (serviceName, defaultOptions = {}) => ({
22
+ /**
23
+ * @param {{ now: boolean, user: boolean }} options
24
+ */
25
+ disable: (options = {}) => run('disable', serviceName, { ...defaultOptions, ...options }),
26
+ /**
27
+ * @param {{ now: boolean, user: boolean }} options
28
+ */
29
+ enable: (options = {}) => run('enable', serviceName, { ...defaultOptions, ...options }),
30
+ /**
31
+ * @param {{ now: boolean, user: boolean }} options
32
+ */
33
+ enableAndStart: (options = {}) => run('enable', serviceName, { now: true, ...defaultOptions, ...options }),
34
+ /**
35
+ * @param {{ now: boolean, user: boolean }} options
36
+ */
37
+ restart: (options = {}) => run('restart', serviceName, { ...defaultOptions, ...options }),
38
+ /**
39
+ * @param {{ now: boolean, user: boolean }} options
40
+ */
41
+ start: (options = {}) => run('start', serviceName, { ...defaultOptions, ...options }),
42
+ /**
43
+ * @param {{ now: boolean, user: boolean }} options
44
+ */
45
+ stop: (options = {}) => run('stop', serviceName, { ...defaultOptions, ...options }),
46
+ /**
47
+ * @param {{ now: boolean, user: boolean }} options
48
+ */
49
+ isEnabled: async (options = {}) => {
25
50
  try {
26
- const { result } = await run('is-enabled', serviceName);
51
+ const { result } = await run('is-enabled', serviceName, { ...defaultOptions, ...options });
27
52
  return result.includes('enabled');
28
53
  } catch (e) {
29
54
  return false;
30
55
  }
31
56
  },
32
- isRunning: async () => {
57
+ /**
58
+ * @param {{ now: boolean, user: boolean }} options
59
+ */
60
+ isRunning: async (options = {}) => {
33
61
  try {
34
- const { result } = await run('status', serviceName);
62
+ const { result } = await run('status', serviceName, { ...defaultOptions, ...options });
35
63
 
36
64
  return result.includes('active (running)');
37
65
  } catch (e) {
38
66
  return false;
39
67
  }
68
+ },
69
+ /**
70
+ * @param {{ user: boolean }} options
71
+ */
72
+ exists: async (options = {}) => {
73
+ const optionsToUse = { ...defaultOptions, ...options };
74
+ try {
75
+ // eslint-disable-next-line max-len, no-useless-escape
76
+ const command = `if [[ $(systemctl ${ optionsToUse.user ? '--user ' : ''}list-units --all -t service --full --no-legend "${ serviceName }.service" | sed 's/^\\s*//g' | cut -f1 -d' ') == ${ serviceName }.service ]]; then
77
+ echo "1"
78
+ else
79
+ echo "0"
80
+ fi`;
81
+ const result = await execAsyncSpawn(
82
+ command
83
+ );
84
+
85
+ return result === '1';
86
+ } catch (e) {
87
+ return false;
88
+ }
40
89
  }
41
90
  });
42
91
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Scripts and configuration used by CMA.",
4
4
  "homepage": "https://docs.create-magento-app.com/",
5
5
  "repository": "github:scandipwa/create-magento-app",
6
- "version": "2.0.0-alpha.9",
6
+ "version": "2.0.1",
7
7
  "main": "./index.js",
8
8
  "types": "./typings/index.d.ts",
9
9
  "license": "OSL-3.0",
@@ -54,5 +54,5 @@
54
54
  "mysql",
55
55
  "scandipwa"
56
56
  ],
57
- "gitHead": "0fad81d40dcadf7f9b239d310062c09338c11601"
57
+ "gitHead": "2b9e8f9a3a42beba42f64765585f86955b25b0d0"
58
58
  }