diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 04e8074b9..3303e9afb 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. #------------------------------------------------------------------------------------------------------------- -FROM node:20 +FROM node:22 # Avoid warnings by switching to noninteractive ENV DEBIAN_FRONTEND=noninteractive @@ -35,7 +35,7 @@ RUN apt-get update \ && echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update \ && apt-get -y install --no-install-recommends yarn tmux locales postgresql \ - && apt-get install libpq-dev g++ make \ + && apt-get install libpq-dev python3 g++ make \ # # Install eslint globally && npm install -g eslint \ diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 11e652008..83e302207 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -3,7 +3,6 @@ # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. #------------------------------------------------------------------------------------------------------------- -version: '3.9' services: web: # Uncomment the next line to use a non-root user for all processes. You can also @@ -39,7 +38,7 @@ services: - db:db db: - image: postgres:14-alpine + image: postgres:14 restart: unless-stopped ports: - 5432:5432 diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 050c39538..000000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -/packages/*/dist/ diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index b1999b544..000000000 --- a/.eslintrc +++ /dev/null @@ -1,35 +0,0 @@ -{ - "plugins": ["@typescript-eslint", "prettier"], - "parser": "@typescript-eslint/parser", - "extends": ["eslint:recommended", "plugin:prettier/recommended", "prettier"], - "ignorePatterns": ["node_modules", "coverage", "packages/pg-protocol/dist/**/*", "packages/pg-query-stream/dist/**/*"], - "parserOptions": { - "ecmaVersion": 2017, - "sourceType": "module" - }, - "env": { - "node": true, - "es6": true, - "mocha": true - }, - "rules": { - "@typescript-eslint/no-unused-vars": ["error", { - "args": "none", - "varsIgnorePattern": "^_$" - }], - "no-unused-vars": ["error", { - "args": "none", - "varsIgnorePattern": "^_$" - }], - "no-var": "error", - "prefer-const": "error" - }, - "overrides": [ - { - "files": ["*.ts", "*.mts", "*.cts", "*.tsx"], - "rules": { - "no-undef": "off" - } - } - ] -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d90e474c..551388fcc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - name: Setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 22 cache: yarn - run: yarn install --frozen-lockfile - run: yarn lint @@ -25,28 +25,39 @@ jobs: needs: lint services: postgres: - image: ghcr.io/railwayapp-templates/postgres-ssl + image: ghcr.io/railwayapp-templates/postgres-ssl:${{ matrix.postgres }} env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_HOST_AUTH_METHOD: 'md5' POSTGRES_DB: ci_db_test + # PostgreSQL 18's official image defaults PGDATA to a versioned + # subdirectory (/var/lib/postgresql/18/docker), but the + # railwayapp-templates/postgres-ssl entrypoint requires PGDATA to + # start with /var/lib/postgresql/data so we pin it explicitly. This is + # also the default for the older images, so it is a no-op there. + PGDATA: /var/lib/postgresql/data ports: - 5432:5432 options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: fail-fast: false matrix: - node: - - '16' - - '18' - - '20' - - '22' - - '24' - - '25' - os: - - ubuntu-latest - name: Node.js ${{ matrix.node }} + include: + # Historical Node.js versions tested against a single PostgreSQL version + - { node: '16', postgres: &stable_postgres '18' } + - { node: '18', postgres: *stable_postgres } + - { node: '20', postgres: *stable_postgres } + - { node: '22', postgres: *stable_postgres } + - { node: '24', postgres: *stable_postgres } + # Latest Node.js version tested against multiple PostgreSQL versions + - { node: &latest_node '26', postgres: '13' } + - { node: *latest_node, postgres: '14' } + - { node: *latest_node, postgres: '15' } + - { node: *latest_node, postgres: '16' } + - { node: *latest_node, postgres: '17' } + - { node: *latest_node, postgres: '18' } + name: Node.js ${{ matrix.node }} x PostgreSQL ${{ matrix.postgres }} runs-on: ubuntu-latest env: PGUSER: postgres @@ -56,6 +67,13 @@ jobs: PGTESTNOSSL: 'true' SCRAM_TEST_PGUSER: scram_test SCRAM_TEST_PGPASSWORD: test4scram + SCRAM_TEST_PGUSER_UNICODE: scram_unicode_test + # Raw form of a password whose NFKC normalization differs from itself. + # U+2168 (ROMAN NUMERAL IX) decomposes to ASCII "IX" under NFKC; the + # server stores the verifier from the SASLprep-normalized form, so the + # client must apply SASLprep too. This is the regression check for the + # RFC 4013 fix in packages/pg/lib/crypto/sasl.js. + SCRAM_TEST_PGPASSWORD_UNICODE: "IX-\u2168" steps: - name: Show OS run: | @@ -63,7 +81,8 @@ jobs: - run: | psql \ -c "SET password_encryption = 'scram-sha-256'" \ - -c "CREATE ROLE scram_test LOGIN PASSWORD 'test4scram'" + -c "CREATE ROLE scram_test LOGIN PASSWORD 'test4scram'" \ + -c "CREATE ROLE scram_unicode_test LOGIN PASSWORD U&'IX-\2168'" - uses: actions/checkout@v4 with: persist-credentials: false diff --git a/.gitignore b/.gitignore index 8e242c10d..c6d5700ae 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ dist /.eslintcache .vscode/ manually-test-on-heroku.js +tsconfig.tsbuildinfo diff --git a/CHANGELOG.md b/CHANGELOG.md index b1ee4a6c5..f8158747e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,30 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +## pg@8.23.0 + +- Add support for query [`pipelineing`](https://github.com/brianc/node-postgres/pull/3652). + +## pg@8.22.0 + +- Add support for [sslnegotiation=direct](https://github.com/brianc/node-postgres/pull/3688) for PostgreSQL 17+. + +## pg@8.21.0 + +- Handle [SASL SCRAM](https://github.com/brianc/node-postgres/pull/3521) server error responses properly. +- Add support for [node@26](https://github.com/brianc/node-postgres/pull/3667). +- Add `scramMaxIterations` [config option](https://github.com/brianc/node-postgres/pull/3677). +- Add `client.getTransactionStatus()` [method](https://github.com/brianc/node-postgres/pull/3645). + +## pg@8.20.0 + +- Add [onConnect](https://github.com/brianc/node-postgres/pull/3620) callback to pg.Pool constructor options allowing for async initialization of newly created & connected pooled clients. + +## pg@8.19.0 + +- [Deprecate interal query queue](https://github.com/brianc/node-postgres/pull/3603). +- Pass connection parameters [to password callback](https://github.com/brianc/node-postgres/pull/3602). + ## pg@8.18.0 - [Return the client instance](https://github.com/brianc/node-postgres/pull/3564) as the result of calling `connect` (previously it was `void`). @@ -22,7 +46,7 @@ We do not include break-fix version release in this file. ## pg@8.14.0 -- Add support from SCRAM-SAH-256-PLUS i.e. [channel binding](https://github.com/brianc/node-postgres/pull/3356). +- Add support for SCRAM-SHA-256-PLUS, i.e. [channel binding](https://github.com/brianc/node-postgres/pull/3356). ## pg@8.13.0 diff --git a/README.md b/README.md index a680ff7b3..ecd94e792 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ NPM version NPM downloads -Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. +Non-blocking PostgreSQL client for Node.js (and bun, deno, cloudflare, etc...). Pure JavaScript and optional native libpq bindings. ## Monorepo @@ -34,6 +34,7 @@ The source repo for the documentation is available for contribution [here](https ### Features +- [Fastest PostgreSQL client for Node.js](https://github.com/nigrosimone/postgres-benchmarks) - Pure JavaScript client and native libpq bindings share _the same API_ - Connection pooling - Extensible JS ↔ PostgreSQL data-type coercion @@ -58,7 +59,7 @@ When you open an issue please provide: - version of Postgres - smallest possible snippet of code to reproduce the problem -You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. +You can also follow me [@brianc](https://bsky.app/profile/brianc.bsky.social) on bluesky if that's your thing for updates on node-postgres with nearly zero non node-postgres content. My old twitter/x account is no longer used. ## Sponsorship :two_hearts: @@ -70,7 +71,7 @@ If you or your company are benefiting from node-postgres and would like to help Special thanks to [medplum](https://medplum.com) for their generous and thoughtful support of node-postgres! -![medplum](https://raw.githubusercontent.com/medplum/medplum-logo/refs/heads/main/medplum-logo.png) +Medplum logo ## Contributing @@ -87,11 +88,11 @@ If your change involves breaking backwards compatibility please please point tha ### Setting up for local development 1. Clone the repo -2. Ensure you have installed libpq-dev in your system. +2. Ensure you have installed libpq-dev in your system (the native bindings are built in the test process) 3. From your workspace root run `yarn` and then `yarn lerna bootstrap` -4. Ensure you have a PostgreSQL instance running with SSL enabled and an empty database for tests -5. Ensure you have the proper environment variables configured for connecting to the instance -6. Run `yarn test` to run all the tests +4. Ensure you have a PostgreSQL instance running with SSL enabled and an empty database for tests. _note: you can skip the tests requring SSL by setting the environment variable `PGTESTNOSSL=1` if you're not changing any SSL related code_. +5. Ensure you have the proper environment variables configured for connecting to your postgres instance. Using the standard `PG*` environment variables like `PGUSER` and `PGPASSWORD` etc... +6. Run `yarn test` to run all the tests. ## Troubleshooting and FAQ diff --git a/SPONSORS.md b/SPONSORS.md index dfcbbd0ab..b482f3678 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -20,6 +20,7 @@ node-postgres is made possible by the helpful contributors from the community as - [loveland](https://github.com/loveland) - [gajus](https://github.com/gajus) - [thirdiron](https://github.com/thirdiron) +- [kiwicopple](https://github.com/kiwicopple) # Supporters diff --git a/docs/components/alert.tsx b/docs/components/alert.tsx index 752b49eab..9a3ed7359 100644 --- a/docs/components/alert.tsx +++ b/docs/components/alert.tsx @@ -1,4 +1,4 @@ -import { Callout } from 'nextra-theme-docs' +import { Callout } from 'nextra/components' export const Alert = ({ children }) => { return ( diff --git a/docs/components/info.tsx b/docs/components/info.tsx index 9cae4b890..79f11a7d6 100644 --- a/docs/components/info.tsx +++ b/docs/components/info.tsx @@ -1,4 +1,4 @@ -import { Callout } from 'nextra-theme-docs' +import { Callout } from 'nextra/components' export const Info = ({ children }) => { return {children} diff --git a/docs/next.config.js b/docs/next.config.js index 45a998c7c..57793f96c 100644 --- a/docs/next.config.js +++ b/docs/next.config.js @@ -1,8 +1,11 @@ -// next.config.js -const withNextra = require('nextra')({ +import nextra from 'nextra' + +const withNextra = nextra({ theme: 'nextra-theme-docs', themeConfig: './theme.config.js', - // optional: add `unstable_staticImage: true` to enable Nextra's auto image import }) -module.exports = withNextra() +export default withNextra({ + output: 'export', + images: { unoptimized: true }, +}) diff --git a/docs/package.json b/docs/package.json index dec5cceb2..a3bdb4f9f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,18 +3,20 @@ "version": "1.0.0", "description": "", "main": "next.config.js", + "type": "module", "scripts": { - "start": "next dev", - "build": "next build && next export" + "dev": "next dev", + "build": "next build" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { - "next": "^12.3.1", - "nextra": "2.0.0-beta.29", - "nextra-theme-docs": "2.0.0-beta.29", - "react": "^17.0.1", - "react-dom": "^17.0.1" + "next": "^13.5.11", + "nextra": "^3.3.1", + "nextra-theme-docs": "^3.3.1", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "typescript": "^5.0.2" } } diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js new file mode 100644 index 000000000..adf56009b --- /dev/null +++ b/docs/pages/_meta.js @@ -0,0 +1,5 @@ +export default { + index: 'Welcome', + announcements: 'Announcements', + apis: 'API', +} diff --git a/docs/pages/_meta.json b/docs/pages/_meta.json deleted file mode 100644 index dd241d886..000000000 --- a/docs/pages/_meta.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "index": "Welcome", - "announcements": "Announcements", - "apis": "API" -} diff --git a/docs/pages/apis/_meta.js b/docs/pages/apis/_meta.js new file mode 100644 index 000000000..94b8802ed --- /dev/null +++ b/docs/pages/apis/_meta.js @@ -0,0 +1,8 @@ +export default { + client: 'pg.Client', + pool: 'pg.Pool', + result: 'pg.Result', + types: 'pg.Types', + cursor: 'Cursor', + utilities: 'Utilities', +} diff --git a/docs/pages/apis/_meta.json b/docs/pages/apis/_meta.json deleted file mode 100644 index 67da94d93..000000000 --- a/docs/pages/apis/_meta.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "client": "pg.Client", - "pool": "pg.Pool", - "result": "pg.Result", - "types": "pg.Types", - "cursor": "Cursor", - "utilities": "Utilities" -} diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index f68542672..973b1a832 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -23,11 +23,14 @@ type Config = { lock_timeout?: number, // number of milliseconds a query is allowed to be en lock state before it's cancelled due to lock timeout application_name?: string, // The name of the application that created this Client instance connectionTimeoutMillis?: number, // number of milliseconds to wait for connection, default is no timeout - keepAliveInitialDelayMillis?: number, // set the initial delay before the first keepalive probe is sent on an idle socket + keepAlive?: boolean, // if true, enable keepalive on the `net.Socket` + keepAliveInitialDelayMillis?: number, // number of milliseconds between last data packet received and first keepalive probe, default is 0 (keep existing value); + // no effect unless `keepAlive` is true idle_in_transaction_session_timeout?: number, // number of milliseconds before terminating any session with an open idle transaction, default is no timeout client_encoding?: string, // specifies the character set encoding that the database uses for sending data to the client fallback_application_name?: string, // provide an application name to use if application_name is not set - options?: string // command-line options to be sent to the server + options?: string, // command-line options to be sent to the server + pipeline?: boolean // when true, enables query pipelining. See /features/pipelining for details. Default false. } ``` @@ -54,6 +57,17 @@ const client = new Client() await client.connect() ``` +## client.pipeline + +`client.pipeline: boolean` (read-only) + +Whether this client has pipelining enabled. Set via the `pipeline` config option to the `Client` constructor. Defaults to `false`. See [Pipelining](/features/pipelining) for details and examples. + +```js +const client = new Client({ pipeline: true }) +await client.connect() +``` + ## client.query ### QueryConfig @@ -173,6 +187,61 @@ await client.end() console.log('client has disconnected') ``` +## client.getTransactionStatus + +`client.getTransactionStatus() => string | null` + +Returns the current transaction status of the client connection. This can be useful for debugging transaction state issues or implementing custom transaction management logic. + +**Return values:** + +- `'I'` - Idle (not in a transaction) +- `'T'` - Transaction active (BEGIN has been issued) +- `'E'` - Error (transaction aborted, requires ROLLBACK) +- `null` - Initial state (before first query) + +The transaction status is updated after each query completes based on the PostgreSQL backend's `ReadyForQuery` message. + +**Example: Checking transaction state** + +```js +import { Client } from 'pg' +const client = new Client() +await client.connect() + +await client.query('BEGIN') +console.log(client.getTransactionStatus()) // 'T' - in transaction + +await client.query('SELECT * FROM users') +console.log(client.getTransactionStatus()) // 'T' - still in transaction + +await client.query('COMMIT') +console.log(client.getTransactionStatus()) // 'I' - idle + +await client.end() +``` + +**Example: Handling transaction errors** + +```js +import { Client } from 'pg' +const client = new Client() +await client.connect() + +await client.query('BEGIN') +try { + await client.query('INVALID SQL') +} catch (err) { + console.log(client.getTransactionStatus()) // 'E' - error state + + // Must rollback to recover + await client.query('ROLLBACK') + console.log(client.getTransactionStatus()) // 'I' - idle again +} + +await client.end() +``` + ## events ### error diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx index fbe0279e1..3627dd1c5 100644 --- a/docs/pages/apis/pool.mdx +++ b/docs/pages/apis/pool.mdx @@ -16,28 +16,28 @@ The pool is initially created empty and will create new clients lazily as they a ```ts type Config = { - // all valid client config options are also valid here - // in addition here are the pool specific configuration parameters: + // All valid client config options are also valid here. + // In addition here are the pool specific configuration parameters: - // number of milliseconds to wait before timing out when connecting a new client - // by default this is 0 which means no timeout + // Number of milliseconds to wait before timing out when connecting a new client. + // By default this is 0 which means no timeout. connectionTimeoutMillis?: number - // number of milliseconds a client must sit idle in the pool and not be checked out - // before it is disconnected from the backend and discarded - // default is 10000 (10 seconds) - set to 0 to disable auto-disconnection of idle clients + // Number of milliseconds a client must sit idle in the pool and not be checked out + // before it is disconnected from the backend and discarded. + // Default is 10000 (10 seconds) - set to 0 to disable auto-disconnection of idle clients. idleTimeoutMillis?: number - // maximum number of clients the pool should contain - // by default this is set to 10. There is some nuance to setting the maximum size of your pool. - // see https://node-postgres.com/guides/pool-sizing for more information + // Maximum number of clients the pool should contain. + // By default this is set to 10. There is some nuance to setting the maximum size of your pool. + // See https://node-postgres.com/guides/pool-sizing for more information. max?: number - // minimum number of clients the pool should hold on to and _not_ destroy with the idleTimeoutMillis - // this can be useful if you get very bursty traffic and want to keep a few clients around. - // note: current the pool will not automatically create and connect new clients up to the min, it will + // Minimum number of clients the pool should hold on to and _not_ destroy with the idleTimeoutMillis. + // This can be useful if you get very bursty traffic and want to keep a few clients around. + // Note: currently the pool will not automatically create and connect new clients up to the min, it will // only not evict and close clients except those which exceed the min count. - // the default is 0 which disables this behavior. + // The default is 0 which disables this behavior. min?: number // Default behavior is the pool will keep clients open & connected to the backend @@ -47,15 +47,33 @@ type Config = { // // Setting `allowExitOnIdle: true` in the config will allow the node event loop to exit // as soon as all clients in the pool are idle, even if their socket is still open - // to the postgres server. This can be handy in scripts & tests + // to the postgres server. This can be handy in scripts & tests // where you don't want to wait for your clients to go idle before your process exits. allowExitOnIdle?: boolean + // Number of times a client can be checked out from the pool before it is + // disconnected and a new client is created in its place. + // The default is Infinity which means a client will never be automatically destroyed + // outside of other lifecycle events like manually removing it, it timing out due to idleness, etc. + maxUses?: number + // Sets a max overall life for the connection. // A value of 60 would evict connections that have been around for over 60 seconds, // regardless of whether they are idle. It's useful to force rotation of connection pools through - // middleware so that you can rotate the underlying servers. The default is disabled (value of zero) + // middleware so that you can rotate the underlying servers. The default is disabled (value of zero). maxLifetimeSeconds?: number + + // Called once when a new client is created, before it is made available to the pool. + // The client is fully connected and queryable at this point. + // Can be a regular function or an async function. + // If the function throws or returns a promise that rejects, the client is destroyed + // and the error is returned to the caller requesting the connection. + onConnect?: (client: Client) => void | Promise + + // When set to true, enables query pipelining on every client the pool creates. + // Pipelined clients send queries to the server without waiting for previous responses. + // Default is false. See /features/pipelining for details. + pipeline?: boolean } ``` @@ -70,7 +88,19 @@ const pool = new Pool({ max: 20, idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, - maxLifetimeSeconds: 60 + maxLifetimeSeconds: 60, +}) +``` + +example using `onConnect` to run setup commands on each new client: + +```js +import { Pool } from 'pg' + +const pool = new Pool({ + onConnect: async (client) => { + await client.query('SET search_path TO my_schema') + }, }) ``` @@ -207,14 +237,11 @@ The number of queued requests waiting on a client when all clients are checked o `pool.on('connect', (client: Client) => void) => void` -Whenever the pool establishes a new client connection to the PostgreSQL backend it will emit the `connect` event with the newly connected client. This presents an opportunity for you to run setup commands on a client. +Whenever the pool establishes a new client connection to the PostgreSQL backend it will emit the `connect` event with the newly connected client. -```js -const pool = new Pool() -pool.on('connect', (client) => { - client.query('SET DATESTYLE = iso, mdy') -}) -``` + + The event listener does not wait for promises or async functions. If you want to run setup commands on each new client, use the `onConnect` option. (See documentation above.) + ### acquire diff --git a/docs/pages/features/_meta.js b/docs/pages/features/_meta.js new file mode 100644 index 000000000..7ddd35a5c --- /dev/null +++ b/docs/pages/features/_meta.js @@ -0,0 +1,12 @@ +export default { + connecting: 'Connecting', + queries: 'Queries', + pipelining: 'Pipelining', + pooling: 'Pooling', + transactions: 'Transactions', + types: 'Data Types', + ssl: 'SSL', + native: 'Native', + esm: 'ESM', + callbacks: 'Callbacks', +} diff --git a/docs/pages/features/_meta.json b/docs/pages/features/_meta.json deleted file mode 100644 index 1c7980490..000000000 --- a/docs/pages/features/_meta.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "connecting": "Connecting", - "queries": "Queries", - "pooling": "Pooling", - "transactions": "Transactions", - "types": "Data Types", - "ssl": "SSL", - "native": "Native", - "esm": "ESM", - "callbacks": "Callbacks" -} diff --git a/docs/pages/features/pipelining.mdx b/docs/pages/features/pipelining.mdx new file mode 100644 index 000000000..7943aa490 --- /dev/null +++ b/docs/pages/features/pipelining.mdx @@ -0,0 +1,132 @@ +--- +title: Pipelining +--- + +import { Alert } from '/components/alert.tsx' + +## What is pipelining? + +By default node-postgres waits for each query to complete before sending the next one. This means every query pays a full network round-trip of latency. **Query pipelining** sends multiple queries to the server without waiting for responses, and the server processes them in order. Each query still gets its own result (or error), but you avoid the idle time between them. + +``` +sequential (default) pipelined +───────────────────── ───────────────────── + client ──Parse──▶ server client ──Parse──▶ server + client ◀──Ready── server ──Parse──▶ + client ──Parse──▶ server ──Parse──▶ + client ◀──Ready── server client ◀──Ready── server + client ──Parse──▶ server client ◀──Ready── server + client ◀──Ready── server client ◀──Ready── server +``` + +In benchmarks, pipelining typically delivers **2-3x throughput** for batches of simple queries on a local connection, with larger gains over higher-latency links. + +## Enabling pipelining + +Pipelining is opt-in. Pass `pipeline: true` to the `Client` constructor: + +```js +import { Client } from 'pg' + +const client = new Client({ pipeline: true }) +await client.connect() + +const [r1, r2, r3] = await Promise.all([ + client.query('SELECT 1 AS num'), + client.query('SELECT 2 AS num'), + client.query('SELECT 3 AS num'), +]) + +console.log(r1.rows[0].num, r2.rows[0].num, r3.rows[0].num) // 1 2 3 + +await client.end() +``` + +All query types work with pipelining: plain text, parameterized, and named prepared statements. + +## Pipelining with a pool + +Pass `pipeline: true` in the pool config to enable it on every client the pool creates: + +```js +import { Pool } from 'pg' + +const pool = new Pool({ pipeline: true }) + +const client = await pool.connect() +// client.pipeline is already true + +const [users, orders] = await Promise.all([ + client.query('SELECT * FROM users WHERE id = $1', [1]), + client.query('SELECT * FROM orders WHERE user_id = $1', [1]), +]) + +client.release() +``` + + +
+ pool.query() checks out a client for a single query and releases it immediately, so pipelining has no effect there. Use pool.connect() to check out a client and send multiple queries on it. +
+
+ +## Error isolation + +Each pipelined query gets its own error boundary. A failing query in the middle of a batch does not break the other queries: + +```js +const results = await Promise.allSettled([ + client.query('SELECT 1 AS num'), + client.query('SELECT INVALID SYNTAX'), + client.query('SELECT 3 AS num'), +]) + +console.log(results[0].status) // 'fulfilled' +console.log(results[1].status) // 'rejected' +console.log(results[2].status) // 'fulfilled' +``` + +This works because node-postgres sends a `Sync` message after each query, which is how PostgreSQL delimits error boundaries in the extended query protocol. + +## Named prepared statements + +Named prepared statements work with pipelining. When two pipelined queries share the same statement name, node-postgres sends `Parse` only once and reuses the prepared statement for subsequent queries: + +```js +const queries = Array.from({ length: 100 }, (_, i) => ({ + name: 'get-user', + text: 'SELECT * FROM users WHERE id = $1', + values: [i], +})) + +const results = await Promise.all(queries.map(q => client.query(q))) +``` + +## Graceful shutdown + +Calling `client.end()` while pipelined queries are in flight will wait for all of them to complete before closing the connection: + +```js +const client = new Client({ pipeline: true }) +await client.connect() + +const p1 = client.query('SELECT 1') +const p2 = client.query('SELECT 2') +const endPromise = client.end() + +// Both queries will resolve normally +const [r1, r2] = await Promise.all([p1, p2]) +await endPromise +``` + +## When to use pipelining + +Pipelining is most useful when you have multiple **independent** queries that don't depend on each other's results. Common use cases: + +- Fetching data from multiple tables in parallel for a page load +- Inserting or updating multiple rows simultaneously +- Running a batch of analytics queries + +
+ Do not use pipelining inside a transaction if you need to read the result of one query before issuing the next. Pipelined queries are all sent before any responses arrive, so you cannot branch on intermediate results. For dependent queries within a transaction, use sequential await calls instead. +
diff --git a/docs/pages/features/queries.mdx b/docs/pages/features/queries.mdx index 39bcfbe1d..63ecdde1e 100644 --- a/docs/pages/features/queries.mdx +++ b/docs/pages/features/queries.mdx @@ -26,7 +26,7 @@ console.log(res.rows[0]) // { name: 'brianc', email: 'brian.m.carlson@gmail.com' } ``` -
+
PostgreSQL does not support parameters for identifiers. If you need to have dynamic database, schema, table, or column names (e.g. in DDL statements) use [pg-format](https://www.npmjs.com/package/pg-format) package for handling escaping these values to ensure you do not have SQL injection!
@@ -99,8 +99,8 @@ console.log(res.rows[0]) In the above example the first time the client sees a query with the name `'fetch-user'` it will send a 'parse' request to the PostgreSQL server & execute the query as normal. The second time, it will skip the 'parse' request and send the _name_ of the query to the PostgreSQL server. -
-
+
+
Be careful not to fall into the trap of premature optimization. Most of your queries will likely not benefit much, if at all, from using prepared statements. This is a somewhat "power user" feature of PostgreSQL that is best used when you know how to use it - namely with very complex queries with lots of joins and advanced operations like union and switch statements. I rarely use this feature in my own apps unless writing complex aggregate queries for reports and I know the reports are going to be executed very frequently.
diff --git a/docs/pages/features/ssl.mdx b/docs/pages/features/ssl.mdx index 2c5e7bd9e..6a29ed739 100644 --- a/docs/pages/features/ssl.mdx +++ b/docs/pages/features/ssl.mdx @@ -15,10 +15,9 @@ const config = { host: 'host-or-ip', // this object will be passed to the TLSSocket constructor ssl: { - rejectUnauthorized: false, - ca: fs.readFileSync('/path/to/server-certificates/root.crt').toString(), - key: fs.readFileSync('/path/to/client-key/postgresql.key').toString(), - cert: fs.readFileSync('/path/to/client-certificates/postgresql.crt').toString(), + ca: fs.readFileSync('/path/to/server-certificates/root.crt'), + key: fs.readFileSync('/path/to/client-key/postgresql.key'), + cert: fs.readFileSync('/path/to/client-certificates/postgresql.crt'), }, } @@ -45,12 +44,36 @@ const config = { connectionString: 'postgres://user:password@host:port/db?sslmode=require', // Beware! The ssl object is overwritten when parsing the connectionString ssl: { - rejectUnauthorized: false, - ca: fs.readFileSync('/path/to/server-certificates/root.crt').toString(), + ca: fs.readFileSync('/path/to/server-certificates/root.crt'), }, } ``` +## Direct SSL negotiation + +By default node-postgres uses the traditional PostgreSQL SSL negotiation: it sends an `SSLRequest` packet, waits for the server to acknowledge it, and only then starts the TLS handshake. PostgreSQL 17 and newer also support _direct_ SSL negotiation, where the TLS handshake begins immediately on connect (similar to HTTPS), saving one network round-trip. + +To use direct negotiation, set `sslnegotiation: 'direct'`. SSL must be enabled, and the server must be PostgreSQL 17+ configured to accept direct SSL connections. + +```js +const config = { + database: 'database-name', + host: 'host-or-ip', + ssl: { rejectUnauthorized: false }, + sslnegotiation: 'direct', +} +``` + +It can also be supplied via a connection string. When `sslnegotiation=direct` is present, SSL is enabled automatically if not otherwise configured: + +```js +const config = { + connectionString: 'postgres://user:password@host:port/db?sslmode=require&sslnegotiation=direct', +} +``` + +Direct negotiation requests the `postgresql` ALPN protocol during the TLS handshake, as required by the server. The default value is `'postgres'`, which preserves the traditional `SSLRequest` behavior. You can also set the `PGSSLNEGOTIATION` environment variable. + ## Channel binding If the PostgreSQL server offers SCRAM-SHA-256-PLUS (i.e. channel binding) for TLS/SSL connections, you can enable this as follows: diff --git a/docs/pages/guides/_meta.js b/docs/pages/guides/_meta.js new file mode 100644 index 000000000..2f13073d5 --- /dev/null +++ b/docs/pages/guides/_meta.js @@ -0,0 +1,6 @@ +export default { + 'project-structure': 'Suggested Code Structure', + 'async-express': 'Express with Async/Await', + 'pool-sizing': 'Pool Sizing', + upgrading: 'Upgrading', +} diff --git a/docs/pages/guides/_meta.json b/docs/pages/guides/_meta.json deleted file mode 100644 index 777acb4e2..000000000 --- a/docs/pages/guides/_meta.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "project-structure": "Suggested Code Structure", - "async-express": "Express with Async/Await", - "pool-sizing": "Pool Sizing", - "upgrading": "Upgrading" -} diff --git a/docs/pages/guides/pool-sizing.md b/docs/pages/guides/pool-sizing.md index 5c7ddaad8..430e69190 100644 --- a/docs/pages/guides/pool-sizing.md +++ b/docs/pages/guides/pool-sizing.md @@ -16,6 +16,14 @@ In this situation, I'd probably set the `max` to 20 or 25. This lets you have pl If the number of instances of your services which connect to your database is more dynamic and based on things like load, auto-scaling containers, or running in cloud-functions, you need to be a bit more thoughtful about what your max might be. Often in these environments, there will be another database pooling proxy in front of the database like pg-bouncer or the RDS-proxy, etc. I'm not sure how all these function exactly, and they all have some trade-offs, but let's assume you're not using a proxy. Then I'd be pretty cautious about how large you set any individual pool. If you're running an application under pretty serious load where you need dynamic scaling or lots of lambdas spinning up and sending queries, your queries are likely fast and you should be fine setting the `max` to a low value like 10 -- or just leave it alone, since `10` is the default. +### Vercel + +If you're running on Vercel with [fluid compute](https://vercel.com/kb/guide/efficiently-manage-database-connection-pools-with-fluid-compute), your serverless functions can handle multiple requests concurrently and stick around between invocations. In this case, you can treat it similarly to a traditional long-lived process and use a default-ish pool size of `10`. The pool will stay warm across requests and you'll get the benefits of connection reuse. You'll probably need to put pgBouncer (or some kind of pooler like what is offered with Supabase, RDS, GCP, etc.) in front of your database, as Vercel worker count can grow quite a bit larger than the number of reasonable max connections Postgres can handle. + +### Cloudflare workers + +In a fully stateless serverless environment like Cloudflare Workers where your worker is killed, suspended, moved to a new compute node, or shut down at the end of every request, you'll still probably be okay with a pool size `max` of `10`, though you can lower it if you start hitting connection exhaustion limits on your pooler. In Cloudflare the pooler is Hyperdrive, and in my experience it works fantastically with their workers setup. Make sure at the end of your serverless handler, after everything is done, you close and dispose of the pool by calling `pool.end()`. Setting the pool to a size larger than 1 is still recommended, as things like tRPC and other server-side routing & request batching code could result in multiple independent queries executing at the same time. With a pool size of `1` you are turning what is "a few things at once" into all things waiting in line one after another on the one available client in the pool. + ## pg-bouncer, RDS-proxy, etc. I'm not sure of all the pooling services for Postgres. I haven't used any myself. Throughout the years of working on `pg`, I've addressed issues caused by various proxies behaving differently than an actual Postgres backend. There are also gotchas with things like transactions. On the other hand, plenty of people run these with much success. In this situation, I would just recommend using some small but reasonable `max` value like the default value of `10` as it can still be helpful to keep a few TCP sockets from your services to the Postgres proxy open. @@ -23,3 +31,7 @@ I'm not sure of all the pooling services for Postgres. I haven't used any myself ## Conclusion, tl;dr It's a bit of a complicated topic and doesn't have much impact on things until you need to start scaling. At that point, your number of connections _still_ probably won't be your scaling bottleneck. It's worth thinking about a bit, but mostly I'd just leave the pool size to the default of `10` until you run into troubles: hopefully you never do! + +## Need help? + +In my career, this has been the most error-prone thing related to running Postgres & Node, particularly with the differences in various serverless providers (Cloudflare, Vercel, Lambda, etc.) versus more traditional hosting. If you have any questions or need help, please don't hesitate to email me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) or reach out on GitHub. diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index ff27662e6..d0ab0edc6 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -5,8 +5,16 @@ slug: / import { Logo } from '/components/logo.tsx' +## Introduction + node-postgres is a collection of node.js modules for interfacing with your PostgreSQL database. It has support for callbacks, promises, async/await, connection pooling, prepared statements, cursors, streaming results, C/C++ bindings, rich type parsing, and more! Just like PostgreSQL itself there are a lot of features: this documentation aims to get you up and running quickly and in the right direction. It also tries to provide guides for more advanced & edge-case topics allowing you to tap into the full power of PostgreSQL from node.js. +## Compatibility + +node-postgres supports every version of the PostgreSQL database from 8.x to the most recent version of PostgreSQL. + +node-postgres supports all current and LTS versions of node as well as bun, deno, and cloudflare workers. + ## Install ```bash @@ -60,12 +68,12 @@ import { Client } from 'pg' const client = await new Client().connect() try { - const res = await client.query('SELECT $1::text as message', ['Hello world!']) - console.log(res.rows[0].message) // Hello world! + const res = await client.query('SELECT $1::text as message', ['Hello world!']) + console.log(res.rows[0].message) // Hello world! } catch (err) { - console.error(err); + console.error(err) } finally { - await client.end() + await client.end() } ``` diff --git a/docs/theme.config.js b/docs/theme.config.js index 29f115cb0..4c10dc5c2 100644 --- a/docs/theme.config.js +++ b/docs/theme.config.js @@ -15,7 +15,20 @@ export default { next: true, }, footer: { - text: `MIT ${new Date().getFullYear()} © Brian Carlson.`, + content: ( + + Please consider{' '} + + sponsoring this project on GitHub! + + ! + + ), }, editLink: { text: 'Edit this page on GitHub', @@ -55,6 +68,21 @@ l-161 -22 -94 41 c-201 87 -327 113 -533 112 -77 -1 -166 -7 -196 -13z m-89 chat: { link: 'https://discord.gg/2afXp5vUWm', }, + navbar: { + extraContent: ( + + + + + + ), + }, head: ( <> diff --git a/docs/yarn.lock b/docs/yarn.lock index aa2c18408..f65b39f82 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -2,324 +2,803 @@ # yarn lockfile v1 -"@babel/runtime@^7.12.5": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" - integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== - dependencies: - regenerator-runtime "^0.13.4" - -"@headlessui/react@^1.6.6": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.2.tgz#e6a6a8d38342064a53182f1eb2bf6d9c1e53ba6a" - integrity sha512-snLv2lxwsf2HNTOBNgHYdvoYZ3ChJE8QszPi1d/hl9js8KrFrUulTaQBfSyPbJP5BybVreWh9DxCgz9S0Z6hKQ== +"@antfu/install-pkg@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-1.1.0.tgz#78fa036be1a6081b5a77a5cf59f50c7752b6ba26" + integrity sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ== + dependencies: + package-manager-detector "^1.3.0" + tinyexec "^1.0.1" + +"@antfu/utils@^9.2.0": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-9.2.1.tgz#0a73683cf0a8c4cd38397b002439488229651cdb" + integrity sha512-TMilPqXyii1AsiEii6l6ubRzbo76p6oshUSYPaKsmXDavyMLqjzVDkcp3pHp5ELMUNJHATcEOGxKTTsX9yYhGg== + +"@braintree/sanitize-url@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz#15e19737d946559289b915e5dad3b4c28407735e" + integrity sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw== + +"@chevrotain/cst-dts-gen@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz#5e0863cc57dc45e204ccfee6303225d15d9d4783" + integrity sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ== + dependencies: + "@chevrotain/gast" "11.0.3" + "@chevrotain/types" "11.0.3" + lodash-es "4.17.21" + +"@chevrotain/gast@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/gast/-/gast-11.0.3.tgz#e84d8880323fe8cbe792ef69ce3ffd43a936e818" + integrity sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q== + dependencies: + "@chevrotain/types" "11.0.3" + lodash-es "4.17.21" + +"@chevrotain/regexp-to-ast@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz#11429a81c74a8e6a829271ce02fc66166d56dcdb" + integrity sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA== + +"@chevrotain/types@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/types/-/types-11.0.3.tgz#f8a03914f7b937f594f56eb89312b3b8f1c91848" + integrity sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ== + +"@chevrotain/utils@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/utils/-/utils-11.0.3.tgz#e39999307b102cff3645ec4f5b3665f5297a2224" + integrity sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ== + +"@floating-ui/core@^1.7.3": + version "1.7.3" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.3.tgz#462d722f001e23e46d86fd2bd0d21b7693ccb8b7" + integrity sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w== + dependencies: + "@floating-ui/utils" "^0.2.10" + +"@floating-ui/dom@^1.7.4": + version "1.7.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.4.tgz#ee667549998745c9c3e3e84683b909c31d6c9a77" + integrity sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA== + dependencies: + "@floating-ui/core" "^1.7.3" + "@floating-ui/utils" "^0.2.10" + +"@floating-ui/react-dom@^2.1.2": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.6.tgz#189f681043c1400561f62972f461b93f01bf2231" + integrity sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw== + dependencies: + "@floating-ui/dom" "^1.7.4" + +"@floating-ui/react@^0.26.16": + version "0.26.28" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.28.tgz#93f44ebaeb02409312e9df9507e83aab4a8c0dc7" + integrity sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw== + dependencies: + "@floating-ui/react-dom" "^2.1.2" + "@floating-ui/utils" "^0.2.8" + tabbable "^6.0.0" + +"@floating-ui/utils@^0.2.10", "@floating-ui/utils@^0.2.8": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c" + integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ== + +"@formatjs/intl-localematcher@^0.5.4": + version "0.5.10" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.5.10.tgz#1e0bd3fc1332c1fe4540cfa28f07e9227b659a58" + integrity sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q== + dependencies: + tslib "2" + +"@headlessui/react@^2.1.2": + version "2.2.9" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-2.2.9.tgz#213f78534c86e03a7c986d2c2abe1270622b3e13" + integrity sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ== + dependencies: + "@floating-ui/react" "^0.26.16" + "@react-aria/focus" "^3.20.2" + "@react-aria/interactions" "^3.25.0" + "@tanstack/react-virtual" "^3.13.9" + use-sync-external-store "^1.5.0" + +"@iconify/types@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" + integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== -"@mdx-js/mdx@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-2.1.3.tgz#d5821920ebe546b45192f4c7a64dcc68a658f7f9" - integrity sha512-ahbb47HJIJ4xnifaL06tDJiSyLEy1EhFAStO7RZIm3GTa7yGW3NGhZaj+GUCveFgl5oI54pY4BgiLmYm97y+zg== +"@iconify/utils@^3.0.1": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@iconify/utils/-/utils-3.0.2.tgz#9599607f20690cd3e7a5d2d459af0eb81a89dc2b" + integrity sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ== + dependencies: + "@antfu/install-pkg" "^1.1.0" + "@antfu/utils" "^9.2.0" + "@iconify/types" "^2.0.0" + debug "^4.4.1" + globals "^15.15.0" + kolorist "^1.8.0" + local-pkg "^1.1.1" + mlly "^1.7.4" + +"@mdx-js/mdx@^3.0.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-3.1.1.tgz#c5ffd991a7536b149e17175eee57a1a2a511c6d1" + integrity sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ== dependencies: + "@types/estree" "^1.0.0" "@types/estree-jsx" "^1.0.0" + "@types/hast" "^3.0.0" "@types/mdx" "^2.0.0" - estree-util-build-jsx "^2.0.0" - estree-util-is-identifier-name "^2.0.0" - estree-util-to-js "^1.1.0" + acorn "^8.0.0" + collapse-white-space "^2.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + estree-util-scope "^1.0.0" estree-walker "^3.0.0" - hast-util-to-estree "^2.0.0" - markdown-extensions "^1.0.0" - periscopic "^3.0.0" - remark-mdx "^2.0.0" - remark-parse "^10.0.0" - remark-rehype "^10.0.0" - unified "^10.0.0" - unist-util-position-from-estree "^1.0.0" - unist-util-stringify-position "^3.0.0" - unist-util-visit "^4.0.0" - vfile "^5.0.0" - -"@mdx-js/react@^2.1.2": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-2.1.3.tgz#4b28a774295ed1398cf6be1b8ddef69d6a30e78d" - integrity sha512-11n4lTvvRyxq3OYbWJwEYM+7q6PE0GxKbk0AwYIIQmrRkxDeljIsjDQkKOgdr/orgRRbYy5zi+iERdnwe01CHQ== + hast-util-to-jsx-runtime "^2.0.0" + markdown-extensions "^2.0.0" + recma-build-jsx "^1.0.0" + recma-jsx "^1.0.0" + recma-stringify "^1.0.0" + rehype-recma "^1.0.0" + remark-mdx "^3.0.0" + remark-parse "^11.0.0" + remark-rehype "^11.0.0" + source-map "^0.7.0" + unified "^11.0.0" + unist-util-position-from-estree "^2.0.0" + unist-util-stringify-position "^4.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" + +"@mdx-js/react@^3.0.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.1.1.tgz#24bda7fffceb2fe256f954482123cda1be5f5fef" + integrity sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw== dependencies: "@types/mdx" "^2.0.0" - "@types/react" ">=16" -"@napi-rs/simple-git-android-arm-eabi@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.8.tgz#303bea1ec00db24466e3b3ba13de337d87c5371b" - integrity sha512-JJCejHBB1G6O8nxjQLT4quWCcvLpC3oRdJJ9G3MFYSCoYS8i1bWCWeU+K7Br+xT+D6s1t9q8kNJAwJv9Ygpi0g== +"@mermaid-js/parser@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@mermaid-js/parser/-/parser-0.6.2.tgz#6d505a33acb52ddeb592c596b14f9d92a30396a9" + integrity sha512-+PO02uGF6L6Cs0Bw8RpGhikVvMWEysfAyl27qTlroUB8jSWr1lL0Sf6zi78ZxlSnmgSY2AMMKVgghnN9jTtwkQ== + dependencies: + langium "3.3.1" + +"@napi-rs/simple-git-android-arm-eabi@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.22.tgz#f2d240dc87e924a8ca4428fa68b121e8697f1765" + integrity sha512-JQZdnDNm8o43A5GOzwN/0Tz3CDBQtBUNqzVwEopm32uayjdjxev1Csp1JeaqF3v9djLDIvsSE39ecsN2LhCKKQ== + +"@napi-rs/simple-git-android-arm64@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.22.tgz#80432fe8ccca85764ca773bd605f456de02e3159" + integrity sha512-46OZ0SkhnvM+fapWjzg/eqbJvClxynUpWYyYBn4jAj7GQs1/Yyc8431spzDmkA8mL0M7Xo8SmbkzTDE7WwYAfg== + +"@napi-rs/simple-git-darwin-arm64@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.22.tgz#cc9730b7895318519a941f8e42d22ec6e458a3f3" + integrity sha512-zH3h0C8Mkn9//MajPI6kHnttywjsBmZ37fhLX/Fiw5XKu84eHA6dRyVtMzoZxj6s+bjNTgaMgMUucxPn9ktxTQ== + +"@napi-rs/simple-git-darwin-x64@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.22.tgz#216d9472db2f5e261e4b2879eef571e24ff05258" + integrity sha512-GZN7lRAkGKB6PJxWsoyeYJhh85oOOjVNyl+/uipNX8bR+mFDCqRsCE3rRCFGV9WrZUHXkcuRL2laIRn7lLi3ag== + +"@napi-rs/simple-git-freebsd-x64@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-freebsd-x64/-/simple-git-freebsd-x64-0.1.22.tgz#a526ebf45fa955b6523b0194d4e702c830503536" + integrity sha512-xyqX1C5I0WBrUgZONxHjZH5a4LqQ9oki3SKFAVpercVYAcx3pq6BkZy1YUOP4qx78WxU1CCNfHBN7V+XO7D99A== + +"@napi-rs/simple-git-linux-arm-gnueabihf@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.22.tgz#54aad93e1391bb242b14ab194b30efca1f53d798" + integrity sha512-4LOtbp9ll93B9fxRvXiUJd1/RM3uafMJE7dGBZGKWBMGM76+BAcCEUv2BY85EfsU/IgopXI6n09TycRfPWOjxA== + +"@napi-rs/simple-git-linux-arm64-gnu@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.22.tgz#1f022edd88904b8e6d58b81b792a3b45f378ab74" + integrity sha512-GVOjP/JjCzbQ0kSqao7ctC/1sodVtv5VF57rW9BFpo2y6tEYPCqHnkQkTpieuwMNe+TVOhBUC1+wH0d9/knIHg== + +"@napi-rs/simple-git-linux-arm64-musl@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.22.tgz#68fc72bd7d6dec9154b9fb0a6ad48bd99eb0c5a2" + integrity sha512-MOs7fPyJiU/wqOpKzAOmOpxJ/TZfP4JwmvPad/cXTOWYwwyppMlXFRms3i98EU3HOazI/wMU2Ksfda3+TBluWA== + +"@napi-rs/simple-git-linux-ppc64-gnu@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-ppc64-gnu/-/simple-git-linux-ppc64-gnu-0.1.22.tgz#19e595c5a13c95ae6a48a096ba5debf6dbc896ed" + integrity sha512-L59dR30VBShRUIZ5/cQHU25upNgKS0AMQ7537J6LCIUEFwwXrKORZKJ8ceR+s3Sr/4jempWVvMdjEpFDE4HYww== + +"@napi-rs/simple-git-linux-s390x-gnu@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-s390x-gnu/-/simple-git-linux-s390x-gnu-0.1.22.tgz#399c7c6a1050ae382c61b276f898155636c83faf" + integrity sha512-4FHkPlCSIZUGC6HiADffbe6NVoTBMd65pIwcd40IDbtFKOgFMBA+pWRqKiQ21FERGH16Zed7XHJJoY3jpOqtmQ== + +"@napi-rs/simple-git-linux-x64-gnu@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.22.tgz#8f74a3a42d6b9e5d50e3f3ff68aeebc5d3768d9d" + integrity sha512-Ei1tM5Ho/dwknF3pOzqkNW9Iv8oFzRxE8uOhrITcdlpxRxVrBVptUF6/0WPdvd7R9747D/q61QG/AVyWsWLFKw== + +"@napi-rs/simple-git-linux-x64-musl@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.22.tgz#71e311b95d07c15c74075b487c6cfa56ac99733c" + integrity sha512-zRYxg7it0p3rLyEJYoCoL2PQJNgArVLyNavHW03TFUAYkYi5bxQ/UFNVpgxMaXohr5yu7qCBqeo9j4DWeysalg== + +"@napi-rs/simple-git-win32-arm64-msvc@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.22.tgz#01b948b52217ae79e3c80bccd9b05ae728c37ce4" + integrity sha512-XGFR1fj+Y9cWACcovV2Ey/R2xQOZKs8t+7KHPerYdJ4PtjVzGznI4c2EBHXtdOIYvkw7tL5rZ7FN1HJKdD5Quw== + +"@napi-rs/simple-git-win32-ia32-msvc@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-win32-ia32-msvc/-/simple-git-win32-ia32-msvc-0.1.22.tgz#3ec733ade79fc50050c9268c7ec163118e4bf1a2" + integrity sha512-Gqr9Y0gs6hcNBA1IXBpoqTFnnIoHuZGhrYqaZzEvGMLrTrpbXrXVEtX3DAAD2RLc1b87CPcJ49a7sre3PU3Rfw== + +"@napi-rs/simple-git-win32-x64-msvc@0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.22.tgz#aee122d7aa030f45775bfd8abff49ffe12b89eb7" + integrity sha512-hQjcreHmUcpw4UrtkOron1/TQObfe484lxiXFLLUj7aWnnnOVs1mnXq5/Bo9+3NYZldFpFRJPdPBeHCisXkKJg== + +"@napi-rs/simple-git@^0.1.9": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git/-/simple-git-0.1.22.tgz#00a2520aedcfc73b65bb8147fde352c78da27423" + integrity sha512-bMVoAKhpjTOPHkW/lprDPwv5aD4R4C3Irt8vn+SKA9wudLe9COLxOhurrKRsxmZccUbWXRF7vukNeGUAj5P8kA== + optionalDependencies: + "@napi-rs/simple-git-android-arm-eabi" "0.1.22" + "@napi-rs/simple-git-android-arm64" "0.1.22" + "@napi-rs/simple-git-darwin-arm64" "0.1.22" + "@napi-rs/simple-git-darwin-x64" "0.1.22" + "@napi-rs/simple-git-freebsd-x64" "0.1.22" + "@napi-rs/simple-git-linux-arm-gnueabihf" "0.1.22" + "@napi-rs/simple-git-linux-arm64-gnu" "0.1.22" + "@napi-rs/simple-git-linux-arm64-musl" "0.1.22" + "@napi-rs/simple-git-linux-ppc64-gnu" "0.1.22" + "@napi-rs/simple-git-linux-s390x-gnu" "0.1.22" + "@napi-rs/simple-git-linux-x64-gnu" "0.1.22" + "@napi-rs/simple-git-linux-x64-musl" "0.1.22" + "@napi-rs/simple-git-win32-arm64-msvc" "0.1.22" + "@napi-rs/simple-git-win32-ia32-msvc" "0.1.22" + "@napi-rs/simple-git-win32-x64-msvc" "0.1.22" + +"@next/env@13.5.11": + version "13.5.11" + resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.11.tgz#6712d907e2682199aa1e8229b5ce028ee5a8001b" + integrity sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg== + +"@next/swc-darwin-arm64@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.9.tgz#46c3a525039171ff1a83c813d7db86fb7808a9b2" + integrity sha512-pVyd8/1y1l5atQRvOaLOvfbmRwefxLhqQOzYo/M7FQ5eaRwA1+wuCn7t39VwEgDd7Aw1+AIWwd+MURXUeXhwDw== + +"@next/swc-darwin-x64@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.9.tgz#b690452e9a6ce839f8738e27e9fd1a8567dd7554" + integrity sha512-DwdeJqP7v8wmoyTWPbPVodTwCybBZa02xjSJ6YQFIFZFZ7dFgrieKW4Eo0GoIcOJq5+JxkQyejmI+8zwDp3pwA== + +"@next/swc-linux-arm64-gnu@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.9.tgz#c3e335e2da3ba932c0b2f571f0672d1aa7af33df" + integrity sha512-wdQsKsIsGSNdFojvjW3Ozrh8Q00+GqL3wTaMjDkQxVtRbAqfFBtrLPO0IuWChVUP2UeuQcHpVeUvu0YgOP00+g== + +"@next/swc-linux-arm64-musl@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.9.tgz#54600d4917bace2508725cc963eeeb3b6432889e" + integrity sha512-6VpS+bodQqzOeCwGxoimlRoosiWlSc0C224I7SQWJZoyJuT1ChNCo+45QQH+/GtbR/s7nhaUqmiHdzZC9TXnXA== + +"@next/swc-linux-x64-gnu@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.9.tgz#f869c2066f13ff2818140e0a145dfea1ea7c0333" + integrity sha512-XxG3yj61WDd28NA8gFASIR+2viQaYZEFQagEodhI/R49gXWnYhiflTeeEmCn7Vgnxa/OfK81h1gvhUZ66lozpw== + +"@next/swc-linux-x64-musl@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.9.tgz#09295ea60a42a1b22d927802d6e543d8a8bbb186" + integrity sha512-/dnscWqfO3+U8asd+Fc6dwL2l9AZDl7eKtPNKW8mKLh4Y4wOpjJiamhe8Dx+D+Oq0GYVjuW0WwjIxYWVozt2bA== + +"@next/swc-win32-arm64-msvc@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.9.tgz#f39e3513058d7af6e9f6b1f296bf071301217159" + integrity sha512-T/iPnyurOK5a4HRUcxAlss8uzoEf5h9tkd+W2dSWAfzxv8WLKlUgbfk+DH43JY3Gc2xK5URLuXrxDZ2mGfk/jw== + +"@next/swc-win32-ia32-msvc@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.9.tgz#d567f471e182efa4ea29f47f3030613dd3fc68b5" + integrity sha512-BLiPKJomaPrTAb7ykjA0LPcuuNMLDVK177Z1xe0nAem33+9FIayU4k/OWrtSn9SAJW/U60+1hoey5z+KCHdRLQ== + +"@next/swc-win32-x64-msvc@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.9.tgz#35c53bd6d33040ec0ce1dd613c59112aac06b235" + integrity sha512-/72/dZfjXXNY/u+n8gqZDjI6rxKMpYsgBBYNZKWOQw0BpBF7WCnPflRy3ZtvQ2+IYI3ZH2bPyj7K+6a6wNk90Q== + +"@react-aria/focus@^3.20.2": + version "3.21.1" + resolved "https://registry.yarnpkg.com/@react-aria/focus/-/focus-3.21.1.tgz#fad9d0803e0e4423bb6e14ed3208fffd694e5e42" + integrity sha512-hmH1IhHlcQ2lSIxmki1biWzMbGgnhdxJUM0MFfzc71Rv6YAzhlx4kX3GYn4VNcjCeb6cdPv4RZ5vunV4kgMZYQ== + dependencies: + "@react-aria/interactions" "^3.25.5" + "@react-aria/utils" "^3.30.1" + "@react-types/shared" "^3.32.0" + "@swc/helpers" "^0.5.0" + clsx "^2.0.0" + +"@react-aria/interactions@^3.25.0", "@react-aria/interactions@^3.25.5": + version "3.25.5" + resolved "https://registry.yarnpkg.com/@react-aria/interactions/-/interactions-3.25.5.tgz#f7f69467c899f9673460c3401fcaac08d2dcac7d" + integrity sha512-EweYHOEvMwef/wsiEqV73KurX/OqnmbzKQa2fLxdULbec5+yDj6wVGaRHIzM4NiijIDe+bldEl5DG05CAKOAHA== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.30.1" + "@react-stately/flags" "^3.1.2" + "@react-types/shared" "^3.32.0" + "@swc/helpers" "^0.5.0" + +"@react-aria/ssr@^3.9.10": + version "3.9.10" + resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.9.10.tgz#7fdc09e811944ce0df1d7e713de1449abd7435e6" + integrity sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-aria/utils@^3.30.1": + version "3.30.1" + resolved "https://registry.yarnpkg.com/@react-aria/utils/-/utils-3.30.1.tgz#9eb704d4193674816e1e0eab758b12c2d69d7b0b" + integrity sha512-zETcbDd6Vf9GbLndO6RiWJadIZsBU2MMm23rBACXLmpRztkrIqPEb2RVdlLaq1+GklDx0Ii6PfveVjx+8S5U6A== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-stately/flags" "^3.1.2" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.0" + "@swc/helpers" "^0.5.0" + clsx "^2.0.0" + +"@react-stately/flags@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-stately/flags/-/flags-3.1.2.tgz#5c8e5ae416d37d37e2e583d2fcb3a046293504f2" + integrity sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg== + dependencies: + "@swc/helpers" "^0.5.0" -"@napi-rs/simple-git-android-arm64@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.8.tgz#42c8d04287364fd1619002629fa52183dcf462ee" - integrity sha512-mraHzwWBw3tdRetNOS5KnFSjvdAbNBnjFLA8I4PwTCPJj3Q4txrigcPp2d59cJ0TC51xpnPXnZjYdNwwSI9g6g== +"@react-stately/utils@^3.10.8": + version "3.10.8" + resolved "https://registry.yarnpkg.com/@react-stately/utils/-/utils-3.10.8.tgz#fdb9d172f7bbc2d083e69190f5ef0edfa4b4392f" + integrity sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g== + dependencies: + "@swc/helpers" "^0.5.0" -"@napi-rs/simple-git-darwin-arm64@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.8.tgz#e210808e6d646d6efecea84c67ced8eb44a8f821" - integrity sha512-ufy/36eI/j4UskEuvqSH7uXtp3oXeLDmjQCfKJz3u5Vx98KmOMKrqAm2H81AB2WOtCo5mqS6PbBeUXR8BJX8lQ== +"@react-types/shared@^3.32.0": + version "3.32.0" + resolved "https://registry.yarnpkg.com/@react-types/shared/-/shared-3.32.0.tgz#6c105ef05e1bd84ab04531e707074dc2a0b3ce07" + integrity sha512-t+cligIJsZYFMSPFMvsJMjzlzde06tZMOIOFa1OV5Z0BcMowrb2g4mB57j/9nP28iJIRYn10xCniQts+qadrqQ== -"@napi-rs/simple-git-darwin-x64@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.8.tgz#d717525c33e0dfd8a6d6215da2fcbc0ad40011e1" - integrity sha512-Vb21U+v3tPJNl+8JtIHHT8HGe6WZ8o1Tq3f6p+Jx9Cz71zEbcIiB9FCEMY1knS/jwQEOuhhlI9Qk7d4HY+rprA== +"@shikijs/core@1.29.2": + version "1.29.2" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.29.2.tgz#9c051d3ac99dd06ae46bd96536380c916e552bf3" + integrity sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ== + dependencies: + "@shikijs/engine-javascript" "1.29.2" + "@shikijs/engine-oniguruma" "1.29.2" + "@shikijs/types" "1.29.2" + "@shikijs/vscode-textmate" "^10.0.1" + "@types/hast" "^3.0.4" + hast-util-to-html "^9.0.4" -"@napi-rs/simple-git-linux-arm-gnueabihf@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.8.tgz#03e7b2dd299c10e61bbf29f405ea74f6571cf6a1" - integrity sha512-6BPTJ7CzpSm2t54mRLVaUr3S7ORJfVJoCk2rQ8v8oDg0XAMKvmQQxOsAgqKBo9gYNHJnqrOx3AEuEgvB586BuQ== +"@shikijs/engine-javascript@1.29.2": + version "1.29.2" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-1.29.2.tgz#a821ad713a3e0b7798a1926fd9e80116e38a1d64" + integrity sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A== + dependencies: + "@shikijs/types" "1.29.2" + "@shikijs/vscode-textmate" "^10.0.1" + oniguruma-to-es "^2.2.0" -"@napi-rs/simple-git-linux-arm64-gnu@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.8.tgz#945123f75c9a36fd0364e789ce06cd29a74a43cc" - integrity sha512-qfESqUCAA/XoQpRXHptSQ8gIFnETCQt1zY9VOkplx6tgYk9PCeaX4B1Xuzrh3eZamSCMJFn+1YB9Ut8NwyGgAA== +"@shikijs/engine-oniguruma@1.29.2": + version "1.29.2" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz#d879717ced61d44e78feab16f701f6edd75434f1" + integrity sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA== + dependencies: + "@shikijs/types" "1.29.2" + "@shikijs/vscode-textmate" "^10.0.1" -"@napi-rs/simple-git-linux-arm64-musl@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.8.tgz#2c20a0bff7c08f60b033ed7056dcb07bbbff8310" - integrity sha512-G80BQPpaRmQpn8dJGHp4I2/YVhWDUNJwcCrJAtAdbKFDCMyCHJBln2ERL/+IEUlIAT05zK/c1Z5WEprvXEdXow== +"@shikijs/langs@1.29.2": + version "1.29.2" + resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-1.29.2.tgz#4f1de46fde8991468c5a68fa4a67dd2875d643cd" + integrity sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ== + dependencies: + "@shikijs/types" "1.29.2" -"@napi-rs/simple-git-linux-x64-gnu@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.8.tgz#980e22b7376252a0767298ec801d374d97553da1" - integrity sha512-NI6o1sZYEf6vPtNWJAm9w8BxJt+LlSFW0liSjYe3lc3e4dhMfV240f0ALeqlwdIldRPaDFwZSJX5/QbS7nMzhw== +"@shikijs/themes@1.29.2": + version "1.29.2" + resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-1.29.2.tgz#293cc5c83dd7df3fdc8efa25cec8223f3a6acb0d" + integrity sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g== + dependencies: + "@shikijs/types" "1.29.2" -"@napi-rs/simple-git-linux-x64-musl@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.8.tgz#edca3b2833dc5d3fc9151f5b931f7b14478ccca4" - integrity sha512-wljGAEOW41er45VTiU8kXJmO480pQKzsgRCvPlJJSCaEVBbmo6XXbFIXnZy1a2J3Zyy2IOsRB4PVkUZaNuPkZQ== +"@shikijs/twoslash@^1.0.0": + version "1.29.2" + resolved "https://registry.yarnpkg.com/@shikijs/twoslash/-/twoslash-1.29.2.tgz#c4b683e25151d66cc35b4d817fcbc1e665e8df67" + integrity sha512-2S04ppAEa477tiaLfGEn1QJWbZUmbk8UoPbAEw4PifsrxkBXtAtOflIZJNtuCwz8ptc/TPxy7CO7gW4Uoi6o/g== + dependencies: + "@shikijs/core" "1.29.2" + "@shikijs/types" "1.29.2" + twoslash "^0.2.12" -"@napi-rs/simple-git-win32-arm64-msvc@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.8.tgz#3ac4c7fe816a2cdafabd091ded76161d1ba1fe88" - integrity sha512-QuV4QILyKPfbWHoQKrhXqjiCClx0SxbCTVogkR89BwivekqJMd9UlMxZdoCmwLWutRx4z9KmzQqokvYI5QeepA== +"@shikijs/types@1.29.2": + version "1.29.2" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.29.2.tgz#a93fdb410d1af8360c67bf5fc1d1a68d58e21c4f" + integrity sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw== + dependencies: + "@shikijs/vscode-textmate" "^10.0.1" + "@types/hast" "^3.0.4" -"@napi-rs/simple-git-win32-x64-msvc@0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.8.tgz#3b825bc2cb1c7ff535a3ca03768142d68bbf5c19" - integrity sha512-UzNS4JtjhZhZ5hRLq7BIUq+4JOwt1ThIKv11CsF1ag2l99f0123XvfEpjczKTaa94nHtjXYc2Mv9TjccBqYOew== +"@shikijs/vscode-textmate@^10.0.1": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz#a90ab31d0cc1dfb54c66a69e515bf624fa7b2224" + integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg== -"@napi-rs/simple-git@^0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@napi-rs/simple-git/-/simple-git-0.1.8.tgz#391cb58436d50bd32d924611d45bdc41f5e7607a" - integrity sha512-BvOMdkkofTz6lEE35itJ/laUokPhr/5ToMGlOH25YnhLD2yN1KpRAT4blW9tT8281/1aZjW3xyi73bs//IrDKA== - optionalDependencies: - "@napi-rs/simple-git-android-arm-eabi" "0.1.8" - "@napi-rs/simple-git-android-arm64" "0.1.8" - "@napi-rs/simple-git-darwin-arm64" "0.1.8" - "@napi-rs/simple-git-darwin-x64" "0.1.8" - "@napi-rs/simple-git-linux-arm-gnueabihf" "0.1.8" - "@napi-rs/simple-git-linux-arm64-gnu" "0.1.8" - "@napi-rs/simple-git-linux-arm64-musl" "0.1.8" - "@napi-rs/simple-git-linux-x64-gnu" "0.1.8" - "@napi-rs/simple-git-linux-x64-musl" "0.1.8" - "@napi-rs/simple-git-win32-arm64-msvc" "0.1.8" - "@napi-rs/simple-git-win32-x64-msvc" "0.1.8" - -"@next/env@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.1.tgz#18266bd92de3b4aa4037b1927aa59e6f11879260" - integrity sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg== - -"@next/swc-android-arm-eabi@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz#b15ce8ad376102a3b8c0f3c017dde050a22bb1a3" - integrity sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ== - -"@next/swc-android-arm64@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz#85d205f568a790a137cb3c3f720d961a2436ac9c" - integrity sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q== - -"@next/swc-darwin-arm64@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz#b105457d6760a7916b27e46c97cb1a40547114ae" - integrity sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg== - -"@next/swc-darwin-x64@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz#6947b39082271378896b095b6696a7791c6e32b1" - integrity sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA== - -"@next/swc-freebsd-x64@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz#2b6c36a4d84aae8b0ea0e0da9bafc696ae27085a" - integrity sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q== - -"@next/swc-linux-arm-gnueabihf@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz#6e421c44285cfedac1f4631d5de330dd60b86298" - integrity sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w== - -"@next/swc-linux-arm64-gnu@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz#8863f08a81f422f910af126159d2cbb9552ef717" - integrity sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ== - -"@next/swc-linux-arm64-musl@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz#0038f07cf0b259d70ae0c80890d826dfc775d9f3" - integrity sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg== - -"@next/swc-linux-x64-gnu@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz#c66468f5e8181ffb096c537f0dbfb589baa6a9c1" - integrity sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA== - -"@next/swc-linux-x64-musl@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz#c6269f3e96ac0395bc722ad97ce410ea5101d305" - integrity sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg== - -"@next/swc-win32-arm64-msvc@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz#83c639ee969cee36ce247c3abd1d9df97b5ecade" - integrity sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw== - -"@next/swc-win32-ia32-msvc@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz#52995748b92aa8ad053440301bc2c0d9fbcf27c2" - integrity sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA== - -"@next/swc-win32-x64-msvc@12.3.1": - version "12.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz#27d71a95247a9eaee03d47adee7e3bd594514136" - integrity sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA== - -"@popperjs/core@^2.11.6": - version "2.11.6" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" - integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== - -"@reach/skip-nav@^0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@reach/skip-nav/-/skip-nav-0.17.0.tgz#225aaaf947f8750568ad5f4cc3646641fd335d56" - integrity sha512-wkkpQK3ffczzGHis6TaUvpOabuAL9n9Kh5vr4h56XPIJP3X77VcHUDk7MK3HbV1mTgamGxc9Hbd1sXKSWLu3yA== - dependencies: - "@reach/utils" "0.17.0" - tslib "^2.3.0" - -"@reach/utils@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.17.0.tgz#3d1d2ec56d857f04fe092710d8faee2b2b121303" - integrity sha512-M5y8fCBbrWeIsxedgcSw6oDlAMQDkl5uv3VnMVJ7guwpf4E48Xlh1v66z/1BgN/WYe2y8mB/ilFD2nysEfdGeA== - dependencies: - tiny-warning "^1.0.3" - tslib "^2.3.0" - -"@swc/helpers@0.4.11": - version "0.4.11" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.11.tgz#db23a376761b3d31c26502122f349a21b592c8de" - integrity sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw== +"@swc/helpers@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d" + integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw== dependencies: tslib "^2.4.0" -"@types/acorn@^4.0.0": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22" - integrity sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ== +"@swc/helpers@^0.5.0": + version "0.5.17" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.17.tgz#5a7be95ac0f0bf186e7e6e890e7a6f6cda6ce971" + integrity sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A== dependencies: - "@types/estree" "*" + tslib "^2.8.0" + +"@tanstack/react-virtual@^3.13.9": + version "3.13.12" + resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz#d372dc2783739cc04ec1a728ca8203937687a819" + integrity sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA== + dependencies: + "@tanstack/virtual-core" "3.13.12" + +"@tanstack/virtual-core@3.13.12": + version "3.13.12" + resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz#1dff176df9cc8f93c78c5e46bcea11079b397578" + integrity sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA== + +"@theguild/remark-mermaid@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@theguild/remark-mermaid/-/remark-mermaid-0.1.3.tgz#55bd0ff5cd890c49f8137e76b5158abd787c3642" + integrity sha512-2FjVlaaKXK7Zj7UJAgOVTyaahn/3/EAfqYhyXg0BfDBVUl+lXcoIWRaxzqfnDr2rv8ax6GsC5mNh6hAaT86PDw== + dependencies: + mermaid "^11.0.0" + unist-util-visit "^5.0.0" + +"@theguild/remark-npm2yarn@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@theguild/remark-npm2yarn/-/remark-npm2yarn-0.3.3.tgz#5c132375d4fc83c5c49cf0fabc4e5f4147dba87c" + integrity sha512-ma6DvR03gdbvwqfKx1omqhg9May/VYGdMHvTzB4VuxkyS7KzfZ/lzrj43hmcsggpMje0x7SADA/pcMph0ejRnA== + dependencies: + npm-to-yarn "^3.0.0" + unist-util-visit "^5.0.0" + +"@types/d3-array@*": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.2.tgz#e02151464d02d4a1b44646d0fcdb93faf88fde8c" + integrity sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw== + +"@types/d3-axis@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795" + integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c" + integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d" + integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-contour@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231" + integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg== + dependencies: + "@types/d3-array" "*" + "@types/geojson" "*" + +"@types/d3-delaunay@*": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1" + integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw== + +"@types/d3-dispatch@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz#ef004d8a128046cfce434d17182f834e44ef95b2" + integrity sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA== + +"@types/d3-drag@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02" + integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17" + integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g== + +"@types/d3-ease@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== + +"@types/d3-fetch@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980" + integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA== + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-force@*": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.10.tgz#6dc8fc6e1f35704f3b057090beeeb7ac674bff1a" + integrity sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw== + +"@types/d3-format@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90" + integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g== + +"@types/d3-geo@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440" + integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ== + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b" + integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg== + +"@types/d3-interpolate@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.1.tgz#f632b380c3aca1dba8e34aa049bcd6a4af23df8a" + integrity sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg== + +"@types/d3-polygon@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c" + integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA== + +"@types/d3-quadtree@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f" + integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg== + +"@types/d3-random@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb" + integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ== + +"@types/d3-scale-chromatic@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#dc6d4f9a98376f18ea50bad6c39537f1b5463c39" + integrity sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ== + +"@types/d3-scale@*": + version "4.0.9" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.9.tgz#57a2f707242e6fe1de81ad7bfcccaaf606179afb" + integrity sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw== + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.11.tgz#bd7a45fc0a8c3167a631675e61bc2ca2b058d4a3" + integrity sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w== + +"@types/d3-shape@*": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.7.tgz#2b7b423dc2dfe69c8c93596e673e37443348c555" + integrity sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2" + integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg== + +"@types/d3-time@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" + integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== + +"@types/d3-timer@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== + +"@types/d3-transition@*": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.9.tgz#1136bc57e9ddb3c390dccc9b5ff3b7d2b8d94706" + integrity sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-zoom@*": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b" + integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^7.4.3": + version "7.4.3" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2" + integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww== + dependencies: + "@types/d3-array" "*" + "@types/d3-axis" "*" + "@types/d3-brush" "*" + "@types/d3-chord" "*" + "@types/d3-color" "*" + "@types/d3-contour" "*" + "@types/d3-delaunay" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" + "@types/d3-fetch" "*" + "@types/d3-force" "*" + "@types/d3-format" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" + "@types/d3-polygon" "*" + "@types/d3-quadtree" "*" + "@types/d3-random" "*" + "@types/d3-scale" "*" + "@types/d3-scale-chromatic" "*" + "@types/d3-selection" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" + "@types/d3-time-format" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-zoom" "*" "@types/debug@^4.0.0": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" - integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== dependencies: "@types/ms" "*" "@types/estree-jsx@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.0.tgz#7bfc979ab9f692b492017df42520f7f765e98df1" - integrity sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ== + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" + integrity sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg== dependencies: "@types/estree" "*" "@types/estree@*", "@types/estree@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/geojson@*": + version "7946.0.16" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a" + integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg== -"@types/hast@^2.0.0": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" - integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== +"@types/hast@^3.0.0", "@types/hast@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" + integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== dependencies: "@types/unist" "*" -"@types/mdast@^3.0.0": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" - integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== +"@types/katex@^0.16.0": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.16.7.tgz#03ab680ab4fa4fbc6cb46ecf987ecad5d8019868" + integrity sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ== + +"@types/mdast@^4.0.0": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" + integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA== dependencies: "@types/unist" "*" -"@types/mdurl@^1.0.0": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" - integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== - "@types/mdx@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.2.tgz#64be19baddba4323ae7893e077e98759316fe279" - integrity sha512-mJGfgj4aWpiKb8C0nnJJchs1sHBHn0HugkVfqqyQi7Wn6mBRksLeQsPOFvih/Pu8L1vlDzfe/LidhVHBeUk3aQ== + version "2.0.13" + resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.13.tgz#68f6877043d377092890ff5b298152b0a21671bd" + integrity sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw== "@types/ms@*": - version "0.7.31" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" - integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== - -"@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== - -"@types/react@>=16": - version "18.0.21" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.21.tgz#b8209e9626bb00a34c76f55482697edd2b43cc67" - integrity sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== - -"@types/unist@*", "@types/unist@^2.0.0": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" + integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== + +"@types/nlcst@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/nlcst/-/nlcst-2.0.3.tgz#31cad346eaab48a9a8a58465d3d05e2530dda762" + integrity sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA== + dependencies: + "@types/unist" "*" + +"@types/trusted-types@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== + +"@types/unist@*", "@types/unist@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" + integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== + +"@types/unist@^2.0.0": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== + +"@typescript/vfs@^1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@typescript/vfs/-/vfs-1.6.1.tgz#fe7087d5a43715754f7ea9bf6e0b905176c9eebd" + integrity sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA== + dependencies: + debug "^4.1.1" + +"@ungap/structured-clone@^1.0.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + +"@xmldom/xmldom@0.9.8": + version "0.9.8" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.9.8.tgz#1471e82bdff9e8f20ee8bbe60d4ffa8a516e78d8" + integrity sha512-p96FSY54r+WJ50FIOsCOjyj/wavs8921hG5+kVMmZgKcvIKxMXHTrjNJvRgWa/zuX3B6t2lijLNFaOyuxUH+2A== acorn-jsx@^5.0.0: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.0.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== - -ansi-styles@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" +acorn@^8.0.0, acorn@^8.15.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== -arch@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" - integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== - -arg@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/arg/-/arg-1.0.0.tgz#444d885a4e25b121640b55155ef7cd03975d6050" - integrity sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw== +arg@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== argparse@^1.0.7: version "1.0.10" @@ -328,34 +807,49 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +array-iterate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-2.0.1.tgz#6efd43f8295b3fee06251d3d62ead4bd9805dd24" + integrity sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg== + astring@^1.8.0: - version "1.8.3" - resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.3.tgz#1a0ae738c7cc558f8e5ddc8e3120636f5cebcb85" - integrity sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A== + version "1.9.0" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.9.0.tgz#cc73e6062a7eb03e7d19c22d8b0b3451fd9bfeef" + integrity sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg== bail@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== +better-react-mathjax@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/better-react-mathjax/-/better-react-mathjax-2.3.0.tgz#d9a29b2b9eae873e60c0ca8042d7ecb94e2aa297" + integrity sha512-K0ceQC+jQmB+NLDogO5HCpqmYf18AU2FxDbLdduYgkHYWZApFggkHE4dIaXCV1NqeoscESYXXo1GSkY6fA295w== + dependencies: + mathjax-full "^3.2.2" + +busboy@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + caniuse-lite@^1.0.30001406: - version "1.0.30001410" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001410.tgz#b5a86366fbbf439d75dd3db1d21137a73e829f44" - integrity sha512-QoblBnuE+rG0lc3Ur9ltP5q47lbguipa/ncNMyyGuqPk44FxbScWAeEO+k5fSQ8WekdAK4mWqNs1rADDAiN5xQ== + version "1.0.30001746" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001746.tgz#199d20f04f5369825e00ff7067d45d5dfa03aee7" + integrity sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA== ccount@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== -chalk@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" - integrity sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q== - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" +chalk@^5.0.0: + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== character-entities-html4@^2.0.0: version "2.1.0" @@ -377,161 +871,580 @@ character-reference-invalid@^2.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9" integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw== -clipboardy@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.2.tgz#2ce320b9ed9be1514f79878b53ff9765420903e2" - integrity sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw== +chevrotain-allstar@~0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz#b7412755f5d83cc139ab65810cdb00d8db40e6ca" + integrity sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw== dependencies: - arch "^2.1.0" - execa "^0.8.0" + lodash-es "^4.17.21" -clsx@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" - integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== +chevrotain@~11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/chevrotain/-/chevrotain-11.0.3.tgz#88ffc1fb4b5739c715807eaeedbbf200e202fc1b" + integrity sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw== + dependencies: + "@chevrotain/cst-dts-gen" "11.0.3" + "@chevrotain/gast" "11.0.3" + "@chevrotain/regexp-to-ast" "11.0.3" + "@chevrotain/types" "11.0.3" + "@chevrotain/utils" "11.0.3" + lodash-es "4.17.21" + +client-only@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== +clipboardy@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-4.0.0.tgz#e73ced93a76d19dd379ebf1f297565426dffdca1" + integrity sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w== dependencies: - color-name "1.1.3" + execa "^8.0.1" + is-wsl "^3.1.0" + is64bit "^2.0.0" + +clsx@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +collapse-white-space@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-2.1.0.tgz#640257174f9f42c740b40f3b55ee752924feefca" + integrity sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw== comma-separated-tokens@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz#d4c25abb679b7751c880be623c1179780fe1dd98" - integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== -compute-scroll-into-view@^1.0.17: - version "1.0.17" - resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab" - integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg== +commander@13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" + integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== +commander@7: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +compute-scroll-into-view@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz#02c3386ec531fb6a9881967388e53e8564f3e9aa" + integrity sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw== + +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +confbox@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" + integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + +cose-base@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-1.0.3.tgz#650334b41b869578a543358b80cda7e0abe0a60a" + integrity sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg== + dependencies: + layout-base "^1.0.0" + +cose-base@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-2.2.0.tgz#1c395c35b6e10bb83f9769ca8b817d614add5c01" + integrity sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g== + dependencies: + layout-base "^2.0.0" + +cross-spawn@^7.0.3: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cytoscape-cose-bilkent@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz#762fa121df9930ffeb51a495d87917c570ac209b" + integrity sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ== dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" + cose-base "^1.0.0" -csstype@^3.0.2: +cytoscape-fcose@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz#e4d6f6490df4fab58ae9cea9e5c3ab8d7472f471" + integrity sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ== + dependencies: + cose-base "^2.2.0" + +cytoscape@^3.29.3: + version "3.33.1" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.33.1.tgz#449e05d104b760af2912ab76482d24c01cdd4c97" + integrity sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ== + +"d3-array@1 - 2": + version "2.12.1" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" + integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ== + dependencies: + internmap "^1.0.0" + +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + +d3-axis@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + +d3-brush@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-contour@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc" + integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA== + dependencies: + d3-array "^3.2.0" + +d3-delaunay@6: + version "6.0.4" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" + integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +d3-fetch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + +d3-force@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +d3-geo@3: version "3.1.1" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d" + integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" + integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +d3-path@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + +d3-random@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +d3-sankey@^0.12.3: + version "0.12.3" + resolved "https://registry.yarnpkg.com/d3-sankey/-/d3-sankey-0.12.3.tgz#b3c268627bd72e5d80336e8de6acbfec9d15d01d" + integrity sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ== + dependencies: + d3-array "1 - 2" + d3-shape "^1.2.0" + +d3-scale-chromatic@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +d3-scale@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +d3-shape@3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +d3-shape@^1.2.0: + version "1.3.7" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" -debug@^4.0.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== dependencies: - ms "2.1.2" + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.9.0: + version "7.9.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.9.0.tgz#579e7acb3d749caf8860bd1741ae8d371070cd5d" + integrity sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "4" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + +dagre-d3-es@7.0.11: + version "7.0.11" + resolved "https://registry.yarnpkg.com/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz#2237e726c0577bfe67d1a7cfd2265b9ab2c15c40" + integrity sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw== + dependencies: + d3 "^7.9.0" + lodash-es "^4.17.21" + +dayjs@^1.11.18: + version "1.11.18" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.18.tgz#835fa712aac52ab9dec8b1494098774ed7070a11" + integrity sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA== + +debug@^4.0.0, debug@^4.1.1, debug@^4.4.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" decode-named-character-reference@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" - integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz#25c32ae6dd5e21889549d40f676030e9514cc0ed" + integrity sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q== dependencies: character-entities "^2.0.0" +delaunator@5: + version "5.0.1" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" + integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw== + dependencies: + robust-predicates "^3.0.2" + dequal@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== -diff@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== +devlop@^1.0.0, devlop@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" + integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== + dependencies: + dequal "^2.0.0" -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +dompurify@^3.2.5: + version "3.2.7" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.7.tgz#721d63913db5111dd6dfda8d3a748cfd7982d44a" + integrity sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw== + optionalDependencies: + "@types/trusted-types" "^2.0.7" + +emoji-regex-xs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz#e8af22e5d9dbd7f7f22d280af3d19d2aab5b0724" + integrity sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg== + +entities@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" + integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== + +esast-util-from-estree@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz#8d1cfb51ad534d2f159dc250e604f3478a79f1ad" + integrity sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ== + dependencies: + "@types/estree-jsx" "^1.0.0" + devlop "^1.0.0" + estree-util-visit "^2.0.0" + unist-util-position-from-estree "^2.0.0" + +esast-util-from-js@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz#5147bec34cc9da44accf52f87f239a40ac3e8225" + integrity sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw== + dependencies: + "@types/estree-jsx" "^1.0.0" + acorn "^8.0.0" + esast-util-from-estree "^2.0.0" + vfile-message "^4.0.0" escape-string-regexp@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== +esm@^3.2.25: + version "3.2.25" + resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" + integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -estree-util-attach-comments@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-2.1.0.tgz#47d69900588bcbc6bf58c3798803ec5f1f3008de" - integrity sha512-rJz6I4L0GaXYtHpoMScgDIwM0/Vwbu5shbMeER596rB2D1EWF6+Gj0e0UKzJPZrpoOc87+Q2kgVFHfjAymIqmw== +estree-util-attach-comments@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz#344bde6a64c8a31d15231e5ee9e297566a691c2d" + integrity sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw== dependencies: "@types/estree" "^1.0.0" -estree-util-build-jsx@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/estree-util-build-jsx/-/estree-util-build-jsx-2.2.0.tgz#d4307bbeee28c14eb4d63b75c9aad28fa61d84f5" - integrity sha512-apsfRxF9uLrqosApvHVtYZjISPvTJ+lBiIydpC+9wE6cF6ssbhnjyQLqaIjgzGxvC2Hbmec1M7g91PoBayYoQQ== +estree-util-build-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz#b6d0bced1dcc4f06f25cf0ceda2b2dcaf98168f1" + integrity sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ== dependencies: "@types/estree-jsx" "^1.0.0" - estree-util-is-identifier-name "^2.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" estree-walker "^3.0.0" -estree-util-is-identifier-name@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-1.1.0.tgz#2e3488ea06d9ea2face116058864f6370b37456d" - integrity sha512-OVJZ3fGGt9By77Ix9NhaRbzfbDV/2rx9EP7YIDJTmsZSEc5kYn2vWcNccYyahJL2uAQZK2a5Or2i0wtIKTPoRQ== - estree-util-is-identifier-name@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.0.1.tgz#cf07867f42705892718d9d89eb2d85eaa8f0fcb5" - integrity sha512-rxZj1GkQhY4x1j/CSnybK9cGuMFQYFPLq0iNyopqf14aOVLFtMv7Esika+ObJWPWiOHuMOAHz3YkWoLYYRnzWQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz#fb70a432dcb19045e77b05c8e732f1364b4b49b2" + integrity sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ== -estree-util-to-js@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/estree-util-to-js/-/estree-util-to-js-1.1.0.tgz#3bd9bb86354063537cc3d81259be2f0d4c3af39f" - integrity sha512-490lbfCcpLk+ofK6HCgqDfYs4KAfq6QVvDw3+Bm1YoKRgiOjKiKYGAVQE1uwh7zVxBgWhqp4FDtp5SqunpUk1A== +estree-util-is-identifier-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz#0b5ef4c4ff13508b34dcd01ecfa945f61fce5dbd" + integrity sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg== + +estree-util-scope@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/estree-util-scope/-/estree-util-scope-1.0.0.tgz#9cbdfc77f5cb51e3d9ed4ad9c4adbff22d43e585" + integrity sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + +estree-util-to-js@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz#10a6fb924814e6abb62becf0d2bc4dea51d04f17" + integrity sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg== dependencies: "@types/estree-jsx" "^1.0.0" astring "^1.8.0" source-map "^0.7.0" -estree-util-value-to-estree@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz#1d3125594b4d6680f666644491e7ac1745a3df49" - integrity sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw== +estree-util-value-to-estree@^3.0.1, estree-util-value-to-estree@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/estree-util-value-to-estree/-/estree-util-value-to-estree-3.4.0.tgz#827122e40c3a756d3c4cf5d5d296fa06026a1a4f" + integrity sha512-Zlp+gxis+gCfK12d3Srl2PdX2ybsEA8ZYy6vQGVQTNNYLEGRQQ56XB64bjemN8kxIKXP1nC9ip4Z+ILy9LGzvQ== dependencies: - is-plain-obj "^3.0.0" + "@types/estree" "^1.0.0" -estree-util-visit@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/estree-util-visit/-/estree-util-visit-1.2.0.tgz#aa0311a9c2f2aa56e9ae5e8b9d87eac14e4ec8f8" - integrity sha512-wdsoqhWueuJKsh5hqLw3j8lwFqNStm92VcwtAOAny8g/KS/l5Y8RISjR4k5W6skCj3Nirag/WUCMS0Nfy3sgsg== +estree-util-visit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/estree-util-visit/-/estree-util-visit-2.0.0.tgz#13a9a9f40ff50ed0c022f831ddf4b58d05446feb" + integrity sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww== dependencies: "@types/estree-jsx" "^1.0.0" - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" estree-walker@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.1.tgz#c2a9fb4a30232f5039b7c030b37ead691932debd" - integrity sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g== - -execa@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" - integrity sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA== - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + +execa@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" + +exsolve@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.7.tgz#3b74e4c7ca5c5f9a19c3626ca857309fa99f9e9e" + integrity sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw== extend-shallow@^2.0.1: version "2.0.1" @@ -545,30 +1458,47 @@ extend@^3.0.0: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -flexsearch@^0.7.21: - version "0.7.21" - resolved "https://registry.yarnpkg.com/flexsearch/-/flexsearch-0.7.21.tgz#0f5ede3f2aae67ddc351efbe3b24b69d29e9d48b" - integrity sha512-W7cHV7Hrwjid6lWmy0IhsWDFQboWSng25U3VVywpHOTJnnAZNPScog67G+cVpeX9f7yDD21ih0WDrMMT+JoaYg== +fault@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fault/-/fault-2.0.1.tgz#d47ca9f37ca26e4bd38374a7c500b5a384755b6c" + integrity sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ== + dependencies: + format "^0.2.0" -focus-visible@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.2.0.tgz#3a9e41fccf587bd25dcc2ef045508284f0a4d6b3" - integrity sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ== +flexsearch@^0.7.43: + version "0.7.43" + resolved "https://registry.yarnpkg.com/flexsearch/-/flexsearch-0.7.43.tgz#34f89b36278a466ce379c5bf6fb341965ed3f16c" + integrity sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg== -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== -github-slugger@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" - integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== + +github-slugger@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-2.0.0.tgz#52cf2f9279a21eb6c59dd385b410f0c0adda8f1a" + integrity sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw== + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +globals@^15.15.0: + version "15.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" + integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== -graceful-fs@^4.2.10: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graceful-fs@^4.1.2, graceful-fs@^4.2.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== gray-matter@^4.0.3: version "4.0.3" @@ -580,51 +1510,228 @@ gray-matter@^4.0.3: section-matter "^1.0.0" strip-bom-string "^1.0.0" -has-flag@^2.0.0: +hachure-fill@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/hachure-fill/-/hachure-fill-0.5.2.tgz#d19bc4cc8750a5962b47fb1300557a85fcf934cc" + integrity sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg== + +hast-util-from-dom@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz#c3c92fbd8d4e1c1625edeb3a773952b9e4ad64a8" + integrity sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q== + dependencies: + "@types/hast" "^3.0.0" + hastscript "^9.0.0" + web-namespaces "^2.0.0" + +hast-util-from-html-isomorphic@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng== + resolved "https://registry.yarnpkg.com/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz#b31baee386a899a2472326a3c5692f29f86d1d3c" + integrity sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw== + dependencies: + "@types/hast" "^3.0.0" + hast-util-from-dom "^5.0.0" + hast-util-from-html "^2.0.0" + unist-util-remove-position "^5.0.0" -hast-util-to-estree@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-2.1.0.tgz#aeac70aad0102ae309570907b3f56a08231d5323" - integrity sha512-Vwch1etMRmm89xGgz+voWXvVHba2iiMdGMKmaMfYt35rbVtFDq8JNwwAIvi8zHMkO6Gvqo9oTMwJTmzVRfXh4g== +hast-util-from-html@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz#485c74785358beb80c4ba6346299311ac4c49c82" + integrity sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw== + dependencies: + "@types/hast" "^3.0.0" + devlop "^1.1.0" + hast-util-from-parse5 "^8.0.0" + parse5 "^7.0.0" + vfile "^6.0.0" + vfile-message "^4.0.0" + +hast-util-from-parse5@^8.0.0: + version "8.0.3" + resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz#830a35022fff28c3fea3697a98c2f4cc6b835a2e" + integrity sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + devlop "^1.0.0" + hastscript "^9.0.0" + property-information "^7.0.0" + vfile "^6.0.0" + vfile-location "^5.0.0" + web-namespaces "^2.0.0" + +hast-util-is-element@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz#6e31a6532c217e5b533848c7e52c9d9369ca0932" + integrity sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g== + dependencies: + "@types/hast" "^3.0.0" + +hast-util-parse-selector@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz#352879fa86e25616036037dd8931fb5f34cb4a27" + integrity sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A== + dependencies: + "@types/hast" "^3.0.0" + +hast-util-raw@^9.0.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-9.1.0.tgz#79b66b26f6f68fb50dfb4716b2cdca90d92adf2e" + integrity sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + "@ungap/structured-clone" "^1.0.0" + hast-util-from-parse5 "^8.0.0" + hast-util-to-parse5 "^8.0.0" + html-void-elements "^3.0.0" + mdast-util-to-hast "^13.0.0" + parse5 "^7.0.0" + unist-util-position "^5.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" + web-namespaces "^2.0.0" + zwitch "^2.0.0" + +hast-util-to-estree@^3.0.0, hast-util-to-estree@^3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz#e654c1c9374645135695cc0ab9f70b8fcaf733d7" + integrity sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w== dependencies: "@types/estree" "^1.0.0" "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" + "@types/hast" "^3.0.0" comma-separated-tokens "^2.0.0" - estree-util-attach-comments "^2.0.0" - estree-util-is-identifier-name "^2.0.0" - hast-util-whitespace "^2.0.0" - mdast-util-mdx-expression "^1.0.0" - mdast-util-mdxjs-esm "^1.0.0" + devlop "^1.0.0" + estree-util-attach-comments "^3.0.0" + estree-util-is-identifier-name "^3.0.0" + hast-util-whitespace "^3.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" + property-information "^7.0.0" + space-separated-tokens "^2.0.0" + style-to-js "^1.0.0" + unist-util-position "^5.0.0" + zwitch "^2.0.0" + +hast-util-to-html@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz#ccc673a55bb8e85775b08ac28380f72d47167005" + integrity sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + ccount "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-whitespace "^3.0.0" + html-void-elements "^3.0.0" + mdast-util-to-hast "^13.0.0" + property-information "^7.0.0" + space-separated-tokens "^2.0.0" + stringify-entities "^4.0.0" + zwitch "^2.0.4" + +hast-util-to-jsx-runtime@^2.0.0: + version "2.3.6" + resolved "https://registry.yarnpkg.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz#ff31897aae59f62232e21594eac7ef6b63333e98" + integrity sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg== + dependencies: + "@types/estree" "^1.0.0" + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + comma-separated-tokens "^2.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + hast-util-whitespace "^3.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" + property-information "^7.0.0" + space-separated-tokens "^2.0.0" + style-to-js "^1.0.0" + unist-util-position "^5.0.0" + vfile-message "^4.0.0" + +hast-util-to-parse5@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz#477cd42d278d4f036bc2ea58586130f6f39ee6ed" + integrity sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw== + dependencies: + "@types/hast" "^3.0.0" + comma-separated-tokens "^2.0.0" + devlop "^1.0.0" property-information "^6.0.0" space-separated-tokens "^2.0.0" - style-to-object "^0.3.0" - unist-util-position "^4.0.0" + web-namespaces "^2.0.0" zwitch "^2.0.0" -hast-util-to-string@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz#9b24c114866bdb9478927d7e9c36a485ac728378" - integrity sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w== +hast-util-to-string@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz#a4f15e682849326dd211c97129c94b0c3e76527c" + integrity sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A== + dependencies: + "@types/hast" "^3.0.0" -hast-util-whitespace@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz#4fc1086467cc1ef5ba20673cb6b03cec3a970f1c" - integrity sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg== +hast-util-to-text@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz#57b676931e71bf9cb852453678495b3080bfae3e" + integrity sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + hast-util-is-element "^3.0.0" + unist-util-find-after "^5.0.0" -inline-style-parser@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" - integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +hast-util-whitespace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" + integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== + dependencies: + "@types/hast" "^3.0.0" + +hastscript@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-9.0.1.tgz#dbc84bef6051d40084342c229c451cd9dc567dff" + integrity sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w== + dependencies: + "@types/hast" "^3.0.0" + comma-separated-tokens "^2.0.0" + hast-util-parse-selector "^4.0.0" + property-information "^7.0.0" + space-separated-tokens "^2.0.0" + +html-void-elements@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" + integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== -intersection-observer@^0.12.2: - version "0.12.2" - resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.2.tgz#4a45349cc0cd91916682b1f44c28d7ec737dc375" - integrity sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg== +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== + +iconv-lite@0.6: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +inline-style-parser@0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz#f4af5fe72e612839fcd453d989a586566d695f22" + integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q== + +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + +internmap@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" + integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== is-alphabetical@^2.0.0: version "2.0.1" @@ -639,16 +1746,16 @@ is-alphanumerical@^2.0.0: is-alphabetical "^2.0.0" is-decimal "^2.0.0" -is-buffer@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - is-decimal@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.1.tgz#9469d2dc190d0214fd87d78b78caecc0cc14eef7" integrity sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A== +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -659,27 +1766,36 @@ is-hexadecimal@^2.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027" integrity sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg== -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" is-plain-obj@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== -is-reference@^3.0.0: +is-stream@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-3.0.0.tgz#b1380c03d96ddf7089709781e3208fceb0c92cd6" - integrity sha512-Eo1W3wUoHWoCoVM4GVl/a+K0IgiqE5aIo4kJABFyMum1ZORlPkC+UC357sSQUL5w5QCE5kCC9upl75b7+7CY/Q== + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== dependencies: - "@types/estree" "*" + is-inside-container "^1.0.0" -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== +is64bit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is64bit/-/is64bit-2.0.0.tgz#198c627cbcb198bbec402251f88e5e1a51236c07" + integrity sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw== + dependencies: + system-architecture "^0.1.0" isexe@^2.0.0: version "2.0.0" @@ -699,25 +1815,67 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsonc-parser@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" - integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== +katex@^0.16.0, katex@^0.16.22, katex@^0.16.9: + version "0.16.22" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.22.tgz#d2b3d66464b1e6d69e6463b28a86ced5a02c5ccd" + integrity sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg== + dependencies: + commander "^8.3.0" + +khroma@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" + integrity sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -kleur@^4.0.3: - version "4.1.5" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" - integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== +kolorist@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +langium@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/langium/-/langium-3.3.1.tgz#da745a40d5ad8ee565090fed52eaee643be4e591" + integrity sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w== + dependencies: + chevrotain "~11.0.3" + chevrotain-allstar "~0.3.0" + vscode-languageserver "~9.0.1" + vscode-languageserver-textdocument "~1.0.11" + vscode-uri "~3.0.8" + +layout-base@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-1.0.2.tgz#1291e296883c322a9dd4c5dd82063721b53e26e2" + integrity sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg== + +layout-base@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-2.0.1.tgz#d0337913586c90f9c2c075292069f5c2da5dd285" + integrity sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg== + +local-pkg@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.2.tgz#c03d208787126445303f8161619dc701afa4abb5" + integrity sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A== + dependencies: + mlly "^1.7.4" + pkg-types "^2.3.0" + quansync "^0.2.11" + +lodash-es@4.17.21, lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== longest-streak@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.0.1.tgz#c97315b7afa0e7d9525db9a5a2953651432bdc5d" - integrity sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4" + integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== loose-envify@^1.1.0: version "1.4.0" @@ -726,686 +1884,847 @@ loose-envify@^1.1.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -markdown-extensions@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-1.1.1.tgz#fea03b539faeaee9b4ef02a3769b455b189f7fc3" - integrity sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q== +markdown-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-2.0.0.tgz#34bebc83e9938cae16e0e017e4a9814a8330d3c4" + integrity sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q== markdown-table@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.2.tgz#9b59eb2c1b22fe71954a65ff512887065a7bb57c" - integrity sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA== + version "3.0.4" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.4.tgz#fe44d6d410ff9d6f2ea1797a3f60aa4d2b631c2a" + integrity sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw== -match-sorter@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda" - integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw== - dependencies: - "@babel/runtime" "^7.12.5" - remove-accents "0.4.2" +marked@^16.2.1: + version "16.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-16.3.0.tgz#2f513891f867d6edc4772b4a026db9cc331eb94f" + integrity sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w== -mdast-util-definitions@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz#2c1d684b28e53f84938bb06317944bee8efa79db" - integrity sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ== +mathjax-full@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/mathjax-full/-/mathjax-full-3.2.2.tgz#43f02e55219db393030985d2b6537ceae82f1fa7" + integrity sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w== dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" - unist-util-visit "^4.0.0" + esm "^3.2.25" + mhchemparser "^4.1.0" + mj-context-menu "^0.6.1" + speech-rule-engine "^4.0.6" -mdast-util-find-and-replace@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.1.tgz#249901ef43c5f41d6e8a8d446b3b63b17e592d7c" - integrity sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw== +mdast-util-find-and-replace@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz#70a3174c894e14df722abf43bc250cbae44b11df" + integrity sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg== dependencies: + "@types/mdast" "^4.0.0" escape-string-regexp "^5.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents "^5.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" -mdast-util-from-markdown@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz#84df2924ccc6c995dec1e2368b2b208ad0a76268" - integrity sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q== +mdast-util-from-markdown@^2.0.0, mdast-util-from-markdown@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz#4850390ca7cf17413a9b9a0fbefcd1bc0eb4160a" + integrity sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA== dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" decode-named-character-reference "^1.0.0" - mdast-util-to-string "^3.1.0" - micromark "^3.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-decode-string "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-stringify-position "^3.0.0" - uvu "^0.5.0" - -mdast-util-gfm-autolink-literal@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz#4032dcbaddaef7d4f2f3768ed830475bb22d3970" - integrity sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg== + devlop "^1.0.0" + mdast-util-to-string "^4.0.0" + micromark "^4.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-decode-string "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-stringify-position "^4.0.0" + +mdast-util-frontmatter@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz#f5f929eb1eb36c8a7737475c7eb438261f964ee8" + integrity sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA== dependencies: - "@types/mdast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + escape-string-regexp "^5.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + micromark-extension-frontmatter "^2.0.0" + +mdast-util-gfm-autolink-literal@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz#abd557630337bd30a6d5a4bd8252e1c2dc0875d5" + integrity sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ== + dependencies: + "@types/mdast" "^4.0.0" ccount "^2.0.0" - mdast-util-find-and-replace "^2.0.0" - micromark-util-character "^1.0.0" + devlop "^1.0.0" + mdast-util-find-and-replace "^3.0.0" + micromark-util-character "^2.0.0" -mdast-util-gfm-footnote@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.1.tgz#11d2d40a1a673a399c459e467fa85e00223191fe" - integrity sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw== +mdast-util-gfm-footnote@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz#7778e9d9ca3df7238cc2bd3fa2b1bf6a65b19403" + integrity sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" - micromark-util-normalize-identifier "^1.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.1.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" -mdast-util-gfm-strikethrough@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.1.tgz#a4a74c36864ec6a6e3bbd31e1977f29beb475789" - integrity sha512-zKJbEPe+JP6EUv0mZ0tQUyLQOC+FADt0bARldONot/nefuISkaZFlmVK4tU6JgfyZGrky02m/I6PmehgAgZgqg== +mdast-util-gfm-strikethrough@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz#d44ef9e8ed283ac8c1165ab0d0dfd058c2764c16" + integrity sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" + "@types/mdast" "^4.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm-table@^1.0.0: - version "1.0.6" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.6.tgz#184e900979fe790745fc3dabf77a4114595fcd7f" - integrity sha512-uHR+fqFq3IvB3Rd4+kzXW8dmpxUhvgCQZep6KdjsLK4O6meK5dYZEayLtIxNus1XO3gfjfcIFe8a7L0HZRGgag== +mdast-util-gfm-table@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz#7a435fb6223a72b0862b33afbd712b6dae878d38" + integrity sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg== dependencies: - "@types/mdast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" markdown-table "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.3.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm-task-list-item@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.1.tgz#6f35f09c6e2bcbe88af62fdea02ac199cc802c5c" - integrity sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA== +mdast-util-gfm-task-list-item@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz#e68095d2f8a4303ef24094ab642e1047b991a936" + integrity sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm@^2.0.0: +mdast-util-gfm@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz#2cdf63b92c2a331406b0fb0db4c077c1b0331751" + integrity sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ== + dependencies: + mdast-util-from-markdown "^2.0.0" + mdast-util-gfm-autolink-literal "^2.0.0" + mdast-util-gfm-footnote "^2.0.0" + mdast-util-gfm-strikethrough "^2.0.0" + mdast-util-gfm-table "^2.0.0" + mdast-util-gfm-task-list-item "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-math@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-math/-/mdast-util-math-3.0.0.tgz#8d79dd3baf8ab8ac781f62b8853768190b9a00b0" + integrity sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + longest-streak "^3.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.1.0" + unist-util-remove-position "^5.0.0" + +mdast-util-mdx-expression@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-2.0.1.tgz#16fcf70110ae689a06d77e8f4e346223b64a0ea6" - integrity sha512-42yHBbfWIFisaAfV1eixlabbsa6q7vHeSPY+cg+BBjX51M8xhgMacqH9g6TftB/9+YkcI0ooV4ncfrJslzm/RQ== - dependencies: - mdast-util-from-markdown "^1.0.0" - mdast-util-gfm-autolink-literal "^1.0.0" - mdast-util-gfm-footnote "^1.0.0" - mdast-util-gfm-strikethrough "^1.0.0" - mdast-util-gfm-table "^1.0.0" - mdast-util-gfm-task-list-item "^1.0.0" - mdast-util-to-markdown "^1.0.0" - -mdast-util-mdx-expression@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.0.tgz#fed063cc6320da1005c8e50338bb374d6dac69ba" - integrity sha512-9kTO13HaL/ChfzVCIEfDRdp1m5hsvsm6+R8yr67mH+KS2ikzZ0ISGLPTbTswOFpLLlgVHO9id3cul4ajutCvCA== + resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz#43f0abac9adc756e2086f63822a38c8d3c3a5096" + integrity sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ== dependencies: "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-mdx-jsx@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.0.tgz#029f5a9c38485dbb5cf482059557ee7d788f1947" - integrity sha512-KzgzfWMhdteDkrY4mQtyvTU5bc/W4ppxhe9SzelO6QUUiwLAM+Et2Dnjjprik74a336kHdo0zKm7Tp+n6FFeRg== +mdast-util-mdx-jsx@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz#fd04c67a2a7499efb905a8a5c578dddc9fdada0d" + integrity sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q== dependencies: "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" ccount "^2.0.0" - mdast-util-to-markdown "^1.3.0" + devlop "^1.1.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" parse-entities "^4.0.0" stringify-entities "^4.0.0" - unist-util-remove-position "^4.0.0" - unist-util-stringify-position "^3.0.0" - vfile-message "^3.0.0" + unist-util-stringify-position "^4.0.0" + vfile-message "^4.0.0" -mdast-util-mdx@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-mdx/-/mdast-util-mdx-2.0.0.tgz#dd4f6c993cf27da32725e50a04874f595b7b63fb" - integrity sha512-M09lW0CcBT1VrJUaF/PYxemxxHa7SLDHdSn94Q9FhxjCQfuW7nMAWKWimTmA3OyDMSTH981NN1csW1X+HPSluw== +mdast-util-mdx@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz#792f9cf0361b46bee1fdf1ef36beac424a099c41" + integrity sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w== dependencies: - mdast-util-mdx-expression "^1.0.0" - mdast-util-mdx-jsx "^2.0.0" - mdast-util-mdxjs-esm "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-mdxjs-esm@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.0.tgz#137345ef827169aeeeb6069277cd3e090830ce9a" - integrity sha512-7N5ihsOkAEGjFotIX9p/YPdl4TqUoMxL4ajNz7PbT89BqsdWJuBC9rvgt6wpbwTZqWWR0jKWqQbwsOWDBUZv4g== +mdast-util-mdxjs-esm@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz#019cfbe757ad62dd557db35a695e7314bcc9fa97" + integrity sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg== dependencies: "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.0.0" - -mdast-util-to-hast@^12.1.0: - version "12.2.2" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.2.2.tgz#2bd8cf985a67c90c181eadcfdd8d31b8798ed9a1" - integrity sha512-lVkUttV9wqmdXFtEBXKcepvU/zfwbhjbkM5rxrquLW55dS1DfOrnAXCk5mg1be1sfY/WfMmayGy1NsbK1GLCYQ== - dependencies: - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - "@types/mdurl" "^1.0.0" - mdast-util-definitions "^5.0.0" - mdurl "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + +mdast-util-phrasing@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz#7cc0a8dec30eaf04b7b1a9661a92adb3382aa6e3" + integrity sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w== + dependencies: + "@types/mdast" "^4.0.0" + unist-util-is "^6.0.0" + +mdast-util-to-hast@^13.0.0, mdast-util-to-hast@^13.2.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4" + integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@ungap/structured-clone" "^1.0.0" + devlop "^1.0.0" + micromark-util-sanitize-uri "^2.0.0" trim-lines "^3.0.0" - unist-builder "^3.0.0" - unist-util-generated "^2.0.0" - unist-util-position "^4.0.0" - unist-util-visit "^4.0.0" + unist-util-position "^5.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" -mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.3.0.tgz#38b6cdc8dc417de642a469c4fc2abdf8c931bd1e" - integrity sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA== +mdast-util-to-markdown@^2.0.0, mdast-util-to-markdown@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz#f910ffe60897f04bb4b7e7ee434486f76288361b" + integrity sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA== dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" longest-streak "^3.0.0" - mdast-util-to-string "^3.0.0" - micromark-util-decode-string "^1.0.0" - unist-util-visit "^4.0.0" + mdast-util-phrasing "^4.0.0" + mdast-util-to-string "^4.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-decode-string "^2.0.0" + unist-util-visit "^5.0.0" zwitch "^2.0.0" -mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9" - integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA== - -mdurl@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== +mdast-util-to-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814" + integrity sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg== + dependencies: + "@types/mdast" "^4.0.0" -micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz#edff4c72e5993d93724a3c206970f5a15b0585ad" - integrity sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA== +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mermaid@^11.0.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-11.12.0.tgz#8e394b6214e33cb52f6e8ad9eb1fd94c67ee5638" + integrity sha512-ZudVx73BwrMJfCFmSSJT84y6u5brEoV8DOItdHomNLz32uBjNrelm7mg95X7g+C6UoQH/W6mBLGDEDv73JdxBg== + dependencies: + "@braintree/sanitize-url" "^7.1.1" + "@iconify/utils" "^3.0.1" + "@mermaid-js/parser" "^0.6.2" + "@types/d3" "^7.4.3" + cytoscape "^3.29.3" + cytoscape-cose-bilkent "^4.1.0" + cytoscape-fcose "^2.2.0" + d3 "^7.9.0" + d3-sankey "^0.12.3" + dagre-d3-es "7.0.11" + dayjs "^1.11.18" + dompurify "^3.2.5" + katex "^0.16.22" + khroma "^2.1.0" + lodash-es "^4.17.21" + marked "^16.2.1" + roughjs "^4.6.6" + stylis "^4.3.6" + ts-dedent "^2.2.0" + uuid "^11.1.0" + +mhchemparser@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/mhchemparser/-/mhchemparser-4.2.1.tgz#d73982e66bc06170a85b1985600ee9dabe157cb0" + integrity sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ== + +micromark-core-commonmark@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz#c691630e485021a68cf28dbc2b2ca27ebf678cd4" + integrity sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg== dependencies: decode-named-character-reference "^1.0.0" - micromark-factory-destination "^1.0.0" - micromark-factory-label "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-factory-title "^1.0.0" - micromark-factory-whitespace "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-classify-character "^1.0.0" - micromark-util-html-tag-name "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - uvu "^0.5.0" - -micromark-extension-gfm-autolink-literal@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.3.tgz#dc589f9c37eaff31a175bab49f12290edcf96058" - integrity sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg== - dependencies: - micromark-util-character "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-extension-gfm-footnote@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.4.tgz#cbfd8873b983e820c494498c6dac0105920818d5" - integrity sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg== - dependencies: - micromark-core-commonmark "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-extension-gfm-strikethrough@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.4.tgz#162232c284ffbedd8c74e59c1525bda217295e18" - integrity sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ== - dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-classify-character "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-extension-gfm-table@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.5.tgz#7b708b728f8dc4d95d486b9e7a2262f9cddbcbb4" - integrity sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg== + devlop "^1.0.0" + micromark-factory-destination "^2.0.0" + micromark-factory-label "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-factory-title "^2.0.0" + micromark-factory-whitespace "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-html-tag-name "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-subtokenize "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-frontmatter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz#651c52ffa5d7a8eeed687c513cd869885882d67a" + integrity sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + fault "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-tagfilter@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.1.tgz#fb2e303f7daf616db428bb6a26e18fda14a90a4d" - integrity sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA== +micromark-extension-gfm-autolink-literal@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz#6286aee9686c4462c1e3552a9d505feddceeb935" + integrity sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw== dependencies: - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-task-list-item@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.3.tgz#7683641df5d4a09795f353574d7f7f66e47b7fc4" - integrity sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q== +micromark-extension-gfm-footnote@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz#4dab56d4e398b9853f6fe4efac4fc9361f3e0750" + integrity sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw== + dependencies: + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm-strikethrough@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz#86106df8b3a692b5f6a92280d3879be6be46d923" + integrity sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw== + dependencies: + devlop "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm-table@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz#fac70bcbf51fe65f5f44033118d39be8a9b5940b" + integrity sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg== + dependencies: + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm-tagfilter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz#f26d8a7807b5985fba13cf61465b58ca5ff7dc57" + integrity sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz#40f3209216127a96297c54c67f5edc7ef2d1a2a2" - integrity sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA== - dependencies: - micromark-extension-gfm-autolink-literal "^1.0.0" - micromark-extension-gfm-footnote "^1.0.0" - micromark-extension-gfm-strikethrough "^1.0.0" - micromark-extension-gfm-table "^1.0.0" - micromark-extension-gfm-tagfilter "^1.0.0" - micromark-extension-gfm-task-list-item "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-extension-mdx-expression@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.3.tgz#cd3843573921bf55afcfff4ae0cd2e857a16dcfa" - integrity sha512-TjYtjEMszWze51NJCZmhv7MEBcgYRgb3tJeMAJ+HQCAaZHHRBaDCccqQzGizR/H4ODefP44wRTgOn2vE5I6nZA== - dependencies: - micromark-factory-mdx-expression "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-extension-mdx-jsx@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.3.tgz#9f196be5f65eb09d2a49b237a7b3398bba2999be" - integrity sha512-VfA369RdqUISF0qGgv2FfV7gGjHDfn9+Qfiv5hEwpyr1xscRj/CiVRkU7rywGFCO7JwJ5L0e7CJz60lY52+qOA== +micromark-extension-gfm-task-list-item@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz#bcc34d805639829990ec175c3eea12bb5b781f2c" + integrity sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw== dependencies: - "@types/acorn" "^4.0.0" - estree-util-is-identifier-name "^2.0.0" - micromark-factory-mdx-expression "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - vfile-message "^3.0.0" - -micromark-extension-mdx-md@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.0.tgz#382f5df9ee3706dd120b51782a211f31f4760d22" - integrity sha512-xaRAMoSkKdqZXDAoSgp20Azm0aRQKGOl0RrS81yGu8Hr/JhMsBmfs4wR7m9kgVUIO36cMUQjNyiyDKPrsv8gOw== + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-gfm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz#3e13376ab95dd7a5cfd0e29560dfe999657b3c5b" + integrity sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w== + dependencies: + micromark-extension-gfm-autolink-literal "^2.0.0" + micromark-extension-gfm-footnote "^2.0.0" + micromark-extension-gfm-strikethrough "^2.0.0" + micromark-extension-gfm-table "^2.0.0" + micromark-extension-gfm-tagfilter "^2.0.0" + micromark-extension-gfm-task-list-item "^2.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-math@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz#c42ee3b1dd5a9a03584e83dd8f08e3de510212c1" + integrity sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg== + dependencies: + "@types/katex" "^0.16.0" + devlop "^1.0.0" + katex "^0.16.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-mdx-expression@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz#43d058d999532fb3041195a3c3c05c46fa84543b" + integrity sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + micromark-factory-mdx-expression "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-extension-mdx-jsx@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz#ffc98bdb649798902fa9fc5689f67f9c1c902044" + integrity sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + micromark-factory-mdx-expression "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + vfile-message "^4.0.0" + +micromark-extension-mdx-md@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz#1d252881ea35d74698423ab44917e1f5b197b92d" + integrity sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ== dependencies: - micromark-util-types "^1.0.0" + micromark-util-types "^2.0.0" -micromark-extension-mdxjs-esm@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.3.tgz#630d9dc9db2c2fd470cac8c1e7a824851267404d" - integrity sha512-2N13ol4KMoxb85rdDwTAC6uzs8lMX0zeqpcyx7FhS7PxXomOnLactu8WI8iBNXW8AVyea3KIJd/1CKnUmwrK9A== - dependencies: - micromark-core-commonmark "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-position-from-estree "^1.1.0" - uvu "^0.5.0" - vfile-message "^3.0.0" - -micromark-extension-mdxjs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.0.tgz#772644e12fc8299a33e50f59c5aa15727f6689dd" - integrity sha512-TZZRZgeHvtgm+IhtgC2+uDMR7h8eTKF0QUX9YsgoL9+bADBpBY6SiLvWqnBlLbCEevITmTqmEuY3FoxMKVs1rQ== +micromark-extension-mdxjs-esm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz#de21b2b045fd2059bd00d36746081de38390d54a" + integrity sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-position-from-estree "^2.0.0" + vfile-message "^4.0.0" + +micromark-extension-mdxjs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz#b5a2e0ed449288f3f6f6c544358159557549de18" + integrity sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ== dependencies: acorn "^8.0.0" acorn-jsx "^5.0.0" - micromark-extension-mdx-expression "^1.0.0" - micromark-extension-mdx-jsx "^1.0.0" - micromark-extension-mdx-md "^1.0.0" - micromark-extension-mdxjs-esm "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-factory-destination@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e" - integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw== + micromark-extension-mdx-expression "^3.0.0" + micromark-extension-mdx-jsx "^3.0.0" + micromark-extension-mdx-md "^2.0.0" + micromark-extension-mdxjs-esm "^3.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-factory-destination@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz#8fef8e0f7081f0474fbdd92deb50c990a0264639" + integrity sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-factory-label@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz#5267efa97f1e5254efc7f20b459a38cb21058ba1" + integrity sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg== dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + devlop "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-label@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz#6be2551fa8d13542fcbbac478258fb7a20047137" - integrity sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg== - dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-factory-mdx-expression@^1.0.0: - version "1.0.6" - resolved "https://registry.yarnpkg.com/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.6.tgz#917e17d16e6e9c2551f3a862e6a9ebdd22056476" - integrity sha512-WRQIc78FV7KrCfjsEf/sETopbYjElh3xAmNpLkd1ODPqxEngP42eVRGbiPEQWpRV27LzqW+XVTvQAMIIRLPnNA== - dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-position-from-estree "^1.0.0" - uvu "^0.5.0" - vfile-message "^3.0.0" - -micromark-factory-space@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633" - integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew== +micromark-factory-mdx-expression@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz#bb09988610589c07d1c1e4425285895041b3dfa9" + integrity sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ== dependencies: - micromark-util-character "^1.0.0" - micromark-util-types "^1.0.0" + "@types/estree" "^1.0.0" + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-position-from-estree "^2.0.0" + vfile-message "^4.0.0" + +micromark-factory-space@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz#36d0212e962b2b3121f8525fc7a3c7c029f334fc" + integrity sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-title@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz#7e09287c3748ff1693930f176e1c4a328382494f" - integrity sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A== +micromark-factory-title@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz#237e4aa5d58a95863f01032d9ee9b090f1de6e94" + integrity sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-whitespace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c" - integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A== +micromark-factory-whitespace@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz#06b26b2983c4d27bfcc657b33e25134d4868b0b1" + integrity sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-character@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86" - integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg== +micromark-util-character@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz#2f987831a40d4c510ac261e89852c4e9703ccda6" + integrity sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q== dependencies: - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-chunked@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06" - integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g== +micromark-util-chunked@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz#47fbcd93471a3fccab86cff03847fc3552db1051" + integrity sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-classify-character@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20" - integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA== +micromark-util-classify-character@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz#d399faf9c45ca14c8b4be98b1ea481bced87b629" + integrity sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q== dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-combine-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5" - integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA== +micromark-util-combine-extensions@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz#2a0f490ab08bff5cc2fd5eec6dd0ca04f89b30a9" + integrity sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg== dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-decode-numeric-character-reference@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946" - integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w== +micromark-util-decode-numeric-character-reference@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz#fcf15b660979388e6f118cdb6bf7d79d73d26fe5" + integrity sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-decode-string@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz#942252ab7a76dec2dbf089cc32505ee2bc3acf02" - integrity sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q== +micromark-util-decode-string@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz#6cb99582e5d271e84efca8e61a807994d7161eb2" + integrity sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ== dependencies: decode-named-character-reference "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-symbol "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-encode@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383" - integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA== +micromark-util-encode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz#0d51d1c095551cfaac368326963cf55f15f540b8" + integrity sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw== -micromark-util-events-to-acorn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.0.tgz#65785cb77299d791bfefdc6a5213ab57ceead115" - integrity sha512-WWp3bf7xT9MppNuw3yPjpnOxa8cj5ACivEzXJKu0WwnjBYfzaBvIAT9KfeyI0Qkll+bfQtfftSwdgTH6QhTOKw== +micromark-util-events-to-acorn@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz#e7a8a6b55a47e5a06c720d5a1c4abae8c37c98f3" + integrity sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg== dependencies: - "@types/acorn" "^4.0.0" "@types/estree" "^1.0.0" - estree-util-visit "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - vfile-location "^4.0.0" - vfile-message "^3.0.0" - -micromark-util-html-tag-name@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz#eb227118befd51f48858e879b7a419fc0df20497" - integrity sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA== + "@types/unist" "^3.0.0" + devlop "^1.0.0" + estree-util-visit "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + vfile-message "^4.0.0" + +micromark-util-html-tag-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz#e40403096481986b41c106627f98f72d4d10b825" + integrity sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA== -micromark-util-normalize-identifier@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828" - integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg== +micromark-util-normalize-identifier@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz#c30d77b2e832acf6526f8bf1aa47bc9c9438c16d" + integrity sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-resolve-all@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88" - integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw== +micromark-util-resolve-all@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz#e1a2d62cdd237230a2ae11839027b19381e31e8b" + integrity sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg== dependencies: - micromark-util-types "^1.0.0" + micromark-util-types "^2.0.0" -micromark-util-sanitize-uri@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz#27dc875397cd15102274c6c6da5585d34d4f12b2" - integrity sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg== +micromark-util-sanitize-uri@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz#ab89789b818a58752b73d6b55238621b7faa8fd7" + integrity sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ== dependencies: - micromark-util-character "^1.0.0" - micromark-util-encode "^1.0.0" - micromark-util-symbol "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-encode "^2.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-subtokenize@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105" - integrity sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA== +micromark-util-subtokenize@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz#d8ade5ba0f3197a1cf6a2999fbbfe6357a1a19ee" + integrity sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA== dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-symbol@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz#b90344db62042ce454f351cf0bebcc0a6da4920e" - integrity sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ== +micromark-util-symbol@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz#e5da494e8eb2b071a0d08fb34f6cefec6c0a19b8" + integrity sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q== -micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.0.2.tgz#f4220fdb319205812f99c40f8c87a9be83eded20" - integrity sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w== +micromark-util-types@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.2.tgz#f00225f5f5a0ebc3254f96c36b6605c4b393908e" + integrity sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA== -micromark@^3.0.0: - version "3.0.10" - resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.0.10.tgz#1eac156f0399d42736458a14b0ca2d86190b457c" - integrity sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg== +micromark@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-4.0.2.tgz#91395a3e1884a198e62116e33c9c568e39936fdb" + integrity sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA== dependencies: "@types/debug" "^4.0.0" debug "^4.0.0" decode-named-character-reference "^1.0.0" - micromark-core-commonmark "^1.0.1" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-encode "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - uvu "^0.5.0" - -mri@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" - integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-encode "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-subtokenize "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mj-context-menu@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz#a043c5282bf7e1cf3821de07b13525ca6f85aa69" + integrity sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA== -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +mlly@^1.7.4: + version "1.8.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e" + integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g== + dependencies: + acorn "^8.15.0" + pathe "^2.0.3" + pkg-types "^1.3.1" + ufo "^1.6.1" -next-themes@^0.2.0-beta.2: - version "0.2.1" - resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.2.1.tgz#0c9f128e847979daf6c67f70b38e6b6567856e45" - integrity sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A== +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -next@^12.3.1: - version "12.3.1" - resolved "https://registry.yarnpkg.com/next/-/next-12.3.1.tgz#127b825ad2207faf869b33393ec8c75fe61e50f1" - integrity sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw== - dependencies: - "@next/env" "12.3.1" - "@swc/helpers" "0.4.11" +nanoid@^3.3.6: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +negotiator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== + +next-themes@^0.4.0: + version "0.4.6" + resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.4.6.tgz#8d7e92d03b8fea6582892a50a928c9b23502e8b6" + integrity sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA== + +next@^13.5.11: + version "13.5.11" + resolved "https://registry.yarnpkg.com/next/-/next-13.5.11.tgz#a021e849c5748fb6e2a4447585614e0c0e6c778d" + integrity sha512-WUPJ6WbAX9tdC86kGTu92qkrRdgRqVrY++nwM+shmWQwmyxt4zhZfR59moXSI4N8GDYCBY3lIAqhzjDd4rTC8Q== + dependencies: + "@next/env" "13.5.11" + "@swc/helpers" "0.5.2" + busboy "1.6.0" caniuse-lite "^1.0.30001406" - postcss "8.4.14" - styled-jsx "5.0.7" - use-sync-external-store "1.2.0" + postcss "8.4.31" + styled-jsx "5.1.1" + watchpack "2.4.0" optionalDependencies: - "@next/swc-android-arm-eabi" "12.3.1" - "@next/swc-android-arm64" "12.3.1" - "@next/swc-darwin-arm64" "12.3.1" - "@next/swc-darwin-x64" "12.3.1" - "@next/swc-freebsd-x64" "12.3.1" - "@next/swc-linux-arm-gnueabihf" "12.3.1" - "@next/swc-linux-arm64-gnu" "12.3.1" - "@next/swc-linux-arm64-musl" "12.3.1" - "@next/swc-linux-x64-gnu" "12.3.1" - "@next/swc-linux-x64-musl" "12.3.1" - "@next/swc-win32-arm64-msvc" "12.3.1" - "@next/swc-win32-ia32-msvc" "12.3.1" - "@next/swc-win32-x64-msvc" "12.3.1" - -nextra-theme-docs@2.0.0-beta.29: - version "2.0.0-beta.29" - resolved "https://registry.yarnpkg.com/nextra-theme-docs/-/nextra-theme-docs-2.0.0-beta.29.tgz#febfaaee75bbe8bd0df744a4da5739c7b9594a8c" - integrity sha512-2oGsuOv7sMxnsYPM6+qI7F0Rcq9cMTtClwa8MeOdn0FCtMjhxJjfeLxpDvXrELkVNOU9/Bg1SFHxHTLpt0/Xjw== - dependencies: - "@headlessui/react" "^1.6.6" - "@mdx-js/react" "^2.1.2" - "@popperjs/core" "^2.11.6" - "@reach/skip-nav" "^0.17.0" - clsx "^1.2.1" - flexsearch "^0.7.21" - focus-visible "^5.2.0" - github-slugger "^1.4.0" - intersection-observer "^0.12.2" - match-sorter "^6.3.1" - next-themes "^0.2.0-beta.2" - parse-git-url "^1.0.1" - scroll-into-view-if-needed "^2.2.29" - -nextra@2.0.0-beta.29: - version "2.0.0-beta.29" - resolved "https://registry.yarnpkg.com/nextra/-/nextra-2.0.0-beta.29.tgz#128383f84e8bcf8826a2f2ad594db945268fcb0e" - integrity sha512-UjsaoMNsJRG0fbzqgoLDXgvJwcSJxwPr+ojBBjJsaZ6fu5+cwbCx8wXazA0y5sSxGw75fG6D1I7rS6pflHctuQ== - dependencies: - "@mdx-js/mdx" "^2.1.3" - "@napi-rs/simple-git" "^0.1.8" - github-slugger "^1.4.0" - graceful-fs "^4.2.10" + "@next/swc-darwin-arm64" "13.5.9" + "@next/swc-darwin-x64" "13.5.9" + "@next/swc-linux-arm64-gnu" "13.5.9" + "@next/swc-linux-arm64-musl" "13.5.9" + "@next/swc-linux-x64-gnu" "13.5.9" + "@next/swc-linux-x64-musl" "13.5.9" + "@next/swc-win32-arm64-msvc" "13.5.9" + "@next/swc-win32-ia32-msvc" "13.5.9" + "@next/swc-win32-x64-msvc" "13.5.9" + +nextra-theme-docs@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nextra-theme-docs/-/nextra-theme-docs-3.3.1.tgz#af845b49d0773e9cf3b40b8749b09877d6f6f2cd" + integrity sha512-P305m2UcW2IDyQhjrcAu0qpdPArikofinABslUCAyixYShsmcdDRUhIMd4QBHYru4gQuVjGWX9PhWZZCbNvzDQ== + dependencies: + "@headlessui/react" "^2.1.2" + clsx "^2.0.0" + escape-string-regexp "^5.0.0" + flexsearch "^0.7.43" + next-themes "^0.4.0" + scroll-into-view-if-needed "^3.1.0" + zod "^3.22.3" + +nextra@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nextra/-/nextra-3.3.1.tgz#d8c919954ba5e82c535efe5c18b32b0281dbeefd" + integrity sha512-jiwj+LfUPHHeAxJAEqFuglxnbjFgzAOnDWFsjv7iv3BWiX8OksDwd3I2Sv3j2zba00iIBDEPdNeylfzTtTLZVg== + dependencies: + "@formatjs/intl-localematcher" "^0.5.4" + "@headlessui/react" "^2.1.2" + "@mdx-js/mdx" "^3.0.0" + "@mdx-js/react" "^3.0.0" + "@napi-rs/simple-git" "^0.1.9" + "@shikijs/twoslash" "^1.0.0" + "@theguild/remark-mermaid" "^0.1.3" + "@theguild/remark-npm2yarn" "^0.3.2" + better-react-mathjax "^2.0.3" + clsx "^2.0.0" + estree-util-to-js "^2.0.0" + estree-util-value-to-estree "^3.0.1" + github-slugger "^2.0.0" + graceful-fs "^4.2.11" gray-matter "^4.0.3" - rehype-mdx-title "^1.0.0" - rehype-pretty-code "0.2.4" - remark-gfm "^3.0.1" + hast-util-to-estree "^3.1.0" + katex "^0.16.9" + mdast-util-from-markdown "^2.0.1" + mdast-util-gfm "^3.0.0" + mdast-util-to-hast "^13.2.0" + negotiator "^1.0.0" + p-limit "^6.0.0" + react-medium-image-zoom "^5.2.12" + rehype-katex "^7.0.0" + rehype-pretty-code "0.14.0" + rehype-raw "^7.0.0" + remark-frontmatter "^5.0.0" + remark-gfm "^4.0.0" + remark-math "^6.0.0" remark-reading-time "^2.0.1" - shiki "0.10.1" - slash "^3.0.0" - title "^3.5.3" - unist-util-visit "^4.1.1" + remark-smartypants "^3.0.0" + shiki "^1.0.0" + slash "^5.1.0" + title "^4.0.0" + unist-util-remove "^4.0.0" + unist-util-visit "^5.0.0" + yaml "^2.3.2" + zod "^3.22.3" + zod-validation-error "^3.0.0" + +nlcst-to-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz#05511e8461ebfb415952eb0b7e9a1a7d40471bd4" + integrity sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA== + dependencies: + "@types/nlcst" "^2.0.0" -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== +npm-run-path@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" + integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== dependencies: - path-key "^2.0.0" + path-key "^4.0.0" -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +npm-to-yarn@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-to-yarn/-/npm-to-yarn-3.0.1.tgz#d1ed47551321ad5cd51342729fe21c8146644529" + integrity sha512-tt6PvKu4WyzPwWUzy/hvPFqn+uwXO0K1ZHka8az3NnrhWJDmSqI8ncWq0fkL0k/lmmi5tAC11FXwXuh0rFbt1A== -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +oniguruma-to-es@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-2.3.0.tgz#35ea9104649b7c05f3963c6b3b474d964625028b" + integrity sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g== + dependencies: + emoji-regex-xs "^1.0.0" + regex "^5.1.1" + regex-recursion "^5.1.1" + +p-limit@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-6.2.0.tgz#c254d22ba6aeef441a3564c5e6c2f2da59268a0f" + integrity sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA== + dependencies: + yocto-queue "^1.1.1" + +package-manager-detector@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-1.3.0.tgz#b42d641c448826e03c2b354272456a771ce453c0" + integrity sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ== parse-entities@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.0.tgz#f67c856d4e3fe19b1a445c3fabe78dcdc1053eeb" - integrity sha512-5nk9Fn03x3rEhGaX1FU6IDwG/k+GxLXlFAkgrbM1asuAFl3BhdQWvASaIsmwWypRNcZKHPYnIuOSfIWEyEQnPQ== + version "4.0.2" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.2.tgz#61d46f5ed28e4ee62e9ddc43d6b010188443f159" + integrity sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw== dependencies: "@types/unist" "^2.0.0" - character-entities "^2.0.0" character-entities-legacy "^3.0.0" character-reference-invalid "^2.0.0" decode-named-character-reference "^1.0.0" @@ -1413,169 +2732,412 @@ parse-entities@^4.0.0: is-decimal "^2.0.0" is-hexadecimal "^2.0.0" -parse-git-url@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-git-url/-/parse-git-url-1.0.1.tgz#92bdaf615a7e24d32bea3bf955ee90a9050aeb57" - integrity sha512-Zukjztu09UXpXV/Q+4vgwyVPzUBkUvDjlqHlpG+swv/zYzed/5Igw/33rIEJxFDRc5LxvEqYDVDzhBfnOLWDYw== +parse-latin@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse-latin/-/parse-latin-7.0.0.tgz#8dfacac26fa603f76417f36233fc45602a323e1d" + integrity sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ== + dependencies: + "@types/nlcst" "^2.0.0" + "@types/unist" "^3.0.0" + nlcst-to-string "^4.0.0" + unist-util-modify-children "^4.0.0" + unist-util-visit-children "^3.0.0" + vfile "^6.0.0" parse-numeric-range@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== -path-key@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - -periscopic@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/periscopic/-/periscopic-3.0.4.tgz#b3fbed0d1bc844976b977173ca2cd4a0ef4fa8d1" - integrity sha512-SFx68DxCv0Iyo6APZuw/AKewkkThGwssmU0QWtTlvov3VAtPX+QJ4CadwSaz8nrT5jPIuxdvJWB4PnD2KNDxQg== +parse5@^7.0.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" + integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw== dependencies: - estree-walker "^3.0.0" - is-reference "^3.0.0" + entities "^6.0.0" + +path-data-parser@0.1.0, path-data-parser@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/path-data-parser/-/path-data-parser-0.1.0.tgz#8f5ba5cc70fc7becb3dcefaea08e2659aba60b8c" + integrity sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +pathe@^2.0.1, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +pkg-types@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +pkg-types@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-2.3.0.tgz#037f2c19bd5402966ff6810e32706558cb5b5726" + integrity sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig== + dependencies: + confbox "^0.2.2" + exsolve "^1.0.7" + pathe "^2.0.3" + +points-on-curve@0.2.0, points-on-curve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/points-on-curve/-/points-on-curve-0.2.0.tgz#7dbb98c43791859434284761330fa893cb81b4d1" + integrity sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A== + +points-on-path@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/points-on-path/-/points-on-path-0.2.1.tgz#553202b5424c53bed37135b318858eacff85dd52" + integrity sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g== + dependencies: + path-data-parser "0.1.0" + points-on-curve "0.2.0" -postcss@8.4.14: - version "8.4.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" - integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== +postcss@8.4.31: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== dependencies: - nanoid "^3.3.4" + nanoid "^3.3.6" picocolors "^1.0.0" source-map-js "^1.0.2" property-information@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22" - integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w== + version "6.5.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" + integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== +property-information@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.1.0.tgz#b622e8646e02b580205415586b40804d3e8bfd5d" + integrity sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ== -react-dom@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== +quansync@^0.2.11: + version "0.2.11" + resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.11.tgz#f9c3adda2e1272e4f8cf3f1457b04cbdb4ee692a" + integrity sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA== + +react-dom@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" + scheduler "^0.23.2" + +react-medium-image-zoom@^5.2.12: + version "5.4.0" + resolved "https://registry.yarnpkg.com/react-medium-image-zoom/-/react-medium-image-zoom-5.4.0.tgz#b89c74a4f631289e8a7a21af26614c58fff0ea81" + integrity sha512-BsE+EnFVQzFIlyuuQrZ9iTwyKpKkqdFZV1ImEQN573QPqGrIUuNni7aF+sZwDcxlsuOMayCr6oO/PZR/yJnbRg== -react@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== +react@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" reading-time@^1.3.0: version "1.5.0" resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +recma-build-jsx@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz#c02f29e047e103d2fab2054954e1761b8ea253c4" + integrity sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew== + dependencies: + "@types/estree" "^1.0.0" + estree-util-build-jsx "^3.0.0" + vfile "^6.0.0" + +recma-jsx@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/recma-jsx/-/recma-jsx-1.0.1.tgz#58e718f45e2102ed0bf2fa994f05b70d76801a1a" + integrity sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w== + dependencies: + acorn-jsx "^5.0.0" + estree-util-to-js "^2.0.0" + recma-parse "^1.0.0" + recma-stringify "^1.0.0" + unified "^11.0.0" + +recma-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/recma-parse/-/recma-parse-1.0.0.tgz#c351e161bb0ab47d86b92a98a9d891f9b6814b52" + integrity sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ== + dependencies: + "@types/estree" "^1.0.0" + esast-util-from-js "^2.0.0" + unified "^11.0.0" + vfile "^6.0.0" -rehype-mdx-title@^1.0.0: +recma-stringify@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/rehype-mdx-title/-/rehype-mdx-title-1.0.0.tgz#292598b5ad8af2c2bd01b3674caea1a44bb60f63" - integrity sha512-5B/53Y+KQHm4/nrE6pIIPc9Ie2fbPMCLs8WwMGYWWHr+5g3TkmEijRkr8TGYHULtc+C7bOoPR8LIF5DpGROIDg== + resolved "https://registry.yarnpkg.com/recma-stringify/-/recma-stringify-1.0.0.tgz#54632030631e0c7546136ff9ef8fde8e7b44f130" + integrity sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g== dependencies: - estree-util-is-identifier-name "^1.1.0" - hast-util-to-string "^1.0.4" - unist-util-visit "^2.0.3" + "@types/estree" "^1.0.0" + estree-util-to-js "^2.0.0" + unified "^11.0.0" + vfile "^6.0.0" -rehype-pretty-code@0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/rehype-pretty-code/-/rehype-pretty-code-0.2.4.tgz#73b1e1c3ca7f50aaeeb131185a744a5ea936a08f" - integrity sha512-vbqwIa4cNwRaVur9caUw/b0jOQR88Svrs9c9RaQoogvbBxs5X9bWrSe5oFypaRTTq2cpZ45YzJQ7UUPO76LMKA== +regex-recursion@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/regex-recursion/-/regex-recursion-5.1.1.tgz#5a73772d18adbf00f57ad097bf54171b39d78f8b" + integrity sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w== dependencies: + regex "^5.1.1" + regex-utilities "^2.3.0" + +regex-utilities@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/regex-utilities/-/regex-utilities-2.3.0.tgz#87163512a15dce2908cf079c8960d5158ff43280" + integrity sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng== + +regex@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/regex/-/regex-5.1.1.tgz#cf798903f24d6fe6e531050a36686e082b29bd03" + integrity sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw== + dependencies: + regex-utilities "^2.3.0" + +rehype-katex@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-7.0.1.tgz#832e6d7af2744a228981d1b0fe89483a9e7c93a1" + integrity sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA== + dependencies: + "@types/hast" "^3.0.0" + "@types/katex" "^0.16.0" + hast-util-from-html-isomorphic "^2.0.0" + hast-util-to-text "^4.0.0" + katex "^0.16.0" + unist-util-visit-parents "^6.0.0" + vfile "^6.0.0" + +rehype-parse@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-9.0.1.tgz#9993bda129acc64c417a9d3654a7be38b2a94c20" + integrity sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag== + dependencies: + "@types/hast" "^3.0.0" + hast-util-from-html "^2.0.0" + unified "^11.0.0" + +rehype-pretty-code@0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/rehype-pretty-code/-/rehype-pretty-code-0.14.0.tgz#bdf828af4575737cc02204fb24d8097e6f010d37" + integrity sha512-hBeKF/Wkkf3zyUS8lal9RCUuhypDWLQc+h9UrP9Pav25FUm/AQAVh4m5gdvJxh4Oz+U+xKvdsV01p1LdvsZTiQ== + dependencies: + "@types/hast" "^3.0.4" + hast-util-to-string "^3.0.0" parse-numeric-range "^1.3.0" + rehype-parse "^9.0.0" + unified "^11.0.5" + unist-util-visit "^5.0.0" -remark-gfm@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-3.0.1.tgz#0b180f095e3036545e9dddac0e8df3fa5cfee54f" - integrity sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig== +rehype-raw@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/rehype-raw/-/rehype-raw-7.0.0.tgz#59d7348fd5dbef3807bbaa1d443efd2dd85ecee4" + integrity sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-gfm "^2.0.0" - micromark-extension-gfm "^2.0.0" - unified "^10.0.0" + "@types/hast" "^3.0.0" + hast-util-raw "^9.0.0" + vfile "^6.0.0" -remark-mdx@^2.0.0: - version "2.1.3" - resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-2.1.3.tgz#6273e8b94d27ade35407a63bc8cdd04592f7be9f" - integrity sha512-3SmtXOy9+jIaVctL8Cs3VAQInjRLGOwNXfrBB9KCT+EpJpKD3PQiy0x8hUNGyjQmdyOs40BqgPU7kYtH9uoR6w== +rehype-recma@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rehype-recma/-/rehype-recma-1.0.0.tgz#d68ef6344d05916bd96e25400c6261775411aa76" + integrity sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw== + dependencies: + "@types/estree" "^1.0.0" + "@types/hast" "^3.0.0" + hast-util-to-estree "^3.0.0" + +remark-frontmatter@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz#b68d61552a421ec412c76f4f66c344627dc187a2" + integrity sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-frontmatter "^2.0.0" + micromark-extension-frontmatter "^2.0.0" + unified "^11.0.0" + +remark-gfm@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-4.0.1.tgz#33227b2a74397670d357bf05c098eaf8513f0d6b" + integrity sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-gfm "^3.0.0" + micromark-extension-gfm "^3.0.0" + remark-parse "^11.0.0" + remark-stringify "^11.0.0" + unified "^11.0.0" + +remark-math@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/remark-math/-/remark-math-6.0.0.tgz#0acdf74675f1c195fea6efffa78582f7ed7fc0d7" + integrity sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-math "^3.0.0" + micromark-extension-math "^3.0.0" + unified "^11.0.0" + +remark-mdx@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-3.1.1.tgz#047f97038bc7ec387aebb4b0a4fe23779999d845" + integrity sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg== dependencies: - mdast-util-mdx "^2.0.0" - micromark-extension-mdxjs "^1.0.0" + mdast-util-mdx "^3.0.0" + micromark-extension-mdxjs "^3.0.0" -remark-parse@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775" - integrity sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw== +remark-parse@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-11.0.0.tgz#aa60743fcb37ebf6b069204eb4da304e40db45a1" + integrity sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-from-markdown "^2.0.0" + micromark-util-types "^2.0.0" + unified "^11.0.0" remark-reading-time@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/remark-reading-time/-/remark-reading-time-2.0.1.tgz#fe8bb8e420db7678dc749385167adb4fc99318f7" - integrity sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw== + version "2.0.2" + resolved "https://registry.yarnpkg.com/remark-reading-time/-/remark-reading-time-2.0.2.tgz#394ec979ae3acf45655fa10fcf15078e806de694" + integrity sha512-ILjIuR0dQQ8pELPgaFvz7ralcSN62rD/L1pTUJgWb4gfua3ZwYEI8mnKGxEQCbrXSUF/OvycTkcUbifGOtOn5A== dependencies: estree-util-is-identifier-name "^2.0.0" - estree-util-value-to-estree "^1.3.0" + estree-util-value-to-estree "^3.3.3" reading-time "^1.3.0" unist-util-visit "^3.1.0" -remark-rehype@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279" - integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw== +remark-rehype@^11.0.0: + version "11.1.2" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.2.tgz#2addaadda80ca9bd9aa0da763e74d16327683b37" + integrity sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + mdast-util-to-hast "^13.0.0" + unified "^11.0.0" + vfile "^6.0.0" + +remark-smartypants@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/remark-smartypants/-/remark-smartypants-3.0.2.tgz#cbaf2b39624c78fcbd6efa224678c1d2e9bc1dfb" + integrity sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA== + dependencies: + retext "^9.0.0" + retext-smartypants "^6.0.0" + unified "^11.0.4" + unist-util-visit "^5.0.0" + +remark-stringify@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-11.0.0.tgz#4c5b01dd711c269df1aaae11743eb7e2e7636fd3" + integrity sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-to-markdown "^2.0.0" + unified "^11.0.0" + +retext-latin@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/retext-latin/-/retext-latin-4.0.0.tgz#d02498aa1fd39f1bf00e2ff59b1384c05d0c7ce3" + integrity sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA== + dependencies: + "@types/nlcst" "^2.0.0" + parse-latin "^7.0.0" + unified "^11.0.0" + +retext-smartypants@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/retext-smartypants/-/retext-smartypants-6.2.0.tgz#4e852c2974cf2cfa253eeec427c97efc43b5d158" + integrity sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ== + dependencies: + "@types/nlcst" "^2.0.0" + nlcst-to-string "^4.0.0" + unist-util-visit "^5.0.0" + +retext-stringify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/retext-stringify/-/retext-stringify-4.0.0.tgz#501d5440bd4d121e351c7c509f8507de9611e159" + integrity sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA== + dependencies: + "@types/nlcst" "^2.0.0" + nlcst-to-string "^4.0.0" + unified "^11.0.0" + +retext@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/retext/-/retext-9.0.0.tgz#ab5cd72836894167b0ca6ae70fdcfaa166267f7a" + integrity sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA== dependencies: - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-to-hast "^12.1.0" - unified "^10.0.0" + "@types/nlcst" "^2.0.0" + retext-latin "^4.0.0" + retext-stringify "^4.0.0" + unified "^11.0.0" -remove-accents@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" - integrity sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA== +robust-predicates@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== -sade@^1.7.3: - version "1.8.1" - resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" - integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== +roughjs@^4.6.6: + version "4.6.6" + resolved "https://registry.yarnpkg.com/roughjs/-/roughjs-4.6.6.tgz#1059f49a5e0c80dee541a005b20cc322b222158b" + integrity sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ== dependencies: - mri "^1.1.0" + hachure-fill "^0.5.2" + path-data-parser "^0.1.0" + points-on-curve "^0.2.0" + points-on-path "^0.2.1" + +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== -scheduler@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" - integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" -scroll-into-view-if-needed@^2.2.29: - version "2.2.29" - resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885" - integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg== +scroll-into-view-if-needed@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz#fa9524518c799b45a2ef6bbffb92bcad0296d01f" + integrity sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ== dependencies: - compute-scroll-into-view "^1.0.17" + compute-scroll-into-view "^3.0.2" section-matter@^1.0.0: version "1.0.0" @@ -1585,61 +3147,80 @@ section-matter@^1.0.0: extend-shallow "^2.0.1" kind-of "^6.0.0" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - -shiki@0.10.1: - version "0.10.1" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.10.1.tgz#6f9a16205a823b56c072d0f1a0bcd0f2646bef14" - integrity sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng== +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: - jsonc-parser "^3.0.0" - vscode-oniguruma "^1.6.1" - vscode-textmate "5.2.0" - -signal-exit@^3.0.0: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + shebang-regex "^3.0.0" -slash@^3.0.0: +shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shiki@^1.0.0: + version "1.29.2" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.29.2.tgz#5c93771f2d5305ce9c05975c33689116a27dc657" + integrity sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg== + dependencies: + "@shikijs/core" "1.29.2" + "@shikijs/engine-javascript" "1.29.2" + "@shikijs/engine-oniguruma" "1.29.2" + "@shikijs/langs" "1.29.2" + "@shikijs/themes" "1.29.2" + "@shikijs/types" "1.29.2" + "@shikijs/vscode-textmate" "^10.0.1" + "@types/hast" "^3.0.4" + +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +slash@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" + integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== source-map@^0.7.0: - version "0.7.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" - integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + version "0.7.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.6.tgz#a3658ab87e5b6429c8a1f3ba0083d4c61ca3ef02" + integrity sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ== space-separated-tokens@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz#43193cec4fb858a2ce934b7f98b7f2c18107098b" - integrity sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw== + version "2.0.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== + +speech-rule-engine@^4.0.6: + version "4.1.2" + resolved "https://registry.yarnpkg.com/speech-rule-engine/-/speech-rule-engine-4.1.2.tgz#3b31b5813a2fc2eaecdfda26ad29c32599e9a537" + integrity sha512-S6ji+flMEga+1QU79NDbwZ8Ivf0S/MpupQQiIC0rTpU/ZTKgcajijJJb1OcByBQDjrXCN1/DJtGz4ZJeBMPGJw== + dependencies: + "@xmldom/xmldom" "0.9.8" + commander "13.1.0" + wicked-good-xpath "1.3.0" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + stringify-entities@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.3.tgz#cfabd7039d22ad30f3cc435b0ca2c1574fc88ef8" - integrity sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g== + version "4.0.4" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" + integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== dependencies: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" @@ -1649,49 +3230,60 @@ strip-bom-string@^1.0.0: resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g== -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== -style-to-object@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" - integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== +style-to-js@^1.0.0: + version "1.1.17" + resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.17.tgz#488b1558a8c1fd05352943f088cc3ce376813d83" + integrity sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA== dependencies: - inline-style-parser "0.1.1" + style-to-object "1.0.9" -styled-jsx@5.0.7: - version "5.0.7" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.7.tgz#be44afc53771b983769ac654d355ca8d019dff48" - integrity sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA== +style-to-object@1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.9.tgz#35c65b713f4a6dba22d3d0c61435f965423653f0" + integrity sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw== + dependencies: + inline-style-parser "0.2.4" -supports-color@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - integrity sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw== +styled-jsx@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" + integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== dependencies: - has-flag "^2.0.0" + client-only "0.0.1" -tiny-warning@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +stylis@^4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.6.tgz#7c7b97191cb4f195f03ecab7d52f7902ed378320" + integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ== -title@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/title/-/title-3.5.3.tgz#b338d701a3d949db6b49b2c86f409f9c2f36cd91" - integrity sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q== - dependencies: - arg "1.0.0" - chalk "2.3.0" - clipboardy "1.2.2" - titleize "1.0.0" +system-architecture@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/system-architecture/-/system-architecture-0.1.0.tgz#71012b3ac141427d97c67c56bc7921af6bff122d" + integrity sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA== -titleize@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/titleize/-/titleize-1.0.0.tgz#7d350722061830ba6617631e0cfd3ea08398d95a" - integrity sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw== +tabbable@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" + integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== + +tinyexec@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.1.tgz#70c31ab7abbb4aea0a24f55d120e5990bfa1e0b1" + integrity sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw== + +title@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/title/-/title-4.0.1.tgz#f5226a0fbec7b3a1c42c2772d67a493d2f189c87" + integrity sha512-xRnPkJx9nvE5MF6LkB5e8QJjE2FW8269wTu/LQdf7zZqBgPly0QJPf/CWAo7srj5so4yXfoLEdCFgurlpi47zg== + dependencies: + arg "^5.0.0" + chalk "^5.0.0" + clipboardy "^4.0.0" trim-lines@^3.0.0: version "3.0.1" @@ -1699,86 +3291,130 @@ trim-lines@^3.0.0: integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== trough@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" - integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== - -tslib@^2.3.0, tslib@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" + integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw== -unified@^10.0.0: - version "10.1.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" - integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== - dependencies: - "@types/unist" "^2.0.0" +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + +tslib@2, tslib@^2.4.0, tslib@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +twoslash-protocol@0.2.12: + version "0.2.12" + resolved "https://registry.yarnpkg.com/twoslash-protocol/-/twoslash-protocol-0.2.12.tgz#4c22fc287bc0fc32eec8e7faa6092b0dc5cc4ecb" + integrity sha512-5qZLXVYfZ9ABdjqbvPc4RWMr7PrpPaaDSeaYY55vl/w1j6H6kzsWK/urAEIXlzYlyrFmyz1UbwIt+AA0ck+wbg== + +twoslash@^0.2.12: + version "0.2.12" + resolved "https://registry.yarnpkg.com/twoslash/-/twoslash-0.2.12.tgz#46b11fb23ff3d950264ca32877576e2c2b4e997e" + integrity sha512-tEHPASMqi7kqwfJbkk7hc/4EhlrKCSLcur+TcvYki3vhIfaRMXnXjaYFgXpoZRbT6GdprD4tGuVBEmTpUgLBsw== + dependencies: + "@typescript/vfs" "^1.6.0" + twoslash-protocol "0.2.12" + +typescript@^5.0.2: + version "5.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== + +ufo@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +unified@^11.0.0, unified@^11.0.4, unified@^11.0.5: + version "11.0.5" + resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.5.tgz#f66677610a5c0a9ee90cab2b8d4d66037026d9e1" + integrity sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA== + dependencies: + "@types/unist" "^3.0.0" bail "^2.0.0" + devlop "^1.0.0" extend "^3.0.0" - is-buffer "^2.0.0" is-plain-obj "^4.0.0" trough "^2.0.0" - vfile "^5.0.0" + vfile "^6.0.0" -unist-builder@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04" - integrity sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ== +unist-util-find-after@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz#3fccc1b086b56f34c8b798e1ff90b5c54468e896" + integrity sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + +unist-util-is@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.2.1.tgz#b74960e145c18dcb6226bc57933597f5486deae9" + integrity sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw== dependencies: "@types/unist" "^2.0.0" -unist-util-generated@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" - integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== +unist-util-is@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" + integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw== + dependencies: + "@types/unist" "^3.0.0" -unist-util-is@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" - integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== +unist-util-modify-children@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz#981d6308e887b005d1f491811d3cbcc254b315e9" + integrity sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw== + dependencies: + "@types/unist" "^3.0.0" + array-iterate "^2.0.0" -unist-util-is@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" - integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== +unist-util-position-from-estree@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz#d94da4df596529d1faa3de506202f0c9a23f2200" + integrity sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ== + dependencies: + "@types/unist" "^3.0.0" -unist-util-position-from-estree@^1.0.0, unist-util-position-from-estree@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.1.tgz#96f4d543dfb0428edc01ebb928570b602d280c4c" - integrity sha512-xtoY50b5+7IH8tFbkw64gisG9tMSpxDjhX9TmaJJae/XuxQ9R/Kc8Nv1eOsf43Gt4KV/LkriMy9mptDr7XLcaw== +unist-util-position@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" + integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA== dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" -unist-util-position@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.3.tgz#5290547b014f6222dff95c48d5c3c13a88fadd07" - integrity sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ== +unist-util-remove-position@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz#fea68a25658409c9460408bc6b4991b965b52163" + integrity sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q== dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" + unist-util-visit "^5.0.0" -unist-util-remove-position@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-4.0.1.tgz#d5b46a7304ac114c8d91990ece085ca7c2c135c8" - integrity sha512-0yDkppiIhDlPrfHELgB+NLQD5mfjup3a8UYclHruTJWmY74je8g+CIFr79x5f6AkmzSwlvKLbs63hC0meOMowQ== +unist-util-remove@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-4.0.0.tgz#94b7d6bbd24e42d2f841e947ed087be5c82b222e" + integrity sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg== dependencies: - "@types/unist" "^2.0.0" - unist-util-visit "^4.0.0" + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" -unist-util-stringify-position@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" - integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== +unist-util-stringify-position@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2" + integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ== dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" -unist-util-visit-parents@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" - integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== +unist-util-visit-children@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz#4bced199b71d7f3c397543ea6cc39e7a7f37dc7e" + integrity sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA== dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" + "@types/unist" "^3.0.0" unist-util-visit-parents@^4.0.0: version "4.1.1" @@ -1788,22 +3424,13 @@ unist-util-visit-parents@^4.0.0: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" -unist-util-visit-parents@^5.0.0, unist-util-visit-parents@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" - integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - -unist-util-visit@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" - integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== +unist-util-visit-parents@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" + integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw== dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" unist-util-visit@^3.1.0: version "3.1.0" @@ -1814,79 +3441,130 @@ unist-util-visit@^3.1.0: unist-util-is "^5.0.0" unist-util-visit-parents "^4.0.0" -unist-util-visit@^4.0.0, unist-util-visit@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.1.tgz#1c4842d70bd3df6cc545276f5164f933390a9aad" - integrity sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg== +unist-util-visit@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" + integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg== dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents "^5.1.1" + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" -use-sync-external-store@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== +use-sync-external-store@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0" + integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A== + +uuid@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.0.tgz#9549028be1753bb934fc96e2bca09bb4105ae912" + integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== -uvu@^0.5.0: - version "0.5.6" - resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" - integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== +vfile-location@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-5.0.3.tgz#cb9eacd20f2b6426d19451e0eafa3d0a846225c3" + integrity sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg== dependencies: - dequal "^2.0.0" - diff "^5.0.0" - kleur "^4.0.3" - sade "^1.7.3" + "@types/unist" "^3.0.0" + vfile "^6.0.0" -vfile-location@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-4.0.1.tgz#06f2b9244a3565bef91f099359486a08b10d3a95" - integrity sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw== +vfile-message@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.3.tgz#87b44dddd7b70f0641c2e3ed0864ba73e2ea8df4" + integrity sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw== dependencies: - "@types/unist" "^2.0.0" - vfile "^5.0.0" + "@types/unist" "^3.0.0" + unist-util-stringify-position "^4.0.0" -vfile-message@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.2.tgz#a2908f64d9e557315ec9d7ea3a910f658ac05f7d" - integrity sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA== +vfile@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.3.tgz#3652ab1c496531852bf55a6bac57af981ebc38ab" + integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q== dependencies: - "@types/unist" "^2.0.0" - unist-util-stringify-position "^3.0.0" + "@types/unist" "^3.0.0" + vfile-message "^4.0.0" + +vscode-jsonrpc@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9" + integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA== -vfile@^5.0.0: - version "5.3.5" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.5.tgz#ec2e206b1414f561c85b7972bb1eeda8ab47ee61" - integrity sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ== +vscode-languageserver-protocol@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea" + integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg== dependencies: - "@types/unist" "^2.0.0" - is-buffer "^2.0.0" - unist-util-stringify-position "^3.0.0" - vfile-message "^3.0.0" + vscode-jsonrpc "8.2.0" + vscode-languageserver-types "3.17.5" -vscode-oniguruma@^1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607" - integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA== +vscode-languageserver-textdocument@~1.0.11: + version "1.0.12" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631" + integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA== -vscode-textmate@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" - integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== +vscode-languageserver-types@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" + integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== +vscode-languageserver@~9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz#500aef82097eb94df90d008678b0b6b5f474015b" + integrity sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g== dependencies: - isexe "^2.0.0" + vscode-languageserver-protocol "3.17.5" -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== +vscode-uri@~3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f" + integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== + +watchpack@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +web-namespaces@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" + integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== -zwitch@^2.0.0: +which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.2.tgz#91f8d0e901ffa3d66599756dde7f57b17c95dce1" - integrity sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA== + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wicked-good-xpath@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz#81b0e95e8650e49c94b22298fff8686b5553cf6c" + integrity sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw== + +yaml@^2.3.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.1.tgz#1870aa02b631f7e8328b93f8bc574fac5d6c4d79" + integrity sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw== + +yocto-queue@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.2.1.tgz#36d7c4739f775b3cbc28e6136e21aa057adec418" + integrity sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg== + +zod-validation-error@^3.0.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.5.3.tgz#85ba33290200d8db9f043621e284f40dddefb7e5" + integrity sha512-OT5Y8lbUadqVZCsnyFaTQ4/O2mys4tj7PqhdbBCp7McPwvIEKfPtdA6QfPeFQK2/Rz5LgwmAXRJTugBNBi0btw== + +zod@^3.22.3: + version "3.25.76" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" + integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== + +zwitch@^2.0.0, zwitch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" + integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..2d969deb0 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,78 @@ +import { defineConfig, globalIgnores } from 'eslint/config' +import typescriptEslint from '@typescript-eslint/eslint-plugin' +import prettier from 'eslint-plugin-prettier' +import globals from 'globals' +import tsParser from '@typescript-eslint/parser' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import js from '@eslint/js' +import { FlatCompat } from '@eslint/eslintrc' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}) + +export default defineConfig([ + globalIgnores([ + '**/node_modules', + '**/coverage', + 'packages/*/dist', + 'packages/pg-protocol/dist/**/*', + 'packages/pg-query-stream/dist/**/*', + ]), + { + extends: compat.extends('eslint:recommended', 'plugin:prettier/recommended', 'prettier'), + + plugins: { + '@typescript-eslint': typescriptEslint, + prettier, + }, + + languageOptions: { + globals: { + ...globals.node, + ...globals.mocha, + }, + + parser: tsParser, + ecmaVersion: 2017, + sourceType: 'module', + }, + + rules: { + '@typescript-eslint/no-unused-vars': [ + 'error', + { + args: 'none', + caughtErrors: 'none', + varsIgnorePattern: '^_$', + }, + ], + + // handled by @typescript-eslint/no-unused-vars + 'no-unused-vars': 'off', + + 'no-var': 'error', + 'prefer-const': 'error', + 'no-constant-condition': [ + 'error', + { + checkLoops: 'all', + }, + ], + }, + }, + { + files: ['**/*.ts', '**/*.mts', '**/*.cts', '**/*.tsx'], + + rules: { + 'no-undef': 'off', + 'no-redeclare': 'off', + '@typescript-eslint/no-redeclare': 'error', + }, + }, +]) diff --git a/package.json b/package.json index 77a1fcc44..e30454007 100644 --- a/package.json +++ b/package.json @@ -14,21 +14,23 @@ "build": "tsc --build", "build:watch": "tsc --build --watch", "docs:build": "cd docs && yarn build", - "docs:start": "cd docs && yarn start", + "docs:start": "cd docs && yarn dev", "pretest": "yarn build", "prepublish": "yarn build", "lint": "eslint --cache 'packages/**/*.{js,ts,tsx}'" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.0.0", - "@typescript-eslint/parser": "^6.17.0", - "eslint": "^8.56.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "^10.0.1", + "@types/node": "^16", + "@typescript-eslint/eslint-plugin": "^8.58.0", + "@typescript-eslint/parser": "^8.58.0", + "eslint": "^10.2.1", "eslint-config-prettier": "^10.1.2", - "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.1.2", "lerna": "^3.19.0", "prettier": "3.0.3", - "typescript": "^4.0.3" + "typescript": "^6.0.3" }, "prettier": { "semi": false, diff --git a/packages/pg-bundler-test/package.json b/packages/pg-bundler-test/package.json index 088a81e2a..fc368c197 100644 --- a/packages/pg-bundler-test/package.json +++ b/packages/pg-bundler-test/package.json @@ -1,6 +1,6 @@ { "name": "pg-bundler-test", - "version": "0.1.0", + "version": "0.3.0", "description": "Test bundlers with pg-cloudflare, https://github.com/brianc/node-postgres/issues/3452", "license": "MIT", "private": true, @@ -9,7 +9,7 @@ "@rollup/plugin-commonjs": "^28.0.3", "@rollup/plugin-node-resolve": "^16.0.1", "esbuild": "^0.25.5", - "pg-cloudflare": "^1.3.0", + "pg-cloudflare": "^1.4.0", "rollup": "^4.41.1", "vite": "^7.1.7", "webpack": "^5.99.9", diff --git a/packages/pg-cloudflare/package.json b/packages/pg-cloudflare/package.json index c1584fc09..4bc706c8a 100644 --- a/packages/pg-cloudflare/package.json +++ b/packages/pg-cloudflare/package.json @@ -1,13 +1,13 @@ { "name": "pg-cloudflare", - "version": "1.3.0", + "version": "1.4.0", "description": "A socket implementation that can run on Cloudflare Workers using native TCP connections.", "main": "dist/index.js", "types": "dist/index.d.ts", "license": "MIT", "devDependencies": { "ts-node": "^8.5.4", - "typescript": "^4.0.3" + "typescript": "^6.0.3" }, "exports": { ".": { diff --git a/packages/pg-cloudflare/src/index.ts b/packages/pg-cloudflare/src/index.ts index d83882efe..d625beee0 100644 --- a/packages/pg-cloudflare/src/index.ts +++ b/packages/pg-cloudflare/src/index.ts @@ -82,11 +82,15 @@ export class CloudflareSocket extends EventEmitter { this.emit('data', Buffer.from(value)) } + write(data: Uint8Array | string, callback?: (error?: unknown) => void): true | void + write(data: Uint8Array | string, encoding?: BufferEncoding, callback?: (error?: unknown) => void): true | void write( data: Uint8Array | string, - encoding: BufferEncoding = 'utf8', - callback: (...args: unknown[]) => void = () => {} - ) { + encodingOrCallback: BufferEncoding | ((error?: unknown) => void) = 'utf8', + callback: (error?: unknown) => void = () => {} + ): true | void { + const encoding = typeof encodingOrCallback === 'function' ? 'utf8' : encodingOrCallback + if (typeof encodingOrCallback === 'function') callback = encodingOrCallback if (data.length === 0) return callback() if (typeof data === 'string') data = Buffer.from(data, encoding) @@ -107,7 +111,7 @@ export class CloudflareSocket extends EventEmitter { end(data = Buffer.alloc(0), encoding: BufferEncoding = 'utf8', callback: (...args: unknown[]) => void = () => {}) { log('ending CF socket') this.write(data, encoding, (err) => { - this._cfSocket!.close() + this._cfSocket?.close() if (callback) callback(err) }) return this @@ -153,7 +157,10 @@ const debug = false function dump(data: unknown) { if (data instanceof Uint8Array || data instanceof ArrayBuffer) { - const hex = Buffer.from(data).toString('hex') + // workaround https://github.com/microsoft/TypeScript/issues/63447 + const buf = data instanceof Uint8Array ? Buffer.from(data) : Buffer.from(data) + + const hex = buf.toString('hex') const str = new TextDecoder().decode(data) return `\n>>> STR: "${str.replace(/\n/g, '\\n')}"\n>>> HEX: ${hex}\n` } else { diff --git a/packages/pg-cloudflare/tsconfig.json b/packages/pg-cloudflare/tsconfig.json index 31d494681..840b52aff 100644 --- a/packages/pg-cloudflare/tsconfig.json +++ b/packages/pg-cloudflare/tsconfig.json @@ -9,15 +9,16 @@ "moduleResolution": "node16", "sourceMap": true, "outDir": "dist", + "rootDir": "./src", "incremental": true, - "baseUrl": ".", "declaration": true, "paths": { "*": [ - "node_modules/*", - "src/types/*" + "./node_modules/*", + "./src/types/*" ] - } + }, + "types": ["node"] }, "include": [ "src/**/*" diff --git a/packages/pg-connection-string/README.md b/packages/pg-connection-string/README.md index e47adc816..5475f63bf 100644 --- a/packages/pg-connection-string/README.md +++ b/packages/pg-connection-string/README.md @@ -3,7 +3,7 @@ pg-connection-string [![NPM](https://nodei.co/npm/pg-connection-string.png?compact=true)](https://nodei.co/npm/pg-connection-string/) -Functions for dealing with a PostgresSQL connection string +Functions for dealing with a PostgreSQL connection string `parse` method taken from [node-postgres](https://github.com/brianc/node-postgres.git) Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com) diff --git a/packages/pg-connection-string/index.d.ts b/packages/pg-connection-string/index.d.ts index 2ebe67534..4b305299e 100644 --- a/packages/pg-connection-string/index.d.ts +++ b/packages/pg-connection-string/index.d.ts @@ -22,6 +22,7 @@ export interface ConnectionOptions { database: string | null | undefined client_encoding?: string ssl?: boolean | string | SSLConfig + sslnegotiation?: 'postgres' | 'direct' application_name?: string fallback_application_name?: string diff --git a/packages/pg-connection-string/index.js b/packages/pg-connection-string/index.js index 29ffeafd7..7ee302976 100644 --- a/packages/pg-connection-string/index.js +++ b/packages/pg-connection-string/index.js @@ -14,7 +14,7 @@ function parse(str, options = {}) { // Check for empty host in URL - const config = {} + const config = Object.create(null) let result let dummyHost = false if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) { @@ -78,6 +78,12 @@ function parse(str, options = {}) { config.ssl = {} } + // sslnegotiation=direct implies SSL is in use (libpq requires sslmode>=require), + // so enable SSL if the connection string did not otherwise configure it. + if (config.sslnegotiation === 'direct' && config.ssl === undefined) { + config.ssl = true + } + // Only try to load fs if we expect to read from the disk const fs = config.sslcert || config.sslkey || config.sslrootcert ? require('fs') : null @@ -164,7 +170,7 @@ function toConnectionOptions(sslConfig) { } return c - }, {}) + }, Object.create(null)) return connectionOptions } @@ -200,7 +206,7 @@ function toClientConfig(config) { } return c - }, {}) + }, Object.create(null)) return poolConfig } diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index f48cf92aa..cf0ac743b 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,7 +1,7 @@ { "name": "pg-connection-string", - "version": "2.11.0", - "description": "Functions for dealing with a PostgresSQL connection string", + "version": "2.14.0", + "description": "Functions for dealing with a PostgreSQL connection string", "main": "./index.js", "types": "./index.d.ts", "exports": { @@ -38,10 +38,10 @@ "chai": "^4.1.1", "coveralls": "^3.0.4", "istanbul": "^0.4.5", - "mocha": "^10.5.2", + "mocha": "^11.7.5", "nyc": "^15", "tsx": "^4.19.4", - "typescript": "^4.0.3" + "typescript": "^6.0.3" }, "files": [ "index.js", diff --git a/packages/pg-connection-string/test/clientConfig.ts b/packages/pg-connection-string/test/clientConfig.ts index 14759570f..c4aeec6a7 100644 --- a/packages/pg-connection-string/test/clientConfig.ts +++ b/packages/pg-connection-string/test/clientConfig.ts @@ -46,7 +46,7 @@ describe('toClientConfig', function () { const config = parse('pg:///?sslmode=no-verify') const clientConfig = toClientConfig(config) - clientConfig.ssl?.should.deep.equal({ + expect(clientConfig.ssl).to.deep.equal({ rejectUnauthorized: false, }) }) @@ -55,14 +55,14 @@ describe('toClientConfig', function () { const config = parse('pg:///?sslmode=verify-ca') const clientConfig = toClientConfig(config) - clientConfig.ssl?.should.deep.equal({}) + expect(clientConfig.ssl).to.deep.equal({}) }) it('converts other sslmode options', function () { const config = parse('pg:///?sslmode=verify-ca') const clientConfig = toClientConfig(config) - clientConfig.ssl?.should.deep.equal({}) + expect(clientConfig.ssl).to.deep.equal({}) }) it('converts ssl cert options', function () { @@ -77,7 +77,7 @@ describe('toClientConfig', function () { const config = parse(connectionString) const clientConfig = toClientConfig(config) - clientConfig.ssl?.should.deep.equal({ + expect(clientConfig.ssl).to.deep.equal({ ca: 'example ca\n', cert: 'example cert\n', key: 'example key\n', @@ -106,9 +106,9 @@ describe('toClientConfig', function () { const clientConfig = toClientConfig(config) - clientConfig.host?.should.equal('boom') - clientConfig.database?.should.equal('lala') - clientConfig.ssl?.should.deep.equal({}) + expect(clientConfig.host).to.equal('boom') + expect(clientConfig.database).to.equal('lala') + expect(clientConfig.ssl).to.deep.equal({}) }) }) diff --git a/packages/pg-connection-string/test/parse.ts b/packages/pg-connection-string/test/parse.ts index a58edbe9c..c2a537581 100644 --- a/packages/pg-connection-string/test/parse.ts +++ b/packages/pg-connection-string/test/parse.ts @@ -216,6 +216,29 @@ describe('parse', function () { subject.ssl?.should.equal(true) }) + it('configuration parameter sslnegotiation=direct', function () { + const connectionString = 'pg:///?sslnegotiation=direct' + const subject = parse(connectionString) + subject.sslnegotiation?.should.equal('direct') + // direct negotiation implies SSL is enabled + subject.ssl?.should.equal(true) + }) + + it('configuration parameter sslnegotiation=postgres', function () { + const connectionString = 'pg:///?sslnegotiation=postgres' + const subject = parse(connectionString) + subject.sslnegotiation?.should.equal('postgres') + // traditional negotiation does not change ssl + ;(subject.ssl === undefined).should.equal(true) + }) + + it('sslnegotiation=direct keeps an explicit ssl config', function () { + const connectionString = 'pg:///?sslnegotiation=direct&sslmode=require' + const subject = parse(connectionString) + subject.sslnegotiation?.should.equal('direct') + subject.ssl?.should.eql({}) + }) + it('configuration parameter sslcert=/path/to/cert', function () { const connectionString = 'pg:///?sslcert=' + __dirname + '/example.cert' const subject = parse(connectionString) @@ -467,4 +490,38 @@ describe('parse', function () { const subject = parse(connectionString) subject.port?.should.equal('1234') }) + + describe('prototype pollution protection', function () { + it('returns object with null prototype', function () { + const subject = parse('postgres://localhost/db') + expect(Object.getPrototypeOf(subject)).to.equal(null) + }) + + it('__proto__ query parameter is stored as regular property', function () { + const subject = parse('postgres://localhost/db?__proto__=malicious') + expect(Object.getPrototypeOf(subject)).to.equal(null) + expect(subject['__proto__']).to.equal('malicious') + // global Object.prototype should not be affected + expect(({} as any).malicious).to.equal(undefined) + }) + + it('constructor query parameter is stored as regular property', function () { + const subject = parse('postgres://localhost/db?constructor=evil') + expect(subject.constructor).to.equal('evil') + }) + + it('prototype query parameter is stored as regular property', function () { + const subject = parse('postgres://localhost/db?prototype=evil') + expect(subject['prototype']).to.equal('evil') + }) + + it('multiple dangerous query parameters are handled safely', function () { + const subject = parse('postgres://localhost/db?__proto__=a&constructor=b&prototype=c&toString=d') + expect(Object.getPrototypeOf(subject)).to.equal(null) + expect(subject['__proto__']).to.equal('a') + expect(subject.constructor).to.equal('b') + expect(subject['prototype']).to.equal('c') + expect(subject['toString']).to.equal('d') + }) + }) }) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index eee585b71..46f3406c2 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.17.0", + "version": "2.22.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "exports": { @@ -24,8 +24,8 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "mocha": "^10.5.2", - "pg": "^8.18.0" + "mocha": "^11.7.5", + "pg": "^8.23.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index b34161a17..4b4c913a3 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -16,11 +16,11 @@ describe('close', function () { it('can close a finished cursor without a callback', function (done) { const cursor = new Cursor(text) this.client.query(cursor) - this.client.query('SELECT NOW()', done) cursor.read(100, function (err) { assert.ifError(err) cursor.close() }) + this.client.once('drain', done) }) it('can close a finished cursor a promise', function (done) { @@ -37,11 +37,11 @@ describe('close', function () { it('closes cursor early', function (done) { const cursor = new Cursor(text) this.client.query(cursor) - this.client.query('SELECT NOW()', done) cursor.read(25, function (err) { assert.ifError(err) cursor.close() }) + this.client.once('drain', done) }) it('works with callback style', function (done) { diff --git a/packages/pg-esm-test/package.json b/packages/pg-esm-test/package.json index 15ff62a1d..23a688bf9 100644 --- a/packages/pg-esm-test/package.json +++ b/packages/pg-esm-test/package.json @@ -1,6 +1,6 @@ { "name": "pg-esm-test", - "version": "1.4.0", + "version": "1.9.0", "description": "A test module for PostgreSQL with ESM support", "main": "index.js", "type": "module", @@ -14,13 +14,13 @@ "test" ], "devDependencies": { - "pg": "^8.18.0", - "pg-cloudflare": "^1.3.0", - "pg-cursor": "^2.17.0", - "pg-native": "^3.5.2", - "pg-pool": "^3.11.0", - "pg-protocol": "^1.11.0", - "pg-query-stream": "^4.12.0" + "pg": "^8.23.0", + "pg-cloudflare": "^1.4.0", + "pg-cursor": "^2.22.0", + "pg-native": "^3.9.0", + "pg-pool": "^3.14.0", + "pg-protocol": "^1.16.0", + "pg-query-stream": "^4.17.0" }, "author": "Brian M. Carlson ", "license": "MIT" diff --git a/packages/pg-esm-test/pg-cloudflare.test.js b/packages/pg-esm-test/pg-cloudflare.test.js index a42620253..75d1f9957 100644 --- a/packages/pg-esm-test/pg-cloudflare.test.js +++ b/packages/pg-esm-test/pg-cloudflare.test.js @@ -6,4 +6,35 @@ describe('pg-cloudflare', () => { it('should export CloudflareSocket constructor', () => { assert.ok(new CloudflareSocket()) }) + + it('should safely end after the underlying socket has closed', async () => { + const socket = new CloudflareSocket() + const underlyingSocket = { closed: Promise.resolve() } + socket._cfSocket = underlyingSocket + socket._addClosedHandler() + + await underlyingSocket.closed + assert.equal(socket._cfSocket, null) + + assert.doesNotThrow(() => socket.end()) + }) + + it('should call the write(data, callback) callback exactly once', async () => { + const socket = new CloudflareSocket() + socket._cfWriter = { write: () => Promise.resolve() } + + let resolve + const promise = new Promise((resolvePromise) => { + resolve = resolvePromise + }) + let called = false + socket.write(Buffer.from('x'), (error) => { + assert.ifError(error) + assert(!called) + called = true + resolve() + }) + + await promise + }) }) diff --git a/packages/pg-native/index.js b/packages/pg-native/index.js index 8c83406bb..451daeb7d 100644 --- a/packages/pg-native/index.js +++ b/packages/pg-native/index.js @@ -6,6 +6,10 @@ const types = require('pg-types') const buildResult = require('./lib/build-result') const CopyStream = require('./lib/copy-stream') +// https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQTRANSACTIONSTATUS +// 0=IDLE, 1=ACTIVE, 2=INTRANS, 3=INERROR +const statusMap = { 0: 'I', 2: 'T', 3: 'E' } + const Client = (module.exports = function (config) { if (!(this instanceof Client)) { return new Client(config) @@ -145,6 +149,10 @@ Client.prototype.escapeIdentifier = function (value) { return this.pq.escapeIdentifier(value) } +Client.prototype.getTransactionStatus = function () { + return statusMap[this.pq.transactionStatus()] ?? null +} + // export the version number so we can check it in node-postgres module.exports.version = require('./package.json').version @@ -166,8 +174,8 @@ Client.prototype._stopReading = function () { this.pq.removeListener('readable', this._read) } -Client.prototype._consumeQueryResults = function (pq) { - return buildResult(pq, this._types, this.arrayMode) +Client.prototype._consumeQueryResults = function (pq, arrayMode = this.arrayMode) { + return buildResult(pq, this._types, arrayMode) } Client.prototype._emitResult = function (pq) { @@ -191,6 +199,10 @@ Client.prototype._emitResult = function (pq) { break } + case 'PGRES_PIPELINE_SYNC': + case 'PGRES_PIPELINE_ABORTED': + break + default: this._readError('unrecognized command status: ' + status) break @@ -306,6 +318,175 @@ Client.prototype._onResult = function (result) { this._resultCount++ } +// Send a batch of queries in pipeline mode and collect results in order. +// Each entry in `queries` is {text, values?, name?}. +// `cb(err, results)` where results is an array, one per query, +// of {err, rows, result} objects. +Client.prototype.pipeline = function (queries, cb) { + const pq = this.pq + + if (!pq.pipelineModeSupported || !pq.pipelineModeSupported()) { + return cb(new Error('Pipeline mode is not supported. Requires PostgreSQL 14+ client libraries.')) + } + + if (!pq.enterPipelineMode()) { + return cb(new Error(pq.errorMessage() || 'Failed to enter pipeline mode')) + } + + pq.setNonBlocking(true) + + // Send all queries, each followed by a sync + for (let i = 0; i < queries.length; i++) { + const q = queries[i] + let sent + if (q.name) { + if (q._alreadyPrepared) { + sent = pq.sendQueryPrepared(q.name, q.values || []) + } else { + // send prepare then execute in same pipeline batch + sent = pq.sendPrepare(q.name, q.text, (q.values || []).length) + if (sent) { + sent = pq.sendQueryPrepared(q.name, q.values || []) + } + } + } else { + // In pipeline mode, simple query protocol (sendQuery) is not allowed. + // Always use extended query protocol (sendQueryParams). + sent = pq.sendQueryParams(q.text, q.values || []) + } + + if (!sent) { + const err = new Error(pq.errorMessage() || 'Failed to send pipelined query') + pq.exitPipelineMode() + return cb(err) + } + + pq.pipelineSync() + } + + // Flush all queued data to the socket + this._waitForDrain(pq, (err) => { + if (err) { + pq.exitPipelineMode() + return cb(err) + } + this._readPipelineResults(queries, cb) + }) +} + +// Read pipeline results for `queries.length` sync points. +// Calls cb(null, results) when all syncs have been received. +Client.prototype._readPipelineResults = function (queries, cb) { + const pq = this.pq + const self = this + const results = [] + let queryIndex = 0 + let currentResult = null + let currentError = null + + const processResults = function () { + if (!pq.consumeInput()) { + // read the message before anything else touches the connection: libpq appends to a single + // error buffer, and exiting pipeline mode on a connection that is still busy adds its own + // "cannot exit pipeline mode while busy" to the end of the reason the caller actually wants. + // The connection is finished either way, so there is nothing to exit cleanly for. + const message = pq.errorMessage() + return cb(new Error(message || 'Failed to consume input')) + } + + while (!pq.isBusy()) { + if (!pq.getResult()) { + // null between result groups in pipeline — try again + if (pq.isBusy()) return // more data needed + if (!pq.getResult()) { + // libpq has no result left and is not waiting for one, yet we have not seen a sync for + // every query. Nothing further is owed on this connection, so breaking out would return + // without ever calling cb and strand the caller. Fail the batch instead. + return cb(new Error(pq.errorMessage() || 'Connection ended before the pipeline completed')) + } + } + + const status = pq.resultStatus() + + if (status === 'PGRES_PIPELINE_SYNC') { + // End of one query's results + sync + if (currentError) { + results.push({ err: currentError, rows: null, result: null }) + } else if (currentResult) { + results.push({ err: null, rows: currentResult.rows, result: currentResult }) + } else { + results.push({ err: null, rows: [], result: null }) + } + currentResult = null + currentError = null + queryIndex++ + + if (queryIndex >= queries.length) { + // All queries processed + pq.exitPipelineMode() + return cb(null, results) + } + continue + } + + if (status === 'PGRES_FATAL_ERROR') { + currentError = new Error(pq.resultErrorMessage()) + // Extract error fields + const fields = pq.resultErrorFields() + if (fields) { + for (const key in fields) { + currentError[key] = fields[key] + } + } + continue + } + + if (status === 'PGRES_PIPELINE_ABORTED') { + // The server refused to run this one: an earlier query in the same sync group failed and + // the pipeline is aborted until the next sync. Falling through left currentError and + // currentResult null, so the sync branch below handed back {err: null, rows: []} and a + // statement that never ran looked like one that matched no rows. + if (!currentError) { + currentError = new Error('Query was not executed: an earlier query in the same pipeline failed') + } + continue + } + + if (status === 'PGRES_TUPLES_OK' || status === 'PGRES_COMMAND_OK' || status === 'PGRES_EMPTY_QUERY') { + currentResult = self._consumeQueryResults(pq, queries[queryIndex].arrayMode) + continue + } + } + + // Still waiting for more data — will be called again when readable + } + + // Use the libuv readable watcher + this._stopReading() + let done = false + const origCb = cb + cb = function (err, results) { + if (done) return + done = true + pq.removeListener('readable', onReadable) + self._stopReading() + origCb(err, results) + } + const onReadable = function () { + processResults() + } + pq.on('readable', onReadable) + pq.startReader() + // startReader() has to be recorded, or _stopReading() short-circuits on the flag and leaves the + // poll watcher running after the batch is over. A later finish() then closes the handle with the + // watcher still armed, and the next startReader() on it aborts the process with + // "uv_poll_start: Assertion `!uv__is_closing(handle)' failed". + this._reading = true + + // Try an initial read in case data is already available + processResults() +} + Client.prototype._onReadyForQuery = function () { // remove instance callback const cb = this._queryCallback diff --git a/packages/pg-native/package.json b/packages/pg-native/package.json index 92bf5cac2..63d7569f3 100644 --- a/packages/pg-native/package.json +++ b/packages/pg-native/package.json @@ -1,6 +1,6 @@ { "name": "pg-native", - "version": "3.5.2", + "version": "3.9.0", "description": "A slightly nicer interface to Postgres over node-libpq", "main": "index.js", "exports": { @@ -42,7 +42,7 @@ "concat-stream": "^1.4.6", "generic-pool": "^2.1.1", "lodash": "^4.17.21", - "mocha": "10.5.2", + "mocha": "11.7.5", "node-gyp": ">=10.x", "okay": "^0.3.0", "semver": "^7.7.2" diff --git a/packages/pg-native/test/index.js b/packages/pg-native/test/index.js index 6770fe143..905225b1b 100644 --- a/packages/pg-native/test/index.js +++ b/packages/pg-native/test/index.js @@ -7,7 +7,7 @@ describe('connection', function () { }) it('connects with args', function (done) { - Client().connect('host=localhost', done) + Client().connect(`host=${process.env.PGHOST || 'localhost'}`, done) }) it('errors out with bad connection args', function (done) { diff --git a/packages/pg-native/test/pipeline-connection-loss.js b/packages/pg-native/test/pipeline-connection-loss.js new file mode 100644 index 000000000..eb5e779a5 --- /dev/null +++ b/packages/pg-native/test/pipeline-connection-loss.js @@ -0,0 +1,76 @@ +const net = require('net') +const assert = require('assert') +const Client = require('../') + +describe('pipeline reader', function () { + let proxy + let proxyPort + let clientSockets + + beforeEach(function (done) { + clientSockets = [] + proxy = net.createServer(function (client) { + const upstream = net.connect(Number(process.env.PGPORT || 5432), process.env.PGHOST || 'localhost') + clientSockets.push(client) + client.pipe(upstream) + upstream.pipe(client) + client.on('error', function () {}) + upstream.on('error', function () {}) + }) + proxy.listen(0, '127.0.0.1', function () { + proxyPort = proxy.address().port + done() + }) + }) + + afterEach(function (done) { + proxy.close(function () { + done() + }) + }) + + // the batch starts the reader, so it has to stop it too. It used to leave the poll watcher armed, + // and a later finish() then closed the handle under it. + it('stops the reader it started once the batch is done', function (done) { + const client = new Client() + client.connect(`host=127.0.0.1 port=${proxyPort}`, function (err) { + assert.ifError(err) + let stopped = 0 + const stopReader = client.pq.stopReader.bind(client.pq) + client.pq.stopReader = function () { + stopped++ + return stopReader() + } + client.pipeline([{ text: 'SELECT 1' }, { text: 'SELECT 2' }], function (err) { + assert.ifError(err) + assert(stopped > 0, 'the reader started for the batch was never stopped') + client.end() + done() + }) + }) + }) + + // exitPipelineMode() on a busy connection appends its own complaint to libpq's error buffer, so + // reading the message afterwards buried the reason the caller wanted. + it('reports why the connection went away', function (done) { + this.timeout(10000) + const client = new Client() + client.connect(`host=127.0.0.1 port=${proxyPort}`, function (err) { + assert.ifError(err) + client.pipeline([{ text: 'SELECT pg_sleep(10)' }], function (err) { + assert(err, 'a batch cut off mid flight must fail') + assert( + !/cannot exit pipeline mode/.test(err.message), + `error should say why the connection ended, got: ${err.message}` + ) + client.end() + done() + }) + setTimeout(function () { + clientSockets.forEach(function (socket) { + socket.end() + }) + }, 100) + }) + }) +}) diff --git a/packages/pg-pool/README.md b/packages/pg-pool/README.md index f3bb2d6be..80c644788 100644 --- a/packages/pg-pool/README.md +++ b/packages/pg-pool/README.md @@ -25,8 +25,7 @@ const pool = new Pool() // you can pass properties to the pool // these properties are passed unchanged to both the node-postgres Client constructor -// and the node-pool (https://github.com/coopernurse/node-pool) constructor -// allowing you to fully configure the behavior of both +// and the pool constructor, allowing you to fully configure the behavior of both const pool2 = new Pool({ database: 'postgres', user: 'brianc', diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 3e505f797..ab514fa88 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -108,6 +108,14 @@ class Pool extends EventEmitter { this.ended = false } + _promiseTry(f) { + const Promise = this.Promise + if (typeof Promise.try === 'function') { + return Promise.try(f) + } + return new Promise((resolve) => resolve(f())) + } + _isFull() { return this._clients.length >= this.options.max } @@ -241,10 +249,16 @@ class Pool extends EventEmitter { let timeoutHit = false if (this.options.connectionTimeoutMillis) { tid = setTimeout(() => { - this.log('ending client due to timeout') - timeoutHit = true - // force kill the node driver, and let libpq do its teardown - client.connection ? client.connection.stream.destroy() : client.end() + if (client.connection) { + this.log('ending client due to timeout') + timeoutHit = true + client.connection.stream.destroy() + } else if (!client.isConnected()) { + this.log('ending client due to timeout') + timeoutHit = true + // force kill the node driver, and let libpq do its teardown + client.end() + } }, this.options.connectionTimeoutMillis) } @@ -271,30 +285,52 @@ class Pool extends EventEmitter { } else { this.log('new client connected') - if (this.options.maxLifetimeSeconds !== 0) { - const maxLifetimeTimeout = setTimeout(() => { - this.log('ending client due to expired lifetime') - this._expired.add(client) - const idleIndex = this._idle.findIndex((idleItem) => idleItem.client === client) - if (idleIndex !== -1) { - this._acquireClient( - client, - new PendingItem((err, client, clientRelease) => clientRelease()), - idleListener, - false - ) + if (this.options.onConnect) { + this._promiseTry(() => this.options.onConnect(client)).then( + () => { + this._afterConnect(client, pendingItem, idleListener) + }, + (hookErr) => { + this._clients = this._clients.filter((c) => c !== client) + client.end(() => { + this._pulseQueue() + if (!pendingItem.timedOut) { + pendingItem.callback(hookErr, undefined, NOOP) + } + }) } - }, this.options.maxLifetimeSeconds * 1000) - - maxLifetimeTimeout.unref() - client.once('end', () => clearTimeout(maxLifetimeTimeout)) + ) + return } - return this._acquireClient(client, pendingItem, idleListener, true) + return this._afterConnect(client, pendingItem, idleListener) } }) } + _afterConnect(client, pendingItem, idleListener) { + if (this.options.maxLifetimeSeconds !== 0) { + const maxLifetimeTimeout = setTimeout(() => { + this.log('ending client due to expired lifetime') + this._expired.add(client) + const idleIndex = this._idle.findIndex((idleItem) => idleItem.client === client) + if (idleIndex !== -1) { + this._acquireClient( + client, + new PendingItem((err, client, clientRelease) => clientRelease()), + idleListener, + false + ) + } + }, this.options.maxLifetimeSeconds * 1000) + + maxLifetimeTimeout.unref() + client.once('end', () => clearTimeout(maxLifetimeTimeout)) + } + + return this._acquireClient(client, pendingItem, idleListener, true) + } + // acquire a client for a pending work item _acquireClient(client, pendingItem, idleListener, isNew) { if (isNew) { @@ -402,7 +438,7 @@ class Pool extends EventEmitter { return response.result } - // allow plain text query without values + // allow plain text query without values, but callback if (typeof values === 'function') { cb = values values = undefined diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 29dae6cb9..6b9f60155 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.11.0", + "version": "3.14.0", "description": "Connection pool for node-postgres", "main": "index.js", "exports": { @@ -38,7 +38,7 @@ "co": "4.6.0", "expect.js": "0.3.1", "lodash": "^4.17.11", - "mocha": "^10.5.2" + "mocha": "^11.7.5" }, "peerDependencies": { "pg": ">=8.0" diff --git a/packages/pg-pool/test/connection-timeout.js b/packages/pg-pool/test/connection-timeout.js index cb83f7006..c4fd1832b 100644 --- a/packages/pg-pool/test/connection-timeout.js +++ b/packages/pg-pool/test/connection-timeout.js @@ -226,4 +226,25 @@ describe('connection timeout', () => { }) }) }) + + it('should connect if timeout is passed, but native client in connected state', (done) => { + const Client = require('pg').native.Client + + Client.prototype.connect = function (cb) { + this._connected = true + + return setTimeout(() => { + cb() + }, 200) + } + + const pool = new Pool({ connectionTimeoutMillis: 100, port: this.port, host: 'localhost' }, Client) + + pool.connect((err, client, release) => { + expect(err).to.be(undefined) + expect(client).to.not.be(undefined) + expect(client.isConnected()).to.be(true) + done() + }) + }) }) diff --git a/packages/pg-pool/test/index.js b/packages/pg-pool/test/index.js index 57a68e01e..cc1e9d905 100644 --- a/packages/pg-pool/test/index.js +++ b/packages/pg-pool/test/index.js @@ -203,6 +203,33 @@ describe('pool', function () { }) }) + it('enables pipeline on clients when configured', async function () { + const pool = new Pool({ pipeline: true }) + const client = await pool.connect() + expect(client.pipeline).to.be(true) + + const [r1, r2, r3] = await Promise.all([ + client.query('SELECT 1 AS num'), + client.query('SELECT 2 AS num'), + client.query('SELECT 3 AS num'), + ]) + + expect(r1.rows[0].num).to.eql(1) + expect(r2.rows[0].num).to.eql(2) + expect(r3.rows[0].num).to.eql(3) + + client.release() + return pool.end() + }) + + it('does not enable pipeline by default', async function () { + const pool = new Pool() + const client = await pool.connect() + expect(client.pipeline).to.be(false) + client.release() + return pool.end() + }) + it('recovers from query errors', function () { const pool = new Pool() diff --git a/packages/pg-pool/test/lifecycle-hooks.js b/packages/pg-pool/test/lifecycle-hooks.js new file mode 100644 index 000000000..05a706d95 --- /dev/null +++ b/packages/pg-pool/test/lifecycle-hooks.js @@ -0,0 +1,164 @@ +const describe = require('mocha').describe +const it = require('mocha').it +const expect = require('expect.js') + +const Pool = require('..') + +describe('lifecycle hooks', () => { + it('are called on connect', async () => { + const pool = new Pool({ + onConnect: (client) => { + client.HOOK_CONNECT_COUNT = (client.HOOK_CONNECT_COUNT || 0) + 1 + }, + }) + const client = await pool.connect() + expect(client.HOOK_CONNECT_COUNT).to.equal(1) + client.release() + const client2 = await pool.connect() + expect(client).to.equal(client2) + expect(client2.HOOK_CONNECT_COUNT).to.equal(1) + client.release() + await pool.end() + }) + + it('are called on connect with an async hook', async () => { + const pool = new Pool({ + onConnect: async (client) => { + const res = await client.query('SELECT 1 AS num') + client.HOOK_CONNECT_RESULT = res.rows[0].num + }, + }) + const client = await pool.connect() + expect(client.HOOK_CONNECT_RESULT).to.equal(1) + const res = await client.query('SELECT 1 AS num') + expect(res.rows[0].num).to.equal(1) + client.release() + const client2 = await pool.connect() + expect(client).to.equal(client2) + expect(client2.HOOK_CONNECT_RESULT).to.equal(1) + client.release() + await pool.end() + }) + + it('errors out the connect call if the async connect hook rejects', async () => { + const pool = new Pool({ + onConnect: async (client) => { + await client.query('SELECT INVALID HERE') + }, + }) + try { + await pool.connect() + throw new Error('Expected connect to throw') + } catch (err) { + expect(err.message).to.contain('invalid') + } + await pool.end() + }) + + it('calls onConnect when using pool.query', async () => { + const pool = new Pool({ + onConnect: async (client) => { + const res = await client.query('SELECT 1 AS num') + client.HOOK_CONNECT_RESULT = res.rows[0].num + }, + }) + const res = await pool.query('SELECT $1::text AS name', ['brianc']) + expect(res.rows[0].name).to.equal('brianc') + const client = await pool.connect() + expect(client.HOOK_CONNECT_RESULT).to.equal(1) + client.release() + await pool.end() + }) + + it('recovers after a hook error', async () => { + let shouldError = true + const pool = new Pool({ + onConnect: () => { + if (shouldError) { + throw new Error('connect hook error') + } + }, + }) + try { + await pool.connect() + throw new Error('Expected connect to throw') + } catch (err) { + expect(err.message).to.equal('connect hook error') + } + shouldError = false + const client = await pool.connect() + const res = await client.query('SELECT 1 AS num') + expect(res.rows[0].num).to.equal(1) + client.release() + await pool.end() + }) + + it('calls onConnect for each new client', async () => { + let connectCount = 0 + const pool = new Pool({ + max: 2, + onConnect: async (client) => { + connectCount++ + await client.query('SELECT 1') + }, + }) + const client1 = await pool.connect() + const client2 = await pool.connect() + expect(connectCount).to.equal(2) + expect(client1).to.not.equal(client2) + client1.release() + client2.release() + await pool.end() + }) + + it('cleans up clients after repeated hook failures', async () => { + let errorCount = 0 + const pool = new Pool({ + max: 2, + onConnect: () => { + if (errorCount < 10) { + errorCount++ + throw new Error('connect hook error') + } + }, + }) + for (let i = 0; i < 10; i++) { + let threw = false + try { + await pool.connect() + } catch (err) { + threw = true + expect(err.message).to.equal('connect hook error') + } + expect(threw).to.equal(true) + } + expect(errorCount).to.equal(10) + expect(pool.totalCount).to.equal(0) + expect(pool.idleCount).to.equal(0) + const client1 = await pool.connect() + const res1 = await client1.query('SELECT 1 AS num') + expect(res1.rows[0].num).to.equal(1) + const client2 = await pool.connect() + const res2 = await client2.query('SELECT 2 AS num') + expect(res2.rows[0].num).to.equal(2) + expect(pool.totalCount).to.equal(2) + client1.release() + client2.release() + await pool.end() + }) + + it('errors out the connect call if the connect hook throws', async () => { + const pool = new Pool({ + onConnect: () => { + throw new Error('connect hook error') + }, + }) + try { + await pool.connect() + throw new Error('Expected connect to throw') + } catch (err) { + expect(err.message).to.equal('connect hook error') + } + await pool.end() + }) +}) diff --git a/packages/pg-pool/test/lifetime-timeout.js b/packages/pg-pool/test/lifetime-timeout.js index 0cdd8c886..e9fa14f19 100644 --- a/packages/pg-pool/test/lifetime-timeout.js +++ b/packages/pg-pool/test/lifetime-timeout.js @@ -12,7 +12,6 @@ describe('lifetime timeout', () => { const pool = new Pool({ maxLifetimeSeconds: 1 }) pool.query('SELECT NOW()') pool.on('remove', () => { - console.log('expired while idle - on-remove event') expect(pool.expiredCount).to.equal(0) expect(pool.totalCount).to.equal(0) done() @@ -22,7 +21,6 @@ describe('lifetime timeout', () => { const pool = new Pool({ maxLifetimeSeconds: 1 }) pool.query('SELECT pg_sleep(1.4)') pool.on('remove', () => { - console.log('expired while busy - on-remove event') expect(pool.expiredCount).to.equal(0) expect(pool.totalCount).to.equal(0) done() diff --git a/packages/pg-pool/test/timeout.js b/packages/pg-pool/test/timeout.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index b0772ab50..f2920d569 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.11.0", + "version": "1.16.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -16,13 +16,12 @@ "license": "MIT", "devDependencies": { "@types/chai": "^4.2.7", - "@types/mocha": "^10.0.7", - "@types/node": "^12.12.21", + "@types/mocha": "^10.0.10", + "@types/node": "^16", "chai": "^4.2.0", - "chunky": "^0.0.0", - "mocha": "^10.5.2", + "mocha": "^11.7.5", "ts-node": "^8.5.4", - "typescript": "^4.0.3" + "typescript": "^6.0.3" }, "scripts": { "test": "mocha dist/**/*.test.js", diff --git a/packages/pg-protocol/src/buffer-reader.ts b/packages/pg-protocol/src/buffer-reader.ts index 62b16a2ed..42a4a23fa 100644 --- a/packages/pg-protocol/src/buffer-reader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -1,10 +1,8 @@ -const emptyBuffer = Buffer.allocUnsafe(0) - export class BufferReader { - private buffer: Buffer = emptyBuffer + private buffer: Buffer = Buffer.allocUnsafe(0) // TODO(bmc): support non-utf8 encoding? - private encoding: string = 'utf-8' + private encoding: BufferEncoding = 'utf-8' constructor(private offset: number = 0) {} @@ -47,7 +45,7 @@ export class BufferReader { const start = this.offset let end = start // eslint-disable-next-line no-empty - while (this.buffer[end++] !== 0) {} + while (this.buffer[end++]) {} this.offset = end return this.buffer.toString(this.encoding, start, end - 1) } diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts index cebb0d9ed..eb69cc8ce 100644 --- a/packages/pg-protocol/src/buffer-writer.ts +++ b/packages/pg-protocol/src/buffer-writer.ts @@ -1,7 +1,7 @@ //binary data writer tuned for encoding binary specific to the postgres binary protocol export class Writer { - private buffer: Buffer + public buffer: Buffer private offset: number = 5 private headerPosition: number = 0 constructor(private size = 256) { @@ -16,7 +16,7 @@ export class Writer { // https://stackoverflow.com/questions/2269063/buffer-growth-strategy const newSize = oldBuffer.length + (oldBuffer.length >> 1) + size this.buffer = Buffer.allocUnsafe(newSize) - oldBuffer.copy(this.buffer) + oldBuffer.copy(this.buffer, 0, 0, this.offset) } } @@ -58,6 +58,26 @@ export class Writer { return this } + // Write an Int32 byte-length prefix immediately followed by the string's UTF-8 + // bytes. Postgres' Bind wire format prefixes every parameter with its length, + // and doing it in one method computes Buffer.byteLength ONCE — the previous + // `addInt32(Buffer.byteLength(s)).addString(s)` pairing scanned the string + // three times (byteLength for the prefix, byteLength again inside addString, + // then the encode), which is costly for large text parameters. + public addInt32PrefixedString(string: string): Writer { + const len = Buffer.byteLength(string) + this.ensure(4 + len) + const buffer = this.buffer + let offset = this.offset + buffer[offset++] = (len >>> 24) & 0xff + buffer[offset++] = (len >>> 16) & 0xff + buffer[offset++] = (len >>> 8) & 0xff + buffer[offset++] = (len >>> 0) & 0xff + buffer.write(string, offset, 'utf-8') + this.offset = offset + len + return this + } + public add(otherBuffer: Buffer): Writer { this.ensure(otherBuffer.length) otherBuffer.copy(this.buffer, this.offset) @@ -65,6 +85,16 @@ export class Writer { return this } + /** + * Appends an uninitialized block of {@link size} bytes to the buffer and returns its offset. + */ + public reserveUnsafe(size: number): number { + const offset = this.offset + this.ensure(size) + this.offset += size + return offset + } + private join(code?: number): Buffer { if (code) { this.buffer[this.headerPosition] = code @@ -82,4 +112,9 @@ export class Writer { this.buffer = Buffer.allocUnsafe(this.size) return result } + + public clear(): void { + this.offset = 5 + this.headerPosition = 0 + } } diff --git a/packages/pg-protocol/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts index 285f4bf2b..8687194c3 100644 --- a/packages/pg-protocol/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -161,6 +161,8 @@ const oneParameterDescBuf = buffers.parameterDescription([1111]) const twoParameterDescBuf = buffers.parameterDescription([2222, 3333]) +const bigOidParameterDescBuf = buffers.parameterDescription([3000000003]) + const expectedEmptyParameterDescriptionMessage = { name: 'parameterDescription', length: 6, @@ -182,6 +184,13 @@ const expectedTwoParameterMessage = { dataTypeIDs: [2222, 3333], } +const expectedBigOidParameterMessage = { + name: 'parameterDescription', + length: 10, + parameterCount: 1, + dataTypeIDs: [3000000003], +} + const testForMessage = function (buffer: Buffer, expectedMessage: any) { it('receives and parses ' + expectedMessage.name, async () => { const messages = await parseBuffers([buffer]) @@ -288,6 +297,7 @@ describe('PgPacketStream', function () { testForMessage(emptyParameterDescriptionBuffer, expectedEmptyParameterDescriptionMessage) testForMessage(oneParameterDescBuf, expectedOneParameterMessage) testForMessage(twoParameterDescBuf, expectedTwoParameterMessage) + testForMessage(bigOidParameterDescBuf, expectedBigOidParameterMessage) }) describe('parsing rows', function () { diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index 0d3e387e4..aac0c57ba 100644 --- a/packages/pg-protocol/src/outbound-serializer.test.ts +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -129,6 +129,28 @@ describe('serializer', () => { .join(true, 'B') assert.deepEqual(actual, expectedBuffer) }) + + it('encodes a multi-byte string param with its UTF-8 byte length, not char length', function () { + // Guards the single-pass addInt32PrefixedString write path: the Int32 + // length prefix must be the UTF-8 byte count, not String.length. 'héllo中🎉' + // is 7 code points / 8 UTF-16 code units but 13 UTF-8 bytes. + const value = 'héllo中🎉' + const bytes = Buffer.from(value, 'utf8') + assert.notEqual(bytes.length, value.length) // sanity: the divergence we're testing + const actual = serialize.bind({ values: [value] }) + const expectedBuffer = new BufferList() + .addCString('') // portal + .addCString('') // statement + .addInt16(1) // param format code count + .addInt16(0) // format code for the one value (text) + .addInt16(1) // value count + .addInt32(bytes.length) // 13 — the UTF-8 byte length, NOT value.length (8) + .add(bytes) + .addInt16(1) // result format code count + .addInt16(0) // result format (text) + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) }) it('with custom valueMapper', function () { @@ -273,4 +295,62 @@ describe('serializer', () => { const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true) assert.deepEqual(actual, expected) }) + + describe('bind error recovery', () => { + const throwingMapper = () => { + throw new Error('valueMapper error') + } + + it('produces correct bind output after a valueMapper exception', () => { + assert.throws(() => { + serialize.bind({ + values: ['fail'], + valueMapper: throwingMapper, + }) + }, /valueMapper error/) + + const actual = serialize.bind({ + portal: 'bang', + statement: 'woo', + values: ['1', 'hi', null, 'zing'], + }) + const expectedBuffer = new BufferList() + .addCString('bang') + .addCString('woo') + .addInt16(4) + .addInt16(0) + .addInt16(0) + .addInt16(0) + .addInt16(0) + .addInt16(4) + .addInt32(1) + .add(Buffer.from('1')) + .addInt32(2) + .add(Buffer.from('hi')) + .addInt32(-1) + .addInt32(4) + .add(Buffer.from('zing')) + .addInt16(1) + .addInt16(0) + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) + + it('produces correct output from other serializer methods after a failed bind', () => { + assert.throws(() => { + serialize.bind({ + values: ['fail'], + valueMapper: throwingMapper, + }) + }, /valueMapper error/) + + const parseActual = serialize.parse({ text: '!' }) + const parseExpected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') + assert.deepEqual(parseActual, parseExpected) + + const queryActual = serialize.query('select 1') + const queryExpected = new BufferList().addCString('select 1').join(true, 'Q') + assert.deepEqual(queryActual, queryExpected) + }) + }) }) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 998077a00..df48ca4a1 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -28,7 +28,7 @@ import { } from './messages' import { BufferReader } from './buffer-reader' -// every message is prefixed with a single bye +// every message is prefixed with a single byte const CODE_LENGTH = 1 // every message has an int32 length which includes itself but does // NOT include the code in the length @@ -300,7 +300,8 @@ const parseParameterDescriptionMessage = (reader: BufferReader) => { const parameterCount = reader.int16() const message = new ParameterDescriptionMessage(LATEINIT_LENGTH, parameterCount) for (let i = 0; i < parameterCount; i++) { - message.dataTypeIDs[i] = reader.int32() + // OIDs are unsigned, same as dataTypeID in parseField above + message.dataTypeIDs[i] = reader.uint32() } return message } diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index bb0441f56..bbd59623e 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -48,7 +48,7 @@ const password = (password: string): Buffer => { const sendSASLInitialResponseMessage = function (mechanism: string, initialResponse: string): Buffer { // 0x70 = 'p' - writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) + writer.addCString(mechanism).addInt32PrefixedString(initialResponse) return writer.flush(code.startup) } @@ -110,34 +110,36 @@ type BindOpts = { valueMapper?: ValueMapper } -const paramWriter = new Writer() - // make this a const enum so typescript will inline the value const enum ParamType { STRING = 0, BINARY = 1, } -const writeValues = function (values: any[], valueMapper?: ValueMapper): void { - for (let i = 0; i < values.length; i++) { +const writeValues = function (values: any[], valueMapper: ValueMapper | undefined, formatsOffset: number): void { + const len = values.length + for (let i = 0; i < len; i++) { const mappedVal = valueMapper ? valueMapper(values[i], i) : values[i] + let formatByte = ParamType.STRING + if (mappedVal == null) { - // add the param type (string) to the writer - writer.addInt16(ParamType.STRING) - // write -1 to the param writer to indicate null - paramWriter.addInt32(-1) + // write -1 to indicate null + writer.addInt32(-1) } else if (mappedVal instanceof Buffer) { - // add the param type (binary) to the writer - writer.addInt16(ParamType.BINARY) + formatByte = ParamType.BINARY + // add the buffer to the param writer - paramWriter.addInt32(mappedVal.length) - paramWriter.add(mappedVal) + writer.addInt32(mappedVal.length) + writer.add(mappedVal) } else { - // add the param type (string) to the writer - writer.addInt16(ParamType.STRING) - paramWriter.addInt32(Buffer.byteLength(mappedVal)) - paramWriter.addString(mappedVal) + // length prefix + UTF-8 bytes in one pass (Buffer.byteLength computed once) + writer.addInt32PrefixedString(mappedVal) } + + // beware: `writer` operations can replace `writer.buffer` with a new buffer + const buf = writer.buffer + buf[formatsOffset++] = 0 + buf[formatsOffset++] = formatByte } } @@ -150,12 +152,22 @@ const bind = (config: BindOpts = {}): Buffer => { const len = values.length writer.addCString(portal).addCString(statement) + + // number of parameter format codes writer.addInt16(len) - writeValues(values, config.valueMapper) + // space for those codes, filled by `writeValues` + const formatsOffset = writer.reserveUnsafe(len * 2) + // number of parameter values writer.addInt16(len) - writer.add(paramWriter.flush()) + + try { + writeValues(values, config.valueMapper, formatsOffset) + } catch (err) { + writer.clear() + throw err + } // all results use the same format code writer.addInt16(1) diff --git a/packages/pg-protocol/src/types/chunky.d.ts b/packages/pg-protocol/src/types/chunky.d.ts deleted file mode 100644 index 7389bda66..000000000 --- a/packages/pg-protocol/src/types/chunky.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'chunky' diff --git a/packages/pg-protocol/tsconfig.json b/packages/pg-protocol/tsconfig.json index 0ae32c8dc..7b31d4d92 100644 --- a/packages/pg-protocol/tsconfig.json +++ b/packages/pg-protocol/tsconfig.json @@ -9,15 +9,18 @@ "moduleResolution": "node16", "sourceMap": true, "outDir": "dist", + "rootDir": "./src", "incremental": true, - "baseUrl": ".", "declaration": true, "paths": { "*": [ - "node_modules/*", - "src/types/*" + "./node_modules/*" ] - } + }, + "types": [ + "node", + "mocha" + ] }, "include": [ "src/**/*" diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7f3399a54..30c416e19 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.12.0", + "version": "4.17.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -38,22 +38,22 @@ }, "devDependencies": { "@types/chai": "^4.2.13", - "@types/mocha": "^10.0.7", - "@types/node": "^14.0.0", + "@types/mocha": "^10.0.10", + "@types/node": "^16.0.0", "@types/pg": "^7.14.5", "JSONStream": "~1.3.5", "concat-stream": "~1.0.1", - "eslint-plugin-promise": "^7.2.1", - "mocha": "^10.5.2", - "pg": "^8.18.0", + "eslint-plugin-promise": "^7.3.0", + "mocha": "^11.7.5", + "pg": "^8.23.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", - "typescript": "^4.0.3" + "typescript": "^6.0.3" }, "peerDependencies": { "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.17.0" + "pg-cursor": "^2.22.0" } } diff --git a/packages/pg-query-stream/src/index.ts b/packages/pg-query-stream/src/index.ts index c942b0441..752e881ca 100644 --- a/packages/pg-query-stream/src/index.ts +++ b/packages/pg-query-stream/src/index.ts @@ -13,6 +13,7 @@ class QueryStream extends Readable implements Submittable { cursor: any _result: any + callback: Function handleRowDescription: Function handleDataRow: Function handlePortalSuspended: Function @@ -26,6 +27,13 @@ class QueryStream extends Readable implements Submittable { super({ objectMode: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }) this.cursor = new Cursor(text, values, config) + this.cursor + .on('end', (result) => { + this.callback && this.callback(null, result) + }) + .on('error', (err) => { + this.callback && this.callback(err) + }) // delegate Submittable callbacks to cursor this.handleRowDescription = this.cursor.handleRowDescription.bind(this.cursor) @@ -64,4 +72,8 @@ class QueryStream extends Readable implements Submittable { } } +namespace QueryStream { + export type Config = QueryStreamConfig +} + export = QueryStream diff --git a/packages/pg-query-stream/test/error.ts b/packages/pg-query-stream/test/error.ts index 8ddb4da7d..5f7a78565 100644 --- a/packages/pg-query-stream/test/error.ts +++ b/packages/pg-query-stream/test/error.ts @@ -170,4 +170,24 @@ describe('error recovery', () => { conn.release() await pool.end() }) + + it('does not crash when query_timeout fires without callback', async () => { + const client = new Client({ query_timeout: 50 }) + await client.connect() + + const stream = new QueryStream('SELECT pg_sleep(10)') + + // cursor.on('error') fires synchronously when handleError is called + // stream.on('error') fires asynchronously via destroy() + // Use cursor for immediate error detection + const errorPromise = new Promise((resolve) => { + stream.cursor.on('error', resolve) + }) + + client.query(stream) + + const error = await errorPromise + assert.equal(error.message, 'Query read timeout') + await client.end() + }) }) diff --git a/packages/pg-query-stream/test/pool.ts b/packages/pg-query-stream/test/pool.ts new file mode 100644 index 000000000..06adf8e18 --- /dev/null +++ b/packages/pg-query-stream/test/pool.ts @@ -0,0 +1,17 @@ +import { Pool } from 'pg' +import QueryStream from '../src' + +describe('pool', function () { + it('works', async function () { + const pool = new Pool() + const query = new QueryStream('SELECT * FROM generate_series(0, 10) num', []) + const q = pool.query(query) + query.on('data', (row) => { + // just consume the whole stream + }) + await q + query.on('end', () => { + pool.end() + }) + }) +}) diff --git a/packages/pg-query-stream/tsconfig.json b/packages/pg-query-stream/tsconfig.json index 56eec5083..e9c97b335 100644 --- a/packages/pg-query-stream/tsconfig.json +++ b/packages/pg-query-stream/tsconfig.json @@ -10,8 +10,8 @@ "sourceMap": true, "pretty": true, "outDir": "dist", + "rootDir": "./src", "incremental": true, - "baseUrl": ".", "declaration": true, "types": [ "node", diff --git a/packages/pg/Makefile b/packages/pg/Makefile index 5575acfd8..2979dd750 100644 --- a/packages/pg/Makefile +++ b/packages/pg/Makefile @@ -6,7 +6,7 @@ params := $(connectionString) node-command := xargs -n 1 -I file node file $(params) -.PHONY : test test-connection test-integration bench test-native \ +.PHONY : test test-integration bench test-native \ publish update-npm all: @@ -27,13 +27,10 @@ bench: @find benchmark -name "*-bench.js" | $(node-command) test-unit: + @chmod 600 test/unit/client/pgpass.file @find test/unit -name "*-tests.js" | $(node-command) -test-connection: - @echo "***Testing connection***" - @node script/create-test-tables.js $(params) - -test-native: test-connection +test-native: @echo "***Testing native bindings***" ifeq ($(TEST_SKIP_NATIVE), true) @echo "***Skipping tests***" @@ -42,11 +39,11 @@ else @find test/integration -name "*-tests.js" | $(node-command) native endif -test-integration: test-connection +test-integration: @echo "***Testing Pure Javascript***" @find test/integration -name "*-tests.js" | $(node-command) -test-binary: test-connection +test-binary: @echo "***Testing Pure Javascript (binary)***" @find test/integration -name "*-tests.js" | $(node-command) binary diff --git a/packages/pg/README.md b/packages/pg/README.md index bf4effefb..2fca0eb10 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -18,6 +18,7 @@ $ npm install pg ### Features +- [Fastest PostgreSQL client for Node.js](https://github.com/nigrosimone/postgres-benchmarks) - Pure JavaScript client and native libpq bindings share _the same API_ - Connection pooling - Extensible JS ↔ PostgreSQL data-type coercion @@ -42,7 +43,7 @@ When you open an issue please provide: - version of Postgres - smallest possible snippet of code to reproduce the problem -You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. +You can also follow me [@brianc](https://bsky.app/profile/brianc.bsky.social) on bluesky if that's your thing for updates on node-postgres with nearly zero non node-postgres content. My old twitter/x account is no longer used. ## Sponsorship :two_hearts: diff --git a/packages/pg/bench-pipelining.js b/packages/pg/bench-pipelining.js new file mode 100644 index 000000000..90f384806 --- /dev/null +++ b/packages/pg/bench-pipelining.js @@ -0,0 +1,216 @@ +'use strict' +const pg = require('./lib') + +let Native +try { + Native = require('pg-native') +} catch (e) { + // pg-native not available — skip native benchmarks +} + +const SECONDS = 5 +const BATCH = 10 + +async function bench(label, fn, seconds) { + // warmup + for (let i = 0; i < 100; i++) await fn() + + const deadline = Date.now() + seconds * 1000 + let count = 0 + while (Date.now() < deadline) { + await fn() + count++ + } + const qps = (count / seconds).toFixed(0) + console.log(` ${label}: ${qps} qps (${count} queries in ${seconds}s)`) + return count / seconds +} + +// --- JS client helpers --- + +async function jsSerial(label, query, seconds) { + const client = new pg.Client() + await client.connect() + const qps = await bench(label, () => client.query(query), seconds) + await client.end() + return qps +} + +async function jsPipelined(label, makeQueries, batchSize, seconds) { + const client = new pg.Client({ pipeline: true }) + await client.connect() + + // warmup + for (let i = 0; i < 10; i++) { + await Promise.all(makeQueries(batchSize).map((q) => client.query(q))) + } + + const deadline = Date.now() + seconds * 1000 + let count = 0 + while (Date.now() < deadline) { + await Promise.all(makeQueries(batchSize).map((q) => client.query(q))) + count += batchSize + } + const qps = (count / seconds).toFixed(0) + console.log(` ${label} (batch=${batchSize}): ${qps} qps`) + await client.end() + return count / seconds +} + +// --- Native client helpers --- + +function nativeConnect() { + return new Promise((resolve, reject) => { + const client = new Native() + client.connect((err) => { + if (err) return reject(err) + resolve(client) + }) + }) +} + +function nativeQuery(client, text, values) { + return new Promise((resolve, reject) => { + client.query(text, values, (err, rows) => { + if (err) return reject(err) + resolve(rows) + }) + }) +} + +function nativeEnd(client) { + return new Promise((resolve) => { + client.end(() => resolve()) + }) +} + +function nativePipeline(client, queries) { + return new Promise((resolve, reject) => { + client.pipeline(queries, (err, results) => { + if (err) return reject(err) + resolve(results) + }) + }) +} + +async function nativeSerial(label, text, values, seconds) { + const client = await nativeConnect() + + // warmup + for (let i = 0; i < 100; i++) await nativeQuery(client, text, values) + + const deadline = Date.now() + seconds * 1000 + let count = 0 + while (Date.now() < deadline) { + await nativeQuery(client, text, values) + count++ + } + const qps = (count / seconds).toFixed(0) + console.log(` ${label}: ${qps} qps (${count} queries in ${seconds}s)`) + await nativeEnd(client) + return count / seconds +} + +async function nativePipelined(label, makeQueries, batchSize, seconds) { + const client = await nativeConnect() + + // warmup + for (let i = 0; i < 10; i++) { + await nativePipeline(client, makeQueries(batchSize)) + } + + const deadline = Date.now() + seconds * 1000 + let count = 0 + while (Date.now() < deadline) { + await nativePipeline(client, makeQueries(batchSize)) + count += batchSize + } + const qps = (count / seconds).toFixed(0) + console.log(` ${label} (batch=${batchSize}): ${qps} qps`) + await nativeEnd(client) + return count / seconds +} + +// --- Main --- + +async function run() { + const results = {} + + console.log('\n=== JS Client — Serial ===') + results.jsSerialSimple = await jsSerial('simple SELECT 1', { text: 'SELECT 1' }, SECONDS) + results.jsSerialParam = await jsSerial('parameterized', { text: 'SELECT $1::int AS n', values: [42] }, SECONDS) + results.jsSerialNamed = await jsSerial( + 'named prepared', + { name: 'bench-named', text: 'SELECT $1::int AS n', values: [42] }, + SECONDS + ) + + console.log('\n=== JS Client — Pipelined ===') + results.jsPipedSimple = await jsPipelined( + 'simple SELECT 1', + (n) => Array.from({ length: n }, () => ({ text: 'SELECT 1' })), + BATCH, + SECONDS + ) + results.jsPipedParam = await jsPipelined( + 'parameterized', + (n) => Array.from({ length: n }, () => ({ text: 'SELECT $1::int AS n', values: [42] })), + BATCH, + SECONDS + ) + results.jsPipedNamed = await jsPipelined( + 'named prepared', + (n) => + Array.from({ length: n }, (_, i) => ({ name: `bench-named-${i}`, text: 'SELECT $1::int AS n', values: [42] })), + BATCH, + SECONDS + ) + + if (Native) { + console.log('\n=== Native Client — Serial ===') + results.nativeSerialSimple = await nativeSerial('simple SELECT 1', 'SELECT 1', undefined, SECONDS) + results.nativeSerialParam = await nativeSerial('parameterized', 'SELECT $1::int AS n', [42], SECONDS) + + console.log('\n=== Native Client — Pipelined ===') + results.nativePipedSimple = await nativePipelined( + 'simple SELECT 1', + (n) => Array.from({ length: n }, () => ({ text: 'SELECT 1' })), + BATCH, + SECONDS + ) + results.nativePipedParam = await nativePipelined( + 'parameterized', + (n) => Array.from({ length: n }, () => ({ text: 'SELECT $1::int AS n', values: [42] })), + BATCH, + SECONDS + ) + } else { + console.log('\n(pg-native not available — skipping native benchmarks)') + } + + // --- Summary --- + console.log('\n=== Speedup Summary ===') + console.log('JS pipelining vs serial:') + console.log(` simple: ${(results.jsPipedSimple / results.jsSerialSimple).toFixed(2)}x`) + console.log(` parameterized: ${(results.jsPipedParam / results.jsSerialParam).toFixed(2)}x`) + console.log(` named: ${(results.jsPipedNamed / results.jsSerialNamed).toFixed(2)}x`) + + if (Native) { + console.log('Native pipelining vs serial:') + console.log(` simple: ${(results.nativePipedSimple / results.nativeSerialSimple).toFixed(2)}x`) + console.log(` parameterized: ${(results.nativePipedParam / results.nativeSerialParam).toFixed(2)}x`) + + console.log('Native serial vs JS serial:') + console.log(` simple: ${(results.nativeSerialSimple / results.jsSerialSimple).toFixed(2)}x`) + console.log(` parameterized: ${(results.nativeSerialParam / results.jsSerialParam).toFixed(2)}x`) + + console.log('Native pipelined vs JS pipelined:') + console.log(` simple: ${(results.nativePipedSimple / results.jsPipedSimple).toFixed(2)}x`) + console.log(` parameterized: ${(results.nativePipedParam / results.jsPipedParam).toFixed(2)}x`) + } +} + +run().catch((e) => { + console.error(e) + process.exit(1) +}) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index b0214e3dc..2b13c1de7 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -1,5 +1,3 @@ -'use strict' - const EventEmitter = require('events').EventEmitter const utils = require('./utils') const nodeUtils = require('util') @@ -14,25 +12,41 @@ const crypto = require('./crypto/utils') const activeQueryDeprecationNotice = nodeUtils.deprecate( () => {}, - 'Client.activeQuery is deprecated and will be removed in a future version.' + 'Client.activeQuery is deprecated and will be removed in pg@9.0' ) const queryQueueDeprecationNotice = nodeUtils.deprecate( () => {}, - 'Client.queryQueue is deprecated and will be removed in a future version.' + 'Client.queryQueue is deprecated and will be removed in pg@9.0.' ) const pgPassDeprecationNotice = nodeUtils.deprecate( () => {}, - 'pgpass support is deprecated and will be removed in a future version. ' + - 'You can provide an async function as the password property to the Client/Pool constructor that returns a password instead. Within this funciton you can call the pgpass module in your own code.' + 'pgpass support is deprecated and will be removed in pg@9.0. ' + + 'You can provide an async function as the password property to the Client/Pool constructor that returns a password instead. Within this function you can call the pgpass module in your own code.' ) const byoPromiseDeprecationNotice = nodeUtils.deprecate( () => {}, - 'Passing a custom Promise implementation to the Client/Pool constructor is deprecated and will be removed in a future version.' + 'Passing a custom Promise implementation to the Client/Pool constructor is deprecated and will be removed in pg@9.0.' ) +const queryQueueLengthDeprecationNotice = nodeUtils.deprecate( + () => {}, + 'Calling client.query() when the client is already executing a query is deprecated and will be removed in pg@9.0. Use async/await or an external async flow control mechanism instead.' +) + +function coerceNumberOrDefault(value, defaultValue) { + if (typeof value === 'number') { + return Number.isFinite(value) ? value : defaultValue + } + if (typeof value === 'string' && value.trim() !== '') { + const n = Number(value) + return Number.isFinite(n) ? n : defaultValue + } + return defaultValue +} + class Client extends EventEmitter { constructor(config) { super() @@ -68,22 +82,28 @@ class Client extends EventEmitter { this._connectionError = false this._queryable = true this._activeQuery = null + this._txStatus = null this.enableChannelBinding = Boolean(c.enableChannelBinding) // set true to use SCRAM-SHA-256-PLUS when offered + this.scramMaxIterations = coerceNumberOrDefault(c.scramMaxIterations, sasl.DEFAULT_MAX_SCRAM_ITERATIONS) this.connection = c.connection || new Connection({ stream: c.stream, ssl: this.connectionParameters.ssl, + sslNegotiation: this.connectionParameters.sslnegotiation, keepAlive: c.keepAlive || false, keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0, encoding: this.connectionParameters.client_encoding || 'utf8', }) this._queryQueue = [] + this._sentQueryQueue = [] + this.pipeline = Boolean(c.pipeline) this.binary = c.binary || defaults.binary this.processID = null this.secretKey = null this.ssl = this.connectionParameters.ssl || false + this.sslNegotiation = this.connectionParameters.sslnegotiation || 'postgres' // As with Password, make SSL->Key (the private key) non-enumerable. // It won't show up in stack traces // or if the client is console.logged @@ -123,6 +143,9 @@ class Client extends EventEmitter { this._activeQuery = null } + this._sentQueryQueue.forEach(enqueueError) + this._sentQueryQueue.length = 0 + this._queryQueue.forEach(enqueueError) this._queryQueue.length = 0 } @@ -161,7 +184,11 @@ class Client extends EventEmitter { // once connection is established send startup message con.on('connect', function () { if (self.ssl) { - con.requestSsl() + // With direct SSL negotiation the connection upgrades to TLS without an + // SSLRequest packet, so the startup message is sent after 'sslconnect'. + if (self.sslNegotiation !== 'direct') { + con.requestSsl() + } } else { con.startup(self.getStartupConf()) } @@ -249,7 +276,7 @@ class Client extends EventEmitter { if (typeof this.password === 'function') { this._Promise .resolve() - .then(() => this.password()) + .then(() => this.password(this.connectionParameters)) .then((pass) => { if (pass !== undefined) { if (typeof pass !== 'string') { @@ -303,7 +330,11 @@ class Client extends EventEmitter { _handleAuthSASL(msg) { this._getPassword(() => { try { - this.saslSession = sasl.startSession(msg.mechanisms, this.enableChannelBinding && this.connection.stream) + this.saslSession = sasl.startSession( + msg.mechanisms, + this.enableChannelBinding && this.connection.stream, + this.scramMaxIterations + ) this.connection.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response) } catch (err) { this.connection.emit('error', err) @@ -356,6 +387,7 @@ class Client extends EventEmitter { } const activeQuery = this._getActiveQuery() this._activeQuery = null + this._txStatus = msg?.status ?? null this.readyForQuery = true if (activeQuery) { activeQuery.handleReadyForQuery(this.connection) @@ -403,6 +435,9 @@ class Client extends EventEmitter { } this._activeQuery = null + if (activeQuery.name) { + delete this.connection.submittedNamedStatements[activeQuery.name] + } activeQuery.handleError(msg, this.connection) } @@ -473,6 +508,7 @@ class Client extends EventEmitter { // it again on the same client if (activeQuery.name) { this.connection.parsedStatements[activeQuery.name] = activeQuery.text + delete this.connection.submittedNamedStatements[activeQuery.name] } } @@ -551,6 +587,10 @@ class Client extends EventEmitter { }) } else if (client._queryQueue.indexOf(query) !== -1) { client._queryQueue.splice(client._queryQueue.indexOf(query), 1) + } else if (client._sentQueryQueue.indexOf(query) !== -1) { + // Query already sent on wire — can't remove it without corrupting the + // pipeline. No-op the callback so the result is silently discarded. + query.callback = () => {} } } @@ -574,6 +614,10 @@ class Client extends EventEmitter { } _pulseQueryQueue() { + if (this.pipeline) { + this._pulsePipelinedQueryQueue() + return + } if (this.readyForQuery === true) { this._activeQuery = this._queryQueue.shift() const activeQuery = this._getActiveQuery() @@ -596,24 +640,50 @@ class Client extends EventEmitter { } } + _pulsePipelinedQueryQueue() { + if (!this._connected || !this._queryable) { + return + } + while (this._queryQueue.length > 0) { + const query = this._queryQueue.shift() + this.hasExecuted = true + const queryError = query.submit(this.connection) + if (queryError) { + process.nextTick(() => { + query.handleError(queryError, this.connection) + }) + continue + } + this._sentQueryQueue.push(query) + } + if (this.readyForQuery && !this._activeQuery && this._sentQueryQueue.length > 0) { + this._activeQuery = this._sentQueryQueue.shift() + this.readyForQuery = false + } + if (!this._activeQuery && this._sentQueryQueue.length === 0 && this._queryQueue.length === 0 && this.hasExecuted) { + this.emit('drain') + } + } + query(config, values, callback) { // can take in strings, config object or query object let query let result - let readTimeout - let readTimeoutTimer - let queryCallback - if (config === null || config === undefined) { + if (config == null) { throw new TypeError('Client was passed a null or undefined query') - } else if (typeof config.submit === 'function') { - readTimeout = config.query_timeout || this.connectionParameters.query_timeout + } + + if (typeof config.submit === 'function') { result = query = config - if (typeof values === 'function') { - query.callback = query.callback || values + if (!query.callback) { + if (typeof values === 'function') { + query.callback = values + } else if (callback) { + query.callback = callback + } } } else { - readTimeout = config.query_timeout || this.connectionParameters.query_timeout query = new Query(config, values, callback) if (!query.callback) { result = new this._Promise((resolve, reject) => { @@ -624,13 +694,16 @@ class Client extends EventEmitter { Error.captureStackTrace(err) throw err }) + } else if (typeof query.callback !== 'function') { + throw new TypeError('callback is not a function') } } + const readTimeout = config.query_timeout || this.connectionParameters.query_timeout if (readTimeout) { - queryCallback = query.callback + const queryCallback = query.callback || (() => {}) - readTimeoutTimer = setTimeout(() => { + const readTimeoutTimer = setTimeout(() => { const error = new Error('Query read timeout') process.nextTick(() => { @@ -643,10 +716,15 @@ class Client extends EventEmitter { // just do nothing if query completes query.callback = () => {} - // Remove from queue + // Remove from queue (only safe if not yet sent) const index = this._queryQueue.indexOf(query) if (index > -1) { this._queryQueue.splice(index, 1) + } else if (this.pipeline) { + // Query already sent — the pipeline is blocked until it completes. + // Destroy the connection to unblock all remaining pipelined queries. + this.connection.stream.destroy() + return } this._pulseQueryQueue() @@ -666,6 +744,24 @@ class Client extends EventEmitter { query._result._types = this._types } + // A query that keeps a portal open across round trips cannot share a pipelined connection: the + // queries written behind it are answered out of its portal, so rows land on the wrong query and + // the reads that follow fail with 'portal does not exist'. Refuse it instead of corrupting. + if (this.pipeline) { + const portalQuery = + typeof config.submit === 'function' && !(query instanceof Query) + ? 'Custom query classes such as pg-cursor and pg-query-stream are' + : query.rows + ? 'The `rows` option is' + : null + if (portalQuery) { + process.nextTick(() => { + query.handleError(new Error(`${portalQuery} not supported in pipeline mode`), this.connection) + }) + return result + } + } + if (!this._queryable) { process.nextTick(() => { query.handleError(new Error('Client has encountered a connection error and is not queryable'), this.connection) @@ -680,6 +776,9 @@ class Client extends EventEmitter { return result } + if (this._queryQueue.length > 0 && !this.pipeline) { + queryQueueLengthDeprecationNotice() + } this._queryQueue.push(query) this._pulseQueryQueue() return result @@ -693,6 +792,10 @@ class Client extends EventEmitter { this.connection.unref() } + getTransactionStatus() { + return this._txStatus + } + end(cb) { this._ending = true @@ -700,14 +803,24 @@ class Client extends EventEmitter { if (!this.connection._connecting || this._ended) { if (cb) { cb() + return } else { return this._Promise.resolve() } } - if (this._getActiveQuery() || !this._queryable) { - // if we have an active query we need to force a disconnect - // on the socket - otherwise a hung query could block end forever + if (!this._queryable) { + // socket is dead — force close + this.connection.stream.destroy() + } else if ( + this.pipeline && + (this._getActiveQuery() || this._sentQueryQueue.length > 0 || this._queryQueue.length > 0) + ) { + // pipelined queries are already on the wire (or queued to send) and will + // complete normally; wait for drain then do a graceful goodbye + this.once('drain', () => this.connection.end()) + } else if (this._getActiveQuery()) { + // non-pipeline: a hung query could block end forever — force disconnect this.connection.stream.destroy() } else { this.connection.end() diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index c153932bb..37987fd68 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -99,6 +99,18 @@ class ConnectionParameters { }) } + // How to negotiate SSL: 'postgres' (default, the traditional SSLRequest + // handshake) or 'direct' (start the TLS handshake immediately on connect). + this.sslnegotiation = val('sslnegotiation', config, 'PGSSLNEGOTIATION') + if (this.sslnegotiation !== undefined && this.sslnegotiation !== 'postgres' && this.sslnegotiation !== 'direct') { + throw new Error( + `Invalid sslnegotiation value: "${this.sslnegotiation}". Valid values are "postgres" and "direct".` + ) + } + if (this.sslnegotiation === 'direct' && !this.ssl) { + throw new Error('sslnegotiation=direct requires SSL to be enabled') + } + this.client_encoding = val('client_encoding', config) this.replication = val('replication', config) // a domain socket begins with '/' @@ -144,6 +156,7 @@ class ConnectionParameters { add(params, ssl, 'sslkey') add(params, ssl, 'sslcert') add(params, ssl, 'sslrootcert') + add(params, this, 'sslnegotiation') if (this.database) { params.push('dbname=' + quoteParamValue(this.database)) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 027f93935..62d38fa69 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -3,7 +3,8 @@ const EventEmitter = require('events').EventEmitter const { parse, serialize } = require('pg-protocol') -const { getStream, getSecureStream } = require('./stream') +const stream = require('./stream') +const { getStream } = stream const flushBuffer = serialize.flush() const syncBuffer = serialize.sync() @@ -23,7 +24,9 @@ class Connection extends EventEmitter { this._keepAlive = config.keepAlive this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis this.parsedStatements = {} + this.submittedNamedStatements = {} this.ssl = config.ssl || false + this.sslNegotiation = config.sslNegotiation || 'postgres' this._ending = false this._emitMessage = false const self = this @@ -65,6 +68,14 @@ class Connection extends EventEmitter { return this.attachListeners(this.stream) } + // With direct SSL negotiation the TLS handshake starts immediately on the + // raw socket, skipping the SSLRequest packet and the server's 'S'/'N' reply. + if (this.sslNegotiation === 'direct') { + return this.stream.once('connect', function () { + self.upgradeToSSL(host, reportStreamError) + }) + } + this.stream.once('data', function (buffer) { const responseCode = buffer.toString('utf8') switch (responseCode) { @@ -78,32 +89,43 @@ class Connection extends EventEmitter { self.stream.end() return self.emit('error', new Error('There was an error establishing an SSL connection')) } - const options = { - socket: self.stream, - } + self.upgradeToSSL(host, reportStreamError) + }) + } - if (self.ssl !== true) { - Object.assign(options, self.ssl) + upgradeToSSL(host, reportStreamError) { + const self = this + const options = { + socket: self.stream, + } - if ('key' in self.ssl) { - options.key = self.ssl.key - } - } + if (self.ssl !== true) { + Object.assign(options, self.ssl) - const net = require('net') - if (net.isIP && net.isIP(host) === 0) { - options.servername = host + if ('key' in self.ssl) { + options.key = self.ssl.key } - try { - self.stream = getSecureStream(options) - } catch (err) { - return self.emit('error', err) - } - self.attachListeners(self.stream) - self.stream.on('error', reportStreamError) + } - self.emit('sslconnect') - }) + // Direct SSL negotiation requires ALPN so the server can confirm it is + // speaking the PostgreSQL protocol over the TLS connection. + if (self.sslNegotiation === 'direct') { + options.ALPNProtocols = ['postgresql'] + } + + const net = require('net') + if (net.isIP && net.isIP(host) === 0) { + options.servername = host + } + try { + self.stream = stream.getSecureStream(options) + } catch (err) { + return self.emit('error', err) + } + self.attachListeners(self.stream) + self.stream.on('error', reportStreamError) + + self.emit('sslconnect') } attachListeners(stream) { diff --git a/packages/pg/lib/crypto/sasl.js b/packages/pg/lib/crypto/sasl.js index 47b77610c..ea63b2413 100644 --- a/packages/pg/lib/crypto/sasl.js +++ b/packages/pg/lib/crypto/sasl.js @@ -2,7 +2,37 @@ const crypto = require('./utils') const { signatureAlgorithmHashFromCertificate } = require('./cert-signatures') -function startSession(mechanisms, stream) { +// SASLprep (RFC 4013) — minimal in-tree implementation. +// +// Per RFC 5802 §2.2, the SCRAM-SHA-256 client must normalize the password via +// SASLprep before feeding it into PBKDF2. PostgreSQL's server applies the same +// SASLprep when computing the stored verifier, and libpq does the same client +// side, so passwords whose NFKC form differs from the raw form +// would otherwise authenticate against psql/libpq but fail against pg with `28P01`. +// +// We deliberately implement only the three steps that change the byte content: +// 1. RFC 3454 Table C.1.2 (non-ASCII space) → U+0020 SPACE. +// 2. RFC 3454 Table B.1 (commonly mapped to nothing) → empty. +// 3. NFKC normalization. +// We skip the prohibition (RFC 4013 §2.3) and bidi (RFC 3454 §6) checks. +// libpq is forgiving on those paths and Postgres's own SASLprep matches that +// leniency for legacy roles, so omitting the rejection logic keeps existing +// roles working without adding complexity. +function saslprep(password) { + // RFC 3454 Table C.1.2 — non-ASCII space characters, mapped to U+0020. + const nonAsciiSpace = /[\u00A0\u1680\u2000-\u200B\u202F\u205F\u3000]/g + // RFC 3454 Table B.1 — "commonly mapped to nothing". The set intentionally + // contains zero-width joiners and variation selectors — the very characters + // ESLint's no-misleading-character-class warns about — because they combine + // with their neighbors and the RFC strips them for that reason. + // eslint-disable-next-line no-misleading-character-class + const mappedToNothing = /[\u00AD\u034F\u1806\u180B\u180C\u180D\u200C\u200D\u2060\uFE00-\uFE0F\uFEFF]/g + return password.replace(nonAsciiSpace, ' ').replace(mappedToNothing, '').normalize('NFKC') +} + +const DEFAULT_MAX_SCRAM_ITERATIONS = 100000 + +function startSession(mechanisms, stream, scramMaxIterations = DEFAULT_MAX_SCRAM_ITERATIONS) { const candidates = ['SCRAM-SHA-256'] if (stream) candidates.unshift('SCRAM-SHA-256-PLUS') // higher-priority, so placed first @@ -25,6 +55,7 @@ function startSession(mechanisms, stream) { clientNonce, response: gs2Header + ',,n=*,r=' + clientNonce, message: 'SASLInitialResponse', + scramMaxIterations, } } @@ -50,6 +81,18 @@ async function continueSession(session, password, serverData, stream) { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce is too short') } + const scramMaxIterations = + typeof session.scramMaxIterations === 'number' ? session.scramMaxIterations : DEFAULT_MAX_SCRAM_ITERATIONS + // a value of 0 disables the iteration count check + if (scramMaxIterations !== 0 && sv.iteration > scramMaxIterations) { + throw new Error( + 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count ' + + sv.iteration + + ' exceeds scramMaxIterations of ' + + scramMaxIterations + ) + } + const clientFirstMessageBare = 'n=*,r=' + session.clientNonce const serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration @@ -70,7 +113,7 @@ async function continueSession(session, password, serverData, stream) { const authMessage = clientFirstMessageBare + ',' + serverFirstMessage + ',' + clientFinalMessageWithoutProof const saltBytes = Buffer.from(sv.salt, 'base64') - const saltedPassword = await crypto.deriveKey(password, saltBytes, sv.iteration) + const saltedPassword = await crypto.deriveKey(saslprep(password), saltBytes, sv.iteration) const clientKey = await crypto.hmacSha256(saltedPassword, 'Client Key') const storedKey = await crypto.sha256(clientKey) const clientSignature = await crypto.hmacSha256(storedKey, authMessage) @@ -178,7 +221,13 @@ function parseServerFirstMessage(data) { function parseServerFinalMessage(serverData) { const attrPairs = parseAttributePairs(serverData) + const error = attrPairs.get('e') const serverSignature = attrPairs.get('v') + + if (error) { + throw new Error(`SASL: SCRAM-SERVER-FINAL-MESSAGE: server returned error: "${error}"`) + } + if (!serverSignature) { throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is missing') } else if (!isBase64(serverSignature)) { @@ -209,4 +258,5 @@ module.exports = { startSession, continueSession, finalizeSession, + DEFAULT_MAX_SCRAM_ITERATIONS, } diff --git a/packages/pg/lib/crypto/utils-legacy.js b/packages/pg/lib/crypto/utils-legacy.js deleted file mode 100644 index d70fdb638..000000000 --- a/packages/pg/lib/crypto/utils-legacy.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict' -// This file contains crypto utility functions for versions of Node.js < 15.0.0, -// which does not support the WebCrypto.subtle API. - -const nodeCrypto = require('crypto') - -function md5(string) { - return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex') -} - -// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html -function postgresMd5PasswordHash(user, password, salt) { - const inner = md5(password + user) - const outer = md5(Buffer.concat([Buffer.from(inner), salt])) - return 'md5' + outer -} - -function sha256(text) { - return nodeCrypto.createHash('sha256').update(text).digest() -} - -function hashByName(hashName, text) { - hashName = hashName.replace(/(\D)-/, '$1') // e.g. SHA-256 -> SHA256 - return nodeCrypto.createHash(hashName).update(text).digest() -} - -function hmacSha256(key, msg) { - return nodeCrypto.createHmac('sha256', key).update(msg).digest() -} - -async function deriveKey(password, salt, iterations) { - return nodeCrypto.pbkdf2Sync(password, salt, iterations, 32, 'sha256') -} - -module.exports = { - postgresMd5PasswordHash, - randomBytes: nodeCrypto.randomBytes, - deriveKey, - sha256, - hashByName, - hmacSha256, - md5, -} diff --git a/packages/pg/lib/crypto/utils-webcrypto.js b/packages/pg/lib/crypto/utils-webcrypto.js deleted file mode 100644 index 65aa4a182..000000000 --- a/packages/pg/lib/crypto/utils-webcrypto.js +++ /dev/null @@ -1,89 +0,0 @@ -const nodeCrypto = require('crypto') - -module.exports = { - postgresMd5PasswordHash, - randomBytes, - deriveKey, - sha256, - hashByName, - hmacSha256, - md5, -} - -/** - * The Web Crypto API - grabbed from the Node.js library or the global - * @type Crypto - */ -// eslint-disable-next-line no-undef -const webCrypto = nodeCrypto.webcrypto || globalThis.crypto -/** - * The SubtleCrypto API for low level crypto operations. - * @type SubtleCrypto - */ -const subtleCrypto = webCrypto.subtle -const textEncoder = new TextEncoder() - -/** - * - * @param {*} length - * @returns - */ -function randomBytes(length) { - return webCrypto.getRandomValues(Buffer.alloc(length)) -} - -async function md5(string) { - try { - return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex') - } catch (e) { - // `createHash()` failed so we are probably not in Node.js, use the WebCrypto API instead. - // Note that the MD5 algorithm on WebCrypto is not available in Node.js. - // This is why we cannot just use WebCrypto in all environments. - const data = typeof string === 'string' ? textEncoder.encode(string) : string - const hash = await subtleCrypto.digest('MD5', data) - return Array.from(new Uint8Array(hash)) - .map((b) => b.toString(16).padStart(2, '0')) - .join('') - } -} - -// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html -async function postgresMd5PasswordHash(user, password, salt) { - const inner = await md5(password + user) - const outer = await md5(Buffer.concat([Buffer.from(inner), salt])) - return 'md5' + outer -} - -/** - * Create a SHA-256 digest of the given data - * @param {Buffer} data - */ -async function sha256(text) { - return await subtleCrypto.digest('SHA-256', text) -} - -async function hashByName(hashName, text) { - return await subtleCrypto.digest(hashName, text) -} - -/** - * Sign the message with the given key - * @param {ArrayBuffer} keyBuffer - * @param {string} msg - */ -async function hmacSha256(keyBuffer, msg) { - const key = await subtleCrypto.importKey('raw', keyBuffer, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']) - return await subtleCrypto.sign('HMAC', key, textEncoder.encode(msg)) -} - -/** - * Derive a key from the password and salt - * @param {string} password - * @param {Uint8Array} salt - * @param {number} iterations - */ -async function deriveKey(password, salt, iterations) { - const key = await subtleCrypto.importKey('raw', textEncoder.encode(password), 'PBKDF2', false, ['deriveBits']) - const params = { name: 'PBKDF2', hash: 'SHA-256', salt: salt, iterations: iterations } - return await subtleCrypto.deriveBits(params, key, 32 * 8, ['deriveBits']) -} diff --git a/packages/pg/lib/crypto/utils.js b/packages/pg/lib/crypto/utils.js index 9644b150f..65aa4a182 100644 --- a/packages/pg/lib/crypto/utils.js +++ b/packages/pg/lib/crypto/utils.js @@ -1,9 +1,89 @@ -'use strict' - -const useLegacyCrypto = parseInt(process.versions && process.versions.node && process.versions.node.split('.')[0]) < 15 -if (useLegacyCrypto) { - // We are on an old version of Node.js that requires legacy crypto utilities. - module.exports = require('./utils-legacy') -} else { - module.exports = require('./utils-webcrypto') +const nodeCrypto = require('crypto') + +module.exports = { + postgresMd5PasswordHash, + randomBytes, + deriveKey, + sha256, + hashByName, + hmacSha256, + md5, +} + +/** + * The Web Crypto API - grabbed from the Node.js library or the global + * @type Crypto + */ +// eslint-disable-next-line no-undef +const webCrypto = nodeCrypto.webcrypto || globalThis.crypto +/** + * The SubtleCrypto API for low level crypto operations. + * @type SubtleCrypto + */ +const subtleCrypto = webCrypto.subtle +const textEncoder = new TextEncoder() + +/** + * + * @param {*} length + * @returns + */ +function randomBytes(length) { + return webCrypto.getRandomValues(Buffer.alloc(length)) +} + +async function md5(string) { + try { + return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex') + } catch (e) { + // `createHash()` failed so we are probably not in Node.js, use the WebCrypto API instead. + // Note that the MD5 algorithm on WebCrypto is not available in Node.js. + // This is why we cannot just use WebCrypto in all environments. + const data = typeof string === 'string' ? textEncoder.encode(string) : string + const hash = await subtleCrypto.digest('MD5', data) + return Array.from(new Uint8Array(hash)) + .map((b) => b.toString(16).padStart(2, '0')) + .join('') + } +} + +// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html +async function postgresMd5PasswordHash(user, password, salt) { + const inner = await md5(password + user) + const outer = await md5(Buffer.concat([Buffer.from(inner), salt])) + return 'md5' + outer +} + +/** + * Create a SHA-256 digest of the given data + * @param {Buffer} data + */ +async function sha256(text) { + return await subtleCrypto.digest('SHA-256', text) +} + +async function hashByName(hashName, text) { + return await subtleCrypto.digest(hashName, text) +} + +/** + * Sign the message with the given key + * @param {ArrayBuffer} keyBuffer + * @param {string} msg + */ +async function hmacSha256(keyBuffer, msg) { + const key = await subtleCrypto.importKey('raw', keyBuffer, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']) + return await subtleCrypto.sign('HMAC', key, textEncoder.encode(msg)) +} + +/** + * Derive a key from the password and salt + * @param {string} password + * @param {Uint8Array} salt + * @param {number} iterations + */ +async function deriveKey(password, salt, iterations) { + const key = await subtleCrypto.importKey('raw', textEncoder.encode(password), 'PBKDF2', false, ['deriveBits']) + const params = { name: 'PBKDF2', hash: 'SHA-256', salt: salt, iterations: iterations } + return await subtleCrypto.deriveBits(params, key, 32 * 8, ['deriveBits']) } diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index 673696f79..427243f50 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -49,6 +49,9 @@ module.exports = { ssl: false, + // SSL negotiation style: 'postgres' (traditional SSLRequest) or 'direct' + sslnegotiation: undefined, + application_name: undefined, fallback_application_name: undefined, diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 4bee7ce3c..9ec3c8c03 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -1,5 +1,4 @@ -'use strict' - +const nodeUtils = require('util') // eslint-disable-next-line var Native // eslint-disable-next-line no-useless-catch @@ -16,6 +15,11 @@ const ConnectionParameters = require('../connection-parameters') const NativeQuery = require('./query') +const queryQueueLengthDeprecationNotice = nodeUtils.deprecate( + () => {}, + 'Calling client.query() when the client is already executing a query is deprecated and will be removed in pg@9.0. Use async/await or an external async flow control mechanism instead.' +) + const Client = (module.exports = function (config) { EventEmitter.call(this) config = config || {} @@ -32,6 +36,8 @@ const Client = (module.exports = function (config) { this._connecting = false this._connected = false this._queryable = true + this.pipeline = Boolean(config.pipeline) + this._pipelineInFlight = false // keep these on the object for legacy reasons // for the time being. TODO: deprecate all this jazz @@ -184,7 +190,7 @@ Client.prototype.query = function (config, values, callback) { } if (readTimeout) { - queryCallback = query.callback + queryCallback = query.callback || (() => {}) readTimeoutTimer = setTimeout(() => { const error = new Error('Query read timeout') @@ -230,6 +236,10 @@ Client.prototype.query = function (config, values, callback) { return result } + if (this._queryQueue.length > 0 && !this.pipeline) { + queryQueueLengthDeprecationNotice() + } + this._queryQueue.push(query) this._pulseQueryQueue() return result @@ -241,8 +251,10 @@ Client.prototype.end = function (cb) { this._ending = true - if (!this._connected) { - this.once('connect', this.end.bind(this, cb)) + if (this._connecting && !this._connected) { + this.once('connect', () => { + this.end(() => {}) + }) } let result if (!cb) { @@ -250,14 +262,26 @@ Client.prototype.end = function (cb) { cb = (err) => (err ? reject(err) : resolve()) }) } - this.native.end(function () { - self._errorAllQueries(new Error('Connection terminated')) - process.nextTick(() => { - self.emit('end') - if (cb) cb() + const doEnd = function () { + self.native.end(function () { + self._connected = false + + self._errorAllQueries(new Error('Connection terminated')) + + process.nextTick(() => { + self.emit('end') + if (cb) cb() + }) }) - }) + } + + // If pipeline has in-flight or queued queries, wait for them to drain before closing + if (this.pipeline && (this._pipelineInFlight || this._queryQueue.length > 0)) { + this.once('drain', doEnd) + } else { + doEnd() + } return result } @@ -269,6 +293,9 @@ Client.prototype._pulseQueryQueue = function (initialConnection) { if (!this._connected) { return } + if (this.pipeline && !initialConnection) { + return this._pulsePipelinedQueryQueue() + } if (this._hasActiveQuery()) { return } @@ -287,6 +314,91 @@ Client.prototype._pulseQueryQueue = function (initialConnection) { }) } +Client.prototype._pulsePipelinedQueryQueue = function () { + if (!this._connected || this._pipelineInFlight) { + return + } + if (this._queryQueue.length === 0) { + if (this.hasExecuted) { + this.emit('drain') + } + return + } + + this._pipelineInFlight = true + const self = this + const queries = [] + const nativeQueries = [] + const utils = require('../utils') + + while (this._queryQueue.length > 0) { + const query = this._queryQueue.shift() + this.hasExecuted = true + nativeQueries.push(query) + + const values = query.values ? query.values.map(utils.prepareValue) : null + const pipelineEntry = { text: query.text, name: query.name, arrayMode: query._arrayMode } + if (values) { + pipelineEntry.values = values + } + if (query.name && this.namedQueries[query.name]) { + pipelineEntry._alreadyPrepared = true + } + queries.push(pipelineEntry) + } + + this.native.pipeline(queries, function (err, results) { + self._pipelineInFlight = false + + if (err) { + // Total pipeline failure. Per-query errors arrive on results[i].err, so reaching here means + // the connection itself is gone: mark it unusable and say so, the way the JS client and the + // non-pipelined native path both do. Without this the client looks healthy after losing its + // backend, a Pool never discards it, and everything routed to it fails one query at a time + // for the life of the process. + self._connected = false + self._queryable = false + for (let i = 0; i < nativeQueries.length; i++) { + const q = nativeQueries[i] + q.native = self.native + q.handleError(err) + } + self._errorAllQueries(err) + self.emit('error', err) + self.emit('end') + return + } + + // Deliver results to each query + for (let i = 0; i < nativeQueries.length; i++) { + const q = nativeQueries[i] + const r = results[i] + q.native = self.native + + if (r.err) { + q.handleError(r.err) + } else { + // Track named queries on success + if (q.name) { + self.namedQueries[q.name] = q.text + } + q.state = 'end' + q.emit('end', r.result) + if (q.callback) { + q.callback(null, r.result) + } + } + + setImmediate(function () { + q.emit('_done') + }) + } + + // Process any queries that arrived while we were reading + self._pulsePipelinedQueryQueue() + }) +} + // attempt to cancel an in-progress query Client.prototype.cancel = function (query) { if (this._activeQuery === query) { @@ -306,3 +418,11 @@ Client.prototype.setTypeParser = function (oid, format, parseFn) { Client.prototype.getTypeParser = function (oid, format) { return this._types.getTypeParser(oid, format) } + +Client.prototype.isConnected = function () { + return this._connected +} + +Client.prototype.getTransactionStatus = function () { + return this.native.getTransactionStatus() +} diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index e02294f63..8cb561979 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -48,7 +48,7 @@ const errorFieldMap = { NativeQuery.prototype.handleError = function (err) { // copy pq error fields into the error object - const fields = this.native.pq.resultErrorFields() + const fields = this.native && this.native.pq.resultErrorFields() if (fields) { for (const key in fields) { const normalizedFieldName = errorFieldMap[key] || key diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 64aab5ff2..6b9214199 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -153,7 +153,7 @@ class Query extends EventEmitter { if (typeof this.text !== 'string' && typeof this.name !== 'string') { return new Error('A query must have either text or a name. Supplying neither is unsupported.') } - const previous = connection.parsedStatements[this.name] + const previous = connection.parsedStatements[this.name] || connection.submittedNamedStatements[this.name] if (this.text && previous && this.text !== previous) { return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`) } @@ -183,7 +183,7 @@ class Query extends EventEmitter { } hasBeenParsed(connection) { - return this.name && connection.parsedStatements[this.name] + return this.name && (connection.parsedStatements[this.name] || connection.submittedNamedStatements[this.name]) } handlePortalSuspended(connection) { @@ -214,6 +214,9 @@ class Query extends EventEmitter { name: this.name, types: this.types, }) + if (this.name) { + connection.submittedNamedStatements[this.name] = this.text + } } // because we're mapping user supplied values to @@ -228,6 +231,10 @@ class Query extends EventEmitter { valueMapper: utils.prepareValue, }) } catch (err) { + // we should close parse to avoid leaking connections + connection.close({ type: 'S', name: this.name }) + connection.sync() + this.handleError(err, connection) return } diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index 0ab7bb80c..329fbf9fc 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -89,7 +89,7 @@ class Result { this._parsers = new Array(fieldDescriptions.length) } - const row = {} + const row = Object.create(null) for (let i = 0; i < fieldDescriptions.length; i++) { const desc = fieldDescriptions[i] diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index e23a55e9a..ba51c82c8 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -1,9 +1,15 @@ 'use strict' const defaults = require('./defaults') +const nodeUtils = require('util') -const util = require('util') -const { isDate } = util.types || util // Node 8 doesn't have `util.types` +const { isDate } = require('util/types') + +const invalidDateDeprecationNotice = nodeUtils.deprecate( + () => {}, + 'Sending an invalid date to Postgres is deprecated and will throw an error in the next major version of pg. Ensure any Date object passed as a query parameter is valid.', + 'PG_INVALID_DATE' +) function escapeElement(elementRepresentation) { const escaped = elementRepresentation.replace(/\\/g, '\\\\').replace(/"/g, '\\"') @@ -18,28 +24,23 @@ function arrayString(val) { let result = '{' for (let i = 0; i < val.length; i++) { if (i > 0) { - result = result + ',' + result += ',' } - if (val[i] === null || typeof val[i] === 'undefined') { - result = result + 'NULL' - } else if (Array.isArray(val[i])) { - result = result + arrayString(val[i]) - } else if (ArrayBuffer.isView(val[i])) { - let item = val[i] + let item = val[i] + if (item == null) { + result += 'NULL' + } else if (Array.isArray(item)) { + result += arrayString(item) + } else if (ArrayBuffer.isView(item)) { if (!(item instanceof Buffer)) { - const buf = Buffer.from(item.buffer, item.byteOffset, item.byteLength) - if (buf.length === item.byteLength) { - item = buf - } else { - item = buf.slice(item.byteOffset, item.byteOffset + item.byteLength) - } + item = Buffer.from(item.buffer, item.byteOffset, item.byteLength) } result += '\\\\x' + item.toString('hex') } else { - result += escapeElement(prepareValue(val[i])) + result += escapeElement(prepareValue(item)) } } - result = result + '}' + result += '}' return result } @@ -57,13 +58,12 @@ const prepareValue = function (val, seen) { return val } if (ArrayBuffer.isView(val)) { - const buf = Buffer.from(val.buffer, val.byteOffset, val.byteLength) - if (buf.length === val.byteLength) { - return buf - } - return buf.slice(val.byteOffset, val.byteOffset + val.byteLength) // Node.js v4 does not support those Buffer.from params + return Buffer.from(val.buffer, val.byteOffset, val.byteLength) } if (isDate(val)) { + if (isNaN(val.getTime())) { + invalidDateDeprecationNotice() + } if (defaults.parseInputDatesAsUTC) { return dateToStringUTC(val) } else { @@ -153,7 +153,8 @@ function dateToStringUTC(date) { function normalizeQueryConfig(config, values, callback) { // can take in strings or config objects - config = typeof config === 'string' ? { text: config } : config + // Copy config so normalization does not mutate the caller's object. + config = typeof config === 'string' ? { text: config } : cloneQueryConfig(config) if (values) { if (typeof values === 'function') { config.callback = values @@ -167,6 +168,13 @@ function normalizeQueryConfig(config, values, callback) { return config } +function cloneQueryConfig(config) { + if (config == null) { + return config + } + return Object.defineProperties(Object.create(Object.getPrototypeOf(config)), Object.getOwnPropertyDescriptors(config)) +} + // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c const escapeIdentifier = function (str) { return '"' + str.replace(/"/g, '""') + '"' diff --git a/packages/pg/package.json b/packages/pg/package.json index 57ec82045..d028179ca 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.18.0", + "version": "8.23.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -32,9 +32,9 @@ "./lib/*.js": "./lib/*.js" }, "dependencies": { - "pg-connection-string": "^2.11.0", - "pg-pool": "^3.11.0", - "pg-protocol": "^1.11.0", + "pg-connection-string": "^2.14.0", + "pg-pool": "^3.14.0", + "pg-protocol": "^1.16.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, @@ -45,12 +45,12 @@ "bluebird": "3.7.2", "co": "4.6.0", "pg-copy-streams": "0.3.0", - "typescript": "^4.0.3", + "typescript": "^6.0.3", "vitest": "~3.0.9", "wrangler": "^3.x" }, "optionalDependencies": { - "pg-cloudflare": "^1.3.0" + "pg-cloudflare": "^1.4.0" }, "peerDependencies": { "pg-native": ">=3.0.1" diff --git a/packages/pg/script/create-test-tables.js b/packages/pg/script/create-test-tables.js deleted file mode 100644 index 76ba2dbe4..000000000 --- a/packages/pg/script/create-test-tables.js +++ /dev/null @@ -1,56 +0,0 @@ -'use strict' -const args = require('../test/cli') -const pg = require('../lib') - -const people = [ - { name: 'Aaron', age: 10 }, - { name: 'Brian', age: 20 }, - { name: 'Chris', age: 30 }, - { name: 'David', age: 40 }, - { name: 'Elvis', age: 50 }, - { name: 'Frank', age: 60 }, - { name: 'Grace', age: 70 }, - { name: 'Haley', age: 80 }, - { name: 'Irma', age: 90 }, - { name: 'Jenny', age: 100 }, - { name: 'Kevin', age: 110 }, - { name: 'Larry', age: 120 }, - { name: 'Michelle', age: 130 }, - { name: 'Nancy', age: 140 }, - { name: 'Olivia', age: 150 }, - { name: 'Peter', age: 160 }, - { name: 'Quinn', age: 170 }, - { name: 'Ronda', age: 180 }, - { name: 'Shelley', age: 190 }, - { name: 'Tobias', age: 200 }, - { name: 'Uma', age: 210 }, - { name: 'Veena', age: 220 }, - { name: 'Wanda', age: 230 }, - { name: 'Xavier', age: 240 }, - { name: 'Yoyo', age: 250 }, - { name: 'Zanzabar', age: 260 }, -] - -async function run() { - const con = new pg.Client({ - user: args.user, - password: args.password, - host: args.host, - port: args.port, - database: args.database, - }) - console.log('creating test dataset') - await con.connect() - await con.query('DROP TABLE IF EXISTS person') - await con.query('CREATE TABLE person (id serial, name varchar(10), age integer)') - await con.query( - 'INSERT INTO person (name, age) VALUES' + people.map((person) => ` ('${person.name}', ${person.age})`).join(',') - ) - await con.end() - console.log('created test dataset') -} - -run().catch((e) => { - console.log('setup failed', e) - process.exit(255) -}) diff --git a/packages/pg/test/cli.js b/packages/pg/test/cli.js deleted file mode 100644 index 5bea4912c..000000000 --- a/packages/pg/test/cli.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' -const ConnectionParameters = require('../lib/connection-parameters') -const config = new ConnectionParameters(process.argv[2]) - -for (let i = 0; i < process.argv.length; i++) { - switch (process.argv[i].toLowerCase()) { - case 'native': - config.native = true - break - case 'binary': - config.binary = true - break - case 'down': - config.down = true - break - default: - break - } -} - -if (process.env['PG_TEST_NATIVE']) { - config.native = true -} - -module.exports = config diff --git a/packages/pg/test/cloudflare/vitest-cf.test.ts b/packages/pg/test/cloudflare/vitest-cf.test.ts index 2fe0188b2..c71e01961 100644 --- a/packages/pg/test/cloudflare/vitest-cf.test.ts +++ b/packages/pg/test/cloudflare/vitest-cf.test.ts @@ -1,10 +1,9 @@ import { Pool } from 'pg' import { test } from 'vitest' import assert from 'assert' -import args from '../cli' test('default', async () => { - const pool = new Pool(args) + const pool = new Pool() const result = await pool.query('SELECT $1::text as name', ['cloudflare']) assert(result.rows[0].name === 'cloudflare') pool.end() diff --git a/packages/pg/test/integration/client/api-tests.js b/packages/pg/test/integration/client/api-tests.js index ab7ad6db8..2b0c3f85b 100644 --- a/packages/pg/test/integration/client/api-tests.js +++ b/packages/pg/test/integration/client/api-tests.js @@ -230,6 +230,21 @@ suite.test('callback is fired once and only once', function (done) { ) }) +suite.test('no-op Client#end callback is called exactly once', (done) => { + const client = new helper.Client() + let called = false + + client.end(() => { + assert(!called) + called = true + + client.connect((err) => { + assert.ifError(err) + client.end(done) + }) + }) +}) + suite.test('can provide callback and config object', function (done) { const pool = new pg.Pool() pool.connect( diff --git a/packages/pg/test/integration/client/async-stack-trace-tests.js b/packages/pg/test/integration/client/async-stack-trace-tests.js index fd5b15da4..567851a72 100644 --- a/packages/pg/test/integration/client/async-stack-trace-tests.js +++ b/packages/pg/test/integration/client/async-stack-trace-tests.js @@ -2,50 +2,41 @@ const helper = require('../test-helper') const pg = helper.pg -process.on('unhandledRejection', function (e) { - console.error(e, e.stack) - process.exit(1) -}) - const suite = new helper.Suite() -// these tests will only work for if --async-stack-traces is on, which is the default starting in node 16. -const NODE_MAJOR_VERSION = +process.versions.node.split('.')[0] -if (NODE_MAJOR_VERSION >= 16) { - suite.testAsync('promise API async stack trace in pool', async function outerFunction() { - async function innerFunction() { - const pool = new pg.Pool() - await pool.query('SELECT test from nonexistent') - } - try { - await innerFunction() - throw Error('should have errored') - } catch (e) { - const stack = e.stack - if (!e.stack.includes('innerFunction') || !e.stack.includes('outerFunction')) { - throw Error('async stack trace does not contain wanted values: ' + stack) - } +suite.test('promise API async stack trace in pool', async function outerFunction() { + async function innerFunction() { + const pool = new pg.Pool() + await pool.query('SELECT test from nonexistent') + } + try { + await innerFunction() + throw Error('should have errored') + } catch (e) { + const stack = e.stack + if (!e.stack.includes('innerFunction') || !e.stack.includes('outerFunction')) { + throw Error('async stack trace does not contain wanted values: ' + stack, { cause: e }) } - }) + } +}) - suite.testAsync('promise API async stack trace in client', async function outerFunction() { - async function innerFunction() { - const client = new pg.Client() - await client.connect() - try { - await client.query('SELECT test from nonexistent') - } finally { - client.end() - } - } +suite.test('promise API async stack trace in client', async function outerFunction() { + async function innerFunction() { + const client = new pg.Client() + await client.connect() try { - await innerFunction() - throw Error('should have errored') - } catch (e) { - const stack = e.stack - if (!e.stack.includes('innerFunction') || !e.stack.includes('outerFunction')) { - throw Error('async stack trace does not contain wanted values: ' + stack) - } + await client.query('SELECT test from nonexistent') + } finally { + client.end() } - }) -} + } + try { + await innerFunction() + throw Error('should have errored') + } catch (e) { + const stack = e.stack + if (!e.stack.includes('innerFunction') || !e.stack.includes('outerFunction')) { + throw Error('async stack trace does not contain wanted values: ' + stack, { cause: e }) + } + } +}) diff --git a/packages/pg/test/integration/client/big-simple-query-tests.js b/packages/pg/test/integration/client/big-simple-query-tests.js index 2e66a1af8..0948d1178 100644 --- a/packages/pg/test/integration/client/big-simple-query-tests.js +++ b/packages/pg/test/integration/client/big-simple-query-tests.js @@ -18,71 +18,80 @@ const big_query_rows_2 = [] const big_query_rows_3 = [] // Works -suite.test('big simple query 1', function (done) { +suite.test('big simple query 1', async function () { const client = helper.client() - client - .query( - new Query( - "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1" + await helper.createPersonTable(client) + return new Promise((resolve) => { + client + .query( + new Query( + "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1" + ) ) - ) - .on('row', function (row) { - big_query_rows_1.push(row) + .on('row', function (row) { + big_query_rows_1.push(row) + }) + .on('error', function (error) { + console.log('big simple query 1 error') + console.log(error) + }) + client.on('drain', () => { + client.end() + resolve() }) - .on('error', function (error) { - console.log('big simple query 1 error') - console.log(error) - }) - client.on('drain', () => { - client.end() - done() }) }) // Works -suite.test('big simple query 2', function (done) { +suite.test('big simple query 2', async function () { const client = helper.client() - client - .query( - new Query( - "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", - [''] + await helper.createPersonTable(client) + return new Promise((resolve) => { + client + .query( + new Query( + "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", + [''] + ) ) - ) - .on('row', function (row) { - big_query_rows_2.push(row) - }) - .on('error', function (error) { - console.log('big simple query 2 error') - console.log(error) + .on('row', function (row) { + big_query_rows_2.push(row) + }) + .on('error', function (error) { + console.log('big simple query 2 error') + console.log(error) + }) + client.on('drain', () => { + client.end() + resolve() }) - client.on('drain', () => { - client.end() - done() }) }) // Fails most of the time with 'invalid byte sequence for encoding "UTF8": 0xb9' or 'insufficient data left in message' // If test 1 and 2 are commented out it works -suite.test('big simple query 3', function (done) { +suite.test('big simple query 3', async function () { const client = helper.client() - client - .query( - new Query( - "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", - [''] + await helper.createPersonTable(client) + return new Promise((resolve) => { + client + .query( + new Query( + "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", + [''] + ) ) - ) - .on('row', function (row) { - big_query_rows_3.push(row) - }) - .on('error', function (error) { - console.log('big simple query 3 error') - console.log(error) + .on('row', function (row) { + big_query_rows_3.push(row) + }) + .on('error', function (error) { + console.log('big simple query 3 error') + console.log(error) + }) + client.on('drain', () => { + client.end() + resolve() }) - client.on('drain', () => { - client.end() - done() }) }) @@ -106,16 +115,19 @@ const runBigQuery = function (client) { ) } -suite.test('many times', function (done) { +suite.test('many times', async function () { const client = helper.client() - for (let i = 0; i < 20; i++) { - runBigQuery(client) - } - client.on('drain', function () { - client.end() - setTimeout(function () { - done() - // let client disconnect fully - }, 100) + await helper.createPersonTable(client) + return new Promise((resolve) => { + for (let i = 0; i < 20; i++) { + runBigQuery(client) + } + client.on('drain', function () { + client.end() + setTimeout(function () { + resolve() + // let client disconnect fully + }, 100) + }) }) }) diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index 8a6fc667f..848839287 100644 --- a/packages/pg/test/integration/client/error-handling-tests.js +++ b/packages/pg/test/integration/client/error-handling-tests.js @@ -47,14 +47,11 @@ suite.test('re-using connections results in error callback', (done) => { }) }) -suite.testAsync('re-using connections results in promise rejection', () => { +suite.test('re-using connections results in promise rejection', async () => { const client = new Client() - return client.connect().then(() => { - return helper.rejection(client.connect()).then((err) => { - assert(err instanceof Error) - return client.end() - }) - }) + await client.connect() + await assert.rejects(client.connect(), Error) + await client.end() }) suite.test('using a client after closing it results in error', (done) => { diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index 6ebdb8b45..362a40abc 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -14,8 +14,8 @@ const Server = function (response) { Server.prototype.start = function (cb) { // this is our fake postgres server - // it responds with our specified response immediatley after receiving every buffer - // this is sufficient into convincing the client its connectet to a valid backend + // it responds with our specified response immediately after receiving every buffer + // this is sufficient into convincing the client its connected to a valid backend // if we respond with a readyForQuery message this.server = net.createServer( function (socket) { diff --git a/packages/pg/test/integration/client/pipeline-portal-tests.js b/packages/pg/test/integration/client/pipeline-portal-tests.js new file mode 100644 index 000000000..b478a461e --- /dev/null +++ b/packages/pg/test/integration/client/pipeline-portal-tests.js @@ -0,0 +1,83 @@ +'use strict' +const helper = require('./test-helper') +const assert = require('assert') +const pg = helper.pg + +// A portal stays open across round trips, so on a pipelined connection the queries written behind +// it were answered out of that portal: rows arrived on the wrong query, later reads failed with +// 'portal does not exist' and pg-cursor crashed on a null row buffer. These must be refused. +const suite = new helper.Suite('pipeline mode portal queries') + +if (helper.args.native) { + return +} + +// stands in for pg-cursor and pg-query-stream, so the test does not need either package +class FakeCursor { + constructor() { + this.error = null + } + submit() {} + handleError(err) { + this.error = err + if (this.onError) this.onError(err) + } +} + +suite.test('rejects a custom query class', (done) => { + const client = new pg.Client({ pipeline: true }) + client.connect((err) => { + if (err) return done(err) + const cursor = client.query(new FakeCursor()) + cursor.onError = (err) => { + assert.ok(/pipeline mode/.test(err.message), `expected a pipeline mode error, got: ${err.message}`) + client.end(done) + } + }) +}) + +suite.test('rejects the rows option', (done) => { + const client = new pg.Client({ pipeline: true }) + client.connect((err) => { + if (err) return done(err) + client + .query({ text: 'SELECT generate_series(1, 10) as num', rows: 3 }) + .then(() => { + client.end(() => done(new Error('a paged query should not be accepted in pipeline mode'))) + }) + .catch((err) => { + assert.ok(/pipeline mode/.test(err.message), `expected a pipeline mode error, got: ${err.message}`) + client.end(done) + }) + }) +}) + +suite.test('accepts both when pipeline mode is off', (done) => { + const client = new pg.Client() + client.connect((err) => { + if (err) return done(err) + client + .query({ text: 'SELECT generate_series(1, 10) as num', rows: 3 }) + .then((res) => { + assert.equal(res.rows.length, 10) + client.end(done) + }) + .catch((err) => client.end(() => done(err))) + }) +}) + +suite.test('leaves normal queries alone', (done) => { + const client = new pg.Client({ pipeline: true }) + client.connect((err) => { + if (err) return done(err) + Promise.all([1, 2, 3].map((i) => client.query('SELECT $1::int as v', [i]))) + .then((results) => { + assert.deepStrictEqual( + results.map((r) => Number(r.rows[0].v)), + [1, 2, 3] + ) + client.end(done) + }) + .catch((err) => client.end(() => done(err))) + }) +}) diff --git a/packages/pg/test/integration/client/pipelining-tests.js b/packages/pg/test/integration/client/pipelining-tests.js new file mode 100644 index 000000000..7f927d2b0 --- /dev/null +++ b/packages/pg/test/integration/client/pipelining-tests.js @@ -0,0 +1,169 @@ +'use strict' +const helper = require('./test-helper') +const assert = require('assert') +const suite = new helper.Suite() + +suite.test('basic pipeline with simple queries', async function () { + const client = helper.client(undefined, { pipeline: true }) + + const [r1, r2, r3] = await Promise.all([ + client.query('SELECT 1 AS num'), + client.query('SELECT 2 AS num'), + client.query('SELECT 3 AS num'), + ]) + + assert.equal(r1.rows[0].num, 1) + assert.equal(r2.rows[0].num, 2) + assert.equal(r3.rows[0].num, 3) + + await client.end() +}) + +suite.test('pipeline with parameterized queries', async function () { + const client = helper.client(undefined, { pipeline: true }) + + const [r1, r2, r3] = await Promise.all([ + client.query('SELECT $1::int AS num', [10]), + client.query('SELECT $1::text AS name', ['hello']), + client.query('SELECT $1::int + $2::int AS sum', [3, 4]), + ]) + + assert.equal(r1.rows[0].num, 10) + assert.equal(r2.rows[0].name, 'hello') + assert.equal(r3.rows[0].sum, 7) + + await client.end() +}) + +suite.test('pipeline preserves row mode for each query', async function () { + const client = new helper.Client({ pipeline: true }) + await client.connect() + + const [arrayResult, objectResult] = await Promise.all([ + client.query({ text: 'SELECT $1::int AS num', values: [10], rowMode: 'array' }), + client.query({ text: 'SELECT $1::int AS num', values: [20] }), + ]) + + assert.deepStrictEqual(arrayResult.rows, [[10]]) + assert.deepStrictEqual(objectResult.rows, [{ num: 20 }]) + + await client.end() +}) + +suite.test('pipeline with named prepared statements', async function () { + const client = helper.client(undefined, { pipeline: true }) + + const [r1, r2] = await Promise.all([ + client.query({ name: 'fetch-num', text: 'SELECT $1::int AS num', values: [42] }), + client.query({ name: 'fetch-num', text: 'SELECT $1::int AS num', values: [99] }), + ]) + + assert.equal(r1.rows[0].num, 42) + assert.equal(r2.rows[0].num, 99) + + await client.end() +}) + +suite.test('pipeline error isolation', async function () { + const client = helper.client(undefined, { pipeline: true }) + + const results = await Promise.allSettled([ + client.query('SELECT 1 AS num'), + client.query('SELECT INVALID SYNTAX'), + client.query('SELECT 3 AS num'), + ]) + + assert.equal(results[0].status, 'fulfilled') + assert.equal(results[0].value.rows[0].num, 1) + assert.equal(results[1].status, 'rejected') + assert.equal(results[2].status, 'fulfilled') + assert.equal(results[2].value.rows[0].num, 3) + + await client.end() +}) + +suite.test('pipeline drain event', async function () { + const client = helper.client(undefined, { pipeline: true }) + + const drainPromise = new Promise((resolve) => { + client.on('drain', resolve) + }) + + client.query('SELECT 1') + client.query('SELECT 2') + client.query('SELECT 3') + + await drainPromise + await client.end() +}) + +// #12: end() during active pipeline — should drain gracefully, not destroy +suite.test('end() waits for in-flight pipelined queries to complete', async function () { + const client = helper.client(undefined, { pipeline: true }) + + // Fire queries then call end() immediately without awaiting them + const p1 = client.query('SELECT 1 AS num') + const p2 = client.query('SELECT 2 AS num') + const endPromise = client.end() + + // All queries should resolve (not error) because end() drains gracefully + const [r1, r2] = await Promise.all([p1, p2]) + assert.equal(r1.rows[0].num, 1) + assert.equal(r2.rows[0].num, 2) + await endPromise +}) + +// #13: named statement error cleanup — submittedNamedStatements not left stale +// This relies on submittedNamedStatements tracking which only exists in the JS client +suite.test( + 'named statement parse error cleans up and allows re-preparation', + !helper.args.native && + async function () { + const client = helper.client(undefined, { pipeline: true }) + + // Use an invalid type to force a server-side parse error + const err = await client + .query({ name: 'bad-stmt', text: 'SELECT $1::nonexistent_type_xyz', values: [1] }) + .then(() => null) + .catch((e) => e) + + assert.ok(err, 'expected parse to fail') + + // The stale submittedNamedStatements entry should be gone. + // Re-using the same name with valid SQL should work. + const result = await client.query({ name: 'bad-stmt', text: 'SELECT $1::int AS n', values: [42] }) + assert.equal(result.rows[0].n, 42) + + await client.end() + } +) + +// #14: query_timeout with pipelining +// When an already-sent pipelined query times out, the connection is destroyed +// to unblock the pipeline — subsequent queries error rather than hanging. +// Native client does not support query_timeout in pipeline mode. +suite.test( + 'query_timeout on sent pipelined query destroys connection to unblock', + !helper.args.native && + async function () { + const client = helper.client(undefined, { pipeline: true }) + client.on('error', () => {}) // absorb the 'error' event emitted when stream is destroyed + + const results = await Promise.allSettled([ + client.query('SELECT 1 AS num'), + client.query({ text: 'SELECT pg_sleep(30)', query_timeout: 100 }), + client.query('SELECT 3 AS num'), + ]) + + // Query 1 completes before the slow query enters the pipeline + assert.equal(results[0].status, 'fulfilled') + assert.equal(results[0].value.rows[0].num, 1) + + // Query 2 times out + assert.equal(results[1].status, 'rejected') + assert.ok(results[1].reason.message.includes('timeout'), `unexpected error: ${results[1].reason.message}`) + + // Query 3 errors because the connection was destroyed to unblock the pipeline + assert.equal(results[2].status, 'rejected') + } +) diff --git a/packages/pg/test/integration/client/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js index 9047eae6c..5c102eb13 100644 --- a/packages/pg/test/integration/client/prepared-statement-tests.js +++ b/packages/pg/test/integration/client/prepared-statement-tests.js @@ -6,78 +6,119 @@ const assert = require('assert') const suite = new helper.Suite() ;(function () { - const client = helper.client() - client.on('drain', client.end.bind(client)) - const queryName = 'user by age and like name' - suite.test('first named prepared statement', function (done) { - const query = client.query( - new Query({ - text: 'select name from person where age <= $1 and name LIKE $2', - values: [20, 'Bri%'], - name: queryName, + suite.test('first named prepared statement', async function () { + const client = helper.client() + await helper.createPersonTable(client) + return new Promise((resolve) => { + const query = client.query( + new Query({ + text: 'select name from person where age <= $1 and name LIKE $2', + values: [20, 'Bri%'], + name: queryName, + }) + ) + + assert.emits(query, 'row', function (row) { + assert.equal(row.name, 'Brian') }) - ) - assert.emits(query, 'row', function (row) { - assert.equal(row.name, 'Brian') + query.on('end', () => { + client.end(resolve) + }) }) - - query.on('end', () => done()) }) - suite.test('second named prepared statement with same name & text', function (done) { - const cachedQuery = client.query( - new Query({ - text: 'select name from person where age <= $1 and name LIKE $2', - name: queryName, - values: [10, 'A%'], + suite.test('second named prepared statement with same name & text', async function () { + const client = helper.client() + await helper.createPersonTable(client) + return new Promise((resolve) => { + const cachedQuery = client.query( + new Query({ + text: 'select name from person where age <= $1 and name LIKE $2', + name: queryName, + values: [10, 'A%'], + }) + ) + + assert.emits(cachedQuery, 'row', function (row) { + assert.equal(row.name, 'Aaron') }) - ) - assert.emits(cachedQuery, 'row', function (row) { - assert.equal(row.name, 'Aaron') + cachedQuery.on('end', () => { + client.end(resolve) + }) }) - - cachedQuery.on('end', () => done()) }) - suite.test('with same name, but without query text', function (done) { - const q = client.query( - new Query({ - name: queryName, - values: [30, '%n%'], - }) - ) - - assert.emits(q, 'row', function (row) { - assert.equal(row.name, 'Aaron') + suite.test('with same name, but without query text', async function () { + const client = helper.client() + await helper.createPersonTable(client) + // First, register the named statement + await new Promise((resolve) => { + const reg = client.query( + new Query({ + text: 'select name from person where age <= $1 and name LIKE $2', + name: queryName, + values: [20, 'Bri%'], + }) + ) + reg.on('end', resolve) + }) + return new Promise((resolve) => { + const q = client.query( + new Query({ + name: queryName, + values: [30, '%n%'], + }) + ) - // test second row is emitted as well assert.emits(q, 'row', function (row) { - assert.equal(row.name, 'Brian') + assert.equal(row.name, 'Aaron') + + // test second row is emitted as well + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') + }) }) - }) - q.on('end', () => done()) + q.on('end', () => { + client.end(resolve) + }) + }) }) - suite.test('with same name, but with different text', function (done) { - client.query( - new Query({ - text: 'select name from person where age >= $1 and name LIKE $2', - name: queryName, - values: [30, '%n%'], - }), - assert.calls((err) => { - assert.equal( - err.message, - `Prepared statements must be unique - '${queryName}' was used for a different statement` - ) - done() - }) - ) + suite.test('with same name, but with different text', async function () { + const client = helper.client() + await helper.createPersonTable(client) + // First, register the named statement + await new Promise((resolve) => { + const reg = client.query( + new Query({ + text: 'select name from person where age <= $1 and name LIKE $2', + name: queryName, + values: [20, 'Bri%'], + }) + ) + reg.on('end', resolve) + }) + return new Promise((resolve) => { + client.query( + new Query({ + text: 'select name from person where age >= $1 and name LIKE $2', + name: queryName, + values: [30, '%n%'], + }), + assert.calls((err) => { + assert.equal( + err.message, + `Prepared statements must be unique - '${queryName}' was used for a different statement` + ) + client.end(resolve) + }) + ) + }) }) })() ;(function () { @@ -85,44 +126,45 @@ const suite = new helper.Suite() const statement1 = 'select count(*)::int4 as count from person' const statement2 = 'select count(*)::int4 as count from person where age < $1' - const client1 = helper.client() - const client2 = helper.client() - - suite.test('client 1 execution', function (done) { - client1.query( - { - name: statementName, - text: statement1, - }, - (err, res) => { - assert(!err) - assert.equal(res.rows[0].count, 26) - done() - } - ) + suite.test('client 1 execution', async function () { + const client1 = helper.client() + await helper.createPersonTable(client1) + return new Promise((resolve) => { + client1.query( + { + name: statementName, + text: statement1, + }, + (err, res) => { + assert(!err) + assert.equal(res.rows[0].count, 26) + client1.end(resolve) + } + ) + }) }) - suite.test('client 2 execution', function (done) { - const query = client2.query( - new Query({ - name: statementName, - text: statement2, - values: [11], - }) - ) + suite.test('client 2 execution', async function () { + const client2 = helper.client() + await helper.createPersonTable(client2) + return new Promise((resolve) => { + const query = client2.query( + new Query({ + name: statementName, + text: statement2, + values: [11], + }) + ) - assert.emits(query, 'row', function (row) { - assert.equal(row.count, 1) - }) + assert.emits(query, 'row', function (row) { + assert.equal(row.count, 1) + }) - assert.emits(query, 'end', function () { - done() + assert.emits(query, 'end', function () { + client2.end(resolve) + }) }) }) - - suite.test('clean up clients', () => { - return client1.end().then(() => client2.end()) - }) })() ;(function () { const client = helper.client() @@ -174,7 +216,7 @@ const suite = new helper.Suite() checkForResults(query) }) - suite.testAsync('with no data response and rows', async function () { + suite.test('with no data response and rows', async function () { const result = await client.query({ name: 'some insert', text: '', diff --git a/packages/pg/test/integration/client/promise-api-tests.js b/packages/pg/test/integration/client/promise-api-tests.js index 9e2ffec0c..8c3cd076b 100644 --- a/packages/pg/test/integration/client/promise-api-tests.js +++ b/packages/pg/test/integration/client/promise-api-tests.js @@ -13,13 +13,6 @@ suite.test('valid connection completes promise', () => { }) }) -suite.test('valid connection completes promise', () => { - const client = new pg.Client() - return client.connect().then(() => { - return client.end().then(() => {}) - }) -}) - suite.test('valid connection returns the client in a promise', () => { const client = new pg.Client() return client.connect().then((clientInside) => { @@ -28,25 +21,7 @@ suite.test('valid connection returns the client in a promise', () => { }) }) -suite.test('invalid connection rejects promise', (done) => { +suite.test('invalid connection rejects promise', async () => { const client = new pg.Client({ host: 'alksdjflaskdfj', port: 1234 }) - return client.connect().catch((e) => { - assert(e instanceof Error) - done() - }) -}) - -suite.test('connected client does not reject promise after connection', (done) => { - const client = new pg.Client() - return client.connect().then(() => { - setTimeout(() => { - client.on('error', (e) => { - assert(e instanceof Error) - client.end() - done() - }) - // manually kill the connection - client.emit('error', new Error('something bad happened...but not really')) - }, 50) - }) + await assert.rejects(client.connect(), Error) }) diff --git a/packages/pg/test/integration/client/query-as-promise-tests.js b/packages/pg/test/integration/client/query-as-promise-tests.js index 8e1ba5c71..8c0fcae72 100644 --- a/packages/pg/test/integration/client/query-as-promise-tests.js +++ b/packages/pg/test/integration/client/query-as-promise-tests.js @@ -4,11 +4,6 @@ const helper = require('../test-helper') const pg = helper.pg const assert = require('assert') -process.on('unhandledRejection', function (e) { - console.error(e, e.stack) - process.exit(1) -}) - const suite = new helper.Suite() suite.test('promise API', (cb) => { diff --git a/packages/pg/test/integration/client/results-as-array-tests.js b/packages/pg/test/integration/client/results-as-array-tests.js index 3e2a36ad9..cdc04b9fb 100644 --- a/packages/pg/test/integration/client/results-as-array-tests.js +++ b/packages/pg/test/integration/client/results-as-array-tests.js @@ -1,5 +1,4 @@ 'use strict' -const util = require('util') const helper = require('./test-helper') const assert = require('assert') const suite = new helper.Suite() @@ -11,7 +10,7 @@ const conInfo = helper.config suite.test('returns results as array', function () { const client = new Client(conInfo) const checkRow = function (row) { - assert(util.isArray(row), 'row should be an array') + assert(Array.isArray(row), 'row should be an array') assert.equal(row.length, 4) assert.equal(row[0].getFullYear(), new Date().getFullYear()) assert.strictEqual(row[1], 1) diff --git a/packages/pg/test/integration/client/sasl-scram-tests.js b/packages/pg/test/integration/client/sasl-scram-tests.js index ce5d63e65..bf1dfcb0d 100644 --- a/packages/pg/test/integration/client/sasl-scram-tests.js +++ b/packages/pg/test/integration/client/sasl-scram-tests.js @@ -37,15 +37,15 @@ const config = { } if (native) { - suite.testAsync('skipping SCRAM tests (on native)', () => {}) + suite.test('skipping SCRAM tests (on native)', () => {}) return } if (!config.user || !config.password) { - suite.testAsync('skipping SCRAM tests (missing env)', () => {}) + suite.test('skipping SCRAM tests (missing env)', () => {}) return } -suite.testAsync('can connect using sasl/scram with channel binding enabled (if using SSL)', async () => { +suite.test('can connect using sasl/scram with channel binding enabled (if using SSL)', async () => { const client = new pg.Client({ ...config, enableChannelBinding: true }) let usingChannelBinding = false let hasPeerCert = false @@ -58,7 +58,7 @@ suite.testAsync('can connect using sasl/scram with channel binding enabled (if u await client.end() }) -suite.testAsync('can connect using sasl/scram with channel binding disabled', async () => { +suite.test('can connect using sasl/scram with channel binding disabled', async () => { const client = new pg.Client({ ...config, enableChannelBinding: false }) let usingSASLWithoutChannelBinding = false client.connection.once('authenticationSASLContinue', () => { @@ -69,7 +69,7 @@ suite.testAsync('can connect using sasl/scram with channel binding disabled', as await client.end() }) -suite.testAsync('sasl/scram fails when password is wrong', async () => { +suite.test('sasl/scram fails when password is wrong', async () => { const client = new pg.Client({ ...config, password: config.password + 'append-something-to-make-it-bad', @@ -88,7 +88,7 @@ suite.testAsync('sasl/scram fails when password is wrong', async () => { assert.ok(usingSasl, 'Should be using SASL for authentication') }) -suite.testAsync('sasl/scram fails when password is empty', async () => { +suite.test('sasl/scram fails when password is empty', async () => { const client = new pg.Client({ ...config, // We use a password function here so the connection defaults do not @@ -108,3 +108,82 @@ suite.testAsync('sasl/scram fails when password is empty', async () => { ) assert.ok(usingSasl, 'Should be using SASL for authentication') }) + +/** + * SASLprep regression coverage. RFC 5802 / RFC 4013 require the SCRAM client + * to normalize the password (B.1 mapping → NFKC → prohibition + bidi check) + * before feeding it into PBKDF2. PostgreSQL's server applies the same + * SASLprep when computing the verifier, so any password whose NFKC form + * differs from the raw form would otherwise authenticate against psql/libpq + * but fail against pg with `28P01`. + * + * To exercise these tests, provision a role whose password contains an + * NFKC-asymmetric character. For example, in psql: + * + * SET password_encryption = 'scram-sha-256'; + * CREATE ROLE scram_unicode_test LOGIN PASSWORD U&'IX-\2168'; + * + * `\2168` is ROMAN NUMERAL IX; the server SASLprep-normalizes this to + * `IX-IX` when computing the verifier. Then export: + * + * SCRAM_TEST_PGUSER_UNICODE=scram_unicode_test + * SCRAM_TEST_PGPASSWORD_UNICODE='IX-\u2168' (i.e. the raw form) + * + * If either env var is unset the suite is skipped, matching the convention + * of the ASCII SCRAM block above. + */ +const unicodeConfig = { + user: process.env.SCRAM_TEST_PGUSER_UNICODE, + password: process.env.SCRAM_TEST_PGPASSWORD_UNICODE, + host: process.env.SCRAM_TEST_PGHOST, + port: process.env.SCRAM_TEST_PGPORT, + database: process.env.SCRAM_TEST_PGDATABASE, +} + +if (!unicodeConfig.user || !unicodeConfig.password) { + suite.test('skipping SCRAM unicode tests (missing env)', () => {}) +} else { + suite.test('sasl/scram authenticates a password requiring SASLprep (raw form)', async () => { + const client = new pg.Client(unicodeConfig) + let usingSasl = false + client.connection.once('authenticationSASL', () => { + usingSasl = true + }) + await client.connect() + assert.ok(usingSasl, 'Should be using SASL for authentication') + await client.end() + }) + + suite.test('sasl/scram authenticates the NFKC-equivalent ASCII form of the same password', async () => { + // The unicode password contains a codepoint that NFKC-decomposes to ASCII + // (e.g. U+2168 → "IX"). The server stored the verifier from the + // SASLprep'd ASCII form, so feeding the client the ASCII form directly + // must also authenticate. This proves that the prep step is symmetric: + // any NFKC-equivalent representation reaches the same PBKDF2 input. + const client = new pg.Client({ + ...unicodeConfig, + password: unicodeConfig.password.normalize('NFKC'), + }) + await client.connect() + await client.end() + }) + + suite.test('sasl/scram fails when unicode password is wrong', async () => { + const client = new pg.Client({ + ...unicodeConfig, + password: unicodeConfig.password + 'append-something-to-make-it-bad', + }) + let usingSasl = false + client.connection.once('authenticationSASL', () => { + usingSasl = true + }) + await assert.rejects( + () => client.connect(), + { + code: '28P01', + }, + 'Error code should be for a password error' + ) + assert.ok(usingSasl, 'Should be using SASL for authentication') + }) +} diff --git a/packages/pg/test/integration/client/simple-query-tests.js b/packages/pg/test/integration/client/simple-query-tests.js index 60a8f76f7..d295abfa1 100644 --- a/packages/pg/test/integration/client/simple-query-tests.js +++ b/packages/pg/test/integration/client/simple-query-tests.js @@ -5,58 +5,61 @@ const assert = require('assert') const suite = new helper.Suite() const test = suite.test.bind(suite) -// before running this test make sure you run the script create-test-tables -test('simple query interface', function () { +test('simple query interface', async function () { const client = helper.client() + await helper.createPersonTable(client) - const query = client.query(new Query('select name from person order by name collate "C"')) + return new Promise((resolve) => { + const query = client.query(new Query('select name from person order by name collate "C"')) - client.on('drain', client.end.bind(client)) - - const rows = [] - query.on('row', function (row, result) { - assert.ok(result) - rows.push(row['name']) - }) - query.once('row', function (row) { - test('returned right columns', function () { - assert.deepStrictEqual(row, { name: row.name }) + const rows = [] + query.on('row', function (row, result) { + assert.ok(result) + rows.push(row['name']) }) - }) - - assert.emits(query, 'end', function () { - test('returned right number of rows', function () { - assert.lengthIs(rows, 26) + query.once('row', function (row) { + test('returned right columns', function () { + assert.deepStrictEqual(row, { name: row.name }) + }) }) - test('row ordering', function () { - assert.equal(rows[0], 'Aaron') - assert.equal(rows[25], 'Zanzabar') + + assert.emits(query, 'end', function () { + test('returned right number of rows', function () { + assert.lengthIs(rows, 26) + }) + test('row ordering', function () { + assert.equal(rows[0], 'Aaron') + assert.equal(rows[25], 'Zanzabar') + }) + client.end(resolve) }) }) }) -test('prepared statements do not mutate params', function () { +test('prepared statements do not mutate params', async function () { const client = helper.client() + await helper.createPersonTable(client) - const params = [1] + return new Promise((resolve) => { + const params = [1] - const query = client.query(new Query('select name from person where $1 = 1 order by name collate "C"', params)) + const query = client.query(new Query('select name from person where $1 = 1 order by name collate "C"', params)) - assert.deepEqual(params, [1]) + assert.deepEqual(params, [1]) - client.on('drain', client.end.bind(client)) - - const rows = [] - query.on('row', function (row, result) { - assert.ok(result) - rows.push(row) - }) + const rows = [] + query.on('row', function (row, result) { + assert.ok(result) + rows.push(row) + }) - query.on('end', function (result) { - assert.lengthIs(rows, 26, 'result returned wrong number of rows') - assert.lengthIs(rows, result.rowCount) - assert.equal(rows[0].name, 'Aaron') - assert.equal(rows[25].name, 'Zanzabar') + query.on('end', function (result) { + assert.lengthIs(rows, 26, 'result returned wrong number of rows') + assert.lengthIs(rows, result.rowCount) + assert.equal(rows[0].name, 'Aaron') + assert.equal(rows[25].name, 'Zanzabar') + client.end(resolve) + }) }) }) diff --git a/packages/pg/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js index bece48f2f..b5b32c5ba 100644 --- a/packages/pg/test/integration/client/ssl-tests.js +++ b/packages/pg/test/integration/client/ssl-tests.js @@ -3,7 +3,7 @@ const helper = require('./test-helper') const assert = require('assert') const suite = new helper.Suite() -suite.test('can connect with ssl', function () { +suite.test('can connect with ssl', function (done) { const config = { ...helper.config, ssl: { @@ -16,9 +16,64 @@ suite.test('can connect with ssl', function () { client.query( 'SELECT NOW()', assert.success(function () { - client.end() + client.end(done) }) ) }) ) }) + +async function getServerVersionNum() { + const client = new helper.pg.Client(helper.config) + await client.connect() + try { + const { + rows: [row], + } = await client.query('SHOW server_version_num') + return parseInt(row.server_version_num, 10) + } finally { + await client.end() + } +} + +// The native client forwards sslnegotiation=direct to libpq, whose support +// for direct SSL depends on the linked libpq version (17+) rather than on +// this library. It also does not expose the underlying TLS socket, so the +// direct-negotiation check below is impossible. So we only test the pure-JS client. +if (!helper.args.native) { + suite.test('can connect with direct SSL negotiation', async () => { + // Direct SSL negotiation (sslnegotiation=direct) is only supported by + // PostgreSQL 17 and newer servers. Probe the server version first and skip + // on older servers rather than failing the test. + const serverVersionNum = await getServerVersionNum() + if (serverVersionNum < 170000) { + console.log(`(skipped: direct SSL requires PostgreSQL 17+, server_version_num=${serverVersionNum}) `) + return + } + + const config = { + ...helper.config, + ssl: { rejectUnauthorized: false }, + sslnegotiation: 'direct', + } + const client = new helper.pg.Client(config) + await client.connect() + const { rows } = await client.query('SELECT NOW()') + assert.strictEqual(rows.length, 1) + + // Verify the connection actually used direct SSL negotiation rather than + // silently falling back to the traditional SSLRequest handshake. pg only + // sends the 'postgresql' ALPN protocol on a direct SSL handshake (see + // Connection#upgradeToSSL), and a PostgreSQL 17+ server echoes it back, so + // its presence on the negotiated TLS socket confirms direct negotiation. + const tlsSocket = client.connection.stream + assert.ok(tlsSocket.encrypted, 'expected the connection to be upgraded to a TLS socket') + assert.strictEqual( + tlsSocket.alpnProtocol, + 'postgresql', + 'expected direct SSL negotiation to select the "postgresql" ALPN protocol' + ) + + await client.end() + }) +} diff --git a/packages/pg/test/integration/client/timezone-tests.js b/packages/pg/test/integration/client/timezone-tests.js index df87dcc74..c7edbbb56 100644 --- a/packages/pg/test/integration/client/timezone-tests.js +++ b/packages/pg/test/integration/client/timezone-tests.js @@ -21,7 +21,7 @@ pool.connect(function (err, client, done) { }) }) - suite.testAsync('date comes out as a date', async function () { + suite.test('date comes out as a date', async function () { const { rows } = await client.query('SELECT NOW()::DATE AS date') assert(rows[0].date instanceof Date) }) diff --git a/packages/pg/test/integration/client/transaction-tests.js b/packages/pg/test/integration/client/transaction-tests.js index feb178fef..7e0b36964 100644 --- a/packages/pg/test/integration/client/transaction-tests.js +++ b/packages/pg/test/integration/client/transaction-tests.js @@ -4,65 +4,38 @@ const suite = new helper.Suite() const pg = helper.pg const assert = require('assert') -const client = new pg.Client() -client.connect( - assert.success(function () { - client.query('begin') +suite.test('transactions', async function () { + const client = new pg.Client() + await client.connect() + await helper.createPersonTable(client) - const getZed = { - text: 'SELECT * FROM person WHERE name = $1', - values: ['Zed'], - } + await client.query('begin') - suite.test('name should not exist in the database', function (done) { - client.query( - getZed, - assert.calls(function (err, result) { - assert(!err) - assert.empty(result.rows) - done() - }) - ) - }) + const getZed = { + text: 'SELECT * FROM person WHERE name = $1', + values: ['Zed'], + } - suite.test('can insert name', (done) => { - client.query( - 'INSERT INTO person(name, age) VALUES($1, $2)', - ['Zed', 270], - assert.calls(function (err, result) { - assert(!err) - done() - }) - ) - }) + // name should not exist + const r1 = await client.query(getZed) + assert.empty(r1.rows) - suite.test('name should exist in the database', function (done) { - client.query( - getZed, - assert.calls(function (err, result) { - assert(!err) - assert.equal(result.rows[0].name, 'Zed') - done() - }) - ) - }) + // insert name + await client.query('INSERT INTO person(name, age) VALUES($1, $2)', ['Zed', 270]) - suite.test('rollback', (done) => { - client.query('rollback', done) - }) + // name should exist + const r2 = await client.query(getZed) + assert.equal(r2.rows[0].name, 'Zed') - suite.test('name should not exist in the database', function (done) { - client.query( - getZed, - assert.calls(function (err, result) { - assert(!err) - assert.empty(result.rows) - client.end(done) - }) - ) - }) - }) -) + // rollback + await client.query('rollback') + + // name should not exist after rollback + const r3 = await client.query(getZed) + assert.empty(r3.rows) + + await client.end() +}) suite.test('gh#36', function (cb) { const pool = new pg.Pool() diff --git a/packages/pg/test/integration/client/txstatus-tests.js b/packages/pg/test/integration/client/txstatus-tests.js new file mode 100644 index 000000000..cb8b740f8 --- /dev/null +++ b/packages/pg/test/integration/client/txstatus-tests.js @@ -0,0 +1,82 @@ +'use strict' +const helper = require('./test-helper') +const suite = new helper.Suite() +const pg = helper.pg +const assert = require('assert') + +suite.test('txStatus tracking', function (done) { + const client = new pg.Client() + client.connect( + assert.success(function () { + // Run a simple query to initialize txStatus + client.query( + 'SELECT 1', + assert.success(function () { + // Test 1: Initial state after query (should be idle) + assert.equal(client.getTransactionStatus(), 'I', 'should start in idle state') + + // Test 2: BEGIN transaction + client.query( + 'BEGIN', + assert.success(function () { + assert.equal(client.getTransactionStatus(), 'T', 'should be in transaction state') + + // Test 3: COMMIT + client.query( + 'COMMIT', + assert.success(function () { + assert.equal(client.getTransactionStatus(), 'I', 'should return to idle after commit') + + client.end(done) + }) + ) + }) + ) + }) + ) + }) + ) +}) + +suite.test('txStatus error state', function (done) { + const client = new pg.Client() + client.connect( + assert.success(function () { + // Run a simple query to initialize txStatus + client.query( + 'SELECT 1', + assert.success(function () { + client.query( + 'BEGIN', + assert.success(function () { + // Execute invalid SQL to trigger error state + client.query('INVALID SQL SYNTAX', function (err) { + assert(err, 'should receive error from invalid query') + + // Issue a sync query to ensure ReadyForQuery has been processed + // This guarantees transaction status has been updated + client.query('SELECT 1', function () { + // This callback fires after ReadyForQuery is processed + assert.equal(client.getTransactionStatus(), 'E', 'should be in error state') + + // Rollback to recover + client.query( + 'ROLLBACK', + assert.success(function () { + assert.equal( + client.getTransactionStatus(), + 'I', + 'should return to idle after rollback from error' + ) + client.end(done) + }) + ) + }) + }) + }) + ) + }) + ) + }) + ) +}) diff --git a/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js b/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js index 260e922d3..402fc5910 100644 --- a/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js +++ b/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js @@ -5,7 +5,7 @@ const assert = require('assert') const suite = new helper.Suite() const testPoolSize = function (max) { - suite.testAsync(`test ${max} queries executed on a pool rapidly`, async () => { + suite.test(`test ${max} queries executed on a pool rapidly`, async () => { const pool = new helper.pg.Pool({ max: 10 }) let count = 0 diff --git a/packages/pg/test/integration/connection-pool/native-instance-tests.js b/packages/pg/test/integration/connection-pool/native-instance-tests.js index 6f713411d..ae49813d0 100644 --- a/packages/pg/test/integration/connection-pool/native-instance-tests.js +++ b/packages/pg/test/integration/connection-pool/native-instance-tests.js @@ -8,6 +8,7 @@ const pool = new pg.Pool() pool.connect( assert.calls(function (err, client, done) { + console.log('native?', native) if (native) { assert(client.native) } else { diff --git a/packages/pg/test/integration/connection-pool/tls-tests.js b/packages/pg/test/integration/connection-pool/tls-tests.js index f85941d45..950f2acf3 100644 --- a/packages/pg/test/integration/connection-pool/tls-tests.js +++ b/packages/pg/test/integration/connection-pool/tls-tests.js @@ -8,7 +8,7 @@ const pg = helper.pg const suite = new helper.Suite() if (process.env.PG_CLIENT_CERT_TEST) { - suite.testAsync('client certificate', async () => { + suite.test('client certificate', async () => { const pool = new pg.Pool({ ssl: { ca: fs.readFileSync(process.env.PGSSLROOTCERT), diff --git a/packages/pg/test/integration/gh-issues/1105-tests.js b/packages/pg/test/integration/gh-issues/1105-tests.js index 1e3f74c03..eb3acbe96 100644 --- a/packages/pg/test/integration/gh-issues/1105-tests.js +++ b/packages/pg/test/integration/gh-issues/1105-tests.js @@ -1,7 +1,7 @@ const helper = require('../test-helper') const suite = new helper.Suite() -suite.testAsync('timeout causing query crashes', async () => { +suite.test('timeout causing query crashes', async () => { const client = new helper.Client() await client.connect() await client.query('CREATE TEMP TABLE foobar( name TEXT NOT NULL, id SERIAL)') diff --git a/packages/pg/test/integration/gh-issues/1542-tests.js b/packages/pg/test/integration/gh-issues/1542-tests.js index 6ad075b22..b38866109 100644 --- a/packages/pg/test/integration/gh-issues/1542-tests.js +++ b/packages/pg/test/integration/gh-issues/1542-tests.js @@ -4,7 +4,7 @@ const assert = require('assert') const suite = new helper.Suite() -suite.testAsync('BoundPool can be subclassed', async () => { +suite.test('BoundPool can be subclassed', async () => { const Pool = helper.pg.Pool class SubPool extends Pool {} const subPool = new SubPool() diff --git a/packages/pg/test/integration/gh-issues/2085-tests.js b/packages/pg/test/integration/gh-issues/2085-tests.js index d71c55c0d..80bc7f33a 100644 --- a/packages/pg/test/integration/gh-issues/2085-tests.js +++ b/packages/pg/test/integration/gh-issues/2085-tests.js @@ -10,7 +10,7 @@ if (process.env.PGTESTNOSSL) { return } -suite.testAsync('it should connect over ssl', async () => { +suite.test('it should connect over ssl', async () => { const ssl = helper.args.native ? 'require' : { @@ -23,7 +23,7 @@ suite.testAsync('it should connect over ssl', async () => { await client.end() }) -suite.testAsync('it should fail with self-signed cert error w/o rejectUnauthorized being passed', async () => { +suite.test('it should fail with self-signed cert error w/o rejectUnauthorized being passed', async () => { const ssl = helper.args.native ? 'verify-ca' : {} const client = new helper.pg.Client({ ssl }) try { diff --git a/packages/pg/test/integration/gh-issues/2108-tests.js b/packages/pg/test/integration/gh-issues/2108-tests.js index 648b0df52..22c97ef7d 100644 --- a/packages/pg/test/integration/gh-issues/2108-tests.js +++ b/packages/pg/test/integration/gh-issues/2108-tests.js @@ -7,7 +7,7 @@ suite.test('Closing an unconnected client calls callback', (done) => { client.end(done) }) -suite.testAsync('Closing an unconnected client resolves promise', () => { +suite.test('Closing an unconnected client resolves promise', () => { const client = new helper.pg.Client() return client.end() }) diff --git a/packages/pg/test/integration/gh-issues/2416-tests.js b/packages/pg/test/integration/gh-issues/2416-tests.js index 1bb5aeff8..88dbd13c8 100644 --- a/packages/pg/test/integration/gh-issues/2416-tests.js +++ b/packages/pg/test/integration/gh-issues/2416-tests.js @@ -3,7 +3,7 @@ const assert = require('assert') const suite = new helper.Suite() -suite.testAsync('it sets search_path on connection', async () => { +suite.test('it sets search_path on connection', async () => { const client = new helper.pg.Client({ options: '--search_path=foo', }) diff --git a/packages/pg/test/integration/gh-issues/2716-tests.js b/packages/pg/test/integration/gh-issues/2716-tests.js index 62d0942ba..87bcc3032 100644 --- a/packages/pg/test/integration/gh-issues/2716-tests.js +++ b/packages/pg/test/integration/gh-issues/2716-tests.js @@ -4,7 +4,7 @@ const helper = require('../test-helper') const suite = new helper.Suite() // https://github.com/brianc/node-postgres/issues/2716 -suite.testAsync('client.end() should resolve if already ended', async () => { +suite.test('client.end() should resolve if already ended', async () => { const client = new helper.pg.Client() await client.connect() diff --git a/packages/pg/test/integration/gh-issues/2862-tests.js b/packages/pg/test/integration/gh-issues/2862-tests.js index 5e36d21ef..8c55bbd9d 100644 --- a/packages/pg/test/integration/gh-issues/2862-tests.js +++ b/packages/pg/test/integration/gh-issues/2862-tests.js @@ -6,7 +6,7 @@ const vm = require('vm') const suite = new helper.Suite() -suite.testAsync('Handle date objects as Date', async () => { +suite.test('Handle date objects as Date', async () => { const crossRealmDate = await vm.runInNewContext('new Date()') assert(!(crossRealmDate instanceof Date)) const date = new Date(crossRealmDate.getTime()) diff --git a/packages/pg/test/integration/gh-issues/3062-tests.js b/packages/pg/test/integration/gh-issues/3062-tests.js index 325bcf9a4..40f4dbc73 100644 --- a/packages/pg/test/integration/gh-issues/3062-tests.js +++ b/packages/pg/test/integration/gh-issues/3062-tests.js @@ -4,7 +4,7 @@ const assert = require('assert') const suite = new helper.Suite() // https://github.com/brianc/node-postgres/issues/3062 -suite.testAsync('result fields with the same name should pick the last value', async () => { +suite.test('result fields with the same name should pick the last value', async () => { const client = new helper.pg.Client() await client.connect() diff --git a/packages/pg/test/integration/gh-issues/3174-tests.js b/packages/pg/test/integration/gh-issues/3174-tests.js index 462cb825e..cd920346a 100644 --- a/packages/pg/test/integration/gh-issues/3174-tests.js +++ b/packages/pg/test/integration/gh-issues/3174-tests.js @@ -2,7 +2,7 @@ const net = require('net') const buffers = require('../../test-buffers') const helper = require('../test-helper') const assert = require('assert') -const cli = require('../../cli') +const cli = helper.args const suite = new helper.Suite() @@ -85,7 +85,7 @@ const delay = (ms) => }) const testErrorBuffer = (bufferName, errorBuffer) => { - suite.testAsync(`Out of order ${bufferName} on simple query is catchable`, async () => { + suite.test(`Out of order ${bufferName} on simple query is catchable`, async () => { const closeServer = await new Promise((resolve, reject) => { return startMockServer(options.port, errorBuffer, (closeServer) => resolve(closeServer)) }) @@ -104,13 +104,15 @@ const testErrorBuffer = (bufferName, errorBuffer) => { if (!cli.native) { assert(errorHit) // further queries on the client should fail since its in an invalid state - await assert.rejects(() => client.query('SELECTR NOW()'), 'Further queries on the client should reject') + await assert.rejects(client.query('SELECT NOW()'), { + message: 'Client has encountered a connection error and is not queryable', + }) } await closeServer() }) - suite.testAsync(`Out of order ${bufferName} on extended query is catchable`, async () => { + suite.test(`Out of order ${bufferName} on extended query is catchable`, async () => { const closeServer = await new Promise((resolve, reject) => { return startMockServer(options.port, errorBuffer, (closeServer) => resolve(closeServer)) }) @@ -129,7 +131,9 @@ const testErrorBuffer = (bufferName, errorBuffer) => { if (!cli.native) { assert(errorHit) // further queries on the client should fail since its in an invalid state - await assert.rejects(() => client.query('SELECTR NOW()'), 'Further queries on the client should reject') + await assert.rejects(client.query('SELECT NOW()'), { + message: 'Client has encountered a connection error and is not queryable', + }) } await client.end() @@ -137,7 +141,7 @@ const testErrorBuffer = (bufferName, errorBuffer) => { await closeServer() }) - suite.testAsync(`Out of order ${bufferName} on pool is catchable`, async () => { + suite.test(`Out of order ${bufferName} on pool is catchable`, async () => { const closeServer = await new Promise((resolve, reject) => { return startMockServer(options.port, errorBuffer, (closeServer) => resolve(closeServer)) }) diff --git a/packages/pg/test/integration/gh-issues/3487-tests.js b/packages/pg/test/integration/gh-issues/3487-tests.js index 3861c82d5..8d187ea25 100644 --- a/packages/pg/test/integration/gh-issues/3487-tests.js +++ b/packages/pg/test/integration/gh-issues/3487-tests.js @@ -3,7 +3,7 @@ const assert = require('assert') const suite = new helper.Suite() -suite.testAsync('allows you to switch between format modes for arrays', async () => { +suite.test('allows you to switch between format modes for arrays', async () => { const client = new helper.pg.Client() await client.connect() diff --git a/packages/pg/test/integration/test-helper.js b/packages/pg/test/integration/test-helper.js index 631acbae3..fe2044f60 100644 --- a/packages/pg/test/integration/test-helper.js +++ b/packages/pg/test/integration/test-helper.js @@ -6,12 +6,12 @@ const assert = require('assert') if (helper.args.native) { Client = require('./../../lib/native') helper.Client = Client - helper.pg = helper.pg.native + helper.pg = require('../../lib').native } // creates a client from cli parameters -helper.client = function (cb) { - const client = new Client() +helper.client = function (cb, options) { + const client = new Client(options) client.connect(cb) return client } diff --git a/packages/pg/test/native/callback-api-tests.js b/packages/pg/test/native/callback-api-tests.js index d129e4a24..8ff2063e5 100644 --- a/packages/pg/test/native/callback-api-tests.js +++ b/packages/pg/test/native/callback-api-tests.js @@ -5,26 +5,29 @@ const Client = require('./../../lib/native') const suite = new helper.Suite() const assert = require('assert') -suite.test('fires callback with results', function (done) { +suite.test('fires callback with results', async function () { const client = new Client(helper.config) client.connect() - client.query( - 'SELECT 1 as num', - assert.calls(function (err, result) { - assert(!err) - assert.equal(result.rows[0].num, 1) - assert.strictEqual(result.rowCount, 1) - client.query( - 'SELECT * FROM person WHERE name = $1', - ['Brian'], - assert.calls(function (err, result) { - assert(!err) - assert.equal(result.rows[0].name, 'Brian') - client.end(done) - }) - ) - }) - ) + await helper.createPersonTable(client) + return new Promise((resolve) => { + client.query( + 'SELECT 1 as num', + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].num, 1) + assert.strictEqual(result.rowCount, 1) + client.query( + 'SELECT * FROM person WHERE name = $1', + ['Brian'], + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].name, 'Brian') + client.end(resolve) + }) + ) + }) + ) + }) }) suite.test('preserves domain', function (done) { diff --git a/packages/pg/test/native/stress-tests.js b/packages/pg/test/native/stress-tests.js index 2cccb44bf..8496abe80 100644 --- a/packages/pg/test/native/stress-tests.js +++ b/packages/pg/test/native/stress-tests.js @@ -5,9 +5,10 @@ const Query = Client.Query const assert = require('assert') const suite = new helper.Suite() -suite.test('many rows', function () { +suite.test('many rows', async function () { const client = new Client(helper.config) client.connect() + await helper.createPersonTable(client) const q = client.query(new Query('SELECT * FROM person')) const rows = [] q.on('row', function (row) { @@ -19,9 +20,10 @@ suite.test('many rows', function () { }) }) -suite.test('many queries', function () { +suite.test('many queries', async function () { const client = new Client(helper.config) client.connect() + await helper.createPersonTable(client) let count = 0 const expected = 100 for (let i = 0; i < expected; i++) { @@ -36,18 +38,20 @@ suite.test('many queries', function () { }) }) -suite.test('many clients', function () { +suite.test('many clients', async function () { const clients = [] for (let i = 0; i < 10; i++) { clients.push(new Client(helper.config)) } - clients.forEach(function (client) { - client.connect() - for (let i = 0; i < 20; i++) { - client.query('SELECT * FROM person') - } - assert.emits(client, 'drain', function () { + await Promise.all( + clients.map(async function (client) { + client.connect() + await helper.createPersonTable(client) + for (let i = 0; i < 20; i++) { + await client.query('SELECT * FROM person') + } + client.end() }) - }) + ) }) diff --git a/packages/pg/test/suite.js b/packages/pg/test/suite.js index 7d19edbb0..e8d9d0834 100644 --- a/packages/pg/test/suite.js +++ b/packages/pg/test/suite.js @@ -29,7 +29,7 @@ class Test { } result.then(() => cb()).catch((err) => cb(err || new Error('Unhandled promise rejection'))) } else { - this.action.call(this, cb) + this.action(cb) } } } @@ -70,27 +70,6 @@ class Suite { const test = new Test(name, cb) this._queue.push(test) } - - /** - * Run an async test that can return a Promise. If the Promise resolves - * successfully then the test will pass. If the Promise rejects with an - * error then the test will be considered failed. - */ - testAsync(name, action) { - const test = new Test(name, (cb) => { - Promise.resolve() - .then(action) - .then(() => cb(null), cb) - }) - this._queue.push(test) - } } -process.on('unhandledRejection', (e) => { - setImmediate(() => { - console.error('Unhandled promise rejection') - throw e - }) -}) - module.exports = Suite diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index da70973f6..3d2d4d4d8 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -3,10 +3,17 @@ const assert = require('assert') const sys = require('util') const Suite = require('./suite') -const args = require('./cli') - const Client = require('./../lib').Client +let isNativeMode = false +for (let i = 0; i < process.argv.length; i++) { + switch (process.argv[i].toLowerCase()) { + case 'native': + isNativeMode = true + break + } +} + process.on('uncaughtException', function (d) { if ('stack' in d && 'message' in d) { console.log('Message: ' + d.message) @@ -14,7 +21,8 @@ process.on('uncaughtException', function (d) { } else { console.log(d) } - process.exit(-1) + // causes xargs to abort right away + process.exit(255) }) const expect = function (callback, timeout) { const executed = false @@ -53,19 +61,12 @@ const expect = function (callback, timeout) { } // print out the filename process.stdout.write(require('path').basename(process.argv[1])) -if (args.binary) process.stdout.write(' (binary)') -if (args.native) process.stdout.write(' (native)') +if (isNativeMode) process.stdout.write(' (native)') process.on('exit', function () { console.log('') }) -process.on('uncaughtException', function (err) { - console.error('\n %s', err.stack || err.toString()) - // causes xargs to abort right away - process.exit(255) -}) - const getTimezoneOffset = Date.prototype.getTimezoneOffset const setTimezoneOffset = function (minutesOffset) { @@ -78,14 +79,6 @@ const resetTimezoneOffset = function () { Date.prototype.getTimezoneOffset = getTimezoneOffset } -const rejection = (promise) => - promise.then( - (value) => { - throw new Error(`Promise resolved when rejection was expected; value: ${sys.inspect(value)}`) - }, - (error) => error - ) - if (Object.isExtensible(assert)) { assert.same = function (actual, expected) { for (const key in expected) { @@ -118,49 +111,6 @@ if (Object.isExtensible(assert)) { }) } - assert.UTCDate = function (actual, year, month, day, hours, min, sec, milisecond) { - const actualYear = actual.getUTCFullYear() - assert.equal(actualYear, year, 'expected year ' + year + ' but got ' + actualYear) - - const actualMonth = actual.getUTCMonth() - assert.equal(actualMonth, month, 'expected month ' + month + ' but got ' + actualMonth) - - const actualDate = actual.getUTCDate() - assert.equal(actualDate, day, 'expected day ' + day + ' but got ' + actualDate) - - const actualHours = actual.getUTCHours() - assert.equal(actualHours, hours, 'expected hours ' + hours + ' but got ' + actualHours) - - const actualMin = actual.getUTCMinutes() - assert.equal(actualMin, min, 'expected min ' + min + ' but got ' + actualMin) - - const actualSec = actual.getUTCSeconds() - assert.equal(actualSec, sec, 'expected sec ' + sec + ' but got ' + actualSec) - - const actualMili = actual.getUTCMilliseconds() - assert.equal(actualMili, milisecond, 'expected milisecond ' + milisecond + ' but got ' + actualMili) - } - - const spit = function (actual, expected) { - console.log('') - console.log('actual ' + sys.inspect(actual)) - console.log('expect ' + sys.inspect(expected)) - console.log('') - } - - assert.equalBuffers = function (actual, expected) { - if (actual.length != expected.length) { - spit(actual, expected) - assert.equal(actual.length, expected.length) - } - for (let i = 0; i < actual.length; i++) { - if (actual[i] != expected[i]) { - spit(actual, expected) - } - assert.equal(actual[i], expected[i]) - } - } - assert.empty = function (actual) { assert.lengthIs(actual, 0) } @@ -199,14 +149,57 @@ if (Object.isExtensible(assert)) { } } +const names = [ + 'Aaron', + 'Brian', + 'Chris', + 'David', + 'Elvis', + 'Frank', + 'Grace', + 'Haley', + 'Irma', + 'Jenny', + 'Kevin', + 'Larry', + 'Michelle', + 'Nancy', + 'Olivia', + 'Peter', + 'Quinn', + 'Ronda', + 'Shelley', + 'Tobias', + 'Uma', + 'Veena', + 'Wanda', + 'Xavier', + 'Yoyo', + 'Zanzabar', +] + +const createPersonTable = async (client) => { + await client.query('CREATE TEMP TABLE person (id serial, name varchar(10), age integer)') + await client.query( + 'INSERT INTO person (name, age) VALUES' + names.map((name, i) => ` ('${name}', ${(i + 1) * 10})`).join(',') + ) +} + module.exports = { Suite: Suite, pg: require('./../lib/'), - args: args, - config: args, + args: { native: isNativeMode }, + config: { + native: isNativeMode, + host: process.env.PGHOST || 'localhost', + port: process.env.PGPORT || 5432, + user: process.env.PGUSER || 'postgres', + password: process.env.PGPASSWORD || '', + database: process.env.PGDATABASE || 'postgres', + }, sys: sys, Client: Client, setTimezoneOffset: setTimezoneOffset, resetTimezoneOffset: resetTimezoneOffset, - rejection: rejection, + createPersonTable: createPersonTable, } diff --git a/packages/pg/test/unit/client/cleartext-password-tests.js b/packages/pg/test/unit/client/cleartext-password-tests.js index 388d94cf9..b844db5e6 100644 --- a/packages/pg/test/unit/client/cleartext-password-tests.js +++ b/packages/pg/test/unit/client/cleartext-password-tests.js @@ -14,7 +14,7 @@ suite.test('cleartext password auth responds with password', function () { const packets = client.connection.stream.packets assert.lengthIs(packets, 1) const packet = packets[0] - assert.equalBuffers(packet, [0x70, 0, 0, 0, 6, 33, 0]) + assert.deepStrictEqual(packet, Buffer.from([0x70, 0, 0, 0, 6, 33, 0])) }) suite.test('cleartext password auth does not crash with null password using pg-pass', function () { diff --git a/packages/pg/test/unit/client/md5-password-tests.js b/packages/pg/test/unit/client/md5-password-tests.js index 8fd2f7c2f..a00b15b1f 100644 --- a/packages/pg/test/unit/client/md5-password-tests.js +++ b/packages/pg/test/unit/client/md5-password-tests.js @@ -18,7 +18,10 @@ test('md5 authentication', async function () { test('should have correct encrypted data', async function () { const password = await crypto.postgresMd5PasswordHash(client.user, client.password, salt) // how do we want to test this? - assert.equalBuffers(client.connection.stream.packets[0], new BufferList().addCString(password).join(true, 'p')) + assert.deepStrictEqual( + client.connection.stream.packets[0], + new BufferList().addCString(password).join(true, 'p') + ) }) }) ) diff --git a/packages/pg/test/unit/client/password-callback-tests.js b/packages/pg/test/unit/client/password-callback-tests.js new file mode 100644 index 000000000..bf1885e94 --- /dev/null +++ b/packages/pg/test/unit/client/password-callback-tests.js @@ -0,0 +1,70 @@ +const helper = require('./test-helper') +const assert = require('assert') +const suite = new helper.Suite() +const pgpass = require('pgpass') + +class Wait { + constructor() { + this.promise = new Promise((resolve) => { + this.resolve = resolve + }) + } + + until() { + return this.promise + } + + done(time) { + if (time) { + setTimeout(this.resolve.bind(this), time) + } else { + this.resolve() + } + } +} + +suite.test('password callback is called with conenction params', async function () { + const wait = new Wait() + const client = helper.client({ + user: 'foo', + database: 'bar', + host: 'baz', + password: async (params) => { + assert.equal(params.user, 'foo') + assert.equal(params.database, 'bar') + assert.equal(params.host, 'baz') + wait.done(10) + return 'password' + }, + }) + client.connection.emit('authenticationCleartextPassword') + await wait.until() + assert.equal(client.user, 'foo') + assert.equal(client.database, 'bar') + assert.equal(client.host, 'baz') + assert.equal(client.connectionParameters.password, 'password') +}) + +suite.test('cleartext password auth does not crash with null password using pg-pass', async function () { + process.env.PGPASSFILE = `${__dirname}/pgpass.file` + // set this to undefined so pgpass will use the file + delete process.env.PGPASSWORD + const wait = new Wait() + const client = helper.client({ + host: 'foo', + port: 5432, + database: 'bar', + user: 'baz', + password: (params) => { + return new Promise((resolve) => { + pgpass(params, (pass) => { + wait.done(10) + resolve(pass) + }) + }) + }, + }) + client.connection.emit('authenticationCleartextPassword') + await wait.until() + assert.equal(client.password, 'quz') +}) diff --git a/packages/pg/test/unit/client/query-timeout-tests.js b/packages/pg/test/unit/client/query-timeout-tests.js new file mode 100644 index 000000000..dbf20cf1f --- /dev/null +++ b/packages/pg/test/unit/client/query-timeout-tests.js @@ -0,0 +1,34 @@ +'use strict' + +const helper = require('./test-helper') +const Query = require('../../../lib/query') +const assert = require('assert') +const suite = new helper.Suite() +const test = suite.test.bind(suite) + +test('query timeout with Submittable without callback delivers error via handleError', function (done) { + const client = helper.client() + client.connectionParameters = { query_timeout: 10 } + + const query = new Query({ text: 'SELECT 1' }) + query.handleError = (err) => { + assert.equal(err.message, 'Query read timeout') + done() + } + + client.connection.emit('readyForQuery') + client.query(query) +}) + +test('query timeout with Submittable with callback delivers error via callback', function (done) { + const client = helper.client() + client.connectionParameters = { query_timeout: 10 } + + const query = new Query({ text: 'SELECT 1' }) + client.connection.emit('readyForQuery') + + client.query(query, (err) => { + assert.equal(err.message, 'Query read timeout') + done() + }) +}) diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index 07d15f660..02b0d4e6d 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -55,67 +55,68 @@ suite.test('sasl/scram', function () { assert(session1.clientNonce != session2.clientNonce) }) + + suite.test('defaults scramMaxIterations to 100000', function () { + const session = sasl.startSession(['SCRAM-SHA-256']) + + assert.equal(session.scramMaxIterations, 100000) + }) + + suite.test('honors a custom scramMaxIterations', function () { + const session = sasl.startSession(['SCRAM-SHA-256'], null, 50) + + assert.equal(session.scramMaxIterations, 50) + }) }) suite.test('continueSession', function () { - suite.testAsync('fails when last session message was not SASLInitialResponse', async function () { - assert.rejects( - function () { - return sasl.continueSession({}, '', '') - }, - { - message: 'SASL: Last message was not SASLInitialResponse', - } - ) + suite.test('fails when last session message was not SASLInitialResponse', async () => { + await assert.rejects(sasl.continueSession({}, '', ''), { + message: 'SASL: Last message was not SASLInitialResponse', + }) }) - suite.testAsync('fails when nonce is missing in server message', function () { - assert.rejects( - function () { - return sasl.continueSession( - { - message: 'SASLInitialResponse', - }, - 'bad-password', - 's=1,i=1' - ) - }, + suite.test('fails when nonce is missing in server message', async () => { + await assert.rejects( + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 'bad-password', + 's=1,i=1' + ), { message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing', } ) }) - suite.testAsync('fails when salt is missing in server message', function () { - assert.rejects( - function () { - return sasl.continueSession( - { - message: 'SASLInitialResponse', - }, - 'bad-password', - 'r=1,i=1' - ) - }, + suite.test('fails when salt is missing in server message', async () => { + await assert.rejects( + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 'bad-password', + 'r=1,i=1' + ), { message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing', } ) }) - suite.testAsync('fails when client password is not a string', function () { + suite.test('fails when client password is not a string', async () => { for (const badPasswordValue of [null, undefined, 123, new Date(), {}]) { - assert.rejects( - function () { - return sasl.continueSession( - { - message: 'SASLInitialResponse', - clientNonce: 'a', - }, - badPasswordValue, - 'r=1,i=1' - ) - }, + await assert.rejects( + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: 'a', + }, + badPasswordValue, + 'r=1,i=1' + ), { message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string', } @@ -123,60 +124,116 @@ suite.test('sasl/scram', function () { } }) - suite.testAsync('fails when client password is an empty string', function () { - assert.rejects( - function () { - return sasl.continueSession( - { - message: 'SASLInitialResponse', - clientNonce: 'a', - }, - '', - 'r=1,i=1' - ) - }, + suite.test('fails when client password is an empty string', async () => { + await assert.rejects( + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: 'a', + }, + '', + 'r=1,i=1' + ), { message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string', } ) }) - suite.testAsync('fails when iteration is missing in server message', function () { - assert.rejects( + suite.test('fails when iteration is missing in server message', async () => { + await assert.rejects( + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 'bad-password', + 'r=1,s=abcd' + ), + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing', + } + ) + }) + + suite.test('fails when server nonce does not start with client nonce', async () => { + await assert.rejects( + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: '2', + }, + 'bad-password', + 'r=1,s=abcd,i=1' + ), + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce', + } + ) + }) + + suite.test('fails when iteration count exceeds default scramMaxIterations', async function () { + await assert.rejects( function () { return sasl.continueSession( { message: 'SASLInitialResponse', + clientNonce: 'a', + scramMaxIterations: 100000, }, - 'bad-password', - 'r=1,s=abcd' + 'password', + 'r=ab,s=abcd,i=100001' ) }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing', + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count 100001 exceeds scramMaxIterations of 100000', } ) }) - suite.testAsync('fails when server nonce does not start with client nonce', function () { - assert.rejects( + suite.test('fails when iteration count exceeds a custom scramMaxIterations', async function () { + await assert.rejects( function () { return sasl.continueSession( { message: 'SASLInitialResponse', - clientNonce: '2', + clientNonce: 'a', + scramMaxIterations: 10, }, - 'bad-password', - 'r=1,s=abcd,i=1' + 'password', + 'r=ab,s=abcd,i=11' ) }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce', + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count 11 exceeds scramMaxIterations of 10', } ) }) - suite.testAsync('sets expected session data (SCRAM-SHA-256)', async function () { + suite.test('allows iteration count at the scramMaxIterations limit', async function () { + const session = { + message: 'SASLInitialResponse', + clientNonce: 'a', + scramMaxIterations: 5, + } + + await sasl.continueSession(session, 'password', 'r=ab,s=abcd,i=5') + + assert.equal(session.message, 'SASLResponse') + }) + + suite.test('disables the iteration count check when scramMaxIterations is 0', async function () { + const session = { + message: 'SASLInitialResponse', + clientNonce: 'a', + scramMaxIterations: 0, + } + + await sasl.continueSession(session, 'password', 'r=ab,s=abcd,i=999999') + + assert.equal(session.message, 'SASLResponse') + }) + + suite.test('sets expected session data (SCRAM-SHA-256)', async function () { const session = { message: 'SASLInitialResponse', clientNonce: 'a', @@ -190,7 +247,7 @@ suite.test('sasl/scram', function () { assert.equal(session.response, 'c=biws,r=ab,p=mU8grLfTjDrJer9ITsdHk0igMRDejG10EJPFbIBL3D0=') }) - suite.testAsync('sets expected session data (SCRAM-SHA-256, channel binding enabled)', async function () { + suite.test('sets expected session data (SCRAM-SHA-256, channel binding enabled)', async function () { const session = { message: 'SASLInitialResponse', clientNonce: 'a', @@ -204,7 +261,65 @@ suite.test('sasl/scram', function () { assert.equal(session.response, 'c=eSws,r=ab,p=YVTEOwOD7khu/NulscjFegHrZoTXJBFI/7L61AN9khc=') }) - suite.testAsync('sets expected session data (SCRAM-SHA-256-PLUS)', async function () { + suite.test('SASLprep maps non-ASCII space characters (RFC 3454 C.1.2) to U+0020 SPACE', async function () { + // SASLprep probably misuses the C.1.2 table; U+200B, in particular, is listed in both the C.1.2 and B.1 tables. We treat it as a space for compatibility with PostgreSQL. + const sessionPrepped = { message: 'SASLInitialResponse', clientNonce: 'a' } + const sessionRef = { message: 'SASLInitialResponse', clientNonce: 'a' } + + await sasl.continueSession(sessionPrepped, '\u200bfoo\xa0bar', 'r=ab,s=abcd,i=1') + await sasl.continueSession(sessionRef, ' foo bar', 'r=ab,s=abcd,i=1') + + assert.equal(sessionPrepped.serverSignature, sessionRef.serverSignature) + assert.equal(sessionPrepped.response, sessionRef.response) + }) + + suite.test('SASLprep maps mapped-to-nothing characters before PBKDF2 (RFC 3454 B.1)', async function () { + // Soft hyphen U+00AD is mapped to nothing by SASLprep, so 'I\u00ADX' + // must produce identical SCRAM output to 'IX'. This proves the prep + // step is engaged on the SCRAM derivation path. Without the fix the + // two would diverge and this assertion would fail. + const sessionPrepped = { message: 'SASLInitialResponse', clientNonce: 'a' } + const sessionRef = { message: 'SASLInitialResponse', clientNonce: 'a' } + + await sasl.continueSession(sessionPrepped, 'I\u00ADX', 'r=ab,s=abcd,i=1') + await sasl.continueSession(sessionRef, 'IX', 'r=ab,s=abcd,i=1') + + assert.equal(sessionPrepped.serverSignature, sessionRef.serverSignature) + assert.equal(sessionPrepped.response, sessionRef.response) + }) + + suite.test('SASLprep NFKC-normalizes passwords before PBKDF2 (RFC 4013 §2.2)', async function () { + // ROMAN NUMERAL IX (U+2168) NFKC-decomposes to the ASCII letters 'IX'. + // PostgreSQL's server applies SASLprep when computing the verifier, so + // a role created with U+2168 is stored as if it were 'IX'. The client + // must do the same. + const sessionPrepped = { message: 'SASLInitialResponse', clientNonce: 'a' } + const sessionRef = { message: 'SASLInitialResponse', clientNonce: 'a' } + + await sasl.continueSession(sessionPrepped, '\u2168', 'r=ab,s=abcd,i=1') + await sasl.continueSession(sessionRef, 'IX', 'r=ab,s=abcd,i=1') + + assert.equal(sessionPrepped.serverSignature, sessionRef.serverSignature) + assert.equal(sessionPrepped.response, sessionRef.response) + }) + + suite.test('passes ASCII control characters through normalization unchanged', async function () { + // BEL (U+0007) is an ASCII control character. The minimal SASLprep + // implementation (B.1 mapping → C.1.2 mapping → NFKC) is the identity + // on ASCII control codes, so the bytes fed to PBKDF2 are exactly the + // raw password. We snapshot the resulting SCRAM output as a regression + // guard: if anyone ever swaps the order of operations, removes the + // NFKC step, or accidentally strips ASCII bytes, this assertion trips. + const session = { message: 'SASLInitialResponse', clientNonce: 'a' } + + await sasl.continueSession(session, '\u0007abc', 'r=ab,s=abcd,i=1') + + assert.equal(session.message, 'SASLResponse') + assert.equal(session.serverSignature, 'ytJN8GA+9TeZpeS28ix+u0cwaIB7iFlWgpAsmy+MmP0=') + assert.equal(session.response, 'c=biws,r=ab,p=04HAPnY4K2UhwiD2RJtFw9sU81SLcas8B1Uqdqv8SeQ=') + }) + + suite.test('sets expected session data (SCRAM-SHA-256-PLUS)', async function () { const session = { message: 'SASLInitialResponse', mechanism: 'SCRAM-SHA-256-PLUS', @@ -284,6 +399,23 @@ suite.test('sasl/scram', function () { ) }) + suite.test('fails when server returns an error', function () { + assert.throws( + function () { + sasl.finalizeSession( + { + message: 'SASLResponse', + serverSignature: 'abcd', + }, + 'e=no-resources' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FINAL-MESSAGE: server returned error: "no-resources"', + } + ) + }) + suite.test('fails when server signature does not match', function () { assert.throws( function () { diff --git a/packages/pg/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index d7d938992..3e3918773 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -114,31 +114,148 @@ test('executing query', function () { }) }) + test('pipeline', function () { + test('sends all queries immediately after readyForQuery', function () { + const client = helper.client({ pipeline: true }) + client.connection.emit('readyForQuery') + client.query('one') + client.query('two') + client.query('three') + assert.lengthIs(client.connection.queries, 3) + assert.equal(client.connection.queries[0], 'one') + assert.equal(client.connection.queries[1], 'two') + assert.equal(client.connection.queries[2], 'three') + }) + + test('completes queries in order', function (done) { + const client = helper.client({ pipeline: true }) + const con = client.connection + con.emit('readyForQuery') + + const results = [] + client.query('one', (err, res) => { + results.push('one') + }) + client.query('two', (err, res) => { + results.push('two') + }) + client.query('three', (err, res) => { + results.push('three') + }) + + // simulate server responding to each query in order + con.emit('readyForQuery') + con.emit('readyForQuery') + con.emit('readyForQuery') + + process.nextTick(() => { + assert.deepStrictEqual(results, ['one', 'two', 'three']) + done() + }) + }) + + test('emits drain after all queries complete', function (done) { + const client = helper.client({ pipeline: true }) + const con = client.connection + con.emit('readyForQuery') + + client.query('one') + client.query('two') + + client.on('drain', () => { + done() + }) + + con.emit('readyForQuery') + con.emit('readyForQuery') + }) + + test('extended protocol: sends parse/bind/sync for each pipelined parameterized query', function () { + const client = helper.client({ pipeline: true }) + const con = client.connection + con.emit('readyForQuery') + + client.query({ text: 'SELECT $1::int', values: [1] }) + client.query({ text: 'SELECT $1::int', values: [2] }) + + // both parse messages should have been sent immediately + assert.lengthIs(con.parseMessages, 2) + assert.equal(con.parseMessages[0].text, 'SELECT $1::int') + assert.equal(con.parseMessages[1].text, 'SELECT $1::int') + // both bind messages too + assert.lengthIs(con.bindMessages, 2) + // each query sends its own sync + assert.equal(con.syncCount, 2) + }) + + test('named statement: parse sent only once when pipelining the same name', function () { + const client = helper.client({ pipeline: true }) + const con = client.connection + con.emit('readyForQuery') + + client.query({ name: 'my-stmt', text: 'SELECT $1::int', values: [1] }) + client.query({ name: 'my-stmt', text: 'SELECT $1::int', values: [2] }) + + // parse sent only once — second query reuses the submitted statement + assert.lengthIs(con.parseMessages, 1) + // both bind messages sent + assert.lengthIs(con.bindMessages, 2) + }) + + test('pipeline disabled by default', function () { + const client = helper.client() + assert.equal(client.pipeline, false) + }) + }) + test('handles errors', function () { const client = helper.client() test('throws an error when config is null', function () { - try { - client.query(null, undefined) - } catch (error) { - assert.equal( - error.message, - 'Client was passed a null or undefined query', - 'Should have thrown an Error for null queries' - ) - } + assert.throws( + () => { + client.query(null, undefined) + }, + { + message: 'Client was passed a null or undefined query', + } + ) }) test('throws an error when config is undefined', function () { - try { - client.query() - } catch (error) { - assert.equal( - error.message, - 'Client was passed a null or undefined query', - 'Should have thrown an Error for null queries' - ) - } + assert.throws( + () => { + client.query() + }, + { + message: 'Client was passed a null or undefined query', + } + ) + }) + + test('throws an error when callback is not a function', function () { + assert.throws( + () => { + client.query('SELECT $1', [1], 'notafunction') + }, + { + message: 'callback is not a function', + } + ) + }) + }) + + test('reusing a config object across calls', function () { + // Regression test for https://github.com/brianc/node-postgres/issues/2651. + test('does not leak callback state into a later promise-style call', function () { + const client = helper.client() + const config = { text: 'SELECT $1', values: [1] } + + client.query(config, function () {}) + const result = client.query(config) + + assert.ok(result instanceof Promise, 'expected client.query() to return a Promise') + result.catch(() => {}) }) }) }) diff --git a/packages/pg/test/unit/client/test-helper.js b/packages/pg/test/unit/client/test-helper.js index 3e8f75c31..8c3c3304e 100644 --- a/packages/pg/test/unit/client/test-helper.js +++ b/packages/pg/test/unit/client/test-helper.js @@ -3,15 +3,30 @@ const helper = require('../test-helper') const Connection = require('../../../lib/connection') const { Client } = helper -const makeClient = function () { +const makeClient = function (config) { const connection = new Connection({ stream: 'no' }) connection.startup = function () {} connection.connect = function () {} connection.query = function (text) { this.queries.push(text) } + connection.parse = function (msg) { + this.parseMessages.push(msg) + } + connection.bind = function (msg) { + this.bindMessages.push(msg) + } + connection.describe = function (msg) {} + connection.execute = function (msg) {} + connection.sync = function () { + this.syncCount++ + } + connection.flush = function () {} connection.queries = [] - const client = new Client({ connection: connection }) + connection.parseMessages = [] + connection.bindMessages = [] + connection.syncCount = 0 + const client = new Client({ connection: connection, ...config }) client.connect() client.connection.emit('connect') return client diff --git a/packages/pg/test/unit/client/throw-in-bind-tests.js b/packages/pg/test/unit/client/throw-in-bind-tests.js new file mode 100644 index 000000000..8b460b9e4 --- /dev/null +++ b/packages/pg/test/unit/client/throw-in-bind-tests.js @@ -0,0 +1,86 @@ +'use strict' +const helper = require('./test-helper') +const Query = require('../../../lib/query') +const assert = require('assert') + +const suite = new helper.Suite() + +const bindError = new Error('TEST: Throw in bind') + +const setupClient = function () { + const client = helper.client() + const con = client.connection + const calls = { parse: 0, sync: 0, describe: 0, execute: 0, close: 0 } + + con.parse = function () { + calls.parse++ + } + con.bind = function () { + throw bindError + } + con.describe = function () { + calls.describe++ + assert.fail('describe should not be called when bind throws') + } + con.execute = function () { + calls.execute++ + assert.fail('execute should not be called when bind throws') + } + con.close = function () { + calls.close++ + } + con.sync = function () { + calls.sync++ + } + + return { client, con, calls } +} + +suite.test('calls callback with error when bind throws', function (done) { + const { client, con, calls } = setupClient() + con.emit('readyForQuery') + client.query( + new Query({ + text: 'select $1', + values: ['x'], + callback: function (err) { + assert.equal(err, bindError) + assert.equal(calls.sync, 1, 'sync should be called once') + assert.equal(calls.describe, 0, 'describe should not be called') + assert.equal(calls.execute, 0, 'execute should not be called') + done() + }, + }) + ) +}) + +suite.test('emits error event when bind throws (no callback)', function (done) { + const { client, con, calls } = setupClient() + con.emit('readyForQuery') + const query = new Query({ + text: 'select $1', + values: ['x'], + }) + query.on('error', function (err) { + assert.equal(err, bindError) + assert.equal(calls.sync, 1, 'sync should be called once') + done() + }) + client.query(query) +}) + +suite.test('send close when bind throws', function (done) { + const { client, con, calls } = setupClient() + con.emit('readyForQuery') + client.query( + new Query({ + text: 'select $1', + values: ['x'], + callback: function (err) { + assert.equal(err, bindError) + assert.equal(calls.close, 1, 'close should be called') + done() + }, + }) + ) +}) diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 158f1dbeb..e326e2630 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -163,7 +163,7 @@ const getDNSHost = async function (host) { }) } -suite.testAsync('builds simple string', async function () { +suite.test('builds simple string', async function () { const config = { user: 'brian', password: 'xyz', @@ -358,3 +358,62 @@ suite.test('ssl is set on client', function () { }) ) }) + +suite.test('sslnegotiation defaults to undefined', function () { + const subject = new ConnectionParameters({}) + assert.strictEqual(subject.sslnegotiation, undefined) +}) + +suite.test('sslnegotiation=direct is read from config', function () { + const subject = new ConnectionParameters({ ssl: true, sslnegotiation: 'direct' }) + assert.strictEqual(subject.sslnegotiation, 'direct') +}) + +suite.test('sslnegotiation=postgres is read from config', function () { + const subject = new ConnectionParameters({ ssl: true, sslnegotiation: 'postgres' }) + assert.strictEqual(subject.sslnegotiation, 'postgres') +}) + +suite.test('sslnegotiation rejects invalid values', function () { + assert.throws(() => new ConnectionParameters({ ssl: true, sslnegotiation: 'bogus' }), /Invalid sslnegotiation value/) +}) + +suite.test('sslnegotiation=direct requires ssl', function () { + assert.throws(() => new ConnectionParameters({ ssl: false, sslnegotiation: 'direct' }), /requires SSL to be enabled/) +}) + +suite.test('sslnegotiation is read from PGSSLNEGOTIATION env var', function () { + const original = process.env.PGSSLNEGOTIATION + process.env.PGSSLNEGOTIATION = 'direct' + try { + const subject = new ConnectionParameters({ ssl: true }) + assert.strictEqual(subject.sslnegotiation, 'direct') + } finally { + if (original === undefined) { + delete process.env.PGSSLNEGOTIATION + } else { + process.env.PGSSLNEGOTIATION = original + } + } +}) + +suite.test('sslnegotiation is included in libpq connection string', function () { + const subject = new ConnectionParameters({ + user: 'brian', + host: 'localhost', + port: 5432, + database: 'postgres', + ssl: true, + sslnegotiation: 'direct', + }) + subject.getLibpqConnectionString( + assert.calls(function (err, pgCString) { + assert(!err) + assert.equal( + pgCString.indexOf("sslnegotiation='direct'") !== -1, + true, + 'libpqConnectionString should contain sslnegotiation' + ) + }) + ) +}) diff --git a/packages/pg/test/unit/connection/error-tests.js b/packages/pg/test/unit/connection/error-tests.js index 2171a25b6..04f1c3f4b 100644 --- a/packages/pg/test/unit/connection/error-tests.js +++ b/packages/pg/test/unit/connection/error-tests.js @@ -60,6 +60,77 @@ const SSLNegotiationPacketTests = [ }, ] +suite.test('direct SSL negotiation upgrades to TLS without an SSLRequest packet', function (done) { + const con = new Connection({ stream: new MemoryStream(), ssl: true, sslNegotiation: 'direct' }) + + // capture the upgrade instead of performing a real TLS handshake + let upgradeCalled = false + con.upgradeToSSL = function () { + upgradeCalled = true + } + + con.connect(1234, 'localhost') + + // simulate the raw socket connecting + con.stream.emit('connect') + + // no SSLRequest packet should have been written to the underlying stream + assert.equal(con.stream.packets.length, 0, 'direct negotiation must not send an SSLRequest packet') + assert.equal(upgradeCalled, true, 'direct negotiation must upgrade to TLS on connect') + done() +}) + +suite.test('direct SSL negotiation passes ALPN protocol to the secure stream', function (done) { + const streamModule = require('../../../lib/stream') + const originalGetSecureStream = streamModule.getSecureStream + + let capturedOptions = null + streamModule.getSecureStream = function (options) { + capturedOptions = options + return options.socket + } + + try { + const con = new Connection({ stream: new MemoryStream(), ssl: true, sslNegotiation: 'direct' }) + con.connect(1234, 'localhost') + con.stream.emit('connect') + + assert(capturedOptions, 'getSecureStream should have been called') + assert.deepEqual( + capturedOptions.ALPNProtocols, + ['postgresql'], + 'direct negotiation must request the postgresql ALPN protocol' + ) + done() + } finally { + streamModule.getSecureStream = originalGetSecureStream + } +}) + +suite.test('traditional SSL negotiation does not set ALPN protocol', function (done) { + const streamModule = require('../../../lib/stream') + const originalGetSecureStream = streamModule.getSecureStream + + let capturedOptions = null + streamModule.getSecureStream = function (options) { + capturedOptions = options + return options.socket + } + + try { + const con = new Connection({ stream: new MemoryStream(), ssl: true }) + con.connect(1234, 'localhost') + // traditional path: server signals SSL support with an 'S' byte + con.stream.emit('data', Buffer.from('S')) + + assert(capturedOptions, 'getSecureStream should have been called') + assert.equal(capturedOptions.ALPNProtocols, undefined, 'traditional negotiation must not request ALPN') + done() + } finally { + streamModule.getSecureStream = originalGetSecureStream + } +}) + for (const tc of SSLNegotiationPacketTests) { suite.test(tc.testName, function (done) { // our fake postgres server diff --git a/packages/pg/test/unit/result-tests.js b/packages/pg/test/unit/result-tests.js new file mode 100644 index 000000000..5135723ed --- /dev/null +++ b/packages/pg/test/unit/result-tests.js @@ -0,0 +1,111 @@ +'use strict' +const helper = require('./test-helper') +const assert = require('assert') +const suite = new helper.Suite() +const test = suite.test.bind(suite) + +const Result = require('../../lib/result') + +test('__proto__ column name does not pollute prototype', function () { + const result = new Result() + result.addFields([ + { name: '__proto__', dataTypeID: 25, format: 'text' }, + { name: 'id', dataTypeID: 23, format: 'text' }, + ]) + const row = result.parseRow(['malicious', '1']) + + // __proto__ should be a regular property, not affect prototype chain + assert.strictEqual(row['__proto__'], 'malicious') + assert.strictEqual(row.id, 1) + + // global Object.prototype should not be affected + assert.strictEqual({}.malicious, undefined) + assert.strictEqual(Object.prototype.malicious, undefined) +}) + +test('__proto__ column with object value does not inject prototype', function () { + // custom type parser that returns objects (like JSON) + const customTypes = { + getTypeParser: () => (val) => JSON.parse(val), + } + const result = new Result('object', customTypes) + result.addFields([ + { name: '__proto__', dataTypeID: 114, format: 'text' }, + { name: 'id', dataTypeID: 23, format: 'text' }, + ]) + + const maliciousPayload = JSON.stringify({ isAdmin: true, role: 'admin' }) + const row = result.parseRow([maliciousPayload, '1']) + + // __proto__ should be stored as a regular property + assert.deepStrictEqual(row['__proto__'], { isAdmin: true, role: 'admin' }) + + // the row should NOT inherit from the malicious payload + assert.strictEqual('isAdmin' in row, false) + assert.strictEqual('role' in row, false) +}) + +test('constructor column name is safely stored as property', function () { + const result = new Result() + result.addFields([ + { name: 'constructor', dataTypeID: 25, format: 'text' }, + { name: 'id', dataTypeID: 23, format: 'text' }, + ]) + const row = result.parseRow(['malicious', '1']) + + assert.strictEqual(row.constructor, 'malicious') + assert.strictEqual(row.id, 1) +}) + +test('hasOwnProperty column name is safely stored as property', function () { + const result = new Result() + result.addFields([ + { name: 'hasOwnProperty', dataTypeID: 25, format: 'text' }, + { name: 'data', dataTypeID: 25, format: 'text' }, + ]) + const row = result.parseRow(['not_a_function', 'value']) + + assert.strictEqual(row.hasOwnProperty, 'not_a_function') + assert.strictEqual(row.data, 'value') + + // can still check properties using Object.prototype.hasOwnProperty.call + assert.strictEqual(Object.prototype.hasOwnProperty.call(row, 'data'), true) +}) + +test('toString column name is safely stored as property', function () { + const result = new Result() + result.addFields([{ name: 'toString', dataTypeID: 25, format: 'text' }]) + const row = result.parseRow(['not_a_function']) + + assert.strictEqual(row.toString, 'not_a_function') +}) + +test('prototype column name is safely stored as property', function () { + const result = new Result() + result.addFields([ + { name: 'prototype', dataTypeID: 25, format: 'text' }, + { name: 'id', dataTypeID: 23, format: 'text' }, + ]) + const row = result.parseRow(['value', '1']) + + assert.strictEqual(row.prototype, 'value') + assert.strictEqual(row.id, 1) +}) + +test('multiple dangerous column names handled safely', function () { + const result = new Result() + result.addFields([ + { name: '__proto__', dataTypeID: 25, format: 'text' }, + { name: 'constructor', dataTypeID: 25, format: 'text' }, + { name: 'prototype', dataTypeID: 25, format: 'text' }, + { name: '__defineGetter__', dataTypeID: 25, format: 'text' }, + { name: 'id', dataTypeID: 23, format: 'text' }, + ]) + const row = result.parseRow(['a', 'b', 'c', 'd', '1']) + + assert.strictEqual(row['__proto__'], 'a') + assert.strictEqual(row.constructor, 'b') + assert.strictEqual(row.prototype, 'c') + assert.strictEqual(row['__defineGetter__'], 'd') + assert.strictEqual(row.id, 1) +}) diff --git a/packages/pg/test/unit/utils-tests.js b/packages/pg/test/unit/utils-tests.js index 5f75f6c2d..ff0d92944 100644 --- a/packages/pg/test/unit/utils-tests.js +++ b/packages/pg/test/unit/utils-tests.js @@ -33,6 +33,41 @@ test('normalizing query configs', function () { assert.deepEqual(config, { text: 'TEXT', values: [10], callback: callback }) }) +test('normalizeQueryConfig does not mutate the passed-in config object', function () { + // Regression test for https://github.com/brianc/node-postgres/issues/2651. + const original = { text: 'TEXT' } + const callback = function () {} + + const normalized = utils.normalizeQueryConfig(original, [10], callback) + + assert.equal(original.callback, undefined) + assert.equal(original.values, undefined) + assert.deepEqual(normalized, { text: 'TEXT', values: [10], callback: callback }) +}) + +test('normalizeQueryConfig preserves inherited config properties', function () { + class QueryConfig { + constructor() { + this._text = 'TEXT' + } + + get text() { + return this._text + } + } + + const original = new QueryConfig() + const callback = function () {} + + const normalized = utils.normalizeQueryConfig(original, [10], callback) + + assert.equal(original.callback, undefined) + assert.equal(original.values, undefined) + assert.equal(normalized.text, 'TEXT') + assert.deepEqual(normalized.values, [10]) + assert.equal(normalized.callback, callback) +}) + test('prepareValues: buffer prepared properly', function () { const buf = Buffer.from('quack') const out = utils.prepareValue(buf) @@ -89,6 +124,23 @@ test('prepareValues: 1 BC date prepared properly', function () { helper.resetTimezoneOffset() }) +test('prepareValue: invalid date emits deprecation warning', function () { + const warningSeen = new Promise((resolve) => { + const onWarning = (warning) => { + if (warning.code === 'PG_INVALID_DATE') { + process.removeListener('warning', onWarning) + resolve() + } + } + process.on('warning', onWarning) + }) + + const out = utils.prepareValue(new Date(NaN)) + assert.strictEqual(out, '0NaN-NaN-NaNTNaN:NaN:NaN.NaN+NaN:NaN') + + return warningSeen +}) + test('prepareValues: undefined prepared properly', function () { const out = utils.prepareValue(void 0) assert.strictEqual(out, null) diff --git a/yarn.lock b/yarn.lock index 8628e175d..a826fd60a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -654,37 +654,80 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": +"@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== +"@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" + integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + dependencies: + eslint-visitor-keys "^3.4.3" -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== +"@eslint-community/regexpp@^4.12.2": + version "4.12.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== + +"@eslint/config-array@^0.23.5": + version "0.23.5" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.23.5.tgz#56e86d243049195d8acc0c06a1b3dfdc3fa3de95" + integrity sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA== dependencies: - ajv "^6.12.4" + "@eslint/object-schema" "^3.0.5" + debug "^4.3.1" + minimatch "^10.2.4" + +"@eslint/config-helpers@^0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.5.5.tgz#ae16134e4792ac5fbdc533548a24ac1ea9f7f3ae" + integrity sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w== + dependencies: + "@eslint/core" "^1.2.1" + +"@eslint/core@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-1.2.1.tgz#c1da7cd1b82fa8787f98b5629fb811848a1b63ce" + integrity sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.3.5": + version "3.3.5" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.5.tgz#c131793cfc1a7b96f24a83e0a8bbd4b881558c60" + integrity sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg== + dependencies: + ajv "^6.14.0" debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" + espree "^10.0.1" + globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" + js-yaml "^4.1.1" + minimatch "^3.1.5" strip-json-comments "^3.1.1" -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@eslint/js@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-10.0.1.tgz#1e8a876f50117af8ab67e47d5ad94d38d6622583" + integrity sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA== + +"@eslint/object-schema@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-3.0.5.tgz#88e9bf4d11d2b19c082e78ebe7ce88724a5eb091" + integrity sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw== + +"@eslint/plugin-kit@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz#c4125fd015eceeb09b793109fdbcd4dd0a02d346" + integrity sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ== + dependencies: + "@eslint/core" "^1.2.1" + levn "^0.4.1" "@evocateur/libnpmaccess@^3.1.2": version "3.1.2" @@ -765,24 +808,36 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== +"@humanfs/core@^0.19.2": + version "0.19.2" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.2.tgz#a8272ca03b2acf492670222b2320b6c421bfde60" + integrity sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA== dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" + "@humanfs/types" "^0.15.0" + +"@humanfs/node@^0.16.6": + version "0.16.8" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.8.tgz#8f800cccc13f4f8cd3116e2d9c0a94939da3e3ed" + integrity sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ== + dependencies: + "@humanfs/core" "^0.19.2" + "@humanfs/types" "^0.15.0" + "@humanwhocodes/retry" "^0.4.0" + +"@humanfs/types@^0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@humanfs/types/-/types-0.15.0.tgz#f2a09f62012390b2bff3fc6fb248ddec8c09a090" + integrity sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q== "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" - integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== +"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@img/sharp-darwin-arm64@0.33.5": version "0.33.5" @@ -1678,37 +1733,11 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - "@nodelib/fs.stat@^1.1.2": version "1.1.3" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@nodelib/fs.stat@^2.0.2": - version "2.0.3" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz" - integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - "@npmcli/agent@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-3.0.0.tgz#1685b1fbd4a1b7bb4f930cbb68ce801edfe7aa44" @@ -1841,10 +1870,10 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@pkgr/core@^0.2.4": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.7.tgz#eb5014dfd0b03e7f3ba2eeeff506eed89b028058" - integrity sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg== +"@pkgr/core@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" + integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== "@rollup/plugin-commonjs@^28.0.3": version "28.0.3" @@ -2010,12 +2039,17 @@ "@types/estree" "*" "@types/json-schema" "*" +"@types/esrecurse@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@types/esrecurse/-/esrecurse-4.3.1.tgz#6f636af962fbe6191b830bd676ba5986926bccec" + integrity sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw== + "@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.6": version "1.0.7" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== -"@types/estree@1.0.8": +"@types/estree@1.0.8", "@types/estree@^1.0.8": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== @@ -2028,7 +2062,7 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -2043,25 +2077,20 @@ resolved "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz" integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= -"@types/mocha@^10.0.7": - version "10.0.7" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.7.tgz#4c620090f28ca7f905a94b706f74dc5b57b44f2f" - integrity sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw== +"@types/mocha@^10.0.10": + version "10.0.10" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== "@types/node@*", "@types/node@>= 8": version "12.12.21" resolved "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz" integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== -"@types/node@^12.12.21": - version "12.12.67" - resolved "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz" - integrity sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg== - -"@types/node@^14.0.0": - version "14.11.8" - resolved "https://registry.npmjs.org/@types/node/-/node-14.11.8.tgz" - integrity sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw== +"@types/node@^16", "@types/node@^16.0.0": + version "16.18.126" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.126.tgz#27875faa2926c0f475b39a8bb1e546c0176f8d4b" + integrity sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -2095,136 +2124,101 @@ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== -"@types/semver@^7.5.0": - version "7.5.6" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" - integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== - -"@typescript-eslint/eslint-plugin@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.0.tgz#62cda0d35bbf601683c6e58cf5d04f0275caca4e" - integrity sha512-M72SJ0DkcQVmmsbqlzc6EJgb/3Oz2Wdm6AyESB4YkGgCxP8u5jt5jn4/OBMPK3HLOxcttZq5xbBBU7e2By4SZQ== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "7.0.0" - "@typescript-eslint/type-utils" "7.0.0" - "@typescript-eslint/utils" "7.0.0" - "@typescript-eslint/visitor-keys" "7.0.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" +"@typescript-eslint/eslint-plugin@^8.58.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.0.tgz#fcbe76b693ce2412410cf4d48aefd617d345f2d9" + integrity sha512-HyAZtpdkgZwpq8Sz3FSUvCR4c+ScbuWa9AksK2Jweub7w4M3yTz4O11AqVJzLYjy/B9ZWPyc81I+mOdJU/bDQw== + dependencies: + "@eslint-community/regexpp" "^4.12.2" + "@typescript-eslint/scope-manager" "8.59.0" + "@typescript-eslint/type-utils" "8.59.0" + "@typescript-eslint/utils" "8.59.0" + "@typescript-eslint/visitor-keys" "8.59.0" + ignore "^7.0.5" natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/parser@^6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.17.0.tgz#8cd7a0599888ca6056082225b2fdf9a635bf32a1" - integrity sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A== - dependencies: - "@typescript-eslint/scope-manager" "6.17.0" - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/typescript-estree" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz#70e6c1334d0d76562dfa61aed9009c140a7601b4" - integrity sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA== - dependencies: - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" - -"@typescript-eslint/scope-manager@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.0.0.tgz#15ea9abad2b56fc8f5c0b516775f41c86c5c8685" - integrity sha512-IxTStwhNDPO07CCrYuAqjuJ3Xf5MrMaNgbAZPxFXAUpAtwqFxiuItxUaVtP/SJQeCdJjwDGh9/lMOluAndkKeg== - dependencies: - "@typescript-eslint/types" "7.0.0" - "@typescript-eslint/visitor-keys" "7.0.0" - -"@typescript-eslint/type-utils@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.0.0.tgz#a4c7ae114414e09dbbd3c823b5924793f7483252" - integrity sha512-FIM8HPxj1P2G7qfrpiXvbHeHypgo2mFpFGoh5I73ZlqmJOsloSa1x0ZyXCer43++P1doxCgNqIOLqmZR6SOT8g== - dependencies: - "@typescript-eslint/typescript-estree" "7.0.0" - "@typescript-eslint/utils" "7.0.0" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/types@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.17.0.tgz#844a92eb7c527110bf9a7d177e3f22bd5a2f40cb" - integrity sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A== - -"@typescript-eslint/types@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.0.0.tgz#2e5889c7fe3c873fc6dc6420aa77775f17cd5dc6" - integrity sha512-9ZIJDqagK1TTs4W9IyeB2sH/s1fFhN9958ycW8NRTg1vXGzzH5PQNzq6KbsbVGMT+oyyfa17DfchHDidcmf5cg== - -"@typescript-eslint/typescript-estree@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz#b913d19886c52d8dc3db856903a36c6c64fd62aa" - integrity sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg== - dependencies: - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" + ts-api-utils "^2.5.0" + +"@typescript-eslint/parser@^8.58.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.59.0.tgz#57a138280b3ceaf07904fbd62c433d5cc1ee1573" + integrity sha512-TI1XGwKbDpo9tRW8UDIXCOeLk55qe9ZFGs8MTKU6/M08HWTw52DD/IYhfQtOEhEdPhLMT26Ka/x7p70nd3dzDg== + dependencies: + "@typescript-eslint/scope-manager" "8.59.0" + "@typescript-eslint/types" "8.59.0" + "@typescript-eslint/typescript-estree" "8.59.0" + "@typescript-eslint/visitor-keys" "8.59.0" + debug "^4.4.3" + +"@typescript-eslint/project-service@8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.59.0.tgz#914bf62069d870faa0389ffd725774a200f511bf" + integrity sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.59.0" + "@typescript-eslint/types" "^8.59.0" + debug "^4.4.3" + +"@typescript-eslint/scope-manager@8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.59.0.tgz#f71be268bd31da1c160815c689e4dde7c9bc9e8e" + integrity sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg== + dependencies: + "@typescript-eslint/types" "8.59.0" + "@typescript-eslint/visitor-keys" "8.59.0" + +"@typescript-eslint/tsconfig-utils@8.59.0", "@typescript-eslint/tsconfig-utils@^8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.0.tgz#1276077f5ad77e384446ea28a2474e8f8be1af41" + integrity sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg== + +"@typescript-eslint/type-utils@8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.59.0.tgz#2834ea3b179cedfc9244dcd4f74105a27751a439" + integrity sha512-3TRiZaQSltGqGeNrJzzr1+8YcEobKH9rHnqIp/1psfKFmhRQDNMGP5hBufanYTGznwShzVLs3Mz+gDN7HkWfXg== + dependencies: + "@typescript-eslint/types" "8.59.0" + "@typescript-eslint/typescript-estree" "8.59.0" + "@typescript-eslint/utils" "8.59.0" + debug "^4.4.3" + ts-api-utils "^2.5.0" + +"@typescript-eslint/types@8.59.0", "@typescript-eslint/types@^8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.59.0.tgz#cfcc643c6e879016479775850d86d84c14492738" + integrity sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A== + +"@typescript-eslint/typescript-estree@8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.0.tgz#feba58a70ab6ea7ac53a2f3ae900db28ce3454c2" + integrity sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw== + dependencies: + "@typescript-eslint/project-service" "8.59.0" + "@typescript-eslint/tsconfig-utils" "8.59.0" + "@typescript-eslint/types" "8.59.0" + "@typescript-eslint/visitor-keys" "8.59.0" + debug "^4.4.3" + minimatch "^10.2.2" + semver "^7.7.3" + tinyglobby "^0.2.15" + ts-api-utils "^2.5.0" -"@typescript-eslint/typescript-estree@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.0.tgz#7ce66f2ce068517f034f73fba9029300302fdae9" - integrity sha512-JzsOzhJJm74aQ3c9um/aDryHgSHfaX8SHFIu9x4Gpik/+qxLvxUylhTsO9abcNu39JIdhY2LgYrFxTii3IajLA== +"@typescript-eslint/utils@8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.59.0.tgz#f50df9bd6967881ef64fba62230111153179ead5" + integrity sha512-I1R/K7V07XsMJ12Oaxg/O9GfrysGTmCRhvZJBv0RE0NcULMzjqVpR5kRRQjHsz3J/bElU7HwCO7zkqL+MSUz+g== dependencies: - "@typescript-eslint/types" "7.0.0" - "@typescript-eslint/visitor-keys" "7.0.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" + "@eslint-community/eslint-utils" "^4.9.1" + "@typescript-eslint/scope-manager" "8.59.0" + "@typescript-eslint/types" "8.59.0" + "@typescript-eslint/typescript-estree" "8.59.0" -"@typescript-eslint/utils@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.0.0.tgz#e43710af746c6ae08484f7afc68abc0212782c7e" - integrity sha512-kuPZcPAdGcDBAyqDn/JVeJVhySvpkxzfXjJq1X1BFSTYo1TTuo4iyb937u457q4K0In84p6u2VHQGaFnv7VYqg== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "7.0.0" - "@typescript-eslint/types" "7.0.0" - "@typescript-eslint/typescript-estree" "7.0.0" - semver "^7.5.4" - -"@typescript-eslint/visitor-keys@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz#3ed043709c39b43ec1e58694f329e0b0430c26b6" - integrity sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg== - dependencies: - "@typescript-eslint/types" "6.17.0" - eslint-visitor-keys "^3.4.1" - -"@typescript-eslint/visitor-keys@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.0.tgz#83cdadd193ee735fe9ea541f6a2b4d76dfe62081" - integrity sha512-JZP0uw59PRHp7sHQl3aF/lFgwOW2rgNVnXUksj1d932PMita9wFBd3621vHQRDvHwPsSY9FMAAHVc8gTvLYY4w== +"@typescript-eslint/visitor-keys@8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.0.tgz#2e80de30e7e944ed4bd47d751e37dcb04db03795" + integrity sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q== dependencies: - "@typescript-eslint/types" "7.0.0" - eslint-visitor-keys "^3.4.1" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + "@typescript-eslint/types" "8.59.0" + eslint-visitor-keys "^5.0.0" "@vitest/expect@3.0.9": version "3.0.9" @@ -2490,10 +2484,10 @@ acorn@^8.14.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== -acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.15.0, acorn@^8.16.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== agent-base@4, agent-base@^4.3.0: version "4.3.0" @@ -2545,7 +2539,7 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.12.3: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2555,6 +2549,16 @@ ajv@^6.12.3, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.14.0: + version "6.15.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.15.0.tgz#07e982c74626167aa7a2495c53817892d7139492" + integrity sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ajv@^8.0.0, ajv@^8.9.0: version "8.17.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" @@ -2570,11 +2574,6 @@ amdefine@>=0.0.4: resolved "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz" @@ -2629,14 +2628,6 @@ any-promise@^1.0.0: resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - append-transform@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" @@ -2721,11 +2712,6 @@ array-union@^1.0.2: dependencies: array-uniq "^1.0.1" -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" @@ -2827,6 +2813,11 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +balanced-match@^4.0.2: + version "4.0.4" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.4.tgz#bfb10662feed8196a2c62e7c68e17720c274179a" + integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== + base64-js@0.0.2: version "0.0.2" resolved "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz" @@ -2857,11 +2848,6 @@ before-after-hook@^2.0.0: resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz" integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== -binary-extensions@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz" - integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== - bindings@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -2907,6 +2893,20 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" +brace-expansion@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.3.tgz#6a9c6c268f85b53959ec527aeafe0f7300258eef" + integrity sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA== + dependencies: + balanced-match "^4.0.2" + +brace-expansion@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.5.tgz#dcc3a37116b79f3e1b46db994ced5d570e930fdb" + integrity sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ== + dependencies: + balanced-match "^4.0.2" + braces@^2.3.1: version "2.3.2" resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" @@ -2923,14 +2923,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browser-stdout@1.3.1: +browser-stdout@^1.3.1: version "1.3.1" resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== @@ -3065,7 +3058,7 @@ callsites@^2.0.0: callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase-keys@^2.0.0: @@ -3157,14 +3150,6 @@ chalk@^2.0.0, chalk@^2.3.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: - version "4.1.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -3188,20 +3173,12 @@ check-error@^2.1.1: resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== -chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" +chokidar@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.4: version "1.1.4" @@ -3218,11 +3195,6 @@ chrome-trace-event@^1.0.2: resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== -chunky@^0.0.0: - version "0.0.0" - resolved "https://registry.npmjs.org/chunky/-/chunky-0.0.0.tgz" - integrity sha1-HnWAojwIOJfSrWYkWefv2EZfYIo= - ci-info@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" @@ -3278,13 +3250,13 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" - strip-ansi "^6.0.0" + strip-ansi "^6.0.1" wrap-ansi "^7.0.0" clone-deep@^4.0.1: @@ -3604,7 +3576,7 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.0: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -3613,7 +3585,7 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -cross-spawn@^7.0.3: +cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -3665,7 +3637,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -3693,6 +3665,13 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.4.0: dependencies: ms "^2.1.3" +debug@^4.3.5, debug@^4.4.3: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz" @@ -3834,16 +3813,16 @@ dezalgo@^1.0.0: asap "^2.0.0" wrappy "1" -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - diff@^4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-7.0.0.tgz#3fb34d387cd76d803f6eebea67b921dab0182a9a" + integrity sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw== + dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz" @@ -3851,20 +3830,6 @@ dir-glob@^2.2.2: dependencies: path-type "^3.0.0" -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - dot-prop@^4.2.0: version "4.2.1" resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz" @@ -4152,16 +4117,16 @@ escalade@^3.2.0: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== -escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escodegen@1.8.x: version "1.8.1" resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz" @@ -4179,38 +4144,18 @@ eslint-config-prettier@^10.1.2: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz#31a4b393c40c4180202c27e829af43323bf85276" integrity sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA== -eslint-plugin-es@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz" - integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== - dependencies: - eslint-utils "^2.0.0" - regexpp "^3.0.0" - -eslint-plugin-node@^11.1.0: - version "11.1.0" - resolved "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz" - integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== - dependencies: - eslint-plugin-es "^3.0.0" - eslint-utils "^2.0.0" - ignore "^5.1.1" - minimatch "^3.0.4" - resolve "^1.10.1" - semver "^6.1.0" - eslint-plugin-prettier@^5.1.2: - version "5.5.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.1.tgz#470820964de9aedb37e9ce62c3266d2d26d08d15" - integrity sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw== + version "5.5.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#9eae11593faa108859c26f9a9c367d619a0769c0" + integrity sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw== dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.11.7" + prettier-linter-helpers "^1.0.1" + synckit "^0.11.12" -eslint-plugin-promise@^7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz#a0652195700aea40b926dc3c74b38e373377bfb0" - integrity sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA== +eslint-plugin-promise@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-7.3.0.tgz#7c61e117f5db8d7a300bd5143c15d1d828e4c124" + integrity sha512-6uGiOR0INuujr6PEQmeSSP7GbIMJ/ebEXXiEzb/nOj68LknH5Pxzb/AbZivmr6VE6TkTE8rTjRK9zhKpK6HsRA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" @@ -4222,83 +4167,84 @@ eslint-scope@5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== +eslint-scope@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-9.1.2.tgz#b9de6ace2fab1cff24d2e58d85b74c8fcea39802" + integrity sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ== dependencies: + "@types/esrecurse" "^4.3.1" + "@types/estree" "^1.0.8" esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.56.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint-visitor-keys@^5.0.0, eslint-visitor-keys@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#9e3c9489697824d2d4ce3a8ad12628f91e9f59be" + integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA== + +eslint@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-10.2.1.tgz#224b2a6caeb34473eddcf918762363e2e063222a" + integrity sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.2" + "@eslint/config-array" "^0.23.5" + "@eslint/config-helpers" "^0.5.5" + "@eslint/core" "^1.2.1" + "@eslint/plugin-kit" "^0.7.1" + "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + ajv "^6.14.0" + cross-spawn "^7.0.6" debug "^4.3.2" - doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" + eslint-scope "^9.1.2" + eslint-visitor-keys "^5.0.1" + espree "^11.2.0" + esquery "^1.7.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" + file-entry-cache "^8.0.0" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" + minimatch "^10.2.4" natural-compare "^1.4.0" optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== +espree@^10.0.1: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== dependencies: - acorn "^8.9.0" + acorn "^8.15.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" + eslint-visitor-keys "^4.2.1" + +espree@^11.2.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-11.2.0.tgz#01d5e47dc332aaba3059008362454a8cc34ccaa5" + integrity sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw== + dependencies: + acorn "^8.16.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^5.0.1" esprima@2.7.x, esprima@^2.7.1: version "2.7.3" @@ -4310,10 +4256,10 @@ esprima@^4.0.0: resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== +esquery@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" + integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== dependencies: estraverse "^5.1.0" @@ -4497,17 +4443,6 @@ fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" @@ -4528,13 +4463,6 @@ fastest-levenshtein@^1.0.12: resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== -fastq@^1.6.0: - version "1.8.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz" - integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== - dependencies: - reusify "^1.0.4" - fdir@^6.2.0, fdir@^6.4.3, fdir@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" @@ -4552,12 +4480,12 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" file-uri-to-path@1.0.0: version "1.0.0" @@ -4574,13 +4502,6 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - find-cache-dir@^3.2.0: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" @@ -4590,14 +4511,6 @@ find-cache-dir@^3.2.0: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-up@5.0.0, find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - find-up@^1.0.0: version "1.1.2" resolved "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz" @@ -4628,14 +4541,21 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" + keyv "^4.5.4" flat@^5.0.2: version "5.0.2" @@ -4924,7 +4844,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2: +glob-parent@^5.0.0: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -4948,17 +4868,6 @@ glob-to-regexp@^0.3.0: resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - glob@^10.2.2: version "10.4.1" resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.1.tgz#0cfb01ab6a6b438177bfe6a58e2576f6efe909c2" @@ -4970,6 +4879,18 @@ glob@^10.2.2: minipass "^7.1.2" path-scurry "^1.11.1" +glob@^10.4.5: + version "10.5.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" + integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^5.0.15: version "5.0.15" resolved "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz" @@ -4998,24 +4919,10 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== globby@^9.2.0: version "9.2.0" @@ -5036,11 +4943,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - handlebars@^4.0.1, handlebars@^4.7.6: version "4.7.7" resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz" @@ -5149,7 +5051,7 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" -he@1.2.0: +he@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -5253,11 +5155,16 @@ ignore@^4.0.3: resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4: +ignore@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== +ignore@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz" @@ -5267,9 +5174,9 @@ import-fresh@^2.0.0: resolve-from "^3.0.0" import-fresh@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz" - integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -5410,13 +5317,6 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" @@ -5529,7 +5429,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -5553,11 +5453,6 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - is-obj@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" @@ -5803,13 +5698,20 @@ js-yaml@3.x, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@4.1.0, js-yaml@^4.1.0: +js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" +js-yaml@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + jsbn@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" @@ -5892,7 +5794,7 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -keyv@^4.5.3: +keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -5969,12 +5871,12 @@ levn@~0.3.0: type-check "~0.3.2" libpq@^1.8.15: - version "1.8.15" - resolved "https://registry.yarnpkg.com/libpq/-/libpq-1.8.15.tgz#bf9cea8e59e1a4a911d06df01d408213a09925ad" - integrity sha512-4lSWmly2Nsj3LaTxxtFmJWuP3Kx+0hYHEd+aNrcXEWT0nKWaPd9/QZPiMkkC680zeALFGHQdQWjBvnilL+vgWA== + version "1.11.0" + resolved "https://registry.yarnpkg.com/libpq/-/libpq-1.11.0.tgz#1baf0920eb51ebe1399de942414e012142dcead8" + integrity sha512-mHoPlvMwYDMJV36bS2w3eSdFD4eDSm7P9FsvruUldQxzE23/W6qitT9VU/yD1+g2vpgpDktnk2iEYJyhy1RR5g== dependencies: bindings "1.5.0" - nan "~2.22.2" + nan "~2.26.2" lines-and-columns@^1.1.6: version "1.1.6" @@ -6073,11 +5975,6 @@ lodash.ismatch@^4.4.0: resolved "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz" integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz" @@ -6118,7 +6015,7 @@ log-driver@^1.2.7: resolved "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== -log-symbols@4.1.0: +log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -6330,7 +6227,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: +merge2@^1.2.3: version "1.4.1" resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -6354,14 +6251,6 @@ micromatch@^3.1.10: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - mime-db@1.44.0: version "1.44.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz" @@ -6435,33 +6324,26 @@ miniflare@4.20250428.0: youch "3.3.4" zod "3.22.3" -"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== +minimatch@^10.2.2, minimatch@^10.2.4: + version "10.2.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.5.tgz#bd48687a0be38ed2961399105600f832095861d1" + integrity sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg== dependencies: - brace-expansion "^2.0.1" + brace-expansion "^5.0.5" -minimatch@9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== +minimatch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: - brace-expansion "^2.0.1" + brace-expansion "^1.1.7" minimatch@^9.0.4: version "9.0.4" @@ -6470,6 +6352,13 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.5: + version "9.0.8" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.8.tgz#bb3aa36d7b42ea77a93c44d5c1082b188112497c" + integrity sha512-reYkDYtj/b19TeqbNZCV4q9t+Yxylf/rYBsLb42SXJatTv4/ylq5lEiAmhA/IToxO7NI2UzNMghHoHuaqDkAjw== + dependencies: + brace-expansion "^5.0.2" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz" @@ -6608,31 +6497,32 @@ mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5: dependencies: minimist "^1.2.5" -mocha@10.5.2, mocha@^10.5.2: - version "10.5.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.5.2.tgz#0a3481fb67c0a7fc144a909b2d6a9fec35ec5989" - integrity sha512-9btlN3JKCefPf+vKd/kcKz2SXxi12z6JswkGfaAF0saQvnsqLJk504ZmbxhSoENge08E9dsymozKgFMTl5PQsA== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "^3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "8.1.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" +mocha@11.7.5, mocha@^11.7.5: + version "11.7.5" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.7.5.tgz#58f5bbfa5e0211ce7e5ee6128107cefc2515a627" + integrity sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig== + dependencies: + browser-stdout "^1.3.1" + chokidar "^4.0.1" + debug "^4.3.5" + diff "^7.0.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^9.0.5" + ms "^2.1.3" + picocolors "^1.1.1" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^9.2.0" + yargs "^17.7.2" + yargs-parser "^21.1.1" + yargs-unparser "^2.0.0" modify-values@^1.0.0: version "1.0.1" @@ -6661,7 +6551,7 @@ ms@2.1.2: resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: +ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -6700,10 +6590,10 @@ mz@^2.5.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@~2.22.2: - version "2.22.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.2.tgz#6b504fd029fb8f38c0990e52ad5c26772fdacfbb" - integrity sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ== +nan@~2.26.2: + version "2.26.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.26.2.tgz#2e5e25764224c737b9897790b57c3294d4dcee9c" + integrity sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw== nanoid@^3.3.11: version "3.3.11" @@ -6840,11 +6730,6 @@ normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package- semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - normalize-url@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz" @@ -7228,6 +7113,11 @@ package-hash@^4.0.0: lodash.flattendeep "^4.4.0" release-zalgo "^1.0.0" +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + parallel-transform@^1.1.0: version "1.2.0" resolved "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz" @@ -7239,7 +7129,7 @@ parallel-transform@^1.1.0: parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" @@ -7368,11 +7258,6 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - pathe@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" @@ -7444,11 +7329,6 @@ picocolors@^1.1.1: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - picomatch@^4.0.2, picomatch@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" @@ -7568,10 +7448,10 @@ prelude-ls@~1.1.2: resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== +prettier-linter-helpers@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz#6a31f88a4bad6c7adda253de12ba4edaea80ebcd" + integrity sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg== dependencies: fast-diff "^1.1.2" @@ -7827,12 +7707,10 @@ readdir-scoped-modules@^1.0.0: graceful-fs "^4.1.2" once "^1.3.0" -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== rechoir@^0.8.0: version "0.8.0" @@ -7873,11 +7751,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" @@ -7987,7 +7860,7 @@ resolve@1.1.x: resolved "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.10.0, resolve@^1.10.1: +resolve@^1.10.0: version "1.17.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== @@ -8026,11 +7899,6 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" @@ -8038,7 +7906,7 @@ rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -8104,11 +7972,6 @@ run-async@^2.2.0: resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== -run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== - run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz" @@ -8160,22 +8023,15 @@ schema-utils@^4.3.0, schema-utils@^4.3.2: resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3, semver@^7.7.1, semver@^7.7.2: - version "7.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" - integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== - -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" +semver@^7.3.5, semver@^7.5.3, semver@^7.6.3, semver@^7.7.1, semver@^7.7.2, semver@^7.7.3: + version "7.7.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" + integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== serialize-javascript@^6.0.2: version "6.0.2" @@ -8286,11 +8142,6 @@ slash@^2.0.0: resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - sliced@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/sliced/-/sliced-0.0.5.tgz#5edc044ca4eb6f7816d50ba2fc63e25d8fe4707f" @@ -8629,7 +8480,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8760,7 +8611,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -8774,13 +8625,6 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" -supports-color@8.1.1, supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-color@^3.1.0: version "3.2.3" resolved "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz" @@ -8802,17 +8646,24 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0, supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.11.7: - version "0.11.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" - integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== +synckit@^0.11.12: + version "0.11.12" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.12.tgz#abe74124264fbc00a48011b0d98bdc1cffb64a7b" + integrity sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ== dependencies: - "@pkgr/core" "^0.2.4" + "@pkgr/core" "^0.2.9" tapable@^2.1.1, tapable@^2.2.0: version "2.2.2" @@ -8896,11 +8747,6 @@ text-extensions@^1.0.0: resolved "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" @@ -8991,13 +8837,6 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" @@ -9053,10 +8892,10 @@ trim-off-newlines@^1.0.0: resolved "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.3.tgz" integrity sha512-kh6Tu6GbeSNMGfrrZh6Bb/4ZEHV1QlB4xNDBeog8Y9/QwFlKTRyWvY3Fs9tRDAMZliVUwieMgEdIeL/FtqjkJg== -ts-api-utils@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" - integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== +ts-api-utils@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz#4acd4a155e22734990a5ed1fe9e97f113bcb37c1" + integrity sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA== ts-node@^8.5.4: version "8.10.2" @@ -9125,11 +8964,6 @@ type-fest@^0.13.1: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz" integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - type-fest@^0.3.0: version "0.3.1" resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz" @@ -9157,10 +8991,10 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.0.3: - version "4.8.4" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz" - integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== +typescript@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.3.tgz#90251dc007916e972786cb94d74d15b185577d21" + integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw== ufo@^1.5.4: version "1.6.1" @@ -9605,10 +9439,10 @@ workerd@1.20250428.0: "@cloudflare/workerd-linux-arm64" "1.20250428.0" "@cloudflare/workerd-windows-64" "1.20250428.0" -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== +workerpool@^9.2.0: + version "9.3.4" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-9.3.4.tgz#f6c92395b2141afd78e2a889e80cb338fe9fca41" + integrity sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg== wrangler@4.14.0: version "4.14.0" @@ -9782,11 +9616,6 @@ yallist@^5.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - yargs-parser@^15.0.1: version "15.0.1" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz" @@ -9803,12 +9632,12 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs-unparser@2.0.0: +yargs-unparser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== @@ -9818,19 +9647,6 @@ yargs-unparser@2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - yargs@^14.2.2: version "14.2.3" resolved "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz" @@ -9865,6 +9681,19 @@ yargs@^15.0.2: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yn@3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz"