diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index d60b0cc49..04e8074b9 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -3,7 +3,7 @@
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
-FROM node:12
+FROM node:20
# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
@@ -16,9 +16,11 @@ ARG USERNAME=node
ARG USER_UID=1000
ARG USER_GID=$USER_UID
+RUN echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list
+
# Configure apt and install packages
RUN apt-get update \
- && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \
+ && apt-get -y install --no-install-recommends dialog 2>&1 \
#
# Verify git and needed tools are installed
&& apt-get -y install git iproute2 procps \
@@ -33,6 +35,7 @@ RUN apt-get update \
&& echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends yarn tmux locales postgresql \
+ && apt-get install libpq-dev g++ make \
#
# Install eslint globally
&& npm install -g eslint \
@@ -47,7 +50,6 @@ RUN apt-get update \
&& apt-get install -y sudo \
&& echo node ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME \
- #
# Clean up
&& apt-get autoremove -y \
&& apt-get clean -y \
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 14fb67344..c8e4b7108 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,31 +1,16 @@
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
{
- "name": "Node.js 12 & Postgres",
+ "name": "Node.js 20 & Postgres",
"dockerComposeFile": "docker-compose.yml",
"service": "web",
"workspaceFolder": "/workspace",
-
- // Use 'settings' to set *default* container specific settings.json values on container create.
- // You can edit these settings after create using File > Preferences > Settings > Remote.
- "settings": {
- "terminal.integrated.shell.linux": "/bin/bash"
- },
-
- // Uncomment the next line if you want start specific services in your Docker Compose config.
- // "runServices": [],
-
- // Uncomment the line below if you want to keep your containers running after VS Code shuts down.
- // "shutdownAction": "none",
-
- // Uncomment the next line to run commands after the container is created.
- // "postCreateCommand": "npm install",
-
- // Uncomment the next line to have VS Code connect as an existing non-root user in the container. See
- // https://aka.ms/vscode-remote/containers/non-root for details on adding a non-root user if none exist.
- // "remoteUser": "node",
-
// Add the IDs of extensions you want installed when the container is created in the array below.
- "extensions": [
- "dbaeumer.vscode-eslint"
- ]
-}
\ No newline at end of file
+ "customizations":{
+ "vscode": {
+ "extensions": ["dbaeumer.vscode-eslint"],
+ "settings": {
+ "terminal.integrated.shell.linux": "/bin/bash"
+ }
+ }
+ }
+}
diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml
index 05475b824..11e652008 100644
--- a/.devcontainer/docker-compose.yml
+++ b/.devcontainer/docker-compose.yml
@@ -3,7 +3,7 @@
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
-version: '3'
+version: '3.9'
services:
web:
# Uncomment the next line to use a non-root user for all processes. You can also
@@ -32,16 +32,21 @@ services:
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
- links:
+ depends_on:
- db
+ links:
+ - db:db
+
db:
- image: postgres
+ image: postgres:14-alpine
restart: unless-stopped
ports:
- 5432:5432
+ command: postgres -c password_encryption=md5
environment:
+ POSTGRES_HOST_AUTH_METHOD: trust
+ POSTGRES_INITDB_ARGS: "--auth-local=md5"
POSTGRES_PASSWORD: pass
POSTGRES_USER: user
POSTGRES_DB: data
-
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 000000000..050c39538
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+/packages/*/dist/
diff --git a/.eslintrc b/.eslintrc
index 4766b9889..b1999b544 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,7 +1,7 @@
{
- "plugins": ["prettier"],
+ "plugins": ["@typescript-eslint", "prettier"],
"parser": "@typescript-eslint/parser",
- "extends": ["plugin:prettier/recommended", "prettier/@typescript-eslint"],
+ "extends": ["eslint:recommended", "plugin:prettier/recommended", "prettier"],
"ignorePatterns": ["node_modules", "coverage", "packages/pg-protocol/dist/**/*", "packages/pg-query-stream/dist/**/*"],
"parserOptions": {
"ecmaVersion": 2017,
@@ -11,5 +11,25 @@
"node": true,
"es6": true,
"mocha": true
- }
+ },
+ "rules": {
+ "@typescript-eslint/no-unused-vars": ["error", {
+ "args": "none",
+ "varsIgnorePattern": "^_$"
+ }],
+ "no-unused-vars": ["error", {
+ "args": "none",
+ "varsIgnorePattern": "^_$"
+ }],
+ "no-var": "error",
+ "prefer-const": "error"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
+ "rules": {
+ "no-undef": "off"
+ }
+ }
+ ]
}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..94f480de9
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* text=auto eol=lf
\ No newline at end of file
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 000000000..7434a61c6
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+/packages/pg-connection-string @hjr3
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ab5bef47b..e65647693 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,45 +6,70 @@ permissions:
contents: read
jobs:
- build:
+ lint:
+ timeout-minutes: 5
runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ - name: Setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ cache: yarn
+ - run: yarn install --frozen-lockfile
+ - run: yarn lint
+ build:
+ timeout-minutes: 15
+ needs: lint
services:
postgres:
- image: postgres:11
+ image: ghcr.io/railwayapp-templates/postgres-ssl
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
- POSTGRES_DB: ci_db_test
POSTGRES_HOST_AUTH_METHOD: 'md5'
+ POSTGRES_DB: ci_db_test
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
strategy:
+ fail-fast: false
matrix:
- node: ['10', '12', '14', '16', '18']
- os: [ubuntu-latest, windows-latest, macos-latest]
- name: Node.js ${{ matrix.node }} (${{ matrix.os }})
+ node:
+ - '16'
+ - '18'
+ - '20'
+ - '22'
+ - '23'
+ os:
+ - ubuntu-latest
+ name: Node.js ${{ matrix.node }}
+ runs-on: ubuntu-latest
env:
- PGUSER: postgres
- PGHOST: localhost
- PGPASSWORD: postgres
- PGDATABASE: ci_db_test
- PGTESTNOSSL: 'true'
- SCRAM_TEST_PGUSER: scram_test
- SCRAM_TEST_PGPASSWORD: test4scram
+ PGUSER: postgres
+ PGPASSWORD: postgres
+ PGHOST: localhost
+ PGDATABASE: ci_db_test
+ PGTESTNOSSL: 'true'
+ SCRAM_TEST_PGUSER: scram_test
+ SCRAM_TEST_PGPASSWORD: test4scram
steps:
+ - name: Show OS
+ run: |
+ uname -a
- run: |
psql \
-c "SET password_encryption = 'scram-sha-256'" \
-c "CREATE ROLE scram_test LOGIN PASSWORD 'test4scram'"
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup node
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: yarn
- - run: yarn install
- # TODO(bmc): get ssl tests working in ci
+ - run: yarn install --frozen-lockfile
- run: yarn test
diff --git a/.gitignore b/.gitignore
index b6e058f2e..8e242c10d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,5 +7,6 @@ package-lock.json
*.swp
dist
.DS_Store
+/.eslintcache
.vscode/
manually-test-on-heroku.js
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 011bd9e01..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,100 +0,0 @@
-language: node_js
-dist: bionic
-
-before_script: |
- yarn build
- node packages/pg/script/create-test-tables.js postgresql:///
-
-env:
- - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres
-
-node_js:
- - lts/dubnium
- - lts/erbium
- # node 13.7 seems to have changed behavior of async iterators exiting early on streams
- # if 13.8 still has this problem when it comes down I'll talk to the node team about the change
- # in the mean time...peg to 13.6
- - 13.6
- - 14
-
-addons:
- postgresql: '10'
-
-matrix:
- include:
- # Run tests/paths that require password authentication
- - node_js: lts/erbium
- env:
- - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres PGPASSWORD=test-password SCRAM_TEST_PGUSER=scram_test SCRAM_TEST_PGPASSWORD=test4scram
- before_script: |
- sudo -u postgres sed -i \
- -e '/^local/ s/trust$/peer/' \
- -e '/^host/ s/trust$/md5/' \
- /etc/postgresql/10/main/pg_hba.conf
- sudo -u postgres psql -c "ALTER ROLE postgres PASSWORD 'test-password'; SELECT pg_reload_conf()"
- yarn build
- node packages/pg/script/create-test-tables.js postgresql:///
- sudo -u postgres -- psql \
- -c "SET password_encryption = 'scram-sha-256'" \
- -c "CREATE ROLE scram_test login password 'test4scram'"
-
- - node_js: lts/carbon
- addons:
- postgresql: '9.5'
- dist: precise
-
- # Run tests/paths with client certificate authentication
- - node_js: lts/*
- env:
- - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres
- PGSSLMODE=verify-full
- PGSSLROOTCERT=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-server-ca.crt
- PGSSLCERT=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-client.crt
- PGSSLKEY=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-client.key
- PG_CLIENT_CERT_TEST=1
- before_script:
- - chmod go= packages/pg/test/tls/test-client.key
- - |
- sudo sed -i \
- -e '/^ssl_cert_file =/d' \
- -e '/^ssl_key_file =/d' \
- /etc/postgresql/10/main/postgresql.conf
-
- cat <<'travis ci breaks heredoc' | sudo tee -a /etc/postgresql/10/main/postgresql.conf > /dev/null
- ssl_cert_file = 'test-server.crt'
- ssl_key_file = 'test-server.key'
- ssl_ca_file = 'test-client-ca.crt'
-
- - printf 'hostssl all all %s cert\n' 127.0.0.1/32 ::1/128 | sudo tee /etc/postgresql/10/main/pg_hba.conf > /dev/null
- - sudo make -C packages/pg/test/tls install DESTDIR=/var/ramfs/postgresql/10/main
- - sudo systemctl restart postgresql@10-main
- - yarn build
- script:
- - cd packages/pg
- - node test/integration/connection-pool/tls-tests.js
- - npm install --no-save pg-native
- - node test/integration/connection-pool/tls-tests.js native
-
- # different PostgreSQL versions on Node LTS
- - node_js: lts/erbium
- addons:
- postgresql: '9.3'
- - node_js: lts/erbium
- addons:
- postgresql: '9.4'
- - node_js: lts/erbium
- addons:
- postgresql: '9.5'
- - node_js: lts/erbium
- addons:
- postgresql: '9.6'
-
- # only run lint on latest Node LTS
- - node_js: lts/*
- script: yarn lint
-
- # PostgreSQL 9.2 only works on precise
- - node_js: lts/carbon
- addons:
- postgresql: '9.2'
- dist: precise
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bf05426e3..24261efa4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,22 @@ 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.15.0
+
+- Add support for [esm](https://github.com/brianc/node-postgres/pull/3423) importing. CommonJS importing is still also supported.
+
+## pg@8.14.0
+
+- Add support from SCRAM-SAH-256-PLUS i.e. [channel binding](https://github.com/brianc/node-postgres/pull/3356).
+
+## pg@8.13.0
+
+- Add ability to specify query timeout on [per-query basis](https://github.com/brianc/node-postgres/pull/3074).
+
+## pg@8.12.0
+
+- Add `queryMode` config option to [force use of the extended query protocol](https://github.com/brianc/node-postgres/pull/3214) on queries without any parameters.
+
## pg-pool@8.10.0
- Emit `release` event when client is returned to [the pool](https://github.com/brianc/node-postgres/pull/2845).
@@ -64,7 +80,7 @@ We do not include break-fix version release in this file.
### pg@8.2.0
-- Switch internal protocol parser & serializer to [pg-protocol](https://github.com/brianc/node-postgres/tree/master/packages/pg-protocol). The change is backwards compatible but results in a significant performance improvement across the board, with some queries as much as 50% faster. This is the first work to land in an on-going performance improvment initiative I'm working on. Stay tuned as things are set to get much faster still! :rocket:
+- Switch internal protocol parser & serializer to [pg-protocol](https://github.com/brianc/node-postgres/tree/master/packages/pg-protocol). The change is backwards compatible but results in a significant performance improvement across the board, with some queries as much as 50% faster. This is the first work to land in an on-going performance improvement initiative I'm working on. Stay tuned as things are set to get much faster still! :rocket:
### pg-cursor@2.2.0
diff --git a/README.md b/README.md
index 35d338000..a680ff7b3 100644
--- a/README.md
+++ b/README.md
@@ -12,11 +12,18 @@ This repo is a monorepo which contains the core [pg](https://github.com/brianc/n
- [pg](https://github.com/brianc/node-postgres/tree/master/packages/pg)
- [pg-pool](https://github.com/brianc/node-postgres/tree/master/packages/pg-pool)
+- [pg-native](https://github.com/brianc/node-postgres/tree/master/packages/pg-native)
- [pg-cursor](https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor)
- [pg-query-stream](https://github.com/brianc/node-postgres/tree/master/packages/pg-query-stream)
- [pg-connection-string](https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string)
- [pg-protocol](https://github.com/brianc/node-postgres/tree/master/packages/pg-protocol)
+## Install
+
+```
+npm install pg
+```
+
## Documentation
Each package in this repo should have its own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see:
@@ -59,6 +66,12 @@ node-postgres's continued development has been made possible in part by generous
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.
+### Featured sponsor
+
+Special thanks to [medplum](https://medplum.com) for their generous and thoughtful support of node-postgres!
+
+
+
## Contributing
**:heart: contributions!**
@@ -74,10 +87,11 @@ If your change involves breaking backwards compatibility please please point tha
### Setting up for local development
1. Clone the repo
-2. From your workspace root run `yarn` and then `yarn lerna bootstrap`
-3. Ensure you have a PostgreSQL instance running with SSL enabled and an empty database for tests
-4. Ensure you have the proper environment variables configured for connecting to the instance
-5. Run `yarn test` to run all the tests
+2. Ensure you have installed libpq-dev in your system.
+3. From your workspace root run `yarn` and then `yarn lerna bootstrap`
+4. Ensure you have a PostgreSQL instance running with SSL enabled and an empty database for tests
+5. Ensure you have the proper environment variables configured for connecting to the instance
+6. Run `yarn test` to run all the tests
## Troubleshooting and FAQ
diff --git a/SPONSORS.md b/SPONSORS.md
index c16b8d3df..dfcbbd0ab 100644
--- a/SPONSORS.md
+++ b/SPONSORS.md
@@ -15,8 +15,11 @@ node-postgres is made possible by the helpful contributors from the community as
- [mpirik](https://github.com/mpirik)
- [@BLUE-DEVIL1134](https://github.com/BLUE-DEVIL1134)
- [bubble.io](https://bubble.io/)
-- GitHub[https://github.com/github]
-- loveland [https://github.com/loveland]
+- [GitHub](https://github.com/github)
+- [n8n](https://n8n.io/)
+- [loveland](https://github.com/loveland)
+- [gajus](https://github.com/gajus)
+- [thirdiron](https://github.com/thirdiron)
# Supporters
@@ -50,3 +53,4 @@ node-postgres is made possible by the helpful contributors from the community as
- [Sideline Sports](https://github.com/SidelineSports)
- [Gadget](https://github.com/gadget-inc)
- [Sentry](https://sentry.io/welcome/)
+- [devlikeapro](https://github.com/devlikepro)
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000..d19c590b9
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,20 @@
+# node-postgres docs website
+
+This is the documentation for node-postgres which is currently hosted at [https://node-postgres.com](https://node-postgres.com).
+
+## Development
+
+To run the documentation locally, you need to have [Node.js](https://nodejs.org) installed. Then, you can clone the repository and install the dependencies:
+
+```bash
+cd docs
+yarn
+```
+
+Once you've installed the deps, you can run the development server:
+
+```bash
+yarn dev
+```
+
+This will start a local server at [http://localhost:3000](http://localhost:3000) where you can view the documentation and see your changes.
diff --git a/docs/components/logo.tsx b/docs/components/logo.tsx
new file mode 100644
index 000000000..5d1175deb
--- /dev/null
+++ b/docs/components/logo.tsx
@@ -0,0 +1,11 @@
+import React from 'react'
+
+type Props = {
+ src: string
+ alt?: string
+}
+
+export function Logo(props: Props) {
+ const alt = props.alt || 'Logo'
+ return
+}
diff --git a/docs/pages/announcements.mdx b/docs/pages/announcements.mdx
index 2bc55e00a..d6a17c244 100644
--- a/docs/pages/announcements.mdx
+++ b/docs/pages/announcements.mdx
@@ -47,11 +47,11 @@ new Client({
- 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.
+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 improvements 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!
+`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 unintentionally. You can still do `console.log(client.password)` if you really want to see it!
- make `pg.native` non-enumerable
@@ -113,10 +113,11 @@ pg@7.1.2
### Example
-To demonstrate the issue & see if you are vunerable execute the following in node:
+To demonstrate the issue & see if you are vulnerable execute the following in node:
```js
-import { Client } from 'pg'
+import pg from 'pg'
+const { Client } = pg
const client = new Client()
client.connect()
diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx
index 340f95c6e..9ce6b111a 100644
--- a/docs/pages/apis/client.mdx
+++ b/docs/pages/apis/client.mdx
@@ -13,16 +13,20 @@ 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
+ database?: string, // default process.env.PGDATABASE || user
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
+ lock_timeout?: number, // number of milliseconds a query is allowed to be en lock state before it's cancelled due to lock timeout
application_name?: string, // The name of the application that created this Client instance
connectionTimeoutMillis?: number, // number of milliseconds to wait for connection, default is no timeout
- idle_in_transaction_session_timeout?: number // number of milliseconds before terminating any session with an open idle transaction, 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
+ client_encoding?: string, // specifies the character set encoding that the database uses for sending data to the client
+ fallback_application_name?: string, // provide an application name to use if application_name is not set
+ options?: string // command-line options to be sent to the server
}
```
@@ -32,11 +36,11 @@ example to create a client with specific connection information:
import { Client } from 'pg'
const client = new Client({
+ user: 'database-user',
+ password: 'secretpassword!!',
host: 'my.database-server.com',
port: 5334,
database: 'database-name',
- user: 'database-user',
- password: 'secretpassword!!',
})
```
@@ -72,6 +76,9 @@ type QueryConfig {
// custom type parsers just for this query result
types?: Types;
+
+ // TODO: document
+ queryMode?: string;
}
```
@@ -173,7 +180,7 @@ console.log('client has disconnected')
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` 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:
+When the client is in the process of connecting, dispatching a query, or disconnecting it will catch and forward errors from the PostgreSQL server to the respective `client.connect` `client.query` or `client.end` 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()
diff --git a/docs/pages/apis/cursor.mdx b/docs/pages/apis/cursor.mdx
index 286e9ca5e..810bccdd3 100644
--- a/docs/pages/apis/cursor.mdx
+++ b/docs/pages/apis/cursor.mdx
@@ -1,6 +1,6 @@
---
title: pg.Cursor
-slug: /api/cursor
+slug: /apis/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.
@@ -28,11 +28,9 @@ const values = [10]
const cursor = client.query(new Cursor(text, values))
-cursor.read(100, (err, rows) => {
- cursor.close(() => {
- client.release()
- })
-})
+const { rows } = await cursor.read(100)
+console.log(rows.length) // 100 (unless the table has fewer than 100 rows)
+client.release()
```
```ts
diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx
index 3cf32b6c4..0a7dd1a43 100644
--- a/docs/pages/apis/pool.mdx
+++ b/docs/pages/apis/pool.mdx
@@ -29,9 +29,17 @@ type Config = {
idleTimeoutMillis?: number
// maximum number of clients the pool should contain
- // by default this is set to 10.
+ // by default this is set to 10. There is some nuance to setting the maxium size of your pool.
+ // see https://node-postgres.com/guides/pool-sizing for more information
max?: number
+ // minimum number of clients the pool should hold on to and _not_ destroy with the idleTimeoutMillis
+ // this can be useful if you get very bursty traffic and want to keep a few clients around.
+ // note: current the pool will not automatically create and connect new clients up to the min, it will
+ // only not evict and close clients except those which execeed the min count.
+ // the default is 0 which disables this behavior.
+ min?: 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
diff --git a/docs/pages/apis/result.mdx b/docs/pages/apis/result.mdx
index 62888f112..da26adc70 100644
--- a/docs/pages/apis/result.mdx
+++ b/docs/pages/apis/result.mdx
@@ -1,6 +1,6 @@
---
title: pg.Result
-slug: /api/result
+slug: /apis/result
---
The `pg.Result` shape is returned for every successful query.
@@ -18,7 +18,8 @@ Every result will have a rows array. If no rows are returned the array will be e
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
-import { Pool } from 'pg'
+import pg from 'pg'
+const { Pool } = pg
const pool = new Pool()
@@ -41,7 +42,7 @@ The command type last executed: `INSERT` `UPDATE` `CREATE` `SELECT` etc.
The number of rows processed by the last command. Can be `null` for commands that never affect rows, such as the `LOCK`-command. More specifically, some commands, including `LOCK`, only return a command tag of the form `COMMAND`, without any `[ROWS]`-field to parse. For such commands `rowCount` will be `null`.
-_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`_.
+_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 response on a `SELECT` query use `result.rows.length === 0`_.
[@sehrope](https://github.com/brianc/node-postgres/issues/2182#issuecomment-620553915) has a good explanation:
diff --git a/docs/pages/apis/types.mdx b/docs/pages/apis/types.mdx
index 55f3b0009..cc8e4c1e3 100644
--- a/docs/pages/apis/types.mdx
+++ b/docs/pages/apis/types.mdx
@@ -1,6 +1,6 @@
---
title: Types
-slug: /api/types
+slug: /apis/types
---
These docs are incomplete, for now please reference [pg-types docs](https://github.com/brianc/node-pg-types).
diff --git a/docs/pages/apis/utilities.mdx b/docs/pages/apis/utilities.mdx
index 921cba8e4..10d9a0108 100644
--- a/docs/pages/apis/utilities.mdx
+++ b/docs/pages/apis/utilities.mdx
@@ -9,7 +9,7 @@ import { Alert } from '/components/alert.tsx'
Escapes a string as a [SQL identifier](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS).
```js
-const { escapeIdentifier } = require('pg')
+import { escapeIdentifier } from 'pg';
const escapedIdentifier = escapeIdentifier('FooIdentifier')
console.log(escapedIdentifier) // '"FooIdentifier"'
```
@@ -27,7 +27,7 @@ console.log(escapedIdentifier) // '"FooIdentifier"'
Escapes a string as a [SQL literal](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS).
```js
-const { escapeLiteral } = require('pg')
+import { escapeLiteral } from 'pg';
const escapedLiteral = escapeLiteral("hello 'world'")
console.log(escapedLiteral) // "'hello ''world'''"
```
diff --git a/docs/pages/features/_meta.json b/docs/pages/features/_meta.json
index a2f5e340a..1c7980490 100644
--- a/docs/pages/features/_meta.json
+++ b/docs/pages/features/_meta.json
@@ -5,5 +5,7 @@
"transactions": "Transactions",
"types": "Data Types",
"ssl": "SSL",
- "native": "Native"
+ "native": "Native",
+ "esm": "ESM",
+ "callbacks": "Callbacks"
}
diff --git a/docs/pages/features/callbacks.mdx b/docs/pages/features/callbacks.mdx
new file mode 100644
index 000000000..8a6e2a525
--- /dev/null
+++ b/docs/pages/features/callbacks.mdx
@@ -0,0 +1,39 @@
+---
+title: Callbacks
+---
+
+## Callback Support
+
+`async` / `await` is the preferred way to write async code these days with node, but callbacks are supported in the `pg` module and the `pg-pool` module. To use them, pass a callback function as the last argument to the following methods & it will be called and a promise will not be returned:
+
+
+```js
+const { Pool, Client } = require('pg')
+
+// pool
+const pool = new Pool()
+// run a query on an available client
+pool.query('SELECT NOW()', (err, res) => {
+ console.log(err, res)
+})
+
+// check out a client to do something more complex like a transaction
+pool.connect((err, client, release) => {
+ client.query('SELECT NOW()', (err, res) => {
+ release()
+ console.log(err, res)
+ pool.end()
+ })
+
+})
+
+// single client
+const client = new Client()
+client.connect((err) => {
+ if (err) throw err
+ client.query('SELECT NOW()', (err, res) => {
+ console.log(err, res)
+ client.end()
+ })
+})
+```
diff --git a/docs/pages/features/connecting.mdx b/docs/pages/features/connecting.mdx
index 3745024ca..97b5c779f 100644
--- a/docs/pages/features/connecting.mdx
+++ b/docs/pages/features/connecting.mdx
@@ -7,7 +7,8 @@ title: Connecting
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
-import { Pool, Client } from 'pg'
+import pg from 'pg'
+const { Pool, Client } = pg
// pools will use environment variables
// for connection information
@@ -30,10 +31,10 @@ To run the above program and specify which database to connect to we can invoke
```sh
$ PGUSER=dbuser \
- PGHOST=database.server.com \
PGPASSWORD=secretpassword \
- PGDATABASE=mydb \
+ PGHOST=database.server.com \
PGPORT=3211 \
+ PGDATABASE=mydb \
node script.js
```
@@ -42,11 +43,11 @@ This allows us to write our programs without having to specify connection inform
The default values for the environment variables used are:
```
-PGHOST=localhost
PGUSER=process.env.USER
-PGDATABASE=process.env.USER
PGPASSWORD=null
+PGHOST=localhost
PGPORT=5432
+PGDATABASE=process.env.USER
```
## Programmatic
@@ -54,24 +55,25 @@ PGPORT=5432
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
-import { Pool, Client } from 'pg'
+import pg from 'pg'
+const { Pool, Client } = pg
const pool = new Pool({
user: 'dbuser',
- host: 'database.server.com',
- database: 'mydb',
password: 'secretpassword',
+ host: 'database.server.com',
port: 3211,
+ database: 'mydb',
})
console.log(await pool.query('SELECT NOW()'))
const client = new Client({
user: 'dbuser',
- host: 'database.server.com',
- database: 'mydb',
password: 'secretpassword',
+ host: 'database.server.com',
port: 3211,
+ database: 'mydb',
})
await client.connect()
@@ -84,7 +86,8 @@ await 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
-import { Pool } from 'pg'
+import pg from 'pg'
+const { Pool } = pg
import { RDS } from 'aws-sdk'
const signerOptions = {
@@ -98,16 +101,16 @@ const signerOptions = {
username: 'api-user',
}
-const signer = new RDS.Signer()
+const signer = new RDS.Signer(signerOptions)
-const getPassword = () => signer.getAuthToken(signerOptions)
+const getPassword = () => signer.getAuthToken()
const pool = new Pool({
+ user: signerOptions.username,
+ password: getPassword,
host: signerOptions.hostname,
port: signerOptions.port,
- user: signerOptions.username,
database: 'my-db',
- password: getPassword,
})
```
@@ -116,11 +119,12 @@ const pool = new Pool({
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
-import { Client } from 'pg'
+import pg from 'pg'
+const { Client } = pg
client = new Client({
- host: '/cloudsql/myproject:zone:mydb',
user: 'username',
password: 'password',
+ host: '/cloudsql/myproject:zone:mydb',
database: 'database_name',
})
```
@@ -130,7 +134,8 @@ client = new Client({
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/brianc/node-postgres/tree/master/packages/pg-connection-string).
```js
-import { Pool, Client } from 'pg'
+import pg from 'pg'
+const { Pool, Client } = pg
const connectionString = 'postgresql://dbuser:secretpassword@database.server.com:3211/mydb'
const pool = new Pool({
diff --git a/docs/pages/features/esm.mdx b/docs/pages/features/esm.mdx
new file mode 100644
index 000000000..7aac546a7
--- /dev/null
+++ b/docs/pages/features/esm.mdx
@@ -0,0 +1,37 @@
+---
+title: ESM
+---
+
+## ESM Support
+
+As of v8.15.x node-postgres supporters the __ECMAScript Module__ (ESM) format. This means you can use `import` statements instead of `require` or `import pg from 'pg'`.
+
+CommonJS modules are still supported. The ESM format is an opt-in feature and will not affect existing codebases that use CommonJS.
+
+The docs have been changed to show ESM usage, but in a CommonJS context you can still use the same code, you just need to change the import format.
+
+If you're using CommonJS, you can use the following code to import the `pg` module:
+
+```js
+ const pg = require('pg')
+ const { Client } = pg
+ // etc...
+```
+
+### ESM Usage
+
+If you're using ESM, you can use the following code to import the `pg` module:
+
+```js
+ import { Client } from 'pg'
+ // etc...
+```
+
+
+Previously if you were using ESM you would have to use the following code:
+
+```js
+ import pg from 'pg'
+ const { Client } = pg
+ // etc...
+```
diff --git a/docs/pages/features/native.mdx b/docs/pages/features/native.mdx
index c6f860119..cdec4ae9b 100644
--- a/docs/pages/features/native.mdx
+++ b/docs/pages/features/native.mdx
@@ -15,7 +15,8 @@ $ 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
-import { native } from 'pg'
+import pg from 'pg'
+const { native } = pg
const { Client, Pool } = native
```
diff --git a/docs/pages/features/pooling.mdx b/docs/pages/features/pooling.mdx
index e5e36345c..ebe2844bc 100644
--- a/docs/pages/features/pooling.mdx
+++ b/docs/pages/features/pooling.mdx
@@ -28,7 +28,8 @@ The client pool allows you to have a reusable pool of clients you can check out,
### Checkout, use, and return
```js
-import { Pool } from 'pg'
+import pg from 'pg'
+const { Pool } = pg
const pool = new Pool()
@@ -60,7 +61,8 @@ client.release()
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
-import { Pool } from 'pg'
+import pg from 'pg'
+const { Pool } = pg
const pool = new Pool()
@@ -73,7 +75,8 @@ console.log('user:', res.rows[0])
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
-import { Pool } from 'pg'
+import pg from 'pg'
+const { Pool } = pg
const pool = new Pool()
console.log('starting async query')
diff --git a/docs/pages/features/queries.mdx b/docs/pages/features/queries.mdx
index a2f6c6a5b..39bcfbe1d 100644
--- a/docs/pages/features/queries.mdx
+++ b/docs/pages/features/queries.mdx
@@ -27,7 +27,7 @@ console.log(res.rows[0])
```