@m2k-5f/pgtx 2.8.1 → 2.8.3
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 +122 -45
- package/dist/clauses/array.clause.d.ts.map +1 -1
- package/dist/clauses/array.clause.js +0 -5
- package/dist/clauses/iden.caluse.d.ts.map +1 -1
- package/dist/clauses/iden.caluse.js +0 -2
- package/dist/clauses/insert.clause.d.ts.map +1 -1
- package/dist/clauses/insert.clause.js +5 -6
- package/dist/clauses/literal.clause.d.ts.map +1 -1
- package/dist/clauses/literal.clause.js +0 -3
- package/dist/clauses/update.clause.d.ts.map +1 -1
- package/dist/clauses/update.clause.js +0 -2
- package/dist/clauses/where.clause.d.ts.map +1 -1
- package/dist/clauses/where.clause.js +0 -2
- package/dist/connection.d.ts +3 -2
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +76 -41
- package/dist/error.d.ts +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +1 -0
- package/dist/index.d.ts +30 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/pool.d.ts +2 -0
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +6 -0
- package/dist/protocol/connection-request-writer.d.ts +1 -1
- package/dist/protocol/connection-request-writer.d.ts.map +1 -1
- package/dist/protocol/connection-request-writer.js +1 -3
- package/dist/protocol/connection-response-reader.d.ts +1 -1
- package/dist/protocol/connection-response-reader.js +1 -1
- package/dist/protocol/constants.js +8 -8
- package/dist/protocol/types.d.ts +0 -2
- package/dist/protocol/types.d.ts.map +1 -1
- package/dist/protocol/types.js +2 -2
- package/dist/query.d.ts +9 -11
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +8 -10
- package/dist/transaction.d.ts +10 -2
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +78 -23
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +0 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +0 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
[](https://github.com/M2K-5F/pgtx/actions/workflows/tests.yaml)
|
|
4
4
|
[](https://www.npmjs.com/package/@m2k-5f/pgtx)
|
|
5
5
|
|
|
6
|
-
A PostgreSQL driver for Node.js
|
|
6
|
+
A PostgreSQL driver for Node.js \| Bun. Built for regular applications, not for people who need four different flavors of the same stream implementation or a config object with forty optional fields you'll never touch.
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
npm install @m2k-5f/pgtx
|
|
9
|
+
npm install @m2k-5f/pgtx # npm
|
|
10
|
+
|
|
11
|
+
bun add @m2k-5f/pgtx # bun
|
|
10
12
|
```
|
|
11
13
|
|
|
12
14
|
## Thirty seconds
|
|
@@ -25,7 +27,7 @@ const [user] = await pool.query<User>`SELECT * FROM users WHERE id = ${1}`
|
|
|
25
27
|
|
|
26
28
|
// returns rows → query, doesn't → execute
|
|
27
29
|
await pool.execute`
|
|
28
|
-
INSERT INTO users ${sql.insert<User>(
|
|
30
|
+
INSERT INTO users ${sql.insert<User>({ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 })}
|
|
29
31
|
`
|
|
30
32
|
|
|
31
33
|
await pool.begin(async tx => {
|
|
@@ -44,9 +46,9 @@ Benchmarks run on GitHub Actions (Ubuntu, 2 vCPUs), reproducible, sources in thi
|
|
|
44
46
|
|
|
45
47
|
| Connections | Pgtx | Postgres.js | Bun.sql |
|
|
46
48
|
|---:|---:|---:|---:|
|
|
47
|
-
| 50 | **
|
|
48
|
-
| 200 | **
|
|
49
|
-
| 500 | **
|
|
49
|
+
| 50 | **29,252 req/s** | 14,267 req/s | 17,634 req/s |
|
|
50
|
+
| 200 | **31,565 req/s** | 12,316 req/s | 19,441 req/s |
|
|
51
|
+
| 500 | **32,091 req/s** | 8,806 req/s | 19,267 req/s |
|
|
50
52
|
|
|
51
53
|
Bun.sql is Bun's own built-in driver, written in native code and generally treated as the speed baseline in that ecosystem. Pgtx stays ahead of it at every concurrency level tested — the gap doesn't come from JS-vs-native, it comes from the protocol implementation.
|
|
52
54
|
|
|
@@ -56,60 +58,100 @@ Bun.sql is Bun's own built-in driver, written in native code and generally treat
|
|
|
56
58
|
## The parts worth knowing about
|
|
57
59
|
|
|
58
60
|
|
|
59
|
-
###
|
|
60
|
-
|
|
61
|
-
Every query returns a `Future<T[], PostgresError>` instead of a bare `Promise`. `await` works as usual, while `Future` also provides typed error handling and recovery without a `try/catch` pyramid.
|
|
61
|
+
### Typed, fluent composition
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
Every query returns a `Future<T, PostgresError>` — a `Promise` subclass from [`fluent-future`](https://www.npmjs.com/package/fluent-future) that keeps the error type attached instead of collapsing it to `unknown`. The same chain handles both paths: transform or act on success, transform or act on failure, without a `try/catch` in sight.
|
|
64
64
|
|
|
65
65
|
```typescript
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
])
|
|
70
|
-
|
|
71
|
-
//
|
|
72
|
-
|
|
66
|
+
const user = await pool.query<User>`
|
|
67
|
+
SELECT * FROM users WHERE id = ${userId}
|
|
68
|
+
`
|
|
69
|
+
.map(rows => rows[0]) // success → new value
|
|
70
|
+
.tap(user => logger.info('loaded user', user.id)) // success → side effect, value untouched
|
|
71
|
+
.andThen(user => // success → new Future
|
|
72
|
+
pool.query<Post>`SELECT * FROM posts WHERE user_id = ${user.id}`
|
|
73
|
+
)
|
|
74
|
+
.recoverIf(err => err.code === '42P01', []) // one specific error → fallback
|
|
75
|
+
.mapErr(err => new AppError(err)) // whatever error is left → transformed
|
|
76
|
+
.tapErr(err => logger.error(err)) // error → side effect, error untouched
|
|
73
77
|
```
|
|
74
78
|
|
|
75
|
-
|
|
79
|
+
`map`, `tap`, and `andThen` never see the error; `mapErr`, `recoverIf`, and `tapErr` never see the success value — each method only touches the side it's named for, so a chain like the one above reads top to bottom without a `try/catch` breaking it up.
|
|
76
80
|
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### Full PostgreSQL type support
|
|
84
|
+
|
|
85
|
+
Pgtx uses PostgreSQL's binary protocol directly, so types aren't passed through as `any` and hoped for — geometric, temporal, and array types decode into real, named shapes:
|
|
86
|
+
|
|
77
87
|
```typescript
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
import type {
|
|
89
|
+
PgPoint, PgLine, PgLineSegment, PgBox, PgPath, PgPolygon, PgInterval
|
|
90
|
+
} from "@m2k-5f/pgtx"
|
|
91
|
+
|
|
92
|
+
const [venue] = await pool.query<{
|
|
93
|
+
id: number
|
|
94
|
+
location: PgPoint
|
|
95
|
+
footprint: PgPolygon
|
|
96
|
+
frontage: PgLineSegment
|
|
97
|
+
openHours: PgInterval
|
|
98
|
+
}>`
|
|
99
|
+
SELECT id, location, footprint, frontage, open_hours
|
|
100
|
+
FROM venues
|
|
101
|
+
WHERE id = ${venueId}
|
|
102
|
+
`
|
|
103
|
+
|
|
104
|
+
venue.location.x // number
|
|
105
|
+
venue.footprint.points // PgPoint[]
|
|
106
|
+
venue.frontage.a.y // number
|
|
107
|
+
venue.openHours.months // number
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`int8` and `int8[]` follow the same principle at the config level: set `int8toBigint` on the pool and the values you get back — and the types you write against them — are `bigint` instead of `number`, with no manual casting at the call site:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const pool = new Pool({ ...config, int8toBigint: true })
|
|
114
|
+
|
|
115
|
+
const [{ total }] = await pool.query<{
|
|
116
|
+
total: bigint
|
|
117
|
+
}>`
|
|
118
|
+
SELECT sum(amount) AS total FROM ledger
|
|
80
119
|
`
|
|
81
|
-
.recoverIf(err => err.code === '42P01', []) // undefined_table → []
|
|
82
|
-
.recoverIf(err => err.code === '23505', []) // unique_violation → []
|
|
83
|
-
.tapErr(err => logger.error(err))
|
|
84
120
|
```
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
|
|
122
|
+
Validation happens before anything hits the socket. If a bound value doesn't match the
|
|
123
|
+
column's type, you get a `PostgresError` from the driver itself — not a round trip and a
|
|
124
|
+
server-side `invalid input syntax`:
|
|
88
125
|
|
|
89
|
-
|
|
126
|
+
```typescript
|
|
127
|
+
await pool.query`INSERT INTO users (age) VALUES (${"twenty"})`
|
|
128
|
+
// PostgresError: Bind error: Parameter $1 type mismatch.
|
|
129
|
+
// Expected PostgreSQL type "int4" (number (-2147483648..2147483647)), received: "twenty".
|
|
130
|
+
// code: '22000', dataType: 'int4'
|
|
131
|
+
// hint: Pass a value matching number (-2147483648..2147483647) for $1.
|
|
132
|
+
```
|
|
90
133
|
|
|
91
|
-
The
|
|
134
|
+
The check is exact, not coercive — `1` is not a `bool`, `99999` is not an `int2`, and a
|
|
135
|
+
malformed UUID string is caught before it's encoded. Nothing is silently cast on your
|
|
136
|
+
behalf, so a type error is always your code's bug and never a value quietly changing shape
|
|
137
|
+
on the way to the database.
|
|
92
138
|
|
|
93
|
-
|
|
139
|
+
---
|
|
94
140
|
|
|
141
|
+
### Pipelining, by default
|
|
95
142
|
|
|
96
|
-
|
|
143
|
+
Queries started in the same tick are folded into one pipelined write automatically — no batching API, no config flag:
|
|
97
144
|
|
|
98
145
|
```typescript
|
|
99
|
-
|
|
100
|
-
|
|
146
|
+
const users = pool.query<User>`SELECT * FROM users`
|
|
147
|
+
const posts = pool.query<Post>`SELECT * FROM posts`
|
|
101
148
|
|
|
102
|
-
|
|
103
|
-
await stx.execute`UPDATE stock SET count = count - 1 WHERE product_id = ${productId}`
|
|
104
|
-
if (outOfStock) throw new Error('out of stock') // only the savepoint rolls back
|
|
105
|
-
}).tapErr(console.log)
|
|
106
|
-
})
|
|
149
|
+
const [usersResult, postsResult] = await Promise.all([users, posts])
|
|
107
150
|
```
|
|
108
151
|
|
|
152
|
+
Both queries go out in a single `socket.write()` and come back demuxed, in order. Whether it's 2 queries or 20, the round trip count doesn't change.
|
|
109
153
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
`Bind`/`.bind` from [fluent-future](https://www.npmjs.com/package/fluent-future) group independent queries into the same pipeline batch for you:
|
|
154
|
+
`fluent-future`'s `Bind` gives the same parallelism a shape suited to independent, differently-typed queries:
|
|
113
155
|
|
|
114
156
|
```typescript
|
|
115
157
|
// 5 queries, 2 round-trips
|
|
@@ -123,7 +165,35 @@ const { user, posts, ...data } = await Bind({
|
|
|
123
165
|
})
|
|
124
166
|
```
|
|
125
167
|
|
|
126
|
-
|
|
168
|
+
`user` and `config` fire together, pipeline together, and resolve together — still 2 RTT total, just with the results already assembled into an object instead of an array you have to destructure by position.
|
|
169
|
+
|
|
170
|
+
Errors don't leak across a batch, either. If one query in a pipelined group fails — a bad column, a constraint violation — only its own `Future` rejects; the others in the same batch still resolve normally with their own rows. Nothing gets rolled back or aborted on their account, because nothing tied them together in the first place beyond sharing a socket.
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
## Extra bits
|
|
174
|
+
|
|
175
|
+
### Transactions and savepoints
|
|
176
|
+
|
|
177
|
+
Transactions are explicit and composable:
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
await pool.begin(async tx => {
|
|
181
|
+
await tx.query`UPDATE accounts SET balance = balance - ${amount}`
|
|
182
|
+
await tx.query`UPDATE accounts SET balance = balance + ${amount}`
|
|
183
|
+
})
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Use savepoints when only part of a transaction should be rolled back:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
await tx.savepoint(async sp => {
|
|
190
|
+
await sp.query`INSERT INTO audit_log ${event}`
|
|
191
|
+
})
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
For a complete list of supported PostgreSQL types, their JavaScript input/output types, and string formats, see the [PostgreSQL Data Types](./DATATYPES.md) reference.
|
|
195
|
+
|
|
196
|
+
---
|
|
127
197
|
|
|
128
198
|
### Streaming that doesn't buffer
|
|
129
199
|
|
|
@@ -135,7 +205,6 @@ for await (const log of pool.stream<Log>`SELECT * FROM application_logs WHERE le
|
|
|
135
205
|
}
|
|
136
206
|
```
|
|
137
207
|
|
|
138
|
-
|
|
139
208
|
It's a real Web Streams object, so it drops straight into an HTTP response body:
|
|
140
209
|
|
|
141
210
|
```typescript
|
|
@@ -145,6 +214,7 @@ fetch(req) {
|
|
|
145
214
|
}
|
|
146
215
|
```
|
|
147
216
|
|
|
217
|
+
---
|
|
148
218
|
|
|
149
219
|
### LISTEN / NOTIFY without babysitting a connection
|
|
150
220
|
|
|
@@ -161,11 +231,13 @@ await unlisten() // sends UNLISTEN, hands the connection back
|
|
|
161
231
|
|
|
162
232
|
`pool.listen` borrows a dedicated connection and manages its lifecycle for you. If you need to multiplex several callbacks onto one channel on a connection you're pinning yourself, drop down to `conn.listen`/`conn.unlisten` directly — just don't release that connection back to the pool while you're still using it for that.
|
|
163
233
|
|
|
234
|
+
---
|
|
235
|
+
|
|
164
236
|
### Building queries without string-gluing
|
|
165
237
|
|
|
166
238
|
```typescript
|
|
167
239
|
// bulk insert — columns inferred from the object
|
|
168
|
-
await pool.execute`INSERT INTO users ${sql.insert(users)}`
|
|
240
|
+
await pool.execute`INSERT INTO users ${sql.insert(...users)}`
|
|
169
241
|
|
|
170
242
|
// dynamic SET clause
|
|
171
243
|
await pool.execute`UPDATE users SET ${sql.update({ status: 'active', last_login: new Date() })} WHERE id = ${userId}`
|
|
@@ -187,7 +259,7 @@ await pool.query`SELECT * FROM posts ${search ? sql.fragment`WHERE title ILIKE $
|
|
|
187
259
|
|
|
188
260
|
`undefined` means `DEFAULT` in an insert, means "skip this field" in an update, and throws if you try to hand it to `VALUES` or an array — it's meant to be a decision point, not a silent `NULL`.
|
|
189
261
|
|
|
190
|
-
|
|
262
|
+
#### Not doing this
|
|
191
263
|
|
|
192
264
|
```typescript
|
|
193
265
|
// don't
|
|
@@ -230,7 +302,7 @@ interface ConnectionPartialConfig {
|
|
|
230
302
|
logLevel?: 'error' | 'notice' | 'query' | "none" // default 'error'
|
|
231
303
|
int8toBigint?: boolean // default false
|
|
232
304
|
queryTimeout?: number // default 30000 (ms)
|
|
233
|
-
|
|
305
|
+
syncSсhedule?: 'beforeMicrotask' | 'afterMicrotask' | 'Immediate' // default 'Immediate'
|
|
234
306
|
ssl?: 'disable' | 'prefer' | 'require' // defaut 'prefer'
|
|
235
307
|
caPath?: string // forces `ssl` to 'require' if provided
|
|
236
308
|
}
|
|
@@ -255,6 +327,8 @@ class Pool {
|
|
|
255
327
|
|
|
256
328
|
get size(): number
|
|
257
329
|
get total(): number
|
|
330
|
+
get isOpened(): boolean
|
|
331
|
+
get isClosed(): boolean
|
|
258
332
|
}
|
|
259
333
|
|
|
260
334
|
interface PoolPartialConfig extends ConnectionPartialConfig {
|
|
@@ -267,6 +341,9 @@ interface PoolPartialConfig extends ConnectionPartialConfig {
|
|
|
267
341
|
```typescript
|
|
268
342
|
class Transaction {
|
|
269
343
|
query<T>(strings: TemplateStringsArray, ...values: any[]): Future<T[], PostgresError>
|
|
344
|
+
execute(templates: TemplateStringsArray, ...params: any[]): Future<void, PostgresError>
|
|
345
|
+
stream<T extends Row>(templates: TemplateStringsArray, ...params: any[]): ReadableStream<T>
|
|
346
|
+
|
|
270
347
|
commit(): Future<void, PostgresError>
|
|
271
348
|
rollback(): Future<void, PostgresError>
|
|
272
349
|
savepoint<T>(name: string, callback: (tx: Transaction) => Promise<T>): Future<T, unknown>
|
|
@@ -303,4 +380,4 @@ MIT © [M2K-5F](https://github.com/M2K-5F)
|
|
|
303
380
|
|
|
304
381
|
**Made with ❤️ and a bit of insanity**
|
|
305
382
|
|
|
306
|
-
*Manufactured under license by the **Blazing Corporation**. Side effects may include throughput.*
|
|
383
|
+
*Manufactured under license by the **Blazing Corporation**. Side effects may include throughput.*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/array.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,qBAAa,WAAY,SAAQ,MAAM;IAE/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF9B,OAAO;IAKP,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,SAAS,GAAE,MAAa,GAAG,WAAW;
|
|
1
|
+
{"version":3,"file":"array.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/array.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,qBAAa,WAAY,SAAQ,MAAM;IAE/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF9B,OAAO;IAKP,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,SAAS,GAAE,MAAa,GAAG,WAAW;IAKzD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAarD"}
|
|
@@ -6,15 +6,10 @@ export class ArrayClause extends Clause {
|
|
|
6
6
|
this.separator = separator;
|
|
7
7
|
}
|
|
8
8
|
static create(array, separator = ", ") {
|
|
9
|
-
if (array.length === 0)
|
|
10
|
-
throw new Error('Array clause is empty.\n Use sql.array([null]) if you want no results, or check your data.');
|
|
11
9
|
return new ArrayClause(array, separator);
|
|
12
10
|
}
|
|
13
11
|
mapIntoQuery(params) {
|
|
14
12
|
this.array.forEach((value, index) => {
|
|
15
|
-
if (value === undefined) {
|
|
16
|
-
throw new TypeError(`Array item at index ${index} is undefined`);
|
|
17
|
-
}
|
|
18
13
|
if (index)
|
|
19
14
|
params.text += this.separator;
|
|
20
15
|
if (value instanceof Clause) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iden.caluse.d.ts","sourceRoot":"","sources":["../../src/clauses/iden.caluse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C,qBAAa,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEtD,QAAQ,CAAC,KAAK,EAAE,CAAC;IADrB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,aAAa,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"iden.caluse.d.ts","sourceRoot":"","sources":["../../src/clauses/iden.caluse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C,qBAAa,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEtD,QAAQ,CAAC,KAAK,EAAE,CAAC;IADrB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,aAAa,EAAE,CAAC;IAIvC,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAGrD"}
|
|
@@ -5,8 +5,6 @@ export class IdentifierClause extends Clause {
|
|
|
5
5
|
this.value = value;
|
|
6
6
|
}
|
|
7
7
|
static create(identificator) {
|
|
8
|
-
if (identificator === undefined)
|
|
9
|
-
throw new TypeError("Identificator undefined");
|
|
10
8
|
return new IdentifierClause(identificator);
|
|
11
9
|
}
|
|
12
10
|
mapIntoQuery(params) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insert.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/insert.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE/D,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE;IADzB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"insert.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/insert.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE/D,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE;IADzB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE;IAI5D,YAAY,CAAC,MAAM,EAAE,oBAAoB;CA0BrD"}
|
|
@@ -5,19 +5,18 @@ export class InsertClause extends Clause {
|
|
|
5
5
|
this.inserts = inserts;
|
|
6
6
|
}
|
|
7
7
|
static create(...objects) {
|
|
8
|
-
if (objects.length === 0) {
|
|
9
|
-
throw new Error('Insert clause has no rows to insert.\n Provide at least one object with data.');
|
|
10
|
-
}
|
|
11
8
|
return new InsertClause(objects);
|
|
12
9
|
}
|
|
13
10
|
mapIntoQuery(params) {
|
|
11
|
+
if (this.inserts.length === 0) {
|
|
12
|
+
params.args.push(undefined);
|
|
13
|
+
params.text += `(undefined) values ($${params.args.length})`;
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
14
16
|
const columns = Object.keys(this.inserts[0]);
|
|
15
17
|
const columnsCount = columns.length;
|
|
16
18
|
params.text += `(${columns.join(', ')}) VALUES `;
|
|
17
19
|
this.inserts.forEach((object, index) => {
|
|
18
|
-
if (Object.keys(object).length !== columnsCount) {
|
|
19
|
-
throw new Error(`all rows must have the same columns`);
|
|
20
|
-
}
|
|
21
20
|
if (index)
|
|
22
21
|
params.text += ', ';
|
|
23
22
|
params.text +=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"literal.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/literal.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAE1C,qBAAa,aAAa,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEnD,QAAQ,CAAC,KAAK,EAAE,CAAC;IADrB,OAAO;IAMP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"literal.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/literal.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAE1C,qBAAa,aAAa,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEnD,QAAQ,CAAC,KAAK,EAAE,CAAC;IADrB,OAAO;IAMP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAIlD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAGrD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/update.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE/D,QAAQ,CAAC,SAAS,EAAE,CAAC;IADzB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IAI7C,YAAY,CAAC,MAAM,EAAE,oBAAoB;
|
|
1
|
+
{"version":3,"file":"update.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/update.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE/D,QAAQ,CAAC,SAAS,EAAE,CAAC;IADzB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IAI7C,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAUrD"}
|
|
@@ -9,8 +9,6 @@ export class UpdateClause extends Clause {
|
|
|
9
9
|
}
|
|
10
10
|
mapIntoQuery(params) {
|
|
11
11
|
const entries = Object.entries(this.updateMap).filter(([_, value]) => value !== undefined);
|
|
12
|
-
if (entries.length === 0)
|
|
13
|
-
throw new Error('Update clause has no data to update. All values are `undefined`');
|
|
14
12
|
entries.forEach(([key, value], index) => {
|
|
15
13
|
if (index)
|
|
16
14
|
params.text += ', ';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"where.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/where.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE9D,OAAO,CAAC,MAAM;IADlB,OAAO;WAIO,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC;IAItD,YAAY,CAAC,MAAM,EAAE,oBAAoB;
|
|
1
|
+
{"version":3,"file":"where.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/where.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE9D,OAAO,CAAC,MAAM;IADlB,OAAO;WAIO,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC;IAItD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAUrD"}
|
|
@@ -9,8 +9,6 @@ export class WhereClause extends Clause {
|
|
|
9
9
|
}
|
|
10
10
|
mapIntoQuery(params) {
|
|
11
11
|
const entries = Object.entries(this._value).filter(([_, value]) => value !== undefined);
|
|
12
|
-
if (entries.length === 0)
|
|
13
|
-
throw new Error('Where clause has no data to update. All values are `undefined`');
|
|
14
12
|
entries.forEach(([key, value], index) => {
|
|
15
13
|
if (index)
|
|
16
14
|
params.text += ' AND ';
|
package/dist/connection.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export declare class Connection {
|
|
|
20
20
|
private _closing;
|
|
21
21
|
private _closed;
|
|
22
22
|
private _reconnecting;
|
|
23
|
+
private _inTransaction;
|
|
23
24
|
private _socket;
|
|
24
25
|
private _parsed;
|
|
25
26
|
private _parsing;
|
|
@@ -29,8 +30,8 @@ export declare class Connection {
|
|
|
29
30
|
private _logError;
|
|
30
31
|
private _logQuery;
|
|
31
32
|
private _logNotice;
|
|
32
|
-
private
|
|
33
|
-
private
|
|
33
|
+
private _registerSсhedule;
|
|
34
|
+
private _sсhedule;
|
|
34
35
|
private _registerQuery;
|
|
35
36
|
private constructor();
|
|
36
37
|
/**
|
package/dist/connection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,uBAAuB,EAAuC,GAAG,EAAiB,MAAM,SAAS,CAAA;AACzI,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAA;AACjD,OAAO,
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,uBAAuB,EAAuC,GAAG,EAAiB,MAAM,SAAS,CAAA;AACzI,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAA;AACjD,OAAO,EAA4E,aAAa,EAAE,MAAM,SAAS,CAAA;AAejH;;;;;;;;;GASG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,MAAM,CAA6B;IAE3C,OAAO,CAAC,QAAQ,CAAsD;IACtE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,aAAa,CAA2C;IAChE,OAAO,CAAC,cAAc,CAAQ;IAE9B,OAAO,CAAC,OAAO,CAAiB;IAEhC,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,QAAQ,CAA6D;IAE7E,OAAO,CAAC,mBAAmB,CAAyD;IACpF,OAAO,CAAC,YAAY,CAAI;IAExB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,cAAc;IA6BtB,OAAO;IAYP;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,uBAAuB;IAkB1C;;;;;;OAMG;IACH,KAAK,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAyBtE,OAAO,CAAC,aAAa;IAwDrB;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAyBzD,OAAO,CAAC,eAAe;IAuDvB;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAuCvE,OAAO,CAAC,cAAc;IAuDtB;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAmB7D,2EAA2E;IAC3E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW;IAKhD,sFAAsF;IACtF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAY/D,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;IAkB/F,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,KAAK,aAAa,GAExB;IAGD,OAAO,CAAC,aAAa;IA2GrB,kDAAkD;IAClD,IAAI,QAAQ,YAEX;IAGD,mDAAmD;IACnD,IAAI,QAAQ,YAEX;IAGD,OAAO,CAAC,iBAAiB;IAczB;;OAEG;IACH,KAAK;CAoBR"}
|