diff --git a/website/.eslintrc.json b/website/.eslintrc.json index b5274adf62..6e0837d54b 100644 --- a/website/.eslintrc.json +++ b/website/.eslintrc.json @@ -106,6 +106,16 @@ ], "no-unused-vars": 2 } + }, + { + "files": ["static/**/*"], + "rules": { + "import/no-unresolved": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/no-unused-vars": "off", + "no-unused-vars": "off", + "no-bitwise": "off" + } } ], "settings": { diff --git a/website/docs/documentation/00-introduction.mdx b/website/docs/documentation/00-index.mdx similarity index 83% rename from website/docs/documentation/00-introduction.mdx rename to website/docs/documentation/00-index.mdx index 8bb4c2b96b..adc40871c6 100644 --- a/website/docs/documentation/00-introduction.mdx +++ b/website/docs/documentation/00-index.mdx @@ -1,8 +1,19 @@ -# Introduction +--- +slug: /documentation +title: Introduction +--- + +import { PageTitle } from '@site/src/components/PageTitle'; + + -MySQL2 aims to be a drop in replacement for [node-mysql](https://github.com/mysqljs/mysql). Please check `node-mysql` for full documentation. +# Documentation -**Note :** _If you see any API incompatibilities with `node-mysql`, please report via github issue._ +MySQL2 aims to be a drop in replacement for [node-mysql](https://github.com/mysqljs/mysql). + +:::note +_If you see any API incompatibilities with `node-mysql`, please report via github issue._ +::: Not only `Node-MySQL2` offers better performance over `node-mysql`, we also support these additional features. @@ -20,7 +31,7 @@ Not only `Node-MySQL2` offers better performance over `node-mysql`, we also supp ## Examples -Please check these [examples](/docs/examples) for `node-mysql2`. +Please check these [examples](/docs/examples) for **MySQL2**. --- diff --git a/website/docs/examples/index.mdx b/website/docs/examples/00-index.mdx similarity index 56% rename from website/docs/examples/index.mdx rename to website/docs/examples/00-index.mdx index 295d4c1e5d..d3dc818db8 100644 --- a/website/docs/examples/index.mdx +++ b/website/docs/examples/00-index.mdx @@ -1,36 +1,120 @@ --- -title: Quickstart +slug: /examples +title: Introduction --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { PageTitle } from '@site/src/components/PageTitle'; + + + # Examples -## Simple SELECT +## Simple `SELECT` + + + + +```js +import mysql from 'mysql2/promise'; + +const connection = await mysql.createConnection({ + user: 'test', + database: 'test', +}); + +const [rows] = await connection.query('SELECT 1+1 AS `test1`'); +// ... +``` + + + ```js const mysql = require('mysql2'); -const connection = mysql.createConnection({ user: 'test', database: 'test' }); -connection.query('SELECT 1+1 as test1', (err, rows) => { - // +const connection = mysql.createConnection({ + user: 'test', + database: 'test', +}); + +connection.query('SELECT 1+1 AS `test1`', (err, rows) => { + // ... }); ``` -## Prepared statement and parameters + + + +--- + +## Prepared Statement and Parameters + + + + +```js +import mysql from 'mysql2/promise'; + +const connection = await mysql.createConnection({ + user: 'test', + database: 'test', +}); + +const [rows] = await connection.execute('SELECT 1+? AS `test1`', [10]); +// ... +``` + + + ```js const mysql = require('mysql2'); -const connection = mysql.createConnection({ user: 'test', database: 'test' }); + +const connection = mysql.createConnection({ + user: 'test', + database: 'test', +}); connection.execute('SELECT 1+? as test1', [10], (err, rows) => { - // + // ... }); ``` + + + +--- + ## Connecting over encrypted connection + + + +```js +import fs from 'fs'; +import mysql from 'mysql2/promise'; + +const connection = await mysql.createConnection({ + user: 'test', + database: 'test', + ssl: { + key: fs.readFileSync('./certs/client-key.pem'), + cert: fs.readFileSync('./certs/client-cert.pem'), + }, +}); + +console.log(await connection.query('SELECT 1+1 AS `test1`')); +``` + + + + ```js const fs = require('fs'); const mysql = require('mysql2'); + const connection = mysql.createConnection({ user: 'test', database: 'test', @@ -39,13 +123,44 @@ const connection = mysql.createConnection({ cert: fs.readFileSync('./certs/client-cert.pem'), }, }); -connection.query('SELECT 1+1 as test1', console.log); + +connection.query('SELECT 1+1 AS `test1`', console.log); ``` + + + You can use 'Amazon RDS' string as value to ssl property to connect to Amazon RDS mysql over ssl (in that case http://s3.amazonaws.com/rds-downloads/mysql-ssl-ca-cert.pem CA cert is used) + + + +```js +import mysql from 'mysql2/promise'; + +try { + const connection = await mysql.createConnection({ + user: 'foo', + password: 'bar', + host: 'db.id.ap-southeast-2.rds.amazonaws.com', + ssl: 'Amazon RDS', + }); + + const [res] = await connection.query("SHOW `status` LIKE 'Ssl_cipher'"); + + console.log(res); + connection.end(); +} catch (err) { + console.log(err); +} +``` + + + + ```js const mysql = require('mysql2'); + const connection = mysql.createConnection({ user: 'foo', password: 'bar', @@ -53,12 +168,17 @@ const connection = mysql.createConnection({ ssl: 'Amazon RDS', }); -connection.query("show status like 'Ssl_cipher'", (err, res) => { +connection.query("SHOW `status` LIKE 'Ssl_cipher'", (err, res) => { console.log(err, res); connection.end(); }); ``` + + + +--- + ## Simple MySQL proxy server ```js @@ -115,6 +235,8 @@ server.on('connection', (conn) => { }); ``` +--- + ## Examples using MySQL server API - [MySQL-pg-proxy](https://github.com/sidorares/mysql-pg-proxy) - MySQL to Postgres proxy server. diff --git a/website/docs/examples/binlog-watcher.mdx b/website/docs/examples/binlog-watcher.mdx new file mode 100644 index 0000000000..596ede1b41 --- /dev/null +++ b/website/docs/examples/binlog-watcher.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Binlog Watcher + + + + + + diff --git a/website/docs/examples/connect-over-socks.mdx b/website/docs/examples/connect-over-socks.mdx new file mode 100644 index 0000000000..99fde510c4 --- /dev/null +++ b/website/docs/examples/connect-over-socks.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Connect Over Socks + + + + + + diff --git a/website/docs/examples/execute.mdx b/website/docs/examples/execute.mdx new file mode 100644 index 0000000000..9807bce224 --- /dev/null +++ b/website/docs/examples/execute.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Execute + + + + + + diff --git a/website/docs/examples/mysqlproxy.mdx b/website/docs/examples/mysqlproxy.mdx new file mode 100644 index 0000000000..e8885be374 --- /dev/null +++ b/website/docs/examples/mysqlproxy.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# MySQL Proxy + + + + + + diff --git a/website/docs/examples/pass-sha.mdx b/website/docs/examples/pass-sha.mdx new file mode 100644 index 0000000000..f25244b5a4 --- /dev/null +++ b/website/docs/examples/pass-sha.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Pass SHA + + + + + + diff --git a/website/docs/examples/pool-test.mdx b/website/docs/examples/pool-test.mdx new file mode 100644 index 0000000000..eb389c4055 --- /dev/null +++ b/website/docs/examples/pool-test.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Pool Test + + + + + + diff --git a/website/docs/examples/prepare.mdx b/website/docs/examples/prepare.mdx new file mode 100644 index 0000000000..ce54110684 --- /dev/null +++ b/website/docs/examples/prepare.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# MySQL Proxy + + + + + + diff --git a/website/docs/examples/promise-co-await.mdx b/website/docs/examples/promise-co-await.mdx new file mode 100644 index 0000000000..fad5e3ca27 --- /dev/null +++ b/website/docs/examples/promise-co-await.mdx @@ -0,0 +1,29 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Promise CO Await + + + + + + + + + + + + + + + diff --git a/website/docs/examples/queries/_category_.json b/website/docs/examples/queries/_category_.json new file mode 100644 index 0000000000..da21855a63 --- /dev/null +++ b/website/docs/examples/queries/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Queries", + "link": { + "type": "generated-index" + } +} diff --git a/website/docs/examples/queries/select.mdx b/website/docs/examples/queries/select.mdx new file mode 100644 index 0000000000..d84bee301c --- /dev/null +++ b/website/docs/examples/queries/select.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# SELECT + + + + + + diff --git a/website/docs/examples/server.mdx b/website/docs/examples/server.mdx new file mode 100644 index 0000000000..59499835a8 --- /dev/null +++ b/website/docs/examples/server.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Server + + + + + + diff --git a/website/docs/examples/ssl/_category_.json b/website/docs/examples/ssl/_category_.json new file mode 100644 index 0000000000..2574b5e900 --- /dev/null +++ b/website/docs/examples/ssl/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "SSL", + "link": { + "type": "generated-index" + } +} diff --git a/website/docs/examples/ssl/rds-ssl.mdx b/website/docs/examples/ssl/rds-ssl.mdx new file mode 100644 index 0000000000..3adde580b4 --- /dev/null +++ b/website/docs/examples/ssl/rds-ssl.mdx @@ -0,0 +1,11 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# RDS SSL + + + + + + diff --git a/website/docs/examples/ssl/select-over-ssl.mdx b/website/docs/examples/ssl/select-over-ssl.mdx new file mode 100644 index 0000000000..985f7bc39c --- /dev/null +++ b/website/docs/examples/ssl/select-over-ssl.mdx @@ -0,0 +1,13 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Select Over SSL + + + + + + + +- See [examples/ssl/certs](https://github.com/sidorares/node-mysql2/tree/master/examples/ssl/certs). diff --git a/website/docs/examples/typescript/_category_.json b/website/docs/examples/typescript/_category_.json new file mode 100644 index 0000000000..0a79b82b72 --- /dev/null +++ b/website/docs/examples/typescript/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "TypeScript", + "link": { + "type": "generated-index" + } +} diff --git a/website/docs/examples/typescript/basic-custom-class.mdx b/website/docs/examples/typescript/basic-custom-class.mdx new file mode 100644 index 0000000000..4f1c2e6af7 --- /dev/null +++ b/website/docs/examples/typescript/basic-custom-class.mdx @@ -0,0 +1,14 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Basic Custom Class + + + + + + diff --git a/website/docs/examples/typescript/procedure-call/00-procedure-call-packet.mdx b/website/docs/examples/typescript/procedure-call/00-procedure-call-packet.mdx new file mode 100644 index 0000000000..89ac0c49c5 --- /dev/null +++ b/website/docs/examples/typescript/procedure-call/00-procedure-call-packet.mdx @@ -0,0 +1,14 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Procedure Call Packet + + + + + + diff --git a/website/docs/examples/typescript/procedure-call/01-row-as-array.mdx b/website/docs/examples/typescript/procedure-call/01-row-as-array.mdx new file mode 100644 index 0000000000..ce8701803f --- /dev/null +++ b/website/docs/examples/typescript/procedure-call/01-row-as-array.mdx @@ -0,0 +1,14 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Procedure Call Packet (Row as Array) + + + + + + diff --git a/website/docs/examples/typescript/procedure-call/_category_.json b/website/docs/examples/typescript/procedure-call/_category_.json new file mode 100644 index 0000000000..abe7167157 --- /dev/null +++ b/website/docs/examples/typescript/procedure-call/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Procedure Call Packet", + "link": { + "type": "generated-index" + } +} diff --git a/website/docs/examples/typescript/row-data/00-row-data-packet.mdx b/website/docs/examples/typescript/row-data/00-row-data-packet.mdx new file mode 100644 index 0000000000..0ad1710bfe --- /dev/null +++ b/website/docs/examples/typescript/row-data/00-row-data-packet.mdx @@ -0,0 +1,14 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Row Data Packet + + + + + + diff --git a/website/docs/examples/typescript/row-data/01-row-as-array.mdx b/website/docs/examples/typescript/row-data/01-row-as-array.mdx new file mode 100644 index 0000000000..417c53b422 --- /dev/null +++ b/website/docs/examples/typescript/row-data/01-row-as-array.mdx @@ -0,0 +1,14 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Row Data Packet (Row as Array) + + + + + + diff --git a/website/docs/examples/typescript/row-data/02-multi-statements.mdx b/website/docs/examples/typescript/row-data/02-multi-statements.mdx new file mode 100644 index 0000000000..60f16eeb7b --- /dev/null +++ b/website/docs/examples/typescript/row-data/02-multi-statements.mdx @@ -0,0 +1,14 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Row Data Packet (Multi Statements) + + + + + + diff --git a/website/docs/examples/typescript/row-data/03-row-as-array-multi-statements.mdx b/website/docs/examples/typescript/row-data/03-row-as-array-multi-statements.mdx new file mode 100644 index 0000000000..c9d71324f5 --- /dev/null +++ b/website/docs/examples/typescript/row-data/03-row-as-array-multi-statements.mdx @@ -0,0 +1,14 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# Row Data Packet (Multi Statements and Row as Array) + + + + + + diff --git a/website/docs/examples/typescript/row-data/_category_.json b/website/docs/examples/typescript/row-data/_category_.json new file mode 100644 index 0000000000..549c5a1120 --- /dev/null +++ b/website/docs/examples/typescript/row-data/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Row Data Packet", + "link": { + "type": "generated-index" + } +} diff --git a/website/docs/stability/index.mdx b/website/docs/stability/index.mdx deleted file mode 100644 index 88470c7ee6..0000000000 --- a/website/docs/stability/index.mdx +++ /dev/null @@ -1 +0,0 @@ -# Stability Index diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 4688c174ae..b0e4bd4be6 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -63,21 +63,11 @@ const config: Config = { className: 'navbar__brand navbar__manual--title text--truncate', activeBaseRegex: `^/$`, }, - { - to: '/docs/examples', - label: 'Examples', - position: 'left', - }, // { // to: '/docs/faq', // label: 'FAQ', // position: 'left', // }, - // { - // to: '/docs/stability', - // label: 'Stability', - // position: 'left', - // }, { type: 'localeDropdown', position: 'right', diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current.json b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current.json index cf538ee161..fe3aac267c 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current.json +++ b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current.json @@ -1,5 +1,8 @@ { "sidebar.docs.category.Documentation": { "message": "Documentação" + }, + "sidebar.docs.category.Examples": { + "message": "Exemplos" } } diff --git a/website/i18n/zh-CN/docusaurus-plugin-content-docs/current.json b/website/i18n/zh-CN/docusaurus-plugin-content-docs/current.json index 02163fbd3b..1acf88478e 100644 --- a/website/i18n/zh-CN/docusaurus-plugin-content-docs/current.json +++ b/website/i18n/zh-CN/docusaurus-plugin-content-docs/current.json @@ -1,5 +1,8 @@ { "sidebar.docs.category.Documentation": { "message": "Documentation" + }, + "sidebar.docs.category.Examples": { + "message": "Examples" } } diff --git a/website/sidebars.ts b/website/sidebars.ts index 495784a3b4..d79c89e471 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -10,12 +10,15 @@ const sidebars: SidebarsConfig = { label: 'Documentation', items: [{ type: 'autogenerated', dirName: 'documentation' }], }, + { + type: 'category', + label: 'Examples', + items: [{ type: 'autogenerated', dirName: 'examples' }], + }, 'acknowledgements', 'contributing', ], - examples: [{ type: 'autogenerated', dirName: 'examples' }], // faq: [{ type: 'autogenerated', dirName: 'faq' }], - // stability: [{ type: 'autogenerated', dirName: 'stability' }], }; export default sidebars; diff --git a/website/src/components/ExternalCodeEmbed.tsx b/website/src/components/ExternalCodeEmbed.tsx new file mode 100644 index 0000000000..95cdde1da8 --- /dev/null +++ b/website/src/components/ExternalCodeEmbed.tsx @@ -0,0 +1,83 @@ +import { useState, useEffect, FC } from 'react'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +// eslint-disable-next-line import/no-unresolved +import CodeBlock from '@theme/CodeBlock'; +import { Loading } from '@site/src/components/Loading'; + +export type ExternalCodeEmbedProps = { + /** Raw URL from GitHub */ + url: string; + /** `js`, `ts`, `json`, etc. */ + language: string; +}; + +/** + * **Usage Example:** + * + * ```tsx + * + * ``` + * + * --- + * + * ```tsx + * + * ``` + */ +export const ExternalCodeEmbed: FC = ({ + url, + language, +}) => { + const [code, setCode] = useState(''); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(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"] }