Skip to content

Commit dc9f3b7

Browse files
build - v1.12.0
1 parent 96361dd commit dc9f3b7

14 files changed

+153
-85
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Download with your package manager of choice. The package name is `mysql-memory-
1717
- ```mysql-memory-server``` can run MySQL versions 5.7.19 and newer (if the version is already installed on your system)
1818
- ```mysql-memory-server``` can download and run MySQL versions (inclusive) 5.7.19 - 5.7.44, 8.0.0 - 8.0.43, 8.1.0 - 8.4.6, and 9.0.1 - 9.4.0 (if the version is not already installed on your system)
1919

20-
Extra system requirements apply when ```mysql-memory-server``` is downloading MySQL instead of running a version of MySQL that is already installed on the system. To see the requirements and learn more about the supported versions for download, [read the doc](https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/blob/v1.11.0/docs/SUPPORTED_MYSQL_DOWNLOADS.md)
20+
Extra system requirements apply when ```mysql-memory-server``` is downloading MySQL instead of running a version of MySQL that is already installed on the system. To see the requirements and learn more about the supported versions for download, [read the doc](https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/blob/v1.12.0/docs/SUPPORTED_MYSQL_DOWNLOADS.md)
2121

2222
## Example Usage - Application Code
2323

@@ -102,11 +102,11 @@ Description: Version of MySQL to use for the database. Uses semver for getting t
102102

103103
If left undefined:
104104
- If the system has MySQL installed, the system-installed version will be used. If the installed version is not supported by this package (currently <5.7.19), an error will be thrown unless `ignoreUnsupportedSystemVersion` is set to `true`.
105-
- If the system does not have MySQL installed, the latest version of MySQL that [this package supports downloading](https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/blob/v1.11.0/docs/SUPPORTED_MYSQL_DOWNLOADS.md) will be downloaded.
105+
- If the system does not have MySQL installed, the latest version of MySQL that [this package supports downloading](https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/blob/v1.12.0/docs/SUPPORTED_MYSQL_DOWNLOADS.md) will be downloaded.
106106

107107
If defined:
108108
- If the version is older than 5.7.19, an error will be thrown as this package does not currently support those versions of MySQL.
109-
- If the desired version of MySQL is already installed on the system, the installed version will be used. Otherwise the selected version will be downloaded as long as this package [supports downloading it](https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/blob/v1.11.0/docs/SUPPORTED_MYSQL_DOWNLOADS.md). If this package does not support downloading the selected version, or your system does not [meet the requirements](https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/blob/v1.11.0/docs/SUPPORTED_MYSQL_DOWNLOADS.md) for that version to be ran, an error will be thrown.
109+
- If the desired version of MySQL is already installed on the system, the installed version will be used. Otherwise the selected version will be downloaded as long as this package [supports downloading it](https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/blob/v1.12.0/docs/SUPPORTED_MYSQL_DOWNLOADS.md). If this package does not support downloading the selected version, or your system does not [meet the requirements](https://github.com/Sebastian-Webster/mysql-memory-server-nodejs/blob/v1.12.0/docs/SUPPORTED_MYSQL_DOWNLOADS.md) for that version to be ran, an error will be thrown.
110110

111111
- `dbName: string`
112112

dist/src/constants.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ declare const internalOptions: {
1515
export declare function getInternalEnvVariable(envVar: keyof typeof internalOptions): string;
1616
export declare const OPTION_TYPE_CHECKS: OptionTypeChecks;
1717
export declare const MIN_SUPPORTED_MYSQL = "5.7.19";
18-
export declare const downloadsBaseURL = "https://cdn.mysql.com//Downloads/MySQL-";
19-
export declare const archiveBaseURL = "https://cdn.mysql.com/archives/mysql-";
18+
export declare const MySQLCDNDownloadsBaseURL = "https://cdn.mysql.com//Downloads/MySQL-";
19+
export declare const MySQLCDNArchivesBaseURL = "https://cdn.mysql.com/archives/mysql-";
2020
export declare const DOWNLOADABLE_MYSQL_VERSIONS: readonly ["5.7.19", "5.7.20", "5.7.21", "5.7.22", "5.7.23", "5.7.24", "5.7.25", "5.7.26", "5.7.27", "5.7.28", "5.7.29", "5.7.30", "5.7.31", "5.7.32", "5.7.33", "5.7.34", "5.7.35", "5.7.36", "5.7.37", "5.7.38", "5.7.39", "5.7.40", "5.7.41", "5.7.42", "5.7.43", "5.7.44", "8.0.0", "8.0.1", "8.0.2", "8.0.3", "8.0.4", "8.0.11", "8.0.12", "8.0.13", "8.0.14", "8.0.15", "8.0.16", "8.0.17", "8.0.18", "8.0.19", "8.0.20", "8.0.21", "8.0.22", "8.0.23", "8.0.24", "8.0.25", "8.0.26", "8.0.27", "8.0.28", "8.0.30", "8.0.31", "8.0.32", "8.0.33", "8.0.34", "8.0.35", "8.0.36", "8.0.37", "8.0.39", "8.0.40", "8.0.41", "8.0.42", "8.0.43", "8.1.0", "8.2.0", "8.3.0", "8.4.0", "8.4.2", "8.4.3", "8.4.4", "8.4.5", "8.4.6", "9.0.1", "9.1.0", "9.2.0", "9.3.0", "9.4.0"];
2121
export declare const MYSQL_ARCH_SUPPORT: {
2222
readonly darwin: {

dist/src/constants.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3-
exports.MYSQL_LINUX_MINIMAL_REBUILD_VERSIONS = exports.MYSQL_LINUX_FILE_EXTENSIONS = exports.MYSQL_LINUX_MINIMAL_INSTALL_AVAILABLE_ARM64 = exports.MYSQL_LINUX_MINIMAL_INSTALL_AVAILABLE = exports.MYSQL_LINUX_GLIBC_VERSIONS = exports.MYSQL_MACOS_VERSIONS_IN_FILENAME = exports.RC_MYSQL_VERSIONS = exports.DMR_MYSQL_VERSIONS = exports.MYSQL_MIN_OS_SUPPORT = exports.MYSQL_ARCH_SUPPORT = exports.DOWNLOADABLE_MYSQL_VERSIONS = exports.archiveBaseURL = exports.downloadsBaseURL = exports.MIN_SUPPORTED_MYSQL = exports.OPTION_TYPE_CHECKS = exports.LOG_LEVELS = exports.DEFAULT_OPTIONS_KEYS = exports.DEFAULT_OPTIONS = void 0;
3+
exports.MYSQL_LINUX_MINIMAL_REBUILD_VERSIONS = exports.MYSQL_LINUX_FILE_EXTENSIONS = exports.MYSQL_LINUX_MINIMAL_INSTALL_AVAILABLE_ARM64 = exports.MYSQL_LINUX_MINIMAL_INSTALL_AVAILABLE = exports.MYSQL_LINUX_GLIBC_VERSIONS = exports.MYSQL_MACOS_VERSIONS_IN_FILENAME = exports.RC_MYSQL_VERSIONS = exports.DMR_MYSQL_VERSIONS = exports.MYSQL_MIN_OS_SUPPORT = exports.MYSQL_ARCH_SUPPORT = exports.DOWNLOADABLE_MYSQL_VERSIONS = exports.MySQLCDNArchivesBaseURL = exports.MySQLCDNDownloadsBaseURL = exports.MIN_SUPPORTED_MYSQL = exports.OPTION_TYPE_CHECKS = exports.LOG_LEVELS = exports.DEFAULT_OPTIONS_KEYS = exports.DEFAULT_OPTIONS = void 0;
44
exports.getInternalEnvVariable = getInternalEnvVariable;
55
const path_1 = require("path");
66
const os_1 = require("os");
@@ -19,7 +19,8 @@ exports.DEFAULT_OPTIONS = {
1919
xPort: 0,
2020
downloadRetries: 10,
2121
initSQLString: '',
22-
arch: process.arch
22+
arch: process.arch,
23+
xEnabled: 'FORCE'
2324
};
2425
exports.DEFAULT_OPTIONS_KEYS = Object.freeze(Object.keys(exports.DEFAULT_OPTIONS));
2526
exports.LOG_LEVELS = {
@@ -38,6 +39,7 @@ function getInternalEnvVariable(envVar) {
3839
return process.env['mysqlmsn_internal_DO_NOT_USE_' + envVar] || internalOptions[envVar];
3940
}
4041
const allowedArches = ['x64', 'arm64'];
42+
const pluginActivationStates = ['OFF', 'FORCE'];
4143
exports.OPTION_TYPE_CHECKS = {
4244
version: {
4345
check: (opt) => opt === undefined || typeof opt === 'string' && (0, semver_1.valid)((0, semver_1.coerce)(opt)) !== null,
@@ -108,11 +110,16 @@ exports.OPTION_TYPE_CHECKS = {
108110
check: (opt) => opt === undefined || allowedArches.includes(opt),
109111
errorMessage: `Option arch must be either of the following: ${allowedArches.join(', ')}`,
110112
definedType: 'string'
113+
},
114+
xEnabled: {
115+
check: (opt) => opt === undefined || pluginActivationStates.includes(opt),
116+
errorMessage: `xEnabled must be either undefined or one of the following: ${pluginActivationStates.join(', ')}`,
117+
definedType: 'boolean'
111118
}
112119
};
113120
exports.MIN_SUPPORTED_MYSQL = '5.7.19';
114-
exports.downloadsBaseURL = 'https://cdn.mysql.com//Downloads/MySQL-';
115-
exports.archiveBaseURL = 'https://cdn.mysql.com/archives/mysql-';
121+
exports.MySQLCDNDownloadsBaseURL = 'https://cdn.mysql.com//Downloads/MySQL-';
122+
exports.MySQLCDNArchivesBaseURL = 'https://cdn.mysql.com/archives/mysql-';
116123
// Versions 8.0.29, 8.0.38, 8.4.1, and 9.0.0 have been purposefully left out of this list as MySQL has removed them from the CDN due to critical issues.
117124
exports.DOWNLOADABLE_MYSQL_VERSIONS = [
118125
'5.7.19', '5.7.20', '5.7.21', '5.7.22', '5.7.23', '5.7.24', '5.7.25', '5.7.26', '5.7.27', '5.7.28', '5.7.29', '5.7.30', '5.7.31', '5.7.32', '5.7.33', '5.7.34', '5.7.35', '5.7.36', '5.7.37', '5.7.38', '5.7.39', '5.7.40', '5.7.41', '5.7.42', '5.7.43', '5.7.44',

dist/src/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const semver_1 = require("semver");
1010
const Version_1 = __importDefault(require("./libraries/Version"));
1111
const Downloader_1 = require("./libraries/Downloader");
1212
const constants_1 = require("./constants");
13+
const LinuxOSRelease_1 = __importDefault(require("./libraries/LinuxOSRelease"));
1314
async function createDB(opts) {
1415
const suppliedOpts = opts || {};
1516
const suppliedOptsKeys = Object.keys(suppliedOpts);
@@ -34,7 +35,7 @@ async function createDB(opts) {
3435
if (throwUnsupportedError) {
3536
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.`;
3637
}
37-
logger.log('Version currently installed:', version);
38+
logger.log('Version currently installed:', version, 'Platform:', process.platform, 'etcOSRelease:', LinuxOSRelease_1.default);
3839
if (version === null || (options.version && !(0, semver_1.satisfies)(version.version, options.version)) || unsupportedMySQLIsInstalled) {
3940
let binaryInfo;
4041
let binaryFilepath;
@@ -47,7 +48,7 @@ async function createDB(opts) {
4748
throw `Failed to download binary. The error was: "${error}"`;
4849
}
4950
logger.log('Running downloaded binary');
50-
return await executor.startMySQL(options, { path: binaryFilepath, version: binaryInfo.version, installedOnSystem: false });
51+
return await executor.startMySQL(options, { path: binaryFilepath, version: binaryInfo.version, installedOnSystem: false, xPluginSupported: binaryInfo.xPluginSupported });
5152
}
5253
else {
5354
logger.log(version);

dist/src/libraries/Downloader.js

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,36 @@ function handleTarExtraction(filepath, extractedPath) {
5656
});
5757
});
5858
}
59+
function getFileDownloadURLRedirect(url) {
60+
const options = {
61+
headers: {
62+
'accept': '*/*',
63+
'connection': 'keep-alive'
64+
}
65+
};
66+
return new Promise((resolve, reject) => {
67+
const request = https.get(url, options, response => {
68+
const statusCode = response.statusCode;
69+
const location = response.headers.location;
70+
if (statusCode !== 302) {
71+
request.destroy();
72+
reject(`Received status code ${statusCode} while getting redirect URL for binary download. Used URL: ${url}`);
73+
return;
74+
}
75+
if (typeof location === 'string' && location.length > 0) {
76+
request.destroy();
77+
resolve(location);
78+
return;
79+
}
80+
request.destroy();
81+
reject(`Received incorrect URL information. Expected a non-empty string. Received: ${JSON.stringify(location)}`);
82+
});
83+
request.on('error', (err) => {
84+
request.destroy();
85+
reject(err.message);
86+
});
87+
});
88+
}
5989
function downloadFromCDN(url, downloadLocation, logger) {
6090
return new Promise(async (resolve, reject) => {
6191
if (fs.existsSync(downloadLocation)) {
@@ -139,7 +169,7 @@ function promisifiedZipExtraction(archiveLocation, extractedLocation) {
139169
});
140170
});
141171
}
142-
function extractBinary(url, archiveLocation, extractedLocation, logger) {
172+
function extractBinary(url, archiveLocation, extractedLocation, binaryInfo, logger) {
143173
return new Promise(async (resolve, reject) => {
144174
if (fs.existsSync(extractedLocation)) {
145175
logger.warn('Removing item at extractedLocation:', extractedLocation, 'so the MySQL binary can be stored there. This is probably because a previous download/extraction failed.');
@@ -148,12 +178,18 @@ function extractBinary(url, archiveLocation, extractedLocation, logger) {
148178
const lastDashIndex = url.lastIndexOf('-');
149179
const fileExtension = url.slice(lastDashIndex).split('.').splice(1).join('.');
150180
await fsPromises.mkdir(extractedLocation, { recursive: true });
151-
const splitURL = url.split('/');
152-
const mySQLFolderName = splitURL[splitURL.length - 1];
153-
if (!mySQLFolderName) {
154-
return reject(`Folder name is undefined for url: ${url}`);
181+
let folderName = '';
182+
if (binaryInfo.hostedByOracle) {
183+
const splitURL = url.split('/');
184+
const mySQLFolderName = splitURL[splitURL.length - 1];
185+
if (!mySQLFolderName) {
186+
return reject(`Folder name is undefined for url: ${url}`);
187+
}
188+
folderName = mySQLFolderName.replace(`.${fileExtension}`, '');
189+
}
190+
else {
191+
folderName = `mysql-${binaryInfo.version}`;
155192
}
156-
const folderName = mySQLFolderName.replace(`.${fileExtension}`, '');
157193
let extractionError = undefined;
158194
if (fileExtension === 'zip') {
159195
//Only Windows MySQL files use the .zip extension
@@ -255,13 +291,13 @@ function downloadBinary(binaryInfo, options, logger) {
255291
let downloadTries = 0;
256292
let useDownloadsURL = false;
257293
do {
294+
const downloadURL = binaryInfo.hostedByOracle ? `${useDownloadsURL ? constants_1.MySQLCDNDownloadsBaseURL : constants_1.MySQLCDNArchivesBaseURL}${url}` : await getFileDownloadURLRedirect(url);
258295
try {
259296
downloadTries++;
260-
const downloadURL = useDownloadsURL ? url.replace(constants_1.archiveBaseURL, constants_1.downloadsBaseURL) : url;
261297
logger.log(`Starting download for MySQL version ${version} from ${downloadURL}.`);
262298
await downloadFromCDN(downloadURL, archivePath, logger);
263299
logger.log(`Finished downloading MySQL version ${version} from ${downloadURL}. Now starting binary extraction.`);
264-
await extractBinary(downloadURL, archivePath, extractedPath, logger);
300+
await extractBinary(downloadURL, archivePath, extractedPath, binaryInfo, logger);
265301
logger.log(`Finished extraction for version ${version}`);
266302
break;
267303
}
@@ -276,22 +312,24 @@ function downloadBinary(binaryInfo, options, logger) {
276312
catch (e) {
277313
logger.error('An error occurred while deleting extractedPath and/or archivePath:', e);
278314
}
279-
if (e?.includes?.('status code 404')) {
280-
if (!useDownloadsURL) {
281-
//Retry with downloads URL
282-
downloadTries--;
315+
// If we got a 404 error while downloading a binary from Oracle and have not retried with the Downloads URL yet
316+
// then retry with the Downloads URL. Otherwise, reject.
317+
if (e?.includes('status code 404')) {
318+
if (binaryInfo.hostedByOracle && useDownloadsURL === false) {
283319
useDownloadsURL = true;
284-
logger.log(`Encountered error 404 when using archives URL for version ${version}. Now retrying with the downloads URL.`);
320+
downloadTries--;
285321
continue;
286322
}
287323
else {
288324
try {
289325
await releaseFunction();
290326
}
291327
catch (e) {
292-
logger.error('An error occurred while releasing lock after receiving a 404 error on both downloads and archives URLs. The error was:', e);
328+
logger.error('An error occurred while releasing lock after receiving a 404 error on download. The error was:', e);
329+
}
330+
finally {
331+
return reject(`Binary download for MySQL version ${binaryInfo.version} returned status code 404 at URL ${downloadURL}. Aborting download.`);
293332
}
294-
return reject(`Both URLs for MySQL version ${binaryInfo.version} returned status code 404. Aborting download.`);
295333
}
296334
}
297335
if (downloadTries > options.downloadRetries) {
@@ -322,17 +360,17 @@ function downloadBinary(binaryInfo, options, logger) {
322360
let downloadTries = 0;
323361
let useDownloadsURL = false;
324362
do {
363+
const downloadURL = binaryInfo.hostedByOracle ? `${useDownloadsURL ? constants_1.MySQLCDNDownloadsBaseURL : constants_1.MySQLCDNArchivesBaseURL}${url}` : await getFileDownloadURLRedirect(url);
325364
const uuid = (0, crypto_1.randomUUID)();
326365
const zipFilepath = `${dirpath}/${uuid}.${fileExtension}`;
327366
logger.log('Binary filepath:', zipFilepath);
328367
const extractedPath = `${dirpath}/${uuid}`;
329368
try {
330369
downloadTries++;
331-
const downloadURL = useDownloadsURL ? url.replace(constants_1.archiveBaseURL, constants_1.downloadsBaseURL) : url;
332370
logger.log(`Starting download for MySQL version ${version} from ${downloadURL}.`);
333371
await downloadFromCDN(downloadURL, zipFilepath, logger);
334372
logger.log(`Finished downloading MySQL version ${version} from ${downloadURL}. Now starting binary extraction.`);
335-
const binaryPath = await extractBinary(downloadURL, zipFilepath, extractedPath, logger);
373+
const binaryPath = await extractBinary(downloadURL, zipFilepath, extractedPath, binaryInfo, logger);
336374
logger.log(`Finished extraction for version ${version}`);
337375
return resolve(binaryPath);
338376
}
@@ -347,16 +385,16 @@ function downloadBinary(binaryInfo, options, logger) {
347385
catch (e) {
348386
logger.error('An error occurred while deleting extractedPath and/or archivePath:', e);
349387
}
350-
if (e?.includes?.('status code 404')) {
351-
if (!useDownloadsURL) {
352-
//Retry with downloads URL
353-
downloadTries--;
388+
// If we got a 404 error while downloading a binary from Oracle and have not retried with the Downloads URL yet
389+
// then retry with the Downloads URL. Otherwise, reject.
390+
if (e?.includes('status code 404')) {
391+
if (binaryInfo.hostedByOracle && useDownloadsURL === false) {
354392
useDownloadsURL = true;
355-
logger.log(`Encountered error 404 when using archives URL for version ${version}. Now retrying with the downloads URL.`);
393+
downloadTries--;
356394
continue;
357395
}
358396
else {
359-
return reject(`Both URLs for MySQL version ${binaryInfo.version} returned status code 404. Aborting download.`);
397+
return reject(`Binary download for MySQL version ${binaryInfo.version} returned status code 404 at URL ${downloadURL}. Aborting download.`);
360398
}
361399
}
362400
if (downloadTries > options.downloadRetries) {

dist/src/libraries/Executor.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ declare class Executor {
77
removeExitHandler: () => void;
88
version: string;
99
versionInstalledOnSystem: boolean;
10+
versionSupportsMySQLX: boolean;
1011
databasePath: string;
1112
killedFromPortIssue: boolean;
1213
constructor(logger: Logger);

0 commit comments

Comments
 (0)