@m2k-5f/pgtx 2.5.0 → 2.5.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.
package/README.md CHANGED
@@ -179,6 +179,9 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
179
179
  > 🚀 Pgtx automatically groups concurrent queries into pipeline batches, reducing network overhead by up to 5x compared to sequential queries.
180
180
 
181
181
 
182
+ ---
183
+
184
+
182
185
  ### High-Performance Data Streaming (`pool.stream`)
183
186
 
184
187
  For heavy database lookups (exporting millions of rows, bulk reports, or large analytical dumps), memory accumulation is the ultimate killer of backend stability. Storing rows in a standard JavaScript array causes massive heap pollution and triggers blocking Garbage Collection spikes.
@@ -232,6 +235,7 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
232
235
  };
233
236
  ```
234
237
 
238
+ ---
235
239
 
236
240
  ### Transactions & Savepoints
237
241
 
@@ -247,6 +251,7 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
247
251
  })
248
252
  ```
249
253
 
254
+ ---
250
255
 
251
256
  ### Async Notifications (LISTEN / NOTIFY)
252
257
 
@@ -300,6 +305,7 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
300
305
 
301
306
  > ⚠️ **Architecture Note:** While `pool.notify` is a fire-and-forget atomic command, subscription states (`LISTEN`/`UNLISTEN`) are strictly tied to specific PostgreSQL backend processes. Using the high-level `pool.listen()` is strongly recommended for application code, as it encapsulates socket management into an elegant, leak-proof callback boundary.
302
307
 
308
+ ---
303
309
 
304
310
  ### Bulk Inserts
305
311
 
@@ -315,6 +321,8 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
315
321
  // INSERT INTO users (name, email) VALUES ($1, $2), ($3, $4)
316
322
  ```
317
323
 
324
+ ---
325
+
318
326
  ### Dynamic Updates
319
327
 
320
328
  ```typescript
@@ -326,6 +334,8 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
326
334
  // UPDATE users SET status = $1, last_login = $2 WHERE id = $3
327
335
  ```
328
336
 
337
+ ---
338
+
329
339
  ### Recursive Fragments
330
340
 
331
341
  ```typescript
@@ -338,6 +348,8 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
338
348
  `
339
349
  ```
340
350
 
351
+ ---
352
+
341
353
  ### Smart Lists
342
354
 
343
355
  ```typescript
@@ -356,6 +368,8 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
356
368
  `
357
369
  ```
358
370
 
371
+ ---
372
+
359
373
  ### Clean WHERE Clauses
360
374
 
361
375
  ```typescript
@@ -366,6 +380,8 @@ In the `mitata` benchmark, Pgtx also demonstrated approximately **3× lower memo
366
380
  // SELECT * FROM users WHERE role = $1 AND active = $2
367
381
  ```
368
382
 
383
+ ---
384
+
369
385
  ### Conditional Logic
370
386
 
371
387
  ```typescript
@@ -129,7 +129,7 @@ export declare class Connection {
129
129
  * })
130
130
  * ```
131
131
  */
132
- begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Future<T, Error>;
132
+ begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Future<T, unknown>;
133
133
  /**
134
134
  * Sends an asynchronous notification to a channel via `pg_notify`.
135
135
  *
@@ -153,7 +153,7 @@ export declare class Connection {
153
153
  * await conn.listen('events', data => console.log(data))
154
154
  * ```
155
155
  */
156
- listen(channelName: string, callback: (payload: string) => void): Future<Record<string, any>[], PostgresError>;
156
+ listen(channelName: string, callback: (payload: string) => void): Future<void, PostgresError>;
157
157
  /**
158
158
  * Unsubscribes a callback. Sends `UNLISTEN` if no callbacks remain for the channel.
159
159
  *
@@ -165,7 +165,7 @@ export declare class Connection {
165
165
  * await conn.unlisten('events', callback)
166
166
  * ```
167
167
  */
168
- unlisten(channelName: string, callback: (payload: string) => void): Future<[], PostgresError>;
168
+ unlisten(channelName: string, callback: (payload: string) => void): Future<void, PostgresError>;
169
169
  /**
170
170
  * Executes an SQL query in streaming mode.
171
171
  *
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ import { SocketConnector } from "./protocol/socket-connector";
7
7
  import { Queue } from "./queue";
8
8
  import { Query, QueryState, StreamQuery } from "./query";
9
9
  import { sql } from ".";
10
- import { Begin, Future, Resolve } from 'fluent-future';
10
+ import { Begin, Future, Ok } from 'fluent-future';
11
11
  import { PostgresError } from "./error";
12
12
  const ErrConnectionClosed = new PostgresError("Connection is closed", 'connection_closed', "", "ERROR");
13
13
  const ErrConnectionReconnecring = new PostgresError("Connection are reconnecting", "connection_reconnecting", "", "ERROR");
@@ -62,7 +62,10 @@ export class Connection {
62
62
  this._stmtCounter = 0;
63
63
  this.params = params;
64
64
  this._logLevel = logLevel;
65
- this._socket = new SocketConnector(socket, (type, _, reader) => this._handlePacket(type, reader), (err) => this._registerReconnect());
65
+ this._socket = new SocketConnector(socket, (type, _, reader) => this._handlePacket(type, reader), (err) => {
66
+ // console.log(err)
67
+ this._registerReconnect();
68
+ });
66
69
  this._writer = writer;
67
70
  }
68
71
  /**
@@ -86,7 +89,7 @@ export class Connection {
86
89
  static new(params) {
87
90
  const writer = ConnectionRequestWriter.new();
88
91
  return createAuthorizedSocket(writer, params)
89
- .andThen(socket => Resolve(new Connection(socket, writer, params.logLevel || 'error', params)));
92
+ .andThen(socket => Ok(new Connection(socket, writer, params.logLevel || 'error', params)));
90
93
  }
91
94
  /**
92
95
  * Executes a query using tagged template literals.
@@ -193,7 +196,7 @@ export class Connection {
193
196
  }
194
197
  const callbackSet = this._listeningCallbacks.get(channelName);
195
198
  callbackSet.add(callback);
196
- return this.query `listen ${sql.ident(channelName)};`;
199
+ return this.query `listen ${sql.ident(channelName)};`.map(() => { });
197
200
  }
198
201
  /**
199
202
  * Unsubscribes a callback. Sends `UNLISTEN` if no callbacks remain for the channel.
@@ -209,15 +212,15 @@ export class Connection {
209
212
  unlisten(channelName, callback) {
210
213
  this._checkOpened();
211
214
  if (!this._listeningCallbacks.has(channelName)) {
212
- return Resolve([]);
215
+ return Ok();
213
216
  }
214
217
  const callbackSet = this._listeningCallbacks.get(channelName);
215
218
  callbackSet.delete(callback);
216
219
  if (callbackSet.size === 0) {
217
220
  this._listeningCallbacks.delete(channelName);
218
- return this.query `unlisten ${sql.ident(channelName)};`;
221
+ return this.query `unlisten ${sql.ident(channelName)};`.map(() => { });
219
222
  }
220
- return Resolve([]);
223
+ return Ok();
221
224
  }
222
225
  /**
223
226
  * Executes an SQL query in streaming mode.
package/dist/pool.d.ts CHANGED
@@ -86,7 +86,7 @@ export declare class Pool {
86
86
  * return await conn.query`SELECT pg_is_in_recovery()`;
87
87
  * });
88
88
  */
89
- withAcquire<T>(fn: (conn: Connection) => Promise<T>): Future<T, Error>;
89
+ withAcquire<T>(fn: (conn: Connection) => Promise<T>): Future<T, unknown>;
90
90
  /**
91
91
  * Releases the connection back to the pool.
92
92
  *
@@ -124,7 +124,7 @@ export declare class Pool {
124
124
  * })
125
125
  * ```
126
126
  */
127
- begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Future<T, Error>;
127
+ begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Future<T, unknown>;
128
128
  /**
129
129
  * Executes a one-off query using pipeline.
130
130
  *
@@ -1 +1 @@
1
- {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAG3C,OAAO,EAAS,MAAM,EAAW,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,IAAI;IACb,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,YAAY;gBAIR,MAAM,EAAE,UAAU;IAM9B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO;IA2BP;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC;IAUnD;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU;IAiBxB;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAY7D;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;IAuBpF;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC;IAoCzG;;;;;;;;;;OAUG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GACuB,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC;IAIhG;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAY3D;;OAEG;IACH,IAAI,IAAI,WAEP;IAGD;;;OAGG;IACH,IAAI,KAAK,WAER;IAGD;;;;;;;;;;OAUG;IACH,KAAK;CAWR"}
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAG3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,IAAI;IACb,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,YAAY;gBAIR,MAAM,EAAE,UAAU;IAM9B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO;IA2BP;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC;IAUnD;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU;IAiBxB;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAY7D;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;IAuBpF;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC;IAoCzG;;;;;;;;;;OAUG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GACuB,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC;IAIhG;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAY3D;;OAEG;IACH,IAAI,IAAI,WAEP;IAGD;;;OAGG;IACH,IAAI,KAAK,WAER;IAGD;;;;;;;;;;OAUG;IACH,KAAK;CAWR"}
package/dist/pool.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Connection } from "./connection";
2
2
  import { Queue } from "./queue";
3
- import { Begin, Future, Resolve } from "fluent-future";
3
+ import { Begin, Future, Ok } from "fluent-future";
4
4
  import { PostgresError } from "./error";
5
5
  const ErrPoolClosed = new PostgresError('Pool closed');
6
6
  /**
@@ -74,7 +74,7 @@ export class Pool {
74
74
  while (this._available.hasMore) {
75
75
  const conn = this._available.shift;
76
76
  if (conn.isOpened) {
77
- return Resolve(conn);
77
+ return Ok(conn);
78
78
  }
79
79
  this._total--;
80
80
  }
@@ -6,7 +6,7 @@ export class ConnectionRequestBuffer {
6
6
  this.lastRequestLenByteOffset = lastRequestLenByteOffset;
7
7
  }
8
8
  static new(capacity) {
9
- return new ConnectionRequestBuffer(Buffer.alloc(capacity));
9
+ return new ConnectionRequestBuffer(Buffer.allocUnsafe(capacity));
10
10
  }
11
11
  ensureCapacity(needed) {
12
12
  const required = needed + this.offset;
@@ -12,7 +12,6 @@ export declare class ConnectionResponseBuffer {
12
12
  readInt16(): number;
13
13
  readCString(): string;
14
14
  readRawString(length: number): string;
15
- readBytes(length: number): Buffer;
16
15
  hasMore(): boolean;
17
16
  readRawBinaryString(length: number): string;
18
17
  readBinaryDate(): Date;
@@ -24,7 +23,10 @@ export declare class ConnectionResponseBuffer {
24
23
  readBool(): boolean;
25
24
  readBigInt64(): bigint;
26
25
  readInt64(): number;
26
+ readFloat32(): number;
27
27
  readFloat64(): number;
28
+ readUuid(): string;
29
+ readBytes(length: number): Buffer<ArrayBuffer>;
28
30
  getBufferHash(length: number): number;
29
31
  }
30
32
  export declare class ConnectionResponseReader {
@@ -37,7 +39,7 @@ export declare class ConnectionResponseReader {
37
39
  length: number;
38
40
  };
39
41
  readAuthentication(): AuthenticationCode;
40
- readMD5Salt(): Buffer<ArrayBufferLike>;
42
+ readMD5Salt(): Buffer<ArrayBuffer>;
41
43
  readParameterStatus(): {
42
44
  name: string;
43
45
  value: string;
@@ -1 +1 @@
1
- {"version":3,"file":"connection-response-reader.d.ts","sourceRoot":"","sources":["../../src/protocol/connection-response-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA6B,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC5G,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAM3C,qBAAa,wBAAwB;IAI7B,OAAO,CAAC,MAAM;IAHlB,OAAO,CAAC,KAAK,CAAI;IAEjB,OAAO;IAKP,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM;IAK1B,QAAQ,IAAI,MAAM;IAOlB,SAAS,IAAI,MAAM;IAOnB,SAAS,IAAI,MAAM;IAOnB,WAAW,IAAI,MAAM;IAQrB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOrC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOjC,OAAO,IAAI,OAAO;IAKlB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAO3C,cAAc,IAAI,IAAI;IAOtB,mBAAmB,IAAI,IAAI;IAO3B,cAAc,IAAI,MAAM;IAaxB,SAAS,CAAC,SAAS,EAAE,MAAM;IAK3B,aAAa,IAAI,OAAO;IAaxB,iBAAiB;IAIjB,QAAQ;IAMR,YAAY,IAAI,MAAM;IAOtB,SAAS;IAST,WAAW,IAAI,MAAM;IAMrB,aAAa,CAAC,MAAM,EAAE,MAAM;CAW/B;AAGD,qBAAa,wBAAwB;IAI7B,OAAO,CAAC,MAAM;IAHlB,OAAO,CAAC,mBAAmB,CAAK;IAEhC,OAAO;IAKP,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM;IAK1B,QAAQ;cACoC,YAAY;;;IAIxD,kBAAkB,IACoB,kBAAkB;IAIxD,WAAW;IAKX,mBAAmB;;;;IAQnB,kBAAkB;;;;IAQlB,iBAAiB,IAAI,aAAa;IA4ClC,iBAAiB,IACoB,iBAAiB;IAItD,kBAAkB,IAAI,MAAM,EAAE;IAa9B,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAKvC,kBAAkB;IAsBlB,WAAW,CAAC,YAAY,EAAE,iBAAiB,EAAE,EAAE,YAAY,GAAE,OAAe,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IA6FlG,wBAAwB;;;;IASxB,mBAAmB,IAAI,MAAM;IAK7B,OAAO;IAKP,aAAa;IAKb,iBAAiB;IAKjB,iBAAiB;IAGjB,gBAAgB;IAGhB,wBAAwB;IAOxB,UAAU;CACb"}
1
+ {"version":3,"file":"connection-response-reader.d.ts","sourceRoot":"","sources":["../../src/protocol/connection-response-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA6B,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC5G,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAM3C,qBAAa,wBAAwB;IAI7B,OAAO,CAAC,MAAM;IAHlB,OAAO,CAAC,KAAK,CAAI;IAEjB,OAAO;IAKP,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM;IAK1B,QAAQ,IAAI,MAAM;IAOlB,SAAS,IAAI,MAAM;IAOnB,SAAS,IAAI,MAAM;IAOnB,WAAW,IAAI,MAAM;IAQrB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOrC,OAAO,IAAI,OAAO;IAKlB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAO3C,cAAc,IAAI,IAAI;IAOtB,mBAAmB,IAAI,IAAI;IAO3B,cAAc,IAAI,MAAM;IAaxB,SAAS,CAAC,SAAS,EAAE,MAAM;IAK3B,aAAa,IAAI,OAAO;IAaxB,iBAAiB;IAIjB,QAAQ;IAMR,YAAY,IAAI,MAAM;IAOtB,SAAS;IAST,WAAW;IAOX,WAAW,IAAI,MAAM;IAMrB,QAAQ;IAWR,SAAS,CAAC,MAAM,EAAE,MAAM;IAQxB,aAAa,CAAC,MAAM,EAAE,MAAM;CAW/B;AAGD,qBAAa,wBAAwB;IAI7B,OAAO,CAAC,MAAM;IAHlB,OAAO,CAAC,mBAAmB,CAAK;IAEhC,OAAO;IAKP,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM;IAK1B,QAAQ;cACoC,YAAY;;;IAIxD,kBAAkB,IACoB,kBAAkB;IAIxD,WAAW;IAKX,mBAAmB;;;;IAQnB,kBAAkB;;;;IAQlB,iBAAiB,IAAI,aAAa;IA4ClC,iBAAiB,IACoB,iBAAiB;IAItD,kBAAkB,IAAI,MAAM,EAAE;IAa9B,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAKvC,kBAAkB;IAsBlB,WAAW,CAAC,YAAY,EAAE,iBAAiB,EAAE,EAAE,YAAY,GAAE,OAAe,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IA0GlG,wBAAwB;;;;IASxB,mBAAmB,IAAI,MAAM;IAK7B,OAAO;IAKP,aAAa;IAKb,iBAAiB;IAKjB,iBAAiB;IAGjB,gBAAgB;IAGhB,wBAAwB;IAOxB,UAAU;CACb"}
@@ -36,11 +36,6 @@ export class ConnectionResponseBuffer {
36
36
  this.caret += length;
37
37
  return text;
38
38
  }
39
- readBytes(length) {
40
- const slice = this.buffer.subarray(this.caret, this.caret + length);
41
- this.caret += length;
42
- return slice;
43
- }
44
39
  hasMore() {
45
40
  return this.caret < this.buffer.length;
46
41
  }
@@ -99,11 +94,30 @@ export class ConnectionResponseBuffer {
99
94
  this.caret += 8;
100
95
  return (hi * 4294967296) + lo;
101
96
  }
97
+ readFloat32() {
98
+ const value = this.buffer.readFloatBE(this.caret);
99
+ this.caret += 4;
100
+ return value;
101
+ }
102
102
  readFloat64() {
103
103
  const value = this.buffer.readDoubleBE(this.caret);
104
104
  this.caret += 8;
105
105
  return value;
106
106
  }
107
+ readUuid() {
108
+ const buf = this.readBytes(16);
109
+ return buf.toString('hex', 0, 4) + '-' +
110
+ buf.toString('hex', 4, 6) + '-' +
111
+ buf.toString('hex', 6, 8) + '-' +
112
+ buf.toString('hex', 8, 10) + '-' +
113
+ buf.toString('hex', 10, 16);
114
+ }
115
+ readBytes(length) {
116
+ const result = Buffer.allocUnsafe(length);
117
+ this.buffer.copy(result, 0, this.caret, this.caret + length);
118
+ this.caret += length;
119
+ return result;
120
+ }
107
121
  getBufferHash(length) {
108
122
  let hash = 2166136261;
109
123
  const end = this.caret + length;
@@ -228,19 +242,17 @@ export class ConnectionResponseReader {
228
242
  for (let i = 0; i < fieldsCount; i++) {
229
243
  const fieldLength = this.buffer.readInt32();
230
244
  const desc = descriptions[i];
231
- const key = desc ? desc.name : `col_${i}`;
245
+ const key = desc.name;
232
246
  if (fieldLength === -1) {
233
247
  row[key] = null;
234
248
  continue;
235
249
  }
236
- const oid = desc ? desc.typeOID : 0;
250
+ const oid = desc.typeOID;
237
251
  switch (oid) {
238
- case DataTypeOids.Int4:
239
- row[key] = this.buffer.readInt32();
240
- break;
241
252
  case DataTypeOids.Text:
242
253
  case DataTypeOids.Varchar:
243
254
  case DataTypeOids.Char:
255
+ case DataTypeOids.Bpchar:
244
256
  {
245
257
  if (fieldLength <= 32) {
246
258
  let cacheForColumn = columnValueCache.get(i);
@@ -267,36 +279,72 @@ export class ConnectionResponseReader {
267
279
  }
268
280
  break;
269
281
  case DataTypeOids.Int2:
270
- row[key] = this.buffer.readInt16();
282
+ {
283
+ row[key] = this.buffer.readInt16();
284
+ }
271
285
  break;
272
- case DataTypeOids.Bool:
273
- row[key] = this.buffer.readBool();
286
+ case DataTypeOids.Int4:
287
+ {
288
+ row[key] = this.buffer.readInt32();
289
+ }
274
290
  break;
275
291
  case DataTypeOids.Int8:
276
292
  {
277
293
  row[key] = int8toBigint ? this.buffer.readBigInt64() : this.buffer.readInt64();
278
294
  }
279
295
  break;
296
+ case DataTypeOids.Float4:
297
+ {
298
+ row[key] = this.buffer.readFloat32();
299
+ }
300
+ break;
280
301
  case DataTypeOids.Float8:
281
- row[key] = this.buffer.readFloat64();
302
+ {
303
+ row[key] = this.buffer.readFloat64();
304
+ }
305
+ break;
306
+ case DataTypeOids.Bool:
307
+ {
308
+ row[key] = this.buffer.readBool();
309
+ }
310
+ break;
311
+ case DataTypeOids.Bytea:
312
+ {
313
+ row[key] = this.buffer.readBytes(fieldLength);
314
+ }
282
315
  break;
283
316
  case DataTypeOids.Jsonb:
284
- this.buffer.skipBytes(1);
285
- row[key] = JSON.parse(this.buffer.readRawString(fieldLength - 1));
317
+ {
318
+ this.buffer.skipBytes(1);
319
+ row[key] = JSON.parse(this.buffer.readRawString(fieldLength - 1));
320
+ }
286
321
  break;
287
322
  case DataTypeOids.Json:
288
- row[key] = JSON.parse(this.buffer.readRawString(fieldLength));
323
+ {
324
+ row[key] = JSON.parse(this.buffer.readRawString(fieldLength));
325
+ }
289
326
  break;
290
327
  case DataTypeOids.Date:
291
- row[key] = this.buffer.readBinaryDate();
328
+ {
329
+ row[key] = this.buffer.readBinaryDate();
330
+ }
292
331
  break;
293
332
  case DataTypeOids.Timestamp:
294
333
  case DataTypeOids.Timestamptz:
295
- row[key] = this.buffer.readBinaryTimestamp();
334
+ {
335
+ row[key] = this.buffer.readBinaryTimestamp();
336
+ }
337
+ break;
338
+ case DataTypeOids.Uuid:
339
+ {
340
+ row[key] = this.buffer.readUuid();
341
+ }
296
342
  break;
297
343
  default:
298
- this.buffer.skipBytes(fieldLength);
299
- row[key] = null;
344
+ {
345
+ this.buffer.skipBytes(fieldLength);
346
+ row[key] = null;
347
+ }
300
348
  break;
301
349
  }
302
350
  }
@@ -11,5 +11,6 @@ export type AuthorizationParams = {
11
11
  };
12
12
  export declare const ErrNonceMismatch: PostgresError;
13
13
  export declare const ErrPasswordRequired: PostgresError;
14
+ export declare const ErrSocketFailedDuringAuth: PostgresError;
14
15
  export declare const createAuthorizedSocket: (writer: ConnectionRequestWriter, params: AuthorizationParams) => Future<Socket, PostgresError>;
15
16
  //# sourceMappingURL=socket-authorization.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"socket-authorization.d.ts","sourceRoot":"","sources":["../../src/protocol/socket-authorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,MAAM,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAA;AAKrE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAGtC,MAAM,MAAM,mBAAmB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAGD,eAAO,MAAM,gBAAgB,eAAmF,CAAA;AAChH,eAAO,MAAM,mBAAmB,eAAqE,CAAA;AAIrG,eAAO,MAAM,sBAAsB,GAAI,QAAQ,uBAAuB,EAAE,QAAQ,mBAAmB,kCAyHlG,CAAA"}
1
+ {"version":3,"file":"socket-authorization.d.ts","sourceRoot":"","sources":["../../src/protocol/socket-authorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,MAAM,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAA;AAKrE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAGtC,MAAM,MAAM,mBAAmB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAGD,eAAO,MAAM,gBAAgB,eAAmF,CAAA;AAChH,eAAO,MAAM,mBAAmB,eAAqE,CAAA;AACrG,eAAO,MAAM,yBAAyB,eAAiD,CAAA;AAIvF,eAAO,MAAM,sBAAsB,GAAI,QAAQ,uBAAuB,EAAE,QAAQ,mBAAmB,kCAoHlG,CAAA"}
@@ -7,93 +7,90 @@ import { PostgresError } from "../error";
7
7
  import { Future } from "fluent-future";
8
8
  export const ErrNonceMismatch = new PostgresError("Protocol violation: server nonce doesn't match client nonce");
9
9
  export const ErrPasswordRequired = new PostgresError('The authorization method requires a password.');
10
+ export const ErrSocketFailedDuringAuth = new PostgresError("Socket failed during auth");
10
11
  export const createAuthorizedSocket = (writer, params) => {
11
- return Future.of(new Promise((resolve, reject) => {
12
- const nonce = generateNonce();
13
- let clientMessage = '';
14
- let serverMessage = '';
15
- const socket = createConnection({ host: params.host, port: params.port });
16
- const connector = new SocketConnector(socket, (type, length, reader) => {
17
- writer.clear();
18
- switch (type) {
19
- case ResponseTypes.Authentication: {
20
- switch (reader.readAuthentication()) {
21
- case AuthenticationCodes.Ok: break;
22
- case AuthenticationCodes.CleartextPassword: {
23
- if (!params.password)
24
- throw ErrPasswordRequired;
25
- connector.write(writer.writePassword(params.password));
26
- break;
27
- }
28
- case AuthenticationCodes.MD5Password: {
29
- const salt = reader.readMD5Salt();
30
- if (!params.password)
31
- throw ErrPasswordRequired;
32
- const password = encryptMd5(params.password, params.user, salt);
33
- connector.write(writer.writePassword(password));
34
- break;
35
- }
36
- case AuthenticationCodes.SASL: {
37
- reader.readSaslMechanisms();
38
- if (!params.password)
39
- throw ErrPasswordRequired;
40
- clientMessage = `n=${params.user},r=${nonce}`;
41
- connector.write(writer.writeSaslInitial('SCRAM-SHA-256', `n,,${clientMessage}`));
42
- break;
43
- }
44
- case AuthenticationCodes.SASLContinue: {
45
- serverMessage = reader.readSaslMessage(length);
46
- if (!params.password)
47
- throw ErrPasswordRequired;
48
- const parts = Object.fromEntries(serverMessage.split(',').map(x => x.split('=')));
49
- const serverNonce = parts.r;
50
- const saltBase64 = parts.s;
51
- const iterations = parseInt(parts.i, 10);
52
- if (!serverNonce.startsWith(nonce)) {
53
- connector.destroy();
54
- return reject(ErrNonceMismatch);
55
- }
56
- const clientFinalMessageWithoutProof = `c=biws,r=${serverNonce}`;
57
- const authMessage = `${clientMessage},${serverMessage},${clientFinalMessageWithoutProof}`;
58
- const { clientProof } = calculateScramAuth(params.password, saltBase64, iterations, authMessage);
59
- const clientFinalMessage = `${clientFinalMessageWithoutProof},p=${clientProof}`;
60
- connector.write(writer.writeSaslResponse(clientFinalMessage));
61
- break;
62
- }
63
- case AuthenticationCodes.SASLFinal: {
64
- reader.readSaslMessage(length);
65
- break;
12
+ const { future, reject, resolve } = Future.withResolvers();
13
+ const nonce = generateNonce();
14
+ let clientMessage = '';
15
+ let serverMessage = '';
16
+ const socket = createConnection({ host: params.host, port: params.port });
17
+ const connector = new SocketConnector(socket, (type, length, reader) => {
18
+ writer.clear();
19
+ switch (type) {
20
+ case ResponseTypes.Authentication: {
21
+ switch (reader.readAuthentication()) {
22
+ case AuthenticationCodes.Ok: break;
23
+ case AuthenticationCodes.CleartextPassword: {
24
+ if (!params.password)
25
+ throw ErrPasswordRequired;
26
+ connector.write(writer.writePassword(params.password));
27
+ break;
28
+ }
29
+ case AuthenticationCodes.MD5Password: {
30
+ const salt = reader.readMD5Salt();
31
+ if (!params.password)
32
+ throw ErrPasswordRequired;
33
+ const password = encryptMd5(params.password, params.user, salt);
34
+ connector.write(writer.writePassword(password));
35
+ break;
36
+ }
37
+ case AuthenticationCodes.SASL: {
38
+ reader.readSaslMechanisms();
39
+ if (!params.password)
40
+ throw ErrPasswordRequired;
41
+ clientMessage = `n=${params.user},r=${nonce}`;
42
+ connector.write(writer.writeSaslInitial('SCRAM-SHA-256', `n,,${clientMessage}`));
43
+ break;
44
+ }
45
+ case AuthenticationCodes.SASLContinue: {
46
+ serverMessage = reader.readSaslMessage(length);
47
+ if (!params.password)
48
+ throw ErrPasswordRequired;
49
+ const parts = Object.fromEntries(serverMessage.split(',').map(x => x.split('=')));
50
+ const serverNonce = parts.r;
51
+ const saltBase64 = parts.s;
52
+ const iterations = parseInt(parts.i, 10);
53
+ if (!serverNonce.startsWith(nonce)) {
54
+ connector.destroy();
55
+ return reject(ErrNonceMismatch);
66
56
  }
57
+ const clientFinalMessageWithoutProof = `c=biws,r=${serverNonce}`;
58
+ const authMessage = `${clientMessage},${serverMessage},${clientFinalMessageWithoutProof}`;
59
+ const { clientProof } = calculateScramAuth(params.password, saltBase64, iterations, authMessage);
60
+ const clientFinalMessage = `${clientFinalMessageWithoutProof},p=${clientProof}`;
61
+ connector.write(writer.writeSaslResponse(clientFinalMessage));
62
+ break;
63
+ }
64
+ case AuthenticationCodes.SASLFinal: {
65
+ reader.readSaslMessage(length);
66
+ break;
67
67
  }
68
- break;
69
- }
70
- case ResponseTypes.ParamaterStatus: {
71
- reader.readParameterStatus();
72
- break;
73
- }
74
- case ResponseTypes.ErrorResponse: {
75
- const error = reader.readErrorResponse();
76
- connector.destroy();
77
- reject(error);
78
- return;
79
- }
80
- case ResponseTypes.BackendKeyData: {
81
- reader.readBackendKeyData();
82
- }
83
- case ResponseTypes.ReadyForQuery: {
84
- reader.readReadyForQuery();
85
- resolve(connector.unwrapSocket());
86
- return;
87
68
  }
69
+ break;
88
70
  }
89
- }, error => {
90
- reject(error);
91
- });
92
- connector.write(writer.writeStartup(params.user, params.database));
93
- writer.clear();
94
- }), error => {
95
- if (error instanceof PostgresError)
96
- return error;
97
- return new PostgresError(error.message);
71
+ case ResponseTypes.ParamaterStatus: {
72
+ reader.readParameterStatus();
73
+ break;
74
+ }
75
+ case ResponseTypes.ErrorResponse: {
76
+ const error = reader.readErrorResponse();
77
+ connector.destroy();
78
+ reject(error);
79
+ return;
80
+ }
81
+ case ResponseTypes.BackendKeyData: {
82
+ reader.readBackendKeyData();
83
+ }
84
+ case ResponseTypes.ReadyForQuery: {
85
+ reader.readReadyForQuery();
86
+ resolve(connector.unwrapSocket());
87
+ return;
88
+ }
89
+ }
90
+ }, error => {
91
+ reject(ErrSocketFailedDuringAuth);
98
92
  });
93
+ connector.write(writer.writeStartup(params.user, params.database));
94
+ writer.clear();
95
+ return future;
99
96
  };
@@ -17,11 +17,11 @@ export declare class Transaction {
17
17
  /**
18
18
  * Commits the current transaction.
19
19
  */
20
- commit(): Future<[], PostgresError>;
20
+ commit(): Future<void, any>;
21
21
  /**
22
22
  * Rolls back the current transaction.
23
23
  */
24
- rollback(): Future<[], PostgresError>;
24
+ rollback(): Future<void, any>;
25
25
  /**
26
26
  * Executes a query within the current transaction.
27
27
  */
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,eAAe,CAAA;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAEvC;;;GAGG;AACH,qBAAa,WAAW;IAIhB,QAAQ,CAAC,IAAI,EAAE,UAAU;IAH7B,OAAO,CAAC,UAAU,CAAiB;gBAGtB,IAAI,EAAE,UAAU;IAG7B;;OAEG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACI,MAAM,IAIiC,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC;IAGvE;;OAEG;IACI,QAAQ,IAI+B,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC;IAGvE;;OAEG;IACI,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAK3F;;;;;;;;;OASG;IACI,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC;CAWjG"}
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,eAAe,CAAA;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAEvC;;;GAGG;AACH,qBAAa,WAAW;IAIhB,QAAQ,CAAC,IAAI,EAAE,UAAU;IAH7B,OAAO,CAAC,UAAU,CAAiB;gBAGtB,IAAI,EAAE,UAAU;IAG7B;;OAEG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACI,MAAM;IAQb;;OAEG;IACI,QAAQ;IAQf;;OAEG;IACI,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAK3F;;;;;;;;;OASG;IACI,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC;CAWjG"}
@@ -26,7 +26,8 @@ export class Transaction {
26
26
  commit() {
27
27
  this.checkActive();
28
28
  return this.conn.query `COMMIT`
29
- .tap(() => this.isFinished = true);
29
+ .tap(() => { this.isFinished = true; })
30
+ .map(() => { });
30
31
  }
31
32
  /**
32
33
  * Rolls back the current transaction.
@@ -34,7 +35,8 @@ export class Transaction {
34
35
  rollback() {
35
36
  this.checkActive();
36
37
  return this.conn.query `ROLLBACK`
37
- .tap(() => this.isFinished = true);
38
+ .tap(() => { this.isFinished = true; })
39
+ .map(() => { });
38
40
  }
39
41
  /**
40
42
  * Executes a query within the current transaction.
@@ -32,6 +32,9 @@ const prepareValue = (value) => {
32
32
  if (value instanceof Date) {
33
33
  return value.toISOString();
34
34
  }
35
+ if (Buffer.isBuffer(value) || value instanceof Uint8Array) {
36
+ return '\\x' + Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString('hex');
37
+ }
35
38
  if (Array.isArray(value)) {
36
39
  const elements = value.map(el => {
37
40
  if (el === null || el === undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m2k-5f/pgtx",
3
- "version": "2.5.0",
3
+ "version": "2.5.2",
4
4
  "type": "module",
5
5
  "description": "Blazing-fast PostgreSQL driver with pipeline support.",
6
6
  "files": [
@@ -42,14 +42,14 @@
42
42
  }
43
43
  },
44
44
  "devDependencies": {
45
- "@types/node": "^26.1.2",
45
+ "@types/node": "^26.2.0",
46
46
  "mitata": "^1.0.34",
47
- "pg": "^8.22.0",
47
+ "pg": "^8.23.0",
48
48
  "postgres": "^3.4.9",
49
- "tsx": "^4.23.5",
49
+ "tsx": "^4.23.11",
50
50
  "typescript": "^5.9.3"
51
51
  },
52
52
  "dependencies": {
53
- "fluent-future": "^1.3.3"
53
+ "fluent-future": "^1.4.1"
54
54
  }
55
55
  }