mysqlsyncr 1.1.10 → 1.1.12

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.
package/README.md CHANGED
@@ -1,186 +1,187 @@
1
- # MySQLSyncr
2
-
3
- Warning: Please be careful when using this tool. It is still in development and may not be fully stable. Test on a development database before using on production.
4
-
5
- MySQLSyncr is a command-line tool for managing and comparing MySQL database structures with JSON dumps. It allows users to dump the database structure, compare it with existing JSON files, and update the database based on those JSON definitions.
6
-
7
- ## Table of Contents
8
-
9
- - [Features](#features)
10
- - [Installation](#installation)
11
- - [Global Installation](#global-installation)
12
- - [Local Installation](#local-installation)
13
- - [Usage](#usage)
14
- - [Commands](#commands)
15
- - [Configuration Options](#configuration-options)
16
- - [Using MySQLSyncr as a Module](#using-mysqlsyncr-as-a-module)
17
- - [Contributing](#contributing)
18
- - [License](#license)
19
-
20
- ## Features
21
-
22
- - **Dump**: Export the database structure to JSON files.
23
- - **Compare**: Compare the current database structure with JSON dumps to identify differences.
24
- - **Update**: Update the database structure based on the provided JSON definitions.
25
- - **UI**: Open a web-based database browser interface.
26
- - **Verbose Logging**: Enable detailed logging for debugging purposes.
27
-
28
- ![Database Browser Interface](view.png)
29
-
30
- ## Installation
31
-
32
- ### Global Installation
33
-
34
- To install MySQLSync globally, allowing you to use it from the command line, run the following command:
35
-
36
- ```bash
37
- npm install -g mysqlsyncr
38
- ```
39
-
40
- This will allow you to run the command as `mysqlsyncr` from anywhere in your terminal.
41
-
42
- ### Local Installation
43
-
44
- If you prefer to use MySQLSyncr locally within a project, you can install it as a dependency:
45
-
46
- ```bash
47
- npm install mysqlsyncr
48
- ```
49
-
50
- This will add MySQLSyncr to your project's `node_modules` and allow you to use it within your project.
51
-
52
- ## Usage
53
-
54
- You can run MySQLSync commands using the following syntax:
55
-
56
- ```bash
57
- mysqlsyncr <command> [options]
58
- ```
59
-
60
- ### Commands
61
-
62
- - `dump`: Dumps the database structure to files.
63
- - `compare`: Compares the database structure with JSON dumps (dry run).
64
- - `update`: Updates the database structure based on JSON dumps.
65
- - `ui`: Opens a web-based database browser in your default system browser.
66
-
67
- ### Configuration Options
68
-
69
- You can configure the following options when running the commands:
70
-
71
- | Option | Alias | Description | Default Value |
72
- |-------------|-------|-----------------------------------------------------------------------------|--------------------------------|
73
- | `uiPort` | `-U` | UI port | `3600` |
74
- | `openUI` | `-O` | Open UI in default browser (boolean) | `true` |
75
- | `host` | `-h` | Database host | `localhost` |
76
- | `port` | `-P` | Database port | `3306` |
77
- | `user` | `-u` | Database user | `root` |
78
- | `password` | `-p` | Database password (required) | |
79
- | `database` | `-d` | Target database | `null` |
80
- | `output` | `-o` | Output directory for dumping. Default is one level up from the current directory in a new folder called `db-dump` | `../db-dump` |
81
- | `verbose` | `-v` | Enable verbose logging (boolean) | `false` |
82
-
83
- ### Example Usage
84
-
85
- 1. **Dump the database structure**:
86
- ```bash
87
- mysqlsyncr dump --host localhost --user root --password yourpassword
88
- ```
89
-
90
- 2. **Compare the database structure with JSON dumps**:
91
- ```bash
92
- mysqlsyncr compare --host localhost --user root --password yourpassword
93
- ```
94
-
95
- 3. **Update the database structure based on JSON dumps**:
96
- ```bash
97
- mysqlsyncr update --host localhost --user root --password yourpassword
98
- ```
99
-
100
- 4. **Open the database browser interface**:
101
- ```bash
102
- mysqlsyncr ui --host localhost --user root --password yourpassword
103
- ```
104
-
105
- ## Using MySQLSync as a Module
106
-
107
- If you want to use MySQLSync as a module in your own Node.js application, you can require it in your code:
108
-
109
- ```javascript
110
- import mysqlsyncr from 'mysqlsyncr';
111
-
112
- // Example usage
113
- const config = {
114
- host: 'localhost',
115
- user: 'root',
116
- password: 'yourpassword',
117
- database: 'yourdatabase'
118
- };
119
- ```
120
-
121
- ```javascript
122
- // app.js
123
- import mysqlsyncr from 'mysqlsyncr';
124
- import fs from 'fs';
125
- import path from 'path';
126
-
127
- // Database configuration
128
- const config = {
129
- host: 'localhost',
130
- user: 'root',
131
- password: 'yourpassword',
132
- database: 'yourdatabase'
133
- };
134
-
135
- // Function to dump the database structure
136
- async function dumpDatabase() {
137
- try {
138
- console.log('Dumping the database structure...');
139
- await mysqlsyncr.dump(config);
140
- console.log('Database structure dumped successfully.');
141
- } catch (error) {
142
- console.error('Error dumping database:', error.message);
143
- }
144
- }
145
-
146
- // Function to compare the database structure with JSON dumps
147
- async function compareDatabase() {
148
- try {
149
- const inputDir = path.join(__dirname, 'db-dump'); // Directory where JSON dumps are stored
150
- console.log('Comparing the database structure with JSON dumps...');
151
- const differences = await mysqlsyncr.compare(config, inputDir);
152
-
153
- if (differences.length > 0) {
154
- console.log('Differences found:');
155
- console.log(differences);
156
- } else {
157
- console.log('No differences found. The database structure matches the JSON dumps.');
158
- }
159
- } catch (error) {
160
- console.error('Error comparing database:', error.message);
161
- }
162
- }
163
-
164
- // Main function to execute dump and compare
165
- (async () => {
166
- await dumpDatabase();
167
- await compareDatabase();
168
- })();
169
- ```
170
-
171
- Make sure to check the source code for available functions and their usage.
172
-
173
- ## Contributing
174
-
175
- Contributions are welcome! If you would like to contribute to MySQLSyncr, please follow these steps:
176
-
177
- 1. Fork the repository.
178
- 2. Create a new branch for your feature or bug fix.
179
- 3. Make your changes and commit them with clear messages.
180
- 4. Push your changes to your forked repository.
181
- 5. Open a pull request to the main repository.
182
-
183
-
184
- ## License
185
-
186
- This project is licensed under the ISC License. See the [LICENSE](LICENSE) file for more details.
1
+ # MySQLSyncr
2
+
3
+ Warning: Please be careful when using this tool. It is still in development and may not be fully stable. Test on a development database before using on production.
4
+
5
+ MySQLSyncr is a command-line tool for managing and comparing MySQL database structures with JSON dumps. It allows users to dump the database structure, compare it with existing JSON files, and update the database based on those JSON definitions.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Features](#features)
10
+ - [Installation](#installation)
11
+ - [Global Installation](#global-installation)
12
+ - [Local Installation](#local-installation)
13
+ - [Usage](#usage)
14
+ - [Commands](#commands)
15
+ - [Configuration Options](#configuration-options)
16
+ - [Using MySQLSyncr as a Module](#using-mysqlsyncr-as-a-module)
17
+ - [Contributing](#contributing)
18
+ - [License](#license)
19
+
20
+ ## Features
21
+
22
+ - **Dump**: Export the database structure to JSON files.
23
+ - **Compare**: Compare the current database structure with JSON dumps to identify differences.
24
+ - **Update**: Update the database structure based on the provided JSON definitions.
25
+ - **UI**: Open a web-based database browser interface.
26
+ - **Verbose Logging**: Enable detailed logging for debugging purposes.
27
+
28
+ ![Database Browser Interface](view.png)
29
+
30
+ ## Installation
31
+
32
+ ### Global Installation
33
+
34
+ To install MySQLSync globally, allowing you to use it from the command line, run the following command:
35
+
36
+ ```bash
37
+ npm install -g mysqlsyncr
38
+ ```
39
+
40
+ This will allow you to run the command as `mysqlsyncr` from anywhere in your terminal.
41
+
42
+ ### Local Installation
43
+
44
+ If you prefer to use MySQLSyncr locally within a project, you can install it as a dependency:
45
+
46
+ ```bash
47
+ npm install mysqlsyncr
48
+ ```
49
+
50
+ This will add MySQLSyncr to your project's `node_modules` and allow you to use it within your project.
51
+
52
+ ## Usage
53
+
54
+ You can run MySQLSync commands using the following syntax:
55
+
56
+ ```bash
57
+ mysqlsyncr <command> [options]
58
+ ```
59
+
60
+ ### Commands
61
+
62
+ - `dump`: Dumps the database structure to files.
63
+ - `compare`: Compares the database structure with JSON dumps (dry run).
64
+ - `update`: Updates the database structure based on JSON dumps.
65
+ - `ui`: Opens a web-based database browser in your default system browser.
66
+
67
+ ### Configuration Options
68
+
69
+ You can configure the following options when running the commands:
70
+
71
+ | Option | Alias | Description | Default Value |
72
+ |-------------|-------|-----------------------------------------------------------------------------|--------------------------------|
73
+ | `uiPort` | `-U` | UI port | `3600` |
74
+ | `openUI` | `-O` | Open UI in default browser (boolean) | `true` |
75
+ | `host` | `-h` | Database host | `localhost` |
76
+ | `port` | `-P` | Database port | `3306` |
77
+ | `user` | `-u` | Database user | `root` |
78
+ | `password` | `-p` | Database password (required) | |
79
+ | `database` | `-d` | Target database | `null` |
80
+ | `output` | `-o` | Output directory for dumping. Default is one level up from the current directory in a new folder called `db-dump` | `../db-dump` |
81
+ | `verbose` | `-v` | Enable verbose logging (boolean) | `false` |
82
+
83
+ ### Example Usage
84
+
85
+ 1. **Dump the database structure**:
86
+ ```bash
87
+ mysqlsyncr dump --host localhost --user root --password yourpassword
88
+ ```
89
+
90
+ 2. **Compare the database structure with JSON dumps**:
91
+ ```bash
92
+ mysqlsyncr compare --host localhost --user root --password yourpassword
93
+ ```
94
+
95
+ 3. **Update the database structure based on JSON dumps**:
96
+ ```bash
97
+ mysqlsyncr update --host localhost --user root --password yourpassword
98
+ ```
99
+
100
+ 4. **Open the database browser interface**:
101
+ *Note: This does not work with PowerShell. Must use Command Prompt in windows*
102
+ ```bash
103
+ mysqlsyncr ui --host localhost --user root --password yourpassword
104
+ ```
105
+
106
+ ## Using MySQLSync as a Module
107
+
108
+ If you want to use MySQLSync as a module in your own Node.js application, you can require it in your code:
109
+
110
+ ```javascript
111
+ import mysqlsyncr from 'mysqlsyncr';
112
+
113
+ // Example usage
114
+ const config = {
115
+ host: 'localhost',
116
+ user: 'root',
117
+ password: 'yourpassword',
118
+ database: 'yourdatabase'
119
+ };
120
+ ```
121
+
122
+ ```javascript
123
+ // app.js
124
+ import mysqlsyncr from 'mysqlsyncr';
125
+ import fs from 'fs';
126
+ import path from 'path';
127
+
128
+ // Database configuration
129
+ const config = {
130
+ host: 'localhost',
131
+ user: 'root',
132
+ password: 'yourpassword',
133
+ database: 'yourdatabase'
134
+ };
135
+
136
+ // Function to dump the database structure
137
+ async function dumpDatabase() {
138
+ try {
139
+ console.log('Dumping the database structure...');
140
+ await mysqlsyncr.dump(config);
141
+ console.log('Database structure dumped successfully.');
142
+ } catch (error) {
143
+ console.error('Error dumping database:', error.message);
144
+ }
145
+ }
146
+
147
+ // Function to compare the database structure with JSON dumps
148
+ async function compareDatabase() {
149
+ try {
150
+ const inputDir = path.join(__dirname, 'db-dump'); // Directory where JSON dumps are stored
151
+ console.log('Comparing the database structure with JSON dumps...');
152
+ const differences = await mysqlsyncr.compare(config, inputDir);
153
+
154
+ if (differences.length > 0) {
155
+ console.log('Differences found:');
156
+ console.log(differences);
157
+ } else {
158
+ console.log('No differences found. The database structure matches the JSON dumps.');
159
+ }
160
+ } catch (error) {
161
+ console.error('Error comparing database:', error.message);
162
+ }
163
+ }
164
+
165
+ // Main function to execute dump and compare
166
+ (async () => {
167
+ await dumpDatabase();
168
+ await compareDatabase();
169
+ })();
170
+ ```
171
+
172
+ Make sure to check the source code for available functions and their usage.
173
+
174
+ ## Contributing
175
+
176
+ Contributions are welcome! If you would like to contribute to MySQLSyncr, please follow these steps:
177
+
178
+ 1. Fork the repository.
179
+ 2. Create a new branch for your feature or bug fix.
180
+ 3. Make your changes and commit them with clear messages.
181
+ 4. Push your changes to your forked repository.
182
+ 5. Open a pull request to the main repository.
183
+
184
+
185
+ ## License
186
+
187
+ This project is licensed under the ISC License. See the [LICENSE](LICENSE) file for more details.
package/dist/index.cjs CHANGED
@@ -2560,7 +2560,11 @@ var parseCreateTableSQL = function parseCreateTableSQL(createTableSQL) {
2560
2560
  var columnRegex = /`([^`]+)`\s+([^\s,]+)(\s+NOT NULL|\s+NULL)?(\s+DEFAULT\s+([^,\s]+))?(\s+AUTO_INCREMENT)?/;
2561
2561
 
2562
2562
  // Regular expression to match index definitions
2563
- var indexRegex = /(PRIMARY|UNIQUE)?\s*KEY\s*`([^`]+)`\s*\(([^)]+)\)|PRIMARY KEY\s*\(([^)]+)\)/;
2563
+ var indexRegex_Old = /(PRIMARY|UNIQUE)?\s*KEY\s*`([^`]+)`\s*\(([^)]+)\)|PRIMARY KEY\s*\(([^)]+)\)/;
2564
+
2565
+ // Updated to support indexes for text fields
2566
+ // 'KEY `idx_e2alarms_alarmstring` (`alarmString`(255))' -- would cut off the final bracket and wouldnt work.
2567
+ var indexRegex = /(PRIMARY|UNIQUE)?\s*KEY\s*`([^`]+)`\s*\(((?:`[^`]+`(?:\(\d+\))?(?:\s*,\s*)?)+)\)|PRIMARY KEY\s*\(((?:`[^`]+`(?:\(\d+\))?(?:\s*,\s*)?)+)\)/;
2564
2568
 
2565
2569
  // Regular expression to match table options (ENGINE, CHARSET, COLLATE)
2566
2570
  var optionsRegex = /ENGINE=(\w+)\s+DEFAULT\s+CHARSET=(\w+)(\s+COLLATE=(\w+))?/;
@@ -2577,6 +2581,7 @@ var parseCreateTableSQL = function parseCreateTableSQL(createTableSQL) {
2577
2581
  // Check if the line contains a column definition
2578
2582
  var columnMatch = columnRegex.exec(line);
2579
2583
  var indexMatch = indexRegex.exec(line);
2584
+ var indexMatch_Old = indexRegex_Old.exec(line);
2580
2585
  var constraintMatch = parseConstraint(line);
2581
2586
  if (columnMatch && !indexMatch && !constraintMatch) {
2582
2587
  var columnType = parseColumnType(line);
@@ -3798,7 +3803,8 @@ var applyDifferences = /*#__PURE__*/function () {
3798
3803
  return col.Field;
3799
3804
  }); // Check if all columns for the index exist
3800
3805
  missingColumns = Array.isArray(diff.index.ColumnName) ? diff.index.ColumnName.filter(function (col) {
3801
- return !columnNames.includes(col);
3806
+ var _col$split;
3807
+ return !columnNames.includes(col) && !columnNames.includes((_col$split = col.split("(")) === null || _col$split === undefined ? undefined : _col$split[0]);
3802
3808
  }) : [];
3803
3809
  if (!(missingColumns.length > 0)) {
3804
3810
  _context.next = 72;
@@ -3809,9 +3815,19 @@ var applyDifferences = /*#__PURE__*/function () {
3809
3815
  case 72:
3810
3816
  // Prepare the index columns with proper formatting
3811
3817
  indexColumns = diff.index.ColumnName.map(function (col) {
3812
- return "`".concat(col, "`");
3813
- }); // Format column names
3814
- // Handle PRIMARY index creation
3818
+ if (col.includes("(")) {
3819
+ var match = col.match(/^(?:`([^`]+)`|([A-Za-z_][A-Za-z0-9_\$]*))\((\d+)\)$/);
3820
+ if (match) {
3821
+ var name = match[1] || match[2]; // one of them will be filled
3822
+ var size = match[3];
3823
+ console.log(name, size);
3824
+ return "`".concat(name, "`(").concat(size, ")");
3825
+ }
3826
+ return "`".concat(col.split("(")[0], "`");
3827
+ } else {
3828
+ return "`".concat(col, "`"); // Format column names
3829
+ }
3830
+ }); // Handle PRIMARY index creation
3815
3831
  if (!(diff.index.Name === 'PRIMARY')) {
3816
3832
  _context.next = 84;
3817
3833
  break;
@@ -5449,10 +5465,8 @@ var apply = /*#__PURE__*/function () {
5449
5465
  // Only run this if this is the main module
5450
5466
  var isMain = function () {
5451
5467
  try {
5452
- // console.log('Checking if this is the main module');
5453
- // console.log(require.main === module)
5454
- // console.log(require.main);
5455
- return require.main === module;
5468
+ var modulePath = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
5469
+ return process.argv[1] === modulePath;
5456
5470
  } catch (e) {
5457
5471
  return false;
5458
5472
  }
package/dist/index.js CHANGED
@@ -2557,7 +2557,11 @@ var parseCreateTableSQL = function parseCreateTableSQL(createTableSQL) {
2557
2557
  var columnRegex = /`([^`]+)`\s+([^\s,]+)(\s+NOT NULL|\s+NULL)?(\s+DEFAULT\s+([^,\s]+))?(\s+AUTO_INCREMENT)?/;
2558
2558
 
2559
2559
  // Regular expression to match index definitions
2560
- var indexRegex = /(PRIMARY|UNIQUE)?\s*KEY\s*`([^`]+)`\s*\(([^)]+)\)|PRIMARY KEY\s*\(([^)]+)\)/;
2560
+ var indexRegex_Old = /(PRIMARY|UNIQUE)?\s*KEY\s*`([^`]+)`\s*\(([^)]+)\)|PRIMARY KEY\s*\(([^)]+)\)/;
2561
+
2562
+ // Updated to support indexes for text fields
2563
+ // 'KEY `idx_e2alarms_alarmstring` (`alarmString`(255))' -- would cut off the final bracket and wouldnt work.
2564
+ var indexRegex = /(PRIMARY|UNIQUE)?\s*KEY\s*`([^`]+)`\s*\(((?:`[^`]+`(?:\(\d+\))?(?:\s*,\s*)?)+)\)|PRIMARY KEY\s*\(((?:`[^`]+`(?:\(\d+\))?(?:\s*,\s*)?)+)\)/;
2561
2565
 
2562
2566
  // Regular expression to match table options (ENGINE, CHARSET, COLLATE)
2563
2567
  var optionsRegex = /ENGINE=(\w+)\s+DEFAULT\s+CHARSET=(\w+)(\s+COLLATE=(\w+))?/;
@@ -2574,6 +2578,7 @@ var parseCreateTableSQL = function parseCreateTableSQL(createTableSQL) {
2574
2578
  // Check if the line contains a column definition
2575
2579
  var columnMatch = columnRegex.exec(line);
2576
2580
  var indexMatch = indexRegex.exec(line);
2581
+ var indexMatch_Old = indexRegex_Old.exec(line);
2577
2582
  var constraintMatch = parseConstraint(line);
2578
2583
  if (columnMatch && !indexMatch && !constraintMatch) {
2579
2584
  var columnType = parseColumnType(line);
@@ -3795,7 +3800,8 @@ var applyDifferences = /*#__PURE__*/function () {
3795
3800
  return col.Field;
3796
3801
  }); // Check if all columns for the index exist
3797
3802
  missingColumns = Array.isArray(diff.index.ColumnName) ? diff.index.ColumnName.filter(function (col) {
3798
- return !columnNames.includes(col);
3803
+ var _col$split;
3804
+ return !columnNames.includes(col) && !columnNames.includes((_col$split = col.split("(")) === null || _col$split === undefined ? undefined : _col$split[0]);
3799
3805
  }) : [];
3800
3806
  if (!(missingColumns.length > 0)) {
3801
3807
  _context.next = 72;
@@ -3806,9 +3812,19 @@ var applyDifferences = /*#__PURE__*/function () {
3806
3812
  case 72:
3807
3813
  // Prepare the index columns with proper formatting
3808
3814
  indexColumns = diff.index.ColumnName.map(function (col) {
3809
- return "`".concat(col, "`");
3810
- }); // Format column names
3811
- // Handle PRIMARY index creation
3815
+ if (col.includes("(")) {
3816
+ var match = col.match(/^(?:`([^`]+)`|([A-Za-z_][A-Za-z0-9_\$]*))\((\d+)\)$/);
3817
+ if (match) {
3818
+ var name = match[1] || match[2]; // one of them will be filled
3819
+ var size = match[3];
3820
+ console.log(name, size);
3821
+ return "`".concat(name, "`(").concat(size, ")");
3822
+ }
3823
+ return "`".concat(col.split("(")[0], "`");
3824
+ } else {
3825
+ return "`".concat(col, "`"); // Format column names
3826
+ }
3827
+ }); // Handle PRIMARY index creation
3812
3828
  if (!(diff.index.Name === 'PRIMARY')) {
3813
3829
  _context.next = 84;
3814
3830
  break;
@@ -5446,10 +5462,8 @@ var apply = /*#__PURE__*/function () {
5446
5462
  // Only run this if this is the main module
5447
5463
  var isMain = function () {
5448
5464
  try {
5449
- // console.log('Checking if this is the main module');
5450
- // console.log(require.main === module)
5451
- // console.log(require.main);
5452
- return require.main === module;
5465
+ var modulePath = fileURLToPath$1(import.meta.url);
5466
+ return process.argv[1] === modulePath;
5453
5467
  } catch (e) {
5454
5468
  return false;
5455
5469
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysqlsyncr",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
package/rollup.config.js CHANGED
@@ -1,25 +1,25 @@
1
- import babel from 'rollup-plugin-babel';
2
- import resolve from '@rollup/plugin-node-resolve';
3
- import commonjs from '@rollup/plugin-commonjs';
4
-
5
- export default {
6
- input: 'src/index.js',
7
- output: [
8
- {
9
- file: 'dist/index.cjs',
10
- format: 'cjs'
11
- },
12
- {
13
- file: 'dist/index.js',
14
- format: 'es'
15
- }
16
- ],
17
- plugins: [
18
- babel({
19
- exclude: 'node_modules/**'
20
- }),
21
- resolve(),
22
- commonjs()
23
- ],
24
- external: ['cors', 'express', 'mysql2', 'yargs']
1
+ import babel from 'rollup-plugin-babel';
2
+ import resolve from '@rollup/plugin-node-resolve';
3
+ import commonjs from '@rollup/plugin-commonjs';
4
+
5
+ export default {
6
+ input: 'src/index.js',
7
+ output: [
8
+ {
9
+ file: 'dist/index.cjs',
10
+ format: 'cjs'
11
+ },
12
+ {
13
+ file: 'dist/index.js',
14
+ format: 'es'
15
+ }
16
+ ],
17
+ plugins: [
18
+ babel({
19
+ exclude: 'node_modules/**'
20
+ }),
21
+ resolve(),
22
+ commonjs()
23
+ ],
24
+ external: ['cors', 'express', 'mysql2', 'yargs']
25
25
  };