Skip to content

Commit 9d7a21d

Browse files
committed
Build deno and cjs
1 parent 04644c0 commit 9d7a21d

File tree

9 files changed

+113
-38
lines changed

9 files changed

+113
-38
lines changed

cjs/src/connection.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
359359
}
360360

361361
function reconnect() {
362-
setTimeout(connect, closedDate ? closedDate + delay - Date.now() : 0)
362+
setTimeout(connect, closedDate ? closedDate + delay - Number(process.hrtime.bigint() / 1000000n) : 0)
363363
}
364364

365365
function connected() {
@@ -446,7 +446,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
446446
return reconnect()
447447

448448
!hadError && (query || sent.length) && error(Errors.connection('CONNECTION_CLOSED', options, socket))
449-
closedDate = Date.now()
449+
closedDate = Number(process.hrtime.bigint() / 1000000n)
450450
hadError && options.shared.retries++
451451
delay = (typeof backoff === 'function' ? backoff(options.shared.retries) : backoff) * 1000
452452
onclose(connection)

cjs/src/query.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ const Query = module.exports.Query = class Query extends Promise {
118118

119119
forEach(fn) {
120120
this.forEachFn = fn
121+
this.handle()
121122
return this
122123
}
123124

cjs/src/types.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,28 @@ function values(first, rest, parameters, types, transform) {
110110
return valuesBuilder(multi ? first : [first], parameters, types, transform, columns)
111111
}
112112

113+
function select(first, rest, parameters, types, transform) {
114+
typeof first === 'string' && (first = [first].concat(rest))
115+
if (Array.isArray(first))
116+
return first.map(x => escapeIdentifier(transform.column.to ? transform.column.to(x) : x)).join(',')
117+
118+
let value
119+
const columns = rest.length ? rest.flat() : Object.keys(first)
120+
return columns.map(x => {
121+
value = first[x]
122+
return (
123+
value instanceof Query ? value.strings[0] :
124+
value instanceof Identifier ? value.value :
125+
handleValue(value, parameters, types)
126+
) + ' as ' + escapeIdentifier(transform.column.to ? transform.column.to(x) : x)
127+
}).join(',')
128+
}
129+
113130
const builders = Object.entries({
114131
values,
115132
in: values,
133+
select,
134+
returning: select,
116135

117136
update(first, rest, parameters, types, transform) {
118137
return (rest.length ? rest.flat() : Object.keys(first)).map(x =>
@@ -121,23 +140,6 @@ const builders = Object.entries({
121140
)
122141
},
123142

124-
select(first, rest, parameters, types, transform) {
125-
typeof first === 'string' && (first = [first].concat(rest))
126-
if (Array.isArray(first))
127-
return first.map(x => escapeIdentifier(transform.column.to ? transform.column.to(x) : x)).join(',')
128-
129-
let value
130-
const columns = rest.length ? rest.flat() : Object.keys(first)
131-
return columns.map(x => {
132-
value = first[x]
133-
return (
134-
value instanceof Query ? value.strings[0] :
135-
value instanceof Identifier ? value.value :
136-
handleValue(value, parameters, types)
137-
) + ' as ' + escapeIdentifier(transform.column.to ? transform.column.to(x) : x)
138-
}).join(',')
139-
},
140-
141143
insert(first, rest, parameters, types, transform) {
142144
const columns = rest.length ? rest.flat() : Object.keys(Array.isArray(first) ? first[0] : first)
143145
return '(' + columns.map(x =>

cjs/tests/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,15 @@ t('dynamic select array', async() => {
961961
return ['yay', (await sql`select ${ sql(['a', 'b']) } from test`)[0].b, await sql`drop table test`]
962962
})
963963

964+
t('dynamic returning array', async() => {
965+
await sql`create table test (a int, b text)`
966+
return [
967+
'yay',
968+
(await sql`insert into test (a, b) values (42, 'yay') returning ${ sql(['a', 'b']) }`)[0].b,
969+
await sql`drop table test`
970+
]
971+
})
972+
964973
t('dynamic select args', async() => {
965974
await sql`create table test (a int, b text)`
966975
await sql`insert into test (a, b) values (42, 'yay')`

deno/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ async function insertUser({ name, age }) {
6464
* [Building queries](#building-queries)
6565
* [Advanced query methods](#advanced-query-methods)
6666
* [Transactions](#transactions)
67+
* [Data Transformation](#data-transformation)
6768
* [Listen & notify](#listen--notify)
6869
* [Realtime subscribe](#realtime-subscribe)
6970
* [Numbers, bigint, numeric](#numbers-bigint-numeric)
@@ -513,6 +514,38 @@ sql.begin('read write', async sql => {
513514
514515
Do note that you can often achieve the same result using [`WITH` queries (Common Table Expressions)](https://www.postgresql.org/docs/current/queries-with.html) instead of using transactions.
515516
517+
## Data Transformation
518+
519+
`postgres.js` comes with a number of built-in data transformation functions that can be used to transform the data returned from a query or when inserting data. They are available under `transformation` option in the `postgres()` function connection options.
520+
521+
Like - `postgres('connectionURL', { transformation: {...} })`
522+
523+
### Parameters
524+
* `to`: The function to transform the outgoing query column name to, i.e ``SELECT ${ sql('aName') }` to `SELECT a_name` when using `postgres.toCamel`.
525+
* `from`: The function to transform the incoming query result column name to, see example below.
526+
527+
> Both parameters are optional, if not provided, the default transformation function will be used.
528+
529+
Built in transformation functions are:
530+
* For camelCase - `postgres.toCamel` and `postgres.fromCamel`
531+
* For PascalCase - `postgres.toPascal` and `postgres.fromPascal`
532+
* For Kebab-Case - `postgres.toKebab` and `postgres.fromKebab`
533+
534+
These functions can be passed in as options when calling `postgres()`. For example -
535+
```js
536+
// this will tranform the column names to camel case back and forth
537+
(async function () {
538+
const sql = postgres('connectionURL', { transform: { column: { to: postgres.fromCamel, from: postgres.toCamel } }});
539+
await sql`CREATE TABLE IF NOT EXISTS camel_case (a_test INTEGER, b_test TEXT)`;
540+
await sql`INSERT INTO camel_case ${ sql([{ aTest: 1, bTest: 1 }]) }`
541+
const data = await sql`SELECT ${ sql('aTest', 'bTest') } FROM camel_case`;
542+
console.log(data) // [ { aTest: 1, bTest: '1' } ]
543+
process.exit(1)
544+
})();
545+
```
546+
547+
> Note that if a column name is originally registered as snake_case in the database then to tranform it from camelCase to snake_case when querying or inserting, the column camelCase name must be put in `sql('columnName')` as it's done in the above example.
548+
516549
## Listen & notify
517550
518551
When you call `.listen`, a dedicated connection will be created to ensure that you receive notifications instantly. This connection will be used for any further calls to `.listen`. The connection will automatically reconnect according to a backoff reconnection pattern to not overload the database server.
@@ -682,6 +715,23 @@ Connections are created lazily once a query is created. This means that simply d
682715
683716
> No connection will be made until a query is made.
684717
718+
For example:
719+
720+
```js
721+
const sql = postgres() // no connections are opened
722+
723+
await sql`...` // one connection is now opened
724+
await sql`...` // previous opened connection is reused
725+
726+
// two connections are opened now
727+
await Promise.all([
728+
sql`...`,
729+
sql`...`
730+
])
731+
```
732+
733+
> When there are high amount of concurrent queries, `postgres` will open as many connections as needed up until `max` number of connections is reached. By default `max` is 10. This can be changed by setting `max` in the `postgres()` call. Example - `postgres('connectionURL', { max: 20 })`.
734+
685735
This means that we get a much simpler story for error handling and reconnections. Queries will be sent over the wire immediately on the next available connection in the pool. Connections are automatically taken out of the pool if you start a transaction using `sql.begin()`, and automatically returned to the pool once your transaction is done.
686736
687737
Any query which was already sent over the wire will be rejected if the connection is lost. It'll automatically defer to the error handling you have for that query, and since connections are lazy it'll automatically try to reconnect the next time a query is made. The benefit of this is no weird generic "onerror" handler that tries to get things back to normal, and also simpler application code since you don't have to handle errors out of context.

deno/src/connection.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { HmacSha256 } from 'https://deno.land/std@0.132.0/hash/sha256.ts'
22
import { Buffer } from 'https://deno.land/std@0.132.0/node/buffer.ts'
3+
import process from 'https://deno.land/std@0.132.0/node/process.ts'
34
import { setImmediate, clearImmediate } from '../polyfills.js'
45
import { net } from '../polyfills.js'
56
import { tls } from '../polyfills.js'
@@ -362,7 +363,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
362363
}
363364

364365
function reconnect() {
365-
setTimeout(connect, closedDate ? closedDate + delay - Date.now() : 0)
366+
setTimeout(connect, closedDate ? closedDate + delay - Number(process.hrtime.bigint() / 1000000n) : 0)
366367
}
367368

368369
function connected() {
@@ -449,7 +450,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
449450
return reconnect()
450451

451452
!hadError && (query || sent.length) && error(Errors.connection('CONNECTION_CLOSED', options, socket))
452-
closedDate = Date.now()
453+
closedDate = Number(process.hrtime.bigint() / 1000000n)
453454
hadError && options.shared.retries++
454455
delay = (typeof backoff === 'function' ? backoff(options.shared.retries) : backoff) * 1000
455456
onclose(connection)

deno/src/query.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export class Query extends Promise {
118118

119119
forEach(fn) {
120120
this.forEachFn = fn
121+
this.handle()
121122
return this
122123
}
123124

deno/src/types.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,28 @@ function values(first, rest, parameters, types, transform) {
111111
return valuesBuilder(multi ? first : [first], parameters, types, transform, columns)
112112
}
113113

114+
function select(first, rest, parameters, types, transform) {
115+
typeof first === 'string' && (first = [first].concat(rest))
116+
if (Array.isArray(first))
117+
return first.map(x => escapeIdentifier(transform.column.to ? transform.column.to(x) : x)).join(',')
118+
119+
let value
120+
const columns = rest.length ? rest.flat() : Object.keys(first)
121+
return columns.map(x => {
122+
value = first[x]
123+
return (
124+
value instanceof Query ? value.strings[0] :
125+
value instanceof Identifier ? value.value :
126+
handleValue(value, parameters, types)
127+
) + ' as ' + escapeIdentifier(transform.column.to ? transform.column.to(x) : x)
128+
}).join(',')
129+
}
130+
114131
const builders = Object.entries({
115132
values,
116133
in: values,
134+
select,
135+
returning: select,
117136

118137
update(first, rest, parameters, types, transform) {
119138
return (rest.length ? rest.flat() : Object.keys(first)).map(x =>
@@ -122,23 +141,6 @@ const builders = Object.entries({
122141
)
123142
},
124143

125-
select(first, rest, parameters, types, transform) {
126-
typeof first === 'string' && (first = [first].concat(rest))
127-
if (Array.isArray(first))
128-
return first.map(x => escapeIdentifier(transform.column.to ? transform.column.to(x) : x)).join(',')
129-
130-
let value
131-
const columns = rest.length ? rest.flat() : Object.keys(first)
132-
return columns.map(x => {
133-
value = first[x]
134-
return (
135-
value instanceof Query ? value.strings[0] :
136-
value instanceof Identifier ? value.value :
137-
handleValue(value, parameters, types)
138-
) + ' as ' + escapeIdentifier(transform.column.to ? transform.column.to(x) : x)
139-
}).join(',')
140-
},
141-
142144
insert(first, rest, parameters, types, transform) {
143145
const columns = rest.length ? rest.flat() : Object.keys(Array.isArray(first) ? first[0] : first)
144146
return '(' + columns.map(x =>

deno/tests/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,15 @@ t('dynamic select array', async() => {
963963
return ['yay', (await sql`select ${ sql(['a', 'b']) } from test`)[0].b, await sql`drop table test`]
964964
})
965965

966+
t('dynamic returning array', async() => {
967+
await sql`create table test (a int, b text)`
968+
return [
969+
'yay',
970+
(await sql`insert into test (a, b) values (42, 'yay') returning ${ sql(['a', 'b']) }`)[0].b,
971+
await sql`drop table test`
972+
]
973+
})
974+
966975
t('dynamic select args', async() => {
967976
await sql`create table test (a int, b text)`
968977
await sql`insert into test (a, b) values (42, 'yay')`

0 commit comments

Comments
 (0)