diff --git a/.github/workflows/website.yml b/.github/workflows/ci-website.yml similarity index 91% rename from .github/workflows/website.yml rename to .github/workflows/ci-website.yml index 15b81f567b..734e3dbeaa 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/ci-website.yml @@ -33,5 +33,8 @@ jobs: - name: Checking Types run: cd website && npm run typecheck + - name: Run Unit Tests + run: cd website && npm run test:unit + - name: Checking Build run: cd website && npm run build diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 2bb4160189..071004f19a 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -32,6 +32,9 @@ jobs: - name: Checking Types run: cd website && npm run typecheck + - name: Run Unit Tests + run: cd website && npm run test:unit + - name: Building Site run: cd website && npm run build diff --git a/website/.eslintignore b/website/.eslintignore index 11611db07a..c3e8b07cbf 100644 --- a/website/.eslintignore +++ b/website/.eslintignore @@ -1,4 +1,3 @@ /build /.docusaurus /.cache-loader -/**/*.mdx diff --git a/website/.eslintrc.json b/website/.eslintrc.json index 6e0837d54b..724ac47660 100644 --- a/website/.eslintrc.json +++ b/website/.eslintrc.json @@ -8,7 +8,8 @@ "plugin:import/errors", "plugin:import/warnings", "plugin:react-hooks/recommended", - "plugin:react/jsx-runtime" + "plugin:react/jsx-runtime", + "plugin:@docusaurus/recommended" ], "parserOptions": { "ecmaVersion": "latest", diff --git a/website/.prettierignore b/website/.prettierignore index 98edfa0cf6..9ef0805a02 100644 --- a/website/.prettierignore +++ b/website/.prettierignore @@ -2,4 +2,3 @@ /.docusaurus /.cache-loader # /**/*.mdx -package-lock.json diff --git a/website/docs/contributing/website.mdx b/website/docs/contributing/website.mdx index 2e0869f7b0..2d82b166da 100644 --- a/website/docs/contributing/website.mdx +++ b/website/docs/contributing/website.mdx @@ -5,6 +5,7 @@ title: Documentation Site import { FAQ } from '@site/src/components/FAQ'; import { History } from '@site/src/components/History'; import { Stability } from '@site/src/components/Stability'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; # Website Contributing Guidelines @@ -145,7 +146,8 @@ import { FAQ } from '@site/src/components/FAQ'; - The **FAQ** component can be utilized in any section or page. - Code blocks are compatible and can be used within the **FAQ** component. - ::: + +::: @@ -157,6 +159,42 @@ import { FAQ } from '@site/src/components/FAQ'; --- +### ExternalCodeEmbed + +{/* prettier-ignore-start */} +```tsx +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + + + + +``` +{/* prettier-ignore-end */} + + + + + + + +--- + ## Running Tests ```bash diff --git a/website/docs/documentation/prepared-statements.mdx b/website/docs/documentation/prepared-statements.mdx index 82a5011e58..2cd0bfb544 100644 --- a/website/docs/documentation/prepared-statements.mdx +++ b/website/docs/documentation/prepared-statements.mdx @@ -1,3 +1,7 @@ +--- +tags: [Prepared Statements, execute] +--- + # Prepared Statements ## Automatic creation, cached and re-used by connection @@ -39,11 +43,11 @@ connection.prepare('select ? + ? as tests', (err, statement) => { Note that you should not use statement after connection reset (`changeUser()` or disconnect). Statement scope is connection, you need to prepare statement for each new connection in order to use it. -# Configuration +## Configuration `maxPreparedStatements` : We keep the cached statements in a [lru-cache](https://github.com/isaacs/node-lru-cache). Default size is `16000` but you can use this option to override it. Any statements that are dropped from cache will be `closed`. -# Serialization of bind parameters +## Serialization of bind parameters The bind parameter values passed to `execute` are serialized JS -> MySQL as: @@ -57,3 +61,36 @@ The bind parameter values passed to `execute` are serialized JS -> MySQL as: - Other -> `VAR_STRING` Passing in `undefined` or a `function` will result in an error. + +## Prepared Statements Helper + +MySQL2 provides `execute` helper which will prepare and query the statement. You can also manually prepare / unprepare statement with `prepare` / `unprepare` methods. + +```js +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); + } + ); + } + ); + } +); +``` + +## Examples + +For Prepared Statements examples, please see [here](http://localhost:3000/node-mysql2/docs/examples/queries/prepared-statements). diff --git a/website/docs/documentation/promise-wrapper.mdx b/website/docs/documentation/promise-wrapper.mdx index 631c051b22..91212d4f21 100644 --- a/website/docs/documentation/promise-wrapper.mdx +++ b/website/docs/documentation/promise-wrapper.mdx @@ -72,4 +72,4 @@ co(function* () { }); ``` -Examples in [/examples/promise-co-await](/docs/examples/promise-co-await) +Examples in [/examples/promise-co-await](/docs/examples/promise-wrapper/co-await) diff --git a/website/docs/documentation/typescript-examples.mdx b/website/docs/documentation/typescript-examples.mdx index 71a2c89457..8bd71c82c7 100644 --- a/website/docs/documentation/typescript-examples.mdx +++ b/website/docs/documentation/typescript-examples.mdx @@ -401,10 +401,10 @@ For `ProcedureCallPacket`, please see the following examples. You can also check some code examples using **MySQL2** and **TypeScript** to understand advanced concepts: -- [Extending and using **Interfaces** with `RowDataPacket`](/docs/examples/typescript/row-data/row-data-packet) +- [Extending and using **Interfaces** with `RowDataPacket`](/docs/examples/typescript/row-data/index) - [Extending and using **Interfaces** with `RowDataPacket` and `rowAsArray`](/docs/examples/typescript/row-data/row-as-array) - [Extending and using **Interfaces** with `RowDataPacket` and `multipleStatements`](/docs/examples/typescript/row-data/multi-statements) - [Extending and using **Interfaces** with `RowDataPacket`, `rowAsArray` and `multipleStatements`](/docs/examples/typescript/row-data/row-as-array-multi-statements) -- [Checking for `ResultSetHeader`, extending and using **Interfaces** with `RowDataPacket` from `ProcedureCallPacket`](/docs/examples/typescript/procedure-call/procedure-call-packet) +- [Checking for `ResultSetHeader`, extending and using **Interfaces** with `RowDataPacket` from `ProcedureCallPacket`](/docs/examples/typescript/procedure-call/index) - [Checking for `ResultSetHeader`, extending and using **Interfaces** with `RowDataPacket` and `rowAsArray` from `ProcedureCallPacket`](/docs/examples/typescript/procedure-call/row-as-array) - [Creating a basic custom **MySQL2** **Class**](/docs/examples/typescript/basic-custom-class) diff --git a/website/docs/examples/00-index.mdx b/website/docs/examples/00-index.mdx index dfc4718e97..c1cd6606bf 100644 --- a/website/docs/examples/00-index.mdx +++ b/website/docs/examples/00-index.mdx @@ -11,231 +11,9 @@ import { PageTitle } from '@site/src/components/PageTitle'; # Examples -## 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) => { - // ... -}); -``` - - - - ---- - -## 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', -}); - -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', - ssl: { - key: fs.readFileSync('./certs/client-key.pem'), - cert: fs.readFileSync('./certs/client-cert.pem'), - }, -}); - -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 https://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', - host: 'db.id.ap-southeast-2.rds.amazonaws.com', - ssl: 'Amazon RDS', -}); - -connection.query("SHOW `status` LIKE 'Ssl_cipher'", (err, res) => { - console.log(err, res); - connection.end(); -}); -``` - - - - ---- - -## Simple MySQL proxy server - -```js -const mysql = require('mysql2'); - -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, - }); - - 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)); -}); -``` - ---- +:::tip +To explore the examples, please use the **sidebar navigation** on desktop or access the **menu** on mobile devices. +::: ## Examples using MySQL server API diff --git a/website/docs/examples/connect-over-socks.mdx b/website/docs/examples/connect-over-socks.mdx deleted file mode 100644 index aa6c845205..0000000000 --- a/website/docs/examples/connect-over-socks.mdx +++ /dev/null @@ -1,45 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Connect Over Socks - - - - -```js -'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/docs/examples/connections/_category_.json b/website/docs/examples/connections/_category_.json new file mode 100644 index 0000000000..816ced577a --- /dev/null +++ b/website/docs/examples/connections/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Connections", + "position": 1 +} diff --git a/website/docs/examples/connections/create-connection.mdx b/website/docs/examples/connections/create-connection.mdx new file mode 100644 index 0000000000..88be8a6876 --- /dev/null +++ b/website/docs/examples/connections/create-connection.mdx @@ -0,0 +1,395 @@ +--- +sidebar_position: 1 +tags: [createConnection, URI, SHA1, RDS, SSL, Socks] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# createConnection + +:::info +For queries please see the [**Simple Queries**](/docs/examples/queries/simple-queries) and [**Prepared Statements**](/docs/examples/queries/prepared-statements) examples. +::: + +## createConnection(connectionUri) + +> **createConnection(connectionUri: string)** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const connection = await mysql.createConnection( + 'mysql://root:password@localhost:3306/test' + ); + // highlight-end +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const connection = mysql.createConnection( + 'mysql://root:password@localhost:3306/test' +); + +connection.addListener('error', (err) => { + console.log(err); +}); +``` + + + + +--- + +## createConnection(config) + +> **createConnection(config: [ConnectionOptions](#connectionoptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const connection = await mysql.createConnection({ + host: 'localhost', + user: 'root', + database: 'test', + // port: 3306, + // password: '', + }); + // highlight-end +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const connection = mysql.createConnection({ + host: 'localhost', + user: 'root', + database: 'test', + // port: 3306, + // password: '', +}); + +connection.addListener('error', (err) => { + console.log(err); +}); +``` + + + + +--- + +## createConnection(config) — SHA1 + +> **createConnection(config: [ConnectionOptions](#connectionoptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const connection = await mysql.createConnection({ + // ... + passwordSha1: Buffer.from( + '8bb6118f8fd6935ad0876a3be34a717d32708ffd', + 'hex' + ), + }); + // highlight-end +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const connection = mysql.createConnection({ + // ... + passwordSha1: Buffer.from('8bb6118f8fd6935ad0876a3be34a717d32708ffd', 'hex'), +}); + +connection.addListener('error', (err) => { + console.log(err); +}); +``` + + + + +--- + +## createConnection(config) — SSL + +> **createConnection(config: [ConnectionOptions](#connectionoptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const connection = await mysql.createConnection({ + // ... + ssl: { + // key: fs.readFileSync('./certs/client-key.pem'), + // cert: fs.readFileSync('./certs/client-cert.pem') + ca: fs.readFileSync('./certs/ca-cert.pem'), + }, + }); + // highlight-end +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const connection = mysql.createConnection({ + // ... + ssl: { + // key: fs.readFileSync('./certs/client-key.pem'), + // cert: fs.readFileSync('./certs/client-cert.pem') + ca: fs.readFileSync('./certs/ca-cert.pem'), + }, +}); + +connection.addListener('error', (err) => { + console.log(err); +}); +``` + + + + + + - See [ssl/certs](https://github.com/sidorares/node-mysql2/tree/master/test/fixtures/ssl/certs). + + + + +--- + +## createConnection(config) — RDS SSL + +> **createConnection(config: [ConnectionOptions](#connectionoptions))** + +You can use **Amazon RDS** string as value to ssl property to connect to **Amazon RDS** MySQL over SSL. + +In that case https://s3.amazonaws.com/rds-downloads/mysql-ssl-ca-cert.pem CA cert is used: + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const connection = await mysql.createConnection({ + // ... + host: 'db.id.ap-southeast-2.rds.amazonaws.com', + ssl: 'Amazon RDS', + }); + // highlight-end +} catch (err) { + console.log(err); +} +``` + +:::tip Testing + +```js +try { + const [res] = await connection.query('SHOW `status` LIKE "Ssl_cipher"'); + await connection.end(); + + console.log(res); +} catch (err) { + console.log(err); +} +``` + +::: + + + + +```js +const mysql = require('mysql2'); + +const connection = mysql.createConnection({ + // ... + host: 'db.id.ap-southeast-2.rds.amazonaws.com', + ssl: 'Amazon RDS', +}); + +connection.addListener('error', (err) => { + console.log(err); +}); +``` + +:::tip Testing + +```js +connectionquery('SHOW `status` LIKE "Ssl_cipher"', function (err, res) { + connection.end(); + + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(res); +}); +``` + +::: + + + + +### Related Links + +- **Issues** + - [#2130 — Update TLS certs for Amazon RDS instances](https://github.com/sidorares/node-mysql2/issues/2130) +- **Pull Requests** + - [#2119 — fix: make startTls code compatible with Bun](https://github.com/sidorares/node-mysql2/pull/2119) + - [#2131 — Update Amazon RDS SSL CA cert](https://github.com/sidorares/node-mysql2/pull/2131) + +--- + +## createConnection(config) — Socks + +> **createConnection(config: [ConnectionOptions](#connectionoptions))** + + + + +```js +const mysql = require('mysql2'); +const SocksConnection = require('socksjs'); + +const socksProxy = new SocksConnection({ port: 3306 }); +// highlight-start +const connection = mysql.createConnection({ + stream: socksProxy, +}); +// highlight-end + +connection.addListener('error', (err) => { + console.log(err); +}); +``` + + + + +```js +const mysql = require('mysql2'); +const SocksConnection = require('socksjs'); + +// highlight-start +const connection = mysql.createConnection({ + debug: 1, + stream: function () { + return new SocksConnection({ port: 3306 }); + }, +}); +// highlight-end + +connection.addListener('error', (err) => { + console.log(err); +}); +``` + + + + +:::tip Testing + +```js +connection.execute('SELECT SLEEP(1.1) AS `www`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); + +connection.execute('SELECT SLEEP(1) AS `qqq`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); + +connection.execute('SELECT SLEEP(1) AS `qqq`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); +``` + +::: + +--- + +## Glossary + +### ConnectionOptions + + + + diff --git a/website/docs/examples/connections/create-pool.mdx b/website/docs/examples/connections/create-pool.mdx new file mode 100644 index 0000000000..cf71a0ccbe --- /dev/null +++ b/website/docs/examples/connections/create-pool.mdx @@ -0,0 +1,499 @@ +--- +sidebar_position: 2 +tags: [createPool, URI, SHA1, RDS, SSL, Socks] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# createPool + +:::info +For queries please see the [**Simple Queries**](/docs/examples/queries/simple-queries) and [**Prepared Statements**](/docs/examples/queries/prepared-statements) examples. +::: + +## createPool(connectionUri) + +> **createPool(connectionUri: string)** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const pool = mysql.createPool('mysql://root:password@localhost:3306/test'); + const connection = await pool.getConnection(); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const pool = mysql.createPool('mysql://root:password@localhost:3306/test'); + +pool.getConnection(function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `pool.releaseConnection(connection)` +- `connection.release()` + +::: + +--- + +## createPool(config) + +> **createPool(config: [PoolOptions](#pooloptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const pool = mysql.createPool({ + host: 'localhost', + user: 'root', + database: 'test', + // port: 3306, + // password: '', + }); + const connection = await pool.getConnection(); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const pool = mysql.createPool({ + host: 'localhost', + user: 'root', + database: 'test', + // port: 3306, + // password: '', +}); + +pool.getConnection(function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `pool.releaseConnection(connection)` +- `connection.release()` + +::: + +--- + +## createPool(config) — SHA1 + +> **createPool(config: [PoolOptions](#pooloptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const pool = mysql.createPool({ + // ... + passwordSha1: Buffer.from( + '8bb6118f8fd6935ad0876a3be34a717d32708ffd', + 'hex' + ), + }); + const connection = await pool.getConnection(); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const pool = mysql.createPool({ + // ... + passwordSha1: Buffer.from('8bb6118f8fd6935ad0876a3be34a717d32708ffd', 'hex'), +}); + +pool.getConnection(function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `pool.releaseConnection(connection)` +- `connection.release()` + +::: + +--- + +## createPool(config) — SSL + +> **createPool(config: [PoolOptions](#pooloptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const pool = mysql.createPool({ + // ... + ssl: { + // key: fs.readFileSync('./certs/client-key.pem'), + // cert: fs.readFileSync('./certs/client-cert.pem') + ca: fs.readFileSync('./certs/ca-cert.pem'), + }, + }); + const connection = await pool.getConnection(); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const pool = mysql.createPool({ + // ... + ssl: { + // key: fs.readFileSync('./certs/client-key.pem'), + // cert: fs.readFileSync('./certs/client-cert.pem') + ca: fs.readFileSync('./certs/ca-cert.pem'), + }, +}); + +pool.getConnection(function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + + + + + + - See [ssl/certs](https://github.com/sidorares/node-mysql2/tree/master/test/fixtures/ssl/certs). + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `pool.releaseConnection(connection)` +- `connection.release()` + +::: + +--- + +## createPool(config) — RDS SSL + +> **createPool(config: [PoolOptions](#pooloptions))** + +You can use **Amazon RDS** string as value to ssl property to connect to **Amazon RDS** MySQL over SSL. + +In that case https://s3.amazonaws.com/rds-downloads/mysql-ssl-ca-cert.pem CA cert is used: + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const pool = mysql.createPool({ + // ... + host: 'db.id.ap-southeast-2.rds.amazonaws.com', + ssl: 'Amazon RDS', + }); + const connection = await pool.getConnection(); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + +:::tip Testing + +```js +try { + const [res] = await connection.query('SHOW `status` LIKE "Ssl_cipher"'); + await pool.end(); + + console.log(res); +} catch (err) { + console.log(err); +} +``` + +::: + + + + +```js +const mysql = require('mysql2'); + +const pool = mysql.createPool({ + // ... + host: 'db.id.ap-southeast-2.rds.amazonaws.com', + ssl: 'Amazon RDS', +}); + +pool.getConnection(function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + +:::tip Testing + +```js +connectionquery('SHOW `status` LIKE "Ssl_cipher"', function (err, res) { + pool.end(); + + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(res); +}); +``` + +::: + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `pool.releaseConnection(connection)` +- `connection.release()` + +::: + +### Related Links + +- **Issues** + - [#2130 — Update TLS certs for Amazon RDS instances](https://github.com/sidorares/node-mysql2/issues/2130) +- **Pull Requests** + - [#2119 — fix: make startTls code compatible with Bun](https://github.com/sidorares/node-mysql2/pull/2119) + - [#2131 — Update Amazon RDS SSL CA cert](https://github.com/sidorares/node-mysql2/pull/2131) + +--- + +## createPool(config) — Socks + +> **createPool(config: [PoolOptions](#pooloptions))** + + + + +```js +const mysql = require('mysql2'); +const SocksConnection = require('socksjs'); + +const socksProxy = new SocksConnection({ port: 3306 }); +// highlight-start +const pool = mysql.createPool({ + stream: socksProxy, +}); +// highlight-end +``` + + + + +```js +const mysql = require('mysql2'); +const SocksConnection = require('socksjs'); + +// highlight-start +const pool = mysql.createPool({ + debug: 1, + stream: function () { + return new SocksConnection({ port: 3306 }); + }, +}); +// highlight-end +``` + + + + +:::tip Testing + +```js +pool.execute('SELECT SLEEP(1.1) AS `www`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); + +pool.execute('SELECT SLEEP(1) AS `qqq`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); + +pool.execute('SELECT SLEEP(1) AS `qqq`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); +``` + +::: + +--- + +## Glossary + +### PoolOptions + +> **PoolOptions** extends all options from **ConnectionOptions**: +> +> +> language='ts' +> url='https://raw.githubusercontent.com/sidorares/node-mysql2/master/typings/mysql/lib/Connection.d.ts' +> extractMethod='ConnectionOptions' +> methodType='interface' +> /> +> + + + + diff --git a/website/docs/examples/connections/createPoolCluster.mdx b/website/docs/examples/connections/createPoolCluster.mdx new file mode 100644 index 0000000000..0a77a20f59 --- /dev/null +++ b/website/docs/examples/connections/createPoolCluster.mdx @@ -0,0 +1,539 @@ +--- +sidebar_position: 3 +tags: [createPoolCluster, URI, SHA1, RDS, SSL, Socks] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# createPoolCluster + +:::info +For queries please see the [**Simple Queries**](/docs/examples/queries/simple-queries) and [**Prepared Statements**](/docs/examples/queries/prepared-statements) examples. +::: + +## add(group, connectionUri) + +> **add(group: string, connectionUri: string)** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const poolCluster = mysql.createPoolCluster(); + + poolCluster.add('clusterA', 'mysql://root:password@localhost:3306/test'); + // poolCluster.add('clusterB', '...'); + + const connection = await poolCluster.getConnection('clusterA'); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const poolCluster = mysql.createPoolCluster(); + +poolCluster.add('clusterA', 'mysql://root:password@localhost:3306/test'); +// poolCluster.add('clusterB', '...'); + +poolCluster.getConnection('clusterA', function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `connection.release()` + +::: + +--- + +## add(group, config) + +> **add(group: string, config: [PoolOptions](#pooloptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const poolCluster = mysql.createPoolCluster(); + + poolCluster.add('clusterA', { + host: 'localhost', + user: 'root', + database: 'test', + // port: 3306, + // password: '', + }); + // poolCluster.add('clusterB', '...'); + + const connection = await poolCluster.getConnection('clusterA'); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const poolCluster = mysql.createPoolCluster(); + +poolCluster.add('clusterA', { + host: 'localhost', + user: 'root', + database: 'test', + // port: 3306, + // password: '', +}); +// poolCluster.add('clusterB', '...'); + +poolCluster.getConnection('clusterA', function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `connection.release()` + +::: + +--- + +## add(group, config) — SHA1 + +> **add(group: string, config: [PoolOptions](#pooloptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const poolCluster = mysql.createPoolCluster(); + + poolCluster.add('clusterA', { + // ... + passwordSha1: Buffer.from( + '8bb6118f8fd6935ad0876a3be34a717d32708ffd', + 'hex' + ), + }); + // poolCluster.add('clusterB', '...'); + + const connection = await poolCluster.getConnection('clusterA'); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const poolCluster = mysql.createPoolCluster(); + +poolCluster.add('clusterA', { + // ... + passwordSha1: Buffer.from('8bb6118f8fd6935ad0876a3be34a717d32708ffd', 'hex'), +}); +// poolCluster.add('clusterB', '...'); + +poolCluster.getConnection('clusterA', function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `connection.release()` + +::: + +--- + +## add(group, config) — SSL + +> **add(group: string, config: [PoolOptions](#pooloptions))** + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const poolCluster = mysql.createPoolCluster(); + + poolCluster.add('clusterA', { + // ... + ssl: { + // key: fs.readFileSync('./certs/client-key.pem'), + // cert: fs.readFileSync('./certs/client-cert.pem') + ca: fs.readFileSync('./certs/ca-cert.pem'), + }, + }); + // poolCluster.add('clusterB', '...'); + + const connection = await poolCluster.getConnection('clusterA'); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const mysql = require('mysql2'); + +const poolCluster = mysql.createPoolCluster(); + +poolCluster.add('clusterA', { + // ... + ssl: { + // key: fs.readFileSync('./certs/client-key.pem'), + // cert: fs.readFileSync('./certs/client-cert.pem') + ca: fs.readFileSync('./certs/ca-cert.pem'), + }, +}); +// poolCluster.add('clusterB', '...'); + +poolCluster.getConnection('clusterA', function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + + + + + + - See [ssl/certs](https://github.com/sidorares/node-mysql2/tree/master/test/fixtures/ssl/certs). + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `connection.release()` + +::: + +--- + +## add(group, config) — RDS SSL + +> **add(group: string, config: [PoolOptions](#pooloptions))** + +You can use **Amazon RDS** string as value to ssl property to connect to **Amazon RDS** MySQL over SSL. + +In that case https://s3.amazonaws.com/rds-downloads/mysql-ssl-ca-cert.pem CA cert is used: + + + + +```js +import mysql from 'mysql2/promise'; + +try { + // highlight-start + const poolCluster = mysql.createPoolCluster(); + + poolCluster.add('clusterA', { + // ... + host: 'db.id.ap-southeast-2.rds.amazonaws.com', + ssl: 'Amazon RDS', + }); + // poolCluster.add('clusterB', '...'); + + const connection = await poolCluster.getConnection('clusterA'); + // highlight-end + // ... some query + + // highlight-next-line + connection.release(); +} catch (err) { + console.log(err); +} +``` + +:::tip Testing + +```js +try { + const [res] = await connection.query('SHOW `status` LIKE "Ssl_cipher"'); + await poolCluster.end(); + + console.log(res); +} catch (err) { + console.log(err); +} +``` + +::: + + + + +```js +const mysql = require('mysql2'); + +const poolCluster = mysql.createPoolCluster(); + +poolCluster.add('clusterA', { + // ... + host: 'db.id.ap-southeast-2.rds.amazonaws.com', + ssl: 'Amazon RDS', +}); +// poolCluster.add('clusterB', '...'); + +poolCluster.getConnection('clusterA', function (err, connection) { + if (err instanceof Error) { + console.log(err); + return; + } + + // ... some query + + connection.release(); +}); +``` + +:::tip Testing + +```js +connectionquery('SHOW `status` LIKE "Ssl_cipher"', function (err, res) { + poolCluster.end(); + + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(res); +}); +``` + +::: + + + + +:::warning + +Don't forget to release the connection when finished by using: + +- `connection.release()` + +::: + +### Related Links + +- **Issues** + - [#2130 — Update TLS certs for Amazon RDS instances](https://github.com/sidorares/node-mysql2/issues/2130) +- **Pull Requests** + - [#2119 — fix: make startTls code compatible with Bun](https://github.com/sidorares/node-mysql2/pull/2119) + - [#2131 — Update Amazon RDS SSL CA cert](https://github.com/sidorares/node-mysql2/pull/2131) + +--- + +## add(group, config) — Socks + +> **add(group: string, config: [PoolOptions](#pooloptions))** + + + + +```js +const mysql = require('mysql2'); +const SocksConnection = require('socksjs'); + +const socksProxy = new SocksConnection({ port: 3306 }); +// highlight-start +const poolCluster = mysql.createPoolCluster(); + +poolCluster.add('clusterA', { + stream: socksProxy, +}); +// poolCluster.add('clusterB', '...'); + +const poolNamespace = poolCluster.of('clusterA'); +// highlight-end +``` + + + + +```js +const mysql = require('mysql2'); +const SocksConnection = require('socksjs'); + +// highlight-start +const poolCluster = mysql.createPoolCluster(); + +poolCluster.add('clusterA', { + debug: 1, + stream: function () { + return new SocksConnection({ port: 3306 }); + }, +}); +// poolCluster.add('clusterB', '...'); + +const poolNamespace = poolCluster.of('clusterA'); +// highlight-end +``` + + + + +:::tip Testing + +```js +poolNamespace.execute('SELECT SLEEP(1.1) AS `www`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); + +poolNamespace.execute('SELECT SLEEP(1) AS `qqq`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); + +poolNamespace.execute('SELECT SLEEP(1) AS `qqq`', (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows, fields); +}); +``` + +::: + +--- + +## Glossary + +### PoolOptions + +> **PoolOptions** extends all options from **ConnectionOptions**: +> +> +> language='ts' +> url='https://raw.githubusercontent.com/sidorares/node-mysql2/master/typings/mysql/lib/Connection.d.ts' +> extractMethod='ConnectionOptions' +> methodType='interface' +> /> +> + + + + diff --git a/website/docs/examples/execute.mdx b/website/docs/examples/execute.mdx deleted file mode 100644 index 1219d99427..0000000000 --- a/website/docs/examples/execute.mdx +++ /dev/null @@ -1,47 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Execute - - - - -```js -'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/docs/examples/pass-sha.mdx b/website/docs/examples/pass-sha.mdx deleted file mode 100644 index 760d98ddfb..0000000000 --- a/website/docs/examples/pass-sha.mdx +++ /dev/null @@ -1,29 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Pass SHA - - - - -```js -'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/docs/examples/prepare.mdx b/website/docs/examples/prepare.mdx deleted file mode 100644 index 75b3689938..0000000000 --- a/website/docs/examples/prepare.mdx +++ /dev/null @@ -1,37 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Prepared Statements - - - - -```js -'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/docs/examples/promise-wrapper/_category_.json b/website/docs/examples/promise-wrapper/_category_.json new file mode 100644 index 0000000000..6856bbbcb0 --- /dev/null +++ b/website/docs/examples/promise-wrapper/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Promise Wrapper" +} diff --git a/website/docs/examples/promise-co-await.mdx b/website/docs/examples/promise-wrapper/co-await.mdx similarity index 99% rename from website/docs/examples/promise-co-await.mdx rename to website/docs/examples/promise-wrapper/co-await.mdx index 2a7c790a1c..71828e2e74 100644 --- a/website/docs/examples/promise-co-await.mdx +++ b/website/docs/examples/promise-wrapper/co-await.mdx @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Promise CO Await +# await — co diff --git a/website/docs/examples/queries/_category_.json b/website/docs/examples/queries/_category_.json index da21855a63..af83c86c70 100644 --- a/website/docs/examples/queries/_category_.json +++ b/website/docs/examples/queries/_category_.json @@ -1,6 +1,4 @@ { "label": "Queries", - "link": { - "type": "generated-index" - } + "position": 2 } diff --git a/website/docs/examples/queries/prepared-statements/_category_.json b/website/docs/examples/queries/prepared-statements/_category_.json new file mode 100644 index 0000000000..3be960c36a --- /dev/null +++ b/website/docs/examples/queries/prepared-statements/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Prepared Statements", + "position": 2 +} diff --git a/website/docs/examples/queries/prepared-statements/delete.mdx b/website/docs/examples/queries/prepared-statements/delete.mdx new file mode 100644 index 0000000000..a916883db0 --- /dev/null +++ b/website/docs/examples/queries/prepared-statements/delete.mdx @@ -0,0 +1,217 @@ +--- +sidebar_position: 3 +tags: [Prepared Statements, Placeholders, Parameters, execute] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# DELETE + +## execute(sql, values) + +> **execute(sql: string, values: any[])** + + + + +```js +try { + const sql = 'DELETE FROM `users` WHERE `name` = ? LIMIT 1'; + const values = ['Page']; + + // highlight-next-line + const [result, fields] = await connection.execute(sql, values); + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'DELETE FROM `users` WHERE `name` = ? LIMIT 1'; +const values = ['Page']; + +connection.execute(sql, values, (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); +}); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## execute(options) + +> **execute(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = 'DELETE FROM `users` WHERE `name` = ? LIMIT 1'; + const values = ['Page']; + + // highlight-start + const [result, fields] = await connection.execute({ + sql, + values, + // ... other options + }); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'DELETE FROM `users` WHERE `name` = ? LIMIT 1'; +const values = ['Page']; + +connection.execute( + { + sql, + values, + // ... other options + }, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## execute(options, values) + +> **execute(options: [QueryOptions](#queryoptions), values: any[])** + + + + +```js +try { + const sql = 'DELETE FROM `users` WHERE `name` = ? LIMIT 1'; + const values = ['Page']; + + // highlight-start + const [result, fields] = await connection.execute( + { + sql, + // ... other options + }, + values + ); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'DELETE FROM `users` WHERE `name` = ? LIMIT 1'; +const values = ['Page']; + +connection.execute( + { + sql, + // ... other options + }, + values, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## Glossary + +### ResultSetHeader + + + + + +### QueryOptions + + + + diff --git a/website/docs/examples/queries/prepared-statements/index.mdx b/website/docs/examples/queries/prepared-statements/index.mdx new file mode 100644 index 0000000000..4b3ad84928 --- /dev/null +++ b/website/docs/examples/queries/prepared-statements/index.mdx @@ -0,0 +1,19 @@ +# Prepared Statements + +MySQL2 provides `execute` helper which will prepare and query the statement. +You can also manually prepare / unprepare statement with `prepare` / `unprepare` methods. + +See detailed documentaion in [Prepared Statements](/docs/documentation/prepared-statements). + +:::tip +If you execute same statement again, it will be picked form a **LRU cache** which will save query preparation time and give better performance. +::: + +--- + +Usage examples: + +- [x] [**INSERT**](/docs/examples/queries/prepared-statements/insert) +- [x] [**SELECT**](/docs/examples/queries/prepared-statements/select) +- [x] [**UPDATE**](/docs/examples/queries/prepared-statements/update) +- [x] [**DELETE**](/docs/examples/queries/prepared-statements/delete) diff --git a/website/docs/examples/queries/prepared-statements/insert.mdx b/website/docs/examples/queries/prepared-statements/insert.mdx new file mode 100644 index 0000000000..ca766ae560 --- /dev/null +++ b/website/docs/examples/queries/prepared-statements/insert.mdx @@ -0,0 +1,217 @@ +--- +sidebar_position: 0 +tags: [Prepared Statements, Placeholders, Parameters, execute] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# INSERT + +## execute(sql, values) + +> **execute(sql: string, values: any[])** + + + + +```js +try { + const sql = 'INSERT INTO `users`(`name`, `age`) VALUES (?, ?), (?,?)'; + const values = ['Josh', 19, 'Page', 45]; + + // highlight-next-line + const [result, fields] = await connection.execute(sql, values); + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'INSERT INTO `users`(`name`, `age`) VALUES (?, ?), (?,?)'; +const values = ['Josh', 19, 'Page', 45]; + +connection.execute(sql, values, (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); +}); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## execute(options) + +> **execute(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = 'INSERT INTO `users`(`name`, `age`) VALUES (?, ?), (?,?)'; + const values = ['Josh', 19, 'Page', 45]; + + // highlight-start + const [result, fields] = await connection.execute({ + sql, + values, + // ... other options + }); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'INSERT INTO `users`(`name`, `age`) VALUES (?, ?), (?,?)'; +const values = ['Josh', 19, 'Page', 45]; + +connection.execute( + { + sql, + values, + // ... other options + }, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## execute(options, values) + +> **execute(options: [QueryOptions](#queryoptions), values: any[])** + + + + +```js +try { + const sql = 'INSERT INTO `users`(`name`, `age`) VALUES (?, ?), (?,?)'; + const values = ['Josh', 19, 'Page', 45]; + + // highlight-start + const [result, fields] = await connection.execute( + { + sql, + // ... other options + }, + values + ); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'INSERT INTO `users`(`name`, `age`) VALUES (?, ?), (?,?)'; +const values = ['Josh', 19, 'Page', 45]; + +connection.execute( + { + sql, + // ... other options + }, + values, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## Glossary + +### ResultSetHeader + + + + + +### QueryOptions + + + + diff --git a/website/docs/examples/queries/prepared-statements/select.mdx b/website/docs/examples/queries/prepared-statements/select.mdx new file mode 100644 index 0000000000..3bc0f6aa36 --- /dev/null +++ b/website/docs/examples/queries/prepared-statements/select.mdx @@ -0,0 +1,206 @@ +--- +sidebar_position: 1 +tags: [Prepared Statements, Placeholders, Parameters, execute] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# SELECT + +## execute(sql, values) + +> **execute(sql: string, values: any[])** + + + + +```js +try { + const sql = 'SELECT * FROM `users` WHERE `name` = ? AND `age` > ?'; + const values = ['Page', 45]; + + // highlight-next-line + const [rows, fields] = await connection.execute(sql, values); + + console.log(rows); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'SELECT * FROM `users` WHERE `name` = ? AND `age` > ?'; +const values = ['Page', 45]; + +connection.execute(sql, values, (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows); + console.log(fields); +}); +``` + + + + +- **rows** contains rows returned by server +- **fields** contains extra meta data about rows, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## execute(options) + +> **execute(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = 'SELECT * FROM `users` WHERE `name` = ? AND `age` > ?'; + const values = ['Page', 45]; + + // highlight-start + const [rows, fields] = await connection.execute({ + sql, + values, + // ... other options + }); + // highlight-end + + console.log(rows); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'SELECT * FROM `users` WHERE `name` = ? AND `age` > ?'; +const values = ['Page', 45]; + +connection.execute( + { + sql, + values, + // ... other options + }, + (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows); + console.log(fields); + } +); +``` + + + + +- **rows** contains rows returned by server +- **fields** contains extra meta data about rows, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## execute(options, values) + +> **execute(options: [QueryOptions](#queryoptions), values: any[])** + + + + +```js +try { + const sql = 'SELECT * FROM `users` WHERE `name` = ? AND `age` > ?'; + const values = ['Page', 45]; + + // highlight-start + const [rows, fields] = await connection.execute( + { + sql, + // ... other options + }, + values + ); + // highlight-end + + console.log(rows); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'SELECT * FROM `users` WHERE `name` = ? AND `age` > ?'; +const values = ['Page', 45]; + +connection.execute( + { + sql, + // ... other options + }, + values, + (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows); + console.log(fields); + } +); +``` + + + + +- **rows** contains rows returned by server +- **fields** contains extra meta data about rows, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## Glossary + +### QueryOptions + + + + diff --git a/website/docs/examples/queries/prepared-statements/update.mdx b/website/docs/examples/queries/prepared-statements/update.mdx new file mode 100644 index 0000000000..fbef730b57 --- /dev/null +++ b/website/docs/examples/queries/prepared-statements/update.mdx @@ -0,0 +1,217 @@ +--- +sidebar_position: 2 +tags: [Prepared Statements, Placeholders, Parameters, execute] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# UPDATE + +## execute(sql, values) + +> **execute(sql: string, values: any[])** + + + + +```js +try { + const sql = 'UPDATE `users` SET `age` = ? WHERE `name` = ? LIMIT 1'; + const values = [20, 'Josh']; + + // highlight-next-line + const [result, fields] = await connection.execute(sql, values); + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'UPDATE `users` SET `age` = ? WHERE `name` = ? LIMIT 1'; +const values = [20, 'Josh']; + +connection.execute(sql, values, (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); +}); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## execute(options) + +> **execute(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = 'UPDATE `users` SET `age` = ? WHERE `name` = ? LIMIT 1'; + const values = [20, 'Josh']; + + // highlight-start + const [result, fields] = await connection.execute({ + sql, + values, + // ... other options + }); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'UPDATE `users` SET `age` = ? WHERE `name` = ? LIMIT 1'; +const values = [20, 'Josh']; + +connection.execute( + { + sql, + values, + // ... other options + }, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## execute(options, values) + +> **execute(options: [QueryOptions](#queryoptions), values: any[])** + + + + +```js +try { + const sql = 'UPDATE `users` SET `age` = ? WHERE `name` = ? LIMIT 1'; + const values = [20, 'Josh']; + + // highlight-start + const [result, fields] = await connection.execute( + { + sql, + // ... other options + }, + values + ); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'UPDATE `users` SET `age` = ? WHERE `name` = ? LIMIT 1'; +const values = [20, 'Josh']; + +connection.execute( + { + sql, + // ... other options + }, + values, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`execute`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## Glossary + +### ResultSetHeader + + + + + +### QueryOptions + + + + diff --git a/website/docs/examples/queries/select.mdx b/website/docs/examples/queries/select.mdx deleted file mode 100644 index 251142aac9..0000000000 --- a/website/docs/examples/queries/select.mdx +++ /dev/null @@ -1,42 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# SELECT - - - - -```js -'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/docs/examples/queries/simple-queries/_category_.json b/website/docs/examples/queries/simple-queries/_category_.json new file mode 100644 index 0000000000..8bc971d275 --- /dev/null +++ b/website/docs/examples/queries/simple-queries/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Simple Queries", + "position": 1 +} diff --git a/website/docs/examples/queries/simple-queries/delete.mdx b/website/docs/examples/queries/simple-queries/delete.mdx new file mode 100644 index 0000000000..df7db243f2 --- /dev/null +++ b/website/docs/examples/queries/simple-queries/delete.mdx @@ -0,0 +1,147 @@ +--- +sidebar_position: 3 +tags: [query] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# DELETE + +The examples below also work for the [`execute`](/docs/examples/queries/prepared-statements/delete) method. + +## query(sql) + +> **query(sql: string)** + + + + +```js +try { + const sql = 'DELETE FROM `users` WHERE `name` = "Page" LIMIT 1'; + + // highlight-next-line + const [result, fields] = await connection.query(sql); + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'DELETE FROM `users` WHERE `name` = "Page" LIMIT 1'; + +connection.query(sql, (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); +}); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## query(options) + +> **query(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = 'DELETE FROM `users` WHERE `name` = "Page" LIMIT 1'; + + // highlight-start + const [result, fields] = await connection.query({ + sql, + // ... other options + }); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'DELETE FROM `users` WHERE `name` = "Page" LIMIT 1'; + +connection.query( + { + sql, + // ... other options + }, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## Glossary + +### ResultSetHeader + + + + + +### QueryOptions + + + + diff --git a/website/docs/examples/queries/simple-queries/index.mdx b/website/docs/examples/queries/simple-queries/index.mdx new file mode 100644 index 0000000000..32ce005b43 --- /dev/null +++ b/website/docs/examples/queries/simple-queries/index.mdx @@ -0,0 +1,14 @@ +# Simple Queries + +:::info +For **Prepared Statements** or **Placeholders** / **Parameters** examples, please see [here](/docs/examples/queries/prepared-statements). +::: + +--- + +Usage examples: + +- [x] [**INSERT**](/docs/examples/queries/simple-queries/insert) +- [x] [**SELECT**](/docs/examples/queries/simple-queries/select) +- [x] [**UPDATE**](/docs/examples/queries/simple-queries/update) +- [x] [**DELETE**](/docs/examples/queries/simple-queries/delete) diff --git a/website/docs/examples/queries/simple-queries/insert.mdx b/website/docs/examples/queries/simple-queries/insert.mdx new file mode 100644 index 0000000000..5fbe694d6c --- /dev/null +++ b/website/docs/examples/queries/simple-queries/insert.mdx @@ -0,0 +1,151 @@ +--- +sidebar_position: 0 +tags: [query] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# INSERT + +The examples below also work for the [`execute`](/docs/examples/queries/prepared-statements/insert) method. + +## query(sql) + +> **query(sql: string)** + + + + +```js +try { + const sql = + 'INSERT INTO `users`(`name`, `age`) VALUES ("Josh", 19), ("Page", 45)'; + + // highlight-next-line + const [result, fields] = await connection.query(sql); + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = + 'INSERT INTO `users`(`name`, `age`) VALUES ("Josh", 19), ("Page", 45)'; + +connection.query(sql, (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); +}); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## query(options) + +> **query(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = + 'INSERT INTO `users`(`name`, `age`) VALUES ("Josh", 19), ("Page", 45)'; + + // highlight-start + const [result, fields] = await connection.query({ + sql, + // ... other options + }); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = + 'INSERT INTO `users`(`name`, `age`) VALUES ("Josh", 19), ("Page", 45)'; + +connection.query( + { + sql, + // ... other options + }, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## Glossary + +### ResultSetHeader + + + + + +### QueryOptions + + + + diff --git a/website/docs/examples/queries/simple-queries/select.mdx b/website/docs/examples/queries/simple-queries/select.mdx new file mode 100644 index 0000000000..6da88b6007 --- /dev/null +++ b/website/docs/examples/queries/simple-queries/select.mdx @@ -0,0 +1,198 @@ +--- +sidebar_position: 1 +tags: [query] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# SELECT + +The examples below also work for the [`execute`](/docs/examples/queries/prepared-statements/select) method. + +## query(sql) + +> **query(sql: string)** + + + + +```js +try { + const sql = 'SELECT * FROM `users` WHERE `name` = "Page" AND `age` > 45'; + + // highlight-next-line + const [rows, fields] = await connection.query(sql); + + console.log(rows); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'SELECT * FROM `users` WHERE `name` = "Page" AND `age` > 45'; + +connection.query(sql, (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows); + console.log(fields); +}); +``` + + + + +- **rows** contains rows returned by server +- **fields** contains extra meta data about rows, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## query(options) + +> **query(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = 'SELECT * FROM `users` WHERE `name` = "Page" AND `age` > 45'; + + // highlight-start + const [rows, fields] = await connection.query({ + sql, + // ... other options + }); + // highlight-end + + console.log(rows); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'SELECT * FROM `users` WHERE `name` = "Page" AND `age` > 45'; + +connection.query( + { + sql, + // ... other options + }, + (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows); + console.log(fields); + } +); +``` + + + + +- **rows** contains rows returned by server +- **fields** contains extra meta data about rows, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## query(options) — Row as Array + +> **query(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = 'SELECT * FROM `users` WHERE `name` = "Page" AND `age` > 45'; + + // highlight-start + const [rows, fields] = await connection.query({ + sql, + rowsAsArray: true, + // ... other options + }); + // highlight-end + + console.log(rows); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'SELECT * FROM `users` WHERE `name` = "Page" AND `age` > 45'; + +connection.query( + { + sql, + rowsAsArray: true, + // ... other options + }, + (err, rows, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(rows); + console.log(fields); + } +); +``` + + + + +- **rows** contains rows returned by server as array +- **fields** contains extra meta data about rows, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## Glossary + +### QueryOptions + + + + diff --git a/website/docs/examples/queries/simple-queries/update.mdx b/website/docs/examples/queries/simple-queries/update.mdx new file mode 100644 index 0000000000..63ff8bc1e3 --- /dev/null +++ b/website/docs/examples/queries/simple-queries/update.mdx @@ -0,0 +1,147 @@ +--- +sidebar_position: 2 +tags: [query] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import { ExternalCodeEmbed } from '@site/src/components/ExternalCodeEmbed'; + +# UPDATE + +The examples below also work for the [`execute`](/docs/examples/queries/prepared-statements/update) method. + +## query(sql) + +> **query(sql: string)** + + + + +```js +try { + const sql = 'UPDATE `users` SET `age` = 20 WHERE `name` = "Josh" LIMIT 1'; + + // highlight-next-line + const [result, fields] = await connection.query(sql); + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'UPDATE `users` SET `age` = 20 WHERE `name` = "Josh" LIMIT 1'; + +connection.query(sql, (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); +}); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## query(options) + +> **query(options: [QueryOptions](#queryoptions))** + + + + +```js +try { + const sql = 'UPDATE `users` SET `age` = 20 WHERE `name` = "Josh" LIMIT 1'; + + // highlight-start + const [result, fields] = await connection.query({ + sql, + // ... other options + }); + // highlight-end + + console.log(result); + console.log(fields); +} catch (err) { + console.log(err); +} +``` + + + + +```js +const sql = 'UPDATE `users` SET `age` = 20 WHERE `name` = "Josh" LIMIT 1'; + +connection.query( + { + sql, + // ... other options + }, + (err, result, fields) => { + if (err instanceof Error) { + console.log(err); + return; + } + + console.log(result); + console.log(fields); + } +); +``` + + + + +- **result**: contains a [ResultSetHeader](#resultsetheader) object, which provides details about the operation executed by the server. +- **fields** contains extra meta data about the operation, if available + +:::info +The connection used for the query (`.query()`) can be obtained through the `createConnection`, `createPool` or `createPoolCluster` methods. +::: + +--- + +## Glossary + +### ResultSetHeader + + + + + +### QueryOptions + + + + diff --git a/website/docs/examples/ssl/_category_.json b/website/docs/examples/ssl/_category_.json deleted file mode 100644 index 2574b5e900..0000000000 --- a/website/docs/examples/ssl/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "SSL", - "link": { - "type": "generated-index" - } -} diff --git a/website/docs/examples/ssl/rds-ssl.mdx b/website/docs/examples/ssl/rds-ssl.mdx deleted file mode 100644 index de45be0acd..0000000000 --- a/website/docs/examples/ssl/rds-ssl.mdx +++ /dev/null @@ -1,30 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# RDS SSL - - - - -```js -'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/docs/examples/ssl/select-over-ssl.mdx b/website/docs/examples/ssl/select-over-ssl.mdx deleted file mode 100644 index fc7d413587..0000000000 --- a/website/docs/examples/ssl/select-over-ssl.mdx +++ /dev/null @@ -1,39 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Select Over SSL - - - - -```js -'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); - }); -}); -``` - - - - -- See [examples/ssl/certs](https://github.com/sidorares/node-mysql2/tree/master/examples/ssl/certs). diff --git a/website/docs/examples/tests/_category_.json b/website/docs/examples/tests/_category_.json new file mode 100644 index 0000000000..fd4ebff704 --- /dev/null +++ b/website/docs/examples/tests/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Tests" +} diff --git a/website/docs/examples/mysqlproxy.mdx b/website/docs/examples/tests/mysql-proxy.mdx similarity index 100% rename from website/docs/examples/mysqlproxy.mdx rename to website/docs/examples/tests/mysql-proxy.mdx diff --git a/website/docs/examples/pool-test.mdx b/website/docs/examples/tests/pool.mdx similarity index 98% rename from website/docs/examples/pool-test.mdx rename to website/docs/examples/tests/pool.mdx index 7c9f9f3950..9efe528f3d 100644 --- a/website/docs/examples/pool-test.mdx +++ b/website/docs/examples/tests/pool.mdx @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Pool Test +# Pool diff --git a/website/docs/examples/server.mdx b/website/docs/examples/tests/server.mdx similarity index 100% rename from website/docs/examples/server.mdx rename to website/docs/examples/tests/server.mdx diff --git a/website/docs/examples/typescript/_category_.json b/website/docs/examples/typescript/_category_.json index 0a79b82b72..6bb9677aa4 100644 --- a/website/docs/examples/typescript/_category_.json +++ b/website/docs/examples/typescript/_category_.json @@ -1,6 +1,3 @@ { - "label": "TypeScript", - "link": { - "type": "generated-index" - } + "label": "TypeScript" } diff --git a/website/docs/examples/typescript/procedure-call/00-procedure-call-packet.mdx b/website/docs/examples/typescript/procedure-call/00-index.mdx similarity index 100% rename from website/docs/examples/typescript/procedure-call/00-procedure-call-packet.mdx rename to website/docs/examples/typescript/procedure-call/00-index.mdx diff --git a/website/docs/examples/typescript/procedure-call/_category_.json b/website/docs/examples/typescript/procedure-call/_category_.json index abe7167157..7155b654df 100644 --- a/website/docs/examples/typescript/procedure-call/_category_.json +++ b/website/docs/examples/typescript/procedure-call/_category_.json @@ -1,6 +1,3 @@ { - "label": "Procedure Call Packet", - "link": { - "type": "generated-index" - } + "label": "Procedure Call" } diff --git a/website/docs/examples/typescript/row-data/00-row-data-packet.mdx b/website/docs/examples/typescript/row-data/00-index.mdx similarity index 100% rename from website/docs/examples/typescript/row-data/00-row-data-packet.mdx rename to website/docs/examples/typescript/row-data/00-index.mdx diff --git a/website/docs/examples/typescript/row-data/_category_.json b/website/docs/examples/typescript/row-data/_category_.json index 549c5a1120..9b197bc252 100644 --- a/website/docs/examples/typescript/row-data/_category_.json +++ b/website/docs/examples/typescript/row-data/_category_.json @@ -1,6 +1,3 @@ { - "label": "Row Data Packet", - "link": { - "type": "generated-index" - } + "label": "Row Data" } diff --git a/website/docs/index.mdx b/website/docs/index.mdx index 3518ebf858..67fa090300 100644 --- a/website/docs/index.mdx +++ b/website/docs/index.mdx @@ -60,6 +60,8 @@ npm install --save-dev @types/node ### First Query +> To explore more queries examples, please visit the example sections [**Simple Queries**](/docs/examples/queries/simple-queries) and [**Prepared Statements**](/docs/examples/queries/prepared-statements). + @@ -145,6 +147,8 @@ With MySQL2 you also get the prepared statements. With prepared statements MySQL MySQL2 provides `execute` helper which will prepare and query the statement. You can also manually prepare / unprepare statement with `prepare` / `unprepare` methods. +> To explore more Prepared Statements and Placeholders examples, please visit the example section [**Prepared Statements**](/docs/examples/queries/prepared-statements). + @@ -211,6 +215,8 @@ Connection pools help reduce the time spent connecting to the MySQL server by re This improves the latency of queries as you avoid all of the overhead that comes with establishing a new connection. +> To explore more Connection Pools examples, please visit the example section [**createPool**](/docs/examples/connections/create-pool). + diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 9d0496dec2..ffffa0345d 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -13,7 +13,8 @@ const config: Config = { favicon: 'img/favicon.svg', onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', + onBrokenMarkdownLinks: 'throw', + onBrokenAnchors: 'throw', i18n: { defaultLocale: 'en', diff --git a/website/helpers/extract-method-content.ts b/website/helpers/extract-method-content.ts new file mode 100644 index 0000000000..675129c08e --- /dev/null +++ b/website/helpers/extract-method-content.ts @@ -0,0 +1,32 @@ +export type MethodType = 'class' | 'interface' | 'type' | 'function' | 'const'; + +export const extractMethodContent = ( + text: string, + methodName: string, + type: MethodType +): string => { + const lines = text.split('\n'); + const startPattern = `${type} ${methodName}`; + + let insideSegment: boolean = false; + let depth: number = 0; + let extractedCode: string = ''; + + for (const line of lines) { + if (line.includes(startPattern)) insideSegment = true; + + if (insideSegment) { + if (line.includes('{')) depth++; + + extractedCode += line + '\n'; + + if (line.includes('}')) { + depth--; + + if (depth === 0) break; + } + } + } + + return extractedCode.trim() || text; +}; diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/index.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/index.mdx index 0feea50a70..18b93c63e0 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/index.mdx +++ b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/index.mdx @@ -50,6 +50,8 @@ O MySQL2 não tem restrições nativas e pode ser instalado no Linux, Mac OS ou ### Primeira Consulta (_Query_) +> Para explorar mais exemplos de consulta (queries), visite a seção de exemplos [**Consultas Simples**](/docs/examples/queries/simple-queries) e [**Instruções Preparadas (_Prepared Statements_)**](/docs/examples/queries/prepared-statements). + @@ -135,6 +137,8 @@ Com o MySQL2 você também pode obter Instruções Preparadas (Prepared Statemen O MySQL2 fornece o método auxiliar `execute` que irá preparar e consultar as declarações (_statements_) SQL. Além disso, você também pode usar os métodos `prepare` e `unprepare` para preparar ou desfazer a preparação de declarações (_statements_) manualmente, se necessário. +> Para explorar mais exemplos de Instruções Preparadas (_Prepared Statements_), visite a seção de exemplos [**Instruções Preparadas (_Prepared Statements_)**](/docs/examples/queries/prepared-statements). + @@ -195,12 +199,14 @@ Se você executar a mesma declaração novamente, ela será selecionada a partir --- -### Usando Conjunto de Conexões (_pools_) +### Usando Conjunto de Conexões (_pools_) {#using-connection-pools} O conjunto de conexões (_pools_) ajuda a reduzir o tempo gasto na conexão com o servidor MySQL, reutilizando uma conexão anterior e deixando-as abertas ao invés de fechá-las quando você termina de usá-las. Isto melhora a latência das consultas (_queries_), pois evita toda a sobrecarga associada à criação de uma nova conexão. +> Para explorar mais exemplos de Conjunto de Conexões (_pools_), visite a seção de exemplos [**createPool**](/docs/examples/connections/create-pool). + diff --git a/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/index.mdx b/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/index.mdx index 9cbfb25112..96826539e0 100644 --- a/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/index.mdx +++ b/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/index.mdx @@ -50,6 +50,8 @@ npm install --save-dev @types/node ### 查询数据 +> To explore more queries examples, please visit the example sections [**Simple Queries**](/docs/examples/queries/simple-queries) and [**Prepared Statements**](/docs/examples/queries/prepared-statements). + @@ -135,6 +137,8 @@ connection.query( MySQL2 提供了 `execute` 辅助函数,它将准备和查询语句。 您还可以使用 `prepare` / `unprepare` 方法手动准备/取消准备。 +> To explore more Prepared Statements and Placeholders examples, please visit the example section [**Prepared Statements**](/docs/examples/queries/prepared-statements). + @@ -195,12 +199,14 @@ connection.execute( --- -### 连接池的使用 +### 连接池的使用 {#using-connection-pools} 连接池通过重用以前的连接来帮助减少连接到 MySQL 服务器所花费的时间,当你完成它们时让它们保持打开而不是关闭。 这改善了查询的延迟,因为您避免了建立新连接所带来的所有开销。 +> To explore more Connection Pools examples, please visit the example section [**createPool**](/docs/examples/connections/create-pool). + diff --git a/website/package-lock.json b/website/package-lock.json index c6a1a9fd4b..7877c2e8b2 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -8,22 +8,24 @@ "name": "website", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.0.1", - "@docusaurus/preset-classic": "^3.0.1", + "@docusaurus/core": "^3.1.0", + "@docusaurus/preset-classic": "^3.1.0", "@easyops-cn/docusaurus-search-local": "^0.40.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.1.0", "docusaurus-plugin-sass": "^0.2.5", - "lucide-react": "^0.303.0", + "lucide-react": "^0.306.0", "prism-react-renderer": "^2.3.1", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.69.7" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.0.1", - "@docusaurus/tsconfig": "^3.0.1", - "@docusaurus/types": "^3.0.1", + "@docusaurus/eslint-plugin": "^3.1.0", + "@docusaurus/module-type-aliases": "^3.1.0", + "@docusaurus/tsconfig": "^3.1.0", + "@docusaurus/types": "^3.1.0", + "@types/node": "^20.10.6", "@typescript-eslint/eslint-plugin": "^6.17.0", "@typescript-eslint/parser": "^6.17.0", "eslint": "^8.56.0", @@ -33,6 +35,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", "prettier": "^3.1.1", + "tsx": "^4.7.0", "typescript": "^5.3.3" }, "engines": { @@ -90,74 +93,74 @@ } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.20.0.tgz", - "integrity": "sha512-uujahcBt4DxduBTvYdwO3sBfHuJvJokiC3BP1+O70fglmE1ShkH8lpXqZBac1rrU3FnNYSUs4pL9lBdTKeRPOQ==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.0.tgz", + "integrity": "sha512-uZ1uZMLDZb4qODLfTSNHxSi4fH9RdrQf7DXEzW01dS8XK7QFtFh29N5NGKa9S+Yudf1vUMIF+/RiL4i/J0pWlQ==", "dependencies": { - "@algolia/cache-common": "4.20.0" + "@algolia/cache-common": "4.22.0" } }, "node_modules/@algolia/cache-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.20.0.tgz", - "integrity": "sha512-vCfxauaZutL3NImzB2G9LjLt36vKAckc6DhMp05An14kVo8F1Yofb6SIl6U3SaEz8pG2QOB9ptwM5c+zGevwIQ==" + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.22.0.tgz", + "integrity": "sha512-TPwUMlIGPN16eW67qamNQUmxNiGHg/WBqWcrOoCddhqNTqGDPVqmgfaM85LPbt24t3r1z0zEz/tdsmuq3Q6oaA==" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.20.0.tgz", - "integrity": "sha512-Wm9ak/IaacAZXS4mB3+qF/KCoVSBV6aLgIGFEtQtJwjv64g4ePMapORGmCyulCFwfePaRAtcaTbMcJF+voc/bg==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.22.0.tgz", + "integrity": "sha512-kf4Cio9NpPjzp1+uXQgL4jsMDeck7MP89BYThSvXSjf2A6qV/0KeqQf90TL2ECS02ovLOBXkk98P7qVarM+zGA==", "dependencies": { - "@algolia/cache-common": "4.20.0" + "@algolia/cache-common": "4.22.0" } }, "node_modules/@algolia/client-account": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.20.0.tgz", - "integrity": "sha512-GGToLQvrwo7am4zVkZTnKa72pheQeez/16sURDWm7Seyz+HUxKi3BM6fthVVPUEBhtJ0reyVtuK9ArmnaKl10Q==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.22.0.tgz", + "integrity": "sha512-Bjb5UXpWmJT+yGWiqAJL0prkENyEZTBzdC+N1vBuHjwIJcjLMjPB6j1hNBRbT12Lmwi55uzqeMIKS69w+0aPzA==", "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.22.0", + "@algolia/client-search": "4.22.0", + "@algolia/transporter": "4.22.0" } }, "node_modules/@algolia/client-analytics": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.20.0.tgz", - "integrity": "sha512-EIr+PdFMOallRdBTHHdKI3CstslgLORQG7844Mq84ib5oVFRVASuuPmG4bXBgiDbcsMLUeOC6zRVJhv1KWI0ug==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.22.0.tgz", + "integrity": "sha512-os2K+kHUcwwRa4ArFl5p/3YbF9lN3TLOPkbXXXxOvDpqFh62n9IRZuzfxpHxMPKAQS3Et1s0BkKavnNP02E9Hg==", "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.22.0", + "@algolia/client-search": "4.22.0", + "@algolia/requester-common": "4.22.0", + "@algolia/transporter": "4.22.0" } }, "node_modules/@algolia/client-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.20.0.tgz", - "integrity": "sha512-P3WgMdEss915p+knMMSd/fwiHRHKvDu4DYRrCRaBrsfFw7EQHon+EbRSm4QisS9NYdxbS04kcvNoavVGthyfqQ==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.22.0.tgz", + "integrity": "sha512-BlbkF4qXVWuwTmYxVWvqtatCR3lzXwxx628p1wj1Q7QP2+LsTmGt1DiUYRuy9jG7iMsnlExby6kRMOOlbhv2Ag==", "dependencies": { - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/requester-common": "4.22.0", + "@algolia/transporter": "4.22.0" } }, "node_modules/@algolia/client-personalization": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.20.0.tgz", - "integrity": "sha512-N9+zx0tWOQsLc3K4PVRDV8GUeOLAY0i445En79Pr3zWB+m67V+n/8w4Kw1C5LlbHDDJcyhMMIlqezh6BEk7xAQ==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.22.0.tgz", + "integrity": "sha512-pEOftCxeBdG5pL97WngOBi9w5Vxr5KCV2j2D+xMVZH8MuU/JX7CglDSDDb0ffQWYqcUN+40Ry+xtXEYaGXTGow==", "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.22.0", + "@algolia/requester-common": "4.22.0", + "@algolia/transporter": "4.22.0" } }, "node_modules/@algolia/client-search": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.20.0.tgz", - "integrity": "sha512-zgwqnMvhWLdpzKTpd3sGmMlr4c+iS7eyyLGiaO51zDZWGMkpgoNVmltkzdBwxOVXz0RsFMznIxB9zuarUv4TZg==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.0.tgz", + "integrity": "sha512-bn4qQiIdRPBGCwsNuuqB8rdHhGKKWIij9OqidM1UkQxnSG8yzxHdb7CujM30pvp5EnV7jTqDZRbxacbjYVW20Q==", "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.22.0", + "@algolia/requester-common": "4.22.0", + "@algolia/transporter": "4.22.0" } }, "node_modules/@algolia/events": { @@ -166,47 +169,47 @@ "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" }, "node_modules/@algolia/logger-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.20.0.tgz", - "integrity": "sha512-xouigCMB5WJYEwvoWW5XDv7Z9f0A8VoXJc3VKwlHJw/je+3p2RcDXfksLI4G4lIVncFUYMZx30tP/rsdlvvzHQ==" + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.22.0.tgz", + "integrity": "sha512-HMUQTID0ucxNCXs5d1eBJ5q/HuKg8rFVE/vOiLaM4Abfeq1YnTtGV3+rFEhOPWhRQxNDd+YHa4q864IMc0zHpQ==" }, "node_modules/@algolia/logger-console": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.20.0.tgz", - "integrity": "sha512-THlIGG1g/FS63z0StQqDhT6bprUczBI8wnLT3JWvfAQDZX5P6fCg7dG+pIrUBpDIHGszgkqYEqECaKKsdNKOUA==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.22.0.tgz", + "integrity": "sha512-7JKb6hgcY64H7CRm3u6DRAiiEVXMvCJV5gRE672QFOUgDxo4aiDpfU61g6Uzy8NKjlEzHMmgG4e2fklELmPXhQ==", "dependencies": { - "@algolia/logger-common": "4.20.0" + "@algolia/logger-common": "4.22.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.20.0.tgz", - "integrity": "sha512-HbzoSjcjuUmYOkcHECkVTwAelmvTlgs48N6Owt4FnTOQdwn0b8pdht9eMgishvk8+F8bal354nhx/xOoTfwiAw==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.0.tgz", + "integrity": "sha512-BHfv1h7P9/SyvcDJDaRuIwDu2yrDLlXlYmjvaLZTtPw6Ok/ZVhBR55JqW832XN/Fsl6k3LjdkYHHR7xnsa5Wvg==", "dependencies": { - "@algolia/requester-common": "4.20.0" + "@algolia/requester-common": "4.22.0" } }, "node_modules/@algolia/requester-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.20.0.tgz", - "integrity": "sha512-9h6ye6RY/BkfmeJp7Z8gyyeMrmmWsMOCRBXQDs4mZKKsyVlfIVICpcSibbeYcuUdurLhIlrOUkH3rQEgZzonng==" + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.22.0.tgz", + "integrity": "sha512-Y9cEH/cKjIIZgzvI1aI0ARdtR/xRrOR13g5psCxkdhpgRN0Vcorx+zePhmAa4jdQNqexpxtkUdcKYugBzMZJgQ==" }, "node_modules/@algolia/requester-node-http": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.20.0.tgz", - "integrity": "sha512-ocJ66L60ABSSTRFnCHIEZpNHv6qTxsBwJEPfYaSBsLQodm0F9ptvalFkHMpvj5DfE22oZrcrLbOYM2bdPJRHng==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.22.0.tgz", + "integrity": "sha512-8xHoGpxVhz3u2MYIieHIB6MsnX+vfd5PS4REgglejJ6lPigftRhTdBCToe6zbwq4p0anZXjjPDvNWMlgK2+xYA==", "dependencies": { - "@algolia/requester-common": "4.20.0" + "@algolia/requester-common": "4.22.0" } }, "node_modules/@algolia/transporter": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.20.0.tgz", - "integrity": "sha512-Lsii1pGWOAISbzeyuf+r/GPhvHMPHSPrTDWNcIzOE1SG1inlJHICaVe2ikuoRjcpgxZNU54Jl+if15SUCsaTUg==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.22.0.tgz", + "integrity": "sha512-ieO1k8x2o77GNvOoC+vAkFKppydQSVfbjM3YrSjLmgywiBejPTvU1R1nEvG59JIIUvtSLrZsLGPkd6vL14zopA==", "dependencies": { - "@algolia/cache-common": "4.20.0", - "@algolia/logger-common": "4.20.0", - "@algolia/requester-common": "4.20.0" + "@algolia/cache-common": "4.22.0", + "@algolia/logger-common": "4.22.0", + "@algolia/requester-common": "4.22.0" } }, "node_modules/@ampproject/remapping": { @@ -2186,9 +2189,9 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.0.1.tgz", - "integrity": "sha512-CXrLpOnW+dJdSv8M5FAJ3JBwXtL6mhUWxFA8aS0ozK6jBG/wgxERk5uvH28fCeFxOGbAT9v1e9dOMo1X2IEVhQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.1.0.tgz", + "integrity": "sha512-GWudMGYA9v26ssbAWJNfgeDZk+lrudUTclLPRsmxiknEBk7UMp7Rglonhqbsf3IKHOyHkMU4Fr5jFyg5SBx9jQ==", "dependencies": { "@babel/core": "^7.23.3", "@babel/generator": "^7.23.3", @@ -2200,13 +2203,13 @@ "@babel/runtime": "^7.22.6", "@babel/runtime-corejs3": "^7.22.6", "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", + "@docusaurus/cssnano-preset": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@slorber/static-site-generator-webpack-plugin": "^4.0.7", "@svgr/webpack": "^6.5.1", "autoprefixer": "^10.4.14", @@ -2272,9 +2275,9 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.0.1.tgz", - "integrity": "sha512-wjuXzkHMW+ig4BD6Ya1Yevx9UJadO4smNZCEljqBoQfIQrQskTswBs7lZ8InHP7mCt273a/y/rm36EZhqJhknQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.1.0.tgz", + "integrity": "sha512-ned7qsgCqSv/e7KyugFNroAfiszuxLwnvMW7gmT2Ywxb/Nyt61yIw7KHyAZCMKglOalrqnYA4gMhLUCK/mVePA==", "dependencies": { "cssnano-preset-advanced": "^5.3.10", "postcss": "^8.4.26", @@ -2285,10 +2288,126 @@ "node": ">=18.0" } }, + "node_modules/@docusaurus/eslint-plugin": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/eslint-plugin/-/eslint-plugin-3.1.0.tgz", + "integrity": "sha512-Zo/QNKFyHa0JG2shKwFKZTQnSc8ECXIWmnfi8y5RjTBiWLsoxusePCRcOQMqVWSRknO0bumZyOLjKEFK7Z57Ew==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.62.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "eslint": ">=6" + } + }, + "node_modules/@docusaurus/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@docusaurus/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@docusaurus/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@docusaurus/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@docusaurus/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@docusaurus/logger": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.0.1.tgz", - "integrity": "sha512-I5L6Nk8OJzkVA91O2uftmo71LBSxe1vmOn9AMR6JRCzYeEBrqneWMH02AqMvjJ2NpMiviO+t0CyPjyYV7nxCWQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.1.0.tgz", + "integrity": "sha512-p740M+HCst1VnKKzL60Hru9xfG4EUYJDarjlEC4hHeBy9+afPmY3BNPoSHx9/8zxuYfUlv/psf7I9NvRVdmdvg==", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.6.0" @@ -2298,15 +2417,15 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.0.1.tgz", - "integrity": "sha512-ldnTmvnvlrONUq45oKESrpy+lXtbnTcTsFkOTIDswe5xx5iWJjt6eSa0f99ZaWlnm24mlojcIGoUWNCS53qVlQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.1.0.tgz", + "integrity": "sha512-D7onDz/3mgBonexWoQXPw3V2E5Bc4+jYRf9gGUUK+KoQwU8xMDaDkUUfsr7t6UBa/xox9p5+/3zwLuXOYMzGSg==", "dependencies": { "@babel/parser": "^7.22.7", "@babel/traverse": "^7.22.8", - "@docusaurus/logger": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/logger": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -2338,12 +2457,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.0.1.tgz", - "integrity": "sha512-DEHpeqUDsLynl3AhQQiO7AbC7/z/lBra34jTcdYuvp9eGm01pfH1wTVq8YqWZq6Jyx0BgcVl/VJqtE9StRd9Ag==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.1.0.tgz", + "integrity": "sha512-XUl7Z4PWlKg4l6KF05JQ3iDHQxnPxbQUqTNKvviHyuHdlalOFv6qeDAm7IbzyQPJD5VA6y4dpRbTWSqP9ClwPg==", "dependencies": { "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "3.0.1", + "@docusaurus/types": "3.1.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2357,17 +2476,17 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.0.1.tgz", - "integrity": "sha512-cLOvtvAyaMQFLI8vm4j26svg3ktxMPSXpuUJ7EERKoGbfpJSsgtowNHcRsaBVmfuCsRSk1HZ/yHBsUkTmHFEsg==", - "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.1.0.tgz", + "integrity": "sha512-iMa6WBaaEdYuxckvJtLcq/HQdlA4oEbCXf/OFfsYJCCULcDX7GDZpKxLF3X1fLsax3sSm5bmsU+CA0WD+R1g3A==", + "dependencies": { + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", @@ -2388,17 +2507,17 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.0.1.tgz", - "integrity": "sha512-dRfAOA5Ivo+sdzzJGXEu33yAtvGg8dlZkvt/NEJ7nwi1F2j4LEdsxtfX2GKeETB2fP6XoGNSQnFXqa2NYGrHFg==", - "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.1.0.tgz", + "integrity": "sha512-el5GxhT8BLrsWD0qGa8Rq+Ttb/Ni6V3DGT2oAPio0qcs/mUAxeyXEAmihkvmLCnAgp6xD27Ce7dISZ5c6BXeqA==", + "dependencies": { + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -2417,15 +2536,15 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.0.1.tgz", - "integrity": "sha512-oP7PoYizKAXyEttcvVzfX3OoBIXEmXTMzCdfmC4oSwjG4SPcJsRge3mmI6O8jcZBgUPjIzXD21bVGWEE1iu8gg==", - "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.1.0.tgz", + "integrity": "sha512-9gntYQFpk+93+Xl7gYczJu8I9uWoyRLnRwS0+NUFcs9iZtHKsdqKWPRrONC9elfN3wJ9ORwTbcVzsTiB8jvYlg==", + "dependencies": { + "@docusaurus/core": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -2439,13 +2558,13 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.0.1.tgz", - "integrity": "sha512-09dxZMdATky4qdsZGzhzlUvvC+ilQ2hKbYF+wez+cM2mGo4qHbv8+qKXqxq0CQZyimwlAOWQLoSozIXU0g0i7g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.1.0.tgz", + "integrity": "sha512-AbvJwCVRbmQ8w9d8QXbF4Iq/ui0bjPZNYFIhtducGFnm2YQRN1mraK8mCEQb0Aq0T8SqRRvSfC/far4n/s531w==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", "fs-extra": "^11.1.1", "react-json-view-lite": "^1.2.0", "tslib": "^2.6.0" @@ -2459,13 +2578,13 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.0.1.tgz", - "integrity": "sha512-jwseSz1E+g9rXQwDdr0ZdYNjn8leZBnKPjjQhMBEiwDoenL3JYFcNW0+p0sWoVF/f2z5t7HkKA+cYObrUh18gg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.1.0.tgz", + "integrity": "sha512-zvUOMzu9Uhz0ciqnSbtnp/5i1zEYlzarQrOXG90P3Is3efQI43p2YLW/rzSGdLb5MfQo2HvKT6Q5+tioMO045Q==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "tslib": "^2.6.0" }, "engines": { @@ -2477,13 +2596,13 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.0.1.tgz", - "integrity": "sha512-UFTDvXniAWrajsulKUJ1DB6qplui1BlKLQZjX4F7qS/qfJ+qkKqSkhJ/F4VuGQ2JYeZstYb+KaUzUzvaPK1aRQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.1.0.tgz", + "integrity": "sha512-0txshvaY8qIBdkk2UATdVcfiCLGq3KAUfuRQD2cRNgO39iIf4/ihQxH9NXcRTwKs4Q5d9yYHoix3xT6pFuEYOg==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -2496,13 +2615,13 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.0.1.tgz", - "integrity": "sha512-IPFvuz83aFuheZcWpTlAdiiX1RqWIHM+OH8wS66JgwAKOiQMR3+nLywGjkLV4bp52x7nCnwhNk1rE85Cpy/CIw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.1.0.tgz", + "integrity": "sha512-zOWPEi8kMyyPtwG0vhyXrdbLs8fIZmY5vlbi9lUU+v8VsroO5iHmfR2V3SMsrsfOanw5oV/ciWqbxezY00qEZg==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "tslib": "^2.6.0" }, "engines": { @@ -2514,16 +2633,16 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.0.1.tgz", - "integrity": "sha512-xARiWnjtVvoEniZudlCq5T9ifnhCu/GAZ5nA7XgyLfPcNpHQa241HZdsTlLtVcecEVVdllevBKOp7qknBBaMGw==", - "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.1.0.tgz", + "integrity": "sha512-TkR5vGBpUooEB9SoW42thahqqwKzfHrQQhkB+JrEGERsl4bKODSuJNle4aA4h6LSkg4IyfXOW8XOI0NIPWb9Cg==", + "dependencies": { + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -2537,23 +2656,23 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.0.1.tgz", - "integrity": "sha512-il9m9xZKKjoXn6h0cRcdnt6wce0Pv1y5t4xk2Wx7zBGhKG1idu4IFHtikHlD0QPuZ9fizpXspXcTzjL5FXc1Gw==", - "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/plugin-debug": "3.0.1", - "@docusaurus/plugin-google-analytics": "3.0.1", - "@docusaurus/plugin-google-gtag": "3.0.1", - "@docusaurus/plugin-google-tag-manager": "3.0.1", - "@docusaurus/plugin-sitemap": "3.0.1", - "@docusaurus/theme-classic": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-search-algolia": "3.0.1", - "@docusaurus/types": "3.0.1" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.1.0.tgz", + "integrity": "sha512-xGLQRFmmT9IinAGUDVRYZ54Ys28USNbA3OTXQXnSJLPr1rCY7CYnHI4XoOnKWrNnDiAI4ruMzunXWyaElUYCKQ==", + "dependencies": { + "@docusaurus/core": "3.1.0", + "@docusaurus/plugin-content-blog": "3.1.0", + "@docusaurus/plugin-content-docs": "3.1.0", + "@docusaurus/plugin-content-pages": "3.1.0", + "@docusaurus/plugin-debug": "3.1.0", + "@docusaurus/plugin-google-analytics": "3.1.0", + "@docusaurus/plugin-google-gtag": "3.1.0", + "@docusaurus/plugin-google-tag-manager": "3.1.0", + "@docusaurus/plugin-sitemap": "3.1.0", + "@docusaurus/theme-classic": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-search-algolia": "3.1.0", + "@docusaurus/types": "3.1.0" }, "engines": { "node": ">=18.0" @@ -2576,22 +2695,22 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.0.1.tgz", - "integrity": "sha512-XD1FRXaJiDlmYaiHHdm27PNhhPboUah9rqIH0lMpBt5kYtsGjJzhqa27KuZvHLzOP2OEpqd2+GZ5b6YPq7Q05Q==", - "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.1.0.tgz", + "integrity": "sha512-/+jMl2Z9O8QQxves5AtHdt91gWsEZFgOV3La/6eyKEd7QLqQUtM5fxEJ40rq9NKYjqCd1HzZ9egIMeJoWwillw==", + "dependencies": { + "@docusaurus/core": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/plugin-content-blog": "3.1.0", + "@docusaurus/plugin-content-docs": "3.1.0", + "@docusaurus/plugin-content-pages": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-translations": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", @@ -2615,17 +2734,17 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.0.1.tgz", - "integrity": "sha512-cr9TOWXuIOL0PUfuXv6L5lPlTgaphKP+22NdVBOYah5jSq5XAAulJTjfe+IfLsEG4L7lJttLbhW7LXDFSAI7Ag==", - "dependencies": { - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.1.0.tgz", + "integrity": "sha512-YGwEFALLIbF5ocW/Fy6Ae7tFWUOugEN3iwxTx8UkLAcLqYUboDSadesYtVBmRCEB4FVA2qoP7YaW3lu3apUPPw==", + "dependencies": { + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/plugin-content-blog": "3.1.0", + "@docusaurus/plugin-content-docs": "3.1.0", + "@docusaurus/plugin-content-pages": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2644,18 +2763,18 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.0.1.tgz", - "integrity": "sha512-DDiPc0/xmKSEdwFkXNf1/vH1SzJPzuJBar8kMcBbDAZk/SAmo/4lf6GU2drou4Ae60lN2waix+jYWTWcJRahSA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.1.0.tgz", + "integrity": "sha512-8cJH0ZhPsEDjq3jR3I+wHmWzVY2bXMQJ59v2QxUmsTZxbWA4u+IzccJMIJx4ooFl9J6iYynwYsFuHxyx/KUmfQ==", "dependencies": { "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/plugin-content-docs": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-translations": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "algoliasearch": "^4.18.0", "algoliasearch-helper": "^3.13.3", "clsx": "^2.0.0", @@ -2674,9 +2793,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.0.1.tgz", - "integrity": "sha512-6UrbpzCTN6NIJnAtZ6Ne9492vmPVX+7Fsz4kmp+yor3KQwA1+MCzQP7ItDNkP38UmVLnvB/cYk/IvehCUqS3dg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.1.0.tgz", + "integrity": "sha512-DApE4AbDI+WBajihxB54L4scWQhVGNZAochlC9fkbciPuFAgdRBD3NREb0rgfbKexDC/rioppu/WJA0u8tS+yA==", "dependencies": { "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -2686,16 +2805,17 @@ } }, "node_modules/@docusaurus/tsconfig": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.0.1.tgz", - "integrity": "sha512-hT2HCdNE3pWTzXV/7cSsowfmaOxXVOTFOXmkqaYjBWjaxjJ3FO0nHbdJ8rF6Da7PvWmIPbUekdP5gep1XCJ7Vg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.1.0.tgz", + "integrity": "sha512-PE6fSuj5gJy5sNC1OO+bYAU1/xZH5YqddGjhrNu3/T7OAUroqkMZfVl13Tz70CjYB8no4OWcraqSkObAeNdIcQ==", "dev": true }, "node_modules/@docusaurus/types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.0.1.tgz", - "integrity": "sha512-plyX2iU1tcUsF46uQ01pAd4JhexR7n0iiQ5MSnBFX6M6NSJgDYdru/i1/YNPKOnQHBoXGLHv0dNT6OAlDWNjrg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.1.0.tgz", + "integrity": "sha512-VaczOZf7+re8aFBIWnex1XENomwHdsSTkrdX43zyor7G/FY4OIsP6X28Xc3o0jiY0YdNuvIDyA5TNwOtpgkCVw==", "dependencies": { + "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", "@types/react": "*", "commander": "^5.1.0", @@ -2711,11 +2831,11 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.0.1.tgz", - "integrity": "sha512-TwZ33Am0q4IIbvjhUOs+zpjtD/mXNmLmEgeTGuRq01QzulLHuPhaBTTAC/DHu6kFx3wDgmgpAlaRuCHfTcXv8g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-LgZfp0D+UBqAh7PZ//MUNSFBMavmAPku6Si9x8x3V+S318IGCNJ6hUr2O29UO0oLybEWUjD5Jnj9IUN6XyZeeg==", "dependencies": { - "@docusaurus/logger": "3.0.1", + "@docusaurus/logger": "3.1.0", "@svgr/webpack": "^6.5.1", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", @@ -2746,9 +2866,9 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.0.1.tgz", - "integrity": "sha512-W0AxD6w6T8g6bNro8nBRWf7PeZ/nn7geEWM335qHU2DDDjHuV4UZjgUGP1AQsdcSikPrlIqTJJbKzer1lRSlIg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.1.0.tgz", + "integrity": "sha512-SfvnRLHoZ9bwTw67knkSs7IcUR0GY2SaGkpdB/J9pChrDiGhwzKNUhcieoPyPYrOWGRPk3rVNYtoy+Bc7psPAw==", "dependencies": { "tslib": "^2.6.0" }, @@ -2765,12 +2885,12 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.0.1.tgz", - "integrity": "sha512-ujTnqSfyGQ7/4iZdB4RRuHKY/Nwm58IIb+41s5tCXOv/MBU2wGAjOHq3U+AEyJ8aKQcHbxvTKJaRchNHYUVUQg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.1.0.tgz", + "integrity": "sha512-dFxhs1NLxPOSzmcTk/eeKxLY5R+U4cua22g9MsAMiRWcwFKStZ2W3/GDY0GmnJGqNS8QAQepJrxQoyxXkJNDeg==", "dependencies": { - "@docusaurus/logger": "3.0.1", - "@docusaurus/utils": "3.0.1", + "@docusaurus/logger": "3.1.0", + "@docusaurus/utils": "3.1.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", "tslib": "^2.6.0" @@ -2840,6 +2960,374 @@ "node": ">=12" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", + "integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz", + "integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz", + "integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz", + "integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz", + "integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz", + "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz", + "integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz", + "integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz", + "integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz", + "integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz", + "integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz", + "integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz", + "integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz", + "integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz", + "integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz", + "integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz", + "integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz", + "integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz", + "integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz", + "integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz", + "integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz", + "integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", + "integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -3940,9 +4428,9 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "20.9.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", - "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", + "version": "20.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", + "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", "dependencies": { "undici-types": "~5.26.4" } @@ -4593,30 +5081,30 @@ } }, "node_modules/algoliasearch": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.20.0.tgz", - "integrity": "sha512-y+UHEjnOItoNy0bYO+WWmLWBlPwDjKHW6mNHrPi0NkuhpQOOEbrkwQH/wgKFDLh7qlKjzoKeiRtlpewDPDG23g==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.20.0", - "@algolia/cache-common": "4.20.0", - "@algolia/cache-in-memory": "4.20.0", - "@algolia/client-account": "4.20.0", - "@algolia/client-analytics": "4.20.0", - "@algolia/client-common": "4.20.0", - "@algolia/client-personalization": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/logger-common": "4.20.0", - "@algolia/logger-console": "4.20.0", - "@algolia/requester-browser-xhr": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/requester-node-http": "4.20.0", - "@algolia/transporter": "4.20.0" + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.0.tgz", + "integrity": "sha512-gfceltjkwh7PxXwtkS8KVvdfK+TSNQAWUeNSxf4dA29qW5tf2EGwa8jkJujlT9jLm17cixMVoGNc+GJFO1Mxhg==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.22.0", + "@algolia/cache-common": "4.22.0", + "@algolia/cache-in-memory": "4.22.0", + "@algolia/client-account": "4.22.0", + "@algolia/client-analytics": "4.22.0", + "@algolia/client-common": "4.22.0", + "@algolia/client-personalization": "4.22.0", + "@algolia/client-search": "4.22.0", + "@algolia/logger-common": "4.22.0", + "@algolia/logger-console": "4.22.0", + "@algolia/requester-browser-xhr": "4.22.0", + "@algolia/requester-common": "4.22.0", + "@algolia/requester-node-http": "4.22.0", + "@algolia/transporter": "4.22.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.15.0.tgz", - "integrity": "sha512-DGUnK3TGtDQsaUE4ayF/LjSN0DGsuYThB8WBgnnDY0Wq04K6lNVruO3LfqJOgSfDiezp+Iyt8Tj4YKHi+/ivSA==", + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.16.1.tgz", + "integrity": "sha512-qxAHVjjmT7USVvrM8q6gZGaJlCK1fl4APfdAA7o8O6iXEc68G0xMNrzRkxoB/HmhhvyHnoteS/iMTiHiTcQQcg==", "dependencies": { "@algolia/events": "^4.0.1" }, @@ -6723,6 +7211,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", + "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.11", + "@esbuild/android-arm": "0.19.11", + "@esbuild/android-arm64": "0.19.11", + "@esbuild/android-x64": "0.19.11", + "@esbuild/darwin-arm64": "0.19.11", + "@esbuild/darwin-x64": "0.19.11", + "@esbuild/freebsd-arm64": "0.19.11", + "@esbuild/freebsd-x64": "0.19.11", + "@esbuild/linux-arm": "0.19.11", + "@esbuild/linux-arm64": "0.19.11", + "@esbuild/linux-ia32": "0.19.11", + "@esbuild/linux-loong64": "0.19.11", + "@esbuild/linux-mips64el": "0.19.11", + "@esbuild/linux-ppc64": "0.19.11", + "@esbuild/linux-riscv64": "0.19.11", + "@esbuild/linux-s390x": "0.19.11", + "@esbuild/linux-x64": "0.19.11", + "@esbuild/netbsd-x64": "0.19.11", + "@esbuild/openbsd-x64": "0.19.11", + "@esbuild/sunos-x64": "0.19.11", + "@esbuild/win32-arm64": "0.19.11", + "@esbuild/win32-ia32": "0.19.11", + "@esbuild/win32-x64": "0.19.11" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -10037,9 +10563,9 @@ } }, "node_modules/lucide-react": { - "version": "0.303.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.303.0.tgz", - "integrity": "sha512-B0B9T3dLEFBYPCUlnUS1mvAhW1craSbF9HO+JfBjAtpFUJ7gMIqmEwNSclikY3RiN2OnCkj/V1ReAQpaHae8Bg==", + "version": "0.306.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.306.0.tgz", + "integrity": "sha512-eShuk2PI3vxN4YN8kNPmhAsroSvPXbtaxU/UX/zrBcLLg8FeFH9MG7C2EYzYsT2rNrPVjbP7rpBz3mOviZYN3A==", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0" } @@ -14838,9 +15364,9 @@ } }, "node_modules/search-insights": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.11.0.tgz", - "integrity": "sha512-Uin2J8Bpm3xaZi9Y8QibSys6uJOFZ+REMrf42v20AA3FUDUrshKkMEP6liJbMAHCm71wO6ls4mwAf7a3gFVxLw==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.13.0.tgz", + "integrity": "sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==", "peer": true }, "node_modules/section-matter": { @@ -15947,6 +16473,46 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsx": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz", + "integrity": "sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==", + "dev": true, + "dependencies": { + "esbuild": "~0.19.10", + "get-tsconfig": "^4.7.2" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/website/package.json b/website/package.json index 16bdc4aea9..210dc25998 100644 --- a/website/package.json +++ b/website/package.json @@ -14,25 +14,28 @@ "typecheck": "tsc", "lintcheck": "prettier --check . && eslint . --ext .ts,.tsx", "lint": "prettier --write . && eslint . --fix", - "test": "npm run typecheck && npm run lintcheck && npm run clear && npm run build" + "test:unit": "npx tsx test/index.ts", + "test": "npm run typecheck && npm run lintcheck && npm run test:unit && npm run clear && npm run build" }, "dependencies": { - "@docusaurus/core": "^3.0.1", - "@docusaurus/preset-classic": "^3.0.1", + "@docusaurus/core": "^3.1.0", + "@docusaurus/preset-classic": "^3.1.0", "@easyops-cn/docusaurus-search-local": "^0.40.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.1.0", "docusaurus-plugin-sass": "^0.2.5", - "lucide-react": "^0.303.0", + "lucide-react": "^0.306.0", "prism-react-renderer": "^2.3.1", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.69.7" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.0.1", - "@docusaurus/tsconfig": "^3.0.1", - "@docusaurus/types": "^3.0.1", + "@docusaurus/eslint-plugin": "^3.1.0", + "@docusaurus/module-type-aliases": "^3.1.0", + "@docusaurus/tsconfig": "^3.1.0", + "@docusaurus/types": "^3.1.0", + "@types/node": "^20.10.6", "@typescript-eslint/eslint-plugin": "^6.17.0", "@typescript-eslint/parser": "^6.17.0", "eslint": "^8.56.0", @@ -42,6 +45,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", "prettier": "^3.1.1", + "tsx": "^4.7.0", "typescript": "^5.3.3" }, "browserslist": { diff --git a/website/src/components/ExternalCodeEmbed.tsx b/website/src/components/ExternalCodeEmbed.tsx index 95cdde1da8..f4ded461b6 100644 --- a/website/src/components/ExternalCodeEmbed.tsx +++ b/website/src/components/ExternalCodeEmbed.tsx @@ -3,15 +3,24 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; // eslint-disable-next-line import/no-unresolved import CodeBlock from '@theme/CodeBlock'; import { Loading } from '@site/src/components/Loading'; +import { + MethodType, + extractMethodContent, +} from '@site/helpers/extract-method-content'; export type ExternalCodeEmbedProps = { /** Raw URL from GitHub */ url: string; /** `js`, `ts`, `json`, etc. */ language: string; + extractMethod?: string; + methodType?: MethodType; }; /** + * Experimental + * + * * **Usage Example:** * * ```tsx @@ -33,6 +42,8 @@ export type ExternalCodeEmbedProps = { export const ExternalCodeEmbed: FC = ({ url, language, + extractMethod, + methodType, }) => { const [code, setCode] = useState(''); const [loading, setLoading] = useState(true); @@ -48,7 +59,12 @@ export const ExternalCodeEmbed: FC = ({ fetch(finalURL, { signal }) .then((response) => response.text()) .then((text) => { - setCode(text); + const extractedCode = + extractMethod && methodType + ? extractMethodContent(text, extractMethod, methodType) + : text; + + setCode(extractedCode || text); setLoading(false); setError(false); }) @@ -60,7 +76,7 @@ export const ExternalCodeEmbed: FC = ({ return () => { controller.abort(); }; - }, [finalURL]); + }, [finalURL, extractMethod, methodType]); return ( <> diff --git a/website/test/fixtures/external-code-embed/HistoryRecords.txt b/website/test/fixtures/external-code-embed/HistoryRecords.txt new file mode 100644 index 0000000000..66650e5585 --- /dev/null +++ b/website/test/fixtures/external-code-embed/HistoryRecords.txt @@ -0,0 +1,29 @@ +export type HistoryRecords = { + /** **Examples:** + * + * - `3.x` + * - `3.2.x` + * - `3.2.6` + */ + version: string; + /** + * Examples: + * + * --- + * + * - string + * ```plain + * Indicate your changes + * ``` + * + * --- + * + * - JSX + * ```tsx + * <> + * Method Name and your changes + * + * ``` + */ + changes: (string | JSX.Element)[]; +}; \ No newline at end of file diff --git a/website/test/fixtures/external-code-embed/Pool.txt b/website/test/fixtures/external-code-embed/Pool.txt new file mode 100644 index 0000000000..1c44eadbad --- /dev/null +++ b/website/test/fixtures/external-code-embed/Pool.txt @@ -0,0 +1,215 @@ +class Pool extends EventEmitter { + constructor(options) { + super(); + this.config = options.config; + this.config.connectionConfig.pool = this; + this._allConnections = new Queue(); + this._freeConnections = new Queue(); + this._connectionQueue = new Queue(); + this._closed = false; + if (this.config.maxIdle < this.config.connectionLimit) { + // create idle connection timeout automatically release job + this._removeIdleTimeoutConnections(); + } + } + + promise(promiseImpl) { + const PromisePool = require('../promise').PromisePool; + return new PromisePool(this, promiseImpl); + } + + getConnection(cb) { + if (this._closed) { + return process.nextTick(() => cb(new Error('Pool is closed.'))); + } + let connection; + if (this._freeConnections.length > 0) { + connection = this._freeConnections.pop(); + this.emit('acquire', connection); + return process.nextTick(() => cb(null, connection)); + } + if ( + this.config.connectionLimit === 0 || + this._allConnections.length < this.config.connectionLimit + ) { + connection = new PoolConnection(this, { + config: this.config.connectionConfig, + }); + this._allConnections.push(connection); + return connection.connect((err) => { + if (this._closed) { + return cb(new Error('Pool is closed.')); + } + if (err) { + return cb(err); + } + this.emit('connection', connection); + this.emit('acquire', connection); + return cb(null, connection); + }); + } + if (!this.config.waitForConnections) { + return process.nextTick(() => cb(new Error('No connections available.'))); + } + if ( + this.config.queueLimit && + this._connectionQueue.length >= this.config.queueLimit + ) { + return cb(new Error('Queue limit reached.')); + } + this.emit('enqueue'); + return this._connectionQueue.push(cb); + } + + releaseConnection(connection) { + let cb; + if (!connection._pool) { + // The connection has been removed from the pool and is no longer good. + if (this._connectionQueue.length) { + cb = this._connectionQueue.shift(); + process.nextTick(this.getConnection.bind(this, cb)); + } + } else if (this._connectionQueue.length) { + cb = this._connectionQueue.shift(); + process.nextTick(cb.bind(null, null, connection)); + } else { + this._freeConnections.push(connection); + this.emit('release', connection); + } + } + + end(cb) { + this._closed = true; + if (typeof cb !== 'function') { + cb = function (err) { + if (err) { + throw err; + } + }; + } + let calledBack = false; + let closedConnections = 0; + let connection; + const endCB = function (err) { + if (calledBack) { + return; + } + if (err || ++closedConnections >= this._allConnections.length) { + calledBack = true; + cb(err); + return; + } + }.bind(this); + if (this._allConnections.length === 0) { + endCB(); + return; + } + for (let i = 0; i < this._allConnections.length; i++) { + connection = this._allConnections.get(i); + connection._realEnd(endCB); + } + } + + query(sql, values, cb) { + const cmdQuery = Connection.createQuery( + sql, + values, + cb, + this.config.connectionConfig + ); + if (typeof cmdQuery.namedPlaceholders === 'undefined') { + cmdQuery.namedPlaceholders = + this.config.connectionConfig.namedPlaceholders; + } + this.getConnection((err, conn) => { + if (err) { + if (typeof cmdQuery.onResult === 'function') { + cmdQuery.onResult(err); + } else { + cmdQuery.emit('error', err); + } + return; + } + try { + conn.query(cmdQuery).once('end', () => { + conn.release(); + }); + } catch (e) { + conn.release(); + throw e; + } + }); + return cmdQuery; + } + + execute(sql, values, cb) { + // TODO construct execute command first here and pass it to connection.execute + // so that polymorphic arguments logic is there in one place + if (typeof values === 'function') { + cb = values; + values = []; + } + this.getConnection((err, conn) => { + if (err) { + return cb(err); + } + try { + conn.execute(sql, values, cb).once('end', () => { + conn.release(); + }); + } catch (e) { + conn.release(); + return cb(e); + } + }); + } + + _removeConnection(connection) { + // Remove connection from all connections + spliceConnection(this._allConnections, connection); + // Remove connection from free connections + spliceConnection(this._freeConnections, connection); + this.releaseConnection(connection); + } + + _removeIdleTimeoutConnections() { + if (this._removeIdleTimeoutConnectionsTimer) { + clearTimeout(this._removeIdleTimeoutConnectionsTimer); + } + + this._removeIdleTimeoutConnectionsTimer = setTimeout(() => { + try { + while ( + this._freeConnections.length > this.config.maxIdle && + Date.now() - this._freeConnections.get(0).lastActiveTime > + this.config.idleTimeout + ) { + this._freeConnections.get(0).destroy(); + } + } finally { + this._removeIdleTimeoutConnections(); + } + }, 1000); + } + + format(sql, values) { + return mysql.format( + sql, + values, + this.config.connectionConfig.stringifyObjects, + this.config.connectionConfig.timezone + ); + } + + escape(value) { + return mysql.escape( + value, + this.config.connectionConfig.stringifyObjects, + this.config.connectionConfig.timezone + ); + } + + escapeId(value) { + return mysql.escapeId(value, false); + } +} \ No newline at end of file diff --git a/website/test/fixtures/external-code-embed/QueryOptions.txt b/website/test/fixtures/external-code-embed/QueryOptions.txt new file mode 100644 index 0000000000..e12549ffce --- /dev/null +++ b/website/test/fixtures/external-code-embed/QueryOptions.txt @@ -0,0 +1,63 @@ +export interface QueryOptions { + /** + * The SQL for the query + */ + sql: string; + + /** + * The values for the query + */ + values?: any | any[] | { [param: string]: any }; + + /** + * This overrides the namedPlaceholders option set at the connection level. + */ + namedPlaceholders?: boolean; + + /** + * 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; + + /** + * This overrides the same option set at the connection level. + * + */ + rowsAsArray?: boolean; + + /** + * By specifying a function that returns a readable stream, an arbitrary stream can be sent when sending a local fs file. + */ + infileStreamFactory?: (path: string) => Readable; +} \ No newline at end of file diff --git a/website/test/fixtures/external-code-embed/handleCompressedPacket.txt b/website/test/fixtures/external-code-embed/handleCompressedPacket.txt new file mode 100644 index 0000000000..64e68b896e --- /dev/null +++ b/website/test/fixtures/external-code-embed/handleCompressedPacket.txt @@ -0,0 +1,26 @@ +function handleCompressedPacket(packet) { + // eslint-disable-next-line consistent-this, no-invalid-this + const connection = this; + const deflatedLength = packet.readInt24(); + const body = packet.readBuffer(); + + if (deflatedLength !== 0) { + connection.inflateQueue.push(task => { + zlib.inflate(body, (err, data) => { + if (err) { + connection._handleNetworkError(err); + return; + } + connection._bumpCompressedSequenceId(packet.numPackets); + connection._inflatedPacketsParser.execute(data); + task.done(); + }); + }); + } else { + connection.inflateQueue.push(task => { + connection._bumpCompressedSequenceId(packet.numPackets); + connection._inflatedPacketsParser.execute(body); + task.done(); + }); + } +} \ No newline at end of file diff --git a/website/test/fixtures/external-code-embed/handler.txt b/website/test/fixtures/external-code-embed/handler.txt new file mode 100644 index 0000000000..5b8c7aacc3 --- /dev/null +++ b/website/test/fixtures/external-code-embed/handler.txt @@ -0,0 +1,5 @@ +function handler(packet) { + //console.log(packet.length(), packet.sequenceId); + cc += packet.sequenceId; + count++; +} \ No newline at end of file diff --git a/website/test/fixtures/external-code-embed/makeSelector.txt b/website/test/fixtures/external-code-embed/makeSelector.txt new file mode 100644 index 0000000000..9efc2a86cc --- /dev/null +++ b/website/test/fixtures/external-code-embed/makeSelector.txt @@ -0,0 +1,13 @@ +const makeSelector = { + RR() { + let index = 0; + return clusterIds => clusterIds[index++ % clusterIds.length]; + }, + RANDOM() { + return clusterIds => + clusterIds[Math.floor(Math.random() * clusterIds.length)]; + }, + ORDER() { + return clusterIds => clusterIds[0]; + } +}; \ No newline at end of file diff --git a/website/test/index.ts b/website/test/index.ts new file mode 100644 index 0000000000..28d230df3a --- /dev/null +++ b/website/test/index.ts @@ -0,0 +1,16 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +const runTests = async (dir: string) => { + const testDir = path.join(__dirname, dir); + const files = fs.readdirSync(testDir); + + for (const file of files) { + if (file.endsWith('.ts')) { + await import(path.join(testDir, file)); + console.log(`✅ ${file}`); + } + } +}; + +runTests('./unit'); diff --git a/website/test/resources/external-code-embed/random-methods.txt b/website/test/resources/external-code-embed/random-methods.txt new file mode 100644 index 0000000000..ddf6fee73f --- /dev/null +++ b/website/test/resources/external-code-embed/random-methods.txt @@ -0,0 +1,365 @@ +/** + * This file is for testing purposes only. + * Please see the ExternalCodeEmbed component and extractMethodContent for more context. + */ + +import { Sequence } from './Sequence.js'; +import { OkPacket, RowDataPacket, FieldPacket } from '../packets/index.js'; +import { Readable } from 'stream'; + +export interface QueryOptions { + /** + * The SQL for the query + */ + sql: string; + + /** + * The values for the query + */ + values?: any | any[] | { [param: string]: any }; + + /** + * This overrides the namedPlaceholders option set at the connection level. + */ + namedPlaceholders?: boolean; + + /** + * 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; + + /** + * This overrides the same option set at the connection level. + * + */ + rowsAsArray?: boolean; + + /** + * By specifying a function that returns a readable stream, an arbitrary stream can be sent when sending a local fs file. + */ + infileStreamFactory?: (path: string) => Readable; +} + +class Pool extends EventEmitter { + constructor(options) { + super(); + this.config = options.config; + this.config.connectionConfig.pool = this; + this._allConnections = new Queue(); + this._freeConnections = new Queue(); + this._connectionQueue = new Queue(); + this._closed = false; + if (this.config.maxIdle < this.config.connectionLimit) { + // create idle connection timeout automatically release job + this._removeIdleTimeoutConnections(); + } + } + + promise(promiseImpl) { + const PromisePool = require('../promise').PromisePool; + return new PromisePool(this, promiseImpl); + } + + getConnection(cb) { + if (this._closed) { + return process.nextTick(() => cb(new Error('Pool is closed.'))); + } + let connection; + if (this._freeConnections.length > 0) { + connection = this._freeConnections.pop(); + this.emit('acquire', connection); + return process.nextTick(() => cb(null, connection)); + } + if ( + this.config.connectionLimit === 0 || + this._allConnections.length < this.config.connectionLimit + ) { + connection = new PoolConnection(this, { + config: this.config.connectionConfig, + }); + this._allConnections.push(connection); + return connection.connect((err) => { + if (this._closed) { + return cb(new Error('Pool is closed.')); + } + if (err) { + return cb(err); + } + this.emit('connection', connection); + this.emit('acquire', connection); + return cb(null, connection); + }); + } + if (!this.config.waitForConnections) { + return process.nextTick(() => cb(new Error('No connections available.'))); + } + if ( + this.config.queueLimit && + this._connectionQueue.length >= this.config.queueLimit + ) { + return cb(new Error('Queue limit reached.')); + } + this.emit('enqueue'); + return this._connectionQueue.push(cb); + } + + releaseConnection(connection) { + let cb; + if (!connection._pool) { + // The connection has been removed from the pool and is no longer good. + if (this._connectionQueue.length) { + cb = this._connectionQueue.shift(); + process.nextTick(this.getConnection.bind(this, cb)); + } + } else if (this._connectionQueue.length) { + cb = this._connectionQueue.shift(); + process.nextTick(cb.bind(null, null, connection)); + } else { + this._freeConnections.push(connection); + this.emit('release', connection); + } + } + + end(cb) { + this._closed = true; + if (typeof cb !== 'function') { + cb = function (err) { + if (err) { + throw err; + } + }; + } + let calledBack = false; + let closedConnections = 0; + let connection; + const endCB = function (err) { + if (calledBack) { + return; + } + if (err || ++closedConnections >= this._allConnections.length) { + calledBack = true; + cb(err); + return; + } + }.bind(this); + if (this._allConnections.length === 0) { + endCB(); + return; + } + for (let i = 0; i < this._allConnections.length; i++) { + connection = this._allConnections.get(i); + connection._realEnd(endCB); + } + } + + query(sql, values, cb) { + const cmdQuery = Connection.createQuery( + sql, + values, + cb, + this.config.connectionConfig + ); + if (typeof cmdQuery.namedPlaceholders === 'undefined') { + cmdQuery.namedPlaceholders = + this.config.connectionConfig.namedPlaceholders; + } + this.getConnection((err, conn) => { + if (err) { + if (typeof cmdQuery.onResult === 'function') { + cmdQuery.onResult(err); + } else { + cmdQuery.emit('error', err); + } + return; + } + try { + conn.query(cmdQuery).once('end', () => { + conn.release(); + }); + } catch (e) { + conn.release(); + throw e; + } + }); + return cmdQuery; + } + + execute(sql, values, cb) { + // TODO construct execute command first here and pass it to connection.execute + // so that polymorphic arguments logic is there in one place + if (typeof values === 'function') { + cb = values; + values = []; + } + this.getConnection((err, conn) => { + if (err) { + return cb(err); + } + try { + conn.execute(sql, values, cb).once('end', () => { + conn.release(); + }); + } catch (e) { + conn.release(); + return cb(e); + } + }); + } + + _removeConnection(connection) { + // Remove connection from all connections + spliceConnection(this._allConnections, connection); + // Remove connection from free connections + spliceConnection(this._freeConnections, connection); + this.releaseConnection(connection); + } + + _removeIdleTimeoutConnections() { + if (this._removeIdleTimeoutConnectionsTimer) { + clearTimeout(this._removeIdleTimeoutConnectionsTimer); + } + + this._removeIdleTimeoutConnectionsTimer = setTimeout(() => { + try { + while ( + this._freeConnections.length > this.config.maxIdle && + Date.now() - this._freeConnections.get(0).lastActiveTime > + this.config.idleTimeout + ) { + this._freeConnections.get(0).destroy(); + } + } finally { + this._removeIdleTimeoutConnections(); + } + }, 1000); + } + + format(sql, values) { + return mysql.format( + sql, + values, + this.config.connectionConfig.stringifyObjects, + this.config.connectionConfig.timezone + ); + } + + escape(value) { + return mysql.escape( + value, + this.config.connectionConfig.stringifyObjects, + this.config.connectionConfig.timezone + ); + } + + escapeId(value) { + return mysql.escapeId(value, false); + } +} + +const makeSelector = { + RR() { + let index = 0; + return clusterIds => clusterIds[index++ % clusterIds.length]; + }, + RANDOM() { + return clusterIds => + clusterIds[Math.floor(Math.random() * clusterIds.length)]; + }, + ORDER() { + return clusterIds => clusterIds[0]; + } +}; + +function handleCompressedPacket(packet) { + // eslint-disable-next-line consistent-this, no-invalid-this + const connection = this; + const deflatedLength = packet.readInt24(); + const body = packet.readBuffer(); + + if (deflatedLength !== 0) { + connection.inflateQueue.push(task => { + zlib.inflate(body, (err, data) => { + if (err) { + connection._handleNetworkError(err); + return; + } + connection._bumpCompressedSequenceId(packet.numPackets); + connection._inflatedPacketsParser.execute(data); + task.done(); + }); + }); + } else { + connection.inflateQueue.push(task => { + connection._bumpCompressedSequenceId(packet.numPackets); + connection._inflatedPacketsParser.execute(body); + task.done(); + }); + } +} + +export type HistoryRecords = { + /** **Examples:** + * + * - `3.x` + * - `3.2.x` + * - `3.2.6` + */ + version: string; + /** + * Examples: + * + * --- + * + * - string + * ```plain + * Indicate your changes + * ``` + * + * --- + * + * - JSX + * ```tsx + * <> + * Method Name and your changes + * + * ``` + */ + changes: (string | JSX.Element)[]; +}; + +function handler(packet) { + //console.log(packet.length(), packet.sequenceId); + cc += packet.sequenceId; + count++; +} diff --git a/website/test/unit/check-extensions.ts b/website/test/unit/check-extensions.ts new file mode 100644 index 0000000000..a49c50cdbf --- /dev/null +++ b/website/test/unit/check-extensions.ts @@ -0,0 +1,48 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { EOL } from 'node:os'; + +const checkExtensions = ( + directoriesToCheck: string[], + allowedExtensions: string[], + ignoreList: string[] = ['.DS_Store'] +) => { + const isIgnored = (fileName: string): boolean => { + return ( + ignoreList.includes(fileName) || + allowedExtensions.includes(path.extname(fileName)) + ); + }; + + const findInvalidFiles = (dir: string): string[] => { + return fs.readdirSync(dir, { withFileTypes: true }).flatMap((file) => { + const fullPath = path.join(dir, file.name); + + if (file.isDirectory()) return findInvalidFiles(fullPath); + if (file.isFile() && !isIgnored(file.name)) return [fullPath]; + + return []; + }); + }; + + const invalidFiles = directoriesToCheck.flatMap((dir) => + findInvalidFiles(dir) + ); + + if (invalidFiles.length > 0) { + console.log( + '❌ Invalid file types found in restricted directories:', + invalidFiles, + EOL, + ` Please ensure that files in these directories have one of the following extensions: ${allowedExtensions.join( + ', ' + )}.` + ); + process.exit(1); + } +}; + +checkExtensions(['docs', 'i18n'], ['.mdx', '.json']); +checkExtensions(['helpers', 'plugins', 'test/unit', 'test/utils'], ['.ts']); +checkExtensions(['src/components', 'src/pages'], ['.tsx']); +checkExtensions(['src/css'], ['.scss']); diff --git a/website/test/unit/external-code-embed.ts b/website/test/unit/external-code-embed.ts new file mode 100644 index 0000000000..3f801ddb37 --- /dev/null +++ b/website/test/unit/external-code-embed.ts @@ -0,0 +1,43 @@ +/** + * Fixtures generated using './test/utils/gen-expected-extract-results.ts' + */ + +import fs from 'node:fs'; +import path from 'node:path'; +import { + extractMethodContent, + MethodType, +} from '@site/helpers/extract-method-content'; + +const resource = fs.readFileSync( + path.resolve('./test/resources/external-code-embed/random-methods.txt'), + 'utf-8' +); + +const checkResult = (methodName: string, methodType: MethodType) => { + if ( + fs.readFileSync( + path.resolve(`./test/fixtures/external-code-embed/${methodName}.txt`), + 'utf-8' + ) !== extractMethodContent(resource, methodName, methodType) + ) { + console.log(`❌ ${methodName} example failed`); + process.exit(1); + } +}; + +// Valid methods +checkResult('QueryOptions', 'interface'); +checkResult('Pool', 'class'); +checkResult('makeSelector', 'const'); +checkResult('handleCompressedPacket', 'function'); +checkResult('HistoryRecords', 'type'); +checkResult('handler', 'function'); + +// Invalid method +if (resource !== extractMethodContent(resource, 'invalidMethod', 'function')) { + console.log( + `❌ Invalid method example failed. It should return the original content when it didn't find the requested method.` + ); + process.exit(1); +} diff --git a/website/test/utils/gen-expected-extract-results.ts b/website/test/utils/gen-expected-extract-results.ts new file mode 100644 index 0000000000..e51caba71a --- /dev/null +++ b/website/test/utils/gen-expected-extract-results.ts @@ -0,0 +1,45 @@ +/** + * This file is not included in the tests and can be triggered manually using the command: + * `npx tsx test/utils/gen-expected-extract-results.ts` + */ + +import fs from 'node:fs'; +import path from 'node:path'; +import { extractMethodContent } from '@site/helpers/extract-method-content'; + +const resource = fs.readFileSync( + path.resolve('./test/resources/external-code-embed/random-methods.txt'), + 'utf-8' +); + +fs.writeFileSync( + path.resolve('./test/fixtures/external-code-embed/QueryOptions.txt'), + extractMethodContent(resource, 'QueryOptions', 'interface') +); + +fs.writeFileSync( + path.resolve('./test/fixtures/external-code-embed/Pool.txt'), + extractMethodContent(resource, 'Pool', 'class') +); + +fs.writeFileSync( + path.resolve('./test/fixtures/external-code-embed/makeSelector.txt'), + extractMethodContent(resource, 'makeSelector', 'const') +); + +fs.writeFileSync( + path.resolve( + './test/fixtures/external-code-embed/handleCompressedPacket.txt' + ), + extractMethodContent(resource, 'handleCompressedPacket', 'function') +); + +fs.writeFileSync( + path.resolve('./test/fixtures/external-code-embed/HistoryRecords.txt'), + extractMethodContent(resource, 'HistoryRecords', 'type') +); + +fs.writeFileSync( + path.resolve('./test/fixtures/external-code-embed/handler.txt'), + extractMethodContent(resource, 'handler', 'function') +);