(true);
+ const { siteConfig } = useDocusaurusContext();
+ const baseUrl = siteConfig.baseUrl.replace(/\/$/, '');
+ const finalURL = /^\//.test(url) ? `${baseUrl}${url}` : url;
+
+ useEffect(() => {
+ const controller = new AbortController();
+ const signal = controller.signal;
+
+ fetch(finalURL, { signal })
+ .then((response) => response.text())
+ .then((text) => {
+ setCode(text);
+ setLoading(false);
+ setError(false);
+ })
+ .catch(() => {
+ setError(true);
+ setLoading(false);
+ });
+
+ return () => {
+ controller.abort();
+ };
+ }, [finalURL]);
+
+ return (
+ <>
+ {loading ? (
+
+ ) : (
+ <>
+ {error ? (
+
+ Unable to access the requested link: {finalURL}
.
+ Please verify the link or try again later.
+
+ ) : (
+ {code}
+ )}
+ >
+ )}
+ >
+ );
+};
diff --git a/website/src/components/Loading.tsx b/website/src/components/Loading.tsx
new file mode 100644
index 0000000000..dca85ed72a
--- /dev/null
+++ b/website/src/components/Loading.tsx
@@ -0,0 +1,4 @@
+/**
+ * Credits: https://cssloaders.github.io/
+ */
+export const Loading = () => ;
diff --git a/website/src/components/PageTitle.tsx b/website/src/components/PageTitle.tsx
new file mode 100644
index 0000000000..9500df8c80
--- /dev/null
+++ b/website/src/components/PageTitle.tsx
@@ -0,0 +1,29 @@
+import { FC } from 'react';
+import Head from '@docusaurus/Head';
+
+export type PageTitleProps = {
+ title: string;
+};
+
+/**
+ * **Force a custom Tab Title:** this component sets a specific title for the browser tab.
+ *
+ * Use it to override the default title derived from the document or page content.
+ *
+ * ℹ️ Ideal for situations where the tab title needs to be different from the page's main heading or `.mdx` title.
+ *
+ * ---
+ *
+ * **Usage:**
+ *
+ * ```tsx
+ *
+ * ```
+ */
+export const PageTitle: FC = ({ title }) => {
+ return (
+
+ {title}
+
+ );
+};
diff --git a/website/src/css/custom.scss b/website/src/css/custom.scss
index 61fe2fb92f..1855f10ad7 100644
--- a/website/src/css/custom.scss
+++ b/website/src/css/custom.scss
@@ -80,3 +80,48 @@ pre[class*='language-'] {
}
}
}
+
+[title='
currentLocale === 'en'
- ? '/node-mysql2/docs'
- : `/node-mysql2/${currentLocale}/docs`;
+ ? `${baseUrl}docs`
+ : `${baseUrl}${currentLocale}/docs`;
const redirectUrl = setLocaleRedirectMap();
return ;
diff --git a/website/static/examples/binlog-watcher.js b/website/static/examples/binlog-watcher.js
new file mode 100644
index 0000000000..8ac1fabd7c
--- /dev/null
+++ b/website/static/examples/binlog-watcher.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const mysql = require('mysql2');
+const through2 = require('through2');
+
+const binlogStream = mysql.createBinlogStream({
+ serverId: 123, // slave ID, first field in "show slave hosts" sql response
+ // you can also specify slave host, username, password and port
+ masterId: 0,
+ filename: 'mysql-bin.000007',
+ binlogPos: 120,
+ flags: 1, // 1 = "non-blocking mode"
+});
+
+binlogStream.pipe(
+ through2.obj((obj, enc, next) => {
+ console.log(obj);
+ next();
+ })
+);
diff --git a/website/static/examples/connect-over-socks.js b/website/static/examples/connect-over-socks.js
new file mode 100644
index 0000000000..ac7022957d
--- /dev/null
+++ b/website/static/examples/connect-over-socks.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const mysql = require('mysql2');
+const SocksConnection = require('socksjs');
+
+// const socksProxy = new SocksConnection({ port: 3306 });
+// const conn = mysql.createConnection({
+// stream: socksProxy,
+// });
+
+// conn.query("select 1+1", function(err, rows, fields) {
+// console.log(err, rows, fields);
+// });
+
+const conn1 = mysql.createPool({
+ debug: 1,
+ stream: function () {
+ return new SocksConnection({ port: 3306 });
+ },
+});
+
+conn1.execute('select sleep(1.1) as www', (err, rows, fields) => {
+ console.log(err, rows, fields);
+});
+
+conn1.execute('select sleep(1) as qqq', (err, rows, fields) => {
+ console.log(err, rows, fields);
+});
+
+conn1.execute('select sleep(1) as qqq', (err, rows, fields) => {
+ console.log(err, rows, fields);
+});
diff --git a/website/static/examples/execute.js b/website/static/examples/execute.js
new file mode 100644
index 0000000000..c44a28d72a
--- /dev/null
+++ b/website/static/examples/execute.js
@@ -0,0 +1,34 @@
+'use strict';
+
+// get the client
+const mysql = require('mysql2');
+
+// create the connection to database
+const connection = mysql.createConnection({
+ host: 'localhost',
+ user: 'root',
+ database: 'test',
+});
+
+connection.execute(
+ 'select ?+1 as qqq, ? as rrr, ? as yyy',
+ [1, null, 3],
+ (err, rows, fields) => {
+ console.log(err, rows, fields);
+ connection.execute(
+ 'select ?+1 as qqq, ? as rrr, ? as yyy',
+ [3, null, 3],
+ (err, rows, fields) => {
+ console.log(err, rows, fields);
+ connection.unprepare('select ?+1 as qqq, ? as rrr, ? as yyy');
+ connection.execute(
+ 'select ?+1 as qqq, ? as rrr, ? as yyy',
+ [3, null, 3],
+ (err, rows, fields) => {
+ console.log(err, rows, fields);
+ }
+ );
+ }
+ );
+ }
+);
diff --git a/website/static/examples/mysqlproxy.js b/website/static/examples/mysqlproxy.js
new file mode 100644
index 0000000000..9ed5748ed6
--- /dev/null
+++ b/website/static/examples/mysqlproxy.js
@@ -0,0 +1,55 @@
+'use strict';
+
+const mysql = require('mysql2');
+const ClientFlags = require('mysql2/lib/constants/client.js');
+
+const server = mysql.createServer();
+server.listen(3307);
+
+server.on('connection', (conn) => {
+ console.log('connection');
+
+ conn.serverHandshake({
+ protocolVersion: 10,
+ serverVersion: 'node.js rocks',
+ connectionId: 1234,
+ statusFlags: 2,
+ characterSet: 8,
+ capabilityFlags: 0xffffff ^ ClientFlags.COMPRESS,
+ });
+
+ conn.on('field_list', (table, fields) => {
+ console.log('field list:', table, fields);
+ conn.writeEof();
+ });
+
+ const remote = mysql.createConnection({
+ user: 'root',
+ database: 'dbname',
+ host: 'server.example.com',
+ password: 'secret',
+ });
+
+ conn.on('query', (sql) => {
+ console.log(`proxying query: ${sql}`);
+ remote.query(sql, function (err) {
+ // overloaded args, either (err, result :object)
+ // or (err, rows :array, columns :array)
+ if (Array.isArray(arguments[1])) {
+ // response to a 'select', 'show' or similar
+ const rows = arguments[1],
+ columns = arguments[2];
+ console.log('rows', rows);
+ console.log('columns', columns);
+ conn.writeTextResult(rows, columns);
+ } else {
+ // response to an 'insert', 'update' or 'delete'
+ const result = arguments[1];
+ console.log('result', result);
+ conn.writeOk(result);
+ }
+ });
+ });
+
+ conn.on('end', remote.end.bind(remote));
+});
diff --git a/website/static/examples/pass-sha.js b/website/static/examples/pass-sha.js
new file mode 100644
index 0000000000..92a720b812
--- /dev/null
+++ b/website/static/examples/pass-sha.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const mysql = require('mysql2').createConnection({
+ host: 'localhost',
+ user: 'root',
+ database: 'test',
+ passwordSha1: Buffer.from('8bb6118f8fd6935ad0876a3be34a717d32708ffd', 'hex'),
+});
+
+mysql.execute(
+ 'select ?+1 as qqq, ? as rrr, ? as yyy',
+ [1, null, 3],
+ (err, rows, fields) => {
+ console.log(err, rows, fields);
+ }
+);
diff --git a/website/static/examples/pool-test.js b/website/static/examples/pool-test.js
new file mode 100644
index 0000000000..7f5a5261ed
--- /dev/null
+++ b/website/static/examples/pool-test.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const pool = require('mysql2').createPool({
+ host: 'localhost',
+ user: 'root',
+ database: 'test',
+ password: 'root',
+});
+
+setInterval(() => {
+ for (let i = 0; i < 5; ++i) {
+ pool.query((err, rows, fields) => {
+ console.log(rows, fields);
+ // Connection is automatically released once query resolves
+ });
+ }
+}, 1000);
+
+setInterval(() => {
+ for (let i = 0; i < 5; ++i) {
+ pool.getConnection((err, db) => {
+ db.query('select sleep(0.5) as qqq', (err, rows, fields) => {
+ console.log(rows, fields);
+ db.release();
+ });
+ });
+ }
+}, 1000);
diff --git a/website/static/examples/prepare.js b/website/static/examples/prepare.js
new file mode 100644
index 0000000000..53d533152f
--- /dev/null
+++ b/website/static/examples/prepare.js
@@ -0,0 +1,24 @@
+'use strict';
+
+// get the client
+const mysql = require('mysql2');
+
+// create the connection to database
+const connection = mysql.createConnection({
+ host: 'localhost',
+ user: 'root',
+ database: 'test',
+});
+
+// execute will internally call prepare and query
+connection.execute(
+ 'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
+ ['Rick C-137', 53],
+ (err, results, fields) => {
+ console.log(results); // results contains rows returned by server
+ console.log(fields); // fields contains extra meta data about results, if available
+
+ // If you execute same statement again, it will be picked form a LRU cache
+ // which will save query preparation time and give better performance
+ }
+);
diff --git a/website/static/examples/promise-co-await/await.js b/website/static/examples/promise-co-await/await.js
new file mode 100644
index 0000000000..198114c567
--- /dev/null
+++ b/website/static/examples/promise-co-await/await.js
@@ -0,0 +1,68 @@
+'use strict';
+
+const mysql = require('mysql2/promise');
+
+async function test() {
+ const c = await mysql.createConnection({
+ port: 3306,
+ user: 'testuser',
+ namedPlaceholders: true,
+ password: 'testpassword',
+ });
+ console.log('connected!');
+ const [rows, fields] = await c.query('show databases');
+ console.log(rows);
+
+ try {
+ const [rows, fields] = await c.query('some invalid sql here');
+ } catch (e) {
+ console.log('caught exception!', e);
+ }
+
+ console.log(await c.execute('select sleep(0.5)'));
+ console.log('after first sleep');
+ console.log(await c.execute('select sleep(0.5)'));
+ console.log('after second sleep');
+ let start = +new Date();
+ console.log(
+ await Promise.all([
+ c.execute('select sleep(2.5)'),
+ c.execute('select sleep(2.5)'),
+ ])
+ );
+ console.log(
+ 'after 2+3 parallel sleep which is in fact not parallel because commands are queued per connection'
+ );
+ let end = +new Date();
+ console.log(end - start);
+ await c.end();
+
+ const p = mysql.createPool({
+ port: 3306,
+ user: 'testuser',
+ namedPlaceholders: true,
+ password: 'testpassword',
+ });
+ console.log(await p.execute('select sleep(0.5)'));
+ console.log('after first pool sleep');
+ start = +new Date();
+ console.log(
+ await Promise.all([
+ p.execute('select sleep(2.5)'),
+ p.execute('select sleep(2.5)'),
+ ])
+ );
+ console.log('after 2+3 parallel pool sleep');
+ end = +new Date();
+ console.log(end - start);
+ await p.end();
+}
+
+test()
+ .then(() => {
+ console.log('done');
+ })
+ .catch((err) => {
+ console.log('error!', err);
+ throw err;
+ });
diff --git a/website/static/examples/promise-co-await/babelrc.json b/website/static/examples/promise-co-await/babelrc.json
new file mode 100644
index 0000000000..0d67235e87
--- /dev/null
+++ b/website/static/examples/promise-co-await/babelrc.json
@@ -0,0 +1,3 @@
+{
+ "plugins": ["transform-async-to-generator"]
+}
diff --git a/website/static/examples/promise-co-await/co.js b/website/static/examples/promise-co-await/co.js
new file mode 100644
index 0000000000..caa9c8d52e
--- /dev/null
+++ b/website/static/examples/promise-co-await/co.js
@@ -0,0 +1,23 @@
+'use strict';
+
+const mysql = require('mysql2/promise');
+const co = require('co');
+
+co(function* () {
+ const c = yield mysql.createConnection({
+ port: 3306,
+ user: 'root',
+ namedPlaceholders: true,
+ });
+ const rows = yield c.query('show databases');
+ console.log(rows);
+ console.log(yield c.execute('select 1+:toAdd as qqq', { toAdd: 10 }));
+ yield c.end();
+})
+ .then(function () {
+ console.log('done');
+ })
+ .catch(function (err) {
+ console.log(err);
+ throw err;
+ });
diff --git a/website/static/examples/promise-co-await/package.json b/website/static/examples/promise-co-await/package.json
new file mode 100644
index 0000000000..38f35dc103
--- /dev/null
+++ b/website/static/examples/promise-co-await/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "promise-co-await",
+ "version": "1.0.0",
+ "description": "",
+ "main": "await.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "babel-cli": "^6.9.0"
+ }
+}
diff --git a/website/static/examples/queries/select.js b/website/static/examples/queries/select.js
new file mode 100644
index 0000000000..c983e77176
--- /dev/null
+++ b/website/static/examples/queries/select.js
@@ -0,0 +1,29 @@
+'use strict';
+
+// get the client
+const mysql = require('mysql2');
+
+// create the connection to database
+const connection = mysql.createConnection({
+ host: 'localhost',
+ user: 'root',
+ database: 'test',
+});
+
+// simple query
+connection.query(
+ 'SELECT * FROM `table` WHERE `name` = "Page" AND `age` > 45',
+ (err, results, fields) => {
+ console.log(results); // results contains rows returned by server
+ console.log(fields); // fields contains extra meta data about results, if available
+ }
+);
+
+// with placeholder
+connection.query(
+ 'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
+ ['Page', 45],
+ (err, results) => {
+ console.log(results);
+ }
+);
diff --git a/website/static/examples/server.js b/website/static/examples/server.js
new file mode 100644
index 0000000000..edd1d66444
--- /dev/null
+++ b/website/static/examples/server.js
@@ -0,0 +1,68 @@
+'use strict';
+
+const mysql = require('mysql2');
+const flags = require('mysql2/lib/constants/client.js');
+const auth = require('mysql2/lib/auth_41.js');
+
+function authenticate(params, cb) {
+ console.log(params);
+ const doubleSha = auth.doubleSha1('pass123');
+ const isValid = auth.verifyToken(
+ params.authPluginData1,
+ params.authPluginData2,
+ params.authToken,
+ doubleSha
+ );
+ if (isValid) {
+ cb(null);
+ } else {
+ // for list of codes lib/constants/errors.js
+ cb(null, { message: 'wrong password dude', code: 1045 });
+ }
+}
+
+const server = mysql.createServer();
+server.listen(3333);
+server.on('connection', (conn) => {
+ // we can deny connection here:
+ // conn.writeError({ message: 'secret', code: 123 });
+ // conn.close();
+ conn.serverHandshake({
+ protocolVersion: 10,
+ serverVersion: '5.6.10', // 'node.js rocks',
+ connectionId: 1234,
+ statusFlags: 2,
+ characterSet: 8,
+ // capabilityFlags: 0xffffff,
+ // capabilityFlags: -2113931265,
+ capabilityFlags: 2181036031,
+ authCallback: authenticate,
+ });
+
+ conn.on('field_list', (table, fields) => {
+ console.log('FIELD LIST:', table, fields);
+ conn.writeEof();
+ });
+
+ conn.on('query', (query) => {
+ conn.writeColumns([
+ {
+ catalog: 'def',
+ schema: 'test',
+ table: 'test_table',
+ orgTable: 'test_table',
+ name: 'beta',
+ orgName: 'beta',
+ characterSet: 33,
+ columnLength: 384,
+ columnType: 253,
+ flags: 0,
+ decimals: 0,
+ },
+ ]);
+ conn.writeTextRow(['test тест テスト փորձարկում পরীক্ষা kiểm tra ']);
+ conn.writeTextRow(['ტესტი પરીક્ષણ מבחן פּרובירן اختبار परीक्षण']);
+ conn.writeEof();
+ conn.close();
+ });
+});
diff --git a/website/static/examples/ssl/rds-ssl.js b/website/static/examples/ssl/rds-ssl.js
new file mode 100644
index 0000000000..5930bef134
--- /dev/null
+++ b/website/static/examples/ssl/rds-ssl.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const mysql = require('mysql2');
+
+const conn = mysql.createConnection({
+ user: process.env.USER,
+ password: process.env.PASSWORD,
+ database: process.env.DB,
+ host: process.env.HOST,
+ port: 3306,
+ ssl: 'Amazon RDS',
+});
+
+conn.query("show status like 'Ssl_cipher'", function (err, res) {
+ console.log(err, res);
+ conn.end();
+});
diff --git a/website/static/examples/ssl/select-over-ssl.js b/website/static/examples/ssl/select-over-ssl.js
new file mode 100644
index 0000000000..b051908b78
--- /dev/null
+++ b/website/static/examples/ssl/select-over-ssl.js
@@ -0,0 +1,24 @@
+'use strict';
+
+const fs = require('fs');
+const mysql = require('mysql2');
+
+const conn = mysql.createConnection({
+ user: 'root',
+ password: '',
+ database: 'test',
+ host: '127.0.0.1',
+ port: '3306',
+ ssl: {
+ // key: fs.readFileSync('./certs/client-key.pem'),
+ // cert: fs.readFileSync('./certs/client-cert.pem')
+ ca: fs.readFileSync('./certs/ca-cert.pem'),
+ },
+});
+
+conn.query('select 1+1 as test', function (err, res) {
+ console.log(res);
+ conn.query('select repeat("a", 100) as test', function (err, res) {
+ console.log(res);
+ });
+});
diff --git a/website/static/examples/typescript/basic-custom-class.ts b/website/static/examples/typescript/basic-custom-class.ts
new file mode 100644
index 0000000000..c26605cfb6
--- /dev/null
+++ b/website/static/examples/typescript/basic-custom-class.ts
@@ -0,0 +1,141 @@
+/**
+ * The types are explicity for learning purpose
+ */
+
+import {
+ createPool,
+ PoolOptions,
+ Pool,
+ ResultSetHeader,
+ RowDataPacket,
+} from 'mysql2/promise';
+
+interface User extends RowDataPacket {
+ id: number;
+ name: string;
+}
+
+class MySQL {
+ private conn: Pool;
+ private credentials: PoolOptions;
+
+ constructor(credentials: PoolOptions) {
+ this.credentials = credentials;
+ this.conn = createPool(this.credentials);
+ }
+
+ /** A random method to simulate a step before to get the class methods */
+ private ensureConnection() {
+ if (!this?.conn) this.conn = createPool(this.credentials);
+ }
+
+ /** For `SELECT` and `SHOW` */
+ get queryRows() {
+ this.ensureConnection();
+ return this.conn.query.bind(this.conn);
+ }
+
+ /** For `SELECT` and `SHOW` with `rowAsArray` as `true` */
+ get queryRowsAsArray() {
+ this.ensureConnection();
+ return this.conn.query.bind(this.conn);
+ }
+
+ /** For `INSERT`, `UPDATE`, etc. */
+ get queryResult() {
+ this.ensureConnection();
+ return this.conn.query.bind(this.conn);
+ }
+
+ /** For multiple `INSERT`, `UPDATE`, etc. with `multipleStatements` as `true` */
+ get queryResults() {
+ this.ensureConnection();
+ return this.conn.query.bind(this.conn);
+ }
+
+ /** For `SELECT` and `SHOW` */
+ get executeRows() {
+ this.ensureConnection();
+ return this.conn.execute.bind(this.conn);
+ }
+
+ /** For `SELECT` and `SHOW` with `rowAsArray` as `true` */
+ get executeRowsAsArray() {
+ this.ensureConnection();
+ return this.conn.execute.bind(this.conn);
+ }
+
+ /** For `INSERT`, `UPDATE`, etc. */
+ get executeResult() {
+ this.ensureConnection();
+ return this.conn.execute.bind(this.conn);
+ }
+
+ /** For multiple `INSERT`, `UPDATE`, etc. with `multipleStatements` as `true` */
+ get executeResults() {
+ this.ensureConnection();
+ return this.conn.execute.bind(this.conn);
+ }
+
+ /** Expose the Pool Connection */
+ get connection() {
+ return this.conn;
+ }
+}
+
+(async () => {
+ const access: PoolOptions = {
+ host: '',
+ user: '',
+ password: '',
+ database: '',
+ };
+
+ const mysql = new MySQL(access);
+
+ /** Deleting the `users` table, if it exists */
+ await mysql.queryResult('DROP TABLE IF EXISTS `users`;');
+
+ /** Creating a minimal user table */
+ await mysql.queryResult(
+ 'CREATE TABLE `users` (`id` INT(11) AUTO_INCREMENT, `name` VARCHAR(50), PRIMARY KEY (`id`));'
+ );
+
+ /** Inserting some users */
+ const [inserted] = await mysql.executeResult(
+ 'INSERT INTO `users`(`name`) VALUES(?), (?), (?), (?);',
+ ['Josh', 'John', 'Marie', 'Gween']
+ );
+
+ console.log('Inserted:', inserted.affectedRows);
+
+ /** Getting users */
+ const [users] = await mysql.queryRows(
+ 'SELECT * FROM `users` ORDER BY `name` ASC;'
+ );
+
+ users.forEach((user: User) => {
+ console.log('-----------');
+ console.log('id: ', user.id);
+ console.log('name:', user.name);
+ });
+
+ await mysql.connection.end();
+})();
+
+/** Output
+ *
+ * Inserted: 4
+ * -----------
+ * id: 4
+ * name: Gween
+ * -----------
+ * id: 2
+ * name: John
+ * -----------
+ * id: 1
+ * name: Josh
+ * -----------
+ * id: 3
+ * name: Marie
+ */
diff --git a/website/static/examples/typescript/procedure-call-packet-row-as-array.ts b/website/static/examples/typescript/procedure-call-packet-row-as-array.ts
new file mode 100644
index 0000000000..a4ad962590
--- /dev/null
+++ b/website/static/examples/typescript/procedure-call-packet-row-as-array.ts
@@ -0,0 +1,112 @@
+/**
+ * The types are explicity for learning purpose
+ * By extending the `RowDataPacket`, you can use your Interface in `query` and `execute`
+ */
+
+import mysql, {
+ ConnectionOptions,
+ ProcedureCallPacket,
+ ResultSetHeader,
+ RowDataPacket,
+} from 'mysql2/promise';
+
+interface User extends RowDataPacket {
+ /** id */
+ 0: number;
+ /** name */
+ 1: string;
+}
+
+const isResultSetHeader = (data: unknown): data is ResultSetHeader => {
+ if (!data || typeof data !== 'object') return false;
+
+ const keys = [
+ 'fieldCount',
+ 'affectedRows',
+ 'insertId',
+ 'info',
+ 'serverStatus',
+ 'warningStatus',
+ 'changedRows',
+ ];
+
+ return keys.every((key) => key in data);
+};
+
+(async () => {
+ const access: ConnectionOptions = {
+ host: '',
+ user: '',
+ password: '',
+ database: '',
+ rowsAsArray: true,
+ };
+
+ const conn = await mysql.createConnection(access);
+
+ /** Deleting the `users` table, if it exists */
+ await conn.query('DROP TABLE IF EXISTS `users`;');
+
+ /** Creating a minimal user table */
+ await conn.query(
+ 'CREATE TABLE `users` (`id` INT(11) AUTO_INCREMENT, `name` VARCHAR(50), PRIMARY KEY (`id`));'
+ );
+
+ /** Inserting some users */
+ const [inserted] = await conn.execute(
+ 'INSERT INTO `users`(`name`) VALUES(?), (?), (?), (?);',
+ ['Josh', 'John', 'Marie', 'Gween']
+ );
+
+ console.log('Inserted:', inserted.affectedRows);
+
+ /** Deleting the `getUsers` procedure, if it exists */
+ await conn.query('DROP PROCEDURE IF EXISTS getUsers');
+
+ /** Creating a procedure to get the users */
+ await conn.query(`
+ CREATE PROCEDURE getUsers()
+ BEGIN
+ SELECT * FROM users ORDER BY name ASC;
+ END
+ `);
+
+ /** Getting users */
+ const [procedureResult] =
+ await conn.query>('CALL getUsers()');
+
+ procedureResult.forEach((users) => {
+ /** By perform a `SELECT` or `SHOW`, The last item of `procedureResult` always be a `ResultSetHeader` */
+ if (isResultSetHeader(users)) {
+ console.log('----------------');
+ console.log('Affected Rows:', users.affectedRows);
+ } else {
+ users.forEach((user) => {
+ console.log('----------------');
+ console.log('id: ', user[0]);
+ console.log('name:', user[1]);
+ });
+ }
+ });
+
+ await conn.end();
+})();
+
+/** Output
+ *
+ * Inserted: 4
+ * ----------------
+ * id: 4
+ * name: Gween
+ * ----------------
+ * id: 2
+ * name: John
+ * ----------------
+ * id: 1
+ * name: Josh
+ * ----------------
+ * id: 3
+ * name: Marie
+ * ----------------
+ * Affected Rows: 0
+ */
diff --git a/website/static/examples/typescript/procedure-call-packet.ts b/website/static/examples/typescript/procedure-call-packet.ts
new file mode 100644
index 0000000000..f9fbc32575
--- /dev/null
+++ b/website/static/examples/typescript/procedure-call-packet.ts
@@ -0,0 +1,109 @@
+/**
+ * The types are explicity for learning purpose
+ * By extending the `RowDataPacket`, you can use your Interface in `query` and `execute`
+ */
+
+import mysql, {
+ ConnectionOptions,
+ ProcedureCallPacket,
+ ResultSetHeader,
+ RowDataPacket,
+} from 'mysql2/promise';
+
+interface User extends RowDataPacket {
+ id: number;
+ name: string;
+}
+
+const isResultSetHeader = (data: unknown): data is ResultSetHeader => {
+ if (!data || typeof data !== 'object') return false;
+
+ const keys = [
+ 'fieldCount',
+ 'affectedRows',
+ 'insertId',
+ 'info',
+ 'serverStatus',
+ 'warningStatus',
+ 'changedRows',
+ ];
+
+ return keys.every((key) => key in data);
+};
+
+(async () => {
+ const access: ConnectionOptions = {
+ host: '',
+ user: '',
+ password: '',
+ database: '',
+ };
+
+ const conn = await mysql.createConnection(access);
+
+ /** Deleting the `users` table, if it exists */
+ await conn.query('DROP TABLE IF EXISTS `users`;');
+
+ /** Creating a minimal user table */
+ await conn.query(
+ 'CREATE TABLE `users` (`id` INT(11) AUTO_INCREMENT, `name` VARCHAR(50), PRIMARY KEY (`id`));'
+ );
+
+ /** Inserting some users */
+ const [inserted] = await conn.execute(
+ 'INSERT INTO `users`(`name`) VALUES(?), (?), (?), (?);',
+ ['Josh', 'John', 'Marie', 'Gween']
+ );
+
+ console.log('Inserted:', inserted.affectedRows);
+
+ /** Deleting the `getUsers` procedure, if it exists */
+ await conn.query('DROP PROCEDURE IF EXISTS getUsers');
+
+ /** Creating a procedure to get the users */
+ await conn.query(`
+ CREATE PROCEDURE getUsers()
+ BEGIN
+ SELECT * FROM users ORDER BY name ASC;
+ END
+ `);
+
+ /** Getting users */
+ const [procedureResult] =
+ await conn.query>('CALL getUsers()');
+
+ procedureResult.forEach((users) => {
+ /** By perform a `SELECT` or `SHOW`, The last item of `procedureResult` always be a `ResultSetHeader` */
+ if (isResultSetHeader(users)) {
+ console.log('----------------');
+ console.log('Affected Rows:', users.affectedRows);
+ } else {
+ users.forEach((user) => {
+ console.log('----------------');
+ console.log('id: ', user.id);
+ console.log('name:', user.name);
+ });
+ }
+ });
+
+ await conn.end();
+})();
+
+/** Output
+ *
+ * Inserted: 4
+ * ----------------
+ * id: 4
+ * name: Gween
+ * ----------------
+ * id: 2
+ * name: John
+ * ----------------
+ * id: 1
+ * name: Josh
+ * ----------------
+ * id: 3
+ * name: Marie
+ * ----------------
+ * Affected Rows: 0
+ */
diff --git a/website/static/examples/typescript/row-data-packet-multi-statements.ts b/website/static/examples/typescript/row-data-packet-multi-statements.ts
new file mode 100644
index 0000000000..8a78e8205d
--- /dev/null
+++ b/website/static/examples/typescript/row-data-packet-multi-statements.ts
@@ -0,0 +1,78 @@
+/**
+ * The types are explicity for learning purpose
+ * By extending the `RowDataPacket`, you can use your Interface in `query` and `execute`
+ */
+
+import mysql, {
+ ConnectionOptions,
+ ResultSetHeader,
+ RowDataPacket,
+} from 'mysql2/promise';
+
+interface User extends RowDataPacket {
+ id: number;
+ name: string;
+}
+
+(async () => {
+ const access: ConnectionOptions = {
+ host: '',
+ user: '',
+ password: '',
+ database: '',
+ multipleStatements: true,
+ };
+
+ const conn = await mysql.createConnection(access);
+
+ /** Deleting the `users` table, if it exists */
+ await conn.query('DROP TABLE IF EXISTS `users`;');
+
+ /** Creating a minimal user table */
+ await conn.query(
+ 'CREATE TABLE `users` (`id` INT(11) AUTO_INCREMENT, `name` VARCHAR(50), PRIMARY KEY (`id`));'
+ );
+
+ /** Inserting some users */
+ const [inserted] = await conn.execute(
+ 'INSERT INTO `users`(`name`) VALUES(?), (?), (?), (?);',
+ ['Josh', 'John', 'Marie', 'Gween']
+ );
+
+ console.log('Inserted:', inserted.affectedRows);
+
+ /** Getting users */
+ const [rows] = await conn.query(
+ [
+ 'SELECT * FROM `users` ORDER BY `name` ASC LIMIT 2;',
+ 'SELECT * FROM `users` ORDER BY `name` ASC LIMIT 2 OFFSET 2;',
+ ].join(' ')
+ );
+
+ rows.forEach((users) => {
+ users.forEach((user) => {
+ console.log('-----------');
+ console.log('id: ', user.id);
+ console.log('name:', user.name);
+ });
+ });
+
+ await conn.end();
+})();
+
+/** Output
+ *
+ * Inserted: 4
+ * -----------
+ * id: 4
+ * name: Gween
+ * -----------
+ * id: 2
+ * name: John
+ * -----------
+ * id: 1
+ * name: Josh
+ * -----------
+ * id: 3
+ * name: Marie
+ */
diff --git a/website/static/examples/typescript/row-data-packet-row-as-array-multi-statements.ts b/website/static/examples/typescript/row-data-packet-row-as-array-multi-statements.ts
new file mode 100644
index 0000000000..fc511326aa
--- /dev/null
+++ b/website/static/examples/typescript/row-data-packet-row-as-array-multi-statements.ts
@@ -0,0 +1,81 @@
+/**
+ * The types are explicity for learning purpose
+ * By extending the `RowDataPacket`, you can use your Interface in `query` and `execute`
+ */
+
+import mysql, {
+ ConnectionOptions,
+ ResultSetHeader,
+ RowDataPacket,
+} from 'mysql2/promise';
+
+interface User extends RowDataPacket {
+ /** id */
+ 0: number;
+ /** name */
+ 1: string;
+}
+
+(async () => {
+ const access: ConnectionOptions = {
+ host: '',
+ user: '',
+ password: '',
+ database: '',
+ multipleStatements: true,
+ rowsAsArray: true,
+ };
+
+ const conn = await mysql.createConnection(access);
+
+ /** Deleting the `users` table, if it exists */
+ await conn.query('DROP TABLE IF EXISTS `users`;');
+
+ /** Creating a minimal user table */
+ await conn.query(
+ 'CREATE TABLE `users` (`id` INT(11) AUTO_INCREMENT, `name` VARCHAR(50), PRIMARY KEY (`id`));'
+ );
+
+ /** Inserting some users */
+ const [inserted] = await conn.execute(
+ 'INSERT INTO `users`(`name`) VALUES(?), (?), (?), (?);',
+ ['Josh', 'John', 'Marie', 'Gween']
+ );
+
+ console.log('Inserted:', inserted.affectedRows);
+
+ /** Getting users */
+ const [rows] = await conn.query(
+ [
+ 'SELECT * FROM `users` ORDER BY `name` ASC LIMIT 2;',
+ 'SELECT * FROM `users` ORDER BY `name` ASC LIMIT 2 OFFSET 2;',
+ ].join(' ')
+ );
+
+ rows.forEach((users) => {
+ users.forEach((user) => {
+ console.log('-----------');
+ console.log('id: ', user[0]);
+ console.log('name:', user[1]);
+ });
+ });
+
+ await conn.end();
+})();
+
+/** Output
+ *
+ * Inserted: 4
+ * -----------
+ * id: 4
+ * name: Gween
+ * -----------
+ * id: 2
+ * name: John
+ * -----------
+ * id: 1
+ * name: Josh
+ * -----------
+ * id: 3
+ * name: Marie
+ */
diff --git a/website/static/examples/typescript/row-data-packet-row-as-array.ts b/website/static/examples/typescript/row-data-packet-row-as-array.ts
new file mode 100644
index 0000000000..c74867ca8e
--- /dev/null
+++ b/website/static/examples/typescript/row-data-packet-row-as-array.ts
@@ -0,0 +1,75 @@
+/**
+ * The types are explicity for learning purpose
+ * By extending the `RowDataPacket`, you can use your Interface in `query` and `execute`
+ */
+
+import mysql, {
+ ConnectionOptions,
+ ResultSetHeader,
+ RowDataPacket,
+} from 'mysql2/promise';
+
+interface User extends RowDataPacket {
+ /** id */
+ 0: number;
+ /** name */
+ 1: string;
+}
+
+(async () => {
+ const access: ConnectionOptions = {
+ host: '',
+ user: '',
+ password: '',
+ database: '',
+ rowsAsArray: true,
+ };
+
+ const conn = await mysql.createConnection(access);
+
+ /** Deleting the `users` table, if it exists */
+ await conn.query('DROP TABLE IF EXISTS `users`;');
+
+ /** Creating a minimal user table */
+ await conn.query(
+ 'CREATE TABLE `users` (`id` INT(11) AUTO_INCREMENT, `name` VARCHAR(50), PRIMARY KEY (`id`));'
+ );
+
+ /** Inserting some users */
+ const [inserted] = await conn.execute(
+ 'INSERT INTO `users`(`name`) VALUES(?), (?), (?), (?);',
+ ['Josh', 'John', 'Marie', 'Gween']
+ );
+
+ console.log('Inserted:', inserted.affectedRows);
+
+ /** Getting users */
+ const [users] = await conn.query(
+ 'SELECT * FROM `users` ORDER BY `name` ASC;'
+ );
+
+ users.forEach((user) => {
+ console.log('-----------');
+ console.log('id: ', user[0]);
+ console.log('name:', user[1]);
+ });
+
+ await conn.end();
+})();
+
+/** Output
+ *
+ * Inserted: 4
+ * -----------
+ * id: 4
+ * name: Gween
+ * -----------
+ * id: 2
+ * name: John
+ * -----------
+ * id: 1
+ * name: Josh
+ * -----------
+ * id: 3
+ * name: Marie
+ */
diff --git a/website/static/examples/typescript/row-data-packet.ts b/website/static/examples/typescript/row-data-packet.ts
new file mode 100644
index 0000000000..c149c0f19e
--- /dev/null
+++ b/website/static/examples/typescript/row-data-packet.ts
@@ -0,0 +1,72 @@
+/**
+ * The types are explicity for learning purpose
+ * By extending the `RowDataPacket`, you can use your Interface in `query` and `execute`
+ */
+
+import mysql, {
+ ConnectionOptions,
+ ResultSetHeader,
+ RowDataPacket,
+} from 'mysql2/promise';
+
+interface User extends RowDataPacket {
+ id: number;
+ name: string;
+}
+
+(async () => {
+ const access: ConnectionOptions = {
+ host: '',
+ user: '',
+ password: '',
+ database: '',
+ };
+
+ const conn = await mysql.createConnection(access);
+
+ /** Deleting the `users` table, if it exists */
+ await conn.query('DROP TABLE IF EXISTS `users`;');
+
+ /** Creating a minimal user table */
+ await conn.query(
+ 'CREATE TABLE `users` (`id` INT(11) AUTO_INCREMENT, `name` VARCHAR(50), PRIMARY KEY (`id`));'
+ );
+
+ /** Inserting some users */
+ const [inserted] = await conn.execute(
+ 'INSERT INTO `users`(`name`) VALUES(?), (?), (?), (?);',
+ ['Josh', 'John', 'Marie', 'Gween']
+ );
+
+ console.log('Inserted:', inserted.affectedRows);
+
+ /** Getting users */
+ const [users] = await conn.query(
+ 'SELECT * FROM `users` ORDER BY `name` ASC;'
+ );
+
+ users.forEach((user) => {
+ console.log('-----------');
+ console.log('id: ', user.id);
+ console.log('name:', user.name);
+ });
+
+ await conn.end();
+})();
+
+/** Output
+ *
+ * Inserted: 4
+ * -----------
+ * id: 4
+ * name: Gween
+ * -----------
+ * id: 2
+ * name: John
+ * -----------
+ * id: 1
+ * name: Josh
+ * -----------
+ * id: 3
+ * name: Marie
+ */
diff --git a/website/tsconfig.json b/website/tsconfig.json
index 35f06d1c7a..c878a8674b 100644
--- a/website/tsconfig.json
+++ b/website/tsconfig.json
@@ -9,5 +9,6 @@
"alwaysStrict": true,
"strictFunctionTypes": true,
"noUnusedLocals": true
- }
+ },
+ "exclude": ["static"]
}