@m2k-5f/pgtx 2.5.0 → 2.5.1
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 +16 -0
- package/dist/connection.d.ts +3 -3
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +6 -6
- package/dist/pool.d.ts +2 -2
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +2 -2
- package/dist/protocol/socket-authorization.d.ts +1 -0
- package/dist/protocol/socket-authorization.d.ts.map +1 -1
- package/dist/protocol/socket-authorization.js +80 -83
- package/dist/transaction.d.ts +2 -2
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +4 -2
- package/package.json +4 -5
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
|
package/dist/connection.d.ts
CHANGED
|
@@ -129,7 +129,7 @@ export declare class Connection {
|
|
|
129
129
|
* })
|
|
130
130
|
* ```
|
|
131
131
|
*/
|
|
132
|
-
begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Future<T,
|
|
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<
|
|
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<
|
|
168
|
+
unlisten(channelName: string, callback: (payload: string) => void): Future<void, PostgresError>;
|
|
169
169
|
/**
|
|
170
170
|
* Executes an SQL query in streaming mode.
|
|
171
171
|
*
|
package/dist/connection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C,OAAO,
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
|
package/dist/connection.js
CHANGED
|
@@ -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,
|
|
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");
|
|
@@ -86,7 +86,7 @@ export class Connection {
|
|
|
86
86
|
static new(params) {
|
|
87
87
|
const writer = ConnectionRequestWriter.new();
|
|
88
88
|
return createAuthorizedSocket(writer, params)
|
|
89
|
-
.andThen(socket =>
|
|
89
|
+
.andThen(socket => Ok(new Connection(socket, writer, params.logLevel || 'error', params)));
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
92
|
* Executes a query using tagged template literals.
|
|
@@ -193,7 +193,7 @@ export class Connection {
|
|
|
193
193
|
}
|
|
194
194
|
const callbackSet = this._listeningCallbacks.get(channelName);
|
|
195
195
|
callbackSet.add(callback);
|
|
196
|
-
return this.query `listen ${sql.ident(channelName)}
|
|
196
|
+
return this.query `listen ${sql.ident(channelName)};`.map(() => { });
|
|
197
197
|
}
|
|
198
198
|
/**
|
|
199
199
|
* Unsubscribes a callback. Sends `UNLISTEN` if no callbacks remain for the channel.
|
|
@@ -209,15 +209,15 @@ export class Connection {
|
|
|
209
209
|
unlisten(channelName, callback) {
|
|
210
210
|
this._checkOpened();
|
|
211
211
|
if (!this._listeningCallbacks.has(channelName)) {
|
|
212
|
-
return
|
|
212
|
+
return Ok();
|
|
213
213
|
}
|
|
214
214
|
const callbackSet = this._listeningCallbacks.get(channelName);
|
|
215
215
|
callbackSet.delete(callback);
|
|
216
216
|
if (callbackSet.size === 0) {
|
|
217
217
|
this._listeningCallbacks.delete(channelName);
|
|
218
|
-
return this.query `unlisten ${sql.ident(channelName)}
|
|
218
|
+
return this.query `unlisten ${sql.ident(channelName)};`.map(() => { });
|
|
219
219
|
}
|
|
220
|
-
return
|
|
220
|
+
return Ok();
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
223
223
|
* 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,
|
|
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,
|
|
127
|
+
begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Future<T, unknown>;
|
|
128
128
|
/**
|
|
129
129
|
* Executes a one-off query using pipeline.
|
|
130
130
|
*
|
package/dist/pool.d.ts.map
CHANGED
|
@@ -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,
|
|
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,
|
|
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
|
|
77
|
+
return Ok(conn);
|
|
78
78
|
}
|
|
79
79
|
this._total--;
|
|
80
80
|
}
|
|
@@ -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;
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
};
|
package/dist/transaction.d.ts
CHANGED
|
@@ -17,11 +17,11 @@ export declare class Transaction {
|
|
|
17
17
|
/**
|
|
18
18
|
* Commits the current transaction.
|
|
19
19
|
*/
|
|
20
|
-
commit(): Future<
|
|
20
|
+
commit(): Future<void, any>;
|
|
21
21
|
/**
|
|
22
22
|
* Rolls back the current transaction.
|
|
23
23
|
*/
|
|
24
|
-
rollback(): Future<
|
|
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
|
|
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"}
|
package/dist/transaction.js
CHANGED
|
@@ -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.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m2k-5f/pgtx",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Blazing-fast PostgreSQL driver with pipeline support.",
|
|
6
6
|
"files": [
|
|
@@ -42,14 +42,13 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@types/node": "^26.
|
|
45
|
+
"@types/node": "^26.2.0",
|
|
46
46
|
"mitata": "^1.0.34",
|
|
47
|
-
"pg": "^8.22.0",
|
|
48
47
|
"postgres": "^3.4.9",
|
|
49
|
-
"tsx": "^4.23.
|
|
48
|
+
"tsx": "^4.23.11",
|
|
50
49
|
"typescript": "^5.9.3"
|
|
51
50
|
},
|
|
52
51
|
"dependencies": {
|
|
53
|
-
"fluent-future": "^1.
|
|
52
|
+
"fluent-future": "^1.4.1"
|
|
54
53
|
}
|
|
55
54
|
}
|