From aedaa59afe6028fb1a13187695325e8dbacb2c30 Mon Sep 17 00:00:00 2001 From: Bluenix Date: Tue, 27 Jul 2021 16:40:32 +0200 Subject: [PATCH 001/261] Add support for using promises in Cursor methods (#2554) * Add similar promise variables to read() and close() as seen in query() * Add testing for promise specific usage * Simplify tests as no real callbacks are involved Removes usage of `done()` since we can end the test when we exit the function Co-Authored-By: Charmander <~@charmander.me> * Switch to let over var Co-authored-by: Charmander <~@charmander.me> --- packages/pg-cursor/index.js | 40 ++++++++++++++++------ packages/pg-cursor/test/promises.js | 51 +++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 packages/pg-cursor/test/promises.js diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 8e8552be8..b77fd5977 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -17,6 +17,7 @@ class Cursor extends EventEmitter { this._queue = [] this.state = 'initialized' this._result = new Result(this._conf.rowMode, this._conf.types) + this._Promise = this._conf.Promise || global.Promise this._cb = null this._rows = null this._portal = null @@ -198,6 +199,14 @@ class Cursor extends EventEmitter { } close(cb) { + let promise + + if (!cb) { + promise = new this._Promise((resolve, reject) => { + cb = (err) => (err ? reject(err) : resolve()) + }) + } + if (!this.connection || this.state === 'done') { if (cb) { return setImmediate(cb) @@ -213,23 +222,34 @@ class Cursor extends EventEmitter { cb() }) } + + // Return the promise (or undefined) + return promise } read(rows, cb) { - if (this.state === 'idle' || this.state === 'submitted') { - return this._getRows(rows, cb) - } - if (this.state === 'busy' || this.state === 'initialized') { - return this._queue.push([rows, cb]) - } - if (this.state === 'error') { - return setImmediate(() => cb(this._error)) + let promise + + if (!cb) { + promise = new this._Promise((resolve, reject) => { + cb = (err, rows) => (err ? reject(err) : resolve(rows)) + }) } - if (this.state === 'done') { - return setImmediate(() => cb(null, [])) + + if (this.state === 'idle' || this.state === 'submitted') { + this._getRows(rows, cb) + } else if (this.state === 'busy' || this.state === 'initialized') { + this._queue.push([rows, cb]) + } else if (this.state === 'error') { + setImmediate(() => cb(this._error)) + } else if (this.state === 'done') { + setImmediate(() => cb(null, [])) } else { throw new Error('Unknown state: ' + this.state) } + + // Return the promise (or undefined) + return promise } } diff --git a/packages/pg-cursor/test/promises.js b/packages/pg-cursor/test/promises.js new file mode 100644 index 000000000..7b36dab8f --- /dev/null +++ b/packages/pg-cursor/test/promises.js @@ -0,0 +1,51 @@ +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') + +const text = 'SELECT generate_series as num FROM generate_series(0, 5)' + +describe('cursor using promises', function () { + beforeEach(function (done) { + const client = (this.client = new pg.Client()) + client.connect(done) + + this.pgCursor = function (text, values) { + return client.query(new Cursor(text, values || [])) + } + }) + + afterEach(function () { + this.client.end() + }) + + it('resolve with result', async function () { + const cursor = this.pgCursor(text) + const res = await cursor.read(6) + assert.strictEqual(res.length, 6) + }) + + it('reject with error', function (done) { + const cursor = this.pgCursor('select asdfasdf') + cursor.read(1).error((err) => { + assert(err) + done() + }) + }) + + it('read multiple times', async function () { + const cursor = this.pgCursor(text) + let res + + res = await cursor.read(2) + assert.strictEqual(res.length, 2) + + res = await cursor.read(3) + assert.strictEqual(res.length, 3) + + res = await cursor.read(1) + assert.strictEqual(res.length, 1) + + res = await cursor.read(1) + assert.strictEqual(res.length, 0) + }) +}) From 684cd09bcecbf5ad5f451fdf608a3e9a9444524e Mon Sep 17 00:00:00 2001 From: Brian Crowell Date: Tue, 27 Jul 2021 11:29:07 -0500 Subject: [PATCH 002/261] Allow Node to exit if the pool is idle (#2568) Based on the suggestion from #2078. This adds ref/unref methods to the Connection and Client classes and then uses them to allow the process to exit if all of the connections in the pool are idle. This behavior is controlled by the allowExitOnIdle flag to the Pool constructor; it defaults to the old behavior. --- packages/pg-pool/index.js | 11 ++++++++ packages/pg-pool/test/idle-timeout-exit.js | 16 +++++++++++ packages/pg-pool/test/idle-timeout.js | 31 ++++++++++++++++++++++ packages/pg/lib/client.js | 8 ++++++ packages/pg/lib/connection.js | 8 ++++++ 5 files changed, 74 insertions(+) create mode 100644 packages/pg-pool/test/idle-timeout-exit.js diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 403d05a19..5557de5c0 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -83,6 +83,7 @@ class Pool extends EventEmitter { this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity + this.options.allowExitOnIdle = this.options.allowExitOnIdle || false this.log = this.options.log || function () {} this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -136,6 +137,7 @@ class Pool extends EventEmitter { const idleItem = this._idle.pop() clearTimeout(idleItem.timeoutId) const client = idleItem.client + client.ref() const idleListener = idleItem.idleListener return this._acquireClient(client, pendingItem, idleListener, false) @@ -323,6 +325,15 @@ class Pool extends EventEmitter { this.log('remove idle client') this._remove(client) }, this.options.idleTimeoutMillis) + + if (this.options.allowExitOnIdle) { + // allow Node to exit if this is all that's left + tid.unref() + } + } + + if (this.options.allowExitOnIdle) { + client.unref() } this._idle.push(new IdleItem(client, idleListener, tid)) diff --git a/packages/pg-pool/test/idle-timeout-exit.js b/packages/pg-pool/test/idle-timeout-exit.js new file mode 100644 index 000000000..1292634a8 --- /dev/null +++ b/packages/pg-pool/test/idle-timeout-exit.js @@ -0,0 +1,16 @@ +// This test is meant to be spawned from idle-timeout.js +if (module === require.main) { + const allowExitOnIdle = process.env.ALLOW_EXIT_ON_IDLE === '1' + const Pool = require('../index') + + const pool = new Pool({ idleTimeoutMillis: 200, ...(allowExitOnIdle ? { allowExitOnIdle: true } : {}) }) + pool.query('SELECT NOW()', (err, res) => console.log('completed first')) + pool.on('remove', () => { + console.log('removed') + done() + }) + + setTimeout(() => { + pool.query('SELECT * from generate_series(0, 1000)', (err, res) => console.log('completed second')) + }, 50) +} diff --git a/packages/pg-pool/test/idle-timeout.js b/packages/pg-pool/test/idle-timeout.js index fd9fba4a4..0bb097565 100644 --- a/packages/pg-pool/test/idle-timeout.js +++ b/packages/pg-pool/test/idle-timeout.js @@ -4,6 +4,8 @@ const expect = require('expect.js') const describe = require('mocha').describe const it = require('mocha').it +const { fork } = require('child_process') +const path = require('path') const Pool = require('../') @@ -84,4 +86,33 @@ describe('idle timeout', () => { return pool.end() }) ) + + it('unrefs the connections and timeouts so the program can exit when idle when the allowExitOnIdle option is set', function (done) { + const child = fork(path.join(__dirname, 'idle-timeout-exit.js'), [], { + silent: true, + env: { ...process.env, ALLOW_EXIT_ON_IDLE: '1' }, + }) + let result = '' + child.stdout.setEncoding('utf8') + child.stdout.on('data', (chunk) => (result += chunk)) + child.on('error', (err) => done(err)) + child.on('close', () => { + expect(result).to.equal('completed first\ncompleted second\n') + done() + }) + }) + + it('keeps old behavior when allowExitOnIdle option is not set', function (done) { + const child = fork(path.join(__dirname, 'idle-timeout-exit.js'), [], { + silent: true, + }) + let result = '' + child.stdout.setEncoding('utf8') + child.stdout.on('data', (chunk) => (result += chunk)) + child.on('error', (err) => done(err)) + child.on('close', () => { + expect(result).to.equal('completed first\ncompleted second\nremoved\n') + done() + }) + }) }) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 1e1e83374..589aa9f84 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -577,6 +577,14 @@ class Client extends EventEmitter { return result } + ref() { + this.connection.ref() + } + + unref() { + this.connection.unref() + } + end(cb) { this._ending = true diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 7d45de2b7..ebb2f099d 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -177,6 +177,14 @@ class Connection extends EventEmitter { this._send(syncBuffer) } + ref() { + this.stream.ref() + } + + unref() { + this.stream.unref() + } + end() { // 0x58 = 'X' this._ending = true From f824d74afe99b21de2681cd665e4cee74e769960 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 27 Jul 2021 11:35:55 -0500 Subject: [PATCH 003/261] Update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26e368ff9..5347e3557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ 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.7.0 + +- Add optional config to [pool](https://github.com/brianc/node-postgres/pull/2568) to allow process to exit if pool is idle. + +### pg-cursor@2.7.0 + +- Convert to [es6 class](https://github.com/brianc/node-postgres/pull/2553) +- Add support for promises [to cursor methods](https://github.com/brianc/node-postgres/pull/2554) + ### pg@8.6.0 - Better [SASL](https://github.com/brianc/node-postgres/pull/2436) error messages & more validation on bad configuration. From d8ce457e83146a960fee9328789142327b0c8f70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jul 2021 11:36:35 -0500 Subject: [PATCH 004/261] Bump handlebars from 4.7.6 to 4.7.7 (#2538) Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.7.6 to 4.7.7. - [Release notes](https://github.com/wycats/handlebars.js/releases) - [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md) - [Commits](https://github.com/wycats/handlebars.js/compare/v4.7.6...v4.7.7) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index e579f984e..3372de6a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3066,9 +3066,9 @@ growl@1.10.5: integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1, handlebars@^4.7.6: - version "4.7.6" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" - integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== dependencies: minimist "^1.2.5" neo-async "^2.6.0" @@ -6125,9 +6125,9 @@ typescript@^4.0.3: integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== uglify-js@^3.1.4: - version "3.11.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.11.1.tgz#32d274fea8aac333293044afd7f81409d5040d38" - integrity sha512-OApPSuJcxcnewwjSGGfWOjx3oix5XpmrK9Z2j0fTRlHGoZ49IU6kExfZTM0++fCArOOCet+vIfWwFHbvWqwp6g== + version "3.13.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.5.tgz#5d71d6dbba64cf441f32929b1efce7365bb4f113" + integrity sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw== uid-number@0.0.6: version "0.0.6" From 83aae778e8dcb3fb35a84de6667e21e0c8276a99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jul 2021 11:37:10 -0500 Subject: [PATCH 005/261] Bump ssri from 6.0.1 to 6.0.2 (#2531) Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/npm/ssri/releases) - [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md) - [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3372de6a5..ad4eed181 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5647,9 +5647,9 @@ sshpk@^1.7.0: tweetnacl "~0.14.0" ssri@^6.0.0, ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== dependencies: figgy-pudding "^3.5.1" From 0da7882f45d0c63d4bb310c7d137434ef4b22d18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jul 2021 11:42:04 -0500 Subject: [PATCH 006/261] Bump y18n from 4.0.0 to 4.0.1 (#2506) Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1. - [Release notes](https://github.com/yargs/y18n/releases) - [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md) - [Commits](https://github.com/yargs/y18n/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ad4eed181..e779f038c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6388,9 +6388,9 @@ xtend@^4.0.0, xtend@~4.0.1: integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + version "4.0.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" + integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.1.1" From 779803fbce195ae5610761606dcdcd78ca4cd439 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 27 Jul 2021 12:23:30 -0500 Subject: [PATCH 007/261] Add ref/unref noop to native client (#2581) * Add ref/unref noop to native client * Use promise.catch in test * Make partition test not flake on old node * Fix test flake on old node --- packages/pg-cursor/test/promises.js | 2 +- packages/pg/lib/native/client.js | 3 +++ .../integration/client/connection-timeout-tests.js | 11 ++++++----- .../integration/client/network-partition-tests.js | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/pg-cursor/test/promises.js b/packages/pg-cursor/test/promises.js index 7b36dab8f..1635a1a8b 100644 --- a/packages/pg-cursor/test/promises.js +++ b/packages/pg-cursor/test/promises.js @@ -26,7 +26,7 @@ describe('cursor using promises', function () { it('reject with error', function (done) { const cursor = this.pgCursor('select asdfasdf') - cursor.read(1).error((err) => { + cursor.read(1).catch((err) => { assert(err) done() }) diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 6cf800d0e..d1faeb3d8 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -285,6 +285,9 @@ Client.prototype.cancel = function (query) { } } +Client.prototype.ref = function () {} +Client.prototype.unref = function () {} + Client.prototype.setTypeParser = function (oid, format, parseFn) { return this._types.setTypeParser(oid, format, parseFn) } diff --git a/packages/pg/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js index 843fa95bb..6b99698bc 100644 --- a/packages/pg/test/integration/client/connection-timeout-tests.js +++ b/packages/pg/test/integration/client/connection-timeout-tests.js @@ -13,7 +13,7 @@ const options = { database: 'existing', } -const serverWithConnectionTimeout = (timeout, callback) => { +const serverWithConnectionTimeout = (port, timeout, callback) => { const sockets = new Set() const server = net.createServer((socket) => { @@ -47,11 +47,11 @@ const serverWithConnectionTimeout = (timeout, callback) => { } } - server.listen(options.port, options.host, () => callback(closeServer)) + server.listen(port, options.host, () => callback(closeServer)) } suite.test('successful connection', (done) => { - serverWithConnectionTimeout(0, (closeServer) => { + serverWithConnectionTimeout(options.port, 0, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have connected successfully but it did not.') }, 3000) @@ -67,12 +67,13 @@ suite.test('successful connection', (done) => { }) suite.test('expired connection timeout', (done) => { - serverWithConnectionTimeout(options.connectionTimeoutMillis * 2, (closeServer) => { + const opts = { ...options, port: 54322 } + serverWithConnectionTimeout(opts.port, opts.connectionTimeoutMillis * 2, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have emitted an error but it did not.') }, 3000) - const client = new helper.Client(options) + const client = new helper.Client(opts) client .connect() .then(() => client.end()) diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index 993396401..2ac100dff 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -11,6 +11,7 @@ var Server = function (response) { this.response = response } +let port = 54321 Server.prototype.start = function (cb) { // this is our fake postgres server // it responds with our specified response immediatley after receiving every buffer @@ -39,7 +40,7 @@ Server.prototype.start = function (cb) { }.bind(this) ) - var port = 54321 + port = port + 1 var options = { host: 'localhost', From f3b0ee4c09cd01e37baf580d72dffc43edcc29f3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 27 Jul 2021 12:41:17 -0500 Subject: [PATCH 008/261] Publish - pg-cursor@2.7.0 - pg-pool@3.4.0 - pg-query-stream@4.2.0 - pg@8.7.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 5607ea955..be43e15f6 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.6.0", + "version": "2.7.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.6.0" + "pg": "^8.7.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index b92e7df90..e23191828 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.3.0", + "version": "3.4.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index d01b18d86..63697b387 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.1.0", + "version": "4.2.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.6.0", + "pg": "^8.7.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.6.0" + "pg-cursor": "^2.7.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index af71629f3..10c941466 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.6.0", + "version": "8.7.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.3.0", + "pg-pool": "^3.4.0", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 86d31a6fad6ee05facd85bc5f83ca081ebe725b7 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 27 Jul 2021 17:27:05 -0500 Subject: [PATCH 009/261] Only call client.ref if it exists * Only call client.ref if it exists. Fixes #2582 * Make test requiring port less flakey * Bump port range Fixes #2582 Fixes #2584 --- packages/pg-pool/index.js | 2 +- packages/pg/test/integration/client/connection-timeout-tests.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 5557de5c0..48bf5c788 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -137,7 +137,7 @@ class Pool extends EventEmitter { const idleItem = this._idle.pop() clearTimeout(idleItem.timeoutId) const client = idleItem.client - client.ref() + client.ref && client.ref() const idleListener = idleItem.idleListener return this._acquireClient(client, pendingItem, idleListener, false) diff --git a/packages/pg/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js index 6b99698bc..7a3ee4447 100644 --- a/packages/pg/test/integration/client/connection-timeout-tests.js +++ b/packages/pg/test/integration/client/connection-timeout-tests.js @@ -7,7 +7,7 @@ const suite = new helper.Suite() const options = { host: 'localhost', - port: 54321, + port: Math.floor(Math.random() * 2000) + 2000, connectionTimeoutMillis: 2000, user: 'not', database: 'existing', From 92b4d37926c276d343bfe56447ff6f526af757cf Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 27 Jul 2021 17:33:19 -0500 Subject: [PATCH 010/261] Publish - pg-cursor@2.7.1 - pg-pool@3.4.1 - pg-query-stream@4.2.1 - pg@8.7.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index be43e15f6..b85000aba 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.0", + "version": "2.7.1", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.7.0" + "pg": "^8.7.1" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index e23191828..d479ae55f 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.4.0", + "version": "3.4.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 63697b387..5f332e8cd 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.2.0", + "version": "4.2.1", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.7.0", + "pg": "^8.7.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.7.0" + "pg-cursor": "^2.7.1" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 10c941466..930a7d928 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.7.0", + "version": "8.7.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.4.0", + "pg-pool": "^3.4.1", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 98cd59e3e7bd14f77d5f31dbc4115a9de9d26db1 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 29 Jul 2021 17:17:15 -0500 Subject: [PATCH 011/261] Return promise on cursor end (#2589) * Return promise on cursor end * Remove redudant if --- packages/pg-cursor/index.js | 15 +++++---------- packages/pg-cursor/test/close.js | 11 +++++++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index b77fd5977..ddfb2b4ca 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -208,20 +208,15 @@ class Cursor extends EventEmitter { } if (!this.connection || this.state === 'done') { - if (cb) { - return setImmediate(cb) - } else { - return - } + setImmediate(cb) + return promise } this._closePortal() this.state = 'done' - if (cb) { - this.connection.once('readyForQuery', function () { - cb() - }) - } + this.connection.once('readyForQuery', function () { + cb() + }) // Return the promise (or undefined) return promise diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index e63512abd..b34161a17 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -23,6 +23,17 @@ describe('close', function () { }) }) + it('can close a finished cursor a promise', function (done) { + const cursor = new Cursor(text) + this.client.query(cursor) + cursor.read(100, (err) => { + assert.ifError(err) + cursor.close().then(() => { + this.client.query('SELECT NOW()', done) + }) + }) + }) + it('closes cursor early', function (done) { const cursor = new Cursor(text) this.client.query(cursor) From 947ccee346f0d598e135548e1e4936a9a008fc6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Aug 2021 00:59:44 +0000 Subject: [PATCH 012/261] Bump tar from 4.4.13 to 4.4.15 (#2592) Bumps [tar](https://github.com/npm/node-tar) from 4.4.13 to 4.4.15. - [Release notes](https://github.com/npm/node-tar/releases) - [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-tar/compare/v4.4.13...v4.4.15) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e779f038c..bc5330a1d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5868,9 +5868,9 @@ table@^5.2.3: string-width "^3.0.0" tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + version "4.4.15" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.15.tgz#3caced4f39ebd46ddda4d6203d48493a919697f8" + integrity sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" From 3aba3794cf7d8749c19081314a875af61efee61e Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 17 Nov 2021 10:02:22 -0600 Subject: [PATCH 013/261] Use github actions for CI (#2654) This is the initial port to github actions. Still pending are the SSL and client SSL cert tests which are currently being skipped. But perfect is the enemy of the good here, and having no CI because travis-ci keeps not working is unacceptable. --- .github/workflows/ci.yml | 31 ++ .../pg-query-stream/test/async-iterator.ts | 15 +- .../connection-parameters/creation-tests.js | 407 +++++++++--------- 3 files changed, 251 insertions(+), 202 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..13c6c77eb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: CI + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:11 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: ci_db_test + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + strategy: + matrix: + node: ['8', '10', '12', '14', '16', '17'] + name: Node ${{ matrix.node }} + steps: + - uses: actions/checkout@v2 + - name: Setup node + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node }} + cache: yarn + - run: yarn install + # TODO(bmc): get ssl tests working in ci + - run: PGTESTNOSSL=true PGUSER=postgres PGPASSWORD=postgres PGDATABASE=ci_db_test yarn test diff --git a/packages/pg-query-stream/test/async-iterator.ts b/packages/pg-query-stream/test/async-iterator.ts index 06539d124..d47ede164 100644 --- a/packages/pg-query-stream/test/async-iterator.ts +++ b/packages/pg-query-stream/test/async-iterator.ts @@ -88,11 +88,16 @@ if (!process.version.startsWith('v8')) { rows.push(row) break } - for await (const row of stream) { - rows.push(row) - } - for await (const row of stream) { - rows.push(row) + + try { + for await (const row of stream) { + rows.push(row) + } + for await (const row of stream) { + rows.push(row) + } + } catch (e) { + // swallow error - node 17 throws if stream is aborted } assert.strictEqual(rows.length, 1) client.release() diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 633b0eaf4..40381e788 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -1,15 +1,18 @@ 'use strict' -var helper = require('../test-helper') -var assert = require('assert') -var ConnectionParameters = require('../../../lib/connection-parameters') -var defaults = require('../../../lib').defaults +const helper = require('../test-helper') +const assert = require('assert') +const ConnectionParameters = require('../../../lib/connection-parameters') +const defaults = require('../../../lib').defaults +const dns = require('dns') // clear process.env for (var key in process.env) { delete process.env[key] } -test('ConnectionParameters construction', function () { +const suite = new helper.Suite() + +suite.test('ConnectionParameters construction', function () { assert.ok(new ConnectionParameters(), 'with null config') assert.ok(new ConnectionParameters({ user: 'asdf' }), 'with config object') assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string') @@ -33,13 +36,13 @@ var compare = function (actual, expected, type) { ) } -test('ConnectionParameters initializing from defaults', function () { +suite.test('ConnectionParameters initializing from defaults', function () { var subject = new ConnectionParameters() compare(subject, defaults, 'defaults') assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from defaults with connectionString set', function () { +suite.test('ConnectionParameters initializing from defaults with connectionString set', function () { var config = { user: 'brians-are-the-best', database: 'scoobysnacks', @@ -62,7 +65,7 @@ test('ConnectionParameters initializing from defaults with connectionString set' compare(subject, config, 'defaults-connectionString') }) -test('ConnectionParameters initializing from config', function () { +suite.test('ConnectionParameters initializing from config', function () { var config = { user: 'brian', database: 'home', @@ -83,7 +86,7 @@ test('ConnectionParameters initializing from config', function () { assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from config and config.connectionString', function () { +suite.test('ConnectionParameters initializing from config and config.connectionString', function () { var subject1 = new ConnectionParameters({ connectionString: 'postgres://test@host/db', }) @@ -105,31 +108,31 @@ test('ConnectionParameters initializing from config and config.connectionString' assert.equal(subject4.ssl, true) }) -test('escape spaces if present', function () { +suite.test('escape spaces if present', function () { var subject = new ConnectionParameters('postgres://localhost/post gres') assert.equal(subject.database, 'post gres') }) -test('do not double escape spaces', function () { +suite.test('do not double escape spaces', function () { var subject = new ConnectionParameters('postgres://localhost/post%20gres') assert.equal(subject.database, 'post gres') }) -test('initializing with unix domain socket', function () { +suite.test('initializing with unix domain socket', function () { var subject = new ConnectionParameters('/var/run/') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/var/run/') assert.equal(subject.database, defaults.user) }) -test('initializing with unix domain socket and a specific database, the simple way', function () { +suite.test('initializing with unix domain socket and a specific database, the simple way', function () { var subject = new ConnectionParameters('/var/run/ mydb') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/var/run/') assert.equal(subject.database, 'mydb') }) -test('initializing with unix domain socket, the health way', function () { +suite.test('initializing with unix domain socket, the health way', function () { var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/some path/') @@ -137,7 +140,7 @@ test('initializing with unix domain socket, the health way', function () { assert.equal(subject.client_encoding, 'utf8') }) -test('initializing with unix domain socket, the escaped health way', function () { +suite.test('initializing with unix domain socket, the escaped health way', function () { var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/some path/') @@ -145,201 +148,211 @@ test('initializing with unix domain socket, the escaped health way', function () assert.equal(subject.client_encoding, 'utf8') }) -test('libpq connection string building', function () { - var checkForPart = function (array, part) { - assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part) - } +var checkForPart = function (array, part) { + assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part) +} - test('builds simple string', function () { - var config = { - user: 'brian', - password: 'xyz', - port: 888, - host: 'localhost', - database: 'bam', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "password='xyz'") - checkForPart(parts, "port='888'") - checkForPart(parts, "hostaddr='127.0.0.1'") - checkForPart(parts, "dbname='bam'") - }) - ) +const getDNSHost = async function (host) { + return new Promise((resolve, reject) => { + dns.lookup(host, (err, addresses) => { + err ? reject(err) : resolve(addresses) + }) }) +} - test('builds dns string', function () { - var config = { - user: 'brian', - password: 'asdf', - port: 5432, - host: 'localhost', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "hostaddr='127.0.0.1'") - }) - ) +suite.testAsync('builds simple string', async function () { + var config = { + user: 'brian', + password: 'xyz', + port: 888, + host: 'localhost', + database: 'bam', + } + var subject = new ConnectionParameters(config) + const dnsHost = await getDNSHost(config.host) + return new Promise((resolve) => { + subject.getLibpqConnectionString(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "password='xyz'") + checkForPart(parts, "port='888'") + checkForPart(parts, `hostaddr='${dnsHost}'`) + checkForPart(parts, "dbname='bam'") + resolve() + }) }) +}) - test('error when dns fails', function () { - var config = { - user: 'brian', - password: 'asf', - port: 5432, - host: 'asdlfkjasldfkksfd#!$!!!!..com', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert.ok(err) - assert.isNull(constring) - }) - ) +suite.test('builds dns string', async function () { + var config = { + user: 'brian', + password: 'asdf', + port: 5432, + host: 'localhost', + } + var subject = new ConnectionParameters(config) + const dnsHost = await getDNSHost(config.host) + return new Promise((resolve) => { + subject.getLibpqConnectionString(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, `hostaddr='${dnsHost}'`) + resolve() + }) }) +}) - test('connecting to unix domain socket', function () { - var config = { - user: 'brian', - password: 'asf', - port: 5432, - host: '/tmp/', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "host='/tmp/'") - }) - ) - }) +suite.test('error when dns fails', function () { + var config = { + user: 'brian', + password: 'asf', + port: 5432, + host: 'asdlfkjasldfkksfd#!$!!!!..com', + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert.ok(err) + assert.isNull(constring) + }) + ) +}) - test('config contains quotes and backslashes', function () { - var config = { - user: 'not\\brian', - password: "bad'chars", - port: 5432, - host: '/tmp/', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='not\\\\brian'") - checkForPart(parts, "password='bad\\'chars'") - }) - ) - }) +suite.test('connecting to unix domain socket', function () { + var config = { + user: 'brian', + password: 'asf', + port: 5432, + host: '/tmp/', + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "host='/tmp/'") + }) + ) +}) - test('encoding can be specified by config', function () { - var config = { - client_encoding: 'utf-8', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "client_encoding='utf-8'") - }) - ) - }) +suite.test('config contains quotes and backslashes', function () { + var config = { + user: 'not\\brian', + password: "bad'chars", + port: 5432, + host: '/tmp/', + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='not\\\\brian'") + checkForPart(parts, "password='bad\\'chars'") + }) + ) +}) - test('password contains < and/or > characters', function () { - var sourceConfig = { - user: 'brian', - password: 'helloe', - port: 5432, - host: 'localhost', - database: 'postgres', - } - var connectionString = - 'postgres://' + - sourceConfig.user + - ':' + - sourceConfig.password + - '@' + - sourceConfig.host + - ':' + - sourceConfig.port + - '/' + - sourceConfig.database - var subject = new ConnectionParameters(connectionString) - assert.equal(subject.password, sourceConfig.password) - }) +suite.test('encoding can be specified by config', function () { + var config = { + client_encoding: 'utf-8', + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "client_encoding='utf-8'") + }) + ) +}) - test('username or password contains weird characters', function () { - var defaults = require('../../../lib/defaults') - defaults.ssl = true - var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' - var subject = new ConnectionParameters(strang) - assert.equal(subject.user, 'my f%irst name') - assert.equal(subject.password, 'is&%awesome!') - assert.equal(subject.host, 'localhost') - assert.equal(subject.ssl, true) - }) +suite.test('password contains < and/or > characters', function () { + var sourceConfig = { + user: 'brian', + password: 'helloe', + port: 5432, + host: 'localhost', + database: 'postgres', + } + var connectionString = + 'postgres://' + + sourceConfig.user + + ':' + + sourceConfig.password + + '@' + + sourceConfig.host + + ':' + + sourceConfig.port + + '/' + + sourceConfig.database + var subject = new ConnectionParameters(connectionString) + assert.equal(subject.password, sourceConfig.password) +}) - test('url is properly encoded', function () { - var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' - var subject = new ConnectionParameters(encoded) - assert.equal(subject.user, 'bi%na%%ry ') - assert.equal(subject.password, 's@f#') - assert.equal(subject.host, 'localhost') - assert.equal(subject.database, ' u%20rl') - }) +suite.test('username or password contains weird characters', function () { + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' + var subject = new ConnectionParameters(strang) + assert.equal(subject.user, 'my f%irst name') + assert.equal(subject.password, 'is&%awesome!') + assert.equal(subject.host, 'localhost') + assert.equal(subject.ssl, true) +}) - test('ssl is set on client', function () { - var Client = require('../../../lib/client') - var defaults = require('../../../lib/defaults') - defaults.ssl = true - var c = new Client('postgres://user@password:host/database') - assert(c.ssl, 'Client should have ssl enabled via defaults') - }) +suite.test('url is properly encoded', function () { + var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' + var subject = new ConnectionParameters(encoded) + assert.equal(subject.user, 'bi%na%%ry ') + assert.equal(subject.password, 's@f#') + assert.equal(subject.host, 'localhost') + assert.equal(subject.database, ' u%20rl') +}) - test('coercing string "true" to boolean', function () { - const subject = new ConnectionParameters({ ssl: 'true' }) - assert.strictEqual(subject.ssl, true) - }) +suite.test('ssl is set on client', function () { + var Client = require('../../../lib/client') + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var c = new Client('postgres://user@password:host/database') + assert(c.ssl, 'Client should have ssl enabled via defaults') +}) - test('ssl is set on client', function () { - var sourceConfig = { - user: 'brian', - password: 'helloe', - port: 5432, - host: 'localhost', - database: 'postgres', - ssl: { - sslmode: 'verify-ca', - sslca: '/path/ca.pem', - sslkey: '/path/cert.key', - sslcert: '/path/cert.crt', - sslrootcert: '/path/root.crt', - }, - } - var Client = require('../../../lib/client') - var defaults = require('../../../lib/defaults') - defaults.ssl = true - var c = new ConnectionParameters(sourceConfig) - c.getLibpqConnectionString( - assert.calls(function (err, pgCString) { - assert(!err) - assert.equal( - pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1, - true, - 'libpqConnectionString should contain sslrootcert' - ) - }) - ) - }) +suite.test('coercing string "true" to boolean', function () { + const subject = new ConnectionParameters({ ssl: 'true' }) + assert.strictEqual(subject.ssl, true) +}) + +suite.test('ssl is set on client', function () { + var sourceConfig = { + user: 'brian', + password: 'helloe', + port: 5432, + host: 'localhost', + database: 'postgres', + ssl: { + sslmode: 'verify-ca', + sslca: '/path/ca.pem', + sslkey: '/path/cert.key', + sslcert: '/path/cert.crt', + sslrootcert: '/path/root.crt', + }, + } + var Client = require('../../../lib/client') + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var c = new ConnectionParameters(sourceConfig) + c.getLibpqConnectionString( + assert.calls(function (err, pgCString) { + assert(!err) + assert.equal( + pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1, + true, + 'libpqConnectionString should contain sslrootcert' + ) + }) + ) }) From b0bd1c32f1f415adab3a3b25379a9cb3236ebd84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Nov 2021 11:02:04 -0600 Subject: [PATCH 014/261] Bump tar from 4.4.15 to 4.4.19 (#2604) Bumps [tar](https://github.com/npm/node-tar) from 4.4.15 to 4.4.19. - [Release notes](https://github.com/npm/node-tar/releases) - [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-tar/compare/v4.4.15...v4.4.19) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/yarn.lock b/yarn.lock index bc5330a1d..d2c7f6f23 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1682,7 +1682,7 @@ chokidar@3.3.0: optionalDependencies: fsevents "~2.1.1" -chownr@^1.1.1, chownr@^1.1.2: +chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -2807,7 +2807,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: +fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== @@ -4124,7 +4124,7 @@ minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: +minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== @@ -4132,7 +4132,7 @@ minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.2.1: +minizlib@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== @@ -4175,7 +4175,7 @@ mkdirp@*: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@0.5.5, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.5, mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -5368,7 +5368,7 @@ rxjs@^6.4.0: dependencies: tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5868,17 +5868,17 @@ table@^5.2.3: string-width "^3.0.0" tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: - version "4.4.15" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.15.tgz#3caced4f39ebd46ddda4d6203d48493a919697f8" - integrity sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA== + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" temp-dir@^1.0.0: version "1.0.0" @@ -6392,7 +6392,7 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== From 97eea2d7a4453645e44129378215f88dff371a08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Nov 2021 09:38:43 -0600 Subject: [PATCH 015/261] Bump path-parse from 1.0.6 to 1.0.7 (#2595) Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7. - [Release notes](https://github.com/jbgutierrez/path-parse/releases) - [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7) --- updated-dependencies: - dependency-name: path-parse dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d2c7f6f23..1ec815582 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4793,9 +4793,9 @@ path-key@^3.1.0: integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^1.0.0: version "1.1.0" From 2c3adf25f94358defb84f14ca50f6873a3340618 Mon Sep 17 00:00:00 2001 From: Steffen Weidenhaus Date: Fri, 17 Dec 2021 17:15:26 +1100 Subject: [PATCH 016/261] Update README.md (#2671) Change `name` to `now` for time column --- packages/pg-pool/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-pool/README.md b/packages/pg-pool/README.md index c6d7e9287..b5f20bae9 100644 --- a/packages/pg-pool/README.md +++ b/packages/pg-pool/README.md @@ -136,7 +136,7 @@ because its so common to just run a query and return the client to the pool afte var pool = new Pool() var time = await pool.query('SELECT NOW()') var name = await pool.query('select $1::text as name', ['brianc']) -console.log(name.rows[0].name, 'says hello at', time.rows[0].name) +console.log(name.rows[0].name, 'says hello at', time.rows[0].now) ``` you can also use a callback here if you'd like: From 392a7f4a66d111cc4e9fd14253f09215441eed98 Mon Sep 17 00:00:00 2001 From: darkgl0w <31093081+darkgl0w@users.noreply.github.com> Date: Fri, 17 Dec 2021 07:21:35 +0100 Subject: [PATCH 017/261] chore (ci): add macOS and Windows to the CI OS matrix (#2657) * chore (ci): add macOS and Windows to the CI OS matrix * chore (ci): fix macOS runner name --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13c6c77eb..aa0a956b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,8 @@ jobs: strategy: matrix: node: ['8', '10', '12', '14', '16', '17'] - name: Node ${{ matrix.node }} + os: [ubuntu-latest, windows-latest, macos-latest] + name: Node.js ${{ matrix.node }} (${{ matrix.os }}) steps: - uses: actions/checkout@v2 - name: Setup node From 1f7b8cb6fa000af11bda84c1961c7252b34b8ee9 Mon Sep 17 00:00:00 2001 From: Andrew Lam <32132177+awhlam@users.noreply.github.com> Date: Sun, 16 Jan 2022 12:40:34 -0800 Subject: [PATCH 018/261] Fix markdown for n8n.io sponsor link (#2685) --- SPONSORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPONSORS.md b/SPONSORS.md index 9d7d314dd..453d11465 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -11,7 +11,7 @@ node-postgres is made possible by the helpful contributors from the community as - [Dataform](https://dataform.co/) - [Eaze](https://www.eaze.com/) - [simpleanalytics](https://simpleanalytics.com/) -- [n8n.io]https://n8n.io/ +- [n8n.io](https://n8n.io/) # Supporters From a09412c603215f7d8e07344b45105d7eac230b4d Mon Sep 17 00:00:00 2001 From: darkgl0w <31093081+darkgl0w@users.noreply.github.com> Date: Thu, 27 Jan 2022 00:20:11 +0100 Subject: [PATCH 019/261] chore (ci): trigger a CI run on PR events (#2681) --- .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 aa0a956b2..98ea909f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ name: CI -on: [push] +on: [push, pull_request] jobs: build: From f3ff3e2d1f60a007e46a3ee5b711aaaa232100c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:34:10 -0600 Subject: [PATCH 020/261] Bump node-fetch from 2.6.1 to 2.6.7 (#2694) Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7. - [Release notes](https://github.com/node-fetch/node-fetch/releases) - [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7) --- updated-dependencies: - dependency-name: node-fetch dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1ec815582..4c5a25507 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4323,9 +4323,11 @@ node-fetch-npm@^2.0.2: safe-buffer "^5.1.1" node-fetch@^2.5.0, node-fetch@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" node-gyp@^5.0.2: version "5.1.1" @@ -6006,6 +6008,11 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + traverser@0.0.x: version "0.0.5" resolved "https://registry.yarnpkg.com/traverser/-/traverser-0.0.5.tgz#c66f38c456a0c21a88014b1223580c7ebe0631eb" @@ -6263,11 +6270,24 @@ wcwidth@^1.0.0: dependencies: defaults "^1.0.3" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" From 998f57324411ad6f53a8e205cbc1df6fcfc742cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:34:36 -0600 Subject: [PATCH 021/261] Bump trim-off-newlines from 1.0.1 to 1.0.3 (#2695) Bumps [trim-off-newlines](https://github.com/stevemao/trim-off-newlines) from 1.0.1 to 1.0.3. - [Release notes](https://github.com/stevemao/trim-off-newlines/releases) - [Commits](https://github.com/stevemao/trim-off-newlines/compare/v1.0.1...v1.0.3) --- updated-dependencies: - dependency-name: trim-off-newlines dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4c5a25507..1cb44de2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6043,9 +6043,9 @@ trim-newlines@^3.0.0: integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== trim-off-newlines@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" - integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= + version "1.0.3" + resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.3.tgz#8df24847fcb821b0ab27d58ab6efec9f2fe961a1" + integrity sha512-kh6Tu6GbeSNMGfrrZh6Bb/4ZEHV1QlB4xNDBeog8Y9/QwFlKTRyWvY3Fs9tRDAMZliVUwieMgEdIeL/FtqjkJg== ts-node@^8.5.4: version "8.10.2" From 5508c0ee6bc751ea2474202d12fb36b4f21089a3 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Fri, 28 Jan 2022 19:59:45 +0100 Subject: [PATCH 022/261] fix: Prevent closing the portal twice (#2609) Fixes brianc/node-postgres#2119 --- packages/pg-cursor/index.js | 5 ++++- packages/pg-query-stream/test/async-iterator.ts | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index ddfb2b4ca..9bbda641a 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -86,6 +86,8 @@ class Cursor extends EventEmitter { } _closePortal() { + if (this.state === 'done') return + // because we opened a named portal to stream results // we need to close the same named portal. Leaving a named portal // open can lock tables for modification if inside a transaction. @@ -97,6 +99,8 @@ class Cursor extends EventEmitter { if (this.state !== 'error') { this.connection.sync() } + + this.state = 'done' } handleRowDescription(msg) { @@ -213,7 +217,6 @@ class Cursor extends EventEmitter { } this._closePortal() - this.state = 'done' this.connection.once('readyForQuery', function () { cb() }) diff --git a/packages/pg-query-stream/test/async-iterator.ts b/packages/pg-query-stream/test/async-iterator.ts index d47ede164..e2f8a7552 100644 --- a/packages/pg-query-stream/test/async-iterator.ts +++ b/packages/pg-query-stream/test/async-iterator.ts @@ -117,5 +117,17 @@ if (!process.version.startsWith('v8')) { client.release() await pool.end() }) + + it('supports breaking with low watermark', async function () { + const pool = new pg.Pool({ max: 1 }) + const client = await pool.connect() + + for await (const _ of client.query(new QueryStream('select TRUE', [], { highWaterMark: 1 }))) break + for await (const _ of client.query(new QueryStream('select TRUE', [], { highWaterMark: 1 }))) break + for await (const _ of client.query(new QueryStream('select TRUE', [], { highWaterMark: 1 }))) break + + client.release() + await pool.end() + }) }) } From 8392918d7bdac88830c3d60922b6f7bb17331aae Mon Sep 17 00:00:00 2001 From: ChrisWritable <50638920+ChrisWritable@users.noreply.github.com> Date: Fri, 28 Jan 2022 15:17:48 -0800 Subject: [PATCH 023/261] Add connection lifetime limit option and tests (#2698) Co-authored-by: ChrisG0x20 --- packages/pg-pool/index.js | 27 +++++++++++++ packages/pg-pool/test/lifetime-timeout.js | 46 +++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 packages/pg-pool/test/lifetime-timeout.js diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 48bf5c788..46d2aab0c 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -84,6 +84,7 @@ class Pool extends EventEmitter { this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity this.options.allowExitOnIdle = this.options.allowExitOnIdle || false + this.options.maxLifetimeSeconds = this.options.maxLifetimeSeconds || 0 this.log = this.options.log || function () {} this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -94,6 +95,7 @@ class Pool extends EventEmitter { this._clients = [] this._idle = [] + this._expired = new WeakSet() this._pendingQueue = [] this._endCallback = undefined this.ending = false @@ -123,6 +125,7 @@ class Pool extends EventEmitter { } return } + // if we don't have any waiting, do nothing if (!this._pendingQueue.length) { this.log('no queued requests') @@ -248,6 +251,17 @@ class Pool extends EventEmitter { } else { this.log('new client connected') + if (this.options.maxLifetimeSeconds !== 0) { + 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) + } + return this._acquireClient(client, pendingItem, idleListener, true) } }) @@ -318,6 +332,15 @@ class Pool extends EventEmitter { return } + const isExpired = this._expired.has(client) + if (isExpired) { + this.log('remove expired client') + this._expired.delete(client) + this._remove(client) + this._pulseQueue() + return + } + // idle timeout let tid if (this.options.idleTimeoutMillis) { @@ -414,6 +437,10 @@ class Pool extends EventEmitter { return this._idle.length } + get expiredCount() { + return this._clients.reduce((acc, client) => acc + (this._expired.has(client) ? 1 : 0), 0) + } + get totalCount() { return this._clients.length } diff --git a/packages/pg-pool/test/lifetime-timeout.js b/packages/pg-pool/test/lifetime-timeout.js new file mode 100644 index 000000000..986161625 --- /dev/null +++ b/packages/pg-pool/test/lifetime-timeout.js @@ -0,0 +1,46 @@ +'use strict' +const co = require('co') +const expect = require('expect.js') + +const describe = require('mocha').describe +const it = require('mocha').it +const path = require('path') + +const Pool = require('../') + +describe('lifetime timeout', () => { + it('connection lifetime should expire and remove the client', (done) => { + 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() + }) + }) + it('connection lifetime should expire and remove the client after the client is done working', (done) => { + const pool = new Pool({ maxLifetimeSeconds: 1 }) + pool.query('SELECT pg_sleep(1.01)') + pool.on('remove', () => { + console.log('expired while busy - on-remove event') + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + done() + }) + }) + it('can remove expired clients and recreate them', + co.wrap(function* () { + const pool = new Pool({ maxLifetimeSeconds: 1 }) + let query = pool.query('SELECT pg_sleep(1)') + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(1) + yield query + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + yield pool.query('SELECT NOW()') + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(1) + }) + ) +}) From e4115854cb65d212f4ea2f9cb835b6a6bd953c38 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:20:51 -0600 Subject: [PATCH 024/261] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5347e3557..4bc9e0594 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.8.0 + +- Add connection [lifetime limit](https://github.com/brianc/node-postgres/pull/2698) config option. + ### pg@8.7.0 - Add optional config to [pool](https://github.com/brianc/node-postgres/pull/2568) to allow process to exit if pool is idle. From 6849cc686855d0399c847f5e3d31cb0c56ae59e0 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:21:57 -0600 Subject: [PATCH 025/261] Publish - pg-cursor@2.7.2 - pg-pool@3.5.0 - pg-query-stream@4.2.2 - pg@8.7.2 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index b85000aba..feb3513fd 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.1", + "version": "2.7.2", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.7.1" + "pg": "^8.7.2" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index d479ae55f..0beba3da2 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.4.1", + "version": "3.5.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 5f332e8cd..f2df775a1 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.2.1", + "version": "4.2.2", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.7.1", + "pg": "^8.7.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.7.1" + "pg-cursor": "^2.7.2" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 930a7d928..3c92052b1 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.7.1", + "version": "8.7.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.4.1", + "pg-pool": "^3.5.0", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From edf1a864d63d00e83866d80de38ab1a44d004d38 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:22:23 -0600 Subject: [PATCH 026/261] Fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bc9e0594..72599c724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ 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.8.0 +### pg-pool@3.5.0 - Add connection [lifetime limit](https://github.com/brianc/node-postgres/pull/2698) config option. From 9a61e9ac587829d7dc486f2da8500708c5d1a8b0 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:27:51 -0600 Subject: [PATCH 027/261] Format with prettier --- packages/pg-pool/index.js | 9 +++++++-- packages/pg-pool/test/lifetime-timeout.js | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 46d2aab0c..0d7314eb6 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -255,9 +255,14 @@ class Pool extends EventEmitter { setTimeout(() => { this.log('ending client due to expired lifetime') this._expired.add(client) - const idleIndex = this._idle.findIndex(idleItem => idleItem.client === 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._acquireClient( + client, + new PendingItem((err, client, clientRelease) => clientRelease()), + idleListener, + false + ) } }, this.options.maxLifetimeSeconds * 1000) } diff --git a/packages/pg-pool/test/lifetime-timeout.js b/packages/pg-pool/test/lifetime-timeout.js index 986161625..fddd5ff00 100644 --- a/packages/pg-pool/test/lifetime-timeout.js +++ b/packages/pg-pool/test/lifetime-timeout.js @@ -29,7 +29,8 @@ describe('lifetime timeout', () => { done() }) }) - it('can remove expired clients and recreate them', + it( + 'can remove expired clients and recreate them', co.wrap(function* () { const pool = new Pool({ maxLifetimeSeconds: 1 }) let query = pool.query('SELECT pg_sleep(1)') From 4fa7ee891a456168a75695ac026792136f16577f Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:28:01 -0600 Subject: [PATCH 028/261] Publish - pg-cursor@2.7.3 - pg-pool@3.5.1 - pg-query-stream@4.2.3 - pg@8.7.3 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index feb3513fd..6104c9557 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.2", + "version": "2.7.3", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.7.2" + "pg": "^8.7.3" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 0beba3da2..d89c12c5e 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.5.0", + "version": "3.5.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index f2df775a1..7e913e128 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.2.2", + "version": "4.2.3", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.7.2", + "pg": "^8.7.3", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.7.2" + "pg-cursor": "^2.7.3" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 3c92052b1..acc5e5f9a 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.7.2", + "version": "8.7.3", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.5.0", + "pg-pool": "^3.5.1", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 21ccd4f1b6e66774bbf24aecfccdbfe7c9b49238 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Feb 2022 14:52:06 -0600 Subject: [PATCH 029/261] Bump pathval from 1.1.0 to 1.1.1 (#2702) Bumps [pathval](https://github.com/chaijs/pathval) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/chaijs/pathval/releases) - [Changelog](https://github.com/chaijs/pathval/blob/master/CHANGELOG.md) - [Commits](https://github.com/chaijs/pathval/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: pathval dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1cb44de2f..3150a8804 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4821,9 +4821,9 @@ path-type@^4.0.0: integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== performance-now@^2.1.0: version "2.1.0" From f5e87ac0b17c8e8d7e66cbcdcc2eac8f9852577d Mon Sep 17 00:00:00 2001 From: Lars Hvam Date: Fri, 1 Apr 2022 18:31:45 +0200 Subject: [PATCH 030/261] pg: update README, remove dead badge (#2719) --- packages/pg/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/pg/README.md b/packages/pg/README.md index e5fcf02c4..b3158b570 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -1,7 +1,6 @@ # node-postgres [![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) -[![Dependency Status](https://david-dm.org/brianc/node-postgres.svg?path=packages/pg)](https://david-dm.org/brianc/node-postgres?path=packages/pg) NPM version NPM downloads From 4b4d97b8f3e141d6bd0f17cfe528db6ba802bb4b Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 10 May 2022 14:49:22 -0500 Subject: [PATCH 031/261] Remove stream-tester (#2743) * Remove stream-tester * Use random port for network-partition tests * Use random port for connection timeout test * Bump CI version --- .github/workflows/ci.yml | 6 +- packages/pg-query-stream/package.json | 1 - packages/pg-query-stream/test/pauses.ts | 15 ++++- .../client/connection-timeout-tests.js | 2 +- .../client/network-partition-tests.js | 16 +++-- yarn.lock | 58 ------------------- 6 files changed, 24 insertions(+), 74 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98ea909f5..14e24db12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,13 +17,13 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: matrix: - node: ['8', '10', '12', '14', '16', '17'] + node: ['8', '10', '12', '14', '16', '18'] os: [ubuntu-latest, windows-latest, macos-latest] name: Node.js ${{ matrix.node }} (${{ matrix.os }}) steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} cache: yarn diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7e913e128..227cdc4fe 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -39,7 +39,6 @@ "mocha": "^7.1.2", "pg": "^8.7.3", "stream-spec": "~0.3.5", - "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, diff --git a/packages/pg-query-stream/test/pauses.ts b/packages/pg-query-stream/test/pauses.ts index daf8347af..75fee57f6 100644 --- a/packages/pg-query-stream/test/pauses.ts +++ b/packages/pg-query-stream/test/pauses.ts @@ -1,8 +1,19 @@ import helper from './helper' import concat from 'concat-stream' -import tester from 'stream-tester' import JSONStream from 'JSONStream' import QueryStream from '../src' +import { Transform, TransformCallback } from 'stream' + +class PauseStream extends Transform { + constructor() { + super({ objectMode: true }) + } + + _transform(chunk, encoding, callback): void { + this.push(chunk, encoding) + setTimeout(callback, 1) + } +} helper('pauses', function (client) { it('pauses', function (done) { @@ -12,7 +23,7 @@ helper('pauses', function (client) { highWaterMark: 2, }) const query = client.query(stream) - const pauser = tester.createPauseStream(0.1, 100) + const pauser = new PauseStream() query .pipe(JSONStream.stringify()) .pipe(pauser) diff --git a/packages/pg/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js index 7a3ee4447..316e0768b 100644 --- a/packages/pg/test/integration/client/connection-timeout-tests.js +++ b/packages/pg/test/integration/client/connection-timeout-tests.js @@ -67,7 +67,7 @@ suite.test('successful connection', (done) => { }) suite.test('expired connection timeout', (done) => { - const opts = { ...options, port: 54322 } + const opts = { ...options, port: options.port + 1 } serverWithConnectionTimeout(opts.port, opts.connectionTimeoutMillis * 2, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have emitted an error but it did not.') diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index 2ac100dff..8397821a8 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -11,7 +11,6 @@ var Server = function (response) { this.response = response } -let port = 54321 Server.prototype.start = function (cb) { // this is our fake postgres server // it responds with our specified response immediatley after receiving every buffer @@ -40,14 +39,13 @@ Server.prototype.start = function (cb) { }.bind(this) ) - port = port + 1 - - var options = { - host: 'localhost', - port: port, - } - this.server.listen(options.port, options.host, function () { - cb(options) + const host = 'localhost' + this.server.listen({ host, port: 0 }, () => { + const port = this.server.address().port + cb({ + host, + port, + }) }) } diff --git a/yarn.lock b/yarn.lock index 3150a8804..6bcd1465f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1334,15 +1334,6 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -assertions@~2.3.0: - version "2.3.4" - resolved "https://registry.yarnpkg.com/assertions/-/assertions-2.3.4.tgz#a9433ced1fce57cc999af0965d1008e96c2796e6" - integrity sha1-qUM87R/OV8yZmvCWXRAI6WwnluY= - dependencies: - fomatto "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" - render "0.1" - traverser "1" - assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2010,11 +2001,6 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" -curry@0.0.x: - version "0.0.4" - resolved "https://registry.yarnpkg.com/curry/-/curry-0.0.4.tgz#1750d518d919c44f3d37ff44edc693de1f0d5fcb" - integrity sha1-F1DVGNkZxE89N/9E7caT3h8NX8s= - cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" @@ -2755,10 +2741,6 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -"fomatto@git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6": - version "0.6.0" - resolved "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2793,11 +2775,6 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -from@~0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/from/-/from-0.0.2.tgz#7fffac647a2f99b20d57b8e28379455cbb4189d0" - integrity sha1-f/+sZHovmbINV7jig3lFXLtBidA= - fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -5215,13 +5192,6 @@ regexpp@^3.0.0, regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -render@0.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/render/-/render-0.1.4.tgz#cfb33a34e26068591d418469e23d8cc5ce1ceff5" - integrity sha1-z7M6NOJgaFkdQYRp4j2Mxc4c7/U= - dependencies: - traverser "0.0.x" - repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" @@ -5683,15 +5653,6 @@ stream-spec@~0.3.5: dependencies: macgyver "~1.10" -stream-tester@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stream-tester/-/stream-tester-0.0.5.tgz#4f86f2531149adaf6dd4b3ff262edf64ae9a171a" - integrity sha1-T4byUxFJra9t1LP/Ji7fZK6aFxo= - dependencies: - assertions "~2.3.0" - from "~0.0.2" - through "~0.0.3" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -5944,11 +5905,6 @@ through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -through@~0.0.3: - version "0.0.4" - resolved "https://registry.yarnpkg.com/through/-/through-0.0.4.tgz#0bf2f0fffafaac4bacbc533667e98aad00b588c8" - integrity sha1-C/Lw//r6rEusvFM2Z+mKrQC1iMg= - tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -6013,20 +5969,6 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= -traverser@0.0.x: - version "0.0.5" - resolved "https://registry.yarnpkg.com/traverser/-/traverser-0.0.5.tgz#c66f38c456a0c21a88014b1223580c7ebe0631eb" - integrity sha1-xm84xFagwhqIAUsSI1gMfr4GMes= - dependencies: - curry "0.0.x" - -traverser@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/traverser/-/traverser-1.0.0.tgz#6f59e5813759aeeab3646b8f4513fd4a62e4fe20" - integrity sha1-b1nlgTdZruqzZGuPRRP9SmLk/iA= - dependencies: - curry "0.0.x" - trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" From b812ec1e65a103d79c603b47d53019fa9f77b7b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 23:41:05 -0500 Subject: [PATCH 032/261] Bump async from 0.9.0 to 2.6.4 (#2736) Bumps [async](https://github.com/caolan/async) from 0.9.0 to 2.6.4. - [Release notes](https://github.com/caolan/async/releases) - [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md) - [Commits](https://github.com/caolan/async/compare/0.9.0...v2.6.4) --- updated-dependencies: - dependency-name: async dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/pg/package.json | 2 +- yarn.lock | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/pg/package.json b/packages/pg/package.json index acc5e5f9a..e1eec9fa9 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -29,7 +29,7 @@ "pgpass": "1.x" }, "devDependencies": { - "async": "0.9.0", + "async": "2.6.4", "bluebird": "3.5.2", "co": "4.6.0", "pg-copy-streams": "0.3.0" diff --git a/yarn.lock b/yarn.lock index 6bcd1465f..1dcce5844 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1344,16 +1344,18 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== -async@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" - integrity sha1-rDYTsdqb7RtHUQu0ZRuJMeRxRsc= - async@1.x: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= +async@2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" From ec06473c164c4ed5e38fedf61026be36dd67b9b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 23:41:19 -0500 Subject: [PATCH 033/261] Bump minimist from 1.2.5 to 1.2.6 (#2727) Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1dcce5844..66527b4aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4099,9 +4099,9 @@ minimist-options@^3.0.1: is-plain-obj "^1.1.0" minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" From c7743646cd734bef4989e2a29a9ae3201b3744f5 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 12 May 2022 19:04:21 -0500 Subject: [PATCH 034/261] Update sponsors --- SPONSORS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index 453d11465..71c5210bc 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -12,6 +12,7 @@ node-postgres is made possible by the helpful contributors from the community as - [Eaze](https://www.eaze.com/) - [simpleanalytics](https://simpleanalytics.com/) - [n8n.io](https://n8n.io/) +- [mpirik](https://github.com/mpirik) # Supporters @@ -39,4 +40,8 @@ node-postgres is made possible by the helpful contributors from the community as - @Guido4000 - [Martti Laine](https://github.com/codeclown) - [Tim Nolet](https://github.com/tnolet) +- [Ideal Postcodes](https://github.com/ideal-postcodes) - [checkly](https://github.com/checkly) +- [Scout APM](https://github.com/scoutapm-sponsorships) +- [Sideline Sports](https://github.com/SidelineSports) +- [Gadget](https://github.com/gadget-inc) From 3ca56027d3079b6bcee81d65e3e590328a74ea3c Mon Sep 17 00:00:00 2001 From: ChrisWritable <50638920+ChrisWritable@users.noreply.github.com> Date: Thu, 12 May 2022 17:05:02 -0700 Subject: [PATCH 035/261] Immediately unref() maxLifetimeSeconds Timeout object to prevent blocking allowExitOnIdle (#2721) --- packages/pg-pool/index.js | 5 ++++- packages/pg-pool/test/idle-timeout-exit.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 0d7314eb6..5e846bb31 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -252,7 +252,7 @@ class Pool extends EventEmitter { this.log('new client connected') if (this.options.maxLifetimeSeconds !== 0) { - setTimeout(() => { + const maxLifetimeTimeout = setTimeout(() => { this.log('ending client due to expired lifetime') this._expired.add(client) const idleIndex = this._idle.findIndex((idleItem) => idleItem.client === client) @@ -265,6 +265,9 @@ class Pool extends EventEmitter { ) } }, this.options.maxLifetimeSeconds * 1000) + + maxLifetimeTimeout.unref() + client.once('end', () => clearTimeout(maxLifetimeTimeout)) } return this._acquireClient(client, pendingItem, idleListener, true) diff --git a/packages/pg-pool/test/idle-timeout-exit.js b/packages/pg-pool/test/idle-timeout-exit.js index 1292634a8..b557af7f6 100644 --- a/packages/pg-pool/test/idle-timeout-exit.js +++ b/packages/pg-pool/test/idle-timeout-exit.js @@ -3,7 +3,7 @@ if (module === require.main) { const allowExitOnIdle = process.env.ALLOW_EXIT_ON_IDLE === '1' const Pool = require('../index') - const pool = new Pool({ idleTimeoutMillis: 200, ...(allowExitOnIdle ? { allowExitOnIdle: true } : {}) }) + const pool = new Pool({ maxLifetimeSeconds: 2, idleTimeoutMillis: 200, ...(allowExitOnIdle ? { allowExitOnIdle: true } : {}) }) pool.query('SELECT NOW()', (err, res) => console.log('completed first')) pool.on('remove', () => { console.log('removed') From 28ac2a17bce287cfa458153dcabe3ca06ca0e28f Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 12 May 2022 22:00:00 -0500 Subject: [PATCH 036/261] Add test for how to set search path (#2700) Also refactor a few tests a bit to slowly clean up some of the old style. --- .../integration/client/type-coercion-tests.js | 1 - .../connection-pool-size-tests.js | 41 ++++++++++++++++--- .../connection-pool/test-helper.js | 29 +------------ .../test/integration/gh-issues/2416-tests.js | 14 +++++++ packages/pg/test/test-helper.js | 28 ------------- 5 files changed, 51 insertions(+), 62 deletions(-) create mode 100644 packages/pg/test/integration/gh-issues/2416-tests.js diff --git a/packages/pg/test/integration/client/type-coercion-tests.js b/packages/pg/test/integration/client/type-coercion-tests.js index 33249a9b2..3bc6273c4 100644 --- a/packages/pg/test/integration/client/type-coercion-tests.js +++ b/packages/pg/test/integration/client/type-coercion-tests.js @@ -1,7 +1,6 @@ 'use strict' var helper = require('./test-helper') var pg = helper.pg -var sink const suite = new helper.Suite() var testForTypeCoercion = function (type) { 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 da281a191..1d87584e6 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 @@ -1,10 +1,41 @@ 'use strict' -var helper = require('./test-helper') +const helper = require('../test-helper') +const assert = require('assert') -helper.testPoolSize(1) +const suite = new helper.Suite() -helper.testPoolSize(2) +const testPoolSize = function (max) { + suite.testAsync(`test ${max} queries executed on a pool rapidly`, () => { + const pool = new helper.pg.Pool({ max: 10 }) -helper.testPoolSize(40) + let count = 0 -helper.testPoolSize(200) + return new Promise((resolve) => { + for (var i = 0; i < max; i++) { + pool.connect(function (err, client, release) { + assert(!err) + client.query('SELECT * FROM NOW()') + client.query('select generate_series(0, 25)', function (err, result) { + assert.strictEqual(result.rows.length, 26) + }) + client.query('SELECT * FROM NOW()', (err) => { + assert(!err) + release() + if (++count === max) { + resolve() + pool.end() + } + }) + }) + } + }) + }) +} + +testPoolSize(1) + +testPoolSize(2) + +testPoolSize(40) + +testPoolSize(200) diff --git a/packages/pg/test/integration/connection-pool/test-helper.js b/packages/pg/test/integration/connection-pool/test-helper.js index 97a177a62..14f8134eb 100644 --- a/packages/pg/test/integration/connection-pool/test-helper.js +++ b/packages/pg/test/integration/connection-pool/test-helper.js @@ -1,31 +1,4 @@ 'use strict' var helper = require('./../test-helper') -const suite = new helper.Suite() - -helper.testPoolSize = function (max) { - suite.test(`test ${max} queries executed on a pool rapidly`, (cb) => { - const pool = new helper.pg.Pool({ max: 10 }) - - var sink = new helper.Sink(max, function () { - pool.end(cb) - }) - - for (var i = 0; i < max; i++) { - pool.connect(function (err, client, done) { - assert(!err) - client.query('SELECT * FROM NOW()') - client.query('select generate_series(0, 25)', function (err, result) { - assert.equal(result.rows.length, 26) - }) - var query = client.query('SELECT * FROM NOW()', (err) => { - assert(!err) - sink.add() - done() - }) - }) - } - }) -} - -module.exports = Object.assign({}, helper, { suite: suite }) +module.exports = helper diff --git a/packages/pg/test/integration/gh-issues/2416-tests.js b/packages/pg/test/integration/gh-issues/2416-tests.js new file mode 100644 index 000000000..669eb7789 --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2416-tests.js @@ -0,0 +1,14 @@ +const helper = require('../test-helper') + +const suite = new helper.Suite() + +suite.testAsync('it sets search_path on connection', async () => { + const client = new helper.pg.Client({ + options: '--search_path=foo', + }) + await client.connect() + const { rows } = await client.query('SHOW search_path') + assert.strictEqual(rows.length, 1) + assert.strictEqual(rows[0].search_path, 'foo') + await client.end() +}) diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 5999ea98f..15abcd465 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -183,33 +183,6 @@ process.on('uncaughtException', function (err) { process.exit(255) }) -var Sink = function (expected, timeout, callback) { - var defaultTimeout = 5000 - if (typeof timeout === 'function') { - callback = timeout - timeout = defaultTimeout - } - timeout = timeout || defaultTimeout - var internalCount = 0 - var kill = function () { - assert.ok(false, 'Did not reach expected ' + expected + ' with an idle timeout of ' + timeout) - } - var killTimeout = setTimeout(kill, timeout) - return { - add: function (count) { - count = count || 1 - internalCount += count - clearTimeout(killTimeout) - if (internalCount < expected) { - killTimeout = setTimeout(kill, timeout) - } else { - assert.equal(internalCount, expected) - callback() - } - }, - } -} - var getTimezoneOffset = Date.prototype.getTimezoneOffset var setTimezoneOffset = function (minutesOffset) { @@ -231,7 +204,6 @@ const rejection = (promise) => ) module.exports = { - Sink: Sink, Suite: Suite, pg: require('./../lib/'), args: args, From 68160a29bd8dfe97c74ab9a74000977da7783d6f Mon Sep 17 00:00:00 2001 From: Peter Rust Date: Mon, 20 Jun 2022 06:25:12 -0700 Subject: [PATCH 037/261] Fix #2556 by keeping callback errors from interfering with cleanup (#2753) * Fix #2556 (handleRowDescription of null) by keeping callback errors from interfering with cleanup * Added regression test for #2556 --- packages/pg/lib/query.js | 9 ++++- .../test/integration/gh-issues/2556-tests.js | 40 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 packages/pg/test/integration/gh-issues/2556-tests.js diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index c0dfedd1e..6655a0e69 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -135,7 +135,14 @@ class Query extends EventEmitter { return this.handleError(this._canceledDueToError, con) } if (this.callback) { - this.callback(null, this._results) + try { + this.callback(null, this._results) + } + catch(err) { + process.nextTick(() => { + throw err + }) + } } this.emit('end', this._results) } diff --git a/packages/pg/test/integration/gh-issues/2556-tests.js b/packages/pg/test/integration/gh-issues/2556-tests.js new file mode 100644 index 000000000..13fdf80eb --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2556-tests.js @@ -0,0 +1,40 @@ +'use strict' +var helper = require('./../test-helper') +var assert = require('assert') + +var callbackError = new Error('TEST: Throw in callback') + +const suite = new helper.Suite() + +suite.test('it should cleanup client even if an error is thrown in a callback', (done) => { + // temporarily replace the test framework's uncaughtException handlers + // with a custom one that ignores the callbackError + let original_handlers = process.listeners('uncaughtException') + process.removeAllListeners('uncaughtException') + process.on('uncaughtException', (err) => { + if (err != callbackError) { + original_handlers[0](err) + } + }) + + // throw an error in a callback and verify that a subsequent query works without error + var client = helper.client() + client.query('SELECT NOW()', (err) => { + assert(!err) + setTimeout(reuseClient, 50) + throw callbackError + }) + + function reuseClient() { + client.query('SELECT NOW()', (err) => { + assert(!err) + + // restore the test framework's uncaughtException handlers + for (let handler of original_handlers) { + process.on('uncaughtException', handler) + } + + client.end(done) + }) + } +}) From 3e53d06cd891797469ebdd2f8a669183ba6224f6 Mon Sep 17 00:00:00 2001 From: Martin Kubliniak Date: Wed, 10 Aug 2022 23:15:06 +0200 Subject: [PATCH 038/261] Support lock_timeout (#2779) --- packages/pg/lib/client.js | 3 +++ packages/pg/lib/connection-parameters.js | 1 + packages/pg/lib/defaults.js | 4 ++++ packages/pg/test/unit/connection-parameters/creation-tests.js | 3 +++ 4 files changed, 11 insertions(+) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 589aa9f84..18238f6fb 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -403,6 +403,9 @@ class Client extends EventEmitter { if (params.statement_timeout) { data.statement_timeout = String(parseInt(params.statement_timeout, 10)) } + if (params.lock_timeout) { + data.lock_timeout = String(parseInt(params.lock_timeout, 10)) + } if (params.idle_in_transaction_session_timeout) { data.idle_in_transaction_session_timeout = String(parseInt(params.idle_in_transaction_session_timeout, 10)) } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 165e6d5d3..6a535a820 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -103,6 +103,7 @@ class ConnectionParameters { this.application_name = val('application_name', config, 'PGAPPNAME') this.fallback_application_name = val('fallback_application_name', config, false) this.statement_timeout = val('statement_timeout', config, false) + this.lock_timeout = val('lock_timeout', config, false) this.idle_in_transaction_session_timeout = val('idle_in_transaction_session_timeout', config, false) this.query_timeout = val('query_timeout', config, false) diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index 9384e01cb..5c5d997d2 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -54,6 +54,10 @@ module.exports = { // false=unlimited statement_timeout: false, + // Abort any statement that waits longer than the specified duration in milliseconds while attempting to acquire a lock. + // false=unlimited + lock_timeout: false, + // Terminate any session with an open transaction that has been idle for longer than the specified duration in milliseconds // false=unlimited idle_in_transaction_session_timeout: false, diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 40381e788..cd27d5011 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -28,6 +28,7 @@ var compare = function (actual, expected, type) { assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') assert.equal(actual.statement_timeout, expected.statement_timeout, type + ' statement_timeout') + assert.equal(actual.lock_timeout, expected.lock_timeout, type + ' lock_timeout') assert.equal(actual.options, expected.options, type + ' options') assert.equal( actual.idle_in_transaction_session_timeout, @@ -51,6 +52,7 @@ suite.test('ConnectionParameters initializing from defaults with connectionStrin host: 'foo.bar.net', binary: defaults.binary, statement_timeout: false, + lock_timeout: false, idle_in_transaction_session_timeout: false, options: '-c geqo=off', } @@ -78,6 +80,7 @@ suite.test('ConnectionParameters initializing from config', function () { asdf: 'blah', }, statement_timeout: 15000, + lock_timeout: 15000, idle_in_transaction_session_timeout: 15000, options: '-c geqo=off', } From 8032fbad43e801b332191b2e0862e177947392af Mon Sep 17 00:00:00 2001 From: Alex Zlotnik Date: Mon, 22 Aug 2022 13:33:51 -0700 Subject: [PATCH 039/261] Catch errors client throws in pool (#2569) * Catch errors client throws in pool * Add a test This test _should be_ right --- packages/pg-pool/index.js | 32 ++++++++++++++----------- packages/pg-pool/test/error-handling.js | 11 +++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 5e846bb31..20dbe734c 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -406,20 +406,24 @@ class Pool extends EventEmitter { client.once('error', onError) this.log('dispatching query') - client.query(text, values, (err, res) => { - this.log('query dispatched') - client.removeListener('error', onError) - if (clientReleased) { - return - } - clientReleased = true - client.release(err) - if (err) { - return cb(err) - } else { - return cb(undefined, res) - } - }) + try { + client.query(text, values, (err, res) => { + this.log('query dispatched') + client.removeListener('error', onError) + if (clientReleased) { + return + } + clientReleased = true + client.release(err) + if (err) { + return cb(err) + } else { + return cb(undefined, res) + } + }) + } catch (err) { + return cb(err) + } }) return response.result } diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index 0a996b82b..f514bd79f 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -37,6 +37,17 @@ describe('pool error handling', function () { }) }) + it('Catches errors in client.query', async function () { + await expect((new Pool()).query(null)).to.throwError() + await expect(async () => { + try { + await (new Pool()).query(null) + } catch (e) { + console.log(e) + } + }).not.to.throwError() + }) + describe('calling release more than once', () => { it( 'should throw each time', From 747485d342b8d7a5b47f988b668cea012ce50cf0 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 22 Aug 2022 15:34:07 -0500 Subject: [PATCH 040/261] Bump min version of pg-native (#2787) Fixes 2786 --- packages/pg/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/package.json b/packages/pg/package.json index e1eec9fa9..34b833298 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -35,7 +35,7 @@ "pg-copy-streams": "0.3.0" }, "peerDependencies": { - "pg-native": ">=2.0.0" + "pg-native": ">=3.0.1" }, "peerDependenciesMeta": { "pg-native": { From a4ef6ce38c1e04bad2215312b1c79e64654cc857 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 22 Aug 2022 19:05:59 -0500 Subject: [PATCH 041/261] Fix error handling test (#2789) * Fix error handling test #2569 introduced a bug in the test. The test never passed but because travis-ci lovingly broke the integration we had a long time ago the tests weren't run in CI until I merged. So, this fixes the tests & does a better job cleaning up the query in an errored state. * Update sponsors --- SPONSORS.md | 3 +++ packages/pg-pool/index.js | 4 ++-- packages/pg-pool/test/error-handling.js | 17 +++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/SPONSORS.md b/SPONSORS.md index 71c5210bc..3bebb01eb 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -13,6 +13,9 @@ node-postgres is made possible by the helpful contributors from the community as - [simpleanalytics](https://simpleanalytics.com/) - [n8n.io](https://n8n.io/) - [mpirik](https://github.com/mpirik) +- [@BLUE-DEVIL1134](https://github.com/BLUE-DEVIL1134) +- [bubble.io](https://bubble.io/) +- GitHub[https://github.com/github] # Supporters diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 20dbe734c..00f55b4da 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -417,11 +417,11 @@ class Pool extends EventEmitter { client.release(err) if (err) { return cb(err) - } else { - return cb(undefined, res) } + return cb(undefined, res) }) } catch (err) { + client.release(err) return cb(err) } }) diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index f514bd79f..7b1570859 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -38,14 +38,15 @@ describe('pool error handling', function () { }) it('Catches errors in client.query', async function () { - await expect((new Pool()).query(null)).to.throwError() - await expect(async () => { - try { - await (new Pool()).query(null) - } catch (e) { - console.log(e) - } - }).not.to.throwError() + let caught = false + const pool = new Pool() + try { + await pool.query(null) + } catch (e) { + caught = true + } + pool.end() + expect(caught).to.be(true) }) describe('calling release more than once', () => { From ff85ac24592441e8092b40373ea4ba88af1aae8a Mon Sep 17 00:00:00 2001 From: Marcin K Date: Tue, 23 Aug 2022 02:06:43 +0200 Subject: [PATCH 042/261] chore(): added dependabot (#2374) --- .github/dependabot.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yaml diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 000000000..41a081f92 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,7 @@ + +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "monthly" \ No newline at end of file From 6e386eb29479e063d741e597ab85d462af31d12f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 21:35:18 -0500 Subject: [PATCH 043/261] Bump prettier from 2.1.2 to 2.7.1 (#2792) Bumps [prettier](https://github.com/prettier/prettier) from 2.1.2 to 2.7.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.1.2...2.7.1) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3de85d252..b8ac7659b 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.4", "lerna": "^3.19.0", - "prettier": "2.1.2", + "prettier": "2.7.1", "typescript": "^4.0.3" }, "prettier": { diff --git a/yarn.lock b/yarn.lock index 66527b4aa..d1cce1ee2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4925,10 +4925,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" - integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== +prettier@2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== process-nextick-args@~2.0.0: version "2.0.1" From 8d498959c396797d60f822c2d1a6ac4a87481d3c Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Tue, 23 Aug 2022 11:29:35 -0500 Subject: [PATCH 044/261] Update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72599c724..f017a3d5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ 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.8.0 + +- Bump minimum required version of [native bindings](https://github.com/brianc/node-postgres/pull/2787) +- Catch previously uncatchable errors thrown in [`pool.query`](https://github.com/brianc/node-postgres/pull/2569) +- Prevent the pool from blocking the event loop if all clients are [idle](https://github.com/brianc/node-postgres/pull/2721) (and `allowExitOnIdle` is enabled) +- Support `lock_timeout` in [client config](https://github.com/brianc/node-postgres/pull/2779) +- Fix errors thrown in callbacks from [interfering with cleanup](https://github.com/brianc/node-postgres/pull/2753) + ### pg-pool@3.5.0 - Add connection [lifetime limit](https://github.com/brianc/node-postgres/pull/2698) config option. From c99fb2c127ddf8d712500db2c7b9a5491a178655 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Tue, 23 Aug 2022 11:36:18 -0500 Subject: [PATCH 045/261] Publish - pg-cursor@2.7.4 - pg-pool@3.5.2 - pg-query-stream@4.2.4 - pg@8.8.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 6104c9557..c12906abd 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.3", + "version": "2.7.4", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.7.3" + "pg": "^8.8.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index d89c12c5e..0bb64b579 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.5.1", + "version": "3.5.2", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 227cdc4fe..528ed271d 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.2.3", + "version": "4.2.4", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,12 +37,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.7.3", + "pg": "^8.8.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.7.3" + "pg-cursor": "^2.7.4" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 34b833298..37afe6149 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.7.3", + "version": "8.8.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.5.1", + "pg-pool": "^3.5.2", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From ad6c4a4693801120eaa0d7941664e2d30d53283d Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 29 Aug 2022 13:32:48 -0500 Subject: [PATCH 046/261] Update README.md (#2799) Build status icon was still pointing at travis. We don't use travis anymore: we use github actions. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf3a7be82..15b693128 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # node-postgres -[![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) +![Build Status](https://github.com/brianc/node-postgres/actions/workflows/ci.yml/badge.svg) NPM version NPM downloads From 8250af4aed9b8977932560733fe8665831aeef4d Mon Sep 17 00:00:00 2001 From: Alex <93376818+sashashura@users.noreply.github.com> Date: Mon, 29 Aug 2022 20:55:10 +0100 Subject: [PATCH 047/261] Minimize GitHub Workflows permissions (#2798) Signed-off-by: sashashura <93376818+sashashura@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14e24db12..73e5709d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,6 +2,9 @@ name: CI on: [push, pull_request] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest From 659ac37ba3922be2be5880d42c09192d951825b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 06:31:37 +0200 Subject: [PATCH 048/261] Bump eslint-plugin-promise from 3.8.0 to 6.0.1 (#2802) Bumps [eslint-plugin-promise](https://github.com/xjamundx/eslint-plugin-promise) from 3.8.0 to 6.0.1. - [Release notes](https://github.com/xjamundx/eslint-plugin-promise/releases) - [Changelog](https://github.com/xjamundx/eslint-plugin-promise/blob/development/CHANGELOG.md) - [Commits](https://github.com/xjamundx/eslint-plugin-promise/commits) --- updated-dependencies: - dependency-name: eslint-plugin-promise dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/pg-query-stream/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 528ed271d..7a789970f 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -35,7 +35,7 @@ "@types/pg": "^7.14.5", "JSONStream": "~0.7.1", "concat-stream": "~1.0.1", - "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-promise": "^6.0.1", "mocha": "^7.1.2", "pg": "^8.8.0", "stream-spec": "~0.3.5", diff --git a/yarn.lock b/yarn.lock index d1cce1ee2..d33799e00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2382,10 +2382,10 @@ eslint-plugin-prettier@^3.1.4: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-promise@^3.5.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" - integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== +eslint-plugin-promise@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz#a8cddf96a67c4059bdabf4d724a29572188ae423" + integrity sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw== eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" From 34d173d9e36430faff8c5aa1749f850fe1a9a739 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 17 Sep 2022 20:59:43 +0200 Subject: [PATCH 049/261] Bump coveralls from 3.1.0 to 3.1.1 (#2801) Bumps [coveralls](https://github.com/nickmerwin/node-coveralls) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/nickmerwin/node-coveralls/releases) - [Commits](https://github.com/nickmerwin/node-coveralls/compare/v3.1.0...3.1.1) --- updated-dependencies: - dependency-name: coveralls dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d33799e00..9cd0b3c06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1966,9 +1966,9 @@ cosmiconfig@^5.1.0: parse-json "^4.0.0" coveralls@^3.0.4: - version "3.1.0" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" - integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== + version "3.1.1" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" + integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== dependencies: js-yaml "^3.13.1" lcov-parse "^1.0.0" From 9a95ee719b181341d381702a4404827ca906b036 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Mon, 19 Sep 2022 19:29:53 +0200 Subject: [PATCH 050/261] pg-query-stream: Add missing peer dependency on pg (#2813) pg-query-stream depends on pg-cursor, which has a peer dependency on pg. --- packages/pg-query-stream/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7a789970f..92a42fe95 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -42,6 +42,9 @@ "ts-node": "^8.5.4", "typescript": "^4.0.3" }, + "peerDependencies": { + "pg": "^8" + }, "dependencies": { "pg-cursor": "^2.7.4" } From 9e2d7c4ad5d5e6c168e428d5b11326f0fd48b6db Mon Sep 17 00:00:00 2001 From: Yue Dai Date: Tue, 27 Sep 2022 03:31:07 -0700 Subject: [PATCH 051/261] Update pg.connect with pool.connect (#2822) pg.connect() has been deprecated. --- packages/pg-query-stream/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/pg-query-stream/README.md b/packages/pg-query-stream/README.md index d5b2802bd..b2e860528 100644 --- a/packages/pg-query-stream/README.md +++ b/packages/pg-query-stream/README.md @@ -15,11 +15,12 @@ _requires pg>=2.8.1_ ```js const pg = require('pg') +var pool = new pg.Pool() const QueryStream = require('pg-query-stream') const JSONStream = require('JSONStream') //pipe 1,000,000 rows to stdout without blowing up your memory usage -pg.connect((err, client, done) => { +pool.connect((err, client, done) => { if (err) throw err const query = new QueryStream('SELECT * FROM generate_series(0, $1) num', [1000000]) const stream = client.query(query) From 9dfb3dccbfd78c088f093dd4c0c11bda7ccd2465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bjka?= Date: Tue, 27 Sep 2022 12:38:28 +0200 Subject: [PATCH 052/261] perf(pg): use native crypto.pbkdf2Sync in sasl auth (#2815) --- packages/pg/lib/sasl.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index c61804750..fb703b270 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -37,7 +37,7 @@ function continueSession(session, password, serverData) { var saltBytes = Buffer.from(sv.salt, 'base64') - var saltedPassword = Hi(password, saltBytes, sv.iteration) + var saltedPassword = crypto.pbkdf2Sync(password, saltBytes, sv.iteration, 32, 'sha256') var clientKey = hmacSha256(saltedPassword, 'Client Key') var storedKey = sha256(clientKey) @@ -191,17 +191,6 @@ function hmacSha256(key, msg) { return crypto.createHmac('sha256', key).update(msg).digest() } -function Hi(password, saltBytes, iterations) { - var ui1 = hmacSha256(password, Buffer.concat([saltBytes, Buffer.from([0, 0, 0, 1])])) - var ui = ui1 - for (var i = 0; i < iterations - 1; i++) { - ui1 = hmacSha256(password, ui1) - ui = xorBuffers(ui, ui1) - } - - return ui -} - module.exports = { startSession, continueSession, From 5bcc05d1e95104d20ce08a6e3e56d0acdcc4b757 Mon Sep 17 00:00:00 2001 From: Alex Anderson <191496+alxndrsn@users.noreply.github.com> Date: Thu, 6 Oct 2022 19:59:11 +0300 Subject: [PATCH 053/261] pg-protocol: fix link to message format docs (#2835) --- packages/pg-protocol/src/testing/test-buffers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-protocol/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts index e0a04a758..a4d49f322 100644 --- a/packages/pg-protocol/src/testing/test-buffers.ts +++ b/packages/pg-protocol/src/testing/test-buffers.ts @@ -1,4 +1,4 @@ -// http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html +// https://www.postgresql.org/docs/current/protocol-message-formats.html import BufferList from './buffer-list' const buffers = { From 1aa08274a52c076af9891650d7228f029439a158 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 10 Oct 2022 12:20:46 -0500 Subject: [PATCH 054/261] Migrate docs repo into monorepo (#2823) * Move files over * Finish initial port of content --- docs/.gitignore | 2 + docs/components/alert.tsx | 10 + docs/components/info.tsx | 6 + docs/next.config.js | 8 + docs/package.json | 20 + docs/pages/_app.js | 9 + docs/pages/_meta.json | 5 + docs/pages/announcements.mdx | 145 ++ docs/pages/apis/_meta.json | 7 + docs/pages/apis/client.mdx | 330 +++++ docs/pages/apis/cursor.mdx | 81 + docs/pages/apis/pool.mdx | 274 ++++ docs/pages/apis/result.mdx | 52 + docs/pages/apis/types.mdx | 6 + docs/pages/features/_meta.json | 9 + docs/pages/features/connecting.mdx | 162 ++ docs/pages/features/native.mdx | 27 + docs/pages/features/pooling.mdx | 173 +++ docs/pages/features/queries.mdx | 211 +++ docs/pages/features/ssl.mdx | 61 + docs/pages/features/transactions.mdx | 93 ++ docs/pages/features/types.mdx | 106 ++ docs/pages/guides/_meta.json | 5 + docs/pages/guides/async-express.md | 83 ++ docs/pages/guides/project-structure.md | 197 +++ docs/pages/guides/upgrading.md | 114 ++ docs/pages/index.mdx | 65 + docs/theme.config.js | 27 + docs/yarn.lock | 1892 ++++++++++++++++++++++++ package.json | 2 + 30 files changed, 4182 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/components/alert.tsx create mode 100644 docs/components/info.tsx create mode 100644 docs/next.config.js create mode 100644 docs/package.json create mode 100644 docs/pages/_app.js create mode 100644 docs/pages/_meta.json create mode 100644 docs/pages/announcements.mdx create mode 100644 docs/pages/apis/_meta.json create mode 100644 docs/pages/apis/client.mdx create mode 100644 docs/pages/apis/cursor.mdx create mode 100644 docs/pages/apis/pool.mdx create mode 100644 docs/pages/apis/result.mdx create mode 100644 docs/pages/apis/types.mdx create mode 100644 docs/pages/features/_meta.json create mode 100644 docs/pages/features/connecting.mdx create mode 100644 docs/pages/features/native.mdx create mode 100644 docs/pages/features/pooling.mdx create mode 100644 docs/pages/features/queries.mdx create mode 100644 docs/pages/features/ssl.mdx create mode 100644 docs/pages/features/transactions.mdx create mode 100644 docs/pages/features/types.mdx create mode 100644 docs/pages/guides/_meta.json create mode 100644 docs/pages/guides/async-express.md create mode 100644 docs/pages/guides/project-structure.md create mode 100644 docs/pages/guides/upgrading.md create mode 100644 docs/pages/index.mdx create mode 100644 docs/theme.config.js create mode 100644 docs/yarn.lock diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..2b3533c7e --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +.next +out diff --git a/docs/components/alert.tsx b/docs/components/alert.tsx new file mode 100644 index 000000000..7bf2237ca --- /dev/null +++ b/docs/components/alert.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import { Callout } from 'nextra-theme-docs' + +export const Alert = ({ children }) => { + return ( + + {children} + + ) +} diff --git a/docs/components/info.tsx b/docs/components/info.tsx new file mode 100644 index 000000000..a61e17fb2 --- /dev/null +++ b/docs/components/info.tsx @@ -0,0 +1,6 @@ +import React from 'react' +import { Callout } from 'nextra-theme-docs' + +export const Info = ({ children }) => { + return {children} +} diff --git a/docs/next.config.js b/docs/next.config.js new file mode 100644 index 000000000..45a998c7c --- /dev/null +++ b/docs/next.config.js @@ -0,0 +1,8 @@ +// next.config.js +const withNextra = require('nextra')({ + theme: 'nextra-theme-docs', + themeConfig: './theme.config.js', + // optional: add `unstable_staticImage: true` to enable Nextra's auto image import +}) + +module.exports = withNextra() diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 000000000..dec5cceb2 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,20 @@ +{ + "name": "docs", + "version": "1.0.0", + "description": "", + "main": "next.config.js", + "scripts": { + "start": "next dev", + "build": "next build && next export" + }, + "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" + } +} diff --git a/docs/pages/_app.js b/docs/pages/_app.js new file mode 100644 index 000000000..19532b06e --- /dev/null +++ b/docs/pages/_app.js @@ -0,0 +1,9 @@ +import 'nextra-theme-docs/style.css' + +export default function Nextra({ Component, pageProps }) { + return ( + <> + + + ) +} diff --git a/docs/pages/_meta.json b/docs/pages/_meta.json new file mode 100644 index 000000000..dd241d886 --- /dev/null +++ b/docs/pages/_meta.json @@ -0,0 +1,5 @@ +{ + "index": "Welcome", + "announcements": "Announcements", + "apis": "API" +} diff --git a/docs/pages/announcements.mdx b/docs/pages/announcements.mdx new file mode 100644 index 000000000..6fec81ca3 --- /dev/null +++ b/docs/pages/announcements.mdx @@ -0,0 +1,145 @@ +import { Alert } from '/components/alert.tsx' + +## 2020-02-25 + +### pg@8.0 release + +`pg@8.0` is [being released](https://github.com/brianc/node-postgres/pull/2117) which contains a handful of breaking changes. + +I will outline each breaking change here and try to give some historical context on them. Most of them are small and subtle and likely wont impact you; **however**, there is one larger breaking change you will likely run into: + +--- + +- Support all `tls.connect` [options](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback) being passed to the client/pool constructor under the `ssl` option. + +Previously we white listed the parameters passed here and did slight massaging of some of them. The main **breaking** change here is that now if you do this: + +```js +const client = new Client({ ssl: true }) +``` + + + Now we will use the default ssl options to tls.connect which includes rejectUnauthorized being enabled. This means + your connection attempt may fail if you are using a self-signed cert. To use the old behavior you should do this: + + +```js +const client = new Client({ ssl: { rejectUnauthorized: false } }) +``` + +This makes pg a bit more secure "out of the box" while still enabling you to opt in to the old behavior. + +--- + +The rest of the changes are relatively minor & you likely wont need to do anything, but good to be aware none the less! + +- change default database name + +If a database name is not specified, available in the environment at `PGDATABASE`, or available at `pg.defaults`, we used to use the username of the process user as the name of the database. Now we will use the `user` property supplied to the client as the database name, if it exists. What this means is this: + +```jsx +new Client({ + user: 'foo', +}) +``` + +`pg@7.x` will default the database name to the _process_ user. `pg@8.x` will use the `user` property supplied to the client. If you have not supplied `user` to the client, and it isn't available through any of its existing lookup mechanisms (environment variables, pg.defaults) then it will still use the process user for the database name. + +- drop support for versions of node older than 8.0 + +Node@6.0 has been out of LTS for quite some time now, and I've removed it from our test matrix. `pg@8.0` _may_ still work on older versions of node, but it isn't a goal of the project anymore. Node@8.0 is actually no longer in the LTS support line, but pg will continue to test against and support 8.0 until there is a compelling reason to drop support for it. Any security vulnerability issues which come up I will back-port fixes to the `pg@7.x` line and do a release, but any other fixes or improvments will not be back ported. + +- prevent password from being logged accidentally + +`pg@8.0` makes the password field on the pool and client non-enumerable. This means when you do `console.log(client)` you wont have your database password printed out unintenionally. You can still do `console.log(client.password)` if you really want to see it! + +- make `pg.native` non-enumerable + +You can use `pg.native.Client` to access the native client. The first time you access the `pg.native` getter it imports the native bindings...which must be installed. In some cases (such as webpacking the pg code for lambda deployment) the `.native` property would be traversed and trigger an import of the native bindings as a side-effect. Making this property non-enumerable will fix this issue. An easy fix, but its technically a breaking change in cases where people _are_ relying on this side effect for any reason. + +- make `pg.Pool` an es6 class + +This makes extending `pg.Pool` possible. Previously it was not a "proper" es6 class and `class MyPool extends pg.Pool` wouldn't work. + +- make `Notice` messages _not_ an instance of a JavaScript error + +The code path for parsing `notice` and `error` messages from the postgres backend is the same. Previously created a JavaScript `Error` instance for _both_ of these message types. Now, only actual `errors` from the postgres backend will be an instance of an `Error`. The _shape_ and _properties_ of the two messages did not change outside of this. + +- monorepo + +While not technically a breaking change for the module itself, I have begun the process of [consolidating](https://github.com/brianc/node-pg-query-stream) [separate](https://github.com/brianc/node-pg-cursor/) [repos](https://github.com/brianc/node-pg-pool) into the main [repo](https://github.com/brianc/node-postgres) and converted it into a monorepo managed by lerna. This will help me stay on top of issues better (it was hard to bounce between 3-4 separate repos) and coordinate bug fixes and changes between dependant modules. + +Thanks for reading that! pg tries to be super pedantic about not breaking backwards-compatibility in non semver major releases....even for seemingly small things. If you ever notice a breaking change on a semver minor/patch release please stop by the [repo](https://github.com/brianc/node-postgres) and open an issue! + +_If you find `pg` valuable to you or your business please consider [supporting](http://github.com/sponsors/brianc) it's continued development! Big performance improvements, typescript, better docs, query pipelining and more are all in the works!_ + +## 2019-07-18 + +### New documentation + +After a _very_ long time on my todo list I've ported the docs from my old hand-rolled webapp running on route53 + elb + ec2 + dokku (I know, I went overboard!) to [gatsby](https://www.gatsbyjs.org/) hosted on [netlify](https://www.netlify.com/) which is _so_ much easier to manage. I've released the code at [https://github.com/brianc/node-postgres-docs](https://github.com/brianc/node-postgres-docs) and invite your contributions! Let's make this documentation better together. Any time changes are merged to master on the documentation repo it will automatically deploy. + +If you see an error in the docs, big or small, use the "edit on github" button to edit the page & submit a pull request right there. I'll get a new version out ASAP with your changes! If you want to add new pages of documentation open an issue if you need guidance, and I'll help you get started. + +I want to extend a special **thank you** to all the [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and [contributors](https://github.com/brianc/node-postgres/graphs/contributors) to the project that have helped keep me going through times of burnout or life "getting in the way." ❤️ + +It's been quite a journey, and I look forward continuing it for as long as I can provide value to all y'all. 🤠 + +## 2017-08-12 + +### code execution vulnerability + +Today [@sehrope](https://github.com/sehrope) found and reported a code execution vulnerability in node-postgres. This affects all versions from `pg@2.x` through `pg@7.1.0`. + +I have published a fix on the tip of each major version branch of all affected versions as well as a fix on each minor version branch of `pg@6.x` and `pg@7.x`: + +### Fixes + +The following versions have been published to npm & contain a patch to fix the vulnerability: + +``` +pg@2.11.2 +pg@3.6.4 +pg@4.5.7 +pg@5.2.1 +pg@6.0.5 +pg@6.1.6 +pg@6.2.5 +pg@6.3.3 +pg@6.4.2 +pg@7.0.3 +pg@7.1.2 +``` + +### Example + +To demonstrate the issue & see if you are vunerable execute the following in node: + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() + +const sql = `SELECT 1 AS "\\'/*", 2 AS "\\'*/\n + console.log(process.env)] = null;\n//"` + +client.query(sql, (err, res) => { + client.end() +}) +``` + +You will see your environment variables printed to your console. An attacker can use this exploit to execute any arbitrary node code within your process. + +### Impact + +This vulnerability _likely_ does not impact you if you are connecting to a database you control and not executing user-supplied sql. Still, you should **absolutely** upgrade to the most recent patch version as soon as possible to be safe. + +Two attack vectors we quickly thought of: + +- 1 - executing unsafe, user-supplied sql which contains a malicious column name like the one above. +- 2 - connecting to an untrusted database and executing a query which returns results where any of the column names are malicious. + +### Support + +I have created [an issue](https://github.com/brianc/node-postgres/issues/1408) you can use to discuss the vulnerability with me or ask questions, and I have reported this issue [on twitter](https://twitter.com/briancarlson) and directly to Heroku and [nodesecurity.io](https://nodesecurity.io/). + +I take security very seriously. If you or your company benefit from node-postgres **[please sponsor my work](https://www.patreon.com/node_postgres)**: this type of issue is one of the many things I am responsible for, and I want to be able to continue to tirelessly provide a world-class PostgreSQL experience in node for years to come. diff --git a/docs/pages/apis/_meta.json b/docs/pages/apis/_meta.json new file mode 100644 index 000000000..0b6a193c7 --- /dev/null +++ b/docs/pages/apis/_meta.json @@ -0,0 +1,7 @@ +{ + "client": "pg.Client", + "pool": "pg.Pool", + "result": "pg.Result", + "types": "pg.Types", + "cursor": "Cursor" +} diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx new file mode 100644 index 000000000..c983859b6 --- /dev/null +++ b/docs/pages/apis/client.mdx @@ -0,0 +1,330 @@ +--- +title: pg.Client +--- + +## new Client + +`new Client(config: Config)` + +Every field of the `config` object is entirely optional. A `Client` instance will use [environment variables](/features/connecting#environment-variables) for all missing values. + +```ts +type Config = { + user?: string, // default process.env.PGUSER || process.env.USER + password?: string or function, //default process.env.PGPASSWORD + host?: string, // default process.env.PGHOST + database?: string, // default process.env.PGDATABASE || user + port?: number, // default process.env.PGPORT + connectionString?: string, // e.g. postgres://user:password@host:5432/database + ssl?: any, // passed directly to node.TLSSocket, supports all tls.connect options + types?: any, // custom type parsers + statement_timeout?: number, // number of milliseconds before a statement in query will time out, default is no timeout + query_timeout?: number, // number of milliseconds before a query call will timeout, default is no 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 + idle_in_transaction_session_timeout?: number // number of milliseconds before terminating any session with an open idle transaction, default is no timeout +} +``` + +example to create a client with specific connection information: + +```js +const { Client } = require('pg') + +const client = new Client({ + host: 'my.database-server.com', + port: 5334, + user: 'database-user', + password: 'secretpassword!!', +}) +``` + +## client.connect + +### `client.connect(callback: (err: Error) => void) => void` + +Calling `client.connect` with a callback: + +```js +const { Client } = require('pg') +const client = new Client() +client.connect((err) => { + if (err) { + console.error('connection error', err.stack) + } else { + console.log('connected') + } +}) +``` + +### `client.connect() => Promise` + +Calling `client.connect` without a callback yields a promise: + +```js +const { Client } = require('pg') +const client = new Client() +client + .connect() + .then(() => console.log('connected')) + .catch((err) => console.error('connection error', err.stack)) +``` + +_note: connect returning a promise only available in pg@7.0 or above_ + +## client.query + +### `client.query` - text, optional values, and callback. + +Passing query text, optional query parameters, and a callback to `client.query` results in a type-signature of: + +```ts +client.query( + text: string, + values?: Array, + callback: (err: Error, result: Result) => void +) => void +``` + +That is a kinda gross type signature but it translates out to this: + +**Plain text query with a callback:** + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() +client.query('SELECT NOW()', (err, res) => { + if (err) throw err + console.log(res) + client.end() +}) +``` + +**Parameterized query with a callback:** + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() +client.query('SELECT $1::text as name', ['brianc'], (err, res) => { + if (err) throw err + console.log(res) + client.end() +}) +``` + +### `client.query` - text, optional values: Promise + +If you call `client.query` with query text and optional parameters but **don't** pass a callback, then you will receive a `Promise` for a query result. + +```ts +client.query( + text: string, + values?: Array +) => Promise +``` + +**Plain text query with a promise** + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() +client + .query('SELECT NOW()') + .then((result) => console.log(result)) + .catch((e) => console.error(e.stack)) + .then(() => client.end()) +``` + +**Parameterized query with a promise** + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() +client + .query('SELECT $1::text as name', ['brianc']) + .then((result) => console.log(result)) + .catch((e) => console.error(e.stack)) + .then(() => client.end()) +``` + +### `client.query(config: QueryConfig, callback: (err?: Error, result?: Result) => void) => void` + +### `client.query(config: QueryConfig) => Promise` + +You can pass an object to `client.query` with the signature of: + +```ts +type QueryConfig { + // the raw query text + text: string; + + // an array of query parameters + values?: Array; + + // name of the query - used for prepared statements + name?: string; + + // by default rows come out as a key/value pair for each row + // pass the string 'array' here to receive rows as an array of values + rowMode?: string; + + // custom type parsers just for this query result + types?: Types; +} +``` + +**client.query with a QueryConfig and a callback** + +If you pass a `name` parameter to the `client.query` method, the client will create a [prepared statement](/features/queries#prepared-statements). + +```js +const query = { + name: 'get-name', + text: 'SELECT $1::text', + values: ['brianc'], + rowMode: 'array', +} + +client.query(query, (err, res) => { + if (err) { + console.error(err.stack) + } else { + console.log(res.rows) // ['brianc'] + } +}) +``` + +**client.query with a QueryConfig and a Promise** + +```js +const query = { + name: 'get-name', + text: 'SELECT $1::text', + values: ['brianc'], + rowMode: 'array', +} + +// promise +client + .query(query) + .then((res) => { + console.log(res.rows) // ['brianc'] + }) + .catch((e) => { + console.error(e.stack) + }) +``` + +**client.query with a `Submittable`** + +If you pass an object to `client.query` and the object has a `.submit` function on it, the client will pass it's PostgreSQL server connection to the object and delegate query dispatching to the supplied object. This is an advanced feature mostly intended for library authors. It is incidentally also currently how the callback and promise based queries above are handled internally, but this is subject to change. It is also how [pg-cursor](https://github.com/brianc/node-pg-cursor) and [pg-query-stream](https://github.com/brianc/node-pg-query-stream) work. + +```js +const Query = require('pg').Query +const query = new Query('select $1::text as name', ['brianc']) + +const result = client.query(query) + +assert(query === result) // true + +query.on('row', (row) => { + console.log('row!', row) // { name: 'brianc' } +}) +query.on('end', () => { + console.log('query done') +}) +query.on('error', (err) => { + console.error(err.stack) +}) +``` + +--- + +## client.end + +### client.end(cb?: (err?: Error) => void) => void + +Disconnects the client from the PostgreSQL server. + +```js +client.end((err) => { + console.log('client has disconnected') + if (err) { + console.log('error during disconnection', err.stack) + } +}) +``` + +### `client.end() => Promise` + +Calling end without a callback yields a promise: + +```js +client + .end() + .then(() => console.log('client has disconnected')) + .catch((err) => console.error('error during disconnection', err.stack)) +``` + +_note: end returning a promise is only available in pg7.0 and above_ + +## events + +### client.on('error', (err: Error) => void) => void + +When the client is in the process of connecting, dispatching a query, or disconnecting it will catch and foward errors from the PostgreSQL server to the respective `client.connect` `client.query` or `client.end` callback/promise; however, the client maintains a long-lived connection to the PostgreSQL back-end and due to network partitions, back-end crashes, fail-overs, etc the client can (and over a long enough time period _will_) eventually be disconnected while it is idle. To handle this you may want to attach an error listener to a client to catch errors. Here's a contrived example: + +```js +const client = new pg.Client() +client.connect() + +client.on('error', (err) => { + console.error('something bad has happened!', err.stack) +}) + +// walk over to server, unplug network cable + +// process output: 'something bad has happened!' followed by stacktrace :P +``` + +### client.on('end') => void + +When the client disconnects from the PostgreSQL server it will emit an end event once. + +### client.on('notification', (notification: Notification) => void) => void + +Used for `listen/notify` events: + +```ts +type Notification { + processId: number, + channel: string, + payload?: string +} +``` + +```js +const client = new pg.Client() +client.connect() + +client.query('LISTEN foo') + +client.on('notification', (msg) => { + console.log(msg.channel) // foo + console.log(msg.payload) // bar! +}) + +client.query(`NOTIFY foo, 'bar!'`) +``` + +### client.on('notice', (notice: Error) => void) => void + +Used to log out [notice messages](https://www.postgresql.org/docs/9.6/static/plpgsql-errors-and-messages.html) from the PostgreSQL server. + +```js +client.on('notice', (msg) => console.warn('notice:', msg)) +``` diff --git a/docs/pages/apis/cursor.mdx b/docs/pages/apis/cursor.mdx new file mode 100644 index 000000000..c4a6928c7 --- /dev/null +++ b/docs/pages/apis/cursor.mdx @@ -0,0 +1,81 @@ +--- +title: pg.Cursor +slug: /api/cursor +--- + +A cursor can be used to efficiently read through large result sets without loading the entire result-set into memory ahead of time. It's useful to simulate a 'streaming' style read of data, or exit early from a large result set. The cursor is passed to `client.query` and is dispatched internally in a way very similar to how normal queries are sent, but the API it presents for consuming the result set is different. + +## install + +``` +$ npm install pg pg-cursor +``` + +## constructor + +### `new Cursor(text: String, values: Any[][, config: CursorQueryConfig])` + +Instantiates a new Cursor. A cursor is an instance of `Submittable` and should be passed directly to the `client.query` method. + +```js +const { Pool } = require('pg') +const Cursor = require('pg-cursor') + +const pool = new Pool() +const client = await pool.connect() +const text = 'SELECT * FROM my_large_table WHERE something > $1' +const values = [10] + +const cursor = client.query(new Cursor(text, values)) + +cursor.read(100, (err, rows) => { + cursor.close(() => { + client.release() + }) +}) +``` + +```ts +type CursorQueryConfig { + // by default rows come out as a key/value pair for each row + // pass the string 'array' here to receive rows as an array of values + rowMode?: string; + + // custom type parsers just for this query result + types?: Types; +} +``` + +## read + +### `cursor.read(rowCount: Number, callback: (err: Error, rows: Row[], result: pg.Result) => void) => void` + +Read `rowCount` rows from the cursor instance. The callback will be called when the rows are available, loaded into memory, parsed, and converted to JavaScript types. + +If the cursor has read to the end of the result sets all subsequent calls to cursor#read will return a 0 length array of rows. Calling `read` on a cursor that has read to the end. + +Here is an example of reading to the end of a cursor: + +```js +const { Pool } = require('pg') +const Cursor = require('pg-cursor') + +const pool = new Pool() +const client = await pool.connect() +const cursor = client.query(new Cursor('select * from generate_series(0, 5)')) +cursor.read(100, (err, rows) => { + if (err) { + throw err + } + assert(rows.length == 6) + cursor.read(100, (err, rows) => { + assert(rows.length == 0) + }) +}) +``` + +## close + +### `cursor.close(callback: () => void) => void` + +Used to close the cursor early. If you want to stop reading from the cursor before you get all of the rows returned, call this. diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx new file mode 100644 index 000000000..6ebc19044 --- /dev/null +++ b/docs/pages/apis/pool.mdx @@ -0,0 +1,274 @@ +--- +title: pg.Pool +--- + +import { Alert } from '/components/alert.tsx' + +## new Pool + +```ts +new Pool(config: Config) +``` + +Constructs a new pool instance. + +The pool is initially created empty and will create new clients lazily as they are needed. Every field of the `config` object is entirely optional. The config passed to the pool is also passed to every client instance within the pool when the pool creates that client. + +```ts +type Config = { + // 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 + 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 + idleTimeoutMillis?: number + + // maximum number of clients the pool should contain + // by default this is set to 10. + max?: number + + // Default behavior is the pool will keep clients open & connected to the backend + // until idleTimeoutMillis expire for each client and node will maintain a ref + // to the socket on the client, keeping the event loop alive until all clients are closed + // after being idle or the pool is manually shutdown with `pool.end()`. + // + // 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 + // where you don't want to wait for your clients to go idle before your process exits. + allowExitOnIdle?: boolean +} +``` + +example to create a new pool with configuration: + +```js +const { Pool } = require('pg') + +const pool = new Pool({ + host: 'localhost', + user: 'database-user', + max: 20, + idleTimeoutMillis: 30000, + connectionTimeoutMillis: 2000, +}) +``` + +## pool.query + +Often we only need to run a single query on the database, so as convenience the pool has a method to run a query on the first available idle client and return its result. + +`pool.query() => Promise` + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool + .query('SELECT $1::text as name', ['brianc']) + .then((res) => console.log(res.rows[0].name)) // brianc + .catch((err) => console.error('Error executing query', err.stack)) +``` + +Callbacks are also supported: + +`pool.query(callback: (err?: Error, result: pg.Result)) => void` + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool.query('SELECT $1::text as name', ['brianc'], (err, result) => { + if (err) { + return console.error('Error executing query', err.stack) + } + console.log(result.rows[0].name) // brianc +}) +``` + +Notice in the example above there is no need to check out or release a client. The pool is doing the acquiring and releasing internally. I find `pool.query` to be a handy shortcut many situations and use it exclusively unless I need a transaction. + + +
+ Do not use pool.query if you are using a transaction. +
+ The pool will dispatch every query passed to pool.query on the first available idle client. Transactions within PostgreSQL + are scoped to a single client and so dispatching individual queries within a single transaction across multiple, random + clients will cause big problems in your app and not work. For more info please read + transactions + . +
+ +## pool.connect + +`pool.connect(callback: (err?: Error, client?: pg.Client, release?: releaseCallback) => void) => void` + +Acquires a client from the pool. + +- If there are idle clients in the pool one will be returned to the callback on `process.nextTick`. +- If the pool is not full but all current clients are checked out a new client will be created & returned to this callback. +- If the pool is 'full' and all clients are currently checked out will wait in a FIFO queue until a client becomes available by it being released back to the pool. + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool.connect((err, client, release) => { + if (err) { + return console.error('Error acquiring client', err.stack) + } + client.query('SELECT NOW()', (err, result) => { + release() + if (err) { + return console.error('Error executing query', err.stack) + } + console.log(result.rows) + }) +}) +``` + +`pool.connect() => Promise` + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +;(async function () { + const client = await pool.connect() + await client.query('SELECT NOW()') + client.release() +})() +``` + +### releasing clients + +`release: (err?: Error)` + +Client instances returned from `pool.connect` will have a `release` method which will release them from the pool. + +The `release` method on an acquired client returns it back to the pool. If you pass a truthy value in the `err` position to the callback, instead of releasing the client to the pool, the pool will be instructed to disconnect and destroy this client, leaving a space within itself for a new client. + +```js +const { Pool } = require('pg') + +const pool = new Pool() +// check out a single client +const client = await pool.connect() +// release the client +client.release() +``` + +```js +const { Pool } = require('pg') + +const pool = new Pool() +assert(pool.totalCount === 0) +assert(pool.idleCount === 0) + +const client = await pool.connect() +await client.query('SELECT NOW()') +assert(pool.totalCount === 1) +assert(pool.idleCount === 0) + +// tell the pool to destroy this client +client.release(true) +assert(pool.idleCount === 0) +assert(pool.totalCount === 0) +``` + + +
+ You must release a client when you are finished with it. +
+ If you forget to release the client then your application will quickly exhaust available, idle clients in the pool and + all further calls to pool.connect will timeout with an error or hang indefinitely if you have + connectionTimeoutMillis + configured to 0. +
+ +## pool.end + +Calling `pool.end` will drain the pool of all active clients, disconnect them, and shut down any internal timers in the pool. It is common to call this at the end of a script using the pool or when your process is attempting to shut down cleanly. + +```js +// again both promises and callbacks are supported: +const { Pool } = require('pg') + +const pool = new Pool() + +// either this: +pool.end(() => { + console.log('pool has ended') +}) + +// or this: +pool.end().then(() => console.log('pool has ended')) +``` + +## properties + +`pool.totalCount: number` + +The total number of clients existing within the pool. + +`pool.idleCount: number` + +The number of clients which are not checked out but are currently idle in the pool. + +`pool.waitingCount: number` + +The number of queued requests waiting on a client when all clients are checked out. It can be helpful to monitor this number to see if you need to adjust the size of the pool. + +## events + +`Pool` instances are also instances of [`EventEmitter`](https://nodejs.org/api/events.html). + +### connect + +`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. + +```js +const pool = new Pool() +pool.on('connect', (client) => { + client.query('SET DATESTYLE = iso, mdy') +}) +``` + +### acquire + +`pool.on('acquire', (client: Client) => void) => void` + +Whenever a client is checked out from the pool the pool will emit the `acquire` event with the client that was acquired. + +### error + +`pool.on('error', (err: Error, client: Client) => void) => void` + +When a client is sitting idly in the pool it can still emit errors because it is connected to a live backend. + +If the backend goes down or a network partition is encountered all the idle, connected clients in your application will emit an error _through_ the pool's error event emitter. + +The error listener is passed the error as the first argument and the client upon which the error occurred as the 2nd argument. The client will be automatically terminated and removed from the pool, it is only passed to the error handler in case you want to inspect it. + + +
You probably want to add an event listener to the pool to catch background errors errors!
+ Just like other event emitters, if a pool emits an error event and no listeners are added node will emit an + uncaught error and potentially crash your node process. +
+ +### remove + +`pool.on('remove', (client: Client) => void) => void` + +Whenever a client is closed & removed from the pool the pool will emit the `remove` event. diff --git a/docs/pages/apis/result.mdx b/docs/pages/apis/result.mdx new file mode 100644 index 000000000..a0ef7ddb8 --- /dev/null +++ b/docs/pages/apis/result.mdx @@ -0,0 +1,52 @@ +--- +title: pg.Result +slug: /api/result +--- + +The `pg.Result` shape is returned for every successful query. + +
note: you cannot instantiate this directly
+ +## properties + +### `result.rows: Array` + +Every result will have a rows array. If no rows are returned the array will be empty. Otherwise the array will contain one item for each row returned from the query. By default node-postgres creates a map from the name to value of each column, giving you a json-like object back for each row. + +### `result.fields: Array` + +Every result will have a fields array. This array contains the `name` and `dataTypeID` of each field in the result. These fields are ordered in the same order as the columns if you are using `arrayMode` for the query: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +const client = await pool.connect() +const result = await client.query({ + rowMode: 'array', + text: 'SELECT 1 as one, 2 as two;', +}) +console.log(result.fields[0].name) // one +console.log(result.fields[1].name) // two +console.log(result.rows) // [ [ 1, 2 ] ] +await client.end() +``` + +### `result.command: string` + +The command type last executed: `INSERT` `UPDATE` `CREATE` `SELECT` etc. + +### `result.rowCount: int` + +The number of rows processed by the last command. + +_note: this does not reflect the number of rows __returned__ from a query. e.g. an update statement could update many rows (so high `result.rowCount` value) but `result.rows.length` would be zero. To check for an empty query reponse on a `SELECT` query use `result.rows.length === 0`_. + +[@sehrope](https://github.com/brianc/node-postgres/issues/2182#issuecomment-620553915) has a good explanation: + +The `rowCount` is populated from the command tag supplied by the PostgreSQL server. It's generally of the form: `COMMAND [OID] [ROWS]` + +For DML commands (INSERT, UPDATE, etc), it reflects how many rows the server modified to process the command. For SELECT or COPY commands it reflects how many rows were retrieved or copied. More info on the specifics here: https://www.postgresql.org/docs/current/protocol-message-formats.html (search for CommandComplete for the message type) + +The note in the docs about the difference is because that value is controlled by the server. It's possible for a non-standard server (ex: PostgreSQL fork) or a server version in the future to provide different information in some situations so it'd be best not to rely on it to assume that the rows array length matches the `rowCount`. It's fine to use it for DML counts though. diff --git a/docs/pages/apis/types.mdx b/docs/pages/apis/types.mdx new file mode 100644 index 000000000..55f3b0009 --- /dev/null +++ b/docs/pages/apis/types.mdx @@ -0,0 +1,6 @@ +--- +title: Types +slug: /api/types +--- + +These docs are incomplete, for now please reference [pg-types docs](https://github.com/brianc/node-pg-types). diff --git a/docs/pages/features/_meta.json b/docs/pages/features/_meta.json new file mode 100644 index 000000000..a2f5e340a --- /dev/null +++ b/docs/pages/features/_meta.json @@ -0,0 +1,9 @@ +{ + "connecting": "Connecting", + "queries": "Queries", + "pooling": "Pooling", + "transactions": "Transactions", + "types": "Data Types", + "ssl": "SSL", + "native": "Native" +} diff --git a/docs/pages/features/connecting.mdx b/docs/pages/features/connecting.mdx new file mode 100644 index 000000000..b3c5ecc40 --- /dev/null +++ b/docs/pages/features/connecting.mdx @@ -0,0 +1,162 @@ +--- +title: Connecting +--- + +## Environment variables + +node-postgres uses the same [environment variables](https://www.postgresql.org/docs/9.1/static/libpq-envars.html) as libpq and psql to connect to a PostgreSQL server. Both individual clients & pools will use these environment variables. Here's a tiny program connecting node.js to the PostgreSQL server: + +```js +const { Pool, Client } = require('pg') + +// pools will use environment variables +// for connection information +const pool = new Pool() + +pool.query('SELECT NOW()', (err, res) => { + console.log(err, res) + pool.end() +}) + +// you can also use async/await +const res = await pool.query('SELECT NOW()') +await pool.end() + +// clients will also use environment variables +// for connection information +const client = new Client() +await client.connect() + +const res = await client.query('SELECT NOW()') +await client.end() +``` + +To run the above program and specify which database to connect to we can invoke it like so: + +```sh +$ PGUSER=dbuser \ + PGHOST=database.server.com \ + PGPASSWORD=secretpassword \ + PGDATABASE=mydb \ + PGPORT=3211 \ + node script.js +``` + +This allows us to write our programs without having to specify connection information in the program and lets us reuse them to connect to different databases without having to modify the code. + +The default values for the environment variables used are: + +``` +PGHOST=localhost +PGUSER=process.env.USER +PGDATABASE=process.env.USER +PGPASSWORD=null +PGPORT=5432 +``` + +## Programmatic + +node-postgres also supports configuring a pool or client programmatically with connection information. Here's our same script from above modified to use programmatic (hard-coded in this case) values. This can be useful if your application already has a way to manage config values or you don't want to use environment variables. + +```js +const { Pool, Client } = require('pg') + +const pool = new Pool({ + user: 'dbuser', + host: 'database.server.com', + database: 'mydb', + password: 'secretpassword', + port: 3211, +}) + +pool.query('SELECT NOW()', (err, res) => { + console.log(err, res) + pool.end() +}) + +const client = new Client({ + user: 'dbuser', + host: 'database.server.com', + database: 'mydb', + password: 'secretpassword', + port: 3211, +}) +client.connect() + +client.query('SELECT NOW()', (err, res) => { + console.log(err, res) + client.end() +}) +``` + +Many cloud providers include alternative methods for connecting to database instances using short-lived authentication tokens. node-postgres supports dynamic passwords via a callback function, either synchronous or asynchronous. The callback function must resolve to a string. + +```js +const { Pool } = require('pg') +const { RDS } = require('aws-sdk') + +const signerOptions = { + credentials: { + accessKeyId: 'YOUR-ACCESS-KEY', + secretAccessKey: 'YOUR-SECRET-ACCESS-KEY', + }, + region: 'us-east-1', + hostname: 'example.aslfdewrlk.us-east-1.rds.amazonaws.com', + port: 5432, + username: 'api-user', +} + +const signer = new RDS.Signer() + +const getPassword = () => signer.getAuthToken(signerOptions) + +const pool = new Pool({ + host: signerOptions.hostname, + port: signerOptions.port, + user: signerOptions.username, + database: 'my-db', + password: getPassword, +}) +``` + +### Unix Domain Sockets + +Connections to unix sockets can also be made. This can be useful on distros like Ubuntu, where authentication is managed via the socket connection instead of a password. + +```js +const { Client } = require('pg') +client = new Client({ + host: '/cloudsql/myproject:zone:mydb', + user: 'username', + password: 'password', + database: 'database_name', +}) +``` + +## Connection URI + +You can initialize both a pool and a client with a connection string URI as well. This is common in environments like Heroku where the database connection string is supplied to your application dyno through an environment variable. Connection string parsing brought to you by [pg-connection-string](https://github.com/iceddev/pg-connection-string). + +```js +const { Pool, Client } = require('pg') +const connectionString = 'postgresql://dbuser:secretpassword@database.server.com:3211/mydb' + +const pool = new Pool({ + connectionString, +}) + +pool.query('SELECT NOW()', (err, res) => { + console.log(err, res) + pool.end() +}) + +const client = new Client({ + connectionString, +}) +client.connect() + +client.query('SELECT NOW()', (err, res) => { + console.log(err, res) + client.end() +}) +``` diff --git a/docs/pages/features/native.mdx b/docs/pages/features/native.mdx new file mode 100644 index 000000000..698d6817b --- /dev/null +++ b/docs/pages/features/native.mdx @@ -0,0 +1,27 @@ +--- +title: Native Bindings +slug: /features/native +metaTitle: bar +--- + +Native bindings between node.js & [libpq](https://www.postgresql.org/docs/9.5/static/libpq.html) are provided by the [node-pg-native](https://github.com/brianc/node-pg-native) package. node-postgres can consume this package & use the native bindings to access the PostgreSQL server while giving you the same interface that is used with the JavaScript version of the library. + +To use the native bindings first you'll need to install them: + +```sh +$ npm install pg pg-native +``` + +Once `pg-native` is installed instead of requiring a `Client` or `Pool` constructor from `pg` you do the following: + +```js +const { Client, Pool } = require('pg').native +``` + +When you access the `.native` property on `require('pg')` it will automatically require the `pg-native` package and wrap it in the same API. + +
+ Care has been taken to normalize between the two, but there might still be edge cases where things behave subtly differently due to the nature of using libpq over handling the binary protocol directly in JavaScript, so it's recommended you chose to either use the JavaScript driver or the native bindings both in development and production. For what its worth: I use the pure JavaScript driver because the JavaScript driver is more portable (doesn't need a compiler), and the pure JavaScript driver is plenty fast. +
+ +Some of the modules using advanced features of PostgreSQL such as [pg-query-stream](https://github.com/brianc/node-pg-query-stream), [pg-cursor](https://github.com/brianc/node-pg-cursor),and [pg-copy-streams](https://github.com/brianc/node-pg-copy-streams) need to operate directly on the binary stream and therefore are incompatible with the native bindings. diff --git a/docs/pages/features/pooling.mdx b/docs/pages/features/pooling.mdx new file mode 100644 index 000000000..4719150be --- /dev/null +++ b/docs/pages/features/pooling.mdx @@ -0,0 +1,173 @@ +--- +title: Pooling +--- + +import { Alert } from '/components/alert.tsx' +import { Info } from '/components/info.tsx' + +If you're working on a web application or other software which makes frequent queries you'll want to use a connection pool. + +The easiest and by far most common way to use node-postgres is through a connection pool. + +## Why? + +- Connecting a new client to the PostgreSQL server requires a handshake which can take 20-30 milliseconds. During this time passwords are negotiated, SSL may be established, and configuration information is shared with the client & server. Incurring this cost _every time_ we want to execute a query would substantially slow down our application. + +- The PostgreSQL server can only handle a [limited number of clients at a time](https://wiki.postgresql.org/wiki/Number_Of_Database_Connections). Depending on the available memory of your PostgreSQL server you may even crash the server if you connect an unbounded number of clients. _note: I have crashed a large production PostgreSQL server instance in RDS by opening new clients and never disconnecting them in a python application long ago. It was not fun._ + +- PostgreSQL can only process one query at a time on a single connected client in a first-in first-out manner. If your multi-tenant web application is using only a single connected client all queries among all simultaneous requests will be pipelined and executed serially, one after the other. No good! + +### Good news + +node-postgres ships with built-in connection pooling via the [pg-pool](/api/pool) module. + +## Examples + +The client pool allows you to have a reusable pool of clients you can check out, use, and return. You generally want a limited number of these in your application and usually just 1. Creating an unbounded number of pools defeats the purpose of pooling at all. + +### Checkout, use, and return + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +// the pool will emit an error on behalf of any idle clients +// it contains if a backend error or network partition happens +pool.on('error', (err, client) => { + console.error('Unexpected error on idle client', err) + process.exit(-1) +}) + +// callback - checkout a client +pool.connect((err, client, done) => { + if (err) throw err + client.query('SELECT * FROM users WHERE id = $1', [1], (err, res) => { + done() + + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + } + }) +}) + +// promise - checkout a client +pool.connect().then((client) => { + return client + .query('SELECT * FROM users WHERE id = $1', [1]) + .then((res) => { + client.release() + console.log(res.rows[0]) + }) + .catch((err) => { + client.release() + console.log(err.stack) + }) +}) + +// async/await - check out a client +;(async () => { + const client = await pool.connect() + try { + const res = await client.query('SELECT * FROM users WHERE id = $1', [1]) + console.log(res.rows[0]) + } catch (err) { + console.log(err.stack) + } finally { + client.release() + } +})() +``` + + +
+ You must always return the client to the pool if you successfully check it out, regardless of whether or not + there was an error with the queries you ran on the client. +
+ If you don't release the client your application will leak them and eventually your pool will be empty forever and all + future requests to check out a client from the pool will wait forever. +
+ +### Single query + +If you don't need a transaction or you just need to run a single query, the pool has a convenience method to run a query on any available client in the pool. This is the preferred way to query with node-postgres if you can as it removes the risk of leaking a client. + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool.query('SELECT * FROM users WHERE id = $1', [1], (err, res) => { + if (err) { + throw err + } + + console.log('user:', res.rows[0]) +}) +``` + +node-postgres also has built-in support for promises throughout all of its async APIs. + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool + .query('SELECT * FROM users WHERE id = $1', [1]) + .then((res) => console.log('user:', res.rows[0])) + .catch((err) => + setImmediate(() => { + throw err + }) + ) +``` + +Promises allow us to use `async`/`await` in node v8.0 and above (or earlier if you're using babel). + +```js +const { Pool } = require('pg') +const pool = new Pool() + +const { rows } = await pool.query('SELECT * FROM users WHERE id = $1', [1]) +console.log('user:', rows[0]) +``` + +### Shutdown + +To shut down a pool call `pool.end()` on the pool. This will wait for all checked-out clients to be returned and then shut down all the clients and the pool timers. + +```js +const { Pool } = require('pg') +const pool = new Pool() + +console.log('starting async query') +const result = await pool.query('SELECT NOW()') +console.log('async query finished') + +console.log('starting callback query') +pool.query('SELECT NOW()', (err, res) => { + console.log('callback query finished') +}) + +console.log('calling end') +await pool.end() +console.log('pool has drained') +``` + +The output of the above will be: + +``` +starting async query +async query finished +starting callback query +calling end +callback query finished +pool has drained +``` + + + The pool will return errors when attempting to check out a client after you've called pool.end() on the pool. + diff --git a/docs/pages/features/queries.mdx b/docs/pages/features/queries.mdx new file mode 100644 index 000000000..0deef0d0d --- /dev/null +++ b/docs/pages/features/queries.mdx @@ -0,0 +1,211 @@ +--- +title: Queries +slug: /features/queries +--- + +The api for executing queries supports both callbacks and promises. I'll provide an example for both _styles_ here. For the sake of brevity I am using the `client.query` method instead of the `pool.query` method - both methods support the same API. In fact, `pool.query` delegates directly to `client.query` internally. + +## Text only + +If your query has no parameters you do not need to include them to the query method: + +```js +// callback +client.query('SELECT NOW() as now', (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + } +}) + +// promise +client + .query('SELECT NOW() as now') + .then(res => console.log(res.rows[0])) + .catch(e => console.error(e.stack)) +``` + +## Parameterized query + +If you are passing parameters to your queries you will want to avoid string concatenating parameters into the query text directly. This can (and often does) lead to sql injection vulnerabilities. node-postgres supports parameterized queries, passing your query text _unaltered_ as well as your parameters to the PostgreSQL server where the parameters are safely substituted into the query with battle-tested parameter substitution code within the server itself. + +```js +const text = 'INSERT INTO users(name, email) VALUES($1, $2) RETURNING *' +const values = ['brianc', 'brian.m.carlson@gmail.com'] + +// callback +client.query(text, values, (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + // { name: 'brianc', email: 'brian.m.carlson@gmail.com' } + } +}) + +// promise +client + .query(text, values) + .then(res => { + console.log(res.rows[0]) + // { name: 'brianc', email: 'brian.m.carlson@gmail.com' } + }) + .catch(e => console.error(e.stack)) + +// async/await +try { + const res = await client.query(text, values) + console.log(res.rows[0]) + // { name: 'brianc', email: 'brian.m.carlson@gmail.com' } +} catch (err) { + console.log(err.stack) +} +``` + +
+ 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 package for handling escaping these values to ensure you do not have SQL injection! +
+ +Parameters passed as the second argument to `query()` will be converted to raw data types using the following rules: + +**null and undefined** + +If parameterizing `null` and `undefined` then both will be converted to `null`. + +**Date** + +Custom conversion to a UTC date string. + +**Buffer** + +Buffer instances are unchanged. + +**Array** + +Converted to a string that describes a Postgres array. Each array item is recursively converted using the rules described here. + +**Object** + +If a parameterized value has the method `toPostgres` then it will be called and its return value will be used in the query. +The signature of `toPostgres` is the following: + +``` +toPostgres (prepareValue: (value) => any): any +``` + +The `prepareValue` function provided can be used to convert nested types to raw data types suitable for the database. + +Otherwise if no `toPostgres` method is defined then `JSON.stringify` is called on the parameterized value. + +**Everything else** + +All other parameterized values will be converted by calling `value.toString` on the value. + +## Query config object + +`pool.query` and `client.query` both support taking a config object as an argument instead of taking a string and optional array of parameters. The same example above could also be performed like so: + +```js +const query = { + text: 'INSERT INTO users(name, email) VALUES($1, $2)', + values: ['brianc', 'brian.m.carlson@gmail.com'], +} + +// callback +client.query(query, (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + } +}) + +// promise +client + .query(query) + .then(res => console.log(res.rows[0])) + .catch(e => console.error(e.stack)) +``` + +The query config object allows for a few more advanced scenarios: + +### Prepared statements + +PostgreSQL has the concept of a [prepared statement](https://www.postgresql.org/docs/9.3/static/sql-prepare.html). node-postgres supports this by supplying a `name` parameter to the query config object. If you supply a `name` parameter the query execution plan will be cached on the PostgreSQL server on a **per connection basis**. This means if you use two different connections each will have to parse & plan the query once. node-postgres handles this transparently for you: a client only requests a query to be parsed the first time that particular client has seen that query name: + +```js +const query = { + // give the query a unique name + name: 'fetch-user', + text: 'SELECT * FROM user WHERE id = $1', + values: [1], +} + +// callback +client.query(query, (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + } +}) + +// promise +client + .query(query) + .then(res => console.log(res.rows[0])) + .catch(e => console.error(e.stack)) +``` + +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. +
+
+ +### Row mode + +By default node-postgres reads rows and collects them into JavaScript objects with the keys matching the column names and the values matching the corresponding row value for each column. If you do not need or do not want this behavior you can pass `rowMode: 'array'` to a query object. This will inform the result parser to bypass collecting rows into a JavaScript object, and instead will return each row as an array of values. + +```js +const query = { + text: 'SELECT $1::text as first_name, $2::text as last_name', + values: ['Brian', 'Carlson'], + rowMode: 'array', +} + +// callback +client.query(query, (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.fields.map(field => field.name)) // ['first_name', 'last_name'] + console.log(res.rows[0]) // ['Brian', 'Carlson'] + } +}) + +// promise +client + .query(query) + .then(res => { + console.log(res.fields.map(field => field.name)) // ['first_name', 'last_name'] + console.log(res.rows[0]) // ['Brian', 'Carlson'] + }) + .catch(e => console.error(e.stack)) +``` + +### Types + +You can pass in a custom set of type parsers to use when parsing the results of a particular query. The `types` property must conform to the [Types](/api/types) API. Here is an example in which every value is returned as a string: + +```js +const query = { + text: 'SELECT * from some_table', + types: { + getTypeParser: () => val => val, + }, +} +``` diff --git a/docs/pages/features/ssl.mdx b/docs/pages/features/ssl.mdx new file mode 100644 index 000000000..0428d0549 --- /dev/null +++ b/docs/pages/features/ssl.mdx @@ -0,0 +1,61 @@ +--- +title: SSL +slug: /features/ssl +--- + +node-postgres supports TLS/SSL connections to your PostgreSQL server as long as the server is configured to support it. When instantiating a pool or a client you can provide an `ssl` property on the config object and it will be passed to the constructor for the [node TLSSocket](https://nodejs.org/api/tls.html#tls_class_tls_tlssocket). + +## Self-signed cert + +Here's an example of a configuration you can use to connect a client or a pool to a PostgreSQL server. + +```js +const config = { + database: 'database-name', + 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(), + }, +} + +import { Client, Pool } from 'pg' + +const client = new Client(config) +client.connect(err => { + if (err) { + console.error('error connecting', err.stack) + } else { + console.log('connected') + client.end() + } +}) + +const pool = new Pool(config) +pool + .connect() + .then(client => { + console.log('connected') + client.release() + }) + .catch(err => console.error('error connecting', err.stack)) + .then(() => pool.end()) +``` + +## Usage with `connectionString` + +If you plan to use a combination of a database connection string from the environment and SSL settings in the config object directly, then you must avoid including any of `sslcert`, `sslkey`, `sslrootcert`, or `sslmode` in the connection string. If any of these options are used then the `ssl` object is replaced and any additional options provided there will be lost. + +```js +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(), + }, +} +``` diff --git a/docs/pages/features/transactions.mdx b/docs/pages/features/transactions.mdx new file mode 100644 index 000000000..408db52f8 --- /dev/null +++ b/docs/pages/features/transactions.mdx @@ -0,0 +1,93 @@ +--- +title: Transactions +--- + +import { Alert } from '/components/alert.tsx' + +To execute a transaction with node-postgres you simply execute `BEGIN / COMMIT / ROLLBACK` queries yourself through a client. Because node-postgres strives to be low level and un-opinionated, it doesn't provide any higher level abstractions specifically around transactions. + + + You must use the same client instance for all statements within a transaction. PostgreSQL + isolates a transaction to individual clients. This means if you initialize or use transactions with the{' '} + pool.query method you will have problems. Do not use transactions with + the pool.query method. + + +## Examples + +### async/await + +Things are considerably more straightforward if you're using async/await: + +```js +const { Pool } = require('pg') +const pool = new Pool() + +// note: we don't try/catch this because if connecting throws an exception +// we don't need to dispose of the client (it will be undefined) +const client = await pool.connect() + +try { + await client.query('BEGIN') + const queryText = 'INSERT INTO users(name) VALUES($1) RETURNING id' + const res = await client.query(queryText, ['brianc']) + + const insertPhotoText = 'INSERT INTO photos(user_id, photo_url) VALUES ($1, $2)' + const insertPhotoValues = [res.rows[0].id, 's3.bucket.foo'] + await client.query(insertPhotoText, insertPhotoValues) + await client.query('COMMIT') +} catch (e) { + await client.query('ROLLBACK') + throw e +} finally { + client.release() +} +``` + +### callbacks + +node-postgres is a very old library, and still has an optional callback API. Here's an example of doing the same code above, but with callbacks: + +```js +const { Pool } = require('pg') +const pool = new Pool() + +pool.connect((err, client, done) => { + const shouldAbort = (err) => { + if (err) { + console.error('Error in transaction', err.stack) + client.query('ROLLBACK', (err) => { + if (err) { + console.error('Error rolling back client', err.stack) + } + // release the client back to the pool + done() + }) + } + return !!err + } + + client.query('BEGIN', (err) => { + if (shouldAbort(err)) return + const queryText = 'INSERT INTO users(name) VALUES($1) RETURNING id' + client.query(queryText, ['brianc'], (err, res) => { + if (shouldAbort(err)) return + + const insertPhotoText = 'INSERT INTO photos(user_id, photo_url) VALUES ($1, $2)' + const insertPhotoValues = [res.rows[0].id, 's3.bucket.foo'] + client.query(insertPhotoText, insertPhotoValues, (err, res) => { + if (shouldAbort(err)) return + + client.query('COMMIT', (err) => { + if (err) { + console.error('Error committing transaction', err.stack) + } + done() + }) + }) + }) + }) +}) +``` + +..thank goodness for `async/await` yeah? diff --git a/docs/pages/features/types.mdx b/docs/pages/features/types.mdx new file mode 100644 index 000000000..65c814bae --- /dev/null +++ b/docs/pages/features/types.mdx @@ -0,0 +1,106 @@ +--- +title: Data Types +--- + +import { Alert } from '/components/alert.tsx' + +PostgreSQL has a rich system of supported [data types](https://www.postgresql.org/docs/9.5/static/datatype.html). node-postgres does its best to support the most common data types out of the box and supplies an extensible type parser to allow for custom type serialization and parsing. + +## strings by default + +node-postgres will convert a database type to a JavaScript string if it doesn't have a registered type parser for the database type. Furthermore, you can send any type to the PostgreSQL server as a string and node-postgres will pass it through without modifying it in any way. To circumvent the type parsing completely do something like the following. + +```js +const queryText = 'SELECT int_col::text, date_col::text, json_col::text FROM my_table' +const result = await client.query(queryText) + +console.log(result.rows[0]) // will contain the unparsed string value of each column +``` + +## type parsing examples + +### uuid + json / jsonb + +There is no data type in JavaScript for a uuid/guid so node-postgres converts a uuid to a string. JavaScript has great support for JSON and node-postgres converts json/jsonb objects directly into their JavaScript object via [`JSON.parse`](https://github.com/brianc/node-pg-types/blob/master/lib/textParsers.js#L193). Likewise sending an object to the PostgreSQL server via a query from node-postgres, node-posgres will call [`JSON.stringify`](https://github.com/brianc/node-postgres/blob/e5f0e5d36a91a72dda93c74388ac890fa42b3be0/lib/utils.js#L47) on your outbound value, automatically converting it to json for the server. + +```js +const createTableText = ` +CREATE EXTENSION IF NOT EXISTS "pgcrypto"; + +CREATE TEMP TABLE IF NOT EXISTS users ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + data JSONB +); +` +// create our temp table +await client.query(createTableText) + +const newUser = { email: 'brian.m.carlson@gmail.com' } +// create a new user +await client.query('INSERT INTO users(data) VALUES($1)', [newUser]) + +const { rows } = await client.query('SELECT * FROM users') + +console.log(rows) +/* +output: +[{ + id: 'd70195fd-608e-42dc-b0f5-eee975a621e9', + data: { email: 'brian.m.carlson@gmail.com' } +}] +*/ +``` + +### date / timestamp / timestamptz + +node-postgres will convert instances of JavaScript date objects into the expected input value for your PostgreSQL server. Likewise, when reading a `date`, `timestamp`, or `timestamptz` column value back into JavaScript, node-postgres will parse the value into an instance of a JavaScript `Date` object. + +```js +const createTableText = ` +CREATE TEMP TABLE dates( + date_col DATE, + timestamp_col TIMESTAMP, + timestamptz_col TIMESTAMPTZ +); +` +// create our temp table +await client.query(createTableText) + +// insert the current time into it +const now = new Date() +const insertText = 'INSERT INTO dates(date_col, timestamp_col, timestamptz_col) VALUES ($1, $2, $3)' +await client.query(insertText, [now, now, now]) + +// read the row back out +const result = await client.query('SELECT * FROM dates') + +console.log(result.rows) +// { +// date_col: 2017-05-29T05:00:00.000Z, +// timestamp_col: 2017-05-29T23:18:13.263Z, +// timestamptz_col: 2017-05-29T23:18:13.263Z +// } +``` + +psql output: + +``` +bmc=# select * from dates; + date_col | timestamp_col | timestamptz_col +------------+-------------------------+---------------------------- + 2017-05-29 | 2017-05-29 18:18:13.263 | 2017-05-29 18:18:13.263-05 +(1 row) +``` + +node-postgres converts `DATE` and `TIMESTAMP` columns into the **local** time of the node process set at `process.env.TZ`. + +_note: I generally use `TIMESTAMPTZ` when storing dates; otherwise, inserting a time from a process in one timezone and reading it out in a process in another timezone can cause unexpected differences in the time._ + + +
+ Although PostgreSQL supports microseconds in dates, JavaScript only supports dates to the millisecond precision. + Keep this in mind when you send dates to and from PostgreSQL from node: your microseconds will be truncated when + converting to a JavaScript date object even if they exist in the database. If you need to preserve them, I recommend + using a custom type parser. +
+
diff --git a/docs/pages/guides/_meta.json b/docs/pages/guides/_meta.json new file mode 100644 index 000000000..3889a0992 --- /dev/null +++ b/docs/pages/guides/_meta.json @@ -0,0 +1,5 @@ +{ + "project-structure": "Suggested Code Structure", + "async-express": "Express with Async/Await", + "upgrading": "Upgrading" +} diff --git a/docs/pages/guides/async-express.md b/docs/pages/guides/async-express.md new file mode 100644 index 000000000..3be6d955a --- /dev/null +++ b/docs/pages/guides/async-express.md @@ -0,0 +1,83 @@ +--- +title: Express with async/await +--- + +My preferred way to use node-postgres (and all async code in node.js) is with `async/await`. I find it makes reasoning about control-flow easier and allows me to write more concise and maintainable code. + +This is how I typically structure express web-applications with node-postgres to use `async/await`: + +``` +- app.js +- index.js +- routes/ + - index.js + - photos.js + - user.js +- db/ + - index.js <--- this is where I put data access code +``` + +That's the same structure I used in the [project structure](/guides/project-structure) example. + +My `db/index.js` file usually starts out like this: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params) => pool.query(text, params), +} +``` + +Then I will install [express-promise-router](https://www.npmjs.com/package/express-promise-router) and use it to define my routes. Here is my `routes/user.js` file: + +```js +const Router = require('express-promise-router') + +const db = require('../db') + +// create a new express-promise-router +// this has the same API as the normal express router except +// it allows you to use async functions as route handlers +const router = new Router() + +// export our router to be mounted by the parent application +module.exports = router + +router.get('/:id', async (req, res) => { + const { id } = req.params + const { rows } = await db.query('SELECT * FROM users WHERE id = $1', [id]) + res.send(rows[0]) +}) +``` + +Then in my `routes/index.js` file I'll have something like this which mounts each individual router into the main application: + +```js +// ./routes/index.js +const users = require('./user') +const photos = require('./photos') + +module.exports = (app) => { + app.use('/users', users) + app.use('/photos', photos) + // etc.. +} +``` + +And finally in my `app.js` file where I bootstrap express I will have my `routes/index.js` file mount all my routes. The routes know they're using async functions but because of express-promise-router the main express app doesn't know and doesn't care! + +```js +// ./app.js +const express = require('express') +const mountRoutes = require('./routes') + +const app = express() +mountRoutes(app) + +// ... more express setup stuff can follow +``` + +Now you've got `async/await`, node-postgres, and express all working together! diff --git a/docs/pages/guides/project-structure.md b/docs/pages/guides/project-structure.md new file mode 100644 index 000000000..742451daa --- /dev/null +++ b/docs/pages/guides/project-structure.md @@ -0,0 +1,197 @@ +--- +title: Suggested Project Structure +--- + +Whenever I am writing a project & using node-postgres I like to create a file within it and make all interactions with the database go through this file. This serves a few purposes: + +- Allows my project to adjust to any changes to the node-postgres API without having to trace down all the places I directly use node-postgres in my application. +- Allows me to have a single place to put logging and diagnostics around my database. +- Allows me to make custom extensions to my database access code & share it throughout the project. +- Allows a single place to bootstrap & configure the database. + +## example + +_note: I am using callbacks in this example to introduce as few concepts as possible at a time, but the same is doable with promises or async/await_ + +The location doesn't really matter - I've found it usually ends up being somewhat app specific and in line with whatever folder structure conventions you're using. For this example I'll use an express app structured like so: + +``` +- app.js +- index.js +- routes/ + - index.js + - photos.js + - user.js +- db/ + - index.js <--- this is where I put data access code +``` + +Typically I'll start out my `db/index.js` file like so: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params, callback) => { + return pool.query(text, params, callback) + }, +} +``` + +That's it. But now everywhere else in my application instead of requiring `pg` directly, I'll require this file. Here's an example of a route within `routes/user.js`: + +```js +// notice here I'm requiring my database adapter file +// and not requiring node-postgres directly +const db = require('../db') + +app.get('/:id', (req, res, next) => { + db.query('SELECT * FROM users WHERE id = $1', [req.params.id], (err, result) => { + if (err) { + return next(err) + } + res.send(result.rows[0]) + }) +}) + +// ... many other routes in this file +``` + +Imagine we have lots of routes scattered throughout many files under our `routes/` directory. We now want to go back and log every single query that's executed, how long it took, and the number of rows it returned. If we had required node-postgres directly in every route file we'd have to go edit every single route - that would take forever & be really error prone! But thankfully we put our data access into `db/index.js`. Let's go add some logging: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params, callback) => { + const start = Date.now() + return pool.query(text, params, (err, res) => { + const duration = Date.now() - start + console.log('executed query', { text, duration, rows: res.rowCount }) + callback(err, res) + }) + }, +} +``` + +That was pretty quick! And now all of our queries everywhere in our application are being logged. + +_note: I didn't log the query parameters. Depending on your application you might be storing encrypted passwords or other sensitive information in your database. If you log your query parameters you might accidentally log sensitive information. Every app is different though so do what suits you best!_ + +Now what if we need to check out a client from the pool to run several queries in a row in a transaction? We can add another method to our `db/index.js` file when we need to do this: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params, callback) => { + const start = Date.now() + return pool.query(text, params, (err, res) => { + const duration = Date.now() - start + console.log('executed query', { text, duration, rows: res.rowCount }) + callback(err, res) + }) + }, + getClient: (callback) => { + pool.connect((err, client, done) => { + callback(err, client, done) + }) + }, +} +``` + +Okay. Great - the simplest thing that could possibly work. It seems like one of our routes that checks out a client to run a transaction is forgetting to call `done` in some situation! Oh no! We are leaking a client & have hundreds of these routes to go audit. Good thing we have all our client access going through this single file. Lets add some deeper diagnostic information here to help us track down where the client leak is happening. + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params, callback) => { + const start = Date.now() + return pool.query(text, params, (err, res) => { + const duration = Date.now() - start + console.log('executed query', { text, duration, rows: res.rowCount }) + callback(err, res) + }) + }, + getClient: (callback) => { + pool.connect((err, client, done) => { + const query = client.query + + // monkey patch the query method to keep track of the last query executed + client.query = (...args) => { + client.lastQuery = args + return query.apply(client, args) + } + + // set a timeout of 5 seconds, after which we will log this client's last query + const timeout = setTimeout(() => { + console.error('A client has been checked out for more than 5 seconds!') + console.error(`The last executed query on this client was: ${client.lastQuery}`) + }, 5000) + + const release = (err) => { + // call the actual 'done' method, returning this client to the pool + done(err) + + // clear our timeout + clearTimeout(timeout) + + // set the query method back to its old un-monkey-patched version + client.query = query + } + + callback(err, client, release) + }) + }, +} +``` + +Using async/await: + +```js +module.exports = { + async query(text, params) { + const start = Date.now() + const res = await pool.query(text, params) + const duration = Date.now() - start + console.log('executed query', { text, duration, rows: res.rowCount }) + return res + }, + + async getClient() { + const client = await pool.connect() + const query = client.query + const release = client.release + // set a timeout of 5 seconds, after which we will log this client's last query + const timeout = setTimeout(() => { + console.error('A client has been checked out for more than 5 seconds!') + console.error(`The last executed query on this client was: ${client.lastQuery}`) + }, 5000) + // monkey patch the query method to keep track of the last query executed + client.query = (...args) => { + client.lastQuery = args + return query.apply(client, args) + } + client.release = () => { + // clear our timeout + clearTimeout(timeout) + // set the methods back to their old un-monkey-patched version + client.query = query + client.release = release + return release.apply(client) + } + return client + }, +} +``` + +That should hopefully give us enough diagnostic information to track down any leaks. diff --git a/docs/pages/guides/upgrading.md b/docs/pages/guides/upgrading.md new file mode 100644 index 000000000..2a1d311a2 --- /dev/null +++ b/docs/pages/guides/upgrading.md @@ -0,0 +1,114 @@ +--- +title: Upgrading +slug: /guides/upgrading +--- + +# Upgrading to 8.0 + +node-postgres at 8.0 introduces a breaking change to ssl-verified connections. If you connect with ssl and use + +``` +const client = new Client({ ssl: true }) +``` + +and the server's SSL certificate is self-signed, connections will fail as of node-postgres 8.0. To keep the existing behavior, modify the invocation to + +``` +const client = new Client({ ssl: { rejectUnauthorized: false } }) +``` + +The rest of the changes are relatively minor and unlikely to cause issues; see [the announcement](/announcements#2020-02-25) for full details. + +# Upgrading to 7.0 + +node-postgres at 7.0 introduces somewhat significant breaking changes to the public API. + +## node version support + +Starting with `pg@7.0` the earliest version of node supported will be `node@4.x LTS`. Support for `node@0.12.x` and `node@.10.x` is dropped, and the module wont work as it relies on new es6 features not available in older versions of node. + +## pg singleton + +In the past there was a singleton pool manager attached to the root `pg` object in the package. This singleton could be used to provision connection pools automatically by calling `pg.connect`. This API caused a lot of confusion for users. It also introduced a opaque module-managed singleton which was difficult to reason about, debug, error-prone, and inflexible. Starting in pg@6.0 the methods' documentation was removed, and starting in pg@6.3 the methods were deprecated with a warning message. + +If your application still relies on these they will be _gone_ in `pg@7.0`. In order to migrate you can do the following: + +```js +// old way, deprecated in 6.3.0: + +// connection using global singleton +pg.connect(function(err, client, done) { + client.query(/* etc, etc */) + done() +}) + +// singleton pool shutdown +pg.end() + +// ------------------ + +// new way, available since 6.0.0: + +// create a pool +var pool = new pg.Pool() + +// connection using created pool +pool.connect(function(err, client, done) { + client.query(/* etc, etc */) + done() +}) + +// pool shutdown +pool.end() +``` + +node-postgres ships with a built-in pool object provided by [pg-pool](https://github.com/brianc/node-pg-pool) which is already used internally by the `pg.connect` and `pg.end` methods. Migrating to a user-managed pool (or set of pools) allows you to more directly control their set up their life-cycle. + +## client.query(...).on + +Before `pg@7.0` the `client.query` method would _always_ return an instance of a query. The query instance was an event emitter, accepted a callback, and was also a promise. A few problems... + +- too many flow control options on a single object was confusing +- event emitter `.on('error')` does not mix well with promise `.catch` +- the `row` event was a common source of errors: it looks like a stream but has no support for back-pressure, misleading users into trying to pipe results or handling them in the event emitter for a desired performance gain. +- error handling with a `.done` and `.error` emitter pair for every query is cumbersome and returning the emitter from `client.query` indicated this sort of pattern may be encouraged: it is not. + +Starting with `pg@7.0` the return value `client.query` will be dependent on what you pass to the method: I think this aligns more with how most node libraries handle the callback/promise combo, and I hope it will make the "just works" :tm: feeling better while reducing surface area and surprises around event emitter / callback combos. + +### client.query with a callback + +```js +const query = client.query('SELECT NOW()', (err, res) => { + /* etc, etc */ +}) +assert(query === undefined) // true +``` + +If you pass a callback to the method `client.query` will return `undefined`. This limits flow control to the callback which is in-line with almost all of node's core APIs. + +### client.query without a callback + +```js +const query = client.query('SELECT NOW()') +assert(query instanceof Promise) // true +assert(query.on === undefined) // true +query.then((res) => /* etc, etc */) +``` + +If you do **not** pass a callback `client.query` will return an instance of a `Promise`. This will **not** be a query instance and will not be an event emitter. This is in line with how most promise-based APIs work in node. + +### client.query(Submittable) + +`client.query` has always accepted any object that has a `.submit` method on it. In this scenario the client calls `.submit` on the object, delegating execution responsibility to it. In this situation the client also **returns the instance it was passed**. This is how [pg-cursor](https://github.com/brianc/node-pg-cursor) and [pg-query-stream](https://github.com/brianc/node-pg-query-stream) work. So, if you need the event emitter functionality on your queries for some reason, it is still possible because `Query` is an instance of `Submittable`: + +```js +const { Client, Query } = require('pg') +const query = client.query(new Query('SELECT NOW()')) +query.on('row', row => {}) +query.on('end', res => {}) +query.on('error', res => {}) +``` + +`Query` is considered a public, documented part of the API of node-postgres and this form will be supported indefinitely. + +_note: I have been building apps with node-postgres for almost 7 years. In that time I have never used the event emitter API as the primary way to execute queries. I used to use callbacks and now I use async/await. If you need to stream results I highly recommend you use [pg-cursor](https://github.com/brianc/node-pg-cursor) or [pg-query-stream](https://github.com/brianc/node-pg-query-stream) and **not** the query object as an event emitter._ diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx new file mode 100644 index 000000000..234cf11e1 --- /dev/null +++ b/docs/pages/index.mdx @@ -0,0 +1,65 @@ +--- +title: Welcome +slug: / +--- + +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. + +## Install + +```bash +$ npm install pg +``` + +## Supporters + +node-postgres continued development and support is made possible by the many [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) with a special thanks to our featured supporters: + +
+
+ + crate.io + +
+
+ + eaze.com + +
+
+ +If you or your company would like to sponsor node-postgres stop by [github sponsors](https://github.com/sponsors/brianc) and sign up or feel free to [email me](mailto:brian@pecanware.com) if you want to add your logo to the documentation or discuss higher tiers of sponsorship! + +# Version compatibility + +node-postgres strives to be compatible with all recent lts versions of node & the most recent "stable" version. At the time of this writing node-postgres is compatible with node 8.x, 10.x, 12.x and 14.x To use node >= 14.x you will need to install `pg@8.2.x` or later due to some internal stream changes on the node 14 branch. Dropping support for an old node lts version will always be considered a breaking change in node-postgres and will be done on _major_ version number changes only, and we will try to keep support for 8.x for as long as reasonably possible. + +## Getting started + +This is the simplest possible way to connect, query, and disconnect with async/await: + +```js +const { Client } = require('pg') +const client = new Client() +await client.connect() + +const res = await client.query('SELECT $1::text as message', ['Hello world!']) +console.log(res.rows[0].message) // Hello world! +await client.end() +``` + +And here's the same thing with callbacks: + +```js +const { Client } = require('pg') +const client = new Client() + +client.connect() + +client.query('SELECT $1::text as message', ['Hello world!'], (err, res) => { + console.log(err ? err.stack : res.rows[0].message) // Hello World! + client.end() +}) +``` + +Our real-world apps are almost always more complicated than that, and I urge you to read on! diff --git a/docs/theme.config.js b/docs/theme.config.js new file mode 100644 index 000000000..1ec4941ad --- /dev/null +++ b/docs/theme.config.js @@ -0,0 +1,27 @@ +// theme.config.js +export default { + projectLink: 'https://github.com/brianc/node-postgres', // GitHub link in the navbar + docsRepositoryBase: 'https://github.com/brianc/node-postgres/blob/master', // base URL for the docs repository + titleSuffix: ' – node-postgres', + nextLinks: true, + prevLinks: true, + search: true, + customSearch: null, // customizable, you can use algolia for example + darkMode: true, + footer: true, + footerText: `MIT ${new Date().getFullYear()} © Brian Carlson.`, + footerEditLink: `Edit this page on GitHub`, + logo: ( + <> + ... + Next.js Static Site Generator + + ), + head: ( + <> + + + + + ), +} diff --git a/docs/yarn.lock b/docs/yarn.lock new file mode 100644 index 000000000..aa2c18408 --- /dev/null +++ b/docs/yarn.lock @@ -0,0 +1,1892 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# 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== + +"@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== + dependencies: + "@types/estree-jsx" "^1.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" + 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== + 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== + +"@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== + +"@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== + +"@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== + +"@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== + +"@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== + +"@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== + +"@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== + +"@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== + +"@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== + +"@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== + +"@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== + 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== + dependencies: + "@types/estree" "*" + +"@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== + 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== + 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== + +"@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== + 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== + 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== + +"@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== + +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" + +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== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +astring@^1.8.0: + version "1.8.3" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.3.tgz#1a0ae738c7cc558f8e5ddc8e3120636f5cebcb85" + integrity sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A== + +bail@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" + integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== + +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== + +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" + +character-entities-html4@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" + integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== + +character-entities-legacy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" + integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== + +character-entities@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== + +character-reference-invalid@^2.0.0: + version "2.0.1" + 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== + dependencies: + arch "^2.1.0" + execa "^0.8.0" + +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== + +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== + dependencies: + color-name "1.1.3" + +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== + +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== + +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== + +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== + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +csstype@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + +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== + dependencies: + ms "2.1.2" + +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== + dependencies: + character-entities "^2.0.0" + +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== + +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== + +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== + +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== + 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== + dependencies: + "@types/estree-jsx" "^1.0.0" + estree-util-is-identifier-name "^2.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== + +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== + 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== + dependencies: + is-plain-obj "^3.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== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/unist" "^2.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" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend@^3.0.0: + version "3.0.2" + 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== + +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== + +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== + +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== + +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== + +gray-matter@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" + integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== + dependencies: + js-yaml "^3.13.1" + kind-of "^6.0.2" + section-matter "^1.0.0" + strip-bom-string "^1.0.0" + +has-flag@^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== + +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== + dependencies: + "@types/estree" "^1.0.0" + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/unist" "^2.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" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^0.3.0" + unist-util-position "^4.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-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== + +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== + +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== + +is-alphabetical@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b" + integrity sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ== + +is-alphanumerical@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz#7c03fbe96e3e931113e57f964b0a368cc2dfd875" + integrity sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw== + dependencies: + 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-extendable@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-hexadecimal@^2.0.0: + version "2.0.1" + 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-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: + 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== + dependencies: + "@types/estree" "*" + +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== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + 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== + +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== + +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== + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + 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-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== + +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" + +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== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + unist-util-visit "^4.0.0" + +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== + dependencies: + escape-string-regexp "^5.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.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== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.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== + dependencies: + "@types/mdast" "^3.0.0" + ccount "^2.0.0" + mdast-util-find-and-replace "^2.0.0" + micromark-util-character "^1.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== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-markdown "^1.3.0" + micromark-util-normalize-identifier "^1.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== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-markdown "^1.3.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== + dependencies: + "@types/mdast" "^3.0.0" + markdown-table "^3.0.0" + mdast-util-from-markdown "^1.0.0" + mdast-util-to-markdown "^1.3.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== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-markdown "^1.3.0" + +mdast-util-gfm@^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== + 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-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== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + ccount "^2.0.0" + mdast-util-to-markdown "^1.3.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" + +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== + dependencies: + mdast-util-mdx-expression "^1.0.0" + mdast-util-mdx-jsx "^2.0.0" + mdast-util-mdxjs-esm "^1.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== + 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" + 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" + +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== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.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" + 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== + +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== + 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== + 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-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== + dependencies: + micromark-util-types "^1.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== + 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-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== + 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== + dependencies: + micromark-util-types "^1.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== + 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== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.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== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-types "^1.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== + 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-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== + 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-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== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.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== + dependencies: + micromark-util-symbol "^1.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== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.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== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-types "^1.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== + dependencies: + micromark-util-symbol "^1.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== + 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-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-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== + 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== + +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== + dependencies: + micromark-util-symbol "^1.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== + dependencies: + micromark-util-types "^1.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== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-symbol "^1.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== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.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-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@^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== + 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== + +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== + +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== + +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== + +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" + caniuse-lite "^1.0.30001406" + postcss "8.4.14" + styled-jsx "5.0.7" + use-sync-external-store "1.2.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" + gray-matter "^4.0.3" + rehype-mdx-title "^1.0.0" + rehype-pretty-code "0.2.4" + remark-gfm "^3.0.1" + remark-reading-time "^2.0.1" + shiki "0.10.1" + slash "^3.0.0" + title "^3.5.3" + unist-util-visit "^4.1.1" + +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== + dependencies: + path-key "^2.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== + +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== + +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== + 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" + is-alphanumerical "^2.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-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== + dependencies: + estree-walker "^3.0.0" + is-reference "^3.0.0" + +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== + +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== + dependencies: + nanoid "^3.3.4" + 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== + +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== + +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== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler "^0.20.2" + +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== + 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== + +rehype-mdx-title@^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== + dependencies: + estree-util-is-identifier-name "^1.1.0" + hast-util-to-string "^1.0.4" + unist-util-visit "^2.0.3" + +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== + dependencies: + parse-numeric-range "^1.3.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== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-gfm "^2.0.0" + micromark-extension-gfm "^2.0.0" + unified "^10.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== + dependencies: + mdast-util-mdx "^2.0.0" + micromark-extension-mdxjs "^1.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== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + unified "^10.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== + dependencies: + estree-util-is-identifier-name "^2.0.0" + estree-util-value-to-estree "^1.3.0" + 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== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-to-hast "^12.1.0" + unified "^10.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== + +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== + dependencies: + mri "^1.1.0" + +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== + 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== + dependencies: + compute-scroll-into-view "^1.0.17" + +section-matter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" + integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== + dependencies: + 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== + 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== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +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== + +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== + +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== + +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== + +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== + dependencies: + character-entities-html4 "^2.0.0" + character-entities-legacy "^3.0.0" + +strip-bom-string@^1.0.0: + version "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== + +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== + dependencies: + inline-style-parser "0.1.1" + +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== + +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== + dependencies: + has-flag "^2.0.0" + +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== + +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" + +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== + +trim-lines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" + 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== + +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" + bail "^2.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" + +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== + 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@^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-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@^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== + dependencies: + "@types/unist" "^2.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== + dependencies: + "@types/unist" "^2.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== + dependencies: + "@types/unist" "^2.0.0" + unist-util-visit "^4.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== + dependencies: + "@types/unist" "^2.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== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + +unist-util-visit-parents@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz#e83559a4ad7e6048a46b1bdb22614f2f3f4724f2" + integrity sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw== + dependencies: + "@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== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +unist-util-visit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-3.1.0.tgz#9420d285e1aee938c7d9acbafc8e160186dbaf7b" + integrity sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA== + dependencies: + "@types/unist" "^2.0.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== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.1.1" + +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== + +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== + dependencies: + dequal "^2.0.0" + diff "^5.0.0" + kleur "^4.0.3" + sade "^1.7.3" + +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== + dependencies: + "@types/unist" "^2.0.0" + vfile "^5.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== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^3.0.0" + +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== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^3.0.0" + vfile-message "^3.0.0" + +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-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== + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +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== + +zwitch@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.2.tgz#91f8d0e901ffa3d66599756dde7f57b17c95dce1" + integrity sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA== diff --git a/package.json b/package.json index b8ac7659b..2dbdaedea 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "test": "yarn lerna exec yarn test", "build": "tsc --build", "build:watch": "tsc --build --watch", + "docs:build": "cd docs && yarn build", + "docs:start": "cd docs && yarn start", "pretest": "yarn build", "prepublish": "yarn build", "lint": "eslint '*/**/*.{js,ts,tsx}'" From c7dc7fd93a1558e6d0f18e30c49cc7daf2a2bd76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Oct 2022 12:55:47 -0500 Subject: [PATCH 055/261] Bump pgpass from 1.0.2 to 1.0.5 (#2827) Bumps [pgpass](https://github.com/hoegaarden/pgpass) from 1.0.2 to 1.0.5. - [Release notes](https://github.com/hoegaarden/pgpass/releases) - [Commits](https://github.com/hoegaarden/pgpass/compare/v1.0.2...v1.0.5) --- updated-dependencies: - dependency-name: pgpass dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9cd0b3c06..6fb12ffc8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4836,11 +4836,11 @@ pg-types@^2.1.0: postgres-interval "^1.1.0" pgpass@1.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" - integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= + version "1.0.5" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" + integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== dependencies: - split "^1.0.0" + split2 "^4.1.0" picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" @@ -5593,6 +5593,11 @@ split2@^2.0.0: dependencies: through2 "^2.0.2" +split2@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" + integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== + split@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" From 406f141a1a62350a632b3182f7a3a0877d7bbe53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 15 Oct 2022 19:57:16 +0200 Subject: [PATCH 056/261] perf: remove superfluous flush message (#2842) --- packages/pg/lib/connection.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index ebb2f099d..fe04efb6b 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -173,7 +173,6 @@ class Connection extends EventEmitter { sync() { this._ending = true - this._send(flushBuffer) this._send(syncBuffer) } From 5538df6b446f4b4f921947b460fe38acb897e579 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Oct 2022 12:57:41 -0500 Subject: [PATCH 057/261] Bump @typescript-eslint/eslint-plugin from 4.4.0 to 4.33.0 (#2826) Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.4.0 to 4.33.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.33.0/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@typescript-eslint/eslint-plugin" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 187 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 143 insertions(+), 44 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6fb12ffc8..a24466c1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -954,10 +954,10 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/json-schema@^7.0.3": - version "7.0.6" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" - integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/json-schema@^7.0.7": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/minimatch@*": version "3.0.3" @@ -1013,29 +1013,30 @@ "@types/pg-types" "*" "@typescript-eslint/eslint-plugin@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.4.0.tgz#0321684dd2b902c89128405cf0385e9fe8561934" - integrity sha512-RVt5wU9H/2H+N/ZrCasTXdGbUTkbf7Hfi9eLiA8vPQkzUJ/bLDCC3CsoZioPrNcnoyN8r0gT153dC++A4hKBQQ== + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== dependencies: - "@typescript-eslint/experimental-utils" "4.4.0" - "@typescript-eslint/scope-manager" "4.4.0" - debug "^4.1.1" + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" + debug "^4.3.1" functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.4.0.tgz#62a05d3f543b8fc5dec4982830618ea4d030e1a9" - integrity sha512-01+OtK/oWeSJTjQcyzDztfLF1YjvKpLFo+JZmurK/qjSRcyObpIecJ4rckDoRCSh5Etw+jKfdSzVEHevh9gJ1w== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.4.0" - "@typescript-eslint/types" "4.4.0" - "@typescript-eslint/typescript-estree" "4.4.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" + ignore "^5.1.8" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" "@typescript-eslint/parser@^4.4.0": version "4.4.0" @@ -1047,6 +1048,14 @@ "@typescript-eslint/typescript-estree" "4.4.0" debug "^4.1.1" +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + "@typescript-eslint/scope-manager@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.4.0.tgz#2f3dd27692a12cc9a046a90ba6a9d8cb7731190a" @@ -1055,11 +1064,29 @@ "@typescript-eslint/types" "4.4.0" "@typescript-eslint/visitor-keys" "4.4.0" +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + "@typescript-eslint/types@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.4.0.tgz#63440ef87a54da7399a13bdd4b82060776e9e621" integrity sha512-nU0VUpzanFw3jjX+50OTQy6MehVvf8pkqFcURPAE06xFNFenMj1GPEI6IESvp7UOHAnq+n/brMirZdR+7rCrlA== +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/typescript-estree@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.4.0.tgz#16a2df7c16710ddd5406b32b86b9c1124b1ca526" @@ -1074,6 +1101,14 @@ semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + dependencies: + "@typescript-eslint/types" "4.33.0" + eslint-visitor-keys "^2.0.0" + "@typescript-eslint/visitor-keys@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.4.0.tgz#0a9118344082f14c0f051342a74b42dfdb012640" @@ -1468,7 +1503,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -2048,10 +2083,10 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^4.0.1, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== +debug@^4.0.1, debug@^4.1.1, debug@^4.3.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" @@ -2387,7 +2422,7 @@ eslint-plugin-promise@^6.0.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz#a8cddf96a67c4059bdabf4d724a29572188ae423" integrity sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw== -eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -2402,6 +2437,13 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" @@ -2631,6 +2673,17 @@ fast-glob@^3.1.1: micromatch "^4.0.2" picomatch "^2.2.1" +fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + 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.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -2961,6 +3014,13 @@ glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" @@ -3020,6 +3080,18 @@ globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" +globby@^11.0.3: + 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" + globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -3215,10 +3287,10 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== import-fresh@^2.0.0: version "2.0.0" @@ -3898,6 +3970,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + macgyver@~1.10: version "1.10.1" resolved "https://registry.yarnpkg.com/macgyver/-/macgyver-1.10.1.tgz#b09d1599d8b36ed5b16f59589515d9d14bc2fd88" @@ -4020,7 +4099,7 @@ meow@^7.0.0: type-fest "^0.13.1" yargs-parser "^18.1.3" -merge2@^1.2.3, merge2@^1.3.0: +merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -4052,6 +4131,14 @@ micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + 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.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -4847,6 +4934,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5374,10 +5466,12 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.2.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== +semver@^7.2.1, semver@^7.3.2, semver@^7.3.5: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -6012,10 +6106,10 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tsutils@^3.17.1: - version "3.17.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" - integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== +tsutils@^3.17.1, tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -6366,6 +6460,11 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@13.1.2, yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" From 89b4e7f2a2bb6d663fcc96b352572c52eb69feb7 Mon Sep 17 00:00:00 2001 From: "Ryan B. Harvey" Date: Fri, 28 Oct 2022 00:56:53 -0500 Subject: [PATCH 058/261] Fix devcontainer build failure due to env var being interpreted as non-string (#2844) --- .devcontainer/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 11c8c9f3b..05475b824 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -27,7 +27,7 @@ services: PGHOST: db # set this to true in the development environment until I can get SSL setup on the # docker postgres instance - PGTESTNOSSL: true + PGTESTNOSSL: 'true' # Overrides default command so things don't shut down after the process ends. command: sleep infinity From 0965531cdaed208f273f5c193dbee912ce835aa1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:29:25 -0500 Subject: [PATCH 059/261] Bump typescript from 4.0.3 to 4.8.4 (#2850) Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.0.3 to 4.8.4. - [Release notes](https://github.com/Microsoft/TypeScript/releases) - [Commits](https://github.com/Microsoft/TypeScript/compare/v4.0.3...v4.8.4) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index a24466c1a..5fc372e9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6170,9 +6170,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5" - integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== + version "4.8.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" + integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== uglify-js@^3.1.4: version "3.13.5" From c253eb669699f5d72f29b30ccfbf934bc7360a95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:30:19 -0500 Subject: [PATCH 060/261] Bump chai from 4.2.0 to 4.3.6 (#2851) Bumps [chai](https://github.com/chaijs/chai) from 4.2.0 to 4.3.6. - [Release notes](https://github.com/chaijs/chai/releases) - [Changelog](https://github.com/chaijs/chai/blob/4.x.x/History.md) - [Commits](https://github.com/chaijs/chai/compare/4.2.0...v4.3.6) --- updated-dependencies: - dependency-name: chai dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5fc372e9e..3a4d75a98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -942,9 +942,9 @@ "@types/node" ">= 8" "@types/chai@^4.2.13", "@types/chai@^4.2.7": - version "4.2.13" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.13.tgz#8a3801f6655179d1803d81e94a2e4aaf317abd16" - integrity sha512-o3SGYRlOpvLFpwJA6Sl1UPOwKFEvE4FxTEB/c9XHI2whdnd4kmPVkNLL8gY4vWGBxWWDumzLbKsAhEH5SKn37Q== + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.3.tgz#3c90752792660c4b562ad73b3fbd68bf3bc7ae07" + integrity sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g== "@types/glob@^7.1.1": version "7.1.3" @@ -1657,15 +1657,16 @@ caseless@~0.12.0: integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= chai@^4.1.1, chai@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" deep-eql "^3.0.1" get-func-name "^2.0.0" - pathval "^1.1.0" + loupe "^2.3.1" + pathval "^1.1.1" type-detect "^4.0.5" chalk@^2.0.0, chalk@^2.3.1, chalk@^2.4.2: @@ -3963,6 +3964,13 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -4886,7 +4894,7 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathval@^1.1.0: +pathval@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== From 15b502d4c1ae3a85c2cdeb0e474f72297d4f63ba Mon Sep 17 00:00:00 2001 From: Frazer Smith Date: Sun, 6 Nov 2022 01:26:42 +0000 Subject: [PATCH 061/261] refactor(pg): remove unused imports (#2854) --- packages/pg/lib/client.js | 1 - packages/pg/lib/native/client.js | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 18238f6fb..82d571d8a 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -1,7 +1,6 @@ 'use strict' var EventEmitter = require('events').EventEmitter -var util = require('util') var utils = require('./utils') var sasl = require('./sasl') var pgPass = require('pgpass') diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index d1faeb3d8..58fc4aeaa 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -3,7 +3,6 @@ // eslint-disable-next-line var Native = require('pg-native') var TypeOverrides = require('../type-overrides') -var pkg = require('../../package.json') var EventEmitter = require('events').EventEmitter var util = require('util') var ConnectionParameters = require('../connection-parameters') From c7133eb67fec1b96735918c11549a0b69d52505d Mon Sep 17 00:00:00 2001 From: Frazer Smith Date: Tue, 8 Nov 2022 19:24:39 +0000 Subject: [PATCH 062/261] ci: remove git credentials after checkout (#2858) --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73e5709d3..8e0f098c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,8 @@ jobs: name: Node.js ${{ matrix.node }} (${{ matrix.os }}) steps: - uses: actions/checkout@v3 + with: + persist-credentials: false - name: Setup node uses: actions/setup-node@v3 with: From c7dc621d3fb52c158eb23aa31dea6bd440700a4a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 21 Nov 2022 09:57:30 -0800 Subject: [PATCH 063/261] pg-cursor: Fix errors only being sent to half the queue (#2831) * pg-cursor: Add failing test for errors on queued reads * pg-cursor: Fix errors being sent to only half the queue --- packages/pg-cursor/index.js | 4 +++- packages/pg-cursor/test/error-handling.js | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 9bbda641a..d3c0266b0 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -171,8 +171,10 @@ class Cursor extends EventEmitter { } // dispatch error to all waiting callbacks for (let i = 0; i < this._queue.length; i++) { - this._queue.pop()[1](msg) + const queuedCallback = this._queue[i][1] + queuedCallback.call(this, msg) } + this._queue.length = 0 if (this.listenerCount('error') > 0) { // only dispatch error events if we have a listener diff --git a/packages/pg-cursor/test/error-handling.js b/packages/pg-cursor/test/error-handling.js index f6edef6d5..22620bd83 100644 --- a/packages/pg-cursor/test/error-handling.js +++ b/packages/pg-cursor/test/error-handling.js @@ -19,6 +19,23 @@ describe('error handling', function () { }) }) }) + + it('errors queued reads', async () => { + const client = new pg.Client() + await client.connect() + + const cursor = client.query(new Cursor('asdfdffsdf')) + + const immediateRead = cursor.read(1) + const queuedRead1 = cursor.read(1) + const queuedRead2 = cursor.read(1) + + assert(await immediateRead.then(() => null, (err) => err)) + assert(await queuedRead1.then(() => null, (err) => err)) + assert(await queuedRead2.then(() => null, (err) => err)) + + client.end() + }) }) describe('read callback does not fire sync', () => { From 12b9a697769b422ad491de3875320665e5a6c61a Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 23 Nov 2022 15:08:09 -0600 Subject: [PATCH 064/261] update docs - clean up interface (#2863) * update docs - clean up interface * Remove node v8.x from test matrix --- .github/workflows/ci.yml | 2 +- SPONSORS.md | 2 + docs/pages/apis/client.mdx | 91 ++++++++++++++++++-------------------- docs/pages/apis/pool.mdx | 8 +++- docs/pages/index.mdx | 15 +------ 5 files changed, 53 insertions(+), 65 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e0f098c1..97f4013ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: matrix: - node: ['8', '10', '12', '14', '16', '18'] + node: ['10', '12', '14', '16', '18'] os: [ubuntu-latest, windows-latest, macos-latest] name: Node.js ${{ matrix.node }} (${{ matrix.os }}) steps: diff --git a/SPONSORS.md b/SPONSORS.md index 3bebb01eb..c16b8d3df 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -16,6 +16,7 @@ node-postgres is made possible by the helpful contributors from the community as - [@BLUE-DEVIL1134](https://github.com/BLUE-DEVIL1134) - [bubble.io](https://bubble.io/) - GitHub[https://github.com/github] +- loveland [https://github.com/loveland] # Supporters @@ -48,3 +49,4 @@ node-postgres is made possible by the helpful contributors from the community as - [Scout APM](https://github.com/scoutapm-sponsorships) - [Sideline Sports](https://github.com/SidelineSports) - [Gadget](https://github.com/gadget-inc) +- [Sentry](https://sentry.io/welcome/) diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index c983859b6..92268bed8 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -41,8 +41,6 @@ const client = new Client({ ## client.connect -### `client.connect(callback: (err: Error) => void) => void` - Calling `client.connect` with a callback: ```js @@ -57,8 +55,6 @@ client.connect((err) => { }) ``` -### `client.connect() => Promise` - Calling `client.connect` without a callback yields a promise: ```js @@ -74,19 +70,35 @@ _note: connect returning a promise only available in pg@7.0 or above_ ## client.query -### `client.query` - text, optional values, and callback. +### QueryConfig -Passing query text, optional query parameters, and a callback to `client.query` results in a type-signature of: +You can pass an object to `client.query` with the signature of: ```ts -client.query( - text: string, - values?: Array, - callback: (err: Error, result: Result) => void -) => void +type QueryConfig { + // the raw query text + text: string; + + // an array of query parameters + values?: Array; + + // name of the query - used for prepared statements + name?: string; + + // by default rows come out as a key/value pair for each row + // pass the string 'array' here to receive rows as an array of values + rowMode?: string; + + // custom type parsers just for this query result + types?: Types; +} ``` -That is a kinda gross type signature but it translates out to this: +### callback API + +```ts +client.query(text: string, values?: any[], callback?: (err: Error, result: QueryResult) => void) => void +``` **Plain text query with a callback:** @@ -114,15 +126,12 @@ client.query('SELECT $1::text as name', ['brianc'], (err, res) => { }) ``` -### `client.query` - text, optional values: Promise +### Promise API If you call `client.query` with query text and optional parameters but **don't** pass a callback, then you will receive a `Promise` for a query result. ```ts -client.query( - text: string, - values?: Array -) => Promise +client.query(text: string, values?: any[]) => Promise ``` **Plain text query with a promise** @@ -151,30 +160,8 @@ client .then(() => client.end()) ``` -### `client.query(config: QueryConfig, callback: (err?: Error, result?: Result) => void) => void` - -### `client.query(config: QueryConfig) => Promise` - -You can pass an object to `client.query` with the signature of: - ```ts -type QueryConfig { - // the raw query text - text: string; - - // an array of query parameters - values?: Array; - - // name of the query - used for prepared statements - name?: string; - - // by default rows come out as a key/value pair for each row - // pass the string 'array' here to receive rows as an array of values - rowMode?: string; - - // custom type parsers just for this query result - types?: Types; -} +client.query(config: QueryConfig) => Promise ``` **client.query with a QueryConfig and a callback** @@ -246,8 +233,6 @@ query.on('error', (err) => { ## client.end -### client.end(cb?: (err?: Error) => void) => void - Disconnects the client from the PostgreSQL server. ```js @@ -259,8 +244,6 @@ client.end((err) => { }) ``` -### `client.end() => Promise` - Calling end without a callback yields a promise: ```js @@ -274,7 +257,11 @@ _note: end returning a promise is only available in pg7.0 and above_ ## events -### client.on('error', (err: Error) => void) => void +### error + +```ts +client.on('error', (err: Error) => void) => void +``` When the client is in the process of connecting, dispatching a query, or disconnecting it will catch and foward errors from the PostgreSQL server to the respective `client.connect` `client.query` or `client.end` callback/promise; however, the client maintains a long-lived connection to the PostgreSQL back-end and due to network partitions, back-end crashes, fail-overs, etc the client can (and over a long enough time period _will_) eventually be disconnected while it is idle. To handle this you may want to attach an error listener to a client to catch errors. Here's a contrived example: @@ -291,11 +278,15 @@ client.on('error', (err) => { // process output: 'something bad has happened!' followed by stacktrace :P ``` -### client.on('end') => void +### end + +```ts +client.on('end') => void +``` When the client disconnects from the PostgreSQL server it will emit an end event once. -### client.on('notification', (notification: Notification) => void) => void +### notification Used for `listen/notify` events: @@ -321,7 +312,11 @@ client.on('notification', (msg) => { client.query(`NOTIFY foo, 'bar!'`) ``` -### client.on('notice', (notice: Error) => void) => void +### notice + +```ts +client.on('notice', (notice: Error) => void) => void +``` Used to log out [notice messages](https://www.postgresql.org/docs/9.6/static/plpgsql-errors-and-messages.html) from the PostgreSQL server. diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx index 6ebc19044..497e5253f 100644 --- a/docs/pages/apis/pool.mdx +++ b/docs/pages/apis/pool.mdx @@ -63,7 +63,9 @@ const pool = new Pool({ Often we only need to run a single query on the database, so as convenience the pool has a method to run a query on the first available idle client and return its result. -`pool.query() => Promise` +```ts +pool.query(text: string, values?: any[]) => Promise +``` ```js const { Pool } = require('pg') @@ -78,7 +80,9 @@ pool Callbacks are also supported: -`pool.query(callback: (err?: Error, result: pg.Result)) => void` +```ts +pool.query(text: string, values?: any[], callback?: (err?: Error, result: pg.Result)) => void +``` ```js const { Pool } = require('pg') diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 234cf11e1..2e14116b5 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -13,20 +13,7 @@ $ npm install pg ## Supporters -node-postgres continued development and support is made possible by the many [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) with a special thanks to our featured supporters: - -
-
- - crate.io - -
-
- - eaze.com - -
-
+node-postgres continued development and support is made possible by the many [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). If you or your company would like to sponsor node-postgres stop by [github sponsors](https://github.com/sponsors/brianc) and sign up or feel free to [email me](mailto:brian@pecanware.com) if you want to add your logo to the documentation or discuss higher tiers of sponsorship! From 27d612a2ac2df8737397019a5806f745f19b760e Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 23 Nov 2022 21:50:36 -0600 Subject: [PATCH 065/261] Update docs (#2867) - fix config warnings - add search bar - add google analytics --- docs/theme.config.js | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/docs/theme.config.js b/docs/theme.config.js index 1ec4941ad..4ab2b8d23 100644 --- a/docs/theme.config.js +++ b/docs/theme.config.js @@ -1,16 +1,26 @@ // theme.config.js export default { - projectLink: 'https://github.com/brianc/node-postgres', // GitHub link in the navbar - docsRepositoryBase: 'https://github.com/brianc/node-postgres/blob/master', // base URL for the docs repository + project: { + link: 'https://github.com/brianc/node-postgres', + }, + twitter: { + cardType: 'summary_large_image', + site: 'https://node-postgres.com', + }, + docsRepositoryBase: 'https://github.com/brianc/node-postgres/blob/master/docs', // base URL for the docs repository titleSuffix: ' – node-postgres', - nextLinks: true, - prevLinks: true, - search: true, - customSearch: null, // customizable, you can use algolia for example darkMode: true, footer: true, - footerText: `MIT ${new Date().getFullYear()} © Brian Carlson.`, - footerEditLink: `Edit this page on GitHub`, + navigation: { + prev: true, + next: true, + }, + footer: { + text: `MIT ${new Date().getFullYear()} © Brian Carlson.`, + }, + editLink: { + text: 'Edit this page on GitHub', + }, logo: ( <> ... @@ -22,6 +32,20 @@ export default { + + ), } From 16118cecdd777ff077b70484cb39abf19f5a22f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Dec 2022 22:02:31 -0600 Subject: [PATCH 066/261] Bump eslint-config-prettier from 6.12.0 to 8.5.0 (#2875) Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 6.12.0 to 8.5.0. - [Release notes](https://github.com/prettier/eslint-config-prettier/releases) - [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-config-prettier/compare/v6.12.0...v8.5.0) --- updated-dependencies: - dependency-name: eslint-config-prettier dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 15 ++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 2dbdaedea..dfd9b0312 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@typescript-eslint/eslint-plugin": "^4.4.0", "@typescript-eslint/parser": "^4.4.0", "eslint": "^7.11.0", - "eslint-config-prettier": "^6.12.0", + "eslint-config-prettier": "^8.5.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.4", "lerna": "^3.19.0", diff --git a/yarn.lock b/yarn.lock index 3a4d75a98..4360e06d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2384,12 +2384,10 @@ escodegen@1.8.x: optionalDependencies: source-map "~0.2.0" -eslint-config-prettier@^6.12.0: - version "6.12.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.12.0.tgz#9eb2bccff727db1c52104f0b49e87ea46605a0d2" - integrity sha512-9jWPlFlgNwRUYVoujvWTQ1aMO8o6648r+K7qU7K5Jmkbyqav1fuEZC0COYpGBxyiAJb65Ra9hrmFx19xRGwXWw== - dependencies: - get-stdin "^6.0.0" +eslint-config-prettier@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== eslint-plugin-es@^3.0.0: version "3.0.1" @@ -2927,11 +2925,6 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" From c6c05f823c6abec337e7ec30db86bba4daababde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Dec 2022 22:02:45 -0600 Subject: [PATCH 067/261] Bump JSONStream from 0.7.4 to 1.3.5 (#2874) Bumps [JSONStream](https://github.com/dominictarr/JSONStream) from 0.7.4 to 1.3.5. - [Release notes](https://github.com/dominictarr/JSONStream/releases) - [Commits](https://github.com/dominictarr/JSONStream/commits) --- updated-dependencies: - dependency-name: JSONStream dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/pg-query-stream/package.json | 2 +- yarn.lock | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 92a42fe95..50f6571f4 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -33,7 +33,7 @@ "@types/mocha": "^8.0.3", "@types/node": "^14.0.0", "@types/pg": "^7.14.5", - "JSONStream": "~0.7.1", + "JSONStream": "~1.3.5", "concat-stream": "~1.0.1", "eslint-plugin-promise": "^6.0.1", "mocha": "^7.1.2", diff --git a/yarn.lock b/yarn.lock index 4360e06d5..2b0959c1b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1126,7 +1126,7 @@ mkdirp-promise "^5.0.1" mz "^2.5.0" -JSONStream@^1.0.4, JSONStream@^1.3.4: +JSONStream@^1.0.4, JSONStream@^1.3.4, JSONStream@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== @@ -1134,14 +1134,6 @@ JSONStream@^1.0.4, JSONStream@^1.3.4: jsonparse "^1.2.0" through ">=2.2.7 <3" -JSONStream@~0.7.1: - version "0.7.4" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-0.7.4.tgz#734290e41511eea7c2cfe151fbf9a563a97b9786" - integrity sha1-c0KQ5BUR7qfCz+FR+/mlY6l7l4Y= - dependencies: - jsonparse "0.0.5" - through ">=2.2.7 <3" - abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -3733,11 +3725,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonparse@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-0.0.5.tgz#330542ad3f0a654665b778f3eb2d9a9fa507ac64" - integrity sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ= - jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" From 3e34816f6fcedb165618367045a3119849ff37cd Mon Sep 17 00:00:00 2001 From: Meron Ogbai <22526062+meronogbai@users.noreply.github.com> Date: Sat, 31 Dec 2022 07:45:42 +0300 Subject: [PATCH 068/261] Update title (#2886) This will change the title of the docs from Next.js Static Site Generator to node-postgres --- docs/theme.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/theme.config.js b/docs/theme.config.js index 4ab2b8d23..263a26945 100644 --- a/docs/theme.config.js +++ b/docs/theme.config.js @@ -24,7 +24,7 @@ export default { logo: ( <> ... - Next.js Static Site Generator + node-postgres ), head: ( From f82f39c20c4a0b834529c7d3d38a43a9ec366572 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Mon, 23 Jan 2023 13:02:39 -0500 Subject: [PATCH 069/261] Add support to stream factory (#2898) This changeset enables declaring the `stream` config value as a factory method. Providing a much more flexible control of the socket connection. Defining a custom `stream` config value allows the postgres driver to support a larger variety of environments/setups such as proxy servers and secure socket connections that are used by cloud providers such as GCP. Currently, usage of the `stream` config value is only viable for single connections given that it's only possible to define a single socket stream instance per new Client/Pool instance. By adding support to a factory function, it becomes possible to enable usage of custom socket streams for connection pools. For reference, see the `mysql2` driver for MySQL (linked below) for prior art example of this pattern. Refs: https://github.com/sidorares/node-mysql2/blob/ba15fe25703665e516ab0a23af8d828d1473b8c3/lib/connection.js#L63-L65 Refs: https://cloud.google.com/sql/docs/postgres/connect-overview Signed-off-by: Ruy Adorno Signed-off-by: Ruy Adorno --- packages/pg/lib/connection.js | 5 +++++ packages/pg/test/unit/connection/startup-tests.js | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index fe04efb6b..86724c5c5 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -14,7 +14,12 @@ class Connection extends EventEmitter { constructor(config) { super() config = config || {} + this.stream = config.stream || new net.Socket() + if (typeof this.stream === 'function') { + this.stream = this.stream(config) + } + this._keepAlive = config.keepAlive this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis this.lastBuffer = false diff --git a/packages/pg/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js index e2eb6ee99..d5d30d5de 100644 --- a/packages/pg/test/unit/connection/startup-tests.js +++ b/packages/pg/test/unit/connection/startup-tests.js @@ -7,6 +7,18 @@ test('connection can take existing stream', function () { assert.equal(con.stream, stream) }) +test('connection can take stream factory method', function () { + var stream = new MemoryStream() + var connectionOpts = {} + var makeStream = function (opts) { + assert.equal(connectionOpts, opts) + return stream + } + connectionOpts.stream = makeStream + var con = new Connection(connectionOpts) + assert.equal(con.stream, stream) +}) + test('using any stream', function () { var makeStream = function () { var stream = new MemoryStream() From bb8745b2159a5096c25acba23dc0603c0f75fe5e Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Mon, 23 Jan 2023 13:03:51 -0500 Subject: [PATCH 070/261] Fix SASL to bubble up errors, enable SASL tests in CI, and add informative empty SASL password message (#2901) * Enable SASL tests in GitHub actions CI * Add SASL test to ensure that client password is a string * Fix SASL error handling to emit and bubble up errors * Add informative error when SASL password is empty string --- .github/workflows/ci.yml | 15 +++++++- packages/pg/lib/client.js | 24 +++++++++--- packages/pg/lib/sasl.js | 3 ++ .../integration/client/sasl-scram-tests.js | 21 ++++++++++ .../pg/test/unit/client/sasl-scram-tests.js | 38 +++++++++++++++++++ 5 files changed, 94 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97f4013ba..ab5bef47b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,7 @@ jobs: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: ci_db_test + POSTGRES_HOST_AUTH_METHOD: 'md5' ports: - 5432:5432 options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 @@ -23,7 +24,19 @@ jobs: node: ['10', '12', '14', '16', '18'] os: [ubuntu-latest, windows-latest, macos-latest] name: Node.js ${{ matrix.node }} (${{ matrix.os }}) + env: + PGUSER: postgres + PGHOST: localhost + PGPASSWORD: postgres + PGDATABASE: ci_db_test + PGTESTNOSSL: 'true' + SCRAM_TEST_PGUSER: scram_test + SCRAM_TEST_PGPASSWORD: test4scram steps: + - run: | + psql \ + -c "SET password_encryption = 'scram-sha-256'" \ + -c "CREATE ROLE scram_test LOGIN PASSWORD 'test4scram'" - uses: actions/checkout@v3 with: persist-credentials: false @@ -34,4 +47,4 @@ jobs: cache: yarn - run: yarn install # TODO(bmc): get ssl tests working in ci - - run: PGTESTNOSSL=true PGUSER=postgres PGPASSWORD=postgres PGDATABASE=ci_db_test yarn test + - run: yarn test diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 82d571d8a..2090c4b5f 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -247,19 +247,31 @@ class Client extends EventEmitter { _handleAuthSASL(msg) { this._checkPgPass(() => { - this.saslSession = sasl.startSession(msg.mechanisms) - this.connection.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response) + try { + this.saslSession = sasl.startSession(msg.mechanisms) + this.connection.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response) + } catch (err) { + this.connection.emit('error', err) + } }) } _handleAuthSASLContinue(msg) { - sasl.continueSession(this.saslSession, this.password, msg.data) - this.connection.sendSCRAMClientFinalMessage(this.saslSession.response) + try { + sasl.continueSession(this.saslSession, this.password, msg.data) + this.connection.sendSCRAMClientFinalMessage(this.saslSession.response) + } catch (err) { + this.connection.emit('error', err) + } } _handleAuthSASLFinal(msg) { - sasl.finalizeSession(this.saslSession, msg.data) - this.saslSession = null + try { + sasl.finalizeSession(this.saslSession, msg.data) + this.saslSession = null + } catch (err) { + this.connection.emit('error', err) + } } _handleBackendKeyData(msg) { diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index fb703b270..c8d2d2bdc 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -23,6 +23,9 @@ function continueSession(session, password, serverData) { if (typeof password !== 'string') { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string') } + if (password === '') { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string') + } if (typeof serverData !== 'string') { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: serverData must be a string') } diff --git a/packages/pg/test/integration/client/sasl-scram-tests.js b/packages/pg/test/integration/client/sasl-scram-tests.js index debc28685..3b3fd4a57 100644 --- a/packages/pg/test/integration/client/sasl-scram-tests.js +++ b/packages/pg/test/integration/client/sasl-scram-tests.js @@ -73,3 +73,24 @@ 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 () => { + const client = new pg.Client({ + ...config, + // We use a password function here so the connection defaults do not + // override the empty string value with one from process.env.PGPASSWORD + password: () => '', + }) + let usingSasl = false + client.connection.once('authenticationSASL', () => { + usingSasl = true + }) + await assert.rejects( + () => client.connect(), + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string', + }, + '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 e53448bdf..36a5556b4 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -80,6 +80,44 @@ test('sasl/scram', function () { ) }) + test('fails when client password is not a string', function () { + for(const badPasswordValue of [null, undefined, 123, new Date(), {}]) { + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: 'a', + }, + badPasswordValue, + 'r=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string', + } + ) + } + }) + + test('fails when client password is an empty string', function () { + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: 'a', + }, + '', + 'r=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string', + } + ) + }) + test('fails when iteration is missing in server message', function () { assert.throws( function () { From 47afe5cded70cfaf873b35ae68eca4986102b988 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 23 Jan 2023 13:55:38 -0800 Subject: [PATCH 071/261] Attempt to fix timing test flake on older versions of node in CI (#2902) --- packages/pg-pool/test/lifetime-timeout.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/pg-pool/test/lifetime-timeout.js b/packages/pg-pool/test/lifetime-timeout.js index fddd5ff00..3e690429e 100644 --- a/packages/pg-pool/test/lifetime-timeout.js +++ b/packages/pg-pool/test/lifetime-timeout.js @@ -21,7 +21,7 @@ describe('lifetime timeout', () => { }) it('connection lifetime should expire and remove the client after the client is done working', (done) => { const pool = new Pool({ maxLifetimeSeconds: 1 }) - pool.query('SELECT pg_sleep(1.01)') + pool.query('SELECT pg_sleep(1.4)') pool.on('remove', () => { console.log('expired while busy - on-remove event') expect(pool.expiredCount).to.equal(0) @@ -33,10 +33,11 @@ describe('lifetime timeout', () => { 'can remove expired clients and recreate them', co.wrap(function* () { const pool = new Pool({ maxLifetimeSeconds: 1 }) - let query = pool.query('SELECT pg_sleep(1)') + let query = pool.query('SELECT pg_sleep(1.4)') expect(pool.expiredCount).to.equal(0) expect(pool.totalCount).to.equal(1) yield query + yield new Promise((resolve) => setTimeout(resolve, 100)) expect(pool.expiredCount).to.equal(0) expect(pool.totalCount).to.equal(0) yield pool.query('SELECT NOW()') From 5bdc61a33d4ef25cc12ea36a4199864109551c56 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 27 Jan 2023 09:11:05 -0600 Subject: [PATCH 072/261] Remove expired sponsors --- README.md | 15 +-------------- packages/pg/README.md | 13 +------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 15b693128..0cf4c5e37 100644 --- a/README.md +++ b/README.md @@ -55,20 +55,7 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that ## Sponsorship :two_hearts: -node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors: - -
-

- - - -

-

- - - -

-
+node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. diff --git a/packages/pg/README.md b/packages/pg/README.md index b3158b570..e21f34a06 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -46,18 +46,7 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that ## Sponsorship :two_hearts: -node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors: - -
- - - - - - - - -
+node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. From 20a243e8b30926a348cafc44177e95345618f7bc Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 27 Jan 2023 09:12:49 -0600 Subject: [PATCH 073/261] Publish - pg-cursor@2.8.0 - pg-protocol@1.6.0 - pg-query-stream@4.3.0 - pg@8.9.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index c12906abd..5fabf5b28 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.4", + "version": "2.8.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.8.0" + "pg": "^8.9.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index ae9ba6f52..ff56dc3be 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.5.0", + "version": "1.6.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 50f6571f4..0c090c4a2 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.2.4", + "version": "4.3.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,7 +37,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^6.0.1", "mocha": "^7.1.2", - "pg": "^8.8.0", + "pg": "^8.9.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" @@ -46,6 +46,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.7.4" + "pg-cursor": "^2.8.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 37afe6149..6c0f60a38 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.8.0", + "version": "8.9.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -24,7 +24,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", "pg-pool": "^3.5.2", - "pg-protocol": "^1.5.0", + "pg-protocol": "^1.6.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, From adbe86d4a057b942298cab1d19b341c67a94d922 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 27 Jan 2023 09:15:30 -0600 Subject: [PATCH 074/261] Update changelog --- CHANGELOG.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f017a3d5a..fff8cdf1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,19 @@ 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.9.0 + +- Add support for [stream factory](https://github.com/brianc/node-postgres/pull/2898). +- [Better errors](https://github.com/brianc/node-postgres/pull/2901) for SASL authentication. +- [Use native crypto module](https://github.com/brianc/node-postgres/pull/2815) for SASL authentication. + ## pg@8.8.0 -- Bump minimum required version of [native bindings](https://github.com/brianc/node-postgres/pull/2787) -- Catch previously uncatchable errors thrown in [`pool.query`](https://github.com/brianc/node-postgres/pull/2569) -- Prevent the pool from blocking the event loop if all clients are [idle](https://github.com/brianc/node-postgres/pull/2721) (and `allowExitOnIdle` is enabled) -- Support `lock_timeout` in [client config](https://github.com/brianc/node-postgres/pull/2779) -- Fix errors thrown in callbacks from [interfering with cleanup](https://github.com/brianc/node-postgres/pull/2753) +- Bump minimum required version of [native bindings](https://github.com/brianc/node-postgres/pull/2787). +- Catch previously uncatchable errors thrown in [`pool.query`](https://github.com/brianc/node-postgres/pull/2569). +- Prevent the pool from blocking the event loop if all clients are [idle](https://github.com/brianc/node-postgres/pull/2721) (and `allowExitOnIdle` is enabled). +- Support `lock_timeout` in [client config](https://github.com/brianc/node-postgres/pull/2779). +- Fix errors thrown in callbacks from [interfering with cleanup](https://github.com/brianc/node-postgres/pull/2753). ### pg-pool@3.5.0 From 5703791640ba92558f162120f235b29eaf0e4cf0 Mon Sep 17 00:00:00 2001 From: Cody Greene Date: Mon, 6 Mar 2023 10:10:07 -0800 Subject: [PATCH 075/261] fix: double client.end() hang (#2717) * fix: double client.end() hang fixes https://github.com/brianc/node-postgres/issues/2716 `client.end()` will resolve early if the connection is already dead, rather than waiting for an "end" event that will never arrive. * fix: client.end() resolves when socket is fully closed --- packages/pg/lib/client.js | 4 +- packages/pg/lib/connection.js | 3 -- .../test/integration/gh-issues/2716-tests.js | 38 +++++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 packages/pg/test/integration/gh-issues/2716-tests.js diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 2090c4b5f..99c06d661 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -37,6 +37,7 @@ class Client extends EventEmitter { this._Promise = c.Promise || global.Promise this._types = new TypeOverrides(c.types) this._ending = false + this._ended = false this._connecting = false this._connected = false this._connectionError = false @@ -132,6 +133,7 @@ class Client extends EventEmitter { clearTimeout(this.connectionTimeoutHandle) this._errorAllQueries(error) + this._ended = true if (!this._ending) { // if the connection is ended without us calling .end() @@ -603,7 +605,7 @@ class Client extends EventEmitter { this._ending = true // if we have never connected, then end is a noop, callback immediately - if (!this.connection._connecting) { + if (!this.connection._connecting || this._ended) { if (cb) { cb() } else { diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 86724c5c5..9e24391b6 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -108,9 +108,6 @@ class Connection extends EventEmitter { } attachListeners(stream) { - stream.on('end', () => { - this.emit('end') - }) parse(stream, (msg) => { var eventName = msg.name === 'error' ? 'errorMessage' : msg.name if (this._emitMessage) { diff --git a/packages/pg/test/integration/gh-issues/2716-tests.js b/packages/pg/test/integration/gh-issues/2716-tests.js new file mode 100644 index 000000000..62d0942ba --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2716-tests.js @@ -0,0 +1,38 @@ +'use strict' +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 () => { + const client = new helper.pg.Client() + await client.connect() + + // this should resolve only when the underlying socket is fully closed, both + // the readable part ("end" event) & writable part ("close" event). + + // https://nodejs.org/docs/latest-v16.x/api/net.html#event-end + // > Emitted when the other end of the socket signals the end of + // > transmission, thus ending the readable side of the socket. + + // https://nodejs.org/docs/latest-v16.x/api/net.html#event-close_1 + // > Emitted once the socket is fully closed. + + // here: stream = socket + + await client.end() + // connection.end() + // stream.end() + // ... + // stream emits "end" + // not listening to this event anymore so the promise doesn't resolve yet + // stream emits "close"; no more events will be emitted from the stream + // connection emits "end" + // promise resolved + + // This should now resolve immediately, rather than wait for connection.on('end') + await client.end() + + // this should resolve immediately, rather than waiting forever + await client.end() +}) From 8804e5caaf2194e75d0a7b44f7819dfc809ea317 Mon Sep 17 00:00:00 2001 From: Aram Zegerius Date: Mon, 6 Mar 2023 19:30:37 +0100 Subject: [PATCH 076/261] Fix typo in URL (#2913) --- docs/pages/features/pooling.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/features/pooling.mdx b/docs/pages/features/pooling.mdx index 4719150be..e291080f2 100644 --- a/docs/pages/features/pooling.mdx +++ b/docs/pages/features/pooling.mdx @@ -19,7 +19,7 @@ The easiest and by far most common way to use node-postgres is through a connect ### Good news -node-postgres ships with built-in connection pooling via the [pg-pool](/api/pool) module. +node-postgres ships with built-in connection pooling via the [pg-pool](/apis/pool) module. ## Examples From 810b12558139d0231a71b9bc81206490f2a27ef3 Mon Sep 17 00:00:00 2001 From: "Ryan B. Harvey" Date: Mon, 6 Mar 2023 12:32:13 -0600 Subject: [PATCH 077/261] Emit a 'release' event when a connection is released back to the pool (#2845) --- packages/pg-pool/index.js | 2 ++ packages/pg-pool/test/events.js | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 00f55b4da..910aee6d2 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -330,6 +330,8 @@ class Pool extends EventEmitter { client._poolUseCount = (client._poolUseCount || 0) + 1 + this.emit('release', err, client) + // TODO(bmc): expose a proper, public interface _queryable and _ending if (err || this.ending || !client._queryable || client._ending || client._poolUseCount >= this.options.maxUses) { if (client._poolUseCount >= this.options.maxUses) { diff --git a/packages/pg-pool/test/events.js b/packages/pg-pool/test/events.js index 61979247d..751b14dbc 100644 --- a/packages/pg-pool/test/events.js +++ b/packages/pg-pool/test/events.js @@ -60,6 +60,42 @@ describe('events', function () { }, 100) }) + it('emits release every time a client is released', function (done) { + const pool = new Pool() + let releaseCount = 0 + pool.on('release', function (err, client) { + expect(err instanceof Error).not.to.be(true) + expect(client).to.be.ok() + releaseCount++ + }) + for (let i = 0; i < 10; i++) { + pool.connect(function (err, client, release) { + if (err) return done(err) + release() + }) + pool.query('SELECT now()') + } + setTimeout(function () { + expect(releaseCount).to.be(20) + pool.end(done) + }, 100) + }) + + it('emits release with an error if client is released due to an error', function (done) { + const pool = new Pool() + pool.connect(function (err, client, release) { + expect(err).to.equal(undefined) + const releaseError = new Error('problem') + pool.once('release', function (err, errClient) { + console.log(err, errClient) + expect(err).to.equal(releaseError) + expect(errClient).to.equal(client) + pool.end(done) + }) + release(releaseError) + }) + }) + it('emits error and client if an idle client in the pool hits an error', function (done) { const pool = new Pool() pool.connect(function (err, client) { From ee302cbcf10437e34fd05d70fc003c357b14c654 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 6 Mar 2023 14:18:02 -0600 Subject: [PATCH 078/261] Publish - pg-cursor@2.9.0 - pg-pool@3.6.0 - pg-query-stream@4.4.0 - pg@8.10.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 5fabf5b28..c99c12c29 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.8.0", + "version": "2.9.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.9.0" + "pg": "^8.10.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 0bb64b579..38b36708f 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.5.2", + "version": "3.6.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 0c090c4a2..23f5fbd3e 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.3.0", + "version": "4.4.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,7 +37,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^6.0.1", "mocha": "^7.1.2", - "pg": "^8.9.0", + "pg": "^8.10.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" @@ -46,6 +46,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.8.0" + "pg-cursor": "^2.9.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 6c0f60a38..6e62a04ea 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.9.0", + "version": "8.10.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.5.2", + "pg-pool": "^3.6.0", "pg-protocol": "^1.6.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 661f870e1c741a1dd712f5ad7631aa34419b2af9 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 6 Mar 2023 15:48:08 -0600 Subject: [PATCH 079/261] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fff8cdf1c..bf05426e3 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-pool@8.10.0 + +- Emit `release` event when client is returned to [the pool](https://github.com/brianc/node-postgres/pull/2845). + ## pg@8.9.0 - Add support for [stream factory](https://github.com/brianc/node-postgres/pull/2898). From 0f76fb3bb70f0cee118d873aeee4283b32f7217f Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 7 Mar 2023 13:55:22 -0600 Subject: [PATCH 080/261] Update path to documentation in readme (#2925) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0cf4c5e37..967431358 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Each package in this repo should have its own readme more focused on how to deve ### :star: [Documentation](https://node-postgres.com) :star: -The source repo for the documentation is https://github.com/brianc/node-postgres-docs. +The source repo for the documentation is available for contribution [here](https://github.com/brianc/node-postgres/tree/master/docs). ### Features From 65ca2458fd0079f36a99a7752a7931483cd57ed6 Mon Sep 17 00:00:00 2001 From: "Ryan B. Harvey" Date: Thu, 16 Mar 2023 11:34:50 -0500 Subject: [PATCH 081/261] Add release event to Pool API docs (#2928) --- docs/pages/apis/pool.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx index 497e5253f..6323f2e2d 100644 --- a/docs/pages/apis/pool.mdx +++ b/docs/pages/apis/pool.mdx @@ -271,6 +271,12 @@ The error listener is passed the error as the first argument and the client upon uncaught error and potentially crash your node process. +### release + +`pool.on('release', (err: Error, client: Client) => void) => void` + +Whenever a client is released back into the pool, the pool will emit the `release` event. + ### remove `pool.on('remove', (client: Client) => void) => void` From 92351b5f3ea7d76183e92d9a1461987fd826f60f Mon Sep 17 00:00:00 2001 From: Samuel Durante <44513615+samueldurantes@users.noreply.github.com> Date: Thu, 30 Mar 2023 12:49:28 -0300 Subject: [PATCH 082/261] docs(client): improve the Client instance example (#2935) --- docs/pages/apis/client.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index 92268bed8..d5f335240 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -34,6 +34,7 @@ const { Client } = require('pg') const client = new Client({ host: 'my.database-server.com', port: 5334, + database: 'database-name', user: 'database-user', password: 'secretpassword!!', }) From 48f4398fa75247f4ed8e2470372d0b77712f73e3 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 30 Mar 2023 11:25:35 -0500 Subject: [PATCH 083/261] Update README.md (#2944) Update href to docs --- packages/pg-cursor/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-cursor/README.md b/packages/pg-cursor/README.md index 1b01b3d83..a3fdf4d00 100644 --- a/packages/pg-cursor/README.md +++ b/packages/pg-cursor/README.md @@ -10,7 +10,7 @@ $ npm install pg-cursor ``` ___note___: this depends on _either_ `npm install pg` or `npm install pg.js`, but you __must__ be using the pure JavaScript client. This will __not work__ with the native bindings. -### :star: [Documentation](https://node-postgres.com/api/cursor) :star: +### :star: [Documentation](https://node-postgres.com/apis/cursor) :star: ### license From b357e1884ad25b23a4ab034b443ddfc8c8261951 Mon Sep 17 00:00:00 2001 From: Jan Piotrowski Date: Thu, 20 Apr 2023 16:03:59 +0200 Subject: [PATCH 084/261] fix(theme.config.js): Replace default meta description and social title (#2952) Currently still nextra default. Those are shown in Slack and other social apps when sharing the website. --- docs/theme.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/theme.config.js b/docs/theme.config.js index 263a26945..00410f791 100644 --- a/docs/theme.config.js +++ b/docs/theme.config.js @@ -30,8 +30,8 @@ export default { head: ( <> - - + +