Socket
Socket
Sign inDemoInstall

postgres

Package Overview
Dependencies
0
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-beta.8 to 2.0.0-beta.9

lib/subscribe.js

10

lib/backend.js

@@ -125,8 +125,8 @@ const { errors } = require('./errors.js')

? (row[i] = value)
: (row[column.name] = transform.value ? transform.value(value) : value)
: (row[column.name] = transform.value.from ? transform.value.from(value) : value)
}
backend.query.stream
? backend.query.stream(transform.row ? transform.row(row) : row, backend.query.result)
: (backend.query.result[rows++] = transform.row ? transform.row(row) : row)
? backend.query.stream(transform.row.from ? transform.row.from(row) : row, backend.query.result)
: (backend.query.result[rows++] = transform.row.from ? transform.row.from(row) : row)
}

@@ -212,4 +212,4 @@

backend.query.statement.columns[i] = {
name: transform.column
? transform.column(x.toString('utf8', start, index - 1))
name: transform.column.from
? transform.column.from(x.toString('utf8', start, index - 1))
: x.toString('utf8', start, index - 1),

@@ -216,0 +216,0 @@ parser: parsers[type],

@@ -36,2 +36,4 @@ const net = require('net')

let connect_timer
let buffers = null
let remaining = 0

@@ -289,13 +291,27 @@ const queries = Queue()

function data(x) {
buffer = buffer.length === 0
? x
: Buffer.concat([buffer, x], buffer.length + x.length)
if (buffers) {
buffers.push(x)
remaining -= x.length
if (remaining >= 0)
return
}
buffer = buffers
? Buffer.concat(buffers, length - remaining)
: buffer.length === 0
? x
: Buffer.concat([buffer, x], buffer.length + x.length)
while (buffer.length > 4) {
length = buffer.readInt32BE(1)
if (length >= buffer.length)
if (length >= buffer.length) {
remaining = length - buffer.length
buffers = [buffer]
break
}
backend[buffer[0]](buffer.slice(0, length + 1))
buffer = buffer.slice(length + 1)
remaining = 0
buffers = null
}

@@ -302,0 +318,0 @@ }

@@ -6,2 +6,3 @@ const fs = require('fs')

const Queue = require('./queue.js')
const Subscribe = require('./subscribe.js')
const { errors, PostgresError } = require('./errors.js')

@@ -12,7 +13,10 @@ const {

arrayParser,
fromPascal,
fromCamel,
fromKebab,
inferType,
toPascal,
entries,
toCamel,
toKebab,
entries,
escape,

@@ -35,5 +39,9 @@ types,

Object.assign(Postgres, {
PostgresError,
toPascal,
toCamel,
toKebab,
fromPascal,
fromCamel,
fromKebab,
BigInt: {

@@ -58,2 +66,4 @@ to: 20,

const max = Math.max(1, options.max)
, subscribe = Subscribe(Postgres, a, b)
, transform = options.transform
, connections = Queue()

@@ -81,2 +91,3 @@ , all = []

parameters: {},
subscribe,
listen,

@@ -259,3 +270,3 @@ begin,

new Promise((resolve, reject) => {
send(connection, { resolve, reject, tagged: false, prepare: false, origin: new Error().stack }, `
send(connection, { resolve, reject, simple: true, tagged: false, prepare: false, origin: new Error().stack }, `
select b.oid, b.typarray

@@ -398,4 +409,4 @@ from pg_catalog.pg_type a

destroy(error, callback) {
callback(error)
query.writable.push({ error })
callback(error)
},

@@ -474,6 +485,12 @@ final(callback) {

return ended = Promise.race([
Promise.resolve(arrayTypesPromise).then(() => Promise.all(all.map(c => c.end())))
Promise.resolve(arrayTypesPromise).then(() => Promise.all(
(subscribe.sql ? [subscribe.sql.end({ timeout: 0 })] : []).concat(all.map(c => c.end()))
))
].concat(
timeout === 0 || timeout > 0
? new Promise(r => destroy = setTimeout(() => (all.map(c => c.destroy()), r()), timeout * 1000))
? new Promise(r => destroy = setTimeout(() => (
subscribe.sql && subscribe.sql.end({ timeout }),
all.map(c => c.destroy()),
r()
), timeout * 1000))
: []

@@ -548,3 +565,5 @@ ))

acc + (!columns.length || columns.indexOf(k) > -1
? (acc ? ',' : '') + parseValue(v, xargs, types) + ' as ' + escape(k)
? (acc ? ',' : '') + parseValue(v, xargs, types) + ' as ' + escape(
transform.column.to ? transform.column.to(k) : k
)
: ''

@@ -570,3 +589,5 @@ ),

return (columns.length ? columns : Object.keys(first)).reduce((acc, k) =>
acc + (acc ? ',' : '') + escape(k) + ' = ' + parseValue(first[k], xargs, types),
acc + (acc ? ',' : '') + escape(
transform.column.to ? transform.column.to(k) : k
) + ' = ' + parseValue(first[k], xargs, types),
''

@@ -577,3 +598,5 @@ )

function escapeHelper(xs) {
return xs.reduce((acc, x) => acc + (acc ? ',' : '') + escape(x), '')
return xs.reduce((acc, x) => acc + (acc ? ',' : '') + escape(
transform.column.to ? transform.column.to(x) : x
), '')
}

@@ -642,3 +665,3 @@

onparameter : o.onparameter,
transform : Object.assign({}, o.transform),
transform : parseTransform(o.transform || {}),
connection : Object.assign({ application_name: 'postgres.js' }, o.connection),

@@ -653,2 +676,19 @@ target_session_attrs: o.target_session_attrs || url.query.target_session_attrs || env.PGTARGETSESSIONATTRS,

function parseTransform(x) {
return {
column: {
from: typeof x.column === 'function' ? x.column : x.column && x.column.from,
to: x.column && x.column.to
},
value: {
from: typeof x.value === 'function' ? x.value : x.value && x.value.from,
to: x.value && x.value.to
},
row: {
from: typeof x.row === 'function' ? x.row : x.row && x.row.from,
to: x.row && x.row.to
}
}
}
function parseSSL(x) {

@@ -655,0 +695,0 @@ return x !== 'disable' && x !== 'false' && x

@@ -38,3 +38,3 @@ const char = module.exports.char = (acc, [k, v]) => (acc[k.charCodeAt(0)] = v, acc)

from: 17,
serialize: x => '\\x' + x.toString('hex'),
serialize: x => '\\x' + Buffer.from(x.buffer, x.byteOffset, x.byteLength).toString('hex'),
parse: x => Buffer.from(x.slice(2), 'hex')

@@ -176,2 +176,6 @@ }

module.exports.fromCamel = x => x.replace(/([A-Z])/g, '_$1').toLowerCase()
module.exports.fromPascal = x => (x.slice(0, 1) + x.slice(1).replace(/([A-Z])/g, '_$1')).toLowerCase()
module.exports.fromKebab = x => x.replace(/-/g, '_')
module.exports.errorFields = entries({

@@ -178,0 +182,0 @@ S: 'severity_local',

{
"name": "postgres",
"version": "2.0.0-beta.8",
"version": "2.0.0-beta.9",
"description": "Fastest full featured PostgreSQL client for Node.js",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -48,30 +48,30 @@ <img align="left" width="440" height="140" alt="Fastest full PostgreSQL nodejs client" src="https://raw.githubusercontent.com/porsager/postgres/master/postgresjs.svg?sanitize=true" />

const sql = postgres('postgres://username:password@host:port/database', {
host : '', // Postgres ip address[s] or domain name[s]
port : 5432, // Postgres server port[s]
path : '', // unix socket path (usually '/tmp')
database : '', // Name of database to connect to
username : '', // Username of database user
password : '', // Password of database user
ssl : false, // true, prefer, require, tls.connect options
max : 10, // Max number of connections
idle_timeout : 0, // Idle connection timeout in seconds
connect_timeout : 30, // Connect timeout in seconds
no_prepare : false, // No automatic creation of prepared statements
types : [], // Array of custom types, see more below
onnotice : fn // Defaults to console.log
onparameter : fn // (key, value) when server param change
debug : fn // Is called with (connection, query, params)
transform : {
column : fn, // Transforms incoming column names
value : fn, // Transforms incoming row values
row : fn // Transforms entire rows
host : '', // Postgres ip address[s] or domain name[s]
port : 5432, // Postgres server port[s]
path : '', // unix socket path (usually '/tmp')
database : '', // Name of database to connect to
username : '', // Username of database user
password : '', // Password of database user
ssl : false, // true, prefer, require, tls.connect options
max : 10, // Max number of connections
idle_timeout : 0, // Idle connection timeout in seconds
connect_timeout : 30, // Connect timeout in seconds
no_prepare : false, // No automatic creation of prepared statements
types : [], // Array of custom types, see more below
onnotice : fn, // Defaults to console.log
onparameter : fn, // (key, value) when server param change
debug : fn, // Is called with (connection, query, params)
transform : {
column : fn, // Transforms incoming column names
value : fn, // Transforms incoming row values
row : fn // Transforms entire rows
},
connection : {
application_name : 'postgres.js', // Default application_name
... // Other connection parameters
connection : {
application_name : 'postgres.js', // Default application_name
... // Other connection parameters
},
target_session_attrs : null // Use 'read-write' with multiple hosts to
// ensure only connecting to primary
fetch_array_types : true // Disable automatically fetching array types
// on initial connection.
target_session_attrs : null, // Use 'read-write' with multiple hosts to
// ensure only connecting to primary
fetch_array_types : true, // Disable automatically fetching array types
// on initial connection.
})

@@ -147,5 +147,41 @@ ```

#### Query parameters
#### TypeScript support
Parameters are automatically inferred and handled by Postgres so that SQL injection isn't possible. No special handling is necessary, simply use JS tagged template literals as usual.
```js
let search = 'Mur'
const users = await sql`
select
name,
age
from users
where
name like ${ search + '%' }
`
// users = [{ name: 'Murray', age: 68 }]
```
> Be careful with quotation marks here. Because Postgres infers the types, you don't need to wrap your interpolated parameters in quotes like `'${name}'`. In fact, this will cause an error because the tagged template replaces `${name}` with `$1` in the query string, leaving Postgres to do the interpolation. If you wrap that in a string, Postgres will see `'$1'` and interpret it as a string as opposed to a parameter.
#### Arrays
Arrays will be handled by replacement parameters too, so `where in` queries are also simple.
```js
const users = await sql`
select
*
from users
where age in (${ [68, 75, 23] })
`
```
### TypeScript support
`postgres` has TypeScript support. You can pass a row list type for your queries in this way:

@@ -188,36 +224,2 @@ ```ts

#### Query parameters
Parameters are automatically inferred and handled by Postgres so that SQL injection isn't possible. No special handling is necessary, simply use JS tagged template literals as usual.
```js
let search = 'Mur'
const users = await sql`
select
name,
age
from users
where
name like ${ search + '%' }
`
// users = [{ name: 'Murray', age: 68 }]
```
Arrays will be handled by replacement parameters too, so `where in` queries are also simple.
```js
const users = await sql`
select
*
from users
where age in (${ [68, 75, 23] })
`
```
## Stream ```sql` `.stream(fn) -> Promise```

@@ -467,2 +469,48 @@

## Subscribe / Realtime
Postgres.js implements the logical replication protocol of PostgreSQL to support subscription to realtime updates of `insert`, `update` and `delete` operations.
> **NOTE** To make this work you must [create the proper publications in your database](https://www.postgresql.org/docs/current/sql-createpublication.html), enable logical replication by setting `wal_level = logical` in `postgresql.conf` and connect using either a replication or superuser.
### Quick start
#### Create a publication (eg. in migration)
```sql
CREATE PUBLICATION alltables FOR ALL TABLES
```
#### Subscribe to updates
```js
const sql = postgres({ publications: 'alltables' })
const { unsubscribe } = await sql.subscribe('insert:events', row =>
// tell about new event row over eg. websockets or do something else
)
```
### Subscribe pattern
You can subscribe to specific operations, tables or even rows with primary keys.
### `operation` `:` `schema` `.` `table` `=` `primary_key`
**`operation`** is one of ``` * | insert | update | delete ``` and defaults to `*`
**`schema`** defaults to `public.`
**`table`** is a specific table name and defaults to `*`
**`primary_key`** can be used to only subscribe to specific rows
#### Examples
```js
sql.subscribe('*', () => /* everything */ )
sql.subscribe('insert', () => /* all inserts */ )
sql.subscribe('*:users', () => /* all operations on the public.users table */ )
sql.subscribe('delete:users', () => /* all deletes on the public.users table */ )
sql.subscribe('update:users=1', () => /* all updates on the users row with a primary key = 1 */ )
```
## Transactions

@@ -538,6 +586,7 @@

## Types
You can add ergonomic support for custom types, or simply pass an object with a `{ type, value }` signature that contains the Postgres `oid` for the type and the correctly serialized value.
## Custom Types
You can add ergonomic support for custom types, or simply pass an object with a `{ type, value }` signature that contains the Postgres `oid` for the type and the correctly serialized value. _(`oid` values for types can be found in the `pg_catalog.pg_types` table.)_
Adding Query helpers is the recommended approach which can be done like this:

@@ -547,8 +596,15 @@

const sql = sql({
const sql = postgres({
types: {
rect: {
// The pg_types oid to pass to the db along with the serialized value.
to : 1337,
// An array of pg_types oids to handle when parsing values coming from the db.
from : [1337],
//Function that transform values before sending them to the db.
serialize : ({ x, y, width, height }) => [x, y, width, height],
// Function that transforms values coming from the db.
parse : ([x, y, width, height]) => { x, y, width, height }

@@ -559,2 +615,3 @@ }

// Now you can use sql.types.rect() as specified above
const [custom] = sql`

@@ -561,0 +618,0 @@ insert into rectangles (

@@ -106,6 +106,6 @@ /**

type PostgresErrorType = PostgresError
type PostgresErrorType = typeof PostgresError
declare namespace postgres {
type PostgresError = PostgresErrorType
export const PostgresError: PostgresErrorType;

@@ -112,0 +112,0 @@ /**

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc