2024-07-04 03:29:44 -07:00
|
|
|
import { createServer, type AddressInfo } from 'node:net';
|
2023-04-12 07:24:17 -07:00
|
|
|
import mysql2 from 'mysql2/promise';
|
2024-07-04 03:29:44 -07:00
|
|
|
import type {
|
|
|
|
ICredentialTestFunctions,
|
|
|
|
IDataObject,
|
|
|
|
IExecuteFunctions,
|
|
|
|
ILoadOptionsFunctions,
|
|
|
|
} from 'n8n-workflow';
|
2023-04-12 07:24:17 -07:00
|
|
|
|
2023-08-09 04:30:53 -07:00
|
|
|
import { formatPrivateKey } from '@utils/utilities';
|
2024-07-04 03:29:44 -07:00
|
|
|
import type { Mysql2Pool, MysqlNodeCredentials } from '../helpers/interfaces';
|
|
|
|
import { LOCALHOST } from '@utils/constants';
|
2023-04-12 07:24:17 -07:00
|
|
|
|
|
|
|
export async function createPool(
|
2024-07-04 03:29:44 -07:00
|
|
|
this: IExecuteFunctions | ICredentialTestFunctions | ILoadOptionsFunctions,
|
|
|
|
credentials: MysqlNodeCredentials,
|
2023-04-12 07:24:17 -07:00
|
|
|
options?: IDataObject,
|
|
|
|
): Promise<Mysql2Pool> {
|
2024-07-04 03:29:44 -07:00
|
|
|
const connectionOptions: mysql2.ConnectionOptions = {
|
|
|
|
host: credentials.host,
|
|
|
|
port: credentials.port,
|
|
|
|
database: credentials.database,
|
|
|
|
user: credentials.user,
|
|
|
|
password: credentials.password,
|
|
|
|
multipleStatements: true,
|
|
|
|
supportBigNumbers: true,
|
|
|
|
};
|
2023-04-12 07:24:17 -07:00
|
|
|
|
2024-07-04 03:29:44 -07:00
|
|
|
if (credentials.ssl) {
|
|
|
|
connectionOptions.ssl = {};
|
2023-04-12 07:24:17 -07:00
|
|
|
|
2024-07-04 03:29:44 -07:00
|
|
|
if (credentials.caCertificate) {
|
|
|
|
connectionOptions.ssl.ca = formatPrivateKey(credentials.caCertificate);
|
2023-04-12 07:24:17 -07:00
|
|
|
}
|
|
|
|
|
2024-07-04 03:29:44 -07:00
|
|
|
if (credentials.clientCertificate || credentials.clientPrivateKey) {
|
|
|
|
connectionOptions.ssl.cert = formatPrivateKey(credentials.clientCertificate);
|
|
|
|
connectionOptions.ssl.key = formatPrivateKey(credentials.clientPrivateKey);
|
2023-04-12 07:24:17 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-03 08:45:21 -07:00
|
|
|
if (options?.nodeVersion && (options.nodeVersion as number) >= 2.1) {
|
|
|
|
connectionOptions.dateStrings = true;
|
|
|
|
}
|
|
|
|
|
2023-04-12 07:24:17 -07:00
|
|
|
if (options?.connectionLimit) {
|
|
|
|
connectionOptions.connectionLimit = options.connectionLimit as number;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options?.connectTimeout) {
|
|
|
|
connectionOptions.connectTimeout = options.connectTimeout as number;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options?.largeNumbersOutput === 'text') {
|
|
|
|
connectionOptions.bigNumberStrings = true;
|
|
|
|
}
|
|
|
|
|
2024-07-04 03:29:44 -07:00
|
|
|
if (!credentials.sshTunnel) {
|
2023-04-12 07:24:17 -07:00
|
|
|
return mysql2.createPool(connectionOptions);
|
|
|
|
} else {
|
2024-07-04 03:29:44 -07:00
|
|
|
if (credentials.sshAuthenticateWith === 'privateKey' && credentials.privateKey) {
|
|
|
|
credentials.privateKey = formatPrivateKey(credentials.privateKey as string);
|
2023-04-12 07:24:17 -07:00
|
|
|
}
|
2024-07-04 03:29:44 -07:00
|
|
|
const sshClient = await this.helpers.getSSHClient(credentials);
|
|
|
|
|
|
|
|
// Find a free TCP port
|
|
|
|
const localPort = await new Promise<number>((resolve) => {
|
|
|
|
const tempServer = createServer();
|
|
|
|
tempServer.listen(0, LOCALHOST, () => {
|
|
|
|
resolve((tempServer.address() as AddressInfo).port);
|
|
|
|
tempServer.close();
|
|
|
|
});
|
|
|
|
});
|
2023-04-12 07:24:17 -07:00
|
|
|
|
2024-07-04 03:29:44 -07:00
|
|
|
const stream = await new Promise((resolve, reject) => {
|
|
|
|
sshClient.forwardOut(
|
|
|
|
LOCALHOST,
|
|
|
|
localPort,
|
|
|
|
credentials.host,
|
|
|
|
credentials.port,
|
|
|
|
(err, clientChannel) => {
|
|
|
|
if (err) return reject(err);
|
|
|
|
resolve(clientChannel);
|
|
|
|
},
|
|
|
|
);
|
2023-04-12 07:24:17 -07:00
|
|
|
});
|
|
|
|
|
2024-07-04 03:29:44 -07:00
|
|
|
return mysql2.createPool({
|
|
|
|
...connectionOptions,
|
|
|
|
stream,
|
|
|
|
});
|
2023-04-12 07:24:17 -07:00
|
|
|
}
|
|
|
|
}
|