@steadybrew/postgresjs 4.1.0 → 4.2.0-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1031,6 +1031,7 @@ const sql = postgres('postgres://username:password@host:port/database', {
1031
1031
  types : [], // Array of custom types, see more below
1032
1032
  onnotice : fn, // Default console.log, set false to silence NOTICE
1033
1033
  onparameter : fn, // (key, value) when server param change
1034
+ onidle : fn, // (connId) when a connection returns to the pool idle
1034
1035
  debug : fn, // Is called with (connection, query, params, types)
1035
1036
  socket : fn, // fn returning custom socket to use
1036
1037
  transform : {
@@ -1139,6 +1140,21 @@ const sql = postgres({
1139
1140
  })
1140
1141
  ```
1141
1142
 
1143
+ ### Vercel Fluid Compute
1144
+
1145
+ On Vercel's Fluid Compute an instance can be suspended while a connection sits idle and before `idle_timeout` has closed it, which leaves the connection open on the server. `attachDatabasePool` from `@vercel/functions` keeps the instance alive until idle connections have closed. Pass it the pool through `vercelPool`:
1146
+
1147
+ ```js
1148
+ import postgres from '@steadybrew/postgresjs'
1149
+ import { vercelPool } from '@steadybrew/postgresjs/vercel'
1150
+ import { attachDatabasePool } from '@vercel/functions'
1151
+
1152
+ const sql = postgres({ idle_timeout: 5 })
1153
+ attachDatabasePool(vercelPool(sql))
1154
+ ```
1155
+
1156
+ `vercelPool` requires `idle_timeout` to be a number of seconds. It hooks into the `onidle` option, which is called with the connection id each time a connection returns to the pool idle and its idle timer starts, and it keeps any `onidle` you set yourself. If `onidle` throws, the error is rethrown as an uncaught exception and the connection is not affected. A connection that was frozen past `idle_timeout` anyway is closed when it is next handed out (see [Connection timeout](#connection-timeout)).
1157
+
1142
1158
  ### Cloudflare Workers support
1143
1159
 
1144
1160
  Postgres.js has built-in support for the [TCP socket API](https://developers.cloudflare.com/workers/runtime-apis/tcp-sockets/) in Cloudflare Workers, which is [on-track](https://github.com/wintercg/proposal-sockets-api) to be standardized and adopted in Node.js and other JavaScript runtimes, such as Deno.
package/cf/src/index.js CHANGED
@@ -160,6 +160,7 @@ function Postgres(a, b) {
160
160
  idle_timeout: null,
161
161
  max_lifetime: null,
162
162
  fetch_types: false,
163
+ onidle: null,
163
164
  onclose() {
164
165
  Object.entries(listen.channels).forEach(([name, { listeners }]) => {
165
166
  delete listen.channels[name]
@@ -369,11 +370,19 @@ function Postgres(a, b) {
369
370
  queue.push(c)
370
371
  c.queue = queue
371
372
  queue === open
372
- ? c.idleTimer.start()
373
+ ? (c.idleTimer.start(), callback(options.onidle, c.id))
373
374
  : c.idleTimer.cancel()
374
375
  return c
375
376
  }
376
377
 
378
+ function callback(fn, ...args) {
379
+ try {
380
+ fn && fn(...args)
381
+ } catch (e) {
382
+ queueMicrotask(() => { throw e })
383
+ }
384
+ }
385
+
377
386
  function json(x) {
378
387
  return new Parameter(x, 3802)
379
388
  }
@@ -616,6 +625,7 @@ function parseOptions(a, b) {
616
625
  onnotice : o.onnotice,
617
626
  onnotify : o.onnotify,
618
627
  onclose : o.onclose,
628
+ onidle : o.onidle,
619
629
  onparameter : o.onparameter,
620
630
  socket : o.socket,
621
631
  transform : parseTransform(o.transform || { undefined: undefined }),
@@ -17,6 +17,7 @@ export default function Subscribe(postgres, options) {
17
17
  fetch_types: false,
18
18
  idle_timeout: null,
19
19
  max_lifetime: null,
20
+ onidle: null,
20
21
  connection: {
21
22
  ...options.connection,
22
23
  replication: 'database'
@@ -0,0 +1,20 @@
1
+ export function vercelPool(sql) {
2
+ const idle_timeout = sql.options.idle_timeout
3
+ if (typeof idle_timeout !== 'number' || !(idle_timeout > 0))
4
+ throw new Error('vercelPool requires idle_timeout to be a positive number of seconds')
5
+
6
+ return {
7
+ options: {
8
+ idleTimeoutMillis: idle_timeout * 1000
9
+ },
10
+ on(event, fn) {
11
+ if (event !== 'release')
12
+ return
13
+
14
+ const previous = sql.options.onidle
15
+ sql.options.onidle = previous
16
+ ? id => (fn(), previous(id))
17
+ : () => fn()
18
+ }
19
+ }
20
+ }
package/cjs/src/index.js CHANGED
@@ -159,6 +159,7 @@ function Postgres(a, b) {
159
159
  idle_timeout: null,
160
160
  max_lifetime: null,
161
161
  fetch_types: false,
162
+ onidle: null,
162
163
  onclose() {
163
164
  Object.entries(listen.channels).forEach(([name, { listeners }]) => {
164
165
  delete listen.channels[name]
@@ -368,11 +369,19 @@ function Postgres(a, b) {
368
369
  queue.push(c)
369
370
  c.queue = queue
370
371
  queue === open
371
- ? c.idleTimer.start()
372
+ ? (c.idleTimer.start(), callback(options.onidle, c.id))
372
373
  : c.idleTimer.cancel()
373
374
  return c
374
375
  }
375
376
 
377
+ function callback(fn, ...args) {
378
+ try {
379
+ fn && fn(...args)
380
+ } catch (e) {
381
+ queueMicrotask(() => { throw e })
382
+ }
383
+ }
384
+
376
385
  function json(x) {
377
386
  return new Parameter(x, 3802)
378
387
  }
@@ -615,6 +624,7 @@ function parseOptions(a, b) {
615
624
  onnotice : o.onnotice,
616
625
  onnotify : o.onnotify,
617
626
  onclose : o.onclose,
627
+ onidle : o.onidle,
618
628
  onparameter : o.onparameter,
619
629
  socket : o.socket,
620
630
  transform : parseTransform(o.transform || { undefined: undefined }),
@@ -16,6 +16,7 @@ module.exports = Subscribe;function Subscribe(postgres, options) {
16
16
  fetch_types: false,
17
17
  idle_timeout: null,
18
18
  max_lifetime: null,
19
+ onidle: null,
19
20
  connection: {
20
21
  ...options.connection,
21
22
  replication: 'database'
@@ -0,0 +1,20 @@
1
+ module.exports.vercelPool = vercelPool;function vercelPool(sql) {
2
+ const idle_timeout = sql.options.idle_timeout
3
+ if (typeof idle_timeout !== 'number' || !(idle_timeout > 0))
4
+ throw new Error('vercelPool requires idle_timeout to be a positive number of seconds')
5
+
6
+ return {
7
+ options: {
8
+ idleTimeoutMillis: idle_timeout * 1000
9
+ },
10
+ on(event, fn) {
11
+ if (event !== 'release')
12
+ return
13
+
14
+ const previous = sql.options.onidle
15
+ sql.options.onidle = previous
16
+ ? id => (fn(), previous(id))
17
+ : () => fn()
18
+ }
19
+ }
20
+ }
package/package.json CHANGED
@@ -1,16 +1,25 @@
1
1
  {
2
2
  "name": "@steadybrew/postgresjs",
3
- "version": "4.1.0",
3
+ "version": "4.2.0-rc1",
4
4
  "description": "PostgreSQL client for Node.js and Deno, independently maintained by Steady Brew",
5
5
  "type": "module",
6
6
  "module": "src/index.js",
7
7
  "main": "cjs/src/index.js",
8
8
  "exports": {
9
- "types": "./types/index.d.ts",
10
- "bun": "./src/index.js",
11
- "workerd": "./cf/src/index.js",
12
- "import": "./src/index.js",
13
- "default": "./cjs/src/index.js"
9
+ ".": {
10
+ "types": "./types/index.d.ts",
11
+ "bun": "./src/index.js",
12
+ "workerd": "./cf/src/index.js",
13
+ "import": "./src/index.js",
14
+ "default": "./cjs/src/index.js"
15
+ },
16
+ "./vercel": {
17
+ "types": "./types/vercel.d.ts",
18
+ "bun": "./src/vercel.js",
19
+ "workerd": "./cf/src/vercel.js",
20
+ "import": "./src/vercel.js",
21
+ "default": "./cjs/src/vercel.js"
22
+ }
14
23
  },
15
24
  "types": "types/index.d.ts",
16
25
  "typings": "types/index.d.ts",
@@ -44,7 +53,10 @@
44
53
  ],
45
54
  "author": "Rasmus Porsager <rasmus@porsager.com> (https://www.porsager.com)",
46
55
  "license": "Unlicense",
47
- "repository": "github:steadybrew/postgresjs",
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/steadybrew/postgresjs.git"
59
+ },
48
60
  "homepage": "https://github.com/steadybrew/postgresjs",
49
61
  "bugs": "https://github.com/steadybrew/postgresjs/issues",
50
62
  "keywords": [
package/src/index.js CHANGED
@@ -159,6 +159,7 @@ function Postgres(a, b) {
159
159
  idle_timeout: null,
160
160
  max_lifetime: null,
161
161
  fetch_types: false,
162
+ onidle: null,
162
163
  onclose() {
163
164
  Object.entries(listen.channels).forEach(([name, { listeners }]) => {
164
165
  delete listen.channels[name]
@@ -368,11 +369,19 @@ function Postgres(a, b) {
368
369
  queue.push(c)
369
370
  c.queue = queue
370
371
  queue === open
371
- ? c.idleTimer.start()
372
+ ? (c.idleTimer.start(), callback(options.onidle, c.id))
372
373
  : c.idleTimer.cancel()
373
374
  return c
374
375
  }
375
376
 
377
+ function callback(fn, ...args) {
378
+ try {
379
+ fn && fn(...args)
380
+ } catch (e) {
381
+ queueMicrotask(() => { throw e })
382
+ }
383
+ }
384
+
376
385
  function json(x) {
377
386
  return new Parameter(x, 3802)
378
387
  }
@@ -615,6 +624,7 @@ function parseOptions(a, b) {
615
624
  onnotice : o.onnotice,
616
625
  onnotify : o.onnotify,
617
626
  onclose : o.onclose,
627
+ onidle : o.onidle,
618
628
  onparameter : o.onparameter,
619
629
  socket : o.socket,
620
630
  transform : parseTransform(o.transform || { undefined: undefined }),
package/src/subscribe.js CHANGED
@@ -16,6 +16,7 @@ export default function Subscribe(postgres, options) {
16
16
  fetch_types: false,
17
17
  idle_timeout: null,
18
18
  max_lifetime: null,
19
+ onidle: null,
19
20
  connection: {
20
21
  ...options.connection,
21
22
  replication: 'database'
package/src/vercel.js ADDED
@@ -0,0 +1,20 @@
1
+ export function vercelPool(sql) {
2
+ const idle_timeout = sql.options.idle_timeout
3
+ if (typeof idle_timeout !== 'number' || !(idle_timeout > 0))
4
+ throw new Error('vercelPool requires idle_timeout to be a positive number of seconds')
5
+
6
+ return {
7
+ options: {
8
+ idleTimeoutMillis: idle_timeout * 1000
9
+ },
10
+ on(event, fn) {
11
+ if (event !== 'release')
12
+ return
13
+
14
+ const previous = sql.options.onidle
15
+ sql.options.onidle = previous
16
+ ? id => (fn(), previous(id))
17
+ : () => fn()
18
+ }
19
+ }
20
+ }
package/types/index.d.ts CHANGED
@@ -119,6 +119,8 @@ interface BaseOptions<T extends Record<string, postgres.PostgresType>> {
119
119
  */
120
120
  publications: string
121
121
  onclose: (connId: number) => void;
122
+ /** Called with the connection id each time a connection returns to the pool idle and its idle timer starts */
123
+ onidle: (connId: number) => void;
122
124
  backoff: boolean | ((attemptNum: number) => number);
123
125
  max_lifetime: number | null;
124
126
  keep_alive: number | null;
@@ -0,0 +1,8 @@
1
+ import postgres from './index.js'
2
+
3
+ export interface VercelPool {
4
+ options: { idleTimeoutMillis: number };
5
+ on(event: string, listener: () => void): void;
6
+ }
7
+
8
+ export function vercelPool(sql: postgres.Sql<any>): VercelPool;