@m2k-5f/pgtx 2.8.0 → 2.8.2

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.
Files changed (46) hide show
  1. package/README.md +107 -47
  2. package/dist/clauses/array.clause.d.ts.map +1 -1
  3. package/dist/clauses/array.clause.js +0 -5
  4. package/dist/clauses/iden.caluse.d.ts.map +1 -1
  5. package/dist/clauses/iden.caluse.js +0 -2
  6. package/dist/clauses/insert.clause.d.ts.map +1 -1
  7. package/dist/clauses/insert.clause.js +5 -6
  8. package/dist/clauses/literal.clause.d.ts.map +1 -1
  9. package/dist/clauses/literal.clause.js +0 -3
  10. package/dist/clauses/update.clause.d.ts.map +1 -1
  11. package/dist/clauses/update.clause.js +0 -2
  12. package/dist/clauses/where.clause.d.ts.map +1 -1
  13. package/dist/clauses/where.clause.js +0 -2
  14. package/dist/connection.d.ts +7 -3
  15. package/dist/connection.d.ts.map +1 -1
  16. package/dist/connection.js +147 -116
  17. package/dist/error.d.ts +1 -0
  18. package/dist/error.d.ts.map +1 -1
  19. package/dist/error.js +40 -9
  20. package/dist/index.d.ts +30 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -1
  23. package/dist/pool.d.ts +2 -0
  24. package/dist/pool.d.ts.map +1 -1
  25. package/dist/pool.js +6 -0
  26. package/dist/protocol/connection-request-writer.d.ts +1 -1
  27. package/dist/protocol/connection-request-writer.d.ts.map +1 -1
  28. package/dist/protocol/connection-request-writer.js +1 -3
  29. package/dist/protocol/connection-response-reader.d.ts +1 -1
  30. package/dist/protocol/connection-response-reader.js +1 -1
  31. package/dist/protocol/constants.js +8 -8
  32. package/dist/protocol/types.d.ts +3 -1
  33. package/dist/protocol/types.d.ts.map +1 -1
  34. package/dist/protocol/types.js +91 -1
  35. package/dist/query.d.ts +9 -11
  36. package/dist/query.d.ts.map +1 -1
  37. package/dist/query.js +8 -10
  38. package/dist/transaction.d.ts +10 -2
  39. package/dist/transaction.d.ts.map +1 -1
  40. package/dist/transaction.js +78 -23
  41. package/dist/types.d.ts +2 -2
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/utils.d.ts +0 -2
  44. package/dist/utils.d.ts.map +1 -1
  45. package/dist/utils.js +0 -46
  46. package/package.json +1 -1
package/README.md CHANGED
@@ -6,7 +6,9 @@
6
6
  A PostgreSQL driver for Node.js with an API that doesn't require a manual to use. 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>([{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }])}
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 | **21,093 req/s** | 8,967 req/s | 10,170 req/s |
48
- | 200 | **22,731 req/s** | 9,861 req/s | 11,725 req/s |
49
- | 500 | **22,673 req/s** | 8,289 req/s | 11,005 req/s |
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,83 @@ 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
- ### Error handling
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
- Queries in the same pipeline are isolated from each other. Each query gets its own `Sync`, so an error in one query does not affect other queries that were sent in the same batch.
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 [a, b] = await Promise.allSettled([
67
- pool.execute`UPDATE accounts SET balance = balance + 100 WHERE id = ${1}`,
68
- pool.execute`INSERT INTO accounts (id) VALUES (${1})` // duplicate key, fails
69
- ])
70
-
71
- // a: fulfilled the balance update is committed
72
- // b: rejected the duplicate key error only affects this query
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
- Errors can be matched and recovered directly on the `Future`:
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
- const users = await pool.query<User>`
79
- SELECT * FROM users WHERE id = ${1}
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
- This isolation is per statement, not atomicity across multiple statements. If several queries must succeed or fail together, use `begin()` and `savepoint()`.
87
-
88
-
89
- ### PostgreSQL Type Support
90
-
91
- The driver provides **100% support for PostgreSQL data types using the full binary protocol**. All supported types are encoded and decoded directly in PostgreSQL's binary wire format, without falling back to text-based parsing.
92
-
93
- For a complete list of supported PostgreSQL types, their JavaScript input/output types, and string formats, see the [PostgreSQL Data Types](./DATATYPES.md) reference.
122
+ ---
94
123
 
124
+ ### Pipelining, by default
95
125
 
96
- ### Transactions and savepoints
126
+ Queries started in the same tick are folded into one pipelined write automatically — no batching API, no config flag:
97
127
 
98
128
  ```typescript
99
- await pool.begin(async tx => {
100
- await tx.execute`INSERT INTO orders (user_id) VALUES (${userId})`
129
+ const users = pool.query<User>`SELECT * FROM users`
130
+ const posts = pool.query<Post>`SELECT * FROM posts`
101
131
 
102
- await tx.savepoint('reserve_stock', async stx => {
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
- })
132
+ const [usersResult, postsResult] = await Promise.all([users, posts])
107
133
  ```
108
134
 
135
+ 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
136
 
110
- ### Pipelining is automatic, not opt-in
111
-
112
- `Bind`/`.bind` from [fluent-future](https://www.npmjs.com/package/fluent-future) group independent queries into the same pipeline batch for you:
137
+ `fluent-future`'s `Bind` gives the same parallelism a shape suited to independent, differently-typed queries:
113
138
 
114
139
  ```typescript
115
140
  // 5 queries, 2 round-trips
@@ -123,7 +148,35 @@ const { user, posts, ...data } = await Bind({
123
148
  })
124
149
  ```
125
150
 
126
- Anything you fire off in the same tick without awaiting in between ends up on the wire together.
151
+ `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.
152
+
153
+ 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.
154
+
155
+
156
+ ## Exstra bits
157
+
158
+ ### Transactions and savepoints
159
+
160
+ Transactions are explicit and composable:
161
+
162
+ ```typescript
163
+ await pool.begin(async tx => {
164
+ await tx.query`UPDATE accounts SET balance = balance - ${amount}`
165
+ await tx.query`UPDATE accounts SET balance = balance + ${amount}`
166
+ })
167
+ ```
168
+
169
+ Use savepoints when only part of a transaction should be rolled back:
170
+
171
+ ```typescript
172
+ await tx.savepoint(async sp => {
173
+ await sp.query`INSERT INTO audit_log ${event}`
174
+ })
175
+ ```
176
+
177
+ For a complete list of supported PostgreSQL types, their JavaScript input/output types, and string formats, see the [PostgreSQL Data Types](./DATATYPES.md) reference.
178
+
179
+ ---
127
180
 
128
181
  ### Streaming that doesn't buffer
129
182
 
@@ -135,7 +188,6 @@ for await (const log of pool.stream<Log>`SELECT * FROM application_logs WHERE le
135
188
  }
136
189
  ```
137
190
 
138
-
139
191
  It's a real Web Streams object, so it drops straight into an HTTP response body:
140
192
 
141
193
  ```typescript
@@ -145,6 +197,7 @@ fetch(req) {
145
197
  }
146
198
  ```
147
199
 
200
+ ---
148
201
 
149
202
  ### LISTEN / NOTIFY without babysitting a connection
150
203
 
@@ -161,11 +214,13 @@ await unlisten() // sends UNLISTEN, hands the connection back
161
214
 
162
215
  `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
216
 
217
+ ---
218
+
164
219
  ### Building queries without string-gluing
165
220
 
166
221
  ```typescript
167
222
  // bulk insert — columns inferred from the object
168
- await pool.execute`INSERT INTO users ${sql.insert(users)}`
223
+ await pool.execute`INSERT INTO users ${sql.insert(...users)}`
169
224
 
170
225
  // dynamic SET clause
171
226
  await pool.execute`UPDATE users SET ${sql.update({ status: 'active', last_login: new Date() })} WHERE id = ${userId}`
@@ -187,7 +242,7 @@ await pool.query`SELECT * FROM posts ${search ? sql.fragment`WHERE title ILIKE $
187
242
 
188
243
  `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
244
 
190
- ## Not doing this
245
+ #### Not doing this
191
246
 
192
247
  ```typescript
193
248
  // don't
@@ -230,7 +285,7 @@ interface ConnectionPartialConfig {
230
285
  logLevel?: 'error' | 'notice' | 'query' | "none" // default 'error'
231
286
  int8toBigint?: boolean // default false
232
287
  queryTimeout?: number // default 30000 (ms)
233
- syncShedule?: 'beforeMicrotask' | 'afterMicrotask' | 'Immediate' // default 'Immediate'
288
+ syncSсhedule?: 'beforeMicrotask' | 'afterMicrotask' | 'Immediate' // default 'Immediate'
234
289
  ssl?: 'disable' | 'prefer' | 'require' // defaut 'prefer'
235
290
  caPath?: string // forces `ssl` to 'require' if provided
236
291
  }
@@ -255,6 +310,8 @@ class Pool {
255
310
 
256
311
  get size(): number
257
312
  get total(): number
313
+ get isOpened(): boolean
314
+ get isClosed(): boolean
258
315
  }
259
316
 
260
317
  interface PoolPartialConfig extends ConnectionPartialConfig {
@@ -267,6 +324,9 @@ interface PoolPartialConfig extends ConnectionPartialConfig {
267
324
  ```typescript
268
325
  class Transaction {
269
326
  query<T>(strings: TemplateStringsArray, ...values: any[]): Future<T[], PostgresError>
327
+ execute(templates: TemplateStringsArray, ...params: any[]): Future<void, PostgresError>
328
+ stream<T extends Row>(templates: TemplateStringsArray, ...params: any[]): ReadableStream<T>
329
+
270
330
  commit(): Future<void, PostgresError>
271
331
  rollback(): Future<void, PostgresError>
272
332
  savepoint<T>(name: string, callback: (tx: Transaction) => Promise<T>): Future<T, unknown>
@@ -303,4 +363,4 @@ MIT © [M2K-5F](https://github.com/M2K-5F)
303
363
 
304
364
  **Made with ❤️ and a bit of insanity**
305
365
 
306
- *Manufactured under license by the **Blazing Corporation**. Side effects may include throughput.*
366
+ *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;IAQzD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAiBrD"}
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;IAMvC,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAGrD"}
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;IAO5D,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAwBrD"}
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;IAQlD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAGrD"}
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"}
@@ -5,9 +5,6 @@ export class LiteralClause extends Clause {
5
5
  this.value = value;
6
6
  }
7
7
  static create(value) {
8
- if (value === undefined) {
9
- throw new TypeError(`Literal undefined`);
10
- }
11
8
  return new LiteralClause(value);
12
9
  }
13
10
  mapIntoQuery(params) {
@@ -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;CAarD"}
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;CAYrD"}
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 ';
@@ -17,18 +17,21 @@ export declare class Connection {
17
17
  private _writer;
18
18
  private _sheduled;
19
19
  private _queue;
20
- private _executingCounter;
21
20
  private _closing;
22
21
  private _closed;
23
22
  private _reconnecting;
23
+ private _inTransaction;
24
24
  private _socket;
25
25
  private _parsed;
26
26
  private _parsing;
27
27
  private _listeningCallbacks;
28
28
  private _stmtCounter;
29
29
  private _nextStatement;
30
- private _registerShedule;
31
- private _shedule;
30
+ private _logError;
31
+ private _logQuery;
32
+ private _logNotice;
33
+ private _registerSсhedule;
34
+ private _sсhedule;
32
35
  private _registerQuery;
33
36
  private constructor();
34
37
  /**
@@ -86,6 +89,7 @@ export declare class Connection {
86
89
  get isOpened(): boolean;
87
90
  /** Whether the connection is closed or closing. */
88
91
  get isClosed(): boolean;
92
+ private _tryFinishClosing;
89
93
  /**
90
94
  * Closes the connection, awaiting for all pending queries. Not usable afterward.
91
95
  */
@@ -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,EAAkD,aAAa,EAAE,MAAM,SAAS,CAAA;AAevF;;;;;;;;;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;IAC3C,OAAO,CAAC,iBAAiB,CAAI;IAE7B,OAAO,CAAC,QAAQ,CAAsD;IACtE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,aAAa,CAA2C;IAEhE,OAAO,CAAC,OAAO,CAAiB;IAEhC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,QAAQ,CAA8D;IAE9E,OAAO,CAAC,mBAAmB,CAAyD;IACpF,OAAO,CAAC,YAAY,CAAI;IAExB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,QAAQ;IAShB,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;IAatE,OAAO,CAAC,aAAa;IA+DrB;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAazD,OAAO,CAAC,eAAe;IA+DvB;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IA2BvE,OAAO,CAAC,cAAc;IAkEtB;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAoB7D,2EAA2E;IAC3E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW;IAOhD,sFAAsF;IACtF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAe/D,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;IAoB/F,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,KAAK,aAAa,GAExB;IAGD,OAAO,CAAC,aAAa;IA6HrB,kDAAkD;IAClD,IAAI,QAAQ,YAEX;IAGD,mDAAmD;IACnD,IAAI,QAAQ,YAEX;IAGD;;OAEG;IACH,KAAK;CAwBR"}
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;AAgBjH;;;;;;;;;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"}