From 46cdf9e32b70e74e0ca89c194827217b912012a5 Mon Sep 17 00:00:00 2001 From: uap-dev Date: Mon, 2 Feb 2026 18:19:30 -0800 Subject: [PATCH 01/81] [fix] fix unhandled callback error for submittables (#3589) * fixes bug where submittable without callback throws error * add querystream to test remove comments * fix test * Revert unrelated reformatting --------- Co-authored-by: Charmander <~@charmander.me> --- packages/pg-query-stream/test/error.ts | 20 +++++++++++ packages/pg/lib/client.js | 2 +- packages/pg/lib/native/client.js | 2 +- .../test/unit/client/query-timeout-tests.js | 34 +++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 packages/pg/test/unit/client/query-timeout-tests.js 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/lib/client.js b/packages/pg/lib/client.js index b0214e3dc..459439037 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -628,7 +628,7 @@ class Client extends EventEmitter { } if (readTimeout) { - queryCallback = query.callback + queryCallback = query.callback || (() => {}) readTimeoutTimer = setTimeout(() => { const error = new Error('Query read timeout') diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 4bee7ce3c..667bf613d 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -184,7 +184,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') 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() + }) +}) From b2e9cb13e29f1054ddfa6feba4d27949ec6969ff Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 3 Feb 2026 10:57:23 -0600 Subject: [PATCH 02/81] Remove testAsync - its redundant (#3588) --- .../client/async-stack-trace-tests.js | 4 ++-- .../client/error-handling-tests.js | 2 +- .../client/prepared-statement-tests.js | 2 +- .../integration/client/sasl-scram-tests.js | 12 +++++------ .../test/integration/client/timezone-tests.js | 2 +- .../connection-pool-size-tests.js | 2 +- .../integration/connection-pool/tls-tests.js | 2 +- .../test/integration/gh-issues/1105-tests.js | 2 +- .../test/integration/gh-issues/1542-tests.js | 2 +- .../test/integration/gh-issues/2085-tests.js | 4 ++-- .../test/integration/gh-issues/2108-tests.js | 2 +- .../test/integration/gh-issues/2416-tests.js | 2 +- .../test/integration/gh-issues/2716-tests.js | 2 +- .../test/integration/gh-issues/2862-tests.js | 2 +- .../test/integration/gh-issues/3062-tests.js | 2 +- .../test/integration/gh-issues/3174-tests.js | 6 +++--- .../test/integration/gh-issues/3487-tests.js | 2 +- packages/pg/test/suite.js | 21 +++++++------------ .../pg/test/unit/client/sasl-scram-tests.js | 20 +++++++++--------- .../connection-parameters/creation-tests.js | 2 +- 20 files changed, 45 insertions(+), 50 deletions(-) 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..92ca3e4d2 100644 --- a/packages/pg/test/integration/client/async-stack-trace-tests.js +++ b/packages/pg/test/integration/client/async-stack-trace-tests.js @@ -12,7 +12,7 @@ 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() { + 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') @@ -28,7 +28,7 @@ if (NODE_MAJOR_VERSION >= 16) { } }) - suite.testAsync('promise API async stack trace in client', async function outerFunction() { + suite.test('promise API async stack trace in client', async function outerFunction() { async function innerFunction() { const client = new pg.Client() await client.connect() diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index 8a6fc667f..7493ef68d 100644 --- a/packages/pg/test/integration/client/error-handling-tests.js +++ b/packages/pg/test/integration/client/error-handling-tests.js @@ -47,7 +47,7 @@ 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', () => { const client = new Client() return client.connect().then(() => { return helper.rejection(client.connect()).then((err) => { diff --git a/packages/pg/test/integration/client/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js index 9047eae6c..5ff72a89e 100644 --- a/packages/pg/test/integration/client/prepared-statement-tests.js +++ b/packages/pg/test/integration/client/prepared-statement-tests.js @@ -174,7 +174,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/sasl-scram-tests.js b/packages/pg/test/integration/client/sasl-scram-tests.js index ce5d63e65..85bf2cd34 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 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/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/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..24347a23e 100644 --- a/packages/pg/test/integration/gh-issues/3174-tests.js +++ b/packages/pg/test/integration/gh-issues/3174-tests.js @@ -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)) }) @@ -110,7 +110,7 @@ const testErrorBuffer = (bufferName, errorBuffer) => { 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)) }) @@ -137,7 +137,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/suite.js b/packages/pg/test/suite.js index 7d19edbb0..7a1c20008 100644 --- a/packages/pg/test/suite.js +++ b/packages/pg/test/suite.js @@ -1,6 +1,11 @@ 'use strict' const async = require('async') +const { deprecate } = require('util') + +const deprecatedTestAsync = deprecate(function (name, cb) { + this.test(name, cb) +}, 'Suite#testAsync is deprecated. Use Suite#test instead - it handles promises & async functions just fine.') class Test { constructor(name, cb) { @@ -29,7 +34,7 @@ class Test { } result.then(() => cb()).catch((err) => cb(err || new Error('Unhandled promise rejection'))) } else { - this.action.call(this, cb) + this.action(cb) } } } @@ -71,18 +76,8 @@ class Suite { 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) + testAsync(name, cb) { + return deprecatedTestAsync.call(this, name, cb) } } diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index 07d15f660..2df0f1860 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -58,7 +58,7 @@ suite.test('sasl/scram', function () { }) suite.test('continueSession', function () { - suite.testAsync('fails when last session message was not SASLInitialResponse', async function () { + suite.test('fails when last session message was not SASLInitialResponse', async function () { assert.rejects( function () { return sasl.continueSession({}, '', '') @@ -69,7 +69,7 @@ suite.test('sasl/scram', function () { ) }) - suite.testAsync('fails when nonce is missing in server message', function () { + suite.test('fails when nonce is missing in server message', function () { assert.rejects( function () { return sasl.continueSession( @@ -86,7 +86,7 @@ suite.test('sasl/scram', function () { ) }) - suite.testAsync('fails when salt is missing in server message', function () { + suite.test('fails when salt is missing in server message', function () { assert.rejects( function () { return sasl.continueSession( @@ -103,7 +103,7 @@ suite.test('sasl/scram', function () { ) }) - suite.testAsync('fails when client password is not a string', function () { + suite.test('fails when client password is not a string', function () { for (const badPasswordValue of [null, undefined, 123, new Date(), {}]) { assert.rejects( function () { @@ -123,7 +123,7 @@ suite.test('sasl/scram', function () { } }) - suite.testAsync('fails when client password is an empty string', function () { + suite.test('fails when client password is an empty string', function () { assert.rejects( function () { return sasl.continueSession( @@ -141,7 +141,7 @@ suite.test('sasl/scram', function () { ) }) - suite.testAsync('fails when iteration is missing in server message', function () { + suite.test('fails when iteration is missing in server message', function () { assert.rejects( function () { return sasl.continueSession( @@ -158,7 +158,7 @@ suite.test('sasl/scram', function () { ) }) - suite.testAsync('fails when server nonce does not start with client nonce', function () { + suite.test('fails when server nonce does not start with client nonce', function () { assert.rejects( function () { return sasl.continueSession( @@ -176,7 +176,7 @@ suite.test('sasl/scram', function () { ) }) - suite.testAsync('sets expected session data (SCRAM-SHA-256)', async function () { + suite.test('sets expected session data (SCRAM-SHA-256)', async function () { const session = { message: 'SASLInitialResponse', clientNonce: 'a', @@ -190,7 +190,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 +204,7 @@ 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('sets expected session data (SCRAM-SHA-256-PLUS)', async function () { const session = { message: 'SASLInitialResponse', mechanism: 'SCRAM-SHA-256-PLUS', diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 158f1dbeb..bb6f815a0 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', From f332f283e923d137fa0499d121b79fbaedaf7de1 Mon Sep 17 00:00:00 2001 From: Maxim Bronnikov Date: Wed, 4 Feb 2026 02:45:53 +0300 Subject: [PATCH 03/81] fix: Connection timeout handling for native clients in connected state (#3512) Now, when using the native client with a connection timeout, the pool could incorrectly destroy or end a client that was already connected, due to not distinguishing between connection states. This caused issues such as https://github.com/brianc/node-pg-native/issues/49, where a native client that had already established a connection could be forcefully closed if the connection callback was delayed past the timeout. Co-authored-by: maxbronnikov10 --- packages/pg-pool/index.js | 14 ++++++++++---- packages/pg-pool/test/connection-timeout.js | 21 +++++++++++++++++++++ packages/pg/lib/native/client.js | 7 +++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 3e505f797..f53a85ab1 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -241,10 +241,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) } 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/lib/native/client.js b/packages/pg/lib/native/client.js index 667bf613d..44d5b5c64 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -250,7 +250,10 @@ Client.prototype.end = function (cb) { cb = (err) => (err ? reject(err) : resolve()) }) } + this.native.end(function () { + self._connected = false + self._errorAllQueries(new Error('Connection terminated')) process.nextTick(() => { @@ -306,3 +309,7 @@ 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 +} From 3ea653754f8bfca8c2e6ecd2269dfcec47cf9860 Mon Sep 17 00:00:00 2001 From: Nigro Simone Date: Tue, 10 Feb 2026 20:08:09 +0100 Subject: [PATCH 04/81] chore: upgrade devcontainer at node 22 and add python3 for pg-native (#3595) * chore: upgrade devcontainer at node 22 and add python3 for pg-native * fix(test): in dev container must be use the env --- .devcontainer/Dockerfile | 4 ++-- .devcontainer/docker-compose.yml | 2 +- packages/pg-native/test/index.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) 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..d0ab0e8dd 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -39,7 +39,7 @@ services: - db:db db: - image: postgres:14-alpine + image: postgres:14 restart: unless-stopped ports: - 5432:5432 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) { From d8c5bf65760cc4ebead4614d821cb26c581cff84 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 10 Feb 2026 13:35:16 -0600 Subject: [PATCH 05/81] Update readme. Remove reference to node-pool as it is no longer used (#3599) --- packages/pg-pool/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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', From 0b64e4de5542725cca62af25036140e29f32517a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 11 Feb 2026 17:55:52 -0800 Subject: [PATCH 06/81] docs: Remove `rejectUnauthorized: false` when specifying a CA Fixes #3600 --- docs/pages/features/ssl.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/pages/features/ssl.mdx b/docs/pages/features/ssl.mdx index 2c5e7bd9e..1deecf024 100644 --- a/docs/pages/features/ssl.mdx +++ b/docs/pages/features/ssl.mdx @@ -15,7 +15,6 @@ 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(), @@ -45,7 +44,6 @@ 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(), }, } From a3eeecb95143680b9d57458e5169a1d866d9f89d Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 11 Feb 2026 18:49:41 -0800 Subject: [PATCH 07/81] =?UTF-8?q?docs:=20Remove=20redundant=20Buffer=20?= =?UTF-8?q?=E2=86=92=20string=20conversions=20in=20TLS=20configuration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/pages/features/ssl.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/pages/features/ssl.mdx b/docs/pages/features/ssl.mdx index 1deecf024..9983c0434 100644 --- a/docs/pages/features/ssl.mdx +++ b/docs/pages/features/ssl.mdx @@ -15,9 +15,9 @@ const config = { host: 'host-or-ip', // this object will be passed to the TLSSocket constructor ssl: { - 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'), }, } @@ -44,7 +44,7 @@ const config = { connectionString: 'postgres://user:password@host:port/db?sslmode=require', // Beware! The ssl object is overwritten when parsing the connectionString ssl: { - ca: fs.readFileSync('/path/to/server-certificates/root.crt').toString(), + ca: fs.readFileSync('/path/to/server-certificates/root.crt'), }, } ``` From d80d883944d818234b09f85b3844061ae2d9b906 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 11 Feb 2026 20:26:46 -0800 Subject: [PATCH 08/81] test: Fix TLS connection test ending too early --- packages/pg/test/integration/client/ssl-tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pg/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js index bece48f2f..33919cdf8 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,7 +16,7 @@ suite.test('can connect with ssl', function () { client.query( 'SELECT NOW()', assert.success(function () { - client.end() + client.end(done) }) ) }) From e6e36920075e2c8b2f9ee5d085c7059b80d39fc8 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 12 Feb 2026 14:02:04 -0600 Subject: [PATCH 09/81] Pass connection parameters to password callback (#3602) * Pass connection parameters to password callback * Works on my machine - adding logging for gh actions * More debugging logging in tests * Blank out password in unit test * Try again... * Remove debugging --- packages/pg/Makefile | 1 + packages/pg/lib/client.js | 2 +- .../unit/client/password-callback-tests.js | 70 +++++++++++++++++++ packages/pg/test/unit/client/test-helper.js | 4 +- 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 packages/pg/test/unit/client/password-callback-tests.js diff --git a/packages/pg/Makefile b/packages/pg/Makefile index 5575acfd8..a66c107ae 100644 --- a/packages/pg/Makefile +++ b/packages/pg/Makefile @@ -27,6 +27,7 @@ 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: diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 459439037..0168ce637 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -249,7 +249,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') { 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/test-helper.js b/packages/pg/test/unit/client/test-helper.js index 3e8f75c31..4a3fa9687 100644 --- a/packages/pg/test/unit/client/test-helper.js +++ b/packages/pg/test/unit/client/test-helper.js @@ -3,7 +3,7 @@ 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 () {} @@ -11,7 +11,7 @@ const makeClient = function () { this.queries.push(text) } connection.queries = [] - const client = new Client({ connection: connection }) + const client = new Client({ connection: connection, ...config }) client.connect() client.connection.emit('connect') return client From 01e05567207872d22f486881300c1ebc2eb48727 Mon Sep 17 00:00:00 2001 From: Alec Larson <1925840+aleclarson@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:03:07 -0500 Subject: [PATCH 10/81] fix(pg-query-stream): invoke `this.callback` on cursor end/error (#2810) * fix(pg-query-stream): invoke `this.callback` on cursor end/error Closes #2013 * fix(Client): respect `callback` argument for `Submittable` case * Add tests * Remove log * Fix lint --------- Co-authored-by: Brian Carlson --- packages/pg-query-stream/src/index.ts | 8 ++++++++ packages/pg-query-stream/test/pool.ts | 17 +++++++++++++++++ packages/pg/lib/client.js | 8 ++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 packages/pg-query-stream/test/pool.ts diff --git a/packages/pg-query-stream/src/index.ts b/packages/pg-query-stream/src/index.ts index c942b0441..2a4509e09 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) 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/lib/client.js b/packages/pg/lib/client.js index 0168ce637..02dca96be 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -609,8 +609,12 @@ class Client extends EventEmitter { } else if (typeof config.submit === 'function') { readTimeout = config.query_timeout || this.connectionParameters.query_timeout 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 From a215bfb5bac4b8b12cd69c9a7f5807eb628a8771 Mon Sep 17 00:00:00 2001 From: David Precious Date: Mon, 23 Feb 2026 19:40:42 +0000 Subject: [PATCH 11/81] Typo fix in PgPass deprecation (funciton) (#3605) Simple typo fix. --- packages/pg/lib/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 02dca96be..2de1f48e9 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -25,7 +25,7 @@ const queryQueueDeprecationNotice = nodeUtils.deprecate( 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.' + '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( From 5a4bafc2b06fe4f12e83be723bf783a171d1959b Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 23 Feb 2026 18:48:25 -0600 Subject: [PATCH 12/81] Deprecate Client's internal query queue (#3603) * Deprecate Client's internal query queue * lint * Minor cleanup --- packages/pg-cursor/test/close.js | 4 ++-- packages/pg-pool/test/lifetime-timeout.js | 2 -- packages/pg-protocol/src/buffer-reader.ts | 4 +--- packages/pg/lib/client.js | 18 ++++++++++++------ packages/pg/lib/native/client.js | 12 ++++++++++-- .../client/results-as-array-tests.js | 3 +-- 6 files changed, 26 insertions(+), 17 deletions(-) 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-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-protocol/src/buffer-reader.ts b/packages/pg-protocol/src/buffer-reader.ts index 62b16a2ed..b89aceb89 100644 --- a/packages/pg-protocol/src/buffer-reader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -1,7 +1,5 @@ -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' diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 2de1f48e9..7d1ad8409 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,23 +12,28 @@ 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. ' + + '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 asycn/await or an external async flow control mechanism instead.' ) class Client extends EventEmitter { @@ -684,6 +687,9 @@ class Client extends EventEmitter { return result } + if (this._queryQueue.length > 0) { + queryQueueLengthDeprecationNotice() + } this._queryQueue.push(query) this._pulseQueryQueue() return result diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 44d5b5c64..dae503c80 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 asycn/await or an external async flow control mechanism instead.' +) + const Client = (module.exports = function (config) { EventEmitter.call(this) config = config || {} @@ -230,6 +234,10 @@ Client.prototype.query = function (config, values, callback) { return result } + if (this._queryQueue.length > 0) { + queryQueueLengthDeprecationNotice() + } + this._queryQueue.push(query) this._pulseQueryQueue() return result 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) From ebc14caaa8619ba68ca01d7ce4c8a3a40dcdce51 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Wed, 25 Feb 2026 11:18:44 -0600 Subject: [PATCH 13/81] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1ee4a6c5..c7933ba47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ 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.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`). From f2d7d1146cc87024a5fa503dce13c59ff5196d26 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Wed, 25 Feb 2026 11:18:58 -0600 Subject: [PATCH 14/81] Publish - pg-bundler-test@0.2.0 - pg-cursor@2.18.0 - pg-esm-test@1.5.0 - pg-native@3.6.0 - pg-pool@3.12.0 - pg-protocol@1.12.0 - pg-query-stream@4.13.0 - pg@8.19.0 --- packages/pg-bundler-test/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-esm-test/package.json | 14 +++++++------- packages/pg-native/package.json | 2 +- packages/pg-pool/package.json | 2 +- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 6 +++--- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/pg-bundler-test/package.json b/packages/pg-bundler-test/package.json index 088a81e2a..b81c6a24d 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.2.0", "description": "Test bundlers with pg-cloudflare, https://github.com/brianc/node-postgres/issues/3452", "license": "MIT", "private": true, diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index eee585b71..6283c6039 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.18.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "exports": { @@ -25,7 +25,7 @@ "license": "MIT", "devDependencies": { "mocha": "^10.5.2", - "pg": "^8.18.0" + "pg": "^8.19.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-esm-test/package.json b/packages/pg-esm-test/package.json index 15ff62a1d..38edaff34 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.5.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": "^8.19.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-cursor": "^2.18.0", + "pg-native": "^3.6.0", + "pg-pool": "^3.12.0", + "pg-protocol": "^1.12.0", + "pg-query-stream": "^4.13.0" }, "author": "Brian M. Carlson ", "license": "MIT" diff --git a/packages/pg-native/package.json b/packages/pg-native/package.json index 92bf5cac2..0622a6794 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.6.0", "description": "A slightly nicer interface to Postgres over node-libpq", "main": "index.js", "exports": { diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 29dae6cb9..1663ed1e1 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.12.0", "description": "Connection pool for node-postgres", "main": "index.js", "exports": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index b0772ab50..7f7b801bc 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.12.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7f3399a54..b4447fb52 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.13.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -45,7 +45,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^7.2.1", "mocha": "^10.5.2", - "pg": "^8.18.0", + "pg": "^8.19.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" @@ -54,6 +54,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.17.0" + "pg-cursor": "^2.18.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 57ec82045..5b1d09ccd 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.18.0", + "version": "8.19.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -33,8 +33,8 @@ }, "dependencies": { "pg-connection-string": "^2.11.0", - "pg-pool": "^3.11.0", - "pg-protocol": "^1.11.0", + "pg-pool": "^3.12.0", + "pg-protocol": "^1.12.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, From ec90a3c3630f31aec16282fc9b279d3b8d4918a0 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 25 Feb 2026 17:56:17 +0000 Subject: [PATCH 15/81] docs: `keepAlive` and `keepAliveInitialDelayMillis` (#3609) Co-authored-by: Corey Van Woert --- docs/pages/apis/client.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index f68542672..5867ad5a6 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -23,7 +23,9 @@ 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 From d90db86ed9eedb66ef69d71ea99dd9e9f0a3cf7c Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 25 Feb 2026 12:22:19 -0600 Subject: [PATCH 16/81] Fix mocha in node 25 (#3610) * Fix mocha in node 25 * Bump more mochas --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 2 +- packages/pg-native/package.json | 2 +- packages/pg-pool/package.json | 2 +- packages/pg-protocol/package.json | 4 +- packages/pg-query-stream/package.json | 4 +- yarn.lock | 356 +++++++++------------ 7 files changed, 157 insertions(+), 215 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index f48cf92aa..ad4e68396 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -38,7 +38,7 @@ "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" diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 6283c6039..e9f4e5aa7 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -24,7 +24,7 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "mocha": "^10.5.2", + "mocha": "^11.7.5", "pg": "^8.19.0" }, "peerDependencies": { diff --git a/packages/pg-native/package.json b/packages/pg-native/package.json index 0622a6794..33ee9d50f 100644 --- a/packages/pg-native/package.json +++ b/packages/pg-native/package.json @@ -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-pool/package.json b/packages/pg-pool/package.json index 1663ed1e1..dd19bfef8 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -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-protocol/package.json b/packages/pg-protocol/package.json index 7f7b801bc..6f60a1ecb 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -16,11 +16,11 @@ "license": "MIT", "devDependencies": { "@types/chai": "^4.2.7", - "@types/mocha": "^10.0.7", + "@types/mocha": "^10.0.10", "@types/node": "^12.12.21", "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" }, diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index b4447fb52..b645dc70e 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -38,13 +38,13 @@ }, "devDependencies": { "@types/chai": "^4.2.13", - "@types/mocha": "^10.0.7", + "@types/mocha": "^10.0.10", "@types/node": "^14.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", + "mocha": "^11.7.5", "pg": "^8.19.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", diff --git a/yarn.lock b/yarn.lock index 8628e175d..195869341 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2043,10 +2043,10 @@ 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" @@ -2570,11 +2570,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 +2624,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" @@ -2827,6 +2814,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 +2849,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 +2894,13 @@ 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" + braces@^2.3.1: version "2.3.2" resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" @@ -2923,14 +2917,14 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.2, 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== @@ -3188,20 +3182,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" @@ -3278,13 +3264,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: @@ -3665,7 +3651,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 +3679,13 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.4.0: dependencies: ms "^2.1.3" +debug@^4.3.5: + 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 +3827,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" @@ -4152,16 +4145,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" @@ -4590,14 +4583,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,6 +4613,14 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.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" + flat-cache@^3.0.4: version "3.2.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" @@ -4924,7 +4917,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, glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -4948,17 +4941,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 +4952,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" @@ -5149,7 +5143,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== @@ -5410,13 +5404,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 +5516,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== @@ -5803,7 +5790,7 @@ 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== @@ -6118,7 +6105,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== @@ -6442,13 +6429,6 @@ miniflare@4.20250428.0: 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== - dependencies: - brace-expansion "^2.0.1" - minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -6456,13 +6436,6 @@ minimatch@9.0.3: 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== - dependencies: - brace-expansion "^2.0.1" - minimatch@^9.0.4: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" @@ -6470,6 +6443,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 +6588,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 +6642,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== @@ -6840,11 +6821,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 +7204,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" @@ -7444,7 +7425,7 @@ 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: +picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -7827,12 +7808,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" @@ -8170,13 +8149,6 @@ semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3, semver@^7.7.1, semve 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" - serialize-javascript@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" @@ -8594,7 +8566,7 @@ stream-spec@~0.3.5: dependencies: macgyver "~1.10" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm: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== @@ -8629,15 +8601,6 @@ 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: - 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== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -8677,7 +8640,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -8705,13 +8668,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -8760,7 +8716,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 +8730,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,6 +8751,13 @@ 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" @@ -9605,10 +9561,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" @@ -9646,7 +9602,7 @@ wrangler@^3.x: fsevents "~2.3.2" sharp "^0.33.5" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9673,15 +9629,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -9782,11 +9729,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 +9745,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 +9760,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 +9794,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" From f0f01ec5825c188365ea41dd63470f7df4b1d2ad Mon Sep 17 00:00:00 2001 From: Mason McAllaster Date: Wed, 25 Feb 2026 15:26:41 -0500 Subject: [PATCH 17/81] docs: upgrade to nextra v3 (#3549) * docs: upgrade to nextra v3 * fix: top-level docs:start script Additionally, remove non-working `start` command from docs `package.json`, as it was replaced by `dev` for consistency with the `README.md` in that directory. --- docs/components/alert.tsx | 2 +- docs/components/info.tsx | 2 +- docs/next.config.js | 11 +- docs/package.json | 15 +- docs/pages/_meta.js | 5 + docs/pages/_meta.json | 5 - docs/pages/apis/_meta.js | 8 + docs/pages/apis/_meta.json | 8 - docs/pages/features/_meta.js | 11 + docs/pages/features/_meta.json | 11 - docs/pages/guides/_meta.js | 6 + docs/pages/guides/_meta.json | 6 - docs/yarn.lock | 4357 ++++++++++++++++++++++---------- package.json | 2 +- 14 files changed, 3063 insertions(+), 1386 deletions(-) create mode 100644 docs/pages/_meta.js delete mode 100644 docs/pages/_meta.json create mode 100644 docs/pages/apis/_meta.js delete mode 100644 docs/pages/apis/_meta.json create mode 100644 docs/pages/features/_meta.js delete mode 100644 docs/pages/features/_meta.json create mode 100644 docs/pages/guides/_meta.js delete mode 100644 docs/pages/guides/_meta.json 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..19aae02fa 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,18 +3,19 @@ "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" } } 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/features/_meta.js b/docs/pages/features/_meta.js new file mode 100644 index 000000000..62f1660ca --- /dev/null +++ b/docs/pages/features/_meta.js @@ -0,0 +1,11 @@ +export default { + 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/_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/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/yarn.lock b/docs/yarn.lock index aa2c18408..ee0cdd142 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,125 @@ 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" + +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 +3419,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 +3436,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/package.json b/package.json index 77a1fcc44..1f40662b9 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "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}'" From 9e8274ffa895e44dcdd0bb80129c1ffbad054eb6 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 25 Feb 2026 14:38:16 -0600 Subject: [PATCH 18/81] Add explicit dependency to typescript for docs (#3611) --- docs/package.json | 3 ++- docs/yarn.lock | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index 19aae02fa..a3bdb4f9f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -16,6 +16,7 @@ "nextra": "^3.3.1", "nextra-theme-docs": "^3.3.1", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "typescript": "^5.0.2" } } diff --git a/docs/yarn.lock b/docs/yarn.lock index ee0cdd142..f65b39f82 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -3318,6 +3318,11 @@ twoslash@^0.2.12: "@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" From cb2fce58cce443c7dddd308381377689c94c8b36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 00:45:26 -0600 Subject: [PATCH 19/81] build(deps-dev): bump semver from 7.7.2 to 7.7.4 (#3614) Bumps [semver](https://github.com/npm/node-semver) from 7.7.2 to 7.7.4. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v7.7.2...v7.7.4) --- updated-dependencies: - dependency-name: semver dependency-version: 7.7.4 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 195869341..dd6662852 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8145,9 +8145,9 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: 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== + 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" @@ -8566,7 +8566,7 @@ stream-spec@~0.3.5: dependencies: macgyver "~1.10" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": 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== @@ -8601,6 +8601,15 @@ 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.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== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -8640,7 +8649,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -8668,6 +8677,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -9602,7 +9618,7 @@ wrangler@^3.x: fsevents "~2.3.2" sharp "^0.33.5" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9629,6 +9645,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From ad36e3c9e80fae771d636328420cebe7d544baae Mon Sep 17 00:00:00 2001 From: Bobbie Goede Date: Mon, 2 Mar 2026 22:18:13 +0100 Subject: [PATCH 20/81] fix: typo in deprecation notice for `client.query()` (#3618) * fix: typo in deprecation notice for client.query() * fix: typo in deprecation notice for client.query() --- packages/pg/lib/client.js | 2 +- packages/pg/lib/native/client.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 7d1ad8409..9200dded6 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -33,7 +33,7 @@ const byoPromiseDeprecationNotice = nodeUtils.deprecate( 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 asycn/await or an external async flow control mechanism instead.' + '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.' ) class Client extends EventEmitter { diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index dae503c80..d8bb4dce5 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -17,7 +17,7 @@ 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 asycn/await or an external async flow control mechanism instead.' + '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) { From 0c7040e3fc011125d02e5539d1aabc5e2d57e541 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 4 Mar 2026 17:45:19 -0600 Subject: [PATCH 21/81] Add `onConnect` callback which allows "setup" of a pooled client (#3620) * wip * Initial connect lifecycle working * Connect hook working * Rename 'hooks.bla' to 'onBla' * Add more tests * More cleanup testing * Use promise.try --- packages/pg-pool/index.js | 64 ++++++--- packages/pg-pool/test/lifecycle-hooks.js | 164 +++++++++++++++++++++++ packages/pg-pool/test/timeout.js | 0 3 files changed, 211 insertions(+), 17 deletions(-) create mode 100644 packages/pg-pool/test/lifecycle-hooks.js delete mode 100644 packages/pg-pool/test/timeout.js diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index f53a85ab1..2fbdb78d5 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 } @@ -277,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) { 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/timeout.js b/packages/pg-pool/test/timeout.js deleted file mode 100644 index e69de29bb..000000000 From 1c8c7107a0e31309a2cc58edb00ec05bca7c3fd7 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Wed, 4 Mar 2026 17:47:34 -0600 Subject: [PATCH 22/81] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7933ba47..36a7136c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ 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.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). From c9070cc8d526fca65780cedc25c1966b57cf7532 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Wed, 4 Mar 2026 17:47:51 -0600 Subject: [PATCH 23/81] Publish - pg-connection-string@2.12.0 - pg-cursor@2.19.0 - pg-esm-test@1.6.0 - pg-native@3.7.0 - pg-pool@3.13.0 - pg-protocol@1.13.0 - pg-query-stream@4.14.0 - pg@8.20.0 --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-esm-test/package.json | 14 +++++++------- packages/pg-native/package.json | 2 +- packages/pg-pool/package.json | 2 +- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 8 ++++---- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index ad4e68396..a60131456 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.11.0", + "version": "2.12.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index e9f4e5aa7..332e51a2f 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.18.0", + "version": "2.19.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "exports": { @@ -25,7 +25,7 @@ "license": "MIT", "devDependencies": { "mocha": "^11.7.5", - "pg": "^8.19.0" + "pg": "^8.20.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-esm-test/package.json b/packages/pg-esm-test/package.json index 38edaff34..0f15f7ff2 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.5.0", + "version": "1.6.0", "description": "A test module for PostgreSQL with ESM support", "main": "index.js", "type": "module", @@ -14,13 +14,13 @@ "test" ], "devDependencies": { - "pg": "^8.19.0", + "pg": "^8.20.0", "pg-cloudflare": "^1.3.0", - "pg-cursor": "^2.18.0", - "pg-native": "^3.6.0", - "pg-pool": "^3.12.0", - "pg-protocol": "^1.12.0", - "pg-query-stream": "^4.13.0" + "pg-cursor": "^2.19.0", + "pg-native": "^3.7.0", + "pg-pool": "^3.13.0", + "pg-protocol": "^1.13.0", + "pg-query-stream": "^4.14.0" }, "author": "Brian M. Carlson ", "license": "MIT" diff --git a/packages/pg-native/package.json b/packages/pg-native/package.json index 33ee9d50f..4c8148ac1 100644 --- a/packages/pg-native/package.json +++ b/packages/pg-native/package.json @@ -1,6 +1,6 @@ { "name": "pg-native", - "version": "3.6.0", + "version": "3.7.0", "description": "A slightly nicer interface to Postgres over node-libpq", "main": "index.js", "exports": { diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index dd19bfef8..7ac434f97 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.12.0", + "version": "3.13.0", "description": "Connection pool for node-postgres", "main": "index.js", "exports": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 6f60a1ecb..896c21e69 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.12.0", + "version": "1.13.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index b645dc70e..5369a3c4c 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.13.0", + "version": "4.14.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -45,7 +45,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^7.2.1", "mocha": "^11.7.5", - "pg": "^8.19.0", + "pg": "^8.20.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" @@ -54,6 +54,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.18.0" + "pg-cursor": "^2.19.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 5b1d09ccd..6be526ee8 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.19.0", + "version": "8.20.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.12.0", - "pg-protocol": "^1.12.0", + "pg-connection-string": "^2.12.0", + "pg-pool": "^3.13.0", + "pg-protocol": "^1.13.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, From c6028a875f953eff9e8e403622b0aac127d1b4a6 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 4 Mar 2026 18:49:05 -0600 Subject: [PATCH 24/81] Docs updates (#3622) * Add docs for * Add docs for max uses * Clean up casing and grammar in comments * Add more docs on pool sizing * Grammar * Add better footer * Final updates --- docs/pages/apis/pool.mdx | 59 +++++++++++++++++++++++--------- docs/pages/features/queries.mdx | 6 ++-- docs/pages/guides/pool-sizing.md | 12 +++++++ docs/theme.config.js | 30 +++++++++++++++- 4 files changed, 86 insertions(+), 21 deletions(-) diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx index fbe0279e1..d9323979e 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,28 @@ 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 } ``` @@ -70,7 +83,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') + }, }) ``` 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/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/theme.config.js b/docs/theme.config.js index 29f115cb0..03ba3665c 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: ( + + As of 2026-03-01 I am taking a break from the workforce to focus entirely on this project! Please consider{' '} + + sponsoring this work 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: ( <> From 412dc88bc962e8792c292943e2f722333415b031 Mon Sep 17 00:00:00 2001 From: Daniel Diekmeier Date: Fri, 6 Mar 2026 00:00:57 +0100 Subject: [PATCH 25/81] Don't encourage people to use on('connect') for setup anymore (#3623) --- docs/pages/apis/pool.mdx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx index d9323979e..123bc8ba4 100644 --- a/docs/pages/apis/pool.mdx +++ b/docs/pages/apis/pool.mdx @@ -232,14 +232,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 From 32ec730b51a1fd73bf97d65105c949729fa9ec80 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 5 Mar 2026 18:26:08 -0600 Subject: [PATCH 26/81] Update readme text slightly (#3637) * Update readme text slightly * Better words --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a680ff7b3..fc052cccf 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,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: @@ -87,11 +87,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 From e7fa94a0f7820bc40949625aea5b8d2b788fe55a Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 6 Mar 2026 01:14:21 -0600 Subject: [PATCH 27/81] Update the sub-readme (#3638) --- packages/pg/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/README.md b/packages/pg/README.md index bf4effefb..75242374c 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -42,7 +42,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: From c78b302666d593007359eb2bd223c5b325a07058 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 6 Mar 2026 19:07:16 -0600 Subject: [PATCH 28/81] Cleanup tests (#3640) --- packages/pg-cloudflare/src/index.ts | 2 +- packages/pg/Makefile | 12 +- packages/pg/script/create-test-tables.js | 56 ----- packages/pg/test/cli.js | 25 -- packages/pg/test/cloudflare/vitest-cf.test.ts | 3 +- .../client/big-simple-query-tests.js | 126 ++++++----- .../client/prepared-statement-tests.js | 214 +++++++++++------- .../integration/client/simple-query-tests.js | 77 ++++--- .../integration/client/transaction-tests.js | 79 +++---- .../connection-pool/native-instance-tests.js | 1 + .../test/integration/gh-issues/3174-tests.js | 2 +- packages/pg/test/integration/test-helper.js | 2 +- packages/pg/test/native/callback-api-tests.js | 39 ++-- packages/pg/test/native/stress-tests.js | 24 +- packages/pg/test/test-helper.js | 62 ++++- 15 files changed, 363 insertions(+), 361 deletions(-) delete mode 100644 packages/pg/script/create-test-tables.js delete mode 100644 packages/pg/test/cli.js diff --git a/packages/pg-cloudflare/src/index.ts b/packages/pg-cloudflare/src/index.ts index d83882efe..1e55c4165 100644 --- a/packages/pg-cloudflare/src/index.ts +++ b/packages/pg-cloudflare/src/index.ts @@ -1,4 +1,4 @@ -import { SocketOptions, Socket, TlsOptions } from 'cloudflare:sockets' +import { SocketOptions, Socket, TlsOptions } from 'cloudflare:sockets' // eslint-disable-line import { EventEmitter } from 'events' /** diff --git a/packages/pg/Makefile b/packages/pg/Makefile index a66c107ae..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: @@ -30,11 +30,7 @@ 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***" @@ -43,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/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/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/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js index 5ff72a89e..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() 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/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/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/gh-issues/3174-tests.js b/packages/pg/test/integration/gh-issues/3174-tests.js index 24347a23e..99044df0e 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() diff --git a/packages/pg/test/integration/test-helper.js b/packages/pg/test/integration/test-helper.js index 631acbae3..9dab8843a 100644 --- a/packages/pg/test/integration/test-helper.js +++ b/packages/pg/test/integration/test-helper.js @@ -6,7 +6,7 @@ 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 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/test-helper.js b/packages/pg/test/test-helper.js index da70973f6..8cd9dda36 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) @@ -53,8 +60,7 @@ 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('') @@ -199,14 +205,58 @@ 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, } From 4e6bdf07eff793ba1753aea28e81c818f6adb362 Mon Sep 17 00:00:00 2001 From: Karl Pietrzak Date: Wed, 22 Apr 2026 16:31:53 -0400 Subject: [PATCH 29/81] Update Medplum logo in README (#3659) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fc052cccf..4ca28ce5d 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,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 From 77cb77150d6c0f07b0aa2134c6b3ef0cb80335c1 Mon Sep 17 00:00:00 2001 From: Karl Pietrzak Date: Wed, 22 Apr 2026 17:11:39 -0400 Subject: [PATCH 30/81] remove deprecated 'version' attribute from docker-compose.ymla (#3660) Removes the warning: ``` WARN[0000] .../node-postgres/.devcontainer/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion ``` The `version` attribute has been removed as of v2 of the docker compose plugin (https://github.com/compose-spec/compose-spec/blob/main/spec.md#version-top-level-element-obsolete). --- .devcontainer/docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index d0ab0e8dd..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 From 341cb60b0f4579382c7f65be97815c3fe4621064 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 30 Apr 2026 10:31:26 +0000 Subject: [PATCH 31/81] =?UTF-8?q?docs:=20Fix=20changelog=20entry=E2=80=99s?= =?UTF-8?q?=20spelling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36a7136c0..8d167ceef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,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 From 02367b8325d6f378419242b07ec3b206309e049f Mon Sep 17 00:00:00 2001 From: Chow Loong Jin Date: Sat, 9 May 2026 22:29:50 +0800 Subject: [PATCH 32/81] Upgrade eslint and typescript (#3662) * Upgrade eslint and typescript * eslint: Port config to new flat config format * Fix preserve-caught-error eslint warning * Drop unused eslint-disable-line * pg-cloudflare: Fix typescript errors - rootDir defaults have changed, so we need to specify it manually now - baseUrl is no longer supported - types no longer loads everything in @types by default, so we have to specify that we want node types - Pin @types/node to 16.* because we support node16 and above * pg-cloudflare: Workaround typescript bug regarding Buffer.from Fixes the following error: % yarn build yarn run v1.22.19 $ tsc --build packages/pg-cloudflare/src/index.ts:156:29 - error TS2769: No overload matches this call. The last overload gave the following error. Argument of type 'ArrayBuffer | Uint8Array' is not assignable to parameter of type 'WithImplicitCoercion | { [Symbol.toPrimitive](hint: "string"): string; }'. Type 'ArrayBuffer' is not assignable to type 'WithImplicitCoercion | { [Symbol.toPrimitive](hint: "string"): string; }'. 156 const hex = Buffer.from(data).toString('hex') ~~~~ node_modules/@types/node/buffer.buffer.d.ts:83:13 83 from( ~~~~~ 84 str: ~~~~~~~~~~~~~~~~~~~~ ... 89 encoding?: BufferEncoding, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 90 ): Buffer; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The last overload is declared here. Found 1 error. See https://github.com/microsoft/TypeScript/issues/63447 for more info * Fix tsconfig for pg-protocol and pg-query-stream * Standardize @types/node on ^16 Fixes the following typescript error: node_modules/typescript/lib/lib.esnext.intl.d.ts:26:135 - error TS2552: Cannot find name 'DateTimeRangeFormatPart'. Did you mean 'DateTimeFormatPart'? 26 formatRangeToParts(startDate: FormattableTemporalObject | Date | number, endDate: FormattableTemporalObject | Date | number): DateTimeRangeFormatPart[]; * pg-protocol: Narrow type of BufferReader.encoding `BufferReader.encoding` to `BufferEncoding` from `string` to match the new signature of `Buffer.toString`. * pg-query-stream: Bump eslint-plugin-promise to fix unmet peer dependency * Run eslint on its own config --- .eslintignore | 1 - .eslintrc | 35 - eslint.config.mjs | 76 ++ package.json | 11 +- packages/pg-cloudflare/package.json | 2 +- packages/pg-cloudflare/src/index.ts | 7 +- packages/pg-cloudflare/tsconfig.json | 9 +- packages/pg-connection-string/package.json | 2 +- packages/pg-protocol/package.json | 4 +- packages/pg-protocol/src/buffer-reader.ts | 2 +- packages/pg-protocol/tsconfig.json | 12 +- packages/pg-query-stream/package.json | 6 +- packages/pg-query-stream/tsconfig.json | 2 +- packages/pg/package.json | 2 +- .../client/async-stack-trace-tests.js | 4 +- yarn.lock | 787 ++++++++---------- 16 files changed, 446 insertions(+), 516 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc create mode 100644 eslint.config.mjs 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/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..3f95083a0 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,76 @@ +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', + }, + }, +]) diff --git a/package.json b/package.json index 1f40662b9..9285ad142 100644 --- a/package.json +++ b/package.json @@ -20,15 +20,18 @@ "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", + "@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", + "@types/node": "^16" }, "prettier": { "semi": false, diff --git a/packages/pg-cloudflare/package.json b/packages/pg-cloudflare/package.json index c1584fc09..ac68bb22e 100644 --- a/packages/pg-cloudflare/package.json +++ b/packages/pg-cloudflare/package.json @@ -7,7 +7,7 @@ "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 1e55c4165..9b1e517ba 100644 --- a/packages/pg-cloudflare/src/index.ts +++ b/packages/pg-cloudflare/src/index.ts @@ -1,4 +1,4 @@ -import { SocketOptions, Socket, TlsOptions } from 'cloudflare:sockets' // eslint-disable-line +import { SocketOptions, Socket, TlsOptions } from 'cloudflare:sockets' import { EventEmitter } from 'events' /** @@ -153,7 +153,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/package.json b/packages/pg-connection-string/package.json index a60131456..d02588a6c 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -41,7 +41,7 @@ "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-protocol/package.json b/packages/pg-protocol/package.json index 896c21e69..d3326bdbc 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -17,12 +17,12 @@ "devDependencies": { "@types/chai": "^4.2.7", "@types/mocha": "^10.0.10", - "@types/node": "^12.12.21", + "@types/node": "^16", "chai": "^4.2.0", "chunky": "^0.0.0", "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 b89aceb89..c9d9c2b66 100644 --- a/packages/pg-protocol/src/buffer-reader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -2,7 +2,7 @@ export class BufferReader { 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) {} diff --git a/packages/pg-protocol/tsconfig.json b/packages/pg-protocol/tsconfig.json index 0ae32c8dc..e09c03cd7 100644 --- a/packages/pg-protocol/tsconfig.json +++ b/packages/pg-protocol/tsconfig.json @@ -9,15 +9,19 @@ "moduleResolution": "node16", "sourceMap": true, "outDir": "dist", + "rootDir": "./src", "incremental": true, - "baseUrl": ".", "declaration": true, "paths": { "*": [ - "node_modules/*", - "src/types/*" + "./node_modules/*", + "./src/types/*" ] - } + }, + "types": [ + "node", + "mocha" + ] }, "include": [ "src/**/*" diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 5369a3c4c..42ef8f268 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -39,16 +39,16 @@ "devDependencies": { "@types/chai": "^4.2.13", "@types/mocha": "^10.0.10", - "@types/node": "^14.0.0", + "@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", + "eslint-plugin-promise": "^7.3.0", "mocha": "^11.7.5", "pg": "^8.20.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", - "typescript": "^4.0.3" + "typescript": "^6.0.3" }, "peerDependencies": { "pg": "^8" 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/package.json b/packages/pg/package.json index 6be526ee8..d14e448d6 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -45,7 +45,7 @@ "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" }, 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 92ca3e4d2..8f289f5ad 100644 --- a/packages/pg/test/integration/client/async-stack-trace-tests.js +++ b/packages/pg/test/integration/client/async-stack-trace-tests.js @@ -23,7 +23,7 @@ if (NODE_MAJOR_VERSION >= 16) { } 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) + throw Error('async stack trace does not contain wanted values: ' + stack, { cause: e }) } } }) @@ -44,7 +44,7 @@ if (NODE_MAJOR_VERSION >= 16) { } 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) + throw Error('async stack trace does not contain wanted values: ' + stack, { cause: e }) } } }) diff --git a/yarn.lock b/yarn.lock index dd6662852..b221bd37a 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: + "@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: - ajv "^6.12.4" + "@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" @@ -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== @@ -2053,15 +2087,10 @@ 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== + 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@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== +"@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" "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" + "@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/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/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" - "@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" - -"@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== - 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" @@ -2708,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" @@ -2901,6 +2900,13 @@ brace-expansion@^5.0.2: 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" @@ -2917,13 +2923,6 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -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: version "1.3.1" resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" @@ -3059,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: @@ -3151,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" @@ -3590,7 +3581,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== @@ -3599,7 +3590,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== @@ -3679,7 +3670,7 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.4.0: dependencies: ms "^2.1.3" -debug@^4.3.5: +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== @@ -3844,20 +3835,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" @@ -4200,10 +4177,10 @@ eslint-plugin-prettier@^5.1.2: prettier-linter-helpers "^1.0.0" synckit "^0.11.7" -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" @@ -4215,11 +4192,13 @@ 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" @@ -4235,63 +4214,74 @@ eslint-visitor-keys@^1.1.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" @@ -4303,10 +4293,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" @@ -4490,17 +4480,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" @@ -4521,13 +4500,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" @@ -4545,12 +4517,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" @@ -4567,13 +4539,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" @@ -4621,14 +4586,13 @@ find-up@^5.0.0: locate-path "^6.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== +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" @@ -4917,7 +4881,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.0.0: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -4992,24 +4956,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" @@ -5030,11 +4980,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" @@ -5247,11 +5192,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.1.1, 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" @@ -5261,9 +5211,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" @@ -5540,11 +5490,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" @@ -5797,6 +5742,13 @@ js-yaml@^4.1.0: 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" @@ -5879,7 +5831,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== @@ -6060,11 +6012,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" @@ -6317,7 +6264,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== @@ -6341,14 +6288,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" @@ -6422,19 +6361,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@9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== +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@^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 "^1.1.7" minimatch@^9.0.4: version "9.0.4" @@ -7220,7 +7166,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" @@ -7349,11 +7295,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" @@ -7425,11 +7366,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.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" @@ -8005,11 +7941,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" @@ -8017,7 +7948,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== @@ -8083,11 +8014,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" @@ -8144,7 +8070,7 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0, semver@^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: +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== @@ -8258,11 +8184,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" @@ -8566,7 +8487,7 @@ stream-spec@~0.3.5: dependencies: macgyver "~1.10" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm: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== @@ -8601,15 +8522,6 @@ 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.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== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -8649,7 +8561,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -8677,13 +8589,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -8868,11 +8773,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" @@ -8963,13 +8863,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" @@ -9025,10 +8918,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" @@ -9097,11 +8990,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" @@ -9129,10 +9017,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" @@ -9618,7 +9506,7 @@ wrangler@^3.x: fsevents "~2.3.2" sharp "^0.33.5" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9645,15 +9533,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 1025d12b24f277f9b7cdba2d5488103745939d6b Mon Sep 17 00:00:00 2001 From: francesco Date: Mon, 11 May 2026 18:39:54 +0200 Subject: [PATCH 33/81] Node JS 26 (#3667) * chore: update libpq to 1.11.0 * chore: add node 26 --- .github/workflows/ci.yml | 2 +- packages/pg-native/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d90e474c..1aae36233 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: - '20' - '22' - '24' - - '25' + - '26' os: - ubuntu-latest name: Node.js ${{ matrix.node }} diff --git a/packages/pg-native/package.json b/packages/pg-native/package.json index 4c8148ac1..b75b2ffdb 100644 --- a/packages/pg-native/package.json +++ b/packages/pg-native/package.json @@ -34,7 +34,7 @@ }, "homepage": "https://github.com/brianc/node-postgres/tree/master/packages/pg-native", "dependencies": { - "libpq": "^1.8.15", + "libpq": "^1.11.0", "pg-types": "2.2.0" }, "devDependencies": { From 7674d8c27fe8c10f981f4db22c89d1ae566c9380 Mon Sep 17 00:00:00 2001 From: "Herman J. Radtke III" Date: Mon, 11 May 2026 15:20:28 -0400 Subject: [PATCH 34/81] Fix pg prototype pollution via server supplied column names (#3656) * fix(pg-connection-string): prototype pollution via query strings * fix(pg): prototype pollution via server-supplied column names Fixes #3654 --- packages/pg-connection-string/index.js | 6 +- .../pg-connection-string/test/clientConfig.ts | 14 +-- packages/pg-connection-string/test/parse.ts | 34 ++++++ packages/pg/lib/result.js | 2 +- packages/pg/test/unit/result-tests.js | 111 ++++++++++++++++++ 5 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 packages/pg/test/unit/result-tests.js diff --git a/packages/pg-connection-string/index.js b/packages/pg-connection-string/index.js index 29ffeafd7..4b8d7afb9 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)) { @@ -164,7 +164,7 @@ function toConnectionOptions(sslConfig) { } return c - }, {}) + }, Object.create(null)) return connectionOptions } @@ -200,7 +200,7 @@ function toClientConfig(config) { } return c - }, {}) + }, Object.create(null)) return poolConfig } 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..814e49c58 100644 --- a/packages/pg-connection-string/test/parse.ts +++ b/packages/pg-connection-string/test/parse.ts @@ -467,4 +467,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/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/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) +}) From effc3f6c2e785f8295a14c53a0c6848c8a66910c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 14:40:03 -0500 Subject: [PATCH 35/81] build(deps-dev): bump eslint-plugin-prettier from 5.5.1 to 5.5.5 (#3648) Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.5.1 to 5.5.5. - [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases) - [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.5.1...v5.5.5) --- updated-dependencies: - dependency-name: eslint-plugin-prettier dependency-version: 5.5.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/yarn.lock b/yarn.lock index b221bd37a..3379c62b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1870,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" @@ -4170,12 +4170,12 @@ eslint-plugin-node@^11.1.0: 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.3.0: version "7.3.0" @@ -7485,10 +7485,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" @@ -8684,12 +8684,12 @@ supports-preserve-symlinks-flag@^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" From 939725e02c392a6f863cd57970aa3202fb500912 Mon Sep 17 00:00:00 2001 From: Leonardo Zanivan Date: Mon, 11 May 2026 16:55:10 -0300 Subject: [PATCH 36/81] feat: add new client.getTransactionStatus() method (#3645) * feat: add new client.getTransactionStatus() method Adds a new public method to retrieve the current transaction status of the client connection. Returns 'I' (idle), 'T' (in transaction), 'E' (error/aborted), or null (initial state/native client). The transaction status is tracked from PostgreSQL's ReadyForQuery message after each query completes. Native client returns null as it does not support this feature yet. * feat: add native client support for getTransactionStatus() - Add getTransactionStatus() to pg-native using libpq's PQtransactionStatus() with status mapping (0->I, 2->T, 3->E) - Update pg native client wrapper to delegate to pg-native - Remove native guard from txstatus tests (now runs in both modes) - Bump libpq to ^1.10.0 for transactionStatus() binding support * docs * Tests * fix: docs * clear docs --------- Co-authored-by: Brian C --- docs/pages/apis/client.mdx | 55 +++++++++++++ packages/pg-native/index.js | 8 ++ packages/pg/lib/client.js | 6 ++ packages/pg/lib/native/client.js | 4 + .../test/integration/client/txstatus-tests.js | 82 +++++++++++++++++++ yarn.lock | 15 ++-- 6 files changed, 165 insertions(+), 5 deletions(-) create mode 100644 packages/pg/test/integration/client/txstatus-tests.js diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index 5867ad5a6..ecfd67fca 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -175,6 +175,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/packages/pg-native/index.js b/packages/pg-native/index.js index 8c83406bb..1c18241db 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 diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 9200dded6..48d3a595b 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -71,6 +71,7 @@ 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.connection = @@ -359,6 +360,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) @@ -703,6 +705,10 @@ class Client extends EventEmitter { this.connection.unref() } + getTransactionStatus() { + return this._txStatus + } + end(cb) { this._ending = true diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index d8bb4dce5..6df471b83 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -321,3 +321,7 @@ Client.prototype.getTypeParser = function (oid, format) { Client.prototype.isConnected = function () { return this._connected } + +Client.prototype.getTransactionStatus = function () { + return this.native.getTransactionStatus() +} 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/yarn.lock b/yarn.lock index 3379c62b4..6e45ace78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5907,13 +5907,13 @@ levn@~0.3.0: prelude-ls "~1.1.2" 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== +libpq@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/libpq/-/libpq-1.10.0.tgz#238d01d416abca8768aab09bc82d81af9c7ffa23" + integrity sha512-PHY+JGD3+9X5b2emXLh+WJEnz1jhczO1xs25ZH0xbMWvQi+Hd9X/mTZOrGA99Rcw/DvNjsBRlegroqigpNfaJA== dependencies: bindings "1.5.0" - nan "~2.22.2" + nan "~2.23.1" lines-and-columns@^1.1.6: version "1.1.6" @@ -6632,6 +6632,11 @@ nan@~2.22.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.2.tgz#6b504fd029fb8f38c0990e52ad5c26772fdacfbb" integrity sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ== +nan@~2.23.1: + version "2.23.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.23.1.tgz#6f86a31dd87e3d1eb77512bf4b9e14c8aded3975" + integrity sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw== + nanoid@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" From 7ba4efe25d40359c0fb2dec0cd674a3abc5d1026 Mon Sep 17 00:00:00 2001 From: felipe stival <14948182+v0idpwn@users.noreply.github.com> Date: Mon, 11 May 2026 17:42:35 -0300 Subject: [PATCH 37/81] Handle SASL SCRAM server error responses (#3521) Add proper error handling for SCRAM-SERVER-FINAL-MESSAGE error attribute. The SCRAM specification allows servers to return error messages via the 'e' attribute in the server final message. Currently, these errors are ignored and authentication fails later during signature verification. Postgres typically doesn't return this error (see [here](https://github.com/postgres/postgres/blob/2047ad068139f0b8c6da73d0b845ca9ba30fb33d/src/backend/libpq/auth-scram.c#L423) on why), but poolers, or other applications using the postgres protocol might, and it's part of the SCRAM spec, so it probably makes sense for node-postgres to handle it. Aligns behaviour with psql, postgrex, and somewhat with pgJDBC (pgJDBC in particular is stricter with scram errors). For reference: - libpq handling it: https://github.com/postgres/postgres/blob/2047ad068139f0b8c6da73d0b845ca9ba30fb33d/src/interfaces/libpq/fe-auth-scram.c#L708 --- packages/pg/lib/crypto/sasl.js | 6 ++++++ .../pg/test/unit/client/sasl-scram-tests.js | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/pg/lib/crypto/sasl.js b/packages/pg/lib/crypto/sasl.js index 47b77610c..a782ae48a 100644 --- a/packages/pg/lib/crypto/sasl.js +++ b/packages/pg/lib/crypto/sasl.js @@ -178,7 +178,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)) { diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index 2df0f1860..7554a9814 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -284,6 +284,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 () { From 3bb9fbaa5f1b25078cd4ba12d501d4bb05677d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sebastian=20kr=C3=A4mer?= Date: Mon, 11 May 2026 22:43:46 +0200 Subject: [PATCH 38/81] Add error handling for non-function callback (#3561) * Add error handling for non-function callback catch callback not a function earlier to get a proper callstack. later when executing the callback the stack may be wrong/insufficient. * fix: lint * fix: lint * fix: test * feat: add test for new error --- packages/pg-pool/index.js | 2 +- packages/pg/lib/client.js | 4 ++++ packages/pg/test/unit/client/simple-query-tests.js | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 2fbdb78d5..ab514fa88 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -438,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/lib/client.js b/packages/pg/lib/client.js index 48d3a595b..33a8e24f0 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -633,6 +633,10 @@ class Client extends EventEmitter { Error.captureStackTrace(err) throw err }) + } else { + if (!(typeof query.callback === 'function')) { + throw new Error('callback is not a 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..6c20c576b 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -140,5 +140,17 @@ test('executing query', function () { ) } }) + + test('throws an error when callback is not a function', function () { + try { + client.query('SELECT $1', [1], 'notafunction') + } catch (error) { + assert.equal( + error.message, + 'callback is not a function', + 'Should have thrown an Error for non function callback' + ) + } + }) }) }) From 0f56b76d09c9596940a78bec4a438712d1823fb5 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 11 May 2026 15:14:33 -0700 Subject: [PATCH 39/81] Throw `TypeError` instead of base `Error` when query callback is not a function & style fix. Follow-up to #3561. --- packages/pg/lib/client.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 33a8e24f0..bb5e6d5f0 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -633,10 +633,8 @@ class Client extends EventEmitter { Error.captureStackTrace(err) throw err }) - } else { - if (!(typeof query.callback === 'function')) { - throw new Error('callback is not a function') - } + } else if (typeof query.callback !== 'function') { + throw new TypeError('callback is not a function') } } From c73a645779838a6c0cf7ae7400e71d94243f8cb2 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 12 May 2026 14:10:58 -0700 Subject: [PATCH 40/81] =?UTF-8?q?test:=20Ensure=20failure=20to=20throw=20a?= =?UTF-8?q?t=20all=20doesn=E2=80=99t=20pass=20(#3671)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pg/test/unit/client/simple-query-tests.js | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/packages/pg/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index 6c20c576b..8cc550830 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -118,39 +118,36 @@ test('executing query', 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 () { - try { - client.query('SELECT $1', [1], 'notafunction') - } catch (error) { - assert.equal( - error.message, - 'callback is not a function', - 'Should have thrown an Error for non function callback' - ) - } + assert.throws( + () => { + client.query('SELECT $1', [1], 'notafunction') + }, + { + message: 'callback is not a function', + } + ) }) }) }) From be880d45552269f0b847a3e568014bde6536eae3 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 12 May 2026 22:54:13 -0700 Subject: [PATCH 41/81] Assorted test fixes and cleanup (#3672) * cleanup: Remove duplicate test * cleanup: Remove nonsense test * cleanup: Simplify promise rejection test * test: Fix and tighten assertion that would always pass because of the `SELECTR` typo. * cleanup: Add missing `await`s when using `assert.rejects` in tests; remove unneeded function wrappers --- .../integration/client/promise-api-tests.js | 29 +--- .../test/integration/gh-issues/3174-tests.js | 8 +- .../pg/test/unit/client/sasl-scram-tests.js | 139 ++++++++---------- 3 files changed, 69 insertions(+), 107 deletions(-) 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/gh-issues/3174-tests.js b/packages/pg/test/integration/gh-issues/3174-tests.js index 99044df0e..cd920346a 100644 --- a/packages/pg/test/integration/gh-issues/3174-tests.js +++ b/packages/pg/test/integration/gh-issues/3174-tests.js @@ -104,7 +104,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 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() diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index 7554a9814..8b0376d67 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -58,64 +58,53 @@ suite.test('sasl/scram', function () { }) suite.test('continueSession', function () { - suite.test('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.test('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.test('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.test('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,53 +112,47 @@ suite.test('sasl/scram', function () { } }) - suite.test('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.test('fails when iteration is missing in server message', function () { - assert.rejects( - function () { - return sasl.continueSession( - { - message: 'SASLInitialResponse', - }, - 'bad-password', - 'r=1,s=abcd' - ) - }, + 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', function () { - assert.rejects( - function () { - return sasl.continueSession( - { - message: 'SASLInitialResponse', - clientNonce: '2', - }, - 'bad-password', - 'r=1,s=abcd,i=1' - ) - }, + 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', } From 63c921bbc7dfba684a75f3da6bc10e4f2cdc27fd Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 12 May 2026 22:54:41 -0700 Subject: [PATCH 42/81] ci: Node 26 followup (#3670) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Revert unneeded pg-native→libpq dependency range adjustment This reverts part of commit 1025d12b24f277f9b7cdba2d5488103745939d6b. * dev: Upgrade libpq/nan in lockfile for Node 26 compatibility --- packages/pg-native/package.json | 2 +- yarn.lock | 23 +++++++++-------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/packages/pg-native/package.json b/packages/pg-native/package.json index b75b2ffdb..4c8148ac1 100644 --- a/packages/pg-native/package.json +++ b/packages/pg-native/package.json @@ -34,7 +34,7 @@ }, "homepage": "https://github.com/brianc/node-postgres/tree/master/packages/pg-native", "dependencies": { - "libpq": "^1.11.0", + "libpq": "^1.8.15", "pg-types": "2.2.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 6e45ace78..92028ecc8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5907,13 +5907,13 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -libpq@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/libpq/-/libpq-1.10.0.tgz#238d01d416abca8768aab09bc82d81af9c7ffa23" - integrity sha512-PHY+JGD3+9X5b2emXLh+WJEnz1jhczO1xs25ZH0xbMWvQi+Hd9X/mTZOrGA99Rcw/DvNjsBRlegroqigpNfaJA== +libpq@^1.8.15: + 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.23.1" + nan "~2.26.2" lines-and-columns@^1.1.6: version "1.1.6" @@ -6627,15 +6627,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.23.1: - version "2.23.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.23.1.tgz#6f86a31dd87e3d1eb77512bf4b9e14c8aded3975" - integrity sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw== +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" From 0ac3eddef6481f4e4f9359c65d3c0cfd7d2124e1 Mon Sep 17 00:00:00 2001 From: Andrew Valleteau Date: Wed, 13 May 2026 07:55:52 +0200 Subject: [PATCH 43/81] fix: apply SASLprep (RFC 4013) to passwords before SCRAM-SHA-256 PBKDF2 (#3669) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: apply SASLprep (RFC 4013) to passwords before SCRAM-SHA-256 PBKDF2 `pg`'s SCRAM-SHA-256 client passes the raw password into PBKDF2 with no normalization, while PostgreSQL's server (and libpq) apply SASLprep (B.1 mapping -> NFKC -> prohibition + bidi check) when computing the stored verifier. Passwords whose NFKC form differs from themselves (e.g. containing U+00A8 dieresis, U+2011 non-breaking hyphen, U+00BC vulgar one quarter, NBSP, soft hyphen) authenticate with psql/libpq but fail against pg with `28P01`. Wire `@mongodb-js/saslprep` (the maintained fork used by mongodb's official Node driver) into `continueSession` before `crypto.deriveKey`, with a try/catch fallback to the raw password on prohibited / bidi violations to match `libpq`'s `pg_saslprep` behavior. Also adds: - Unit tests covering the soft-hyphen B.1 mapping equivalence, the Roman-numeral-IX NFKC asymmetry, the prohibited-char fallback, and a deterministic snapshot for the original bug-report password. - A gated integration test block (SCRAM_TEST_PGUSER_UNICODE / SCRAM_TEST_PGPASSWORD_UNICODE) covering raw + NFKC-equivalent + wrong password. - A `scram_unicode_test` role (password `U&'IX-\2168'`) provisioned in CI plus matching env vars so the new integration tests run on every Node version. - A Cloudflare Workers regression guard that exercises `sasl.continueSession` to ensure `@mongodb-js/saslprep` resolves cleanly under workerd. - A `pg@8.21.0` CHANGELOG entry. * fix: inline SASLprep, drop @mongodb-js/saslprep dependency Per review feedback on #3669: ship the SASLprep step as a small in-tree function instead of pulling a runtime dep with an unpinned transitive. The function performs only the three byte-changing steps from RFC 4013 (Table C.1.2 -> SPACE, Table B.1 -> empty, NFKC) and skips the prohibition (RFC 4013 section 2.3) and bidi (RFC 3454 section 6) checks, since libpq is forgiving on those paths and Postgres's own SASLprep is similarly lenient. Removes the try/catch fallback (no code path throws). The deterministic snapshot tests stay byte-for-byte valid because none of them touch U+200B, the only edge case where the inline impl diverges from `@mongodb-js/saslprep`. RFC 3454 places U+200B in Table B.1 (mapped to nothing); the dep maps it to SPACE. PostgreSQL's saslprep.c follows the RFC, so the inline impl matches libpq more closely on that codepoint. The B.1 unit-test rename ("passes ASCII control characters through normalization unchanged") keeps the same snapshot bytes since BEL is unchanged by all three steps. Co-authored-by: charmander * Revert unrelated no-op changes to yarn.lock now that the associated dependency isn’t being added. * cleanup: Allow Prettier to format some lines * cleanup: Remove changelog entry for unreleased pg version normally added as part of the release process * refactor: Simplify comments in sasl.js and remove unused test cases Updated comments in sasl.js to clarify the password normalization process and removed redundant test cases from vitest-cf.test.ts, streamlining the codebase. * Remove redundant NFKC-only SASLprep test Confirmed in pull request comments that the “macOS/iOS” thing was an AI inventing an unneeded justification, and NFKC is already covered by another test. * fix: SASLprep zero-width space the same way PostgreSQL does As mentioned in the test comment, RFC 3454 defines appendix B for mapping tables and appendix C for prohibition tables. RFC 4013 SASLprep is probably misusing that list of non-ASCII spaces, and says nothing about the overlap. (At least it’s obsoleted.) * cleanup: Simplify regex character classes with ranges --------- Co-authored-by: charmander Co-authored-by: Charmander <~@charmander.me> --- .github/workflows/ci.yml | 10 ++- packages/pg/lib/crypto/sasl.js | 30 ++++++- .../integration/client/sasl-scram-tests.js | 79 +++++++++++++++++++ .../pg/test/unit/client/sasl-scram-tests.js | 58 ++++++++++++++ 4 files changed, 175 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1aae36233..1a266291d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,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 +70,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/packages/pg/lib/crypto/sasl.js b/packages/pg/lib/crypto/sasl.js index a782ae48a..39af4e4cf 100644 --- a/packages/pg/lib/crypto/sasl.js +++ b/packages/pg/lib/crypto/sasl.js @@ -2,6 +2,34 @@ const crypto = require('./utils') const { signatureAlgorithmHashFromCertificate } = require('./cert-signatures') +// 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') +} + function startSession(mechanisms, stream) { const candidates = ['SCRAM-SHA-256'] if (stream) candidates.unshift('SCRAM-SHA-256-PLUS') // higher-priority, so placed first @@ -70,7 +98,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) diff --git a/packages/pg/test/integration/client/sasl-scram-tests.js b/packages/pg/test/integration/client/sasl-scram-tests.js index 85bf2cd34..bf1dfcb0d 100644 --- a/packages/pg/test/integration/client/sasl-scram-tests.js +++ b/packages/pg/test/integration/client/sasl-scram-tests.js @@ -108,3 +108,82 @@ suite.test('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/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index 8b0376d67..fc75a748a 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -187,6 +187,64 @@ suite.test('sasl/scram', function () { assert.equal(session.response, 'c=eSws,r=ab,p=YVTEOwOD7khu/NulscjFegHrZoTXJBFI/7L61AN9khc=') }) + 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', From 2095247a7b10ebe19cd7d518e07ee2f259dda70a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 13 May 2026 20:51:03 -0700 Subject: [PATCH 44/81] cleanup: Combine duplicated code in `Client#query` and avoid unneeded early non-const declarations (#3674) No behaviour change except for the negligible one of reading the `query_timeout` property before `submit`. --- packages/pg/lib/client.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index bb5e6d5f0..fb45649b3 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -605,14 +605,14 @@ class Client extends EventEmitter { // 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 + } + + const readTimeout = config.query_timeout || this.connectionParameters.query_timeout + + if (typeof config.submit === 'function') { result = query = config if (!query.callback) { if (typeof values === 'function') { @@ -622,7 +622,6 @@ class Client extends EventEmitter { } } } else { - readTimeout = config.query_timeout || this.connectionParameters.query_timeout query = new Query(config, values, callback) if (!query.callback) { result = new this._Promise((resolve, reject) => { @@ -639,9 +638,9 @@ class Client extends EventEmitter { } if (readTimeout) { - queryCallback = query.callback || (() => {}) + const queryCallback = query.callback || (() => {}) - readTimeoutTimer = setTimeout(() => { + const readTimeoutTimer = setTimeout(() => { const error = new Error('Query read timeout') process.nextTick(() => { From 88a7e60c7191ce8061d6276b299895bf5511e042 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 14 May 2026 04:46:36 +0000 Subject: [PATCH 45/81] cleanup: Move declaration to more natural place Missed in #3674. --- packages/pg/lib/client.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index fb45649b3..3bfffc7d2 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -610,8 +610,6 @@ class Client extends EventEmitter { throw new TypeError('Client was passed a null or undefined query') } - const readTimeout = config.query_timeout || this.connectionParameters.query_timeout - if (typeof config.submit === 'function') { result = query = config if (!query.callback) { @@ -637,6 +635,7 @@ class Client extends EventEmitter { } } + const readTimeout = config.query_timeout || this.connectionParameters.query_timeout if (readTimeout) { const queryCallback = query.callback || (() => {}) From fa47e73349786c2a76db98801d60c05371b0a906 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 14 May 2026 07:40:29 -0700 Subject: [PATCH 46/81] fix: `Client#end` callback being called multiple times when first is no-op (#3676) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: unintended listener after no-op `Client#end` callback * fix: `Client#end` callback being called multiple times when first is no-op (and unwanted retained listener even when not called multiple times) * fix: Prevent multiple callbacks in pg/native `Client#end`, and align pre-connect behaviour closer to pg As usual, the native client is extra full of bugs and inconsistencies, so this is just “good enough”. --- packages/pg/lib/client.js | 1 + packages/pg/lib/native/client.js | 6 ++++-- packages/pg/test/integration/client/api-tests.js | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 3bfffc7d2..3525cf5ac 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -716,6 +716,7 @@ class Client extends EventEmitter { if (!this.connection._connecting || this._ended) { if (cb) { cb() + return } else { return this._Promise.resolve() } diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 6df471b83..fa17d9f65 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -249,8 +249,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) { 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( From c8da6ab9326d93005e6947217cf665f707e08ec7 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 14 May 2026 07:42:48 -0700 Subject: [PATCH 47/81] Assorted test cleanup (#3673) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: Remove unused `assert.UTCDate` * test: Replace `equalBuffers` with `assert.deepStrictEqual` `spit` isn’t defined. * cleanup: Replace additional helper in test with stdlib `assert.rejects` * cleanup: Merge unused test suite `uncaughtException` handler into first one * cleanup: Remove unused `Suite#testAsync` * cleanup: Remove now-redundant `unhandledRejection` listener in tests All versions of Node (≥16.x) supported by pg 8 default to throwing. --- .../client/error-handling-tests.js | 11 ++-- packages/pg/test/suite.js | 16 ----- packages/pg/test/test-helper.js | 61 +------------------ .../unit/client/cleartext-password-tests.js | 2 +- .../pg/test/unit/client/md5-password-tests.js | 5 +- 5 files changed, 11 insertions(+), 84 deletions(-) diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index 7493ef68d..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.test('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/suite.js b/packages/pg/test/suite.js index 7a1c20008..e8d9d0834 100644 --- a/packages/pg/test/suite.js +++ b/packages/pg/test/suite.js @@ -1,11 +1,6 @@ 'use strict' const async = require('async') -const { deprecate } = require('util') - -const deprecatedTestAsync = deprecate(function (name, cb) { - this.test(name, cb) -}, 'Suite#testAsync is deprecated. Use Suite#test instead - it handles promises & async functions just fine.') class Test { constructor(name, cb) { @@ -75,17 +70,6 @@ class Suite { const test = new Test(name, cb) this._queue.push(test) } - - testAsync(name, cb) { - return deprecatedTestAsync.call(this, name, cb) - } } -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 8cd9dda36..3d2d4d4d8 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -21,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 @@ -66,12 +67,6 @@ 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) { @@ -84,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) { @@ -124,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) } @@ -257,6 +201,5 @@ module.exports = { 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') + ) }) }) ) From f252870eba73c15449b57562e6698b5859e32095 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 14 May 2026 11:32:31 -0700 Subject: [PATCH 48/81] cleanup: pg utils (#3675) * cleanup: `arrayString` code style * cleanup: Move `Buffer.from` Node 4 compatibility code to common function Reviewed-by: brianc --- packages/pg/lib/utils.js | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index e23a55e9a..1bbdebaf9 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -11,6 +11,12 @@ function escapeElement(elementRepresentation) { return '"' + escaped + '"' } +// Node.js v4 does not support those Buffer.from params +const bufferFrom = + Buffer.from(new Uint8Array(1).buffer, 0, 0).length === 0 + ? Buffer.from + : (arrayBuffer, byteOffset, length) => Buffer.from(arrayBuffer).slice(byteOffset, byteOffset + length) + // convert a JS array to a postgres array literal // uses comma separator so won't work for types like box that use // a different array separator. @@ -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 = bufferFrom(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,11 +58,7 @@ 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 bufferFrom(val.buffer, val.byteOffset, val.byteLength) } if (isDate(val)) { if (defaults.parseInputDatesAsUTC) { From f776327b3fcdd997c67e866ef7c620ef9c26b3f2 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 18 May 2026 04:49:06 -0700 Subject: [PATCH 49/81] Remove compatibility code for unsupported versions of Node (<16) (#3678) * Remove compatibility code for unsupported versions of Node (<16) * cleanup: Remove remaining `unhandledRejection` handlers in pg tests Unhandled rejections are errors by default in all supported versions of Node. --- packages/pg/lib/crypto/utils-legacy.js | 43 --------- packages/pg/lib/crypto/utils-webcrypto.js | 89 ----------------- packages/pg/lib/crypto/utils.js | 96 +++++++++++++++++-- packages/pg/lib/utils.js | 13 +-- .../client/async-stack-trace-tests.js | 73 +++++++------- .../client/query-as-promise-tests.js | 5 - 6 files changed, 123 insertions(+), 196 deletions(-) delete mode 100644 packages/pg/lib/crypto/utils-legacy.js delete mode 100644 packages/pg/lib/crypto/utils-webcrypto.js 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/utils.js b/packages/pg/lib/utils.js index 1bbdebaf9..638b43970 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -2,8 +2,7 @@ const defaults = require('./defaults') -const util = require('util') -const { isDate } = util.types || util // Node 8 doesn't have `util.types` +const { isDate } = require('util/types') function escapeElement(elementRepresentation) { const escaped = elementRepresentation.replace(/\\/g, '\\\\').replace(/"/g, '\\"') @@ -11,12 +10,6 @@ function escapeElement(elementRepresentation) { return '"' + escaped + '"' } -// Node.js v4 does not support those Buffer.from params -const bufferFrom = - Buffer.from(new Uint8Array(1).buffer, 0, 0).length === 0 - ? Buffer.from - : (arrayBuffer, byteOffset, length) => Buffer.from(arrayBuffer).slice(byteOffset, byteOffset + length) - // convert a JS array to a postgres array literal // uses comma separator so won't work for types like box that use // a different array separator. @@ -33,7 +26,7 @@ function arrayString(val) { result += arrayString(item) } else if (ArrayBuffer.isView(item)) { if (!(item instanceof Buffer)) { - item = bufferFrom(item.buffer, item.byteOffset, item.byteLength) + item = Buffer.from(item.buffer, item.byteOffset, item.byteLength) } result += '\\\\x' + item.toString('hex') } else { @@ -58,7 +51,7 @@ const prepareValue = function (val, seen) { return val } if (ArrayBuffer.isView(val)) { - return bufferFrom(val.buffer, val.byteOffset, val.byteLength) + return Buffer.from(val.buffer, val.byteOffset, val.byteLength) } if (isDate(val)) { if (defaults.parseInputDatesAsUTC) { 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 8f289f5ad..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.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.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.test('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, { cause: e }) - } + 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/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) => { From cc03fa5cdf0f1e67b2518ebad5cf2269206aa49c Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Mon, 18 May 2026 07:50:22 -0400 Subject: [PATCH 50/81] Add scramMaxIterations option to limit SCRAM iteration count (#3677) Caps the number of SCRAM iterations the driver will perform during SASL auth, defaulting to 100000. Protects against malicious or misconfigured servers requesting unbounded PBKDF2 work. A value of zero disables the check entirely. --- packages/pg/lib/client.js | 18 ++++- packages/pg/lib/crypto/sasl.js | 18 ++++- .../pg/test/unit/client/sasl-scram-tests.js | 74 +++++++++++++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 3525cf5ac..d6c57194c 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -36,6 +36,17 @@ 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() @@ -74,6 +85,7 @@ class Client extends EventEmitter { 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({ @@ -307,7 +319,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) diff --git a/packages/pg/lib/crypto/sasl.js b/packages/pg/lib/crypto/sasl.js index 39af4e4cf..ea63b2413 100644 --- a/packages/pg/lib/crypto/sasl.js +++ b/packages/pg/lib/crypto/sasl.js @@ -30,7 +30,9 @@ function saslprep(password) { return password.replace(nonAsciiSpace, ' ').replace(mappedToNothing, '').normalize('NFKC') } -function startSession(mechanisms, stream) { +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 @@ -53,6 +55,7 @@ function startSession(mechanisms, stream) { clientNonce, response: gs2Header + ',,n=*,r=' + clientNonce, message: 'SASLInitialResponse', + scramMaxIterations, } } @@ -78,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 @@ -243,4 +258,5 @@ module.exports = { startSession, continueSession, finalizeSession, + DEFAULT_MAX_SCRAM_ITERATIONS, } diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index fc75a748a..02b0d4e6d 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -55,6 +55,18 @@ 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 () { @@ -159,6 +171,68 @@ suite.test('sasl/scram', function () { ) }) + suite.test('fails when iteration count exceeds default scramMaxIterations', async function () { + await assert.rejects( + function () { + return sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: 'a', + scramMaxIterations: 100000, + }, + 'password', + 'r=ab,s=abcd,i=100001' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count 100001 exceeds scramMaxIterations of 100000', + } + ) + }) + + suite.test('fails when iteration count exceeds a custom scramMaxIterations', async function () { + await assert.rejects( + function () { + return sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: 'a', + scramMaxIterations: 10, + }, + 'password', + 'r=ab,s=abcd,i=11' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration count 11 exceeds scramMaxIterations of 10', + } + ) + }) + + 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', From 8486337000f7ff5d430acdd60c19f68fa3130697 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 18 May 2026 06:55:25 -0500 Subject: [PATCH 51/81] Sponsors & docs update --- SPONSORS.md | 1 + docs/theme.config.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) 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/theme.config.js b/docs/theme.config.js index 03ba3665c..4c10dc5c2 100644 --- a/docs/theme.config.js +++ b/docs/theme.config.js @@ -17,14 +17,14 @@ export default { footer: { content: ( - As of 2026-03-01 I am taking a break from the workforce to focus entirely on this project! Please consider{' '} + Please consider{' '} - sponsoring this work on GitHub + sponsoring this project on GitHub! ! From d197d7b1093248bd6d94e1cd5cbf5c769f74252d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 18 May 2026 06:59:08 -0500 Subject: [PATCH 52/81] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d167ceef..dd26374a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ 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.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. From 544b1ce8152bc280e398dc1e8a66920abe6a640e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 18 May 2026 06:59:17 -0500 Subject: [PATCH 53/81] Publish - pg-bundler-test@0.3.0 - pg-cloudflare@1.4.0 - pg-connection-string@2.13.0 - pg-cursor@2.20.0 - pg-esm-test@1.7.0 - pg-native@3.8.0 - pg-pool@3.14.0 - pg-protocol@1.14.0 - pg-query-stream@4.15.0 - pg@8.21.0 --- packages/pg-bundler-test/package.json | 4 ++-- packages/pg-cloudflare/package.json | 2 +- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-esm-test/package.json | 16 ++++++++-------- packages/pg-native/package.json | 2 +- packages/pg-pool/package.json | 2 +- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 10 +++++----- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/pg-bundler-test/package.json b/packages/pg-bundler-test/package.json index b81c6a24d..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.2.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 ac68bb22e..4bc706c8a 100644 --- a/packages/pg-cloudflare/package.json +++ b/packages/pg-cloudflare/package.json @@ -1,6 +1,6 @@ { "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", diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index d02588a6c..aa075e154 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.12.0", + "version": "2.13.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 332e51a2f..3949d50c8 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.19.0", + "version": "2.20.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "exports": { @@ -25,7 +25,7 @@ "license": "MIT", "devDependencies": { "mocha": "^11.7.5", - "pg": "^8.20.0" + "pg": "^8.21.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-esm-test/package.json b/packages/pg-esm-test/package.json index 0f15f7ff2..ec3c4a811 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.6.0", + "version": "1.7.0", "description": "A test module for PostgreSQL with ESM support", "main": "index.js", "type": "module", @@ -14,13 +14,13 @@ "test" ], "devDependencies": { - "pg": "^8.20.0", - "pg-cloudflare": "^1.3.0", - "pg-cursor": "^2.19.0", - "pg-native": "^3.7.0", - "pg-pool": "^3.13.0", - "pg-protocol": "^1.13.0", - "pg-query-stream": "^4.14.0" + "pg": "^8.21.0", + "pg-cloudflare": "^1.4.0", + "pg-cursor": "^2.20.0", + "pg-native": "^3.8.0", + "pg-pool": "^3.14.0", + "pg-protocol": "^1.14.0", + "pg-query-stream": "^4.15.0" }, "author": "Brian M. Carlson ", "license": "MIT" diff --git a/packages/pg-native/package.json b/packages/pg-native/package.json index 4c8148ac1..513f3bb3f 100644 --- a/packages/pg-native/package.json +++ b/packages/pg-native/package.json @@ -1,6 +1,6 @@ { "name": "pg-native", - "version": "3.7.0", + "version": "3.8.0", "description": "A slightly nicer interface to Postgres over node-libpq", "main": "index.js", "exports": { diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 7ac434f97..6b9f60155 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.13.0", + "version": "3.14.0", "description": "Connection pool for node-postgres", "main": "index.js", "exports": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index d3326bdbc..4ee3e3f17 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.13.0", + "version": "1.14.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 42ef8f268..6704fcfb9 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.14.0", + "version": "4.15.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -45,7 +45,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^7.3.0", "mocha": "^11.7.5", - "pg": "^8.20.0", + "pg": "^8.21.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^6.0.3" @@ -54,6 +54,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.19.0" + "pg-cursor": "^2.20.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index d14e448d6..61f9b7ede 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.20.0", + "version": "8.21.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.12.0", - "pg-pool": "^3.13.0", - "pg-protocol": "^1.13.0", + "pg-connection-string": "^2.13.0", + "pg-pool": "^3.14.0", + "pg-protocol": "^1.14.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, @@ -50,7 +50,7 @@ "wrangler": "^3.x" }, "optionalDependencies": { - "pg-cloudflare": "^1.3.0" + "pg-cloudflare": "^1.4.0" }, "peerDependencies": { "pg-native": ">=3.0.1" From b7d640a71d70edfbb4199c5d2563358c1fccb665 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 17 Jun 2026 22:12:49 +0200 Subject: [PATCH 54/81] Add docs for supported PostgreSQL versions (#3690) --- docs/pages/index.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index ff27662e6..95a3fb6a6 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -5,8 +5,14 @@ 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. + ## Install ```bash From c4dfbba79a1337746c109d849f3365c9271a5def Mon Sep 17 00:00:00 2001 From: Kyle Cannon Date: Wed, 17 Jun 2026 13:23:56 -0700 Subject: [PATCH 55/81] perf(pg-protocol): encode length-prefixed strings in a single pass (#3681) * perf(pg-protocol): encode length-prefixed strings in a single pass Add Writer.addInt32PrefixedString, which writes a value's Int32 byte-length prefix immediately followed by its UTF-8 bytes, computing Buffer.byteLength once. The previous `addInt32(Buffer.byteLength(s)).addString(s)` pairing scanned each string three times. Used for Bind parameter values and the SASL initial response. Wire output is byte-identical; addInt32/addString are unchanged for other callers. Benchmark (packages/pg-protocol/bench/write-bench.js, alternating-sampled vs base): bind(2 small) +16% bind(10 mixed) +23% bind(unicode) +14% full insert seq +9% Adds a multi-byte unicode bind unit test asserting the Int32 prefix equals the UTF-8 byte length, not the char length. Co-Authored-By: Claude Opus 4.8 (1M context) * Update packages/pg-protocol/src/outbound-serializer.test.ts Co-authored-by: Charmander <~@charmander.me> --------- Co-authored-by: Claude Opus 4.8 (1M context) Co-authored-by: Charmander <~@charmander.me> --- packages/pg-protocol/src/buffer-writer.ts | 20 +++++++++++++++++ .../src/outbound-serializer.test.ts | 22 +++++++++++++++++++ packages/pg-protocol/src/serializer.ts | 6 ++--- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts index cebb0d9ed..d206f322a 100644 --- a/packages/pg-protocol/src/buffer-writer.ts +++ b/packages/pg-protocol/src/buffer-writer.ts @@ -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) diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index 0d3e387e4..856ead7b9 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 () { diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index bb0441f56..137daad79 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) } @@ -135,8 +135,8 @@ const writeValues = function (values: any[], valueMapper?: ValueMapper): void { } 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) + paramWriter.addInt32PrefixedString(mappedVal) } } } From 882fc308cce7bf136cd1448e00395f760dad3e00 Mon Sep 17 00:00:00 2001 From: Shion Ichikawa Date: Thu, 18 Jun 2026 05:24:06 +0900 Subject: [PATCH 56/81] Add support for sslnegotiation=direct (PostgreSQL 17) (#3688) PostgreSQL 17 added the `sslnegotiation` connection parameter, which allows clients to start the TLS handshake immediately after the TCP connection ("direct" negotiation) instead of first sending an SSLRequest packet and waiting for the server's S/N reply ("postgres" negotiation, the default and prior behavior). Direct negotiation saves one network round-trip and works with protocol-agnostic TLS tooling. - connection.js: extract the TLS upgrade into upgradeToSSL(); in direct mode upgrade the socket right after connect (skipping the SSLRequest exchange) and advertise the `postgresql` ALPN protocol as the server requires. - client.js: forward sslNegotiation to the Connection and skip requestSsl() in direct mode. - connection-parameters.js: read sslnegotiation from config / PGSSLNEGOTIATION, validate it is `postgres` or `direct`, require SSL to be enabled for `direct`, and include it in the libpq connection string. - pg-connection-string: parse the sslnegotiation query param and enable SSL automatically when `direct` is requested without other SSL config. - docs: document the new option. - tests: cover connection-string parsing, connection-parameters validation, and the direct-vs-traditional connection behavior (no SSLRequest packet, ALPN set only for direct). Closes #3346 --- docs/pages/features/ssl.mdx | 25 +++++++ packages/pg-connection-string/index.d.ts | 1 + packages/pg-connection-string/index.js | 6 ++ packages/pg-connection-string/test/parse.ts | 23 ++++++ packages/pg/lib/client.js | 8 ++- packages/pg/lib/connection-parameters.js | 13 ++++ packages/pg/lib/connection.js | 65 +++++++++++------ packages/pg/lib/defaults.js | 3 + .../connection-parameters/creation-tests.js | 59 +++++++++++++++ .../pg/test/unit/connection/error-tests.js | 71 +++++++++++++++++++ 10 files changed, 251 insertions(+), 23 deletions(-) diff --git a/docs/pages/features/ssl.mdx b/docs/pages/features/ssl.mdx index 9983c0434..6a29ed739 100644 --- a/docs/pages/features/ssl.mdx +++ b/docs/pages/features/ssl.mdx @@ -49,6 +49,31 @@ const config = { } ``` +## 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/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 4b8d7afb9..7ee302976 100644 --- a/packages/pg-connection-string/index.js +++ b/packages/pg-connection-string/index.js @@ -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 diff --git a/packages/pg-connection-string/test/parse.ts b/packages/pg-connection-string/test/parse.ts index 814e49c58..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) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index d6c57194c..18280f3c6 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -91,6 +91,7 @@ class Client extends EventEmitter { 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', @@ -100,6 +101,7 @@ class Client extends EventEmitter { 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 @@ -177,7 +179,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()) } 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..63cc13a53 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() @@ -24,6 +25,7 @@ class Connection extends EventEmitter { this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis this.parsedStatements = {} this.ssl = config.ssl || false + this.sslNegotiation = config.sslNegotiation || 'postgres' this._ending = false this._emitMessage = false const self = this @@ -65,6 +67,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 +88,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/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/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index bb6f815a0..e326e2630 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -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 From d7175a4aa0347b7416109e9ecc61d4d235486d0e Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Thu, 18 Jun 2026 20:27:56 -0400 Subject: [PATCH 57/81] Expand CI matrix of PG versions and add direct SSL test (#3693) * Remove unused os block from GHA CI matrix * Add historical postgres versions to GHA test matrix Adds testing of historical postgres versions from 13 to 18 to the GitHub Actions CI matrix. They are each tested with the latest node version. Older node versions are only tested against the latest postgresql server version. Both the stable server version and latest node version are defined as YAML anchors to allow updating them in a single place in the future. For v18+ the container requires an explicit PGDATA directory parent path so we add that as well. This applies to older versions too but should not be an issue. * Add direct SSL test that only runs against v17+ --- .github/workflows/ci.yml | 33 +++++++---- .../pg/test/integration/client/ssl-tests.js | 55 +++++++++++++++++++ 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a266291d..6f0751c56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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' - - '26' - 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 diff --git a/packages/pg/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js index 33919cdf8..b5b32c5ba 100644 --- a/packages/pg/test/integration/client/ssl-tests.js +++ b/packages/pg/test/integration/client/ssl-tests.js @@ -22,3 +22,58 @@ suite.test('can connect with ssl', function (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() + }) +} From f49ab4a9795ae0866409f9bfe52a68b4f65ef024 Mon Sep 17 00:00:00 2001 From: Shion Ichikawa Date: Fri, 19 Jun 2026 09:29:00 +0900 Subject: [PATCH 58/81] fix: correct spelling mistakes across codebase (#3692) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: correct spelling mistakes across codebase - "bye" → "byte" in parser.ts comment - "interal" → "internal" in CHANGELOG.md - "PostgresSQL" → "PostgreSQL" in pg-connection-string package.json and README.md - "immediatley" → "immediately" in network-partition-tests.js - "connectet" → "connected" in network-partition-tests.js * revert: restore original CHANGELOG.md spelling CHANGELOG is a historical record of past releases and should not be modified. Reverting the "interal" → "internal" fix from 7cc57c1d. --- packages/pg-connection-string/README.md | 2 +- packages/pg-connection-string/package.json | 2 +- packages/pg-protocol/src/parser.ts | 2 +- .../pg/test/integration/client/network-partition-tests.js | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) 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/package.json b/packages/pg-connection-string/package.json index aa075e154..ffa6705af 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.13.0", - "description": "Functions for dealing with a PostgresSQL connection string", + "description": "Functions for dealing with a PostgreSQL connection string", "main": "./index.js", "types": "./index.d.ts", "exports": { diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 998077a00..3d8ce80c7 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 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) { From 695fe6180401e630a78f50f81b9909b9942f6035 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 18 Jun 2026 19:33:15 -0500 Subject: [PATCH 59/81] Stop cstring reading on any falsy value (#3691) --- .gitignore | 1 + packages/pg-protocol/src/buffer-reader.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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/packages/pg-protocol/src/buffer-reader.ts b/packages/pg-protocol/src/buffer-reader.ts index c9d9c2b66..42a4a23fa 100644 --- a/packages/pg-protocol/src/buffer-reader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -45,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) } From 835fb83ab9e1cf30fa8367ba42bd633720d71832 Mon Sep 17 00:00:00 2001 From: Andrey Pshenkin Date: Fri, 19 Jun 2026 02:35:17 +0200 Subject: [PATCH 60/81] Fix error handling for exceptions on values parsing. (#3574) * fix(pg-protocol): reset Writer state when error throws from valueMapper in bind() When valueMapper throws during serialize.bind(), the module-level singleton Writer instances (writer and paramWriter) are left with partial data from the interrupted operation. This corrupts all subsequent serializer calls since they share the same Writer instances. Add Writer.clear() method that resets the write cursor without allocating a new buffer (zero overhead on the happy path). Wrap writeValues() in bind() with try-catch to clear both writers on error. * fix(pg): send Close and Sync when bind serialization throws When connection.bind() throws during prepare(), the catch block previously called handleError() without sending any protocol messages. Since PARSE was already buffered (due to cork), the server processes it and waits for more messages, leaving the connection hung. Send Close to clean up the parsed statement and Sync to return the connection to a usable state. --- packages/pg-protocol/src/buffer-writer.ts | 5 ++ .../src/outbound-serializer.test.ts | 58 +++++++++++++ packages/pg-protocol/src/serializer.ts | 8 +- packages/pg/lib/query.js | 4 + .../test/unit/client/throw-in-bind-tests.js | 86 +++++++++++++++++++ 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 packages/pg/test/unit/client/throw-in-bind-tests.js diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts index d206f322a..9eae65859 100644 --- a/packages/pg-protocol/src/buffer-writer.ts +++ b/packages/pg-protocol/src/buffer-writer.ts @@ -102,4 +102,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/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index 856ead7b9..aac0c57ba 100644 --- a/packages/pg-protocol/src/outbound-serializer.test.ts +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -295,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/serializer.ts b/packages/pg-protocol/src/serializer.ts index 137daad79..547c053f8 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -152,7 +152,13 @@ const bind = (config: BindOpts = {}): Buffer => { writer.addCString(portal).addCString(statement) writer.addInt16(len) - writeValues(values, config.valueMapper) + try { + writeValues(values, config.valueMapper) + } catch (err) { + writer.clear() + paramWriter.clear() + throw err + } writer.addInt16(len) writer.add(paramWriter.flush()) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 64aab5ff2..04e1c1d65 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -228,6 +228,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/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() + }, + }) + ) +}) From 7bc35ca5c300ab3dc4763bc7c50a4051aec86b85 Mon Sep 17 00:00:00 2001 From: Nigro Simone Date: Fri, 19 Jun 2026 02:38:09 +0200 Subject: [PATCH 61/81] docs: add fastest (#3540) see https://github.com/brianc/node-postgres/issues/3538#issuecomment-3261371631 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ca28ce5d..c2f5c247c 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 [Truly Fastest](https://github.com/nigrosimone/postgres-benchmarks) PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. ## Monorepo From d80b2612fbe83ed8234637f20b943d85e4331094 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 18 Jun 2026 19:52:30 -0500 Subject: [PATCH 62/81] Update docs & changelog --- CHANGELOG.md | 4 ++++ README.md | 3 ++- docs/pages/index.mdx | 10 ++++++---- packages/pg/README.md | 1 + 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd26374a1..d4cf0fedf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ 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.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. diff --git a/README.md b/README.md index c2f5c247c..ecd94e792 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ NPM version NPM downloads -Non-blocking [Truly Fastest](https://github.com/nigrosimone/postgres-benchmarks) 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 diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 95a3fb6a6..d0ab0edc6 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -13,6 +13,8 @@ node-postgres is a collection of node.js modules for interfacing with your Postg 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 @@ -66,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/packages/pg/README.md b/packages/pg/README.md index 75242374c..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 From b617619f9fb6fbd231731823e2732a2927ded4be Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 18 Jun 2026 19:52:53 -0500 Subject: [PATCH 63/81] Publish - pg-connection-string@2.14.0 - pg-cursor@2.21.0 - pg-esm-test@1.8.0 - pg-protocol@1.15.0 - pg-query-stream@4.16.0 - pg@8.22.0 --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-esm-test/package.json | 10 +++++----- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index ffa6705af..cf0ac743b 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.13.0", + "version": "2.14.0", "description": "Functions for dealing with a PostgreSQL connection string", "main": "./index.js", "types": "./index.d.ts", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 3949d50c8..9dc4ef7ff 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.20.0", + "version": "2.21.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "exports": { @@ -25,7 +25,7 @@ "license": "MIT", "devDependencies": { "mocha": "^11.7.5", - "pg": "^8.21.0" + "pg": "^8.22.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-esm-test/package.json b/packages/pg-esm-test/package.json index ec3c4a811..88370652a 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.7.0", + "version": "1.8.0", "description": "A test module for PostgreSQL with ESM support", "main": "index.js", "type": "module", @@ -14,13 +14,13 @@ "test" ], "devDependencies": { - "pg": "^8.21.0", + "pg": "^8.22.0", "pg-cloudflare": "^1.4.0", - "pg-cursor": "^2.20.0", + "pg-cursor": "^2.21.0", "pg-native": "^3.8.0", "pg-pool": "^3.14.0", - "pg-protocol": "^1.14.0", - "pg-query-stream": "^4.15.0" + "pg-protocol": "^1.15.0", + "pg-query-stream": "^4.16.0" }, "author": "Brian M. Carlson ", "license": "MIT" diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 4ee3e3f17..5279b7456 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.14.0", + "version": "1.15.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 6704fcfb9..00969c496 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.15.0", + "version": "4.16.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -45,7 +45,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^7.3.0", "mocha": "^11.7.5", - "pg": "^8.21.0", + "pg": "^8.22.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^6.0.3" @@ -54,6 +54,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.20.0" + "pg-cursor": "^2.21.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 61f9b7ede..f8f614804 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.21.0", + "version": "8.22.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.13.0", + "pg-connection-string": "^2.14.0", "pg-pool": "^3.14.0", - "pg-protocol": "^1.14.0", + "pg-protocol": "^1.15.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, From 1a38e1d774fd77a5f2ab37baa2d35720a1146672 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 22 Jun 2026 13:49:57 -0700 Subject: [PATCH 64/81] =?UTF-8?q?Remove=20unused=20=E2=80=9Cchunky?= =?UTF-8?q?=E2=80=9D=20dev=20dependency=20and=20associated=20leftovers=20(?= =?UTF-8?q?#3697)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unused since 766e48f34a5efaf52cfdc545230aaccfbb3d5107 (Update types & move some configs around). --- packages/pg-protocol/package.json | 1 - packages/pg-protocol/src/types/chunky.d.ts | 1 - packages/pg-protocol/tsconfig.json | 3 +-- yarn.lock | 5 ----- 4 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 packages/pg-protocol/src/types/chunky.d.ts diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 5279b7456..979b2f13a 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -19,7 +19,6 @@ "@types/mocha": "^10.0.10", "@types/node": "^16", "chai": "^4.2.0", - "chunky": "^0.0.0", "mocha": "^11.7.5", "ts-node": "^8.5.4", "typescript": "^6.0.3" 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 e09c03cd7..7b31d4d92 100644 --- a/packages/pg-protocol/tsconfig.json +++ b/packages/pg-protocol/tsconfig.json @@ -14,8 +14,7 @@ "declaration": true, "paths": { "*": [ - "./node_modules/*", - "./src/types/*" + "./node_modules/*" ] }, "types": [ diff --git a/yarn.lock b/yarn.lock index 92028ecc8..e91121be7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3195,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" From e35aed91cb8f04116b3557e09adf33e2677af1ed Mon Sep 17 00:00:00 2001 From: Robert Nilsson <45368533+bobnil@users.noreply.github.com> Date: Fri, 17 Jul 2026 03:40:31 +0200 Subject: [PATCH 65/81] feat(types): expose QueryStream.Config (#3710) --- packages/pg-query-stream/src/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/pg-query-stream/src/index.ts b/packages/pg-query-stream/src/index.ts index 2a4509e09..752e881ca 100644 --- a/packages/pg-query-stream/src/index.ts +++ b/packages/pg-query-stream/src/index.ts @@ -72,4 +72,8 @@ class QueryStream extends Readable implements Submittable { } } +namespace QueryStream { + export type Config = QueryStreamConfig +} + export = QueryStream From c5e8c9a57bff6d9160ec5dbd5c4f4c1e4c460711 Mon Sep 17 00:00:00 2001 From: Noritaka Kobayashi Date: Wed, 22 Jul 2026 00:38:20 +0900 Subject: [PATCH 66/81] fix(lint): support TypeScript declaration merging (#3715) --- eslint.config.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eslint.config.mjs b/eslint.config.mjs index 3f95083a0..2d969deb0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -71,6 +71,8 @@ export default defineConfig([ rules: { 'no-undef': 'off', + 'no-redeclare': 'off', + '@typescript-eslint/no-redeclare': 'error', }, }, ]) From eb19d0fe6d7da11e7f1c5e73e4026350e42f9156 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Sat, 8 Aug 2026 20:13:54 +0100 Subject: [PATCH 67/81] Add opt-in query pipelining (#3652) * Add opt-in query pipelining support Allow multiple queries to be sent on the wire before waiting for responses, reducing round-trip latency. Enabled via client.pipelining = true. Each query gets its own Sync boundary so errors are isolated. Tracks in-flight named statements (submittedNamedStatements) to prevent duplicate Parse messages when pipelining queries with the same prepared statement name. Handles error/disconnect cleanup for the sent queue. * Fix pipelining edge cases and add benchmark - Clean up submittedNamedStatements on error in _handleErrorMessage to prevent stale entries from blocking future re-preparation of the same named statement after a parse failure - Guard _pulsePipelinedQueryQueue against non-queryable connections - Fix cancel() and readTimeout for sent queries: removing an already-sent query from _sentQueryQueue corrupts the pipeline response mapping since the server will still respond to it; no-op the callback instead - Add bench-pipelining.js comparing serial vs pipelined throughput * Fix pipelining activation race and add edge-case tests Gate _sentQueryQueue activation on readyForQuery=true inside _pulsePipelinedQueryQueue (and remove the redundant promotion block from _handleReadyForQuery) to eliminate the microtask/macrotask race where the next query could be activated as _activeQuery before the error's ReadyForQuery arrived, causing that RFQ to be handled by the wrong query. Also adds the error-listener fix for the query_timeout integration test so the expected stream-destroy doesn't leak as an unhandled 'error'. * Add pipelining documentation and pool-level integration - New features/pipelining.mdx documenting the opt-in flag - Client and Pool API reference updated - Pool accepts `pipelining: true` and sets it on every client it creates * Fix prettier formatting * Add pipelining support to native client via libpq pipeline mode - pg-native: handle PGRES_PIPELINE_SYNC/PGRES_PIPELINE_ABORTED in _emitResult; add pipeline() batch method using libpq 14+ pipeline mode (enterPipelineMode, pipelineSync, exitPipelineMode) - pg-native: bump libpq dependency to ^1.9.0 (has pipeline bindings) - native client: add _pulsePipelinedQueryQueue that batches all queued queries through pg-native pipeline(), delivering results per-query - native client: suppress queue length deprecation when pipelining * Fix pipeline mode to use extended query protocol and add JS vs native benchmarks Pipeline mode requires sendQueryParams (extended query protocol), not sendQuery (simple query protocol). PostgreSQL rejects PQsendQuery in pipeline mode. Benchmark script now tests all four combinations: JS serial, JS pipelined, native serial, and native pipelined. * Fix native client end() to wait for in-flight pipeline queries The native client end() was immediately terminating the connection, causing "Connection terminated" errors for queries still in the pipeline. Now waits for the drain event before closing when pipelining is active. Also fix pipeline mode to use sendQueryParams instead of sendQuery, since PostgreSQL rejects simple query protocol in pipeline mode. * Fix native pipelining: guard handleError when query.native is unset and skip JS-only tests handleError in native/query.js crashes when this.native is undefined (e.g. query_timeout fires before pipeline callback sets it). Skip named statement cleanup and query_timeout tests for native client since those features rely on JS-specific internals. * Make pipelining a constructor option named 'pipeline' Move from post-construction property (client.pipelining = true) to constructor option (new Client({ pipeline: true })). Same for the pool: new Pool({ pipeline: true }). Renames the property and internal _pipeliningInFlight to _pipelineInFlight. Tests, docs, and benchmarks updated accordingly. --------- Co-authored-by: Brian C --- docs/pages/apis/client.mdx | 14 +- docs/pages/apis/pool.mdx | 5 + docs/pages/features/_meta.js | 1 + docs/pages/features/pipelining.mdx | 132 +++++++++++ packages/pg-native/index.js | 156 +++++++++++++ packages/pg-pool/test/index.js | 27 +++ packages/pg/bench-pipelining.js | 216 ++++++++++++++++++ packages/pg/lib/client.js | 66 +++++- packages/pg/lib/connection.js | 1 + packages/pg/lib/native/client.js | 107 ++++++++- packages/pg/lib/native/query.js | 2 +- packages/pg/lib/query.js | 7 +- .../integration/client/pipelining-tests.js | 154 +++++++++++++ packages/pg/test/integration/test-helper.js | 4 +- .../pg/test/unit/client/simple-query-tests.js | 94 ++++++++ packages/pg/test/unit/client/test-helper.js | 15 ++ 16 files changed, 982 insertions(+), 19 deletions(-) create mode 100644 docs/pages/features/pipelining.mdx create mode 100644 packages/pg/bench-pipelining.js create mode 100644 packages/pg/test/integration/client/pipelining-tests.js diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index ecfd67fca..973b1a832 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -29,7 +29,8 @@ type Config = { 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. } ``` @@ -56,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 diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx index 123bc8ba4..3627dd1c5 100644 --- a/docs/pages/apis/pool.mdx +++ b/docs/pages/apis/pool.mdx @@ -69,6 +69,11 @@ type Config = { // 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 } ``` diff --git a/docs/pages/features/_meta.js b/docs/pages/features/_meta.js index 62f1660ca..7ddd35a5c 100644 --- a/docs/pages/features/_meta.js +++ b/docs/pages/features/_meta.js @@ -1,6 +1,7 @@ export default { connecting: 'Connecting', queries: 'Queries', + pipelining: 'Pipelining', pooling: 'Pooling', transactions: 'Transactions', types: 'Data Types', 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/packages/pg-native/index.js b/packages/pg-native/index.js index 1c18241db..7fcc26303 100644 --- a/packages/pg-native/index.js +++ b/packages/pg-native/index.js @@ -199,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 @@ -314,6 +318,158 @@ 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()) { + pq.exitPipelineMode() + return cb(new Error(pq.errorMessage() || '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()) { + // truly no more results — should not happen before all syncs + break + } + } + + 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') { + // Query skipped due to previous error in same sync group + continue + } + + if (status === 'PGRES_TUPLES_OK' || status === 'PGRES_COMMAND_OK' || status === 'PGRES_EMPTY_QUERY') { + currentResult = self._consumeQueryResults(pq) + 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() + + // 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-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/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 18280f3c6..7a2fc9a64 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -97,6 +97,8 @@ class Client extends EventEmitter { 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 @@ -141,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 } @@ -430,6 +435,9 @@ class Client extends EventEmitter { } this._activeQuery = null + if (activeQuery.name) { + delete this.connection.submittedNamedStatements[activeQuery.name] + } activeQuery.handleError(msg, this.connection) } @@ -500,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] } } @@ -578,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 = () => {} } } @@ -601,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() @@ -623,6 +640,31 @@ 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 @@ -674,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() @@ -711,7 +758,7 @@ class Client extends EventEmitter { return result } - if (this._queryQueue.length > 0) { + if (this._queryQueue.length > 0 && !this.pipeline) { queryQueueLengthDeprecationNotice() } this._queryQueue.push(query) @@ -744,9 +791,18 @@ class Client extends EventEmitter { } } - 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.js b/packages/pg/lib/connection.js index 63cc13a53..62d38fa69 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -24,6 +24,7 @@ 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 diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index fa17d9f65..d305713d6 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -36,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 @@ -234,7 +236,7 @@ Client.prototype.query = function (config, values, callback) { return result } - if (this._queryQueue.length > 0) { + if (this._queryQueue.length > 0 && !this.pipeline) { queryQueueLengthDeprecationNotice() } @@ -261,16 +263,25 @@ Client.prototype.end = function (cb) { }) } - this.native.end(function () { - self._connected = false + const doEnd = function () { + self.native.end(function () { + self._connected = false - self._errorAllQueries(new Error('Connection terminated')) + self._errorAllQueries(new Error('Connection terminated')) - process.nextTick(() => { - self.emit('end') - if (cb) cb() + 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 } @@ -282,6 +293,9 @@ Client.prototype._pulseQueryQueue = function (initialConnection) { if (!this._connected) { return } + if (this.pipeline && !initialConnection) { + return this._pulsePipelinedQueryQueue() + } if (this._hasActiveQuery()) { return } @@ -300,6 +314,83 @@ 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 } + 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 — error all queries + for (let i = 0; i < nativeQueries.length; i++) { + const q = nativeQueries[i] + q.native = self.native + q.handleError(err) + } + self._pulsePipelinedQueryQueue() + 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) { 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 04e1c1d65..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 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..957047d7d --- /dev/null +++ b/packages/pg/test/integration/client/pipelining-tests.js @@ -0,0 +1,154 @@ +'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 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/test-helper.js b/packages/pg/test/integration/test-helper.js index 9dab8843a..fe2044f60 100644 --- a/packages/pg/test/integration/test-helper.js +++ b/packages/pg/test/integration/test-helper.js @@ -10,8 +10,8 @@ if (helper.args.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/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index 8cc550830..efb705aa1 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -114,6 +114,100 @@ 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() diff --git a/packages/pg/test/unit/client/test-helper.js b/packages/pg/test/unit/client/test-helper.js index 4a3fa9687..8c3c3304e 100644 --- a/packages/pg/test/unit/client/test-helper.js +++ b/packages/pg/test/unit/client/test-helper.js @@ -10,7 +10,22 @@ const makeClient = function (config) { 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 = [] + connection.parseMessages = [] + connection.bindMessages = [] + connection.syncCount = 0 const client = new Client({ connection: connection, ...config }) client.connect() client.connection.emit('connect') From 1be86af091caefdc07abec07242694c4f969ce5b Mon Sep 17 00:00:00 2001 From: Pratik Dulal <72141032+pratik-desgn@users.noreply.github.com> Date: Sun, 9 Aug 2026 01:06:05 +0545 Subject: [PATCH 68/81] fix(pg-protocol): read ParameterDescription type OIDs as unsigned (#3728) parseField() already reads dataTypeID as uint32 for RowDescription (with a regression test covering OIDs above 2^31-1), but parseParameterDescriptionMessage() was still using the signed int32 reader for the same kind of value, so custom extension types with a high OID would come back negative in ParameterDescriptionMessage.dataTypeIDs. --- packages/pg-protocol/src/inbound-parser.test.ts | 10 ++++++++++ packages/pg-protocol/src/parser.ts | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) 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/parser.ts b/packages/pg-protocol/src/parser.ts index 3d8ce80c7..df48ca4a1 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -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 } From 747a68ce273f8cdbb7c9c619f211ac383aaebdab Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Sat, 8 Aug 2026 12:21:33 -0700 Subject: [PATCH 69/81] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4cf0fedf..f8158747e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ 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+. From df274d1ba9ad9d11a8f1079314faeafde7208207 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Sat, 8 Aug 2026 12:22:18 -0700 Subject: [PATCH 70/81] Publish - pg-cursor@2.22.0 - pg-esm-test@1.9.0 - pg-native@3.9.0 - pg-protocol@1.16.0 - pg-query-stream@4.17.0 - pg@8.23.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-esm-test/package.json | 12 ++++++------ packages/pg-native/package.json | 2 +- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 9dc4ef7ff..46f3406c2 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.21.0", + "version": "2.22.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "exports": { @@ -25,7 +25,7 @@ "license": "MIT", "devDependencies": { "mocha": "^11.7.5", - "pg": "^8.22.0" + "pg": "^8.23.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-esm-test/package.json b/packages/pg-esm-test/package.json index 88370652a..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.8.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.22.0", + "pg": "^8.23.0", "pg-cloudflare": "^1.4.0", - "pg-cursor": "^2.21.0", - "pg-native": "^3.8.0", + "pg-cursor": "^2.22.0", + "pg-native": "^3.9.0", "pg-pool": "^3.14.0", - "pg-protocol": "^1.15.0", - "pg-query-stream": "^4.16.0" + "pg-protocol": "^1.16.0", + "pg-query-stream": "^4.17.0" }, "author": "Brian M. Carlson ", "license": "MIT" diff --git a/packages/pg-native/package.json b/packages/pg-native/package.json index 513f3bb3f..63d7569f3 100644 --- a/packages/pg-native/package.json +++ b/packages/pg-native/package.json @@ -1,6 +1,6 @@ { "name": "pg-native", - "version": "3.8.0", + "version": "3.9.0", "description": "A slightly nicer interface to Postgres over node-libpq", "main": "index.js", "exports": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 979b2f13a..f2920d569 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.15.0", + "version": "1.16.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 00969c496..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.16.0", + "version": "4.17.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -45,7 +45,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^7.3.0", "mocha": "^11.7.5", - "pg": "^8.22.0", + "pg": "^8.23.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^6.0.3" @@ -54,6 +54,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.21.0" + "pg-cursor": "^2.22.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index f8f614804..d028179ca 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.22.0", + "version": "8.23.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -34,7 +34,7 @@ "dependencies": { "pg-connection-string": "^2.14.0", "pg-pool": "^3.14.0", - "pg-protocol": "^1.15.0", + "pg-protocol": "^1.16.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, From 6f1cf81ecd877708ea554ecaa38368ceafc92542 Mon Sep 17 00:00:00 2001 From: Noritaka Kobayashi Date: Tue, 11 Aug 2026 15:18:50 +0900 Subject: [PATCH 71/81] ci: run lint on Node.js 22 (#3714) [skip ci] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f0751c56..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 From 203db1da197b46739cb4c654a8c83338f4ea3628 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 11 Aug 2026 07:16:40 +0000 Subject: [PATCH 72/81] cleanup: Regenerate lockfile, workspace package.json with Yarn 1.22.22 (#3741) For ease of review of #3713 (and previously other PRs). [skip ci] --- package.json | 4 ++-- yarn.lock | 31 ++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9285ad142..68e42e353 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "devDependencies": { "@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", @@ -30,8 +31,7 @@ "eslint-plugin-prettier": "^5.1.2", "lerna": "^3.19.0", "prettier": "3.0.3", - "typescript": "^6.0.3", - "@types/node": "^16" + "typescript": "^6.0.3" }, "prettier": { "semi": false, diff --git a/yarn.lock b/yarn.lock index e91121be7..e2977ba3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8482,7 +8482,7 @@ stream-spec@~0.3.5: dependencies: macgyver "~1.10" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": 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== @@ -8517,6 +8517,15 @@ 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.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== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -8556,7 +8565,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -8584,6 +8593,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -9501,7 +9517,7 @@ wrangler@^3.x: fsevents "~2.3.2" sharp "^0.33.5" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9528,6 +9544,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From ff9d775abd12f29dd6df03945253b54eabbb29f2 Mon Sep 17 00:00:00 2001 From: Noritaka Kobayashi Date: Tue, 11 Aug 2026 16:30:39 +0900 Subject: [PATCH 73/81] chore: remove unused eslint-plugin-node (#3713) [skip ci] --- package.json | 1 - yarn.lock | 43 +++---------------------------------------- 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index 68e42e353..e30454007 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "@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", diff --git a/yarn.lock b/yarn.lock index e2977ba3b..a826fd60a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4144,26 +4144,6 @@ 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.5" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#9eae11593faa108859c26f9a9c367d619a0769c0" @@ -4197,18 +4177,6 @@ eslint-scope@^9.1.2: 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.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" @@ -5187,7 +5155,7 @@ 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.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== @@ -7783,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" @@ -7897,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== @@ -8060,7 +8023,7 @@ 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== From 816d073267d2b5b5f04f9aaecd8989e3172a334a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 12 Aug 2026 02:28:41 +0000 Subject: [PATCH 74/81] perf: Copy less when serializing `Bind` messages (#3740) * Skip copying unused space at end of writer buffer when resizing * perf: Write `Bind` parameter values directly to message writer instead of creating a separate `paramWriter`. * fix: Avoid creating message with uninitialized memory when `valueMapper` shrinks values It would have created an incomplete message anyway, but I figured this was vaguely plausible, bad enough, and easy enough to fix. No test though, because the test is annoying to write. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- packages/pg-protocol/src/buffer-writer.ts | 14 ++++++- packages/pg-protocol/src/serializer.ts | 46 +++++++++++++---------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts index 9eae65859..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) } } @@ -85,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 diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index 547c053f8..bbd59623e 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -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) // length prefix + UTF-8 bytes in one pass (Buffer.byteLength computed once) - paramWriter.addInt32PrefixedString(mappedVal) + 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,19 +152,23 @@ const bind = (config: BindOpts = {}): Buffer => { const len = values.length writer.addCString(portal).addCString(statement) + + // number of parameter format codes + writer.addInt16(len) + + // space for those codes, filled by `writeValues` + const formatsOffset = writer.reserveUnsafe(len * 2) + + // number of parameter values writer.addInt16(len) try { - writeValues(values, config.valueMapper) + writeValues(values, config.valueMapper, formatsOffset) } catch (err) { writer.clear() - paramWriter.clear() throw err } - writer.addInt16(len) - writer.add(paramWriter.flush()) - // all results use the same format code writer.addInt16(1) // format code From cd5ec59255dc5ff179c4929fa2eb40ad881d1d07 Mon Sep 17 00:00:00 2001 From: Pratik Dulal <72141032+pratik-desgn@users.noreply.github.com> Date: Wed, 12 Aug 2026 08:15:22 +0545 Subject: [PATCH 75/81] fix(pg-cloudflare): safely end closed sockets (#3735) --- packages/pg-cloudflare/src/index.ts | 2 +- packages/pg-esm-test/pg-cloudflare.test.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/pg-cloudflare/src/index.ts b/packages/pg-cloudflare/src/index.ts index 9b1e517ba..357131911 100644 --- a/packages/pg-cloudflare/src/index.ts +++ b/packages/pg-cloudflare/src/index.ts @@ -107,7 +107,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 diff --git a/packages/pg-esm-test/pg-cloudflare.test.js b/packages/pg-esm-test/pg-cloudflare.test.js index a42620253..c140f0bb1 100644 --- a/packages/pg-esm-test/pg-cloudflare.test.js +++ b/packages/pg-esm-test/pg-cloudflare.test.js @@ -6,4 +6,16 @@ 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()) + }) }) From 7bee4db0dbecfc26ae0daf888d34912e8c8c982e Mon Sep 17 00:00:00 2001 From: Clio Date: Wed, 12 Aug 2026 10:33:29 +0800 Subject: [PATCH 76/81] fix: preserve row mode in native pipelines (#3742) Co-authored-by: zfaustk <4340287+zfaustk@users.noreply.github.com> --- packages/pg-native/index.js | 6 +++--- packages/pg/lib/native/client.js | 2 +- .../test/integration/client/pipelining-tests.js | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/pg-native/index.js b/packages/pg-native/index.js index 7fcc26303..fafd66aaf 100644 --- a/packages/pg-native/index.js +++ b/packages/pg-native/index.js @@ -174,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) { @@ -441,7 +441,7 @@ Client.prototype._readPipelineResults = function (queries, cb) { } if (status === 'PGRES_TUPLES_OK' || status === 'PGRES_COMMAND_OK' || status === 'PGRES_EMPTY_QUERY') { - currentResult = self._consumeQueryResults(pq) + currentResult = self._consumeQueryResults(pq, queries[queryIndex].arrayMode) continue } } diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index d305713d6..2edfff720 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -337,7 +337,7 @@ Client.prototype._pulsePipelinedQueryQueue = function () { nativeQueries.push(query) const values = query.values ? query.values.map(utils.prepareValue) : null - const pipelineEntry = { text: query.text, name: query.name } + const pipelineEntry = { text: query.text, name: query.name, arrayMode: query._arrayMode } if (values) { pipelineEntry.values = values } diff --git a/packages/pg/test/integration/client/pipelining-tests.js b/packages/pg/test/integration/client/pipelining-tests.js index 957047d7d..7f927d2b0 100644 --- a/packages/pg/test/integration/client/pipelining-tests.js +++ b/packages/pg/test/integration/client/pipelining-tests.js @@ -35,6 +35,21 @@ suite.test('pipeline with parameterized queries', async function () { 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 }) From c940d7c206c8545cb195df2ecde230d9ca0279c8 Mon Sep 17 00:00:00 2001 From: Nigro Simone Date: Wed, 12 Aug 2026 04:40:51 +0200 Subject: [PATCH 77/81] Fail pipelined queries when the connection dies instead of hanging (#3736) --- packages/pg-native/index.js | 27 +++++-- .../test/pipeline-connection-loss.js | 76 +++++++++++++++++++ packages/pg/lib/native/client.js | 12 ++- 3 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 packages/pg-native/test/pipeline-connection-loss.js diff --git a/packages/pg-native/index.js b/packages/pg-native/index.js index fafd66aaf..451daeb7d 100644 --- a/packages/pg-native/index.js +++ b/packages/pg-native/index.js @@ -386,8 +386,12 @@ Client.prototype._readPipelineResults = function (queries, cb) { const processResults = function () { if (!pq.consumeInput()) { - pq.exitPipelineMode() - return cb(new Error(pq.errorMessage() || 'Failed to consume input')) + // 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()) { @@ -395,8 +399,10 @@ Client.prototype._readPipelineResults = function (queries, cb) { // null between result groups in pipeline — try again if (pq.isBusy()) return // more data needed if (!pq.getResult()) { - // truly no more results — should not happen before all syncs - break + // 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')) } } @@ -436,7 +442,13 @@ Client.prototype._readPipelineResults = function (queries, cb) { } if (status === 'PGRES_PIPELINE_ABORTED') { - // Query skipped due to previous error in same sync group + // 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 } @@ -465,6 +477,11 @@ Client.prototype._readPipelineResults = function (queries, cb) { } 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() 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/lib/native/client.js b/packages/pg/lib/native/client.js index 2edfff720..9ec3c8c03 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -351,13 +351,21 @@ Client.prototype._pulsePipelinedQueryQueue = function () { self._pipelineInFlight = false if (err) { - // Total pipeline failure — error all queries + // 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._pulsePipelinedQueryQueue() + self._errorAllQueries(err) + self.emit('error', err) + self.emit('end') return } From 299148045f921060b5df91343ab4710d46674b08 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Aug 2026 19:41:23 -0700 Subject: [PATCH 78/81] Deprecate serializing invalid `Date`s (#3731) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: charmander <1889843+charmander@users.noreply.github.com> --- packages/pg/lib/utils.js | 10 ++++++++++ packages/pg/test/unit/utils-tests.js | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index 638b43970..4649405a8 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -1,9 +1,16 @@ 'use strict' const defaults = require('./defaults') +const nodeUtils = require('util') 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, '\\"') @@ -54,6 +61,9 @@ const prepareValue = function (val, seen) { return Buffer.from(val.buffer, val.byteOffset, val.byteLength) } if (isDate(val)) { + if (isNaN(val.getTime())) { + invalidDateDeprecationNotice() + } if (defaults.parseInputDatesAsUTC) { return dateToStringUTC(val) } else { diff --git a/packages/pg/test/unit/utils-tests.js b/packages/pg/test/unit/utils-tests.js index 5f75f6c2d..edb01f414 100644 --- a/packages/pg/test/unit/utils-tests.js +++ b/packages/pg/test/unit/utils-tests.js @@ -89,6 +89,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) From 0cef6afdf781e4cbe7eb5ac943df3c14b49c33de Mon Sep 17 00:00:00 2001 From: Nigro Simone Date: Wed, 12 Aug 2026 04:42:22 +0200 Subject: [PATCH 79/81] Reject portal based queries in pipeline mode instead of misrouting rows (#3737) --- packages/pg/lib/client.js | 18 ++++ .../client/pipeline-portal-tests.js | 83 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 packages/pg/test/integration/client/pipeline-portal-tests.js diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 7a2fc9a64..2b13c1de7 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -744,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) 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))) + }) +}) From 2b02f645687b8536f209aecc24f1b4bdb4c32d16 Mon Sep 17 00:00:00 2001 From: Dustin <85157729+GiHoon1123@users.noreply.github.com> Date: Wed, 12 Aug 2026 11:44:18 +0900 Subject: [PATCH 80/81] fix: avoid mutating query config (#3720) * fix: don't mutate the caller's query config object Fixes #2651. normalizeQueryConfig() wrote values/callback directly onto the object it was given instead of copying it first. Reusing the same config object across calls (callback style, then promise style) left a stale callback on it, so a later promise-style call would see query.callback already set, skip creating the promise, and silently return undefined while the real result went to the old callback instead. Copy the object before writing to it so the caller's config is never touched, and add regression tests for both the direct case and the callback-then-promise reuse scenario. * test: simplify query config comments * fix: preserve query config property access --- packages/pg/lib/utils.js | 10 +++++- .../pg/test/unit/client/simple-query-tests.js | 14 ++++++++ packages/pg/test/unit/utils-tests.js | 35 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index 4649405a8..ba51c82c8 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -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/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index efb705aa1..3e3918773 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -244,4 +244,18 @@ test('executing query', 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/utils-tests.js b/packages/pg/test/unit/utils-tests.js index edb01f414..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) From c9e57617bc92c2ded23a75345f50eadc527bd131 Mon Sep 17 00:00:00 2001 From: Clio Date: Sat, 15 Aug 2026 03:35:15 +0800 Subject: [PATCH 81/81] fix: support callback as second argument to `CloudflareSocket.write` (#3747) `Connection.end()` calls `write(data, callback)`. `CloudflareSocket.write` previously treated the callback as an encoding, so it never ran. --- packages/pg-cloudflare/src/index.ts | 10 +++++++--- packages/pg-esm-test/pg-cloudflare.test.js | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/pg-cloudflare/src/index.ts b/packages/pg-cloudflare/src/index.ts index 357131911..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) diff --git a/packages/pg-esm-test/pg-cloudflare.test.js b/packages/pg-esm-test/pg-cloudflare.test.js index c140f0bb1..75d1f9957 100644 --- a/packages/pg-esm-test/pg-cloudflare.test.js +++ b/packages/pg-esm-test/pg-cloudflare.test.js @@ -18,4 +18,23 @@ describe('pg-cloudflare', () => { 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 + }) })