@scandipwa/magento-scripts 2.0.0-alpha.9 → 2.0.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 (141) 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 +9 -1
  5. package/lib/config/config.js +20 -2
  6. package/lib/config/dependencies-for-platforms.js +1 -1
  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/php/versions/php-7.2.js +1 -0
  11. package/lib/config/php/versions/php-7.3.js +1 -0
  12. package/lib/config/php/versions/php-7.4.js +1 -0
  13. package/lib/config/php/versions/php-8.1.js +1 -0
  14. package/lib/config/php-config.js +4 -3
  15. package/lib/config/port-config.js +3 -1
  16. package/lib/config/services/composer/versions/composer-1.js +13 -0
  17. package/lib/config/services/composer/versions/composer-2.js +8 -0
  18. package/lib/config/services/composer/versions/index.js +4 -0
  19. package/lib/config/services/maildev/index.js +7 -0
  20. package/lib/config/services/nginx/versions/index.js +3 -0
  21. package/lib/config/services/nginx/versions/nginx-1.18.js +11 -0
  22. package/lib/config/{ssl-terminator → services/ssl-terminator}/index.js +3 -0
  23. package/lib/config/templates/magentorc.template +12 -5
  24. package/lib/config/templates/nginx.fastcgi_params.template +29 -0
  25. package/lib/config/templates/php-debug.template.ini +31 -0
  26. package/lib/config/templates/php-fpm.template.conf +1 -2
  27. package/lib/config/templates/php.template.ini +5 -201
  28. package/lib/config/templates/ssl-terminator.template.conf +2 -0
  29. package/lib/config/templates/varnish.template.vcl +20 -13
  30. package/lib/config/varnish/varnish-6-0.js +4 -0
  31. package/lib/config/varnish/varnish-6-6.js +4 -0
  32. package/lib/config/varnish/varnish-7-0.js +4 -0
  33. package/lib/config/versions/magento-2.2.10.js +41 -0
  34. package/lib/config/versions/magento-2.3.0.js +8 -10
  35. package/lib/config/versions/magento-2.3.1.js +8 -10
  36. package/lib/config/versions/magento-2.3.2-p1.js +8 -10
  37. package/lib/config/versions/magento-2.3.2-p2.js +8 -10
  38. package/lib/config/versions/magento-2.3.2.js +8 -10
  39. package/lib/config/versions/magento-2.3.3-p1.js +8 -10
  40. package/lib/config/versions/magento-2.3.3.js +8 -10
  41. package/lib/config/versions/magento-2.3.4-p1.js +8 -10
  42. package/lib/config/versions/magento-2.3.4-p2.js +8 -10
  43. package/lib/config/versions/magento-2.3.4.js +8 -10
  44. package/lib/config/versions/magento-2.3.5-p1.js +8 -10
  45. package/lib/config/versions/magento-2.3.5-p2.js +8 -10
  46. package/lib/config/versions/magento-2.3.5.js +8 -10
  47. package/lib/config/versions/magento-2.3.6-p1.js +8 -10
  48. package/lib/config/versions/magento-2.3.6.js +8 -10
  49. package/lib/config/versions/magento-2.3.7-p1.js +8 -10
  50. package/lib/config/versions/magento-2.3.7-p2.js +8 -10
  51. package/lib/config/versions/magento-2.3.7-p3.js +8 -10
  52. package/lib/config/versions/magento-2.3.7-p4.js +8 -10
  53. package/lib/config/versions/magento-2.3.7.js +8 -10
  54. package/lib/config/versions/magento-2.4.0-p1.js +8 -10
  55. package/lib/config/versions/magento-2.4.0.js +8 -10
  56. package/lib/config/versions/magento-2.4.1-p1.js +8 -10
  57. package/lib/config/versions/magento-2.4.1.js +8 -10
  58. package/lib/config/versions/magento-2.4.2-p1.js +8 -10
  59. package/lib/config/versions/magento-2.4.2-p2.js +8 -10
  60. package/lib/config/versions/magento-2.4.2.js +8 -10
  61. package/lib/config/versions/magento-2.4.3-p1.js +8 -10
  62. package/lib/config/versions/magento-2.4.3-p2.js +8 -10
  63. package/lib/config/versions/magento-2.4.3-p3.js +8 -10
  64. package/lib/config/versions/magento-2.4.3.js +8 -10
  65. package/lib/config/versions/magento-2.4.4-p1.js +8 -10
  66. package/lib/config/versions/magento-2.4.4.js +8 -10
  67. package/lib/config/versions/magento-2.4.5.js +8 -10
  68. package/lib/tasks/cli/create-bashrc-config.js +4 -2
  69. package/lib/tasks/composer/local-auth-json.js +1 -1
  70. package/lib/tasks/database/connect-to-database.js +6 -3
  71. package/lib/tasks/database/create-magento-database.js +5 -2
  72. package/lib/tasks/database/create-magento-user.js +50 -0
  73. package/lib/tasks/database/default-magento-database.js +3 -0
  74. package/lib/tasks/database/default-magento-user.js +7 -0
  75. package/lib/tasks/database/import-dump-to-database.js +3 -2
  76. package/lib/tasks/docker/api.d.ts +25 -1
  77. package/lib/tasks/docker/api.js +31 -1
  78. package/lib/tasks/docker/containers/container-api.d.ts +17 -0
  79. package/lib/tasks/docker/containers/container-api.js +64 -9
  80. package/lib/tasks/docker/containers/tasks.js +44 -13
  81. package/lib/tasks/docker/convert-composer-home-to-composer-cache-volume.js +52 -0
  82. package/lib/tasks/docker/convert-mysql-to-mariadb.js +2 -2
  83. package/lib/tasks/docker/image/image-api.d.ts +44 -0
  84. package/lib/tasks/docker/image/image-api.js +30 -2
  85. package/lib/tasks/docker/index.js +6 -1
  86. package/lib/tasks/docker/project-image-builder.js +37 -14
  87. package/lib/tasks/docker/system/index.js +5 -0
  88. package/lib/tasks/docker/system/system-api.d.ts +71 -0
  89. package/lib/tasks/docker/system/system-api.js +29 -0
  90. package/lib/tasks/docker/volume/index.js +2 -1
  91. package/lib/tasks/docker/volume/tasks.js +67 -9
  92. package/lib/tasks/docker/volume/volume-api.d.ts +40 -0
  93. package/lib/tasks/docker/volume/volume-api.js +54 -1
  94. package/lib/tasks/execute.js +5 -2
  95. package/lib/tasks/file-system/create-nginx-config.js +3 -5
  96. package/lib/tasks/file-system/create-php-config.js +2 -23
  97. package/lib/tasks/file-system/create-php-debug-config.js +45 -0
  98. package/lib/tasks/file-system/create-php-fpm-config.js +2 -4
  99. package/lib/tasks/file-system/create-phpstorm-config/exclude-folder-config.js +13 -3
  100. package/lib/tasks/file-system/create-phpstorm-config/index.js +2 -1
  101. package/lib/tasks/file-system/create-ssl-terminator-config.js +23 -8
  102. package/lib/tasks/file-system/create-varnish-config.js +4 -7
  103. package/lib/tasks/file-system/create-vscode-config.js +2 -1
  104. package/lib/tasks/file-system/index.js +3 -2
  105. package/lib/tasks/magento/setup-magento/configure-elasticsearch.js +2 -4
  106. package/lib/tasks/magento/setup-magento/flush-redis-config.js +3 -6
  107. package/lib/tasks/magento/setup-magento/index.js +2 -0
  108. package/lib/tasks/magento/setup-magento/install-magento.js +8 -13
  109. package/lib/tasks/magento/setup-magento/set-base-url.js +2 -1
  110. package/lib/tasks/magento/setup-magento/set-mail-config.js +22 -0
  111. package/lib/tasks/magento/setup-magento/varnish-config.js +4 -9
  112. package/lib/tasks/magento/setup-magento/waiting-for-varnish.js +15 -16
  113. package/lib/tasks/php/php-container.js +1 -1
  114. package/lib/tasks/php/update-env-php.js +3 -5
  115. package/lib/tasks/{prefix → project-config}/index.js +6 -6
  116. package/lib/tasks/requirements/composer-credentials.js +7 -3
  117. package/lib/tasks/requirements/docker/context.js +88 -0
  118. package/lib/tasks/requirements/docker/index.js +111 -19
  119. package/lib/tasks/requirements/docker/install.js +21 -7
  120. package/lib/tasks/requirements/docker/permissions.js +2 -11
  121. package/lib/tasks/requirements/docker/running-status.js +94 -24
  122. package/lib/tasks/requirements/docker/version.js +1 -0
  123. package/lib/tasks/requirements/index.js +0 -2
  124. package/lib/tasks/requirements/php-version.js +4 -2
  125. package/lib/tasks/start.js +27 -8
  126. package/lib/tasks/status/index.js +60 -21
  127. package/lib/tasks/stop.js +2 -0
  128. package/lib/tasks/theme/retrieve-theme-data.js +12 -2
  129. package/lib/util/config-file-validator.js +17 -3
  130. package/lib/util/execute-in-container.js +7 -8
  131. package/lib/util/instance-metadata.js +14 -2
  132. package/lib/util/systemctl.js +62 -13
  133. package/package.json +2 -2
  134. package/typings/context.d.ts +11 -0
  135. package/typings/index.d.ts +46 -1
  136. package/lib/tasks/requirements/dependency/arch.js +0 -50
  137. package/lib/tasks/requirements/dependency/centos.js +0 -36
  138. package/lib/tasks/requirements/dependency/fedora.js +0 -36
  139. package/lib/tasks/requirements/dependency/index.js +0 -33
  140. package/lib/tasks/requirements/dependency/mac.js +0 -124
  141. package/lib/tasks/requirements/dependency/ubuntu.js +0 -83
@@ -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,23 @@ 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
35
53
  } = ctx;
36
54
  const projectCreatedAt = getProjectCreatedAt();
37
- const composerVersion = await getComposerVersion(ctx);
38
55
 
39
56
  const prefix = getPrefix();
40
57
 
@@ -45,7 +62,7 @@ const prettyStatus = async (ctx) => {
45
62
  block
46
63
  .addHeader(`magento-scripts version: ${ logger.style.link(packageVersion) }`)
47
64
  .addEmptyLine()
48
- .addLine(`Project: ${logger.style.file(baseConfig.prefix)} ${prefix === folderName ? '(without prefix)' : '(with prefix)'} (with php container)`)
65
+ .addLine(`Project: ${logger.style.file(baseConfig.prefix)} ${prefix === folderName ? '(without prefix)' : '(with prefix)'} (with php container)${ projectConfig.debug ? ' (with debugging)' : '' }`)
49
66
  .addLine(`Project location: ${logger.style.link(process.cwd())}`);
50
67
 
51
68
  if (projectCreatedAt) {
@@ -71,19 +88,25 @@ const prettyStatus = async (ctx) => {
71
88
 
72
89
  let containerStatus;
73
90
 
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);
91
+ if (container.status && container.status.State && container.status.State.Health) {
92
+ containerStatus = `✓ ${ logger.style.file(container.status.State.Health.Status) } and ${ logger.style.file('running') }`;
93
+ } else if (container.status && container.status.State) {
94
+ containerStatus = logger.style.file(container.status.State.Status);
78
95
  } else {
79
96
  containerStatus = '✖ Not running';
80
97
  }
81
98
 
82
99
  block
83
100
  .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)}`);
101
+ .addLine(`Name: ${logger.style.misc(container.name)}`);
102
+
103
+ if (container.status && container.status.Config && container.status.Config.Image) {
104
+ block.addLine(`Image: ${logger.style.file(container.status.Config.Image)}`);
105
+ } else {
106
+ block.addLine(`Image: ${logger.style.file(container.image)}`);
107
+ }
108
+
109
+ block.addLine(`Network: ${logger.style.link(container.network)}`);
87
110
 
88
111
  if (!containerStatus.includes('Not running') && container.forwardedPorts && container.forwardedPorts.length > 0) {
89
112
  block.addLine('Port forwarding:');
@@ -100,9 +123,33 @@ const prettyStatus = async (ctx) => {
100
123
  if (container.env && Object.keys(container.env).length > 0) {
101
124
  block.addLine('Environment variables:');
102
125
  for (const [envName, envValue] of Object.entries(container.env)) {
103
- block.addLine(`${' '.repeat(3)} ${logger.style.misc(envName)}=${logger.style.file(envValue)}`);
126
+ if (isJSON(envValue)) {
127
+ const beautifyJSONLines = JSON.stringify(JSON.parse(envValue), null, 1).split('\n');
128
+
129
+ block.addLine(`${' '.repeat(3)} ${logger.style.misc(envName)}=${logger.style.file(beautifyJSONLines.shift())}`);
130
+
131
+ let currentOpeningBracket = 0;
132
+
133
+ beautifyJSONLines.forEach((line) => {
134
+ block.addLine(`${' '.repeat(2 + currentOpeningBracket)}${logger.style.file(line)}`);
135
+ if (['{', '['].some((openingBracketVariant) => line.includes(openingBracketVariant))) {
136
+ currentOpeningBracket++;
137
+ } else if (['}', ']'].some((closingBracketVariant) => line.includes(closingBracketVariant))) {
138
+ currentOpeningBracket--;
139
+ }
140
+ });
141
+ } else {
142
+ block.addLine(`${' '.repeat(3)} ${logger.style.misc(envName)}=${logger.style.file(envValue)}`);
143
+ }
104
144
  }
105
145
  }
146
+
147
+ if (container.description) {
148
+ block.addLine('Description:');
149
+ container.description.split('\n').forEach((line) => {
150
+ block.addLine(line);
151
+ });
152
+ }
106
153
  });
107
154
 
108
155
  const instanceMetadata = getInstanceMetadata(ctx);
@@ -123,14 +170,6 @@ const prettyStatus = async (ctx) => {
123
170
  instanceMetadata.admin.forEach(({ title, text }) => {
124
171
  block.addLine(` ${title}: ${text}`);
125
172
  });
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
173
 
135
174
  block.log();
136
175
  };
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
  /**
@@ -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.0",
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": "7df62ec60329e7e554b7d68a8ddb9c8a73510135"
58
58
  }
@@ -1,11 +1,14 @@
1
1
  import mysql2 from 'mysql2';
2
2
 
3
+ import { ProjectConfig } from '../lib/config/config';
4
+ import { DockerVersionResult } from '../lib/tasks/docker/api';
3
5
  import { CMAConfiguration, PHPExtensions } from './index';
4
6
  import { PHPStormConfig } from './phpstorm';
5
7
 
6
8
  export interface ListrContext {
7
9
  magentoVersion: string
8
10
  composerVersion: string
11
+ phpVersion: string
9
12
  port?: number
10
13
  ports?: {
11
14
  app: number
@@ -16,6 +19,8 @@ export interface ListrContext {
16
19
  elasticsearch: number
17
20
  varnish: number
18
21
  sslTerminator: number
22
+ maildevSMTP: number
23
+ maildevWeb: number
19
24
  }
20
25
  arch: 'arm64' | 'x64'
21
26
  isArm: boolean
@@ -67,6 +72,7 @@ export interface ListrContext {
67
72
  network: string
68
73
  image: string
69
74
  debugImage?: string
75
+ remoteImages?: string[]
70
76
  name: string
71
77
  command: string
72
78
  connectCommand: string[]
@@ -83,6 +89,7 @@ export interface ListrContext {
83
89
  userConfiguration: Omit<CMAConfiguration, 'prefix' | 'useNonOverlappingPorts'>
84
90
  nonOverridenConfiguration: Omit<CMAConfiguration, 'prefix' | 'useNonOverlappingPorts'>
85
91
  phpStorm: PHPStormConfig
92
+ projectConfig: ProjectConfig
86
93
  }
87
94
  systemConfiguration: {
88
95
  analytics: boolean
@@ -90,4 +97,8 @@ export interface ListrContext {
90
97
  }
91
98
  databaseConnection: mysql2.Connection
92
99
  isSetupUpgradeNeeded?: boolean
100
+ isDockerDesktop?: boolean
101
+ dockerServerData?: DockerVersionResult['Server']
102
+ dockerClientData?: DockerVersionResult['Client']
103
+ dockerVersion?: DockerVersionResult['Server']['Version']
93
104
  }
@@ -52,16 +52,53 @@ export interface VarnishConfiguration extends ServiceWithImage {
52
52
  * @example ./my-varnish-config.vcl
53
53
  */
54
54
  configTemplate: string
55
+
56
+ /**
57
+ * Enable or disable healthcheck in the project
58
+ */
59
+ healthCheck: boolean
55
60
  }
56
61
 
57
62
  export interface ComposerConfiguration {
58
63
  /**
59
64
  * Composer version
65
+ *
66
+ * This will become part of the url (`https://getcomposer.org/download/<version>/composer.phar`) so you can use the following variants as well:
67
+ * ```
68
+ * 'latest-stable'
69
+ * 'latest-preview'
70
+ * 'latest-1.x'
71
+ * 'latest-2.x'
72
+ * 'latest-2.2.x'
73
+ *
74
+ * '2.4.1'
75
+ * '2.3.10'
76
+ * '2.2.18'
77
+ * '2.1.14'
78
+ * ```
79
+ *
80
+ * @url https://getcomposer.org/download/
60
81
  */
61
82
  version: string
83
+
84
+ /**
85
+ * Composer global plugins that will be added to Docker image
86
+ */
87
+ plugins: Record<string, {
88
+ version?: string
89
+ options?: string
90
+ /**
91
+ * Enable composer plugin
92
+ */
93
+ enabled?: boolean
94
+ }>
62
95
  }
63
96
 
64
97
  export interface PHPExtensionInstallationInstruction {
98
+ /**
99
+ * Main extension name that will be used for `docker-php-ext-install` command
100
+ */
101
+ name?: string
65
102
  /**
66
103
  * Alternative name for extension
67
104
  *
@@ -80,7 +117,9 @@ export interface PHPExtensionInstallationInstruction {
80
117
  * pecl install xdebug && docker-php-ext-enable xdebug
81
118
  * ```
82
119
  */
83
- command: (arg0: (Omit<PHPExtensionInstallationInstruction, 'command'> & { ctx: ListrContext})) => string | string
120
+ command: string |
121
+ ((arg0: (Omit<PHPExtensionInstallationInstruction, 'command'> & { ctx: ListrContext})) => string) |
122
+ ((arg0: (Omit<PHPExtensionInstallationInstruction, 'command'> & { ctx: ListrContext})) => Promise<string>)
84
123
 
85
124
  /**
86
125
  * System dependencies required by the extension
@@ -118,6 +157,12 @@ export interface PHPConfiguration {
118
157
  * @example ./my-php-template.ini
119
158
  */
120
159
  configTemplate: string
160
+ /**
161
+ * PHP XDebug file template location
162
+ *
163
+ * @example ./my-php-debug-template.ini
164
+ */
165
+ debugTemplate: string
121
166
 
122
167
  /**
123
168
  * PHP-FPM configuration file template location
@@ -1,50 +0,0 @@
1
- const dependenciesForPlatforms = require('../../../config/dependencies-for-platforms');
2
- const UnknownError = require('../../../errors/unknown-error');
3
- const { execAsyncSpawn } = require('../../../util/exec-async-command');
4
- const installDependenciesTask = require('../../../util/install-dependencies-task');
5
-
6
- const pkgRegex = /(\S+)\s(\S+)/i;
7
-
8
- /**
9
- * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
10
- */
11
- const archDependenciesCheck = () => ({
12
- title: 'Checking Arch Linux dependencies',
13
- task: async (ctx, task) => {
14
- const installedDependencies = (await execAsyncSpawn('pacman -Q')).split('\n')
15
- .map((pkg) => {
16
- const result = pkg.match(pkgRegex);
17
-
18
- if (!result) {
19
- throw new UnknownError(`Package without a version!\n\n${pkg}\n\nHOW?`);
20
- }
21
-
22
- return result[1];
23
- });
24
-
25
- const dependenciesToInstall = dependenciesForPlatforms['Arch Linux']
26
- .dependencies
27
- .filter((dep) => {
28
- if (Array.isArray(dep)) {
29
- return !dep.some((dp) => installedDependencies.includes(dp));
30
- }
31
-
32
- return !installedDependencies.includes(dep);
33
- })
34
- .map((dep) => (Array.isArray(dep) ? dep[0] : dep));
35
-
36
- if (dependenciesToInstall.length > 0) {
37
- return task.newListr(
38
- installDependenciesTask({
39
- platform: 'Arch Linux',
40
- dependenciesToInstall
41
- })
42
- );
43
- }
44
- },
45
- options: {
46
- bottomBar: 10
47
- }
48
- });
49
-
50
- module.exports = archDependenciesCheck;
@@ -1,36 +0,0 @@
1
- const dependenciesForPlatforms = require('../../../config/dependencies-for-platforms');
2
- const { execAsyncSpawn } = require('../../../util/exec-async-command');
3
- const installDependenciesTask = require('../../../util/install-dependencies-task');
4
-
5
- /**
6
- * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
7
- */
8
- const centosDependenciesCheck = () => ({
9
- title: 'Checking CentOS dependencies',
10
- task: async (ctx, task) => {
11
- const installedDependencies = (await execAsyncSpawn('yum list installed')).split('\n')
12
- .filter((pkg) => !pkg.toLowerCase().includes('installed packages'))
13
- .map((pkg) => pkg.match(/^(\S+)/i))
14
- .filter(Boolean)
15
- .map((pkg) => pkg[1])
16
- .map((pkg) => pkg.match(/^(\S+)\.\S+/i))
17
- .filter(Boolean)
18
- .map((pkg) => pkg[1]);
19
-
20
- const dependenciesToInstall = dependenciesForPlatforms
21
- .CentOS
22
- .dependencies
23
- .filter((dep) => !installedDependencies.includes(dep));
24
-
25
- if (dependenciesToInstall.length > 0) {
26
- return task.newListr(
27
- installDependenciesTask({
28
- platform: 'CentOS',
29
- dependenciesToInstall
30
- })
31
- );
32
- }
33
- }
34
- });
35
-
36
- module.exports = centosDependenciesCheck;