@scandipwa/magento-scripts 1.13.0 → 1.13.4

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.
@@ -6,33 +6,46 @@ const executeInContainer = require('../tasks/execute');
6
6
  * @param {import('yargs')} yargs
7
7
  */
8
8
  module.exports = (yargs) => {
9
- yargs.command('exec <container name> [commands...]', 'Execute command in docker container', () => {}, async (argv) => {
10
- const containers = (await docker).getContainers();
11
- const services = Object.keys(containers);
9
+ yargs.command(
10
+ 'exec <container name> [commands...]',
11
+ 'Execute command in docker container',
12
+ (yargs) => {
13
+ yargs.usage(`Usage: npm run exec <container name> [commands...]
12
14
 
13
- if (services.includes(argv.containername) || services.some((service) => service.includes(argv.containername))) {
14
- const container = containers[argv.containername]
15
- ? containers[argv.containername]
16
- : Object.entries(containers).find(([key]) => key.includes(argv.containername))[1];
15
+ Available containers:
16
+ - mysql
17
+ - nginx
18
+ - redis
19
+ - elasticsearch`);
20
+ },
21
+ async (argv) => {
22
+ const containers = (await docker).getContainers();
23
+ const services = Object.keys(containers);
17
24
 
18
- if (argv.commands.length === 0) {
25
+ if (services.includes(argv.containername) || services.some((service) => service.includes(argv.containername))) {
26
+ const container = containers[argv.containername]
27
+ ? containers[argv.containername]
28
+ : Object.entries(containers).find(([key]) => key.includes(argv.containername))[1];
29
+
30
+ if (argv.commands.length === 0) {
19
31
  // if we have default connect command then use it
20
- if (container.connectCommand) {
32
+ if (container.connectCommand) {
21
33
  // eslint-disable-next-line no-param-reassign
22
- argv.commands = container.connectCommand;
23
- } else {
34
+ argv.commands = container.connectCommand;
35
+ } else {
24
36
  // otherwise fall back to bash (if it exists inside container)
25
- argv.commands.push('bash');
37
+ argv.commands.push('bash');
38
+ }
26
39
  }
40
+ await executeInContainer({
41
+ containerName: container.name,
42
+ commands: argv.commands
43
+ });
44
+
45
+ return;
27
46
  }
28
- await executeInContainer({
29
- containerName: container.name,
30
- commands: argv.commands
31
- });
32
47
 
33
- return;
48
+ logger.error(`No container found "${argv.containername}"`);
34
49
  }
35
-
36
- logger.error(`No container found "${argv.containername}"`);
37
- });
50
+ );
38
51
  };
@@ -10,6 +10,18 @@ module.exports = (yargs) => {
10
10
  'logs <scope>',
11
11
  'Display application logs.',
12
12
  (yargs) => {
13
+ yargs.usage(`Usage: npm run logs <scope>
14
+
15
+ Available scopes:
16
+ - magento
17
+ - mysql
18
+ - redis
19
+ - nginx
20
+ - elasticsearch
21
+
22
+ And you can use name matching:
23
+ npm run logs ma (will match magento)
24
+ npm run logs re (will match redis)`);
13
25
  yargs.option(
14
26
  'tail',
15
27
  {
@@ -91,7 +103,7 @@ module.exports = (yargs) => {
91
103
 
92
104
  return;
93
105
  }
94
-
106
+ console.log(argv);
95
107
  logger.error(`No service found "${argv.scope}"`);
96
108
  process.exit(1);
97
109
  }
@@ -95,12 +95,14 @@ module.exports = (yargs) => {
95
95
  systemConfiguration: { analytics }
96
96
  } = ctx;
97
97
 
98
+ const webLocation = `${ssl.enabled ? 'https' : 'http'}://${host}${ssl.enabled || ports.app === 80 ? '' : `:${ports.app}`}/`;
99
+
98
100
  const block = new ConsoleBlock();
99
101
  block
100
102
  .addHeader('Magento 2')
101
103
  .addEmptyLine()
102
- .addLine(`Web location: ${logger.style.link(`${ssl.enabled ? 'https' : 'http'}://${host}${ports.app === 80 ? '' : `:${ports.app}`}/`)}`)
103
- .addLine(`Magento Admin panel location: ${logger.style.link(`${ssl.enabled ? 'https' : 'http'}://${host}${ports.app === 80 ? '' : `:${ports.app}`}/${magentoConfiguration.adminuri}`)}`)
104
+ .addLine(`Web location: ${logger.style.link(webLocation)}`)
105
+ .addLine(`Magento Admin panel location: ${logger.style.link(`${webLocation}${magentoConfiguration.adminuri}`)}`)
104
106
  .addLine(`Magento Admin panel credentials: ${logger.style.misc(magentoConfiguration.user)} - ${logger.style.misc(magentoConfiguration.password)}`);
105
107
 
106
108
  const themes = await getCSAThemes();
@@ -130,7 +132,10 @@ module.exports = (yargs) => {
130
132
 
131
133
  block.log();
132
134
 
133
- logger.note(`MySQL credentials, containers status and project information available in ${logger.style.code('npm run status')} command.`);
135
+ logger.note(
136
+ `MySQL credentials, containers status and project information available in ${logger.style.code('npm run status')} command.
137
+ To access Magento CLI, Composer and PHP for this project use ${logger.style.code('npm run cli')} command.`
138
+ );
134
139
  logger.log('');
135
140
 
136
141
  if (!analytics) {
@@ -92,7 +92,8 @@ const dependenciesForPlatforms = {
92
92
  'php-cli',
93
93
  'php-bz2',
94
94
  'pkg-config',
95
- 'autoconf'
95
+ 'autoconf',
96
+ 'cmake'
96
97
  ],
97
98
  installCommand: (deps) => `sudo apt-get install ${deps} -y`
98
99
  }
@@ -5,6 +5,7 @@ const {
5
5
  uninstallMagento,
6
6
  removeMagento
7
7
  } = require('./magento');
8
+ const getMagentoVersionConfig = require('../config/get-magento-version-config');
8
9
  const { stopPhpFpm } = require('./php-fpm');
9
10
  const getProjectConfiguration = require('../config/get-project-configuration');
10
11
  const checkConfigurationFile = require('../config/check-configuration-file');
@@ -16,6 +17,7 @@ const cleanup = () => ({
16
17
  title: 'Cleanup project',
17
18
  task: (ctx, task) => task.newListr([
18
19
  checkConfigurationFile(),
20
+ getMagentoVersionConfig(),
19
21
  getProjectConfiguration(),
20
22
  stopPhpFpm(),
21
23
  stopServices(),
@@ -81,7 +81,7 @@ const enableMagentoComposerPlugins = () => ({
81
81
  const {
82
82
  config: {
83
83
  'allow-plugins': allowPlugins = {}
84
- }
84
+ } = {}
85
85
  } = composerJsonData;
86
86
  const allowPluginsKeys = Object.keys(allowPlugins);
87
87
 
@@ -110,7 +110,7 @@ Do you want to enable them all or disable some of them?`,
110
110
 
111
111
  if (userConfirmation) {
112
112
  composerJsonData.config = {
113
- ...composerJsonData.config,
113
+ ...(composerJsonData.config || {}),
114
114
  'allow-plugins': {
115
115
  ...allowPlugins,
116
116
  ...missingPlugins.reduce((acc, val) => ({ ...acc, [val]: true }), {})
@@ -141,7 +141,7 @@ Do you want to enable them all or disable some of them?`,
141
141
  const disabledPlugins = composerPlugins.filter((p) => !userEnabledPlugins.includes(p));
142
142
 
143
143
  composerJsonData.config = {
144
- ...composerJsonData.config,
144
+ ...(composerJsonData.config || {}),
145
145
  'allow-plugins': {
146
146
  ...allowPlugins,
147
147
  ...disabledPlugins.reduce((acc, val) => ({ ...acc, [val]: false }), {}),
@@ -37,29 +37,27 @@ const magentoFiles = [
37
37
  */
38
38
  const removeMagento = () => ({
39
39
  title: 'Remove magento application folder',
40
- task: async (ctx, task) => {
40
+ skip: async (ctx) => {
41
41
  const { config: { baseConfig } } = ctx;
42
42
  const appPathExists = await pathExists(baseConfig.magentoDir);
43
43
 
44
- if (appPathExists && ctx.force) {
45
- await Promise.all(magentoFiles.map(async (fileName) => {
46
- const filePath = path.join(baseConfig.magentoDir, fileName);
47
- const fileExists = await pathExists(filePath);
48
- if (!fileExists) {
49
- return;
50
- }
51
- const file = await fs.promises.stat(filePath);
52
- if (file.isFile()) {
53
- await fs.promises.unlink(filePath);
54
- } else if (file.isDirectory()) {
55
- await fs.promises.rmdir(filePath, { recursive: true });
56
- }
57
- }));
58
-
59
- return;
60
- }
61
-
62
- task.skip();
44
+ return !(appPathExists && ctx.force);
45
+ },
46
+ task: async (ctx) => {
47
+ const { config: { baseConfig } } = ctx;
48
+ await Promise.all(magentoFiles.map(async (fileName) => {
49
+ const filePath = path.join(baseConfig.magentoDir, fileName);
50
+ const fileExists = await pathExists(filePath);
51
+ if (!fileExists) {
52
+ return;
53
+ }
54
+ const file = await fs.promises.stat(filePath);
55
+ if (file.isFile()) {
56
+ await fs.promises.unlink(filePath);
57
+ } else if (file.isDirectory()) {
58
+ await fs.promises.rmdir(filePath, { recursive: true });
59
+ }
60
+ }));
63
61
  }
64
62
  });
65
63
 
@@ -1,8 +1,11 @@
1
+ const { isTableExists } = require('../../../util/database');
2
+
1
3
  /**
2
4
  * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
3
5
  */
4
6
  const adjustMagentoConfiguration = () => ({
5
7
  title: 'Adjusting Magento Database Configuration',
8
+ skip: async (ctx) => !(await isTableExists('magento', 'core_config_data', ctx)),
6
9
  task: async (ctx) => {
7
10
  const { mysqlConnection } = ctx;
8
11
 
@@ -1,10 +1,11 @@
1
- const { updateTableValues } = require('../../../util/database');
1
+ const { updateTableValues, isTableExists } = require('../../../util/database');
2
2
 
3
3
  /**
4
4
  * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
5
5
  */
6
6
  module.exports = () => ({
7
7
  title: 'Configuring elasticsearch',
8
+ skip: async (ctx) => !(await isTableExists('magento', 'core_config_data', ctx)),
8
9
  task: async ({ ports, mysqlConnection }, task) => {
9
10
  await updateTableValues('core_config_data', [
10
11
  { path: 'catalog/search/engine', value: 'elasticsearch7' },
@@ -1,8 +1,11 @@
1
+ const { isTableExists } = require('../../../util/database');
2
+
1
3
  /**
2
4
  * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
3
5
  */
4
6
  const deleteAdminUsers = () => ({
5
7
  title: 'Deleting old admin users',
8
+ skip: async (ctx) => !(await isTableExists('magento', 'admin_user', ctx)),
6
9
  task: async (ctx) => {
7
10
  const { mysqlConnection } = ctx;
8
11
  await mysqlConnection.query(`
@@ -2,11 +2,14 @@ const semver = require('semver');
2
2
  const runMagentoCommand = require('../../../util/run-magento');
3
3
 
4
4
  /**
5
- * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
5
+ * @type {({ isDbEmpty }: { isDbEmpty: boolean }) => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
6
6
  */
7
- const installMagento = () => ({
8
- title: 'Installing magento...',
7
+ const installMagento = ({ isDbEmpty = false } = {}) => ({
8
+ title: 'Installing magento',
9
9
  task: async (ctx, task) => {
10
+ if (isDbEmpty) {
11
+ task.output = 'No Magento is installed in DB!\nInstalling...';
12
+ }
10
13
  const {
11
14
  magentoVersion,
12
15
  config: {
@@ -18,22 +18,20 @@ const migrateDatabase = (options = {}) => ({
18
18
  } = ctx;
19
19
 
20
20
  const [[{ tableCount }]] = await mysqlConnection.query(`
21
- SELECT count (*) AS tableCount
21
+ SELECT count(*) AS tableCount
22
22
  FROM INFORMATION_SCHEMA.TABLES
23
23
  WHERE TABLE_SCHEMA = 'magento';
24
24
  `);
25
25
 
26
26
  if (tableCount === 0) {
27
- task.output = 'No Magento is installed in DB!\nInstalling...';
28
-
29
27
  if (options.onlyInstallMagento) {
30
28
  return task.newListr(
31
- installMagento()
29
+ installMagento({ isDbEmpty: true })
32
30
  );
33
31
  }
34
32
 
35
33
  return task.newListr([
36
- installMagento(),
34
+ installMagento({ isDbEmpty: true }),
37
35
  setupPersistedQuery(),
38
36
  upgradeMagento(),
39
37
  magentoTask('cache:enable'),
@@ -11,11 +11,11 @@ module.exports = () => ({
11
11
  config: { overridenConfiguration: { host, ssl } },
12
12
  mysqlConnection
13
13
  } = ctx;
14
+ const enableSecureFrontend = ssl.enabled ? '1' : '0';
14
15
  const location = `${host}${ ports.app !== 80 ? `:${ports.app}` : '' }/`;
16
+ const secureLocation = `${host}/`; // SSL will work only on port 443, so you cannot run multiple projects with SSL at the same time.
15
17
  const httpUrl = `http://${location}`;
16
- const httpsUrl = `https://${location}`;
17
-
18
- const enableSecureFrontend = ssl.enabled ? '1' : '0';
18
+ const httpsUrl = `https://${secureLocation}`;
19
19
 
20
20
  await updateTableValues('core_config_data', [
21
21
  { path: 'web/unsecure/base_url', value: httpUrl },
@@ -7,6 +7,7 @@ const sleep = require('../../util/sleep');
7
7
  */
8
8
  const connectToMySQL = () => ({
9
9
  title: 'Connecting to MySQL server...',
10
+ skip: (ctx) => ctx.skipSetup,
10
11
  task: async (ctx, task) => {
11
12
  const { config: { docker }, ports } = ctx;
12
13
  const { mysql: { env, name } } = docker.getContainers();
@@ -27,7 +28,7 @@ Please wait, this will take some time and do not restart the MySQL container unt
27
28
  }
28
29
  try {
29
30
  const connection = await mysql.createConnection({
30
- host: 'localhost',
31
+ host: '127.0.0.1',
31
32
  port: ports.mysql,
32
33
  user: env.MYSQL_USER,
33
34
  password: env.MYSQL_PASSWORD,
@@ -1,21 +1,13 @@
1
+ const { isTableExists } = require('../../util/database');
2
+
1
3
  /**
2
4
  * @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
3
5
  */
4
6
  const dumpThemeConfig = () => ({
5
7
  title: 'Dumping themes and theme configuration',
6
- task: async (ctx) => {
8
+ task: async (ctx, task) => {
7
9
  const { mysqlConnection } = ctx;
8
-
9
- /**
10
- * @type {{ tableCount: number }[][]}
11
- */
12
- const [[{ tableCount }]] = await mysqlConnection.query(`
13
- SELECT count (*) AS tableCount
14
- FROM INFORMATION_SCHEMA.TABLES
15
- WHERE TABLE_SCHEMA = 'magento';
16
- `);
17
-
18
- if (tableCount !== 0) {
10
+ if (await isTableExists('magento', 'theme', ctx)) {
19
11
  const [themes] = await mysqlConnection.query('select * from theme;');
20
12
  if (themes.length === 0) {
21
13
  ctx.themeDump = {
@@ -24,15 +16,19 @@ const dumpThemeConfig = () => ({
24
16
  };
25
17
  }
26
18
 
27
- const [themeIdConfig] = await mysqlConnection.query('select * from core_config_data where path = \'design/theme/theme_id\';');
28
- if (themeIdConfig.length !== 0) {
29
- ctx.themeDump = {
30
- themes,
31
- themeIdConfig: themeIdConfig[0]
32
- };
19
+ if (await isTableExists('magento', 'core_config_data', ctx)) {
20
+ const [themeIdConfig] = await mysqlConnection.query('select * from core_config_data where path = \'design/theme/theme_id\';');
21
+ if (themeIdConfig.length !== 0) {
22
+ ctx.themeDump = {
23
+ themes,
24
+ themeIdConfig: themeIdConfig[0]
25
+ };
33
26
 
34
- return;
27
+ return;
28
+ }
35
29
  }
30
+ } else {
31
+ task.skip();
36
32
  }
37
33
 
38
34
  ctx.themeDump = {
@@ -1,9 +1,31 @@
1
+ const logger = require('@scandipwa/scandipwa-dev-utils/logger');
2
+ const os = require('os');
1
3
  const dependenciesForPlatforms = require('../../../config/dependencies-for-platforms');
2
- const { execAsyncSpawn } = require('../../../util/exec-async-command');
4
+ const { execAsyncSpawn, execCommandTask } = require('../../../util/exec-async-command');
3
5
  const installDependenciesTask = require('../../../util/install-dependencies-task');
4
6
 
5
7
  const pkgRegex = /^(\S+)\/\S+\s(\S+)\s\S+\s\S+$/i;
6
8
 
9
+ const updateSystem = () => ({
10
+ title: 'Updating Ubuntu system',
11
+ task: async (ctx, task) => {
12
+ task.output = 'Enter your sudo password!';
13
+ task.output = logger.style.command(`>[sudo] password for ${ os.userInfo().username }:`);
14
+
15
+ return task.newListr(
16
+ execCommandTask('sudo apt update', {
17
+ callback: (t) => {
18
+ task.output = t;
19
+ },
20
+ pipeInput: true
21
+ })
22
+ );
23
+ },
24
+ options: {
25
+ bottomBar: 10
26
+ }
27
+ });
28
+
7
29
  /**
8
30
  * @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
9
31
  */
@@ -28,6 +50,23 @@ const ubuntuDependenciesCheck = () => ({
28
50
  .map((dep) => (Array.isArray(dep) ? dep[0] : dep));
29
51
 
30
52
  if (dependenciesToInstall.length > 0) {
53
+ const runSystemUpdate = await task.prompt({
54
+ type: 'Confirm',
55
+ message: `Would you like to run ${logger.style.command('apt update')} before installing missing ${dependenciesToInstall.length} dependenc${dependenciesToInstall.length > 1 ? 'ies' : 'y'}?`
56
+ });
57
+
58
+ if (runSystemUpdate) {
59
+ return task.newListr([
60
+ updateSystem(),
61
+ installDependenciesTask({
62
+ platform: 'Ubuntu',
63
+ dependenciesToInstall
64
+ })
65
+ ], {
66
+ concurrent: false
67
+ });
68
+ }
69
+
31
70
  return task.newListr(
32
71
  installDependenciesTask({
33
72
  platform: 'Ubuntu',
@@ -99,9 +99,9 @@ const checkPHPVersion = () => ({
99
99
  task: async (ctx, task) => {
100
100
  const phpVersionResponse = await execAsyncSpawn('php --version');
101
101
 
102
- const phpVersionResponseResult = phpVersionResponse.match(/^PHP\s(\d\.\d\.\d)/i);
102
+ const phpVersionResponseResult = phpVersionResponse.match(/PHP\s(\d\.\d\.\d)/i);
103
103
 
104
- if (phpVersionResponseResult.length > 0) {
104
+ if (phpVersionResponseResult && phpVersionResponseResult.length > 0) {
105
105
  const phpVersion = phpVersionResponseResult[1];
106
106
 
107
107
  if (semver.satisfies(phpVersion, '>=8.1.x')) {
@@ -27,6 +27,8 @@ const pkg = require('../../package.json');
27
27
  const checkConfigurationFile = require('../config/check-configuration-file');
28
28
  const convertLegacyVolumes = require('./docker/convert-legacy-volumes');
29
29
  const enableMagentoComposerPlugins = require('./magento/enable-magento-composer-plugins');
30
+ const getIsWsl = require('../util/is-wsl');
31
+ const checkForXDGOpen = require('../util/xdg-open-exists');
30
32
 
31
33
  /**
32
34
  * @type {() => import('listr2').ListrTask<import('../../typings/context').ListrContext>}
@@ -172,9 +174,23 @@ const start = () => ({
172
174
  finishProjectConfiguration(),
173
175
  {
174
176
  title: 'Opening browser',
175
- skip: (ctx) => ctx.noOpen,
177
+ skip: async (ctx) => {
178
+ if (ctx.noOpen) {
179
+ return true;
180
+ }
181
+
182
+ if (await getIsWsl()) {
183
+ const canOpenBrowser = await checkForXDGOpen();
184
+
185
+ if (!canOpenBrowser) {
186
+ return 'Cannot open the browser, xdg-open is not available.';
187
+ }
188
+ }
189
+
190
+ return false;
191
+ },
176
192
  task: ({ ports, config: { overridenConfiguration: { host, ssl } } }) => {
177
- openBrowser(`${ssl.enabled ? 'https' : 'http'}://${host}${ports.app === 80 ? '' : `:${ports.app}`}/`);
193
+ openBrowser(`${ssl.enabled ? 'https' : 'http'}://${host}${ssl.enabled || ports.app === 80 ? '' : `:${ports.app}`}/`);
178
194
  },
179
195
  options: {
180
196
  showTimer: false
@@ -2,7 +2,7 @@
2
2
  * Update table in **magento** database
3
3
  * @param {String} table Table name
4
4
  * @param {{path: string, value: string}[]} values
5
- * @param {Object} param1
5
+ * @param {import('../../typings/context').ListrContext} param1
6
6
  */
7
7
  const updateTableValues = async (table, values, { mysqlConnection, task }) => {
8
8
  const [rows] = await mysqlConnection.query(`
@@ -58,6 +58,25 @@ const updateTableValues = async (table, values, { mysqlConnection, task }) => {
58
58
  }
59
59
  };
60
60
 
61
+ /**
62
+ * @param {String} database
63
+ * @param {String} tableName
64
+ * @param {import('../../typings/context').ListrContext} param2
65
+ */
66
+ const isTableExists = async (database, tableName, { mysqlConnection }) => {
67
+ /**
68
+ * @type {{ tableCount: number }[][]}
69
+ */
70
+ const [[{ tableCount }]] = await mysqlConnection.query(`
71
+ SELECT count(*) as tableCount
72
+ FROM information_schema.TABLES
73
+ WHERE (TABLE_SCHEMA = ?) AND (TABLE_NAME = ?);
74
+ `, [database, tableName]);
75
+
76
+ return tableCount > 0;
77
+ };
78
+
61
79
  module.exports = {
62
- updateTableValues
80
+ updateTableValues,
81
+ isTableExists
63
82
  };
@@ -2,7 +2,8 @@ const { execAsync } = require('./exec-async-command');
2
2
 
3
3
  const openBrowser = async (url) => {
4
4
  const start = process.platform === 'darwin' ? 'open' : 'xdg-open';
5
- await execAsync(`${start } ${ url}`);
5
+
6
+ await execAsync(`${ start } ${ url }`);
6
7
  };
7
8
 
8
9
  module.exports = openBrowser;
@@ -0,0 +1,27 @@
1
+ const fs = require('fs');
2
+ const pathExists = require('./path-exists');
3
+
4
+ const checkForXDGOpen = async () => {
5
+ const pathParts = process.env.PATH.split(':');
6
+
7
+ const results = await Promise.all(
8
+ pathParts.map(
9
+ async (pathPart) => {
10
+ if (!await pathExists(pathPart)) {
11
+ return false;
12
+ }
13
+
14
+ const files = await fs.promises.readdir(pathPart, {
15
+ encoding: 'utf-8',
16
+ withFileTypes: true
17
+ });
18
+
19
+ return files.some((file) => file.isFile() && file.name === 'xdg-open');
20
+ }
21
+ )
22
+ );
23
+
24
+ return results.includes(true);
25
+ };
26
+
27
+ module.exports = checkForXDGOpen;
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": "1.13.0",
6
+ "version": "1.13.4",
7
7
  "main": "./index.js",
8
8
  "types": "./typings/index.d.ts",
9
9
  "license": "OSL-3.0",
@@ -42,5 +42,5 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "gitHead": "ea9caf4db8672b0cf197e49cd4c9002eea84a113"
45
+ "gitHead": "fa0d2c77e7d3a8c639cbebeef05b1322b20895f4"
46
46
  }
@@ -1,3 +1,5 @@
1
+ import mysql2 from 'mysql2';
2
+
1
3
  import { CMAConfiguration, PHPExtensions } from './index';
2
4
 
3
5
  export interface ListrContext {
@@ -85,4 +87,5 @@ export interface ListrContext {
85
87
  analytics: boolean
86
88
  useNonOverlappingPorts: boolean
87
89
  }
90
+ mysqlConnection: mysql2.Connection
88
91
  }