mysql-memory-server 1.6.0 → 1.7.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MySQL Memory Server
2
2
 
3
- This package allows you to create ephemeral MySQL databases from JavaScript and/or TypeScript code, great for testing. When creating a new database, if the version selected is not installed on the system, the binary is downloaded from MySQL's CDN (cdn.mysql.com)
3
+ This package allows you to create ephemeral MySQL databases from JavaScript and/or TypeScript code and also the CLI, great for testing, CI, and learning MySQL. When creating a new database, if the version selected is not installed on the system, the binary is downloaded from MySQL's CDN (cdn.mysql.com)
4
4
 
5
5
  You can run multiple MySQL databases with this package at the same time. Each database will use a random free port. The databases will automatically shutdown when the JS runtime process exits. A `stop()` method is also provided to stop each database instance.
6
6
 
@@ -30,7 +30,7 @@ Requirements for Linux:
30
30
  - If using the system installed MySQL server: 8.0.20 and newer
31
31
  - If not using the system installed MySQL server: 8.0.39, 8.0.40, 8.1.0, 8.2.0, 8.3.0, 8.4.2, 8.4.3, 9.0.1, 9.1.0
32
32
 
33
- ## Usage
33
+ ## Example Usage - Application Code
34
34
 
35
35
  This package supports both ESM and CJS so you can use import or require.
36
36
 
@@ -45,7 +45,7 @@ const db = await createDB()
45
45
 
46
46
  //Create a new database with custom options set
47
47
  const db = await createDB({
48
- // see Options for the options you can use in this object and their default values
48
+ // see Options below for the options you can use in this object and their default values
49
49
  // for example:
50
50
  version: '8.4.x'
51
51
  })
@@ -73,6 +73,14 @@ await db.stop()
73
73
  MySQL database initialization can take some time. If you run into a "Timeout exceeded" error with your tests, the timeout should be extended.
74
74
  If using Jest, information about how to do this can be found here: https://jestjs.io/docs/jest-object#jestsettimeouttimeout
75
75
 
76
+ ## Example Usage - CLI
77
+
78
+ ```sh
79
+ # Options are added by doing --{optionName} {optionValue}
80
+ # See Options below for the options you can use with this package
81
+ npx mysql-memory-server@latest --version 8.4.x
82
+ ```
83
+
76
84
  ## Documentation
77
85
 
78
86
  ##### `createDB(options: ServerOptions): Promise<MySQLDB>`
@@ -86,10 +94,14 @@ The port that MySQLX is listening on
86
94
  The database that was created on database initialization
87
95
  - `username: string`
88
96
  The name of the user to use to login to the database
97
+ - `socket: string`
98
+ If on Windows, this is the name of the named pipe that MySQL is listening on. If not on Windows, this is the path to the socket that MySQL is listening on.
99
+ - `xSocket: string`
100
+ If on Windows, this is the name of the named pipe that the MySQL X Plugin is listening on. If not on Windows, this is the path that the MySQL X Plugin is listening on.
89
101
  - `stop: () => Promise<void>`
90
102
  The method to stop the database. The returned promise resolves when the database has successfully stopped.
91
103
 
92
- ###### Options:
104
+ #### Options:
93
105
  - `version: string`
94
106
 
95
107
  Required: No
@@ -104,7 +116,7 @@ If left undefined:
104
116
 
105
117
  If defined:
106
118
  - If the version is 8.0.19 or older, an error will be thrown as this package does not currently support those versions of MySQL.
107
- - If MySQL is installed on the system, the installed version will be used. Otherwise the selected version will be downloaded from the MySQL CDN as long as it can be found in the `versions.json` file. If it cannot be found in that file, an error will be thrown.
119
+ - If the desired version of MySQL is installed on the system, the installed version will be used. Otherwise the selected version will be downloaded from the MySQL CDN as long as it can be found in the `versions.json` file. If it cannot be found in that file, an error will be thrown.
108
120
 
109
121
  - `dbName: string`
110
122
 
@@ -202,35 +214,45 @@ Required: No
202
214
 
203
215
  Default: ""
204
216
 
205
- Description: A string with MySQL queries to run before the database starts to accept connections. This option can be used for things like initialising tables without having to first connect to the database to do that.The queries in the string get executed after ```mysql-memory-server```'s queries run. Uses the ```--init-file``` MySQL server option under the hood. Learn more at the [--init-file MySQL Documentation](https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html#sysvar_init_file)
217
+ Description: A string with MySQL queries to run before the database starts to accept connections. This option can be used for things like initialising tables without having to first connect to the database to do that. The queries in the string get executed after ```mysql-memory-server```'s queries run. Uses the ```--init-file``` MySQL server option under the hood. Learn more at the [--init-file MySQL Documentation](https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html#sysvar_init_file)
206
218
 
207
219
  The internal queries that are ran before the queries in ```initSQLString``` are renaming the user from ```root``` to the username specified in the ```username``` option if it's set, and creating a database with the name from the ```dbName``` option.
208
220
 
209
221
  ***
210
222
  ### :warning: Internal Options :warning:
211
223
 
212
- The following options are only meant for internal debugging use. Their behaviour may change or they may get removed between major/minor/patch versions and they are not to be considered stable. The options below will not follow Semantic Versioning so it is advised to not use them.
224
+ The following options are only meant for internal use (such as CI or the internals for running this package via the CLI). Their behaviour may change or they may get removed between major/minor/patch versions and they are not to be considered stable. The options below will not follow Semantic Versioning so it is advised to not use them.
213
225
 
214
- - `deleteDBAfterStopped: boolean`
215
-
216
- Required: No
226
+ - `_DO_NOT_USE_deleteDBAfterStopped: boolean`
217
227
 
218
228
  Default: true
219
229
 
220
230
  Description: Changes whether or not the database will be deleted after it has been stopped. If set to `true`, the database WILL be deleted after it has been stopped.
221
231
 
222
- - `dataPath: string`
223
-
224
- Required: No
232
+ - `_DO_NOT_USE_dbPath: string`
225
233
 
226
234
  Default: `TMPDIR/mysqlmsn/dbs/UUID` (replacing TMPDIR with the OS temp directory and UUID with a UUIDv4 without seperating dashes).
227
235
 
228
236
  Description: The folder to store database-related data in
229
237
 
230
- - `binaryDirectoryPath: string`
231
-
232
- Required: No
238
+ - `_DO_NOT_USE_binaryDirectoryPath: string`
233
239
 
234
240
  Default: `TMPDIR/mysqlmsn/binaries` (replacing TMPDIR with the OS temp directory)
235
241
 
236
242
  Description: The folder to store the MySQL binaries when they are downloaded from the CDN.
243
+
244
+ - `_DO_NOT_USE_beforeSignalCleanupMessage: string`
245
+
246
+ Required: No
247
+
248
+ Default: undefined
249
+
250
+ Description: The message to get displayed in the console before the cleanup that happens when the Node.js process is stopped without the ```stop()``` method being called first.
251
+
252
+ - `_DO_NOT_USE_afterSignalCleanupMessage: string`
253
+
254
+ Required: No
255
+
256
+ Default: undefined
257
+
258
+ Description: The message to get displayed in the console after the cleanup that happens when the Node.js process is stopped without the ```stop()``` method being called first.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const index_1 = require("./index");
5
+ const constants_1 = require("./constants");
6
+ async function main() {
7
+ const definedOptions = process.argv.filter((option) => option.startsWith('--'));
8
+ const options = {
9
+ _DO_NOT_USE_beforeSignalCleanupMessage: '\nShutting down the ephemeral MySQL database and cleaning all related files...',
10
+ _DO_NOT_USE_afterSignalCleanupMessage: 'Shutdown and cleanup is complete.'
11
+ };
12
+ for (const opt of definedOptions) {
13
+ const index = process.argv.indexOf(opt);
14
+ const optionValue = process.argv[index + 1];
15
+ if (optionValue === undefined) {
16
+ throw `Option ${opt} must have a value.`;
17
+ }
18
+ const optionName = opt.slice(2);
19
+ const optionType = constants_1.OPTION_TYPE_CHECKS[optionName].definedType;
20
+ //Try to convert the options to their correct types.
21
+ //We do not need to do any proper type validation here as the library will make sure everything is correct.
22
+ //Like for example, if a string is passed to a number option, it'll be converted to NaN here, but the library
23
+ //will throw an error for it not being an actual number.
24
+ if (optionType === 'boolean') {
25
+ if (optionValue === 'true') {
26
+ options[optionName] = true;
27
+ }
28
+ else if (optionValue === 'false') {
29
+ options[optionName] = false;
30
+ }
31
+ else {
32
+ options[optionName] = optionValue;
33
+ }
34
+ }
35
+ else if (optionType === 'number') {
36
+ options[optionName] = parseInt(optionValue);
37
+ }
38
+ else {
39
+ options[opt.slice(2)] = optionValue;
40
+ }
41
+ }
42
+ console.log('Creating ephemeral MySQL database...');
43
+ const db = await (0, index_1.createDB)(options);
44
+ console.log(`A MySQL database has been successfully created with the following parameters:\n\nUsername: ${db.username} \nDatabase Name: ${db.dbName} \nPort: ${db.port} \nX Plugin Port: ${db.xPort} \nSocket: ${db.socket} \nX Plugin Socket: ${db.xSocket}\n`);
45
+ if (process.platform === 'win32') {
46
+ //The connection information logs will be different for Windows compared to other platforms.
47
+ //Windows uses mysqlsh instead of mysql to invoke the client shell, needs a --sql flag to be put into SQL mode, and also does not have a protocol flag.
48
+ //Also according to https://bugs.mysql.com/bug.php?id=106852, you cannot log into a MySQL database with a named pipe for the first connection so a socket connection suggestion
49
+ //should only be displayed for non-Windows platforms.
50
+ console.log(`If you want to use the MySQL CLI client to connect to the database, you can use the following command: \nmysqlsh --sql -u ${db.username} -P ${db.port}\nIf prompted for a password, leave the password field blank. The database does not have a password set.`);
51
+ }
52
+ else {
53
+ console.log(`If you want to use the MySQL CLI client to connect to the database, you can use either commands: \nmysql -u ${db.username} -P ${db.port} --protocol tcp \nOR\nmysql -u ${db.username} --socket ${db.socket}\nIf prompted for a password, leave the password field blank. The database does not have a password set.`);
54
+ }
55
+ }
56
+ main();
@@ -1,4 +1,11 @@
1
- declare const CONSTANTS: {
2
- MIN_SUPPORTED_MYSQL: string;
1
+ import { InternalServerOptions, OptionTypeChecks } from "../types";
2
+ export declare const MIN_SUPPORTED_MYSQL = "8.0.20";
3
+ export declare const DEFAULT_OPTIONS_GENERATOR: () => InternalServerOptions;
4
+ export declare const DEFAULT_OPTIONS_KEYS: readonly string[];
5
+ export declare const LOG_LEVELS: {
6
+ readonly LOG: 0;
7
+ readonly WARN: 1;
8
+ readonly ERROR: 2;
3
9
  };
4
- export default CONSTANTS;
10
+ export declare const INTERNAL_OPTIONS: readonly ["_DO_NOT_USE_deleteDBAfterStopped", "_DO_NOT_USE_dbPath", "_DO_NOT_USE_binaryDirectoryPath", "_DO_NOT_USE_beforeSignalCleanup", "_DO_NOT_USE_afterSignalCleanup"];
11
+ export declare const OPTION_TYPE_CHECKS: OptionTypeChecks;
@@ -1,6 +1,129 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const CONSTANTS = {
4
- MIN_SUPPORTED_MYSQL: '8.0.20'
3
+ exports.OPTION_TYPE_CHECKS = exports.INTERNAL_OPTIONS = exports.LOG_LEVELS = exports.DEFAULT_OPTIONS_KEYS = exports.DEFAULT_OPTIONS_GENERATOR = exports.MIN_SUPPORTED_MYSQL = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const path_1 = require("path");
6
+ const os_1 = require("os");
7
+ const semver_1 = require("semver");
8
+ exports.MIN_SUPPORTED_MYSQL = '8.0.20';
9
+ const DEFAULT_OPTIONS_GENERATOR = () => ({
10
+ version: undefined,
11
+ dbName: 'dbdata',
12
+ logLevel: 'ERROR',
13
+ portRetries: 10,
14
+ downloadBinaryOnce: true,
15
+ lockRetries: 1000,
16
+ lockRetryWait: 1000,
17
+ username: 'root',
18
+ ignoreUnsupportedSystemVersion: false,
19
+ port: 0,
20
+ xPort: 0,
21
+ downloadRetries: 10,
22
+ initSQLString: '',
23
+ _DO_NOT_USE_deleteDBAfterStopped: true,
24
+ //mysqlmsn = MySQL Memory Server Node.js
25
+ _DO_NOT_USE_dbPath: (0, path_1.normalize)(`${(0, os_1.tmpdir)()}/mysqlmsn/dbs/${(0, crypto_1.randomUUID)().replace(/-/g, '')}`),
26
+ _DO_NOT_USE_binaryDirectoryPath: `${(0, os_1.tmpdir)()}/mysqlmsn/binaries`,
27
+ _DO_NOT_USE_beforeSignalCleanupMessage: '',
28
+ _DO_NOT_USE_afterSignalCleanupMessage: ''
29
+ });
30
+ exports.DEFAULT_OPTIONS_GENERATOR = DEFAULT_OPTIONS_GENERATOR;
31
+ exports.DEFAULT_OPTIONS_KEYS = Object.freeze(Object.keys((0, exports.DEFAULT_OPTIONS_GENERATOR)()));
32
+ exports.LOG_LEVELS = {
33
+ 'LOG': 0,
34
+ 'WARN': 1,
35
+ 'ERROR': 2
36
+ };
37
+ exports.INTERNAL_OPTIONS = ['_DO_NOT_USE_deleteDBAfterStopped', '_DO_NOT_USE_dbPath', '_DO_NOT_USE_binaryDirectoryPath', '_DO_NOT_USE_beforeSignalCleanup', '_DO_NOT_USE_afterSignalCleanup'];
38
+ exports.OPTION_TYPE_CHECKS = {
39
+ version: {
40
+ check: (opt) => opt === undefined || typeof opt === 'string' && (0, semver_1.valid)(opt) !== null,
41
+ errorMessage: 'Option version must be either undefined or a valid semver string.',
42
+ definedType: 'string'
43
+ },
44
+ dbName: {
45
+ check: (opt) => opt === undefined || typeof opt === 'string' && opt.length <= 64,
46
+ errorMessage: 'Option dbName must be either undefined or a string that is not longer than 64 characters.',
47
+ definedType: 'string'
48
+ },
49
+ logLevel: {
50
+ check: (opt) => opt === undefined || Object.keys(exports.LOG_LEVELS).includes(opt),
51
+ errorMessage: 'Option logLevel must be either undefined or "LOG", "WARN", or "ERROR".',
52
+ definedType: 'string'
53
+ },
54
+ portRetries: {
55
+ check: (opt) => opt === undefined || typeof opt === 'number' && opt >= 0,
56
+ errorMessage: 'Option portRetries must be either undefined, a positive number, or 0.',
57
+ definedType: 'number'
58
+ },
59
+ downloadBinaryOnce: {
60
+ check: (opt) => opt === undefined || typeof opt === 'boolean',
61
+ errorMessage: 'Option downloadBinaryOnce must be either undefined or a boolean.',
62
+ definedType: 'boolean'
63
+ },
64
+ lockRetries: {
65
+ check: (opt) => opt === undefined || typeof opt === 'number' && opt >= 0,
66
+ errorMessage: 'Option lockRetries must be either undefined, a positive number, or 0.',
67
+ definedType: 'number'
68
+ },
69
+ lockRetryWait: {
70
+ check: (opt) => opt === undefined || typeof opt === 'number' && opt >= 0,
71
+ errorMessage: 'Option lockRetryWait must be either undefined, a positive number, or 0.',
72
+ definedType: 'number'
73
+ },
74
+ username: {
75
+ check: (opt) => opt === undefined || typeof opt === 'string' && opt.length <= 32,
76
+ errorMessage: 'Option username must be either undefined or a string that is not longer than 32 characters.',
77
+ definedType: 'string'
78
+ },
79
+ ignoreUnsupportedSystemVersion: {
80
+ check: (opt) => opt === undefined || typeof opt === 'boolean',
81
+ errorMessage: 'Option ignoreUnsupportedSystemVersion must be either undefined or a boolean.',
82
+ definedType: 'boolean'
83
+ },
84
+ port: {
85
+ check: (opt) => opt === undefined || typeof opt === 'number' && opt >= 0 && opt <= 65535,
86
+ errorMessage: 'Option port must be either undefined or a number that is between 0 and 65535 inclusive.',
87
+ definedType: 'number'
88
+ },
89
+ xPort: {
90
+ check: (opt) => opt === undefined || typeof opt === 'number' && opt >= 0 && opt <= 65535,
91
+ errorMessage: 'Option xPort must be either undefined or a number that is between 0 and 65535 inclusive.',
92
+ definedType: 'number'
93
+ },
94
+ downloadRetries: {
95
+ check: (opt) => opt === undefined || typeof opt === 'number' && opt >= 0,
96
+ errorMessage: 'Option downloadRetries must be either undefined, a positive number, or 0.',
97
+ definedType: 'number'
98
+ },
99
+ initSQLString: {
100
+ check: (opt) => opt === undefined || typeof opt === 'string',
101
+ errorMessage: 'Option initSQLString must be either undefined or a string.',
102
+ definedType: 'string'
103
+ },
104
+ _DO_NOT_USE_deleteDBAfterStopped: {
105
+ check: (opt) => opt === undefined || typeof opt === 'boolean',
106
+ errorMessage: 'Option _DO_NOT_USE_deleteDBAfterStopped must be either undefined or a boolean.',
107
+ definedType: 'boolean'
108
+ },
109
+ _DO_NOT_USE_dbPath: {
110
+ check: (opt) => opt === undefined || typeof opt === 'string',
111
+ errorMessage: 'Option _DO_NOT_USE_dbPath must be either undefined or a string.',
112
+ definedType: 'string'
113
+ },
114
+ _DO_NOT_USE_binaryDirectoryPath: {
115
+ check: (opt) => opt === undefined || typeof opt === 'string',
116
+ errorMessage: 'Option _DO_NOT_USE_binaryDirectoryPath must be either undefined or a string.',
117
+ definedType: 'string'
118
+ },
119
+ _DO_NOT_USE_beforeSignalCleanupMessage: {
120
+ check: (opt) => opt === undefined || typeof opt === 'string',
121
+ errorMessage: 'Option _DO_NOT_USE_beforeSignalCleanup must be either undefined or a string.',
122
+ definedType: 'string'
123
+ },
124
+ _DO_NOT_USE_afterSignalCleanupMessage: {
125
+ check: (opt) => opt === undefined || typeof opt === 'string',
126
+ errorMessage: 'Option _DO_NOT_USE_afterSignalCleanup must be either undefined or a string.',
127
+ definedType: 'string'
128
+ }
5
129
  };
6
- exports.default = CONSTANTS;
package/dist/src/index.js CHANGED
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
@@ -34,38 +44,37 @@ const semver_1 = require("semver");
34
44
  const Version_1 = __importDefault(require("./libraries/Version"));
35
45
  const versions_json_1 = __importDefault(require("./versions.json"));
36
46
  const Downloader_1 = require("./libraries/Downloader");
37
- const crypto_1 = require("crypto");
38
- const path_1 = require("path");
39
- const constants_1 = __importDefault(require("./constants"));
47
+ const constants_1 = require("./constants");
40
48
  async function createDB(opts) {
41
- const defaultOptions = {
42
- dbName: 'dbdata',
43
- logLevel: 'ERROR',
44
- portRetries: 10,
45
- downloadBinaryOnce: true,
46
- lockRetries: 1000,
47
- lockRetryWait: 1000,
48
- username: 'root',
49
- deleteDBAfterStopped: true,
50
- //mysqlmsn = MySQL Memory Server Node.js
51
- dbPath: (0, path_1.normalize)(`${os.tmpdir()}/mysqlmsn/dbs/${(0, crypto_1.randomUUID)().replace(/-/g, '')}`),
52
- ignoreUnsupportedSystemVersion: false,
53
- port: 0,
54
- xPort: 0,
55
- binaryDirectoryPath: `${os.tmpdir()}/mysqlmsn/binaries`,
56
- downloadRetries: 10,
57
- initSQLString: ''
58
- };
59
- const options = { ...defaultOptions, ...opts };
49
+ const suppliedOpts = opts || {};
50
+ const suppliedOptsKeys = Object.keys(suppliedOpts);
51
+ for (const opt of constants_1.INTERNAL_OPTIONS) {
52
+ if (suppliedOptsKeys.includes(opt)) {
53
+ console.warn(`[ mysql-memory-server - Options WARN ]: Creating MySQL database with option ${opt}. This is considered unstable and should not be used externally. Please consider removing this option.`);
54
+ }
55
+ }
56
+ const options = (0, constants_1.DEFAULT_OPTIONS_GENERATOR)();
57
+ for (const opt of suppliedOptsKeys) {
58
+ if (!constants_1.DEFAULT_OPTIONS_KEYS.includes(opt)) {
59
+ throw `Option ${opt} is not a valid option.`;
60
+ }
61
+ if (!constants_1.OPTION_TYPE_CHECKS[opt].check(suppliedOpts[opt])) {
62
+ //Supplied option failed the check
63
+ throw constants_1.OPTION_TYPE_CHECKS[opt].errorMessage;
64
+ }
65
+ if (suppliedOpts[opt] !== undefined) {
66
+ options[opt] = suppliedOpts[opt];
67
+ }
68
+ }
60
69
  const logger = new Logger_1.default(options.logLevel);
61
70
  const executor = new Executor_1.default(logger);
62
71
  const version = await executor.getMySQLVersion(options.version);
63
- const unsupportedMySQLIsInstalled = version && (0, semver_1.lt)(version.version, constants_1.default.MIN_SUPPORTED_MYSQL);
72
+ const unsupportedMySQLIsInstalled = version && (0, semver_1.lt)(version.version, constants_1.MIN_SUPPORTED_MYSQL);
64
73
  const throwUnsupportedError = unsupportedMySQLIsInstalled && !options.ignoreUnsupportedSystemVersion && !options.version;
65
74
  if (throwUnsupportedError) {
66
75
  throw `A version of MySQL is installed on your system that is not supported by this package. If you want to download a MySQL binary instead of getting this error, please set the option "ignoreUnsupportedSystemVersion" to true.`;
67
76
  }
68
- if (options.version && (0, semver_1.lt)(options.version, constants_1.default.MIN_SUPPORTED_MYSQL)) {
77
+ if (options.version && (0, semver_1.lt)(options.version, constants_1.MIN_SUPPORTED_MYSQL)) {
69
78
  //The difference between the throw here and the throw above is this throw is because the selected "version" is not supported.
70
79
  //The throw above is because the system-installed MySQL is out of date and "ignoreUnsupportedSystemVersion" is not set to true.
71
80
  throw `The selected version of MySQL (${options.version}) is not currently supported by this package. Please choose a different version to use.`;
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
@@ -35,7 +45,6 @@ const adm_zip_1 = __importDefault(require("adm-zip"));
35
45
  const path_1 = require("path");
36
46
  const crypto_1 = require("crypto");
37
47
  const child_process_1 = require("child_process");
38
- const proper_lockfile_1 = require("proper-lockfile");
39
48
  const FileLock_1 = require("./FileLock");
40
49
  function getZipData(entry) {
41
50
  return new Promise((resolve, reject) => {
@@ -199,7 +208,7 @@ function extractBinary(url, archiveLocation, extractedLocation, logger) {
199
208
  function downloadBinary(binaryInfo, options, logger) {
200
209
  return new Promise(async (resolve, reject) => {
201
210
  const { url, version } = binaryInfo;
202
- const dirpath = options.binaryDirectoryPath;
211
+ const dirpath = options._DO_NOT_USE_binaryDirectoryPath;
203
212
  logger.log('Binary path:', dirpath);
204
213
  await fsPromises.mkdir(dirpath, { recursive: true });
205
214
  const lastDashIndex = url.lastIndexOf('-');
@@ -215,11 +224,11 @@ function downloadBinary(binaryInfo, options, logger) {
215
224
  let releaseFunction;
216
225
  while (true) {
217
226
  try {
218
- releaseFunction = (0, proper_lockfile_1.lockSync)(extractedPath, { realpath: false });
227
+ releaseFunction = await (0, FileLock_1.lockFile)(extractedPath);
219
228
  break;
220
229
  }
221
230
  catch (e) {
222
- if (e.code === 'ELOCKED') {
231
+ if (e === 'LOCKED') {
223
232
  logger.log('Waiting for lock for MySQL version', version);
224
233
  await (0, FileLock_1.waitForLock)(extractedPath, options);
225
234
  logger.log('Lock is gone for version', version);
@@ -253,10 +262,10 @@ function downloadBinary(binaryInfo, options, logger) {
253
262
  catch (e) {
254
263
  logger.error('An error occurred while deleting extractedPath and/or archivePath:', e);
255
264
  }
256
- if (downloadTries >= options.downloadRetries) {
265
+ if (downloadTries > options.downloadRetries) {
257
266
  //Only reject if we have met the downloadRetries limit
258
267
  try {
259
- releaseFunction();
268
+ await releaseFunction();
260
269
  }
261
270
  catch (e) {
262
271
  logger.error('An error occurred while releasing lock after downloadRetries exhaustion. The error was:', e);
@@ -268,7 +277,7 @@ function downloadBinary(binaryInfo, options, logger) {
268
277
  console.warn(`An error was encountered during the binary download process. Retrying for retry ${downloadTries}/${options.downloadRetries}. The error was:`, e);
269
278
  }
270
279
  }
271
- } while (downloadTries < options.downloadRetries);
280
+ } while (downloadTries <= options.downloadRetries);
272
281
  try {
273
282
  releaseFunction();
274
283
  }
@@ -301,7 +310,7 @@ function downloadBinary(binaryInfo, options, logger) {
301
310
  catch (e) {
302
311
  logger.error('An error occurred while deleting extractedPath and/or archivePath:', e);
303
312
  }
304
- if (downloadTries >= options.downloadRetries) {
313
+ if (downloadTries > options.downloadRetries) {
305
314
  //Only reject if we have met the downloadRetries limit
306
315
  return reject(e);
307
316
  }
@@ -309,7 +318,7 @@ function downloadBinary(binaryInfo, options, logger) {
309
318
  console.warn(`An error was encountered during the binary download process. Retrying for retry ${downloadTries}/${options.downloadRetries}. The error was:`, e);
310
319
  }
311
320
  }
312
- } while (downloadTries < options.downloadRetries);
321
+ } while (downloadTries <= options.downloadRetries);
313
322
  }
314
323
  });
315
324
  }
@@ -3,6 +3,8 @@ import { InstalledMySQLVersion, InternalServerOptions, MySQLDB } from "../../typ
3
3
  declare class Executor {
4
4
  #private;
5
5
  logger: Logger;
6
+ DBDestroySignal: AbortController;
7
+ removeExitHandler: () => void;
6
8
  constructor(logger: Logger);
7
9
  getMySQLVersion(preferredVersion?: string): Promise<InstalledMySQLVersion | null>;
8
10
  startMySQL(options: InternalServerOptions, binaryFilepath: string): Promise<MySQLDB>;
@@ -15,22 +15,29 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
36
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
37
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
28
38
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
29
39
  };
30
- var __importDefault = (this && this.__importDefault) || function (mod) {
31
- return (mod && mod.__esModule) ? mod : { "default": mod };
32
- };
33
- var _Executor_instances, _Executor_executeFile, _Executor_killProcess, _Executor_deleteDatabaseDirectory, _Executor_startMySQLProcess, _Executor_setupDataDirectories;
40
+ var _Executor_instances, _Executor_executeFile, _Executor_killProcess, _Executor_deleteDatabaseDirectory, _Executor_returnBinaryPathToDelete, _Executor_startMySQLProcess, _Executor_setupDataDirectories;
34
41
  Object.defineProperty(exports, "__esModule", { value: true });
35
42
  const child_process_1 = require("child_process");
36
43
  const semver_1 = require("semver");
@@ -38,13 +45,14 @@ const os = __importStar(require("os"));
38
45
  const fsPromises = __importStar(require("fs/promises"));
39
46
  const fs = __importStar(require("fs"));
40
47
  const Port_1 = require("./Port");
41
- const AbortSignal_1 = __importDefault(require("./AbortSignal"));
42
48
  const path_1 = require("path");
43
- const proper_lockfile_1 = require("proper-lockfile");
44
49
  const FileLock_1 = require("./FileLock");
50
+ const signal_exit_1 = require("signal-exit");
51
+ const crypto_1 = require("crypto");
45
52
  class Executor {
46
53
  constructor(logger) {
47
54
  _Executor_instances.add(this);
55
+ this.DBDestroySignal = new AbortController();
48
56
  this.logger = logger;
49
57
  }
50
58
  getMySQLVersion(preferredVersion) {
@@ -107,8 +115,34 @@ class Executor {
107
115
  });
108
116
  }
109
117
  async startMySQL(options, binaryFilepath) {
118
+ this.removeExitHandler = (0, signal_exit_1.onExit)(() => {
119
+ if (options._DO_NOT_USE_beforeSignalCleanupMessage) {
120
+ console.log(options._DO_NOT_USE_beforeSignalCleanupMessage);
121
+ }
122
+ this.DBDestroySignal.abort();
123
+ if (options._DO_NOT_USE_deleteDBAfterStopped) {
124
+ try {
125
+ fs.rmSync(options._DO_NOT_USE_dbPath, { recursive: true, maxRetries: 50, force: true });
126
+ }
127
+ catch (e) {
128
+ this.logger.error('An error occurred while deleting database directory path:', e);
129
+ }
130
+ }
131
+ const binaryPathToDelete = __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_returnBinaryPathToDelete).call(this, binaryFilepath, options);
132
+ if (binaryPathToDelete) {
133
+ try {
134
+ fs.rmSync(binaryPathToDelete, { force: true, recursive: true, maxRetries: 50 });
135
+ }
136
+ catch (e) {
137
+ this.logger.error('An error occurred while deleting database binary:', e);
138
+ }
139
+ }
140
+ if (options._DO_NOT_USE_afterSignalCleanupMessage) {
141
+ console.log(options._DO_NOT_USE_afterSignalCleanupMessage);
142
+ }
143
+ });
110
144
  let retries = 0;
111
- const datadir = (0, path_1.normalize)(`${options.dbPath}/data`);
145
+ const datadir = (0, path_1.normalize)(`${options._DO_NOT_USE_dbPath}/data`);
112
146
  do {
113
147
  await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_setupDataDirectories).call(this, options, binaryFilepath, datadir, true);
114
148
  this.logger.log('Setting up directories was successful');
@@ -117,7 +151,7 @@ class Executor {
117
151
  this.logger.log('Using port:', port, 'and MySQLX port:', mySQLXPort, 'on retry:', retries);
118
152
  try {
119
153
  this.logger.log('Starting MySQL process');
120
- const resolved = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_startMySQLProcess).call(this, options, port, mySQLXPort, datadir, options.dbPath, binaryFilepath);
154
+ const resolved = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_startMySQLProcess).call(this, options, port, mySQLXPort, datadir, options._DO_NOT_USE_dbPath, binaryFilepath);
121
155
  this.logger.log('Starting process was successful');
122
156
  return resolved;
123
157
  }
@@ -140,7 +174,7 @@ class Executor {
140
174
  }
141
175
  _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_executeFile(command, args) {
142
176
  return new Promise(resolve => {
143
- (0, child_process_1.execFile)(command, args, { signal: AbortSignal_1.default.signal }, (error, stdout, stderr) => {
177
+ (0, child_process_1.execFile)(command, args, { signal: this.DBDestroySignal.signal }, (error, stdout, stderr) => {
144
178
  resolve({ error, stdout, stderr });
145
179
  });
146
180
  });
@@ -181,13 +215,24 @@ _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_
181
215
  this.logger.log('DB data directory deletion failed. Now on retry', retries);
182
216
  }
183
217
  }
218
+ }, _Executor_returnBinaryPathToDelete = function _Executor_returnBinaryPathToDelete(binaryFilepath, options) {
219
+ if (binaryFilepath.includes(os.tmpdir()) && !options.downloadBinaryOnce) {
220
+ const splitPath = binaryFilepath.split(os.platform() === 'win32' ? '\\' : '/');
221
+ const binariesIndex = splitPath.indexOf('binaries');
222
+ //The path will be the directory path for the binary download
223
+ splitPath.splice(binariesIndex + 2);
224
+ return splitPath.join('/');
225
+ }
226
+ return null;
184
227
  }, _Executor_startMySQLProcess = function _Executor_startMySQLProcess(options, port, mySQLXPort, datadir, dbPath, binaryFilepath) {
185
228
  const errors = [];
186
229
  const logFile = `${dbPath}/log.log`;
187
230
  const errorLogFile = `${datadir}/errorlog.err`;
188
231
  return new Promise(async (resolve, reject) => {
189
232
  await fsPromises.rm(logFile, { force: true });
190
- const process = (0, child_process_1.spawn)(binaryFilepath, ['--no-defaults', `--port=${port}`, `--datadir=${datadir}`, `--mysqlx-port=${mySQLXPort}`, `--mysqlx-socket=${dbPath}/x.sock`, `--socket=${dbPath}/m.sock`, `--general-log-file=${logFile}`, '--general-log=1', `--init-file=${dbPath}/init.sql`, '--bind-address=127.0.0.1', '--innodb-doublewrite=OFF', '--mysqlx=FORCE', `--log-error=${errorLogFile}`, `--user=${os.userInfo().username}`], { signal: AbortSignal_1.default.signal, killSignal: 'SIGKILL' });
233
+ const socket = os.platform() === 'win32' ? `MySQL-${(0, crypto_1.randomUUID)()}` : `${dbPath}/m.sock`;
234
+ const xSocket = os.platform() === 'win32' ? `MySQLX-${(0, crypto_1.randomUUID)()}` : `${dbPath}/x.sock`;
235
+ const process = (0, child_process_1.spawn)(binaryFilepath, ['--no-defaults', `--port=${port}`, `--datadir=${datadir}`, `--mysqlx-port=${mySQLXPort}`, `--mysqlx-socket=${xSocket}`, `--socket=${socket}`, `--general-log-file=${logFile}`, '--general-log=1', `--init-file=${dbPath}/init.sql`, '--bind-address=127.0.0.1', '--innodb-doublewrite=OFF', '--mysqlx=FORCE', `--log-error=${errorLogFile}`, `--user=${os.userInfo().username}`], { signal: this.DBDestroySignal.signal, killSignal: 'SIGKILL' });
191
236
  //resolveFunction is the function that will be called to resolve the promise that stops the database.
192
237
  //If resolveFunction is not undefined, the database has received a kill signal and data cleanup procedures should run.
193
238
  //Once ran, resolveFunction will be called.
@@ -206,7 +251,7 @@ _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_
206
251
  if (portIssue || xPortIssue) {
207
252
  this.logger.log('Error log when exiting for port in use error:', errorLog);
208
253
  try {
209
- await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_deleteDatabaseDirectory).call(this, options.dbPath);
254
+ await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_deleteDatabaseDirectory).call(this, options._DO_NOT_USE_dbPath);
210
255
  }
211
256
  catch (e) {
212
257
  this.logger.error(e);
@@ -215,22 +260,18 @@ _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_
215
260
  return reject('Port is already in use');
216
261
  }
217
262
  try {
218
- if (options.deleteDBAfterStopped) {
263
+ if (options._DO_NOT_USE_deleteDBAfterStopped) {
219
264
  await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_deleteDatabaseDirectory).call(this, dbPath);
220
265
  }
221
266
  }
222
267
  catch (e) {
223
- this.logger.error('An erorr occurred while deleting database directory at path:', dbPath, '| The error was:', e);
268
+ this.logger.error('An error occurred while deleting database directory at path:', dbPath, '| The error was:', e);
224
269
  }
225
270
  finally {
226
271
  try {
227
- if (binaryFilepath.includes(os.tmpdir()) && !options.downloadBinaryOnce) {
228
- const splitPath = binaryFilepath.split(os.platform() === 'win32' ? '\\' : '/');
229
- const binariesIndex = splitPath.indexOf('binaries');
230
- //The path will be the directory path for the binary download
231
- splitPath.splice(binariesIndex + 2);
232
- //Delete the binary folder
233
- await fsPromises.rm(splitPath.join('/'), { force: true, recursive: true });
272
+ const binaryPathToDelete = __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_returnBinaryPathToDelete).call(this, binaryFilepath, options);
273
+ if (binaryPathToDelete) {
274
+ await fsPromises.rm(binaryPathToDelete, { force: true, recursive: true, maxRetries: 50 });
234
275
  }
235
276
  }
236
277
  catch (e) {
@@ -282,11 +323,14 @@ _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_
282
323
  resolve({
283
324
  port,
284
325
  xPort: mySQLXPort,
326
+ socket,
327
+ xSocket,
285
328
  dbName: options.dbName,
286
329
  username: options.username,
287
330
  stop: () => {
288
331
  return new Promise(async (resolve, reject) => {
289
332
  resolveFunction = resolve;
333
+ this.removeExitHandler();
290
334
  const killed = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_killProcess).call(this, process);
291
335
  if (!killed) {
292
336
  reject();
@@ -354,11 +398,11 @@ _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_
354
398
  let lockRelease;
355
399
  while (true) {
356
400
  try {
357
- lockRelease = (0, proper_lockfile_1.lockSync)(copyPath, { realpath: false });
401
+ lockRelease = await (0, FileLock_1.lockFile)(copyPath);
358
402
  break;
359
403
  }
360
404
  catch (e) {
361
- if (e.code === 'ELOCKED') {
405
+ if (e === 'LOCKED') {
362
406
  this.logger.log('Waiting for lock for libaio copy');
363
407
  await (0, FileLock_1.waitForLock)(copyPath, options);
364
408
  this.logger.log('Lock is gone for libaio copy');
@@ -396,7 +440,7 @@ _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_
396
440
  }
397
441
  finally {
398
442
  try {
399
- lockRelease();
443
+ await lockRelease();
400
444
  }
401
445
  catch (e) {
402
446
  this.logger.error('Error unlocking libaio file:', e);
@@ -427,7 +471,7 @@ _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_
427
471
  initText += `\n${options.initSQLString}`;
428
472
  }
429
473
  this.logger.log('Writing init file');
430
- await fsPromises.writeFile(`${options.dbPath}/init.sql`, initText, { encoding: 'utf8' });
474
+ await fsPromises.writeFile(`${options._DO_NOT_USE_dbPath}/init.sql`, initText, { encoding: 'utf8' });
431
475
  this.logger.log('Finished writing init file');
432
476
  };
433
477
  exports.default = Executor;
@@ -1,2 +1,3 @@
1
1
  import { InternalServerOptions } from "../../types";
2
2
  export declare function waitForLock(path: string, options: InternalServerOptions): Promise<void>;
3
+ export declare function lockFile(path: string): Promise<() => Promise<void>>;
@@ -1,25 +1,81 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.waitForLock = waitForLock;
4
- const proper_lockfile_1 = require("proper-lockfile");
5
- function waitForLock(path, options) {
6
- return new Promise(async (resolve, reject) => {
7
- let retries = 0;
8
- while (retries <= options.lockRetries) {
9
- retries++;
7
+ exports.lockFile = lockFile;
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const mtimeUpdateIntervalTime = 2000;
10
+ const mtimeLimit = 10000;
11
+ async function waitForLock(path, options) {
12
+ const lockPath = `${path}.lock`;
13
+ let retries = 0;
14
+ do {
15
+ retries++;
16
+ try {
17
+ const stat = await promises_1.default.stat(lockPath);
18
+ if (Date.now() - stat.mtime.getTime() > mtimeLimit) {
19
+ return;
20
+ }
21
+ else {
22
+ await new Promise(resolve => setTimeout(resolve, options.lockRetryWait));
23
+ }
24
+ }
25
+ catch (e) {
26
+ if (e.code === 'ENOENT') {
27
+ return;
28
+ }
29
+ else {
30
+ throw e;
31
+ }
32
+ }
33
+ } while (retries <= options.lockRetries);
34
+ throw `lockRetries has been exceeded. Lock had not been released after ${options.lockRetryWait} * ${options.lockRetries} (${options.lockRetryWait * options.lockRetries}) milliseconds.`;
35
+ }
36
+ function setupMTimeEditor(lockPath) {
37
+ const interval = setInterval(async () => {
38
+ try {
39
+ const time = new Date();
40
+ await promises_1.default.utimes(lockPath, time, time);
41
+ }
42
+ catch { }
43
+ }, mtimeUpdateIntervalTime);
44
+ return async () => {
45
+ clearInterval(interval);
46
+ await promises_1.default.rmdir(lockPath);
47
+ };
48
+ }
49
+ async function lockFile(path) {
50
+ const lockPath = `${path}.lock`;
51
+ try {
52
+ await promises_1.default.mkdir(lockPath);
53
+ return setupMTimeEditor(lockPath);
54
+ }
55
+ catch (e) {
56
+ if (e.code === 'EEXIST') {
10
57
  try {
11
- const locked = (0, proper_lockfile_1.checkSync)(path, { realpath: false });
12
- if (!locked) {
13
- return resolve();
58
+ const stat = await promises_1.default.stat(lockPath);
59
+ if (Date.now() - stat.mtime.getTime() > mtimeLimit) {
60
+ return setupMTimeEditor(lockPath);
14
61
  }
15
62
  else {
16
- await new Promise(resolve => setTimeout(resolve, options.lockRetryWait));
63
+ throw 'LOCKED';
17
64
  }
18
65
  }
19
66
  catch (e) {
20
- return reject(e);
67
+ if (e.code === 'ENOENT') {
68
+ //This will run if the lock gets released after the EEXIST error is thrown but before the stat is checked.
69
+ //If this is the case, the lock acquisition should be retried.
70
+ return await lockFile(path);
71
+ }
72
+ else {
73
+ throw e;
74
+ }
21
75
  }
22
76
  }
23
- reject(`lockRetries has been exceeded. Lock had not been released after ${options.lockRetryWait} * ${options.lockRetries} milliseconds.`);
24
- });
77
+ else {
78
+ throw e;
79
+ }
80
+ }
25
81
  }
@@ -1,13 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const LOG_LEVELS = {
4
- 'LOG': 0,
5
- 'WARN': 1,
6
- 'ERROR': 2
7
- };
3
+ const constants_1 = require("../constants");
8
4
  class Logger {
9
5
  constructor(level) {
10
- this.LOG_LEVEL = LOG_LEVELS[level];
6
+ this.LOG_LEVEL = constants_1.LOG_LEVELS[level];
11
7
  }
12
8
  log(...args) {
13
9
  if (this.LOG_LEVEL === 0) {
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  Object.defineProperty(exports, "__esModule", { value: true });
26
36
  exports.default = getBinaryURL;
27
37
  const os = __importStar(require("os"));
@@ -9,14 +9,16 @@ export type ServerOptions = {
9
9
  lockRetries?: number | undefined;
10
10
  lockRetryWait?: number | undefined;
11
11
  username?: string | undefined;
12
- deleteDBAfterStopped?: boolean | undefined;
13
- dbPath?: string | undefined;
14
12
  ignoreUnsupportedSystemVersion?: boolean | undefined;
15
13
  port?: number | undefined;
16
14
  xPort?: number | undefined;
17
- binaryDirectoryPath?: string | undefined;
18
15
  downloadRetries?: number | undefined;
19
16
  initSQLString?: string | undefined;
17
+ _DO_NOT_USE_deleteDBAfterStopped?: boolean | undefined;
18
+ _DO_NOT_USE_dbPath?: string | undefined;
19
+ _DO_NOT_USE_binaryDirectoryPath?: string | undefined;
20
+ _DO_NOT_USE_beforeSignalCleanupMessage?: string | undefined;
21
+ _DO_NOT_USE_afterSignalCleanupMessage?: string | undefined;
20
22
  };
21
23
  export type InternalServerOptions = {
22
24
  version?: string | undefined;
@@ -27,14 +29,16 @@ export type InternalServerOptions = {
27
29
  lockRetries: number;
28
30
  lockRetryWait: number;
29
31
  username: string;
30
- deleteDBAfterStopped: boolean;
31
- dbPath: string;
32
32
  ignoreUnsupportedSystemVersion: boolean;
33
33
  port: number;
34
34
  xPort: number;
35
- binaryDirectoryPath: string;
36
35
  downloadRetries: number;
37
36
  initSQLString: string;
37
+ _DO_NOT_USE_deleteDBAfterStopped: boolean;
38
+ _DO_NOT_USE_dbPath: string;
39
+ _DO_NOT_USE_binaryDirectoryPath: string;
40
+ _DO_NOT_USE_beforeSignalCleanupMessage: string;
41
+ _DO_NOT_USE_afterSignalCleanupMessage: string;
38
42
  };
39
43
  export type ExecutorOptions = {
40
44
  logLevel: LOG_LEVEL;
@@ -47,6 +51,8 @@ export type ExecuteFileReturn = {
47
51
  export type MySQLDB = {
48
52
  port: number;
49
53
  xPort: number;
54
+ socket: string;
55
+ xSocket: string;
50
56
  dbName: string;
51
57
  username: string;
52
58
  stop: () => Promise<void>;
@@ -66,3 +72,10 @@ export type BinaryInfo = {
66
72
  url: string;
67
73
  version: string;
68
74
  };
75
+ export type OptionTypeChecks = {
76
+ [key in keyof Required<ServerOptions>]: {
77
+ check: (opt: any) => boolean;
78
+ errorMessage: string;
79
+ definedType: "string" | "boolean" | "number";
80
+ };
81
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql-memory-server",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "Spin up an ephemeral MySQL database from your JavaScript code",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -31,18 +31,17 @@
31
31
  "@babel/preset-env": "^7.25.9",
32
32
  "@babel/preset-typescript": "^7.25.9",
33
33
  "@types/adm-zip": "^0.5.5",
34
- "@types/node": "^22.7.9",
35
- "@types/proper-lockfile": "^4.1.4",
34
+ "@types/node": "^22.9.3",
36
35
  "@types/semver": "^7.5.8",
37
36
  "babel-jest": "^29.7.0",
38
37
  "jest": "^29.7.0",
39
38
  "mysql2": "^3.11.3",
40
- "typescript": "^5.6.3"
39
+ "typescript": "^5.7.2"
41
40
  },
42
41
  "dependencies": {
43
42
  "adm-zip": "^0.5.16",
44
- "proper-lockfile": "^4.1.2",
45
- "semver": "^7.6.3"
43
+ "semver": "^7.6.3",
44
+ "signal-exit": "^4.1.0"
46
45
  },
47
46
  "repository": {
48
47
  "type": "git",
@@ -51,5 +50,6 @@
51
50
  "bugs": {
52
51
  "url": "https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/issues"
53
52
  },
54
- "homepage": "https://github.com/Sebastian-Webster/mysql-memory-server-nodejs"
53
+ "homepage": "https://github.com/Sebastian-Webster/mysql-memory-server-nodejs",
54
+ "bin": "dist/src/cli.js"
55
55
  }