mysql-memory-server 1.4.1 → 1.4.3

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
@@ -13,15 +13,20 @@ Download with your package manager of choice. The package name is `mysql-memory-
13
13
  - Node.js 16.6.0 and newer
14
14
  - macOS 13+, Windows, or Linux (This package is only tested on Ubuntu 20.04, 22.04, 24.04, and Fedora 40. Other Linux distributions may or may not work at this time.)
15
15
 
16
- Windows only requirements:
16
+ #### Requirements for downloaded MySQL versions
17
+
18
+ The following requirements only apply if you intend to have `mysql-memory-server` download a version of MySQL to use instead of using an already installed version of MySQL on the system:
19
+
20
+ Requirements for Windows:
17
21
  - `Microsoft Visual C++ 2019 Redistributable Package` needs to be installed
18
22
 
19
- Linux only requirements:
23
+ Requirements for Linux:
20
24
  - The `libaio1` or `libaio1t64` package needs to be installed
21
25
  - If `libaio1` is not available but `libaio1t64` is, the `ldconfig` command needs to be available to run
22
- - The `tar` package needs to be installed if you want to use MySQL versions that aren't system installed
26
+ - The `tar` package needs to be installed
27
+
28
+ #### Currently supported MySQL versions
23
29
 
24
- Currently supported MySQL versions:
25
30
  - If using the system installed MySQL server: 8.0.20 and newer
26
31
  - If not using the system installed MySQL server: 8.0.39, 8.1.0, 8.2.0, 8.3.0, 8.4.2, 9.0.1
27
32
 
@@ -31,15 +36,26 @@ Currently supported MySQL versions:
31
36
  import { createDB } from 'mysql-memory-server';
32
37
  import sql from 'mysql2/promise'
33
38
 
34
- // Create a new database
39
+ // Create a new database with default options
35
40
  const db = await createDB()
36
41
 
42
+ //OR
43
+
44
+ //Create a new database with custom options set
45
+ const db = await createDB({
46
+ // see Options for the options you can use in this object and their default values
47
+ // for example:
48
+ version: '8.4.x'
49
+ })
50
+
37
51
  // Connect to the new database with the port provided
52
+ // The database is initialized with an empty password so use an empty string for the password
38
53
  const connection = await sql.createConnection({
39
54
  host: '127.0.0.1',
40
55
  user: db.username,
41
56
  port: db.port,
42
- database: db.dbName
57
+ database: db.dbName,
58
+ password: ''
43
59
  })
44
60
 
45
61
  // Run your queries here
@@ -52,6 +68,9 @@ await connection.end()
52
68
  await db.stop()
53
69
  ```
54
70
 
71
+ MySQL database initialization can take some time. If you run into a "Timeout exceeded" error with your tests, the timeout should be extended.
72
+ If using Jest, information about how to do this can be found here: https://jestjs.io/docs/jest-object#jestsettimeouttimeout
73
+
55
74
  ## Documentation
56
75
 
57
76
  ##### `createDB(options: ServerOptions): Promise<MySQLDB>`
@@ -167,22 +186,31 @@ Default: false
167
186
 
168
187
  Description: This option only applies if the system-installed MySQL version is lower than the oldest supported MySQL version for this package (8.0.20) and the `version` option is not defined. If set to `true`, this package will use the latest version of MySQL instead of the system-installed version. If `false`, the package will throw an error.
169
188
 
189
+ ***
190
+ ### :warning: Internal Options :warning:
191
+
192
+ 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.
193
+
170
194
  - `deleteDBAfterStopped: boolean`
171
195
 
172
196
  Required: No
173
197
 
174
198
  Default: true
175
199
 
176
- Gotchas: This option is intended to be for internal debugging purposes only and not meant for people to use. As such, this option will not follow Semantic Versioning.
177
-
178
200
  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.
179
201
 
180
202
  - `dataPath: string`
181
203
 
182
204
  Required: No
183
205
 
184
- Default: `TMPDIR/mysqlmsn/dbs/UUID` (replacing TMPDIR with the OS temp directory and UUID with a UUIDv4 without seperating dashes)
185
-
186
- Gotchas: This option is intended to be for internal debugging purposes only and not meant for people to use. As such, this option will not follow Semantic Versioning.
206
+ Default: `TMPDIR/mysqlmsn/dbs/UUID` (replacing TMPDIR with the OS temp directory and UUID with a UUIDv4 without seperating dashes).
187
207
 
188
208
  Description: The folder to store database-related data in
209
+
210
+ - `binaryDirectoryPath: string`
211
+
212
+ Required: No
213
+
214
+ Default: `TMPDIR/mysqlmsn/binaries` (replacing TMPDIR with the OS temp directory)
215
+
216
+ Description: The folder to store the MySQL binaries when they are downloaded from the CDN.
package/dist/src/index.js CHANGED
@@ -51,7 +51,8 @@ async function createDB(opts) {
51
51
  dbPath: (0, path_1.normalize)(`${os.tmpdir()}/mysqlmsn/dbs/${(0, crypto_1.randomUUID)().replace(/-/g, '')}`),
52
52
  ignoreUnsupportedSystemVersion: false,
53
53
  port: 0,
54
- xPort: 0
54
+ xPort: 0,
55
+ binaryDirectoryPath: `${os.tmpdir()}/mysqlmsn/binaries`
55
56
  };
56
57
  const options = { ...defaultOptions, ...opts };
57
58
  const logger = new Logger_1.default(options.logLevel);
@@ -73,7 +74,7 @@ async function createDB(opts) {
73
74
  let binaryFilepath;
74
75
  try {
75
76
  binaryInfo = (0, Version_1.default)(versions_json_1.default, options.version);
76
- logger.log('Downloading binary:', binaryInfo.version, 'from URL:', binaryInfo.url);
77
+ logger.log('Using MySQL binary version:', binaryInfo.version, 'from URL:', binaryInfo.url);
77
78
  }
78
79
  catch (e) {
79
80
  logger.error(e);
@@ -31,7 +31,6 @@ exports.downloadBinary = downloadBinary;
31
31
  const https = __importStar(require("https"));
32
32
  const fs = __importStar(require("fs"));
33
33
  const fsPromises = __importStar(require("fs/promises"));
34
- const os = __importStar(require("os"));
35
34
  const adm_zip_1 = __importDefault(require("adm-zip"));
36
35
  const path_1 = require("path");
37
36
  const crypto_1 = require("crypto");
@@ -52,7 +51,7 @@ function getZipData(entry) {
52
51
  }
53
52
  function handleTarExtraction(filepath, extractedPath) {
54
53
  return new Promise((resolve, reject) => {
55
- (0, child_process_1.exec)(`tar -xf ${filepath} -C ${extractedPath}`, (error, stdout, stderr) => {
54
+ (0, child_process_1.execFile)(`tar`, ['-xf', filepath, '-C', extractedPath], (error, stdout, stderr) => {
56
55
  if (error || stderr) {
57
56
  return reject(error || stderr);
58
57
  }
@@ -86,9 +85,13 @@ function downloadFromCDN(url, downloadLocation, logger) {
86
85
  request.on('error', (err) => {
87
86
  error = err;
88
87
  logger.error(err);
89
- fileStream.close();
90
- fs.unlink(downloadLocation, () => {
91
- reject(err.message);
88
+ fileStream.end(() => {
89
+ fs.unlink(downloadLocation, (unlinkError) => {
90
+ if (unlinkError) {
91
+ logger.error('An error occurred while deleting downloadLocation after an error occurred with the MySQL server binary download. The error was:', unlinkError);
92
+ }
93
+ reject(err.message);
94
+ });
92
95
  });
93
96
  });
94
97
  });
@@ -100,9 +103,13 @@ function downloadFromCDN(url, downloadLocation, logger) {
100
103
  fileStream.on('error', (err) => {
101
104
  error = err;
102
105
  logger.error(err);
103
- fileStream.end();
104
- fs.unlink(downloadLocation, () => {
105
- reject(err.message);
106
+ fileStream.end(() => {
107
+ fs.unlink(downloadLocation, (unlinkError) => {
108
+ if (unlinkError) {
109
+ logger.error('An error occurred while deleting downloadLocation after an error occurred with the fileStream. The error was:', unlinkError);
110
+ }
111
+ reject(err.message);
112
+ });
106
113
  });
107
114
  });
108
115
  });
@@ -167,59 +174,73 @@ function extractBinary(url, archiveLocation, extractedLocation, logger) {
167
174
  function downloadBinary(binaryInfo, options, logger) {
168
175
  return new Promise(async (resolve, reject) => {
169
176
  const { url, version } = binaryInfo;
170
- const dirpath = `${os.tmpdir()}/mysqlmsn/binaries`;
177
+ const dirpath = options.binaryDirectoryPath;
171
178
  logger.log('Binary path:', dirpath);
172
179
  await fsPromises.mkdir(dirpath, { recursive: true });
173
180
  const lastDashIndex = url.lastIndexOf('-');
174
181
  const fileExtension = url.slice(lastDashIndex).split('.').splice(1).join('.');
175
182
  if (options.downloadBinaryOnce) {
176
183
  const extractedPath = `${dirpath}/${version}`;
177
- await fsPromises.mkdir(extractedPath, { recursive: true });
178
184
  const binaryPath = (0, path_1.normalize)(`${extractedPath}/mysql/bin/mysqld${process.platform === 'win32' ? '.exe' : ''}`);
179
185
  const archivePath = `${dirpath}/${version}.${fileExtension}`;
180
186
  const binaryExists = fs.existsSync(binaryPath);
181
187
  if (binaryExists) {
182
188
  return resolve(binaryPath);
183
189
  }
184
- let lockedByUs = false;
185
- try {
186
- (0, proper_lockfile_1.lockSync)(extractedPath);
187
- lockedByUs = true;
188
- await downloadFromCDN(url, archivePath, logger);
189
- await extractBinary(url, archivePath, extractedPath, logger);
190
+ let releaseFunction;
191
+ while (true) {
190
192
  try {
191
- (0, proper_lockfile_1.unlockSync)(extractedPath);
193
+ await fsPromises.mkdir(extractedPath, { recursive: true });
194
+ releaseFunction = (0, proper_lockfile_1.lockSync)(extractedPath);
195
+ break;
192
196
  }
193
197
  catch (e) {
198
+ if (e.code === 'ELOCKED') {
199
+ logger.log('Waiting for lock for MySQL version', version);
200
+ await (0, FileLock_1.waitForLock)(extractedPath, options);
201
+ logger.log('Lock is gone for version', version);
202
+ //If the binary does not exist after lock has been released (like if the download fails and the binary got deleted as a result)
203
+ //then the lock acquisition process should start again
204
+ const binaryExists = fs.existsSync(binaryPath);
205
+ if (!binaryExists)
206
+ continue;
207
+ return resolve(binaryPath);
208
+ }
194
209
  return reject(e);
195
210
  }
196
- return resolve(binaryPath);
211
+ }
212
+ //The code below only runs if the lock has been acquired by us
213
+ try {
214
+ await downloadFromCDN(url, archivePath, logger);
215
+ await extractBinary(url, archivePath, extractedPath, logger);
197
216
  }
198
217
  catch (e) {
199
- if (String(e).includes('Lock file is already being held')) {
200
- logger.log('Waiting for lock for MySQL version', version);
201
- await (0, FileLock_1.waitForLock)(extractedPath, options);
202
- logger.log('Lock is gone for version', version);
203
- return resolve(binaryPath);
218
+ try {
219
+ await Promise.all([
220
+ fsPromises.rm(extractedPath, { force: true, recursive: true }),
221
+ fsPromises.rm(archivePath, { force: true, recursive: true })
222
+ ]);
204
223
  }
205
- if (lockedByUs) {
224
+ catch (e) {
225
+ logger.error('An error occurred while deleting extractedPath and/or archivePath:', e);
226
+ }
227
+ finally {
206
228
  try {
207
- await Promise.all([
208
- fsPromises.rm(extractedPath, { force: true, recursive: true }),
209
- fsPromises.rm(archivePath, { force: true, recursive: true })
210
- ]);
229
+ releaseFunction();
211
230
  }
212
- finally {
213
- try {
214
- (0, proper_lockfile_1.unlockSync)(extractedPath, { realpath: false });
215
- }
216
- catch (e) {
217
- logger.error('An error occurred while unlocking path:', e);
218
- }
231
+ catch (e) {
232
+ logger.error('An error occurred while unlocking path:', e);
219
233
  }
234
+ return reject(e);
220
235
  }
236
+ }
237
+ try {
238
+ releaseFunction();
239
+ }
240
+ catch (e) {
221
241
  return reject(e);
222
242
  }
243
+ return resolve(binaryPath);
223
244
  }
224
245
  const uuid = (0, crypto_1.randomUUID)();
225
246
  const zipFilepath = `${dirpath}/${uuid}.${fileExtension}`;
@@ -30,7 +30,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
30
30
  var __importDefault = (this && this.__importDefault) || function (mod) {
31
31
  return (mod && mod.__esModule) ? mod : { "default": mod };
32
32
  };
33
- var _Executor_instances, _Executor_execute, _Executor_executeFile, _Executor_killProcess, _Executor_startMySQLProcess, _Executor_setupDataDirectories;
33
+ var _Executor_instances, _Executor_executeFile, _Executor_killProcess, _Executor_startMySQLProcess, _Executor_setupDataDirectories;
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
35
  const child_process_1 = require("child_process");
36
36
  const semver_1 = require("semver");
@@ -83,7 +83,7 @@ class Executor {
83
83
  const versions = [];
84
84
  for (const dir of servers) {
85
85
  const path = `${process.env.PROGRAMFILES}\\MySQL\\${dir}\\bin\\mysqld`;
86
- const { error, stdout, stderr } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_execute).call(this, `"${path}" --version`);
86
+ const { error, stdout, stderr } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_executeFile).call(this, path, ['--version']);
87
87
  if (error || stderr) {
88
88
  return reject(error || stderr);
89
89
  }
@@ -110,8 +110,8 @@ class Executor {
110
110
  }
111
111
  }
112
112
  else {
113
- const { error, stdout, stderr } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_execute).call(this, 'mysqld --version');
114
- if (stderr && stderr.includes('not found')) {
113
+ const { error, stdout, stderr } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_executeFile).call(this, 'mysqld', ['--version']);
114
+ if (error && error.code === 'ENOENT') {
115
115
  resolve(null);
116
116
  }
117
117
  else if (error || stderr) {
@@ -161,22 +161,16 @@ class Executor {
161
161
  } while (retries <= options.portRetries);
162
162
  }
163
163
  }
164
- _Executor_instances = new WeakSet(), _Executor_execute = function _Executor_execute(command) {
164
+ _Executor_instances = new WeakSet(), _Executor_executeFile = function _Executor_executeFile(command, args) {
165
165
  return new Promise(resolve => {
166
- (0, child_process_1.exec)(command, { signal: AbortSignal_1.default.signal }, (error, stdout, stderr) => {
166
+ (0, child_process_1.execFile)(command, args, { signal: AbortSignal_1.default.signal }, (error, stdout, stderr) => {
167
167
  resolve({ error, stdout, stderr });
168
168
  });
169
169
  });
170
- }, _Executor_executeFile = function _Executor_executeFile(command, args, cwd) {
171
- return new Promise(resolve => {
172
- (0, child_process_1.execFile)(command, args, { signal: AbortSignal_1.default.signal, cwd }, (error, stdout, stderr) => {
173
- resolve({ stdout, stderr: (error === null || error === void 0 ? void 0 : error.message) || stderr });
174
- });
175
- });
176
170
  }, _Executor_killProcess = async function _Executor_killProcess(process) {
177
171
  let killed = false;
178
172
  if (os.platform() === 'win32') {
179
- const { error, stderr } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_execute).call(this, `taskkill /pid ${process.pid} /t /f`);
173
+ const { error, stderr } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_executeFile).call(this, 'taskkill', ['/pid', String(process.pid), '/t', '/f']);
180
174
  if (!error && !stderr) {
181
175
  killed = true;
182
176
  }
@@ -310,7 +304,7 @@ _Executor_instances = new WeakSet(), _Executor_execute = function _Executor_exec
310
304
  await fsPromises.mkdir(datadir, { recursive: true });
311
305
  let stderr;
312
306
  if (binaryFilepath === 'mysqld') {
313
- const { error, stderr: output } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_execute).call(this, `mysqld --no-defaults --datadir=${datadir} --initialize-insecure`);
307
+ const { error, stderr: output } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_executeFile).call(this, 'mysqld', ['--no-defaults', `--datadir=${datadir}`, '--initialize-insecure']);
314
308
  stderr = output;
315
309
  if (error) {
316
310
  this.logger.error('An error occurred while initializing database with system-installed MySQL:', error);
@@ -320,7 +314,7 @@ _Executor_instances = new WeakSet(), _Executor_execute = function _Executor_exec
320
314
  else {
321
315
  let result;
322
316
  try {
323
- result = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_executeFile).call(this, `${binaryFilepath}`, [`--no-defaults`, `--datadir=${datadir}`, `--initialize-insecure`], (0, path_1.resolve)(`${binaryFilepath}/..`));
317
+ result = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_executeFile).call(this, `${binaryFilepath}`, [`--no-defaults`, `--datadir=${datadir}`, `--initialize-insecure`]);
324
318
  }
325
319
  catch (e) {
326
320
  this.logger.error('Error occurred from executeFile:', e);
@@ -342,7 +336,7 @@ _Executor_instances = new WeakSet(), _Executor_execute = function _Executor_exec
342
336
  throw 'Tried to copy libaio into lib folder and MySQL is still failing to initialize. Please check the console for more information.';
343
337
  }
344
338
  if (binaryFilepath.slice(-16) === 'mysql/bin/mysqld') {
345
- const { error: lderror, stdout, stderr: ldstderr } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_execute).call(this, 'ldconfig -p');
339
+ const { error: lderror, stdout, stderr: ldstderr } = await __classPrivateFieldGet(this, _Executor_instances, "m", _Executor_executeFile).call(this, 'ldconfig', ['-p']);
346
340
  if (lderror || ldstderr) {
347
341
  this.logger.error('The following libaio error occurred:', stderr);
348
342
  this.logger.error('After the libaio error, an ldconfig error occurred:', lderror || ldstderr);
@@ -358,8 +352,34 @@ _Executor_instances = new WeakSet(), _Executor_execute = function _Executor_exec
358
352
  const libaioSymlinkPath = libaioEntry.slice(libaioPathIndex + 3);
359
353
  const libaioPath = await fsPromises.realpath(libaioSymlinkPath);
360
354
  const copyPath = (0, path_1.resolve)(`${binaryFilepath}/../../lib/private/libaio.so.1`);
361
- try {
362
- (0, proper_lockfile_1.lockSync)(copyPath, { realpath: false });
355
+ let lockRelease;
356
+ while (true) {
357
+ try {
358
+ lockRelease = (0, proper_lockfile_1.lockSync)(copyPath, { realpath: false });
359
+ break;
360
+ }
361
+ catch (e) {
362
+ if (e.code === 'ELOCKED') {
363
+ this.logger.log('Waiting for lock for libaio copy');
364
+ await (0, FileLock_1.waitForLock)(copyPath, options);
365
+ this.logger.log('Lock is gone for libaio copy');
366
+ //If libaio does not exist after the lock has been released (like if the copy fails)
367
+ //then the lock acquisition process should start again
368
+ const binaryExists = fs.existsSync(copyPath);
369
+ if (!binaryExists)
370
+ continue;
371
+ break;
372
+ }
373
+ else {
374
+ this.logger.error('An error occurred from locking libaio section:', e);
375
+ throw e;
376
+ }
377
+ }
378
+ }
379
+ if (lockRelease) {
380
+ //This code will only run if the lock has been acquired successfully.
381
+ //If the lock was already acquired by some other process, this process would have already waited for the lock, so no copying needs to be done since it's already happened.
382
+ //If the lock failed to acquire for some other reason, the error would've already been thrown.
363
383
  this.logger.log('libaio copy path:', copyPath, '| libaio symlink path:', libaioSymlinkPath, '| libaio actual path:', libaioPath);
364
384
  let copyError;
365
385
  try {
@@ -377,7 +397,7 @@ _Executor_instances = new WeakSet(), _Executor_execute = function _Executor_exec
377
397
  }
378
398
  finally {
379
399
  try {
380
- (0, proper_lockfile_1.unlockSync)(copyPath, { realpath: false });
400
+ lockRelease();
381
401
  }
382
402
  catch (e) {
383
403
  this.logger.error('Error unlocking libaio file:', e);
@@ -392,15 +412,6 @@ _Executor_instances = new WeakSet(), _Executor_execute = function _Executor_exec
392
412
  return;
393
413
  }
394
414
  }
395
- catch (error) {
396
- if (String(error) === 'Error: Lock file is already being held') {
397
- this.logger.log('Waiting for lock for libaio copy');
398
- await (0, FileLock_1.waitForLock)(copyPath, options);
399
- this.logger.log('Lock is gone for libaio copy');
400
- }
401
- this.logger.error('An error occurred from locking libaio section:', error);
402
- throw error;
403
- }
404
415
  }
405
416
  else {
406
417
  throw 'Cannot recognize file structure for the MySQL binary folder. This was caused by not being able to find libaio. Try installing libaio. Learn more at https://dev.mysql.com/doc/refman/en/binary-installation.html';
@@ -8,7 +8,7 @@ function waitForLock(path, options) {
8
8
  while (retries <= options.lockRetries) {
9
9
  retries++;
10
10
  try {
11
- const locked = (0, proper_lockfile_1.checkSync)(path);
11
+ const locked = (0, proper_lockfile_1.checkSync)(path, { realpath: false });
12
12
  if (!locked) {
13
13
  return resolve();
14
14
  }
@@ -11,17 +11,17 @@ class Logger {
11
11
  }
12
12
  log(...args) {
13
13
  if (this.LOG_LEVEL === 0) {
14
- console.log(...args);
14
+ console.log('[mysql-memory-server - LOG]:', ...args);
15
15
  }
16
16
  }
17
17
  warn(...args) {
18
18
  if (this.LOG_LEVEL <= 1) {
19
- console.warn(...args);
19
+ console.warn('[mysql-memory-server - WARN]:', ...args);
20
20
  }
21
21
  }
22
22
  error(...args) {
23
23
  if (this.LOG_LEVEL <= 2) {
24
- console.error(...args);
24
+ console.error('[mysql-memory-server - ERROR]:', ...args);
25
25
  }
26
26
  }
27
27
  }
@@ -1,4 +1,4 @@
1
- import { ExecException } from "child_process";
1
+ import { ExecFileException } from "child_process";
2
2
  export type LOG_LEVEL = 'LOG' | 'WARN' | 'ERROR';
3
3
  export type ServerOptions = {
4
4
  version?: string;
@@ -14,6 +14,7 @@ export type ServerOptions = {
14
14
  ignoreUnsupportedSystemVersion?: boolean;
15
15
  port?: number;
16
16
  xPort?: number;
17
+ binaryDirectoryPath?: string;
17
18
  };
18
19
  export type InternalServerOptions = {
19
20
  version?: string;
@@ -29,12 +30,13 @@ export type InternalServerOptions = {
29
30
  ignoreUnsupportedSystemVersion: boolean;
30
31
  port: number;
31
32
  xPort: number;
33
+ binaryDirectoryPath: string;
32
34
  };
33
35
  export type ExecutorOptions = {
34
36
  logLevel: LOG_LEVEL;
35
37
  };
36
- export type ExecuteReturn = {
37
- error: ExecException | null;
38
+ export type ExecuteFileReturn = {
39
+ error: ExecFileException | null;
38
40
  stdout: string;
39
41
  stderr: string;
40
42
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql-memory-server",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
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",
@@ -20,6 +20,9 @@
20
20
  "test:ci": "jest --testPathIgnorePatterns=/stress-tests/ --setupFilesAfterEnv ./ciSetup.js --verbose",
21
21
  "stress": "jest --runTestsByPath stress-tests/stress.test.ts --setupFilesAfterEnv ./ciSetup.js --verbose"
22
22
  },
23
+ "engines": {
24
+ "node": ">=16.6.0"
25
+ },
23
26
  "author": "Sebastian-Webster",
24
27
  "license": "MIT",
25
28
  "devDependencies": {
@@ -27,16 +30,16 @@
27
30
  "@babel/preset-env": "^7.25.4",
28
31
  "@babel/preset-typescript": "^7.24.7",
29
32
  "@types/adm-zip": "^0.5.5",
30
- "@types/node": "^22.5.0",
33
+ "@types/node": "^22.5.4",
31
34
  "@types/proper-lockfile": "^4.1.4",
32
35
  "@types/semver": "^7.5.8",
33
36
  "babel-jest": "^29.7.0",
34
37
  "jest": "^29.7.0",
35
- "mysql2": "^3.10.3",
36
- "typescript": "^5.5.4"
38
+ "mysql2": "^3.11.2",
39
+ "typescript": "^5.6.2"
37
40
  },
38
41
  "dependencies": {
39
- "adm-zip": "^0.5.15",
42
+ "adm-zip": "^0.5.16",
40
43
  "proper-lockfile": "^4.1.2",
41
44
  "semver": "^7.6.3"
42
45
  },