diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index aafef048d..3b820eea5 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -248,6 +248,7 @@ All definitions files include a header with the author and editors, so at some p
* [Mousetrap](http://craig.is/killing/mice) (by [Dániel Tar](https://github.com/qcz))
* [msgpack.js](https://github.com/uupaa/msgpack.js) (by [Shinya Mochizuki](https://github.com/enrapt-mochizuki))
* [Mustache.js](https://github.com/janl/mustache.js) (by [Boris Yankov](https://github.com/borisyankov))
+* [mysql](https://github.com/felixge/node-mysql) (by [William Johnston](https://github.com/wjohnsto))
* [nconf](https://github.com/flatiron/nconf) (by [Jeff Goddard](https://github.com/jedigo))
* [noble](https://github.com/sandeepmistry/noble) (by [Seon-Wook Park](https://github.com/swook))
* [nock](https://github.com/pgte/nock) (by [bonnici](https://github.com/bonnici))
diff --git a/mysql/mysql-tests.ts b/mysql/mysql-tests.ts
new file mode 100644
index 000000000..83fdeb06a
--- /dev/null
+++ b/mysql/mysql-tests.ts
@@ -0,0 +1,381 @@
+///
+
+import mysql = require('mysql');
+
+/// Connections
+var connection = mysql.createConnection({
+ host: 'localhost',
+ user: 'me',
+ password: 'secret'
+});
+
+connection.connect();
+
+connection.query('SELECT 1 + 1 AS solution', function (err, rows, fields) {
+ if (err) throw err;
+
+ console.log('The solution is: ', rows[0].solution);
+});
+
+connection.end();
+
+connection = mysql.createConnection({
+ host: 'example.org',
+ user: 'bob',
+ password: 'secret'
+});
+
+connection.connect(function (err) {
+ if (err) {
+ console.error('error connecting: ' + err.stack);
+ return;
+ }
+
+ console.log('connected as id ' + connection.threadId);
+});
+
+connection.query('SELECT 1', function (err, rows) {
+ // connected! (unless `err` is set)
+});
+
+connection = mysql.createConnection({
+ host: 'localhost',
+ ssl: {
+ ca: ''
+ }
+});
+
+connection = mysql.createConnection({
+ host: 'localhost',
+ ssl: {
+ // DO NOT DO THIS
+ // set up your ca correctly to trust the connection
+ rejectUnauthorized: false
+ }
+});
+
+connection.end(function (err) {
+ // The connection is terminated now
+});
+
+connection.destroy();
+
+connection.changeUser({ user: 'john' }, function (err) {
+ if (err) throw err;
+});
+
+var userId = 'some user provided value';
+var sql = 'SELECT * FROM users WHERE id = ' + connection.escape(userId);
+connection.query(sql, function (err, results) {
+ // ...
+});
+connection.query('SELECT * FROM users WHERE id = ?', [userId], function (err, results) {
+ // ...
+});
+
+var post = { id: 1, title: 'Hello MySQL' };
+var query = connection.query('INSERT INTO posts SET ?', post, function (err, result) {
+ // Neat!
+});
+console.log(query.sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
+
+var queryStr = "SELECT * FROM posts WHERE title=" + mysql.escape("Hello MySQL");
+
+console.log(queryStr); // SELECT * FROM posts WHERE title='Hello MySQL'
+
+var sorter = 'date';
+var sql = 'SELECT * FROM posts ORDER BY ' + connection.escapeId(sorter);
+connection.query(sql, function (err, results) {
+ // ...
+});
+
+var sorter = 'date';
+var sql = 'SELECT * FROM posts ORDER BY ' + connection.escapeId('posts.' + sorter);
+connection.query(sql, function (err, results) {
+ // ...
+});
+
+var userIdNum = 1;
+var columns = ['username', 'email'];
+var query = connection.query('SELECT ?? FROM ?? WHERE id = ?', [columns, 'users', userIdNum], function (err, results) {
+ // ...
+});
+
+console.log(query.sql); // SELECT `username`, `email` FROM `users` WHERE id = 1
+
+var sql = "SELECT * FROM ?? WHERE ?? = ?";
+var inserts = ['users', 'id', userId];
+sql = mysql.format(sql, inserts);
+
+connection.config.queryFormat = function (query, values) {
+ if (!values) return query;
+ return query.replace(/\:(\w+)/g, function (txt: string, key: string) {
+ if (values.hasOwnProperty(key)) {
+ return this.escape(values[key]);
+ }
+ return txt;
+ }.bind(this));
+};
+
+connection.query("UPDATE posts SET title = :title", { title: "Hello MySQL" });
+
+connection.query('INSERT INTO posts SET ?', { title: 'test' }, function (err, result) {
+ if (err) throw err;
+
+ console.log(result.insertId);
+});
+
+connection.query('DELETE FROM posts WHERE title = "wrong"', function (err, result) {
+ if (err) throw err;
+
+ console.log('deleted ' + result.affectedRows + ' rows');
+});
+
+connection.query('UPDATE posts SET ...', function (err, result) {
+ if (err) throw err;
+
+ console.log('changed ' + result.changedRows + ' rows');
+});
+
+connection.connect(function (err) {
+ if (err) throw err;
+ console.log('connected as id ' + connection.threadId);
+});
+
+/// Pools
+
+var poolConfig = {
+ connectionLimit: 10,
+ host: 'example.org',
+ user: 'bob',
+ password: 'secret'
+};
+
+var pool = mysql.createPool(poolConfig);
+
+pool.query('SELECT 1 + 1 AS solution', function (err, rows, fields) {
+ if (err) throw err;
+
+ console.log('The solution is: ', rows[0].solution);
+});
+
+pool = mysql.createPool({
+ host: 'example.org',
+ user: 'bob',
+ password: 'secret'
+});
+
+pool.getConnection(function (err, connection) {
+ // connected! (unless `err` is set)
+});
+
+pool.on('connection', function (connection) {
+ connection.query('SET SESSION auto_increment_increment=1')
+});
+
+pool.getConnection(function (err, connection) {
+ // Use the connection
+ connection.query('SELECT something FROM sometable', function (err, rows) {
+ // And done with the connection.
+ connection.release();
+
+ // Don't use the connection here, it has been returned to the pool.
+ });
+});
+
+/// PoolClusters
+
+// create
+var poolCluster = mysql.createPoolCluster();
+
+poolCluster.add(poolConfig); // anonymous group
+poolCluster.add('MASTER', poolConfig);
+poolCluster.add('SLAVE1', poolConfig);
+poolCluster.add('SLAVE2', poolConfig);
+
+// Target Group : ALL(anonymous, MASTER, SLAVE1-2), Selector : round-robin(default)
+poolCluster.getConnection(function (err, connection) { });
+
+// Target Group : MASTER, Selector : round-robin
+poolCluster.getConnection('MASTER', function (err, connection) { });
+
+// Target Group : SLAVE1-2, Selector : order
+// If can't connect to SLAVE1, return SLAVE2. (remove SLAVE1 in the cluster)
+poolCluster.on('remove', function (nodeId) {
+ console.log('REMOVED NODE : ' + nodeId); // nodeId = SLAVE1
+});
+
+poolCluster.getConnection('SLAVE*', 'ORDER', function (err, connection) { });
+
+// of namespace : of(pattern, selector)
+poolCluster.of('*').getConnection(function (err, connection) { });
+
+var pool = poolCluster.of('SLAVE*', 'RANDOM');
+pool.getConnection(function (err, connection) { });
+pool.getConnection(function (err, connection) { });
+
+// destroy
+poolCluster.end();
+
+/// Queries
+
+var query = connection.query('SELECT * FROM posts');
+query
+ .on('error', function (err) {
+ // Handle error, an 'end' event will be emitted after this as well
+ })
+ .on('fields', function (fields) {
+ // the field packets for the rows to follow
+ })
+ .on('result', function (row) {
+ // Pausing the connnection is useful if your processing involves I/O
+ connection.pause();
+
+ var processRow = (row: any, cb: () => void) => {
+ cb();
+ };
+
+ processRow(row, function () {
+ connection.resume();
+ });
+ })
+ .on('end', function () {
+ // all rows have been received
+ });
+
+connection.query('SELECT * FROM posts')
+ .stream({ highWaterMark: 5 })
+ .pipe(() => { });
+
+connection = mysql.createConnection({ multipleStatements: true });
+
+connection.query('SELECT 1; SELECT 2', function (err, results) {
+ if (err) throw err;
+
+ // `results` is an array with one element for every statement in the query:
+ console.log(results[0]); // [{1: 1}]
+ console.log(results[1]); // [{2: 2}]
+});
+
+var query = connection.query('SELECT 1; SELECT 2');
+
+query
+ .on('fields', function (fields, index) {
+ // the fields for the result rows that follow
+ })
+ .on('result', function (row, index) {
+ // index refers to the statement this result belongs to (starts at 0)
+ });
+
+var options = { sql: '...', nestTables: true };
+
+connection.query(options, function (err, results) {
+ /* results will be an array like this now:
+ [{
+ table1: {
+ fieldA: '...',
+ fieldB: '...',
+ },
+ table2: {
+ fieldA: '...',
+ fieldB: '...',
+ },
+ }, ...]
+ */
+});
+
+connection.beginTransaction(function (err) {
+ var title = 'title';
+
+ if (err) { throw err; }
+ connection.query('INSERT INTO posts SET title=?', title, function (err, result) {
+ if (err) {
+ connection.rollback(function () {
+ throw err;
+ });
+ }
+
+ var log = 'Post ' + result.insertId + ' added';
+
+ connection.query('INSERT INTO log SET data=?', log, function (err, result) {
+ if (err) {
+ connection.rollback(function () {
+ throw err;
+ });
+ }
+ connection.commit(function (err) {
+ if (err) {
+ connection.rollback(function () {
+ throw err;
+ });
+ }
+ console.log('success!');
+ });
+ });
+ });
+});
+
+// Kill query after 60s
+connection.query({ sql: 'SELECT COUNT(*) AS count FROM big_table', timeout: 60000 }, function (err, rows) {
+ if (err && err.code === 'PROTOCOL_SEQUENCE_TIMEOUT') {
+ throw new Error('too long to count table rows!');
+ }
+
+ if (err) {
+ throw err;
+ }
+
+ console.log(rows[0].count + ' rows');
+});
+
+connection = mysql.createConnection({
+ port: 84943, // WRONG PORT
+});
+
+connection.connect(function (err) {
+ console.log(err.code); // 'ECONNREFUSED'
+ console.log(err.fatal); // true
+});
+
+connection.query('SELECT 1', function (err) {
+ console.log(err.code); // 'ECONNREFUSED'
+ console.log(err.fatal); // true
+});
+
+connection.query('USE name_of_db_that_does_not_exist', function (err, rows) {
+ console.log(err.code); // 'ER_BAD_DB_ERROR'
+});
+
+connection.query('SELECT 1', function (err, rows) {
+ console.log(err); // null
+ console.log(rows.length); // 1
+});
+
+connection.on('error', function (err) {
+ console.log(err.code); // 'ER_BAD_DB_ERROR'
+});
+
+connection.query('USE name_of_db_that_does_not_exist');
+
+// I am Chuck Norris:
+connection.on('error', function () { });
+
+connection = mysql.createConnection({ typeCast: false });
+
+var query = connection.query({ sql: '...', typeCast: false }, function (err, results) {
+
+});
+
+connection.query({
+ sql: '...',
+ typeCast: function (field: any, next: Function) {
+ if (field.type == 'TINY' && field.length == 1) {
+ return (field.string() == '1'); // 1 = true, 0 = false
+ }
+ return next();
+ }
+});
+
+connection = mysql.createConnection("mysql://localhost/test?flags=-FOUND_ROWS");
+connection = mysql.createConnection({ debug: true });
+connection = mysql.createConnection({ debug: ['ComQueryPacket', 'RowDataPacket'] });
diff --git a/mysql/mysql.d.ts b/mysql/mysql.d.ts
new file mode 100644
index 000000000..479b05266
--- /dev/null
+++ b/mysql/mysql.d.ts
@@ -0,0 +1,487 @@
+// Type definitions for node-mysql
+// Project: https://github.com/felixge/node-mysql
+// Definitions by: William Johnston
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+declare module mysql {
+ export interface IMySql {
+ createConnection(connectionUri: string): IConnection;
+ createConnection(config: IConnectionConfig): IConnection;
+
+ createPool(config: IPoolConfig): IPool;
+
+ createPoolCluster(config?: IPoolClusterConfig): IPoolCluster;
+
+ escape(value: any): string;
+
+ format(sql: string): string;
+ format(sql: string, values: Array): string;
+ }
+
+ export interface IConnectionStatic {
+ createQuery(sql: string): IQuery;
+ createQuery(sql: string, callback: (err: IError, ...args: any[]) => void): IQuery;
+ createQuery(sql: string, values: Array): IQuery;
+ createQuery(sql: string, values: Array, callback: (err: IError, ...args: any[]) => void): IQuery;
+ }
+
+ export interface IConnection {
+ config: IConnectionConfig;
+
+ threadId: number;
+
+ beginTransaction(callback: (err: IError) => void): void;
+
+ connect(): void;
+ connect(callback: (err: IError, ...args: any[]) => void): void;
+ connect(options: any, callback?: (err: IError, ...args: any[]) => void): void;
+
+ commit(callback: (err: IError) => void): void;
+
+ changeUser(options: IConnectionOptions): void;
+ changeUser(options: IConnectionOptions, callback: (err: IError) => void): void;
+
+ query: IQueryFunction;
+
+ end(): void;
+ end(callback: (err: IError, ...args: any[]) => void): void;
+ end(options: any, callback: (err: IError, ...args: any[]) => void): void;
+
+ destroy(): void;
+
+ pause(): void;
+
+ release(): void;
+ resume(): void;
+
+ escape(value: any): string;
+
+ escapeId(value: string): string;
+ escapeId(values: Array): string;
+
+ format(sql: string): string;
+ format(sql: string, values: Array): string;
+
+ on(ev: string, callback: (...args: any[]) => void): IConnection;
+ on(ev: 'error', callback: (err: IError) => void): IConnection;
+
+ rollback(callback: () => void): void;
+ }
+
+ export interface IPool {
+ config: IPoolConfig;
+
+ getConnection(callback: (err: IError, connection: IConnection) => void): void;
+
+ query: IQueryFunction;
+
+ on(ev: string, callback: (...args: any[]) => void): IPool;
+ on(ev: 'connection', callback: (connection: IConnection) => void): IPool;
+ on(ev: 'error', callback: (err: IError) => void): IPool;
+ }
+
+ export interface IPoolCluster {
+ config: IPoolClusterConfig;
+
+ add(config: IPoolConfig): void;
+ add(group: string, config: IPoolConfig): void;
+
+ end(): void;
+
+ getConnection(callback: (err: IError, connection: IConnection) => void): void;
+ getConnection(group: string, callback: (err: IError, connection: IConnection) => void): void;
+ getConnection(group: string, selector: string, callback: (err: IError, connection: IConnection) => void): void;
+
+ of(pattern: string): IPool;
+ of(pattern: string, selector: string): IPool;
+
+ on(ev: string, callback: (...args: any[]) => void): IPoolCluster;
+ on(ev: 'remove', callback: (nodeId: number) => void): IPoolCluster;
+ on(ev: 'connection', callback: (connection: IConnection) => void): IPoolCluster;
+ on(ev: 'error', callback: (err: IError) => void): IPoolCluster;
+ }
+
+ export interface IQuery {
+ /**
+ * The SQL for a constructed query
+ */
+ sql: string;
+
+ /**
+ * Emits a query packet to start the query
+ */
+ start(): void;
+
+ /**
+ * Determines the packet class to use given the first byte of the packet.
+ *
+ * @param firstByte The first byte of the packet
+ * @param parser The packet parser
+ */
+ determinePacket(firstByte: number, parser: any): any;
+
+ /**
+ * Creates a Readable stream with the given options
+ *
+ * @param options The options for the stream.
+ */
+ stream(options: IStreamOptions): IQuery;
+
+ /**
+ * Pipes a stream downstream, providing automatic pause/resume based on the
+ * options sent to the stream.
+ *
+ * @param options The options for the stream.
+ */
+ pipe(callback: (...args: any[]) => void): IQuery;
+
+ on(ev: string, callback: (...args: any[]) => void): IQuery;
+ on(ev: 'error', callback: (err: IError) => void): IQuery;
+ on(ev: 'fields', callback: (fields: any, index: number) => void): IQuery;
+ on(ev: 'result', callback: (row: any, index: number) => void): IQuery;
+ on(ev: 'end', callback: () => void): IQuery;
+ }
+
+ export interface IQueryFunction {
+ (sql: string): IQuery;
+ (sql: string, callback: (err: IError, ...args: any[]) => void): IQuery;
+ (sql: string, values: Array): IQuery;
+ (sql: string, values: Array, callback: (err: IError, ...args: any[]) => void): IQuery;
+ (sql: string, values: any): IQuery;
+ (sql: string, values: any, callback: (err: IError, ...args: any[]) => void): IQuery;
+ (options: IQueryOptions): IQuery;
+ (options: IQueryOptions, callback: (err: IError, ...args: any[]) => void): IQuery;
+ (options: IQueryOptions, values: Array): IQuery;
+ (options: IQueryOptions, values: Array, callback: (err: IError, ...args: any[]) => void): IQuery;
+ (options: IQueryOptions, values: any): IQuery;
+ (options: IQueryOptions, values: any, callback: (err: IError, ...args: any[]) => void): IQuery;
+ }
+
+ export interface IQueryOptions {
+ /**
+ * The SQL for the query
+ */
+ sql: string;
+
+ /**
+ * Every operation takes an optional inactivity timeout option. This allows you to specify appropriate timeouts for
+ * operations. It is important to note that these timeouts are not part of the MySQL protocol, and rather timeout
+ * operations through the client. This means that when a timeout is reached, the connection it occurred on will be
+ * destroyed and no further operations can be performed.
+ */
+ timeout?: number;
+
+ /**
+ * Either a boolean or string. If true, tables will be nested objects. If string (e.g. '_'), tables will be
+ * nested as tableName_fieldName
+ */
+ nestTables?: any;
+
+ /**
+ * Determines if column values should be converted to native JavaScript types. It is not recommended (and may go away / change in the future)
+ * to disable type casting, but you can currently do so on either the connection or query level. (Default: true)
+ *
+ * You can also specify a function (field: any, next: () => void) => {} to do the type casting yourself.
+ *
+ * WARNING: YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once.
+ *
+ * field.string()
+ * field.buffer()
+ * field.geometry()
+ *
+ * are aliases for
+ *
+ * parser.parseLengthCodedString()
+ * parser.parseLengthCodedBuffer()
+ * parser.parseGeometryValue()
+ *
+ * You can find which field function you need to use by looking at: RowDataPacket.prototype._typeCast
+ */
+ typeCast?: any;
+ }
+
+ export interface IStreamOptions {
+ /**
+ * Sets the max buffer size in objects of a stream
+ */
+ highWaterMark?: number;
+
+ /**
+ * The object mode of the stream (Default: true)
+ */
+ objectMode?: any;
+ }
+
+ export interface IConnectionOptions {
+ /**
+ * The MySQL user to authenticate as
+ */
+ user?: string;
+
+ /**
+ * The password of that MySQL user
+ */
+ password?: string;
+
+ /**
+ * Name of the database to use for this connection
+ */
+ database?: string;
+
+ /**
+ * The charset for the connection. This is called "collation" in the SQL-level of MySQL (like utf8_general_ci).
+ * If a SQL-level charset is specified (like utf8mb4) then the default collation for that charset is used.
+ * (Default: 'UTF8_GENERAL_CI')
+ */
+ charset?: string;
+ }
+
+ export interface IConnectionConfig extends IConnectionOptions {
+ /**
+ * The hostname of the database you are connecting to. (Default: localhost)
+ */
+ host?: string;
+
+ /**
+ * The port number to connect to. (Default: 3306)
+ */
+ port?: number;
+
+ /**
+ * The source IP address to use for TCP connection
+ */
+ localAddress?: string;
+
+ /**
+ * The path to a unix domain socket to connect to. When used host and port are ignored
+ */
+ socketPath?: string;
+
+ /**
+ * The timezone used to store local dates. (Default: 'local')
+ */
+ timezone?: string;
+
+ /**
+ * The milliseconds before a timeout occurs during the initial connection to the MySQL server. (Default: 10 seconds)
+ */
+ connectTimeout?: number;
+
+ /**
+ * Stringify objects instead of converting to values. (Default: 'false')
+ */
+ stringifyObjects?: boolean;
+
+ /**
+ * Allow connecting to MySQL instances that ask for the old (insecure) authentication method. (Default: false)
+ */
+ insecureAuth?: boolean;
+
+ /**
+ * Determines if column values should be converted to native JavaScript types. It is not recommended (and may go away / change in the future)
+ * to disable type casting, but you can currently do so on either the connection or query level. (Default: true)
+ *
+ * You can also specify a function (field: any, next: () => void) => {} to do the type casting yourself.
+ *
+ * WARNING: YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once.
+ *
+ * field.string()
+ * field.buffer()
+ * field.geometry()
+ *
+ * are aliases for
+ *
+ * parser.parseLengthCodedString()
+ * parser.parseLengthCodedBuffer()
+ * parser.parseGeometryValue()
+ *
+ * You can find which field function you need to use by looking at: RowDataPacket.prototype._typeCast
+ */
+ typeCast?: any;
+
+ /**
+ * A custom query format function
+ */
+ queryFormat?: (query: string, values: any) => void;
+
+ /**
+ * When dealing with big numbers (BIGINT and DECIMAL columns) in the database, you should enable this option
+ * (Default: false)
+ */
+ supportBigNumbers?: boolean;
+
+ /**
+ * Enabling both supportBigNumbers and bigNumberStrings forces big numbers (BIGINT and DECIMAL columns) to be
+ * always returned as JavaScript String objects (Default: false). Enabling supportBigNumbers but leaving
+ * bigNumberStrings disabled will return big numbers as String objects only when they cannot be accurately
+ * represented with [JavaScript Number objects] (http://ecma262-5.com/ELS5_HTML.htm#Section_8.5)
+ * (which happens when they exceed the [-2^53, +2^53] range), otherwise they will be returned as Number objects.
+ * This option is ignored if supportBigNumbers is disabled.
+ */
+ bigNumberStrings?: boolean;
+
+ /**
+ * Force date types (TIMESTAMP, DATETIME, DATE) to be returned as strings rather then inflated into JavaScript Date
+ * objects. (Default: false)
+ */
+ dateStrings?: boolean;
+
+ /**
+ * This will print all incoming and outgoing packets on stdout.
+ * You can also restrict debugging to packet types by passing an array of types (strings) to debug;
+ *
+ * (Default: false)
+ */
+ debug?: any;
+
+ /**
+ * Generates stack traces on Error to include call site of library entrance ("long stack traces"). Slight
+ * performance penalty for most calls. (Default: true)
+ */
+ trace?: boolean;
+
+ /**
+ * Allow multiple mysql statements per query. Be careful with this, it exposes you to SQL injection attacks. (Default: false)
+ */
+ multipleStatements?: boolean;
+
+ /**
+ * List of connection flags to use other than the default ones. It is also possible to blacklist default ones
+ */
+ flags?: Array;
+
+ /**
+ * object with ssl parameters or a string containing name of ssl profile
+ */
+ ssl?: any;
+ }
+
+ export interface IPoolConfig extends IConnectionConfig {
+ /**
+ * The milliseconds before a timeout occurs during the connection acquisition. This is slightly different from connectTimeout,
+ * because acquiring a pool connection does not always involve making a connection. (Default: 10 seconds)
+ */
+ acquireTimeout?: number;
+
+ /**
+ * Determines the pool's action when no connections are available and the limit has been reached. If true, the pool will queue
+ * the connection request and call it when one becomes available. If false, the pool will immediately call back with an error.
+ * (Default: true)
+ */
+ waitForConnections?: boolean;
+
+ /**
+ * The maximum number of connections to create at once. (Default: 10)
+ */
+ connectionLimit?: number;
+
+ /**
+ * The maximum number of connection requests the pool will queue before returning an error from getConnection. If set to 0, there
+ * is no limit to the number of queued connection requests. (Default: 0)
+ */
+ queueLimit?: number;
+ }
+
+ export interface IPoolClusterConfig {
+ /**
+ * If true, PoolCluster will attempt to reconnect when connection fails. (Default: true)
+ */
+ canRetry?: boolean;
+
+ /**
+ * If connection fails, node's errorCount increases. When errorCount is greater than removeNodeErrorCount,
+ * remove a node in the PoolCluster. (Default: 5)
+ */
+ removeNodeErrorCount?: number;
+
+ /**
+ * The default selector. (Default: RR)
+ * RR: Select one alternately. (Round-Robin)
+ * RANDOM: Select the node by random function.
+ * ORDER: Select the first node available unconditionally.
+ */
+ defaultSelector?: string;
+ }
+
+ export interface ISslCredentials {
+ /**
+ * A string or buffer holding the PFX or PKCS12 encoded private key, certificate and CA certificates
+ */
+ pfx?: string;
+
+ /**
+ * A string holding the PEM encoded private key
+ */
+ key?: string;
+
+ /**
+ * A string of passphrase for the private key or pfx
+ */
+ passphrase?: string;
+
+ /**
+ * A string holding the PEM encoded certificate
+ */
+ cert?: string;
+
+ /**
+ * Either a string or list of strings of PEM encoded CA certificates to trust.
+ */
+ ca?: Array;
+
+ /**
+ * Either a string or list of strings of PEM encoded CRLs (Certificate Revocation List)
+ */
+ crl?: Array;
+
+ /**
+ * A string describing the ciphers to use or exclude
+ */
+ ciphers?: string;
+ }
+
+ export interface IError extends Error {
+ /**
+ * Either a MySQL server error (e.g. 'ER_ACCESS_DENIED_ERROR'),
+ * a node.js error (e.g. 'ECONNREFUSED') or an internal error
+ * (e.g. 'PROTOCOL_CONNECTION_LOST').
+ */
+ code: string;
+
+ /**
+ * The error number for the error code
+ */
+ errno: number;
+
+ /**
+ * The sql state marker
+ */
+ sqlStateMarker?: string;
+
+ /**
+ * The sql state
+ */
+ sqlState?: string;
+
+ /**
+ * The field count
+ */
+ fieldCount?: number;
+
+ /**
+ * The stack trace for the error
+ */
+ stack?: string;
+
+ /**
+ * Boolean, indicating if this error is terminal to the connection object.
+ */
+ fatal: boolean;
+ }
+}
+
+declare module 'mysql' {
+ var mysql: mysql.IMySql;
+
+ export = mysql;
+}