@m2k-5f/pgtx 2.6.0 → 2.6.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 +214 -480
- package/dist/batch.d.ts +3 -2
- package/dist/batch.d.ts.map +1 -1
- package/dist/batch.js +9 -9
- package/dist/clauses/abstract.clause.d.ts.map +1 -1
- package/dist/connection.d.ts +42 -175
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +205 -290
- package/dist/error.d.ts +5 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/pool.d.ts +35 -192
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +70 -202
- package/dist/protocol/connection-response-reader.d.ts +3 -4
- package/dist/protocol/connection-response-reader.d.ts.map +1 -1
- package/dist/protocol/connection-response-reader.js +4 -2
- package/dist/protocol/socket-authorization.d.ts +1 -10
- package/dist/protocol/socket-authorization.d.ts.map +1 -1
- package/dist/protocol/socket-authorization.js +1 -4
- package/dist/protocol/socket-connector.d.ts +5 -5
- package/dist/protocol/socket-connector.d.ts.map +1 -1
- package/dist/protocol/socket-connector.js +24 -17
- package/dist/query.d.ts +17 -26
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +24 -27
- package/dist/transaction.d.ts +11 -4
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +24 -11
- package/dist/types.d.ts +59 -11
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/pool.js
CHANGED
|
@@ -1,76 +1,32 @@
|
|
|
1
1
|
import { Connection } from "./connection";
|
|
2
2
|
import { Queue, RingQueue } from "./queue";
|
|
3
3
|
import { Begin, Future, Ok } from "fluent-future";
|
|
4
|
-
import {
|
|
5
|
-
const ErrPoolClosed = new PostgresError('Pool closed');
|
|
4
|
+
import { ErrPoolClosed } from "./error";
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
8
|
-
* Manages a connection pool and provides high-level API for queries and transactions.
|
|
6
|
+
* Connection pool and the main entry point for Pgtx.
|
|
9
7
|
*
|
|
10
8
|
* @example
|
|
11
|
-
*
|
|
12
|
-
* const pool = new Pool({
|
|
13
|
-
* host: 'localhost',
|
|
14
|
-
* user: 'postgres',
|
|
15
|
-
* password: 'postgres',
|
|
16
|
-
* database: 'test',
|
|
17
|
-
* max: 10
|
|
18
|
-
* })
|
|
19
|
-
*
|
|
20
|
-
* // Simple query
|
|
9
|
+
* const pool = new Pool({ host: 'localhost', user: 'postgres', password: 'postgres', database: 'test', max: 10 })
|
|
21
10
|
* const users = await pool.query`SELECT * FROM users WHERE id = ${1}`
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* const result = await pool.begin(async tx => {
|
|
25
|
-
* await tx.query`INSERT INTO users ...`
|
|
26
|
-
* return 'success'
|
|
27
|
-
* })
|
|
28
|
-
*
|
|
29
|
-
* // Manual acquire/release
|
|
30
|
-
* const conn = await pool.acquire()
|
|
31
|
-
* try {
|
|
32
|
-
* await conn.query`SELECT 1`
|
|
33
|
-
* } finally {
|
|
34
|
-
* pool.release(conn)
|
|
35
|
-
* }
|
|
36
|
-
*
|
|
37
|
-
* // Clean up
|
|
38
|
-
* pool.close()
|
|
39
|
-
* ```
|
|
11
|
+
* await pool.begin(async tx => tx.query`INSERT INTO users ...`)
|
|
12
|
+
* await pool.close()
|
|
40
13
|
*/
|
|
41
14
|
export class Pool {
|
|
42
|
-
|
|
43
|
-
if (this._isClosed)
|
|
44
|
-
throw new Error('Pool closed');
|
|
45
|
-
}
|
|
46
|
-
constructor(params) {
|
|
15
|
+
constructor(config) {
|
|
47
16
|
this._total = 0;
|
|
48
17
|
this._waiting = new Queue();
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
this.
|
|
52
|
-
this._available = new RingQueue(this.
|
|
18
|
+
this._isOpened = true;
|
|
19
|
+
const conf = { ...config, max: config.max || 20 };
|
|
20
|
+
this.config = conf;
|
|
21
|
+
this._available = new RingQueue(this.config.max);
|
|
53
22
|
}
|
|
54
23
|
/**
|
|
55
|
-
* Acquires a dedicated connection
|
|
56
|
-
*
|
|
57
|
-
* **Note:** You must call `pool.release(conn)` manually when finished.
|
|
58
|
-
* For most cases, prefer using `pool.query()` or `pool.begin()` which handle this automatically.
|
|
59
|
-
*
|
|
60
|
-
* @returns A connection from the pool or a new one if available.
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```ts
|
|
64
|
-
* const conn = await pool.acquire()
|
|
65
|
-
* try {
|
|
66
|
-
* await conn.query`SELECT 1`
|
|
67
|
-
* } finally {
|
|
68
|
-
* pool.release(conn)
|
|
69
|
-
* }
|
|
70
|
-
* ```
|
|
24
|
+
* Acquires a dedicated connection. Call `pool.release(conn)` when done —
|
|
25
|
+
* prefer `pool.query()`/`pool.begin()` where possible, they release automatically.
|
|
71
26
|
*/
|
|
72
27
|
acquire() {
|
|
73
|
-
this.
|
|
28
|
+
if (!this._isOpened)
|
|
29
|
+
return Future.reject(ErrPoolClosed);
|
|
74
30
|
while (this._available.hasMore) {
|
|
75
31
|
const conn = this._available.shift;
|
|
76
32
|
if (conn.isOpened) {
|
|
@@ -78,9 +34,9 @@ export class Pool {
|
|
|
78
34
|
}
|
|
79
35
|
this._total--;
|
|
80
36
|
}
|
|
81
|
-
if (this._total < this.
|
|
37
|
+
if (this._total < this.config.max) {
|
|
82
38
|
this._total++;
|
|
83
|
-
return Connection.new(this.
|
|
39
|
+
return Connection.new(this.config)
|
|
84
40
|
.tapErr(() => this._total--);
|
|
85
41
|
}
|
|
86
42
|
const { future, reject, resolve } = Future.withResolvers();
|
|
@@ -88,22 +44,10 @@ export class Pool {
|
|
|
88
44
|
return future;
|
|
89
45
|
}
|
|
90
46
|
/**
|
|
91
|
-
*
|
|
92
|
-
* directly on a single, dedicated `Connection` instance.
|
|
93
|
-
*
|
|
94
|
-
* Automatically borrows a free socket from the pool, forwards it to the provided callback function,
|
|
95
|
-
* and guarantees that the connection is released back to the pool once the execution completes,
|
|
96
|
-
* even if errors or unexpected exceptions are thrown. Prevents connection descriptor leaks.
|
|
97
|
-
*
|
|
98
|
-
* @template T The return type of the provided callback function.
|
|
99
|
-
* @param {(conn: Connection) => Promise<T>} fn A callback function that operates on the allocated Connection.
|
|
100
|
-
* @returns {Future<T, PostgresError>} A `Future` that resolves with the return value of the callback.
|
|
47
|
+
* Runs `fn` with a borrowed connection and releases it afterward, even on error.
|
|
101
48
|
*
|
|
102
49
|
* @example
|
|
103
|
-
*
|
|
104
|
-
* const status = await pool.withAcquire(async (conn) => {
|
|
105
|
-
* return await conn.query`SELECT pg_is_in_recovery()`;
|
|
106
|
-
* });
|
|
50
|
+
* const status = await pool.withAcquire(conn => conn.query`SELECT pg_is_in_recovery()`)
|
|
107
51
|
*/
|
|
108
52
|
withAcquire(fn) {
|
|
109
53
|
return Begin()
|
|
@@ -111,26 +55,12 @@ export class Pool {
|
|
|
111
55
|
.andThen(conn => Future.of(fn(conn))
|
|
112
56
|
.finally(() => this.release(conn)));
|
|
113
57
|
}
|
|
114
|
-
/**
|
|
115
|
-
* Releases the connection back to the pool.
|
|
116
|
-
*
|
|
117
|
-
* If there are pending `acquire()` calls, the connection is passed directly to the next waiter.
|
|
118
|
-
* Otherwise, it's added to the available connections queue.
|
|
119
|
-
*
|
|
120
|
-
* @param conn - The connection to release.
|
|
121
|
-
*
|
|
122
|
-
* @example
|
|
123
|
-
* ```ts
|
|
124
|
-
* const conn = await pool.acquire()
|
|
125
|
-
* try {
|
|
126
|
-
* await conn.query`SELECT 1`
|
|
127
|
-
* } finally {
|
|
128
|
-
* pool.release(conn)
|
|
129
|
-
* }
|
|
130
|
-
* ```
|
|
131
|
-
*/
|
|
58
|
+
/** Returns `conn` to the pool, or hands it directly to the next waiting `acquire()`. */
|
|
132
59
|
release(conn) {
|
|
133
|
-
this.
|
|
60
|
+
if (!this._isOpened) {
|
|
61
|
+
void conn.close();
|
|
62
|
+
throw ErrPoolClosed;
|
|
63
|
+
}
|
|
134
64
|
if (!conn.isOpened) {
|
|
135
65
|
this._total--;
|
|
136
66
|
return;
|
|
@@ -142,55 +72,28 @@ export class Pool {
|
|
|
142
72
|
this._available.push(conn);
|
|
143
73
|
}
|
|
144
74
|
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* Automatically acquires a connection and handles `BEGIN`, `COMMIT`, and `ROLLBACK`.
|
|
148
|
-
* If the callback throws an error, the transaction is rolled back.
|
|
149
|
-
*
|
|
150
|
-
* @param txCallback - Async function that receives a `Transaction` instance.
|
|
151
|
-
* @returns The value returned from the callback.
|
|
75
|
+
* Runs `txCallback` inside a transaction on a borrowed connection, releasing it afterward.
|
|
152
76
|
*
|
|
153
77
|
* @example
|
|
154
|
-
*
|
|
155
|
-
* const result = await pool.begin(async tx => {
|
|
156
|
-
* await tx.query`INSERT INTO accounts (id, balance) VALUES (1, 100)`
|
|
78
|
+
* await pool.begin(async tx => {
|
|
157
79
|
* await tx.query`UPDATE accounts SET balance = balance - 10 WHERE id = 1`
|
|
158
|
-
* return { success: true }
|
|
159
80
|
* })
|
|
160
|
-
* ```
|
|
161
81
|
*/
|
|
162
82
|
begin(txCallback) {
|
|
163
|
-
this._checkClosed();
|
|
164
83
|
return Begin()
|
|
165
84
|
.andThen(() => this.acquire())
|
|
166
85
|
.andThen(conn => conn.begin(txCallback)
|
|
167
86
|
.finally(() => this.release(conn)));
|
|
168
87
|
}
|
|
169
88
|
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* Automatically acquires and releases a connection from the pool.
|
|
173
|
-
* For optimal performance, multiple queries can be pipelined through the same connection.
|
|
174
|
-
*
|
|
175
|
-
* @param templates - Tagged template string with SQL.
|
|
176
|
-
* @param args - Query parameters.
|
|
177
|
-
* @returns Array of rows with proper typing.
|
|
89
|
+
* Runs a one-off query on a borrowed connection.
|
|
178
90
|
*
|
|
179
91
|
* @example
|
|
180
|
-
*
|
|
181
|
-
* // Simple query
|
|
182
|
-
* const users = await pool.query`SELECT * FROM users`
|
|
183
|
-
*
|
|
184
|
-
* // With parameters
|
|
185
|
-
* const user = await pool.query`SELECT * FROM users WHERE id = ${1}`
|
|
186
|
-
*
|
|
187
|
-
* // With typed result
|
|
188
|
-
* type User = { id: number, name: string }
|
|
189
|
-
* const users = await pool.query<User>`SELECT * FROM users`
|
|
190
|
-
* ```
|
|
92
|
+
* const users = await pool.query<User>`SELECT * FROM users WHERE id = ${1}`
|
|
191
93
|
*/
|
|
192
94
|
query(templates, ...args) {
|
|
193
|
-
this.
|
|
95
|
+
if (!this._isOpened)
|
|
96
|
+
return Future.reject(ErrPoolClosed);
|
|
194
97
|
while (this._available.hasMore) {
|
|
195
98
|
const conn = this._available.shift;
|
|
196
99
|
if (!conn.isOpened) {
|
|
@@ -206,33 +109,34 @@ export class Pool {
|
|
|
206
109
|
return conn.query(templates, ...args);
|
|
207
110
|
});
|
|
208
111
|
}
|
|
112
|
+
/** Like {@link query}, but for statements that don't return rows. */
|
|
113
|
+
execute(templates, ...params) {
|
|
114
|
+
if (!this._isOpened)
|
|
115
|
+
return Future.reject(ErrPoolClosed);
|
|
116
|
+
while (this._available.hasMore) {
|
|
117
|
+
const conn = this._available.shift;
|
|
118
|
+
if (conn.isClosed) {
|
|
119
|
+
this._total--;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
this._available.push(conn);
|
|
123
|
+
return conn.execute(templates, ...params);
|
|
124
|
+
}
|
|
125
|
+
return this.acquire()
|
|
126
|
+
.andThen(conn => {
|
|
127
|
+
this.release(conn);
|
|
128
|
+
return conn.execute(templates, ...params);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
209
131
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
* Data is streamed directly from the PostgreSQL binary network buffer into the Web Streams API
|
|
213
|
-
* (`ReadableStream`), bypassing any intermediate array allocation or row accumulation in the JS heap.
|
|
214
|
-
* This pattern provides a true Zero-Memory Footprint and is ideal for exporting massive tables
|
|
215
|
-
* or piping database payloads directly into HTTP responses (e.g., via `Bun.serve` or fetch `Response`).
|
|
216
|
-
*
|
|
217
|
-
* @template T The expected shape of a single row interface.
|
|
218
|
-
* @param {TemplateStringsArray} templates The SQL string parts from the tagged template literal.
|
|
219
|
-
* @param {...any} args The parameterized query arguments.
|
|
220
|
-
* @returns {ReadableStream<T>} Synchronously returns a native Web ReadableStream instance.
|
|
132
|
+
* Streams query results as a `ReadableStream`, without buffering rows in memory.
|
|
221
133
|
*
|
|
222
134
|
* @example
|
|
223
|
-
*
|
|
224
|
-
* const userStream = pool.stream<User>`SELECT id, name FROM users`;
|
|
225
|
-
* return new Response(userStream, { headers: { 'Content-Type': 'application/json' } });
|
|
226
|
-
*
|
|
227
|
-
* @example
|
|
228
|
-
* // Asynchronously iterating over rows as they arrive from the wire socket
|
|
229
|
-
* const stream = pool.stream<User>`SELECT * FROM orders WHERE status = ${'processed'}`;
|
|
230
|
-
* for await (const row of stream) {
|
|
231
|
-
* console.log(row.id, row.amount); // Row object is eligible for GC immediately after iteration
|
|
232
|
-
* }
|
|
135
|
+
* for await (const row of pool.stream<User>`SELECT * FROM orders`) { ... }
|
|
233
136
|
*/
|
|
234
137
|
stream(templates, ...args) {
|
|
235
|
-
this.
|
|
138
|
+
if (!this._isOpened)
|
|
139
|
+
throw ErrPoolClosed;
|
|
236
140
|
while (this._available.hasMore) {
|
|
237
141
|
const conn = this._available.shift;
|
|
238
142
|
if (!conn.isOpened) {
|
|
@@ -251,90 +155,54 @@ export class Pool {
|
|
|
251
155
|
this.acquire()
|
|
252
156
|
.tap(conn => {
|
|
253
157
|
this.release(conn);
|
|
254
|
-
conn['
|
|
158
|
+
conn['_performStream'](templates, args, controller);
|
|
255
159
|
})
|
|
256
160
|
.catch(err => {
|
|
257
161
|
controller.error(err);
|
|
258
162
|
});
|
|
259
163
|
return stream;
|
|
260
164
|
}
|
|
261
|
-
/**
|
|
262
|
-
* Sends an asynchronous notification to a channel via `pg_notify`.
|
|
263
|
-
*
|
|
264
|
-
* @param channelName - The channel identifier
|
|
265
|
-
* @param payload - Optional string data (max 8000 bytes)
|
|
266
|
-
*
|
|
267
|
-
* @example
|
|
268
|
-
* ```ts
|
|
269
|
-
* await pool.notify('events', 'hello')
|
|
270
|
-
* ```
|
|
271
|
-
*/
|
|
165
|
+
/** Sends a `pg_notify` message on `channelName` (payload ≤ 8000 bytes). */
|
|
272
166
|
notify(channelName, payload = "") {
|
|
273
|
-
return this.
|
|
167
|
+
return this.acquire()
|
|
168
|
+
.andThen(conn => conn.notify(channelName, payload)
|
|
169
|
+
.finally(() => this.release(conn)));
|
|
274
170
|
}
|
|
275
171
|
/**
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
* This method automatically claims a dedicated connection from the pool, registers the callback
|
|
279
|
-
* to handle incoming asynchronous database notices (`NotificationResponse` packets), and returns
|
|
280
|
-
* a lazy unsubscribe function wrapped in a `Future`.
|
|
281
|
-
*
|
|
282
|
-
* Invoking the returned unsubscribe function will automatically issue the `UNLISTEN` command
|
|
283
|
-
* to the database backend, clean up the memory callback, and safely release the connection back to the pool.
|
|
284
|
-
*
|
|
285
|
-
* @param {string} channel The name of the PostgreSQL notification channel.
|
|
286
|
-
* @param {(payload: string) => void} callback The event handler invoked when a NOTIFY message arrives.
|
|
287
|
-
* @returns {Future<() => Promise<void>, PostgresError>} A `Future` resolving to an async unsubscribe function.
|
|
172
|
+
* Subscribes `callback` to `channel` on a dedicated connection.
|
|
173
|
+
* Returns an unsubscribe function that issues `UNLISTEN` and releases the connection.
|
|
288
174
|
*
|
|
289
175
|
* @example
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
* const order = JSON.parse(payload);
|
|
293
|
-
* console.log(`New order received: ${order.id}`);
|
|
294
|
-
* });
|
|
295
|
-
*
|
|
296
|
-
* // When the subscription is no longer needed (e.g., during teardown or server stop):
|
|
297
|
-
* await unlisten(); // The socket cleanly issues UNLISTEN and returns to the pool of free connections.
|
|
176
|
+
* const unlisten = await pool.listen('order_created', payload => console.log(payload))
|
|
177
|
+
* await unlisten()
|
|
298
178
|
*/
|
|
299
179
|
listen(channel, callback) {
|
|
300
180
|
return this.acquire()
|
|
301
181
|
.andThen(conn => conn.listen(channel, callback)
|
|
302
|
-
.map(() =>
|
|
303
|
-
|
|
304
|
-
this.release(conn);
|
|
305
|
-
}));
|
|
182
|
+
.map(() => () => conn.unlisten(channel, callback)
|
|
183
|
+
.tap(() => this.release(conn))));
|
|
306
184
|
}
|
|
307
|
-
/**
|
|
308
|
-
* Number of available (idle) connections in the pool.
|
|
309
|
-
*/
|
|
185
|
+
/** Number of idle connections. */
|
|
310
186
|
get size() {
|
|
311
187
|
return this._available.size;
|
|
312
188
|
}
|
|
313
|
-
/**
|
|
314
|
-
* Total number of connections currently managed by the pool
|
|
315
|
-
* (available + in use).
|
|
316
|
-
*/
|
|
189
|
+
/** Total connections managed (idle + in use). */
|
|
317
190
|
get total() {
|
|
318
191
|
return this._total;
|
|
319
192
|
}
|
|
320
193
|
/**
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
* All pending `acquire()` calls will be rejected with an error.
|
|
324
|
-
* The pool cannot be used after calling `close()`.
|
|
325
|
-
*
|
|
326
|
-
* @example
|
|
327
|
-
* ```ts
|
|
328
|
-
* pool.close()
|
|
329
|
-
* ```
|
|
194
|
+
* Closes idle connections and rejects pending `acquire()` calls. Not usable afterward.
|
|
330
195
|
*/
|
|
331
196
|
close() {
|
|
197
|
+
this._isOpened = false;
|
|
198
|
+
const futures = [];
|
|
332
199
|
while (this._available.hasMore) {
|
|
333
|
-
this._available.shift.close();
|
|
200
|
+
futures.push(this._available.shift.close());
|
|
334
201
|
}
|
|
335
202
|
while (this._waiting.hasMore) {
|
|
336
203
|
this._waiting.shift.reject(ErrPoolClosed);
|
|
337
204
|
}
|
|
338
205
|
this._total = 0;
|
|
206
|
+
return Future.all(futures).map(() => { });
|
|
339
207
|
}
|
|
340
208
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { AuthenticationCode, ResponseType, TransactionStatus } from "./constants";
|
|
2
|
-
import { ColumnDescription } from "../types";
|
|
2
|
+
import { ChannelName, ColumnDescription } from "../types";
|
|
3
3
|
import { PostgresError } from "../error";
|
|
4
|
-
import { ChannelName } from "../connection";
|
|
5
4
|
export declare class ConnectionResponseBuffer {
|
|
6
5
|
private buffer;
|
|
7
6
|
private caret;
|
|
@@ -31,7 +30,6 @@ export declare class ConnectionResponseBuffer {
|
|
|
31
30
|
}
|
|
32
31
|
export declare class ConnectionResponseReader {
|
|
33
32
|
private buffer;
|
|
34
|
-
private currentPacketLength;
|
|
35
33
|
private constructor();
|
|
36
34
|
static from(buffer: Buffer): ConnectionResponseReader;
|
|
37
35
|
readType(): {
|
|
@@ -53,7 +51,7 @@ export declare class ConnectionResponseReader {
|
|
|
53
51
|
readSaslMechanisms(): string[];
|
|
54
52
|
readSaslMessage(length: number): string;
|
|
55
53
|
readRowDescription(): ColumnDescription[];
|
|
56
|
-
readDataRow(descriptions: ColumnDescription[], int8toBigint
|
|
54
|
+
readDataRow(descriptions: ColumnDescription[], int8toBigint: boolean): Record<string, any>;
|
|
57
55
|
readNotificationResponse(): {
|
|
58
56
|
name: ChannelName;
|
|
59
57
|
payload: string;
|
|
@@ -66,5 +64,6 @@ export declare class ConnectionResponseReader {
|
|
|
66
64
|
readBindComplete(): void;
|
|
67
65
|
readParameterDescription(): void;
|
|
68
66
|
readNoData(): void;
|
|
67
|
+
skip(count: number): void;
|
|
69
68
|
}
|
|
70
69
|
//# sourceMappingURL=connection-response-reader.d.ts.map
|
|
@@ -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;
|
|
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,WAAW,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAQxC,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;IAG7B,OAAO,CAAC,MAAM;IADlB,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,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IA0G1F,wBAAwB;;;;IASxB,mBAAmB,IAAI,MAAM;IAK7B,OAAO;IAKP,aAAa;IAKb,iBAAiB;IAKjB,iBAAiB;IAGjB,gBAAgB;IAGhB,wBAAwB;IAOxB,UAAU;IAEV,IAAI,CAAC,KAAK,EAAE,MAAM;CAGrB"}
|
|
@@ -131,7 +131,6 @@ export class ConnectionResponseBuffer {
|
|
|
131
131
|
export class ConnectionResponseReader {
|
|
132
132
|
constructor(buffer) {
|
|
133
133
|
this.buffer = buffer;
|
|
134
|
-
this.currentPacketLength = 0;
|
|
135
134
|
}
|
|
136
135
|
static from(buffer) {
|
|
137
136
|
return new ConnectionResponseReader(ConnectionResponseBuffer.from(buffer));
|
|
@@ -236,7 +235,7 @@ export class ConnectionResponseReader {
|
|
|
236
235
|
}
|
|
237
236
|
return columns;
|
|
238
237
|
}
|
|
239
|
-
readDataRow(descriptions, int8toBigint
|
|
238
|
+
readDataRow(descriptions, int8toBigint) {
|
|
240
239
|
const fieldsCount = this.buffer.readInt16();
|
|
241
240
|
const row = {};
|
|
242
241
|
for (let i = 0; i < fieldsCount; i++) {
|
|
@@ -377,4 +376,7 @@ export class ConnectionResponseReader {
|
|
|
377
376
|
}
|
|
378
377
|
}
|
|
379
378
|
readNoData() { }
|
|
379
|
+
skip(count) {
|
|
380
|
+
this.buffer.skipBytes(count);
|
|
381
|
+
}
|
|
380
382
|
}
|
|
@@ -2,15 +2,6 @@ import { Socket } from "node:net";
|
|
|
2
2
|
import { ConnectionRequestWriter } from "./connection-request-writer";
|
|
3
3
|
import { PostgresError } from "../error";
|
|
4
4
|
import { Future } from "fluent-future";
|
|
5
|
-
|
|
6
|
-
host: string;
|
|
7
|
-
port: number;
|
|
8
|
-
user: string;
|
|
9
|
-
database: string;
|
|
10
|
-
password?: string;
|
|
11
|
-
};
|
|
12
|
-
export declare const ErrNonceMismatch: PostgresError;
|
|
13
|
-
export declare const ErrPasswordRequired: PostgresError;
|
|
14
|
-
export declare const ErrSocketFailedDuringAuth: PostgresError;
|
|
5
|
+
import { AuthorizationParams } from "../types";
|
|
15
6
|
export declare const createAuthorizedSocket: (writer: ConnectionRequestWriter, params: AuthorizationParams) => Future<Socket, PostgresError>;
|
|
16
7
|
//# 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,
|
|
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,EAAoE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC1G,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAG9C,eAAO,MAAM,sBAAsB,GAAI,QAAQ,uBAAuB,EAAE,QAAQ,mBAAmB,kCAoHlG,CAAA"}
|
|
@@ -3,11 +3,8 @@ import { calculateScramAuth, generateNonce } from "../security/sasl";
|
|
|
3
3
|
import { SocketConnector } from "./socket-connector";
|
|
4
4
|
import { AuthenticationCodes, ResponseTypes } from "./constants";
|
|
5
5
|
import { encryptMd5 } from "../security/md5";
|
|
6
|
-
import {
|
|
6
|
+
import { ErrNonceMismatch, ErrPasswordRequired, ErrSocketFailedDuringAuth } from "../error";
|
|
7
7
|
import { Future } from "fluent-future";
|
|
8
|
-
export const ErrNonceMismatch = new PostgresError("Protocol violation: server nonce doesn't match client nonce");
|
|
9
|
-
export const ErrPasswordRequired = new PostgresError('The authorization method requires a password.');
|
|
10
|
-
export const ErrSocketFailedDuringAuth = new PostgresError("Socket failed during auth");
|
|
11
8
|
export const createAuthorizedSocket = (writer, params) => {
|
|
12
9
|
const { future, reject, resolve } = Future.withResolvers();
|
|
13
10
|
const nonce = generateNonce();
|
|
@@ -4,14 +4,14 @@ import { ConnectionResponseReader } from '../protocol/connection-response-reader
|
|
|
4
4
|
import { ConnectionRequestWriter } from '../protocol/connection-request-writer';
|
|
5
5
|
export declare class SocketConnector {
|
|
6
6
|
private _socket;
|
|
7
|
-
private _onData;
|
|
8
|
-
private _onError;
|
|
9
7
|
private residualBuffer;
|
|
10
|
-
private
|
|
11
|
-
|
|
8
|
+
private _onError;
|
|
9
|
+
private _onClose;
|
|
10
|
+
private _onData;
|
|
11
|
+
private _destroyed;
|
|
12
|
+
constructor(_socket: Socket, onData: (type: ResponseType, length: number, reader: ConnectionResponseReader) => void, onError: (error: unknown) => void);
|
|
12
13
|
write(writer: ConnectionRequestWriter): void;
|
|
13
14
|
unwrapSocket(): Socket;
|
|
14
15
|
destroy(): void;
|
|
15
|
-
get isDestroyed(): boolean;
|
|
16
16
|
}
|
|
17
17
|
//# sourceMappingURL=socket-connector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-connector.d.ts","sourceRoot":"","sources":["../../src/protocol/socket-connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AAE/E,qBAAa,eAAe;
|
|
1
|
+
{"version":3,"file":"socket-connector.d.ts","sourceRoot":"","sources":["../../src/protocol/socket-connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AAE/E,qBAAa,eAAe;IAQpB,OAAO,CAAC,OAAO;IAPnB,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,UAAU,CAAQ;gBAGd,OAAO,EAAE,MAAM,EACvB,MAAM,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,KAAK,IAAI,EACtF,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IA4CrC,KAAK,CAAC,MAAM,EAAE,uBAAuB;IAKrC,YAAY;IASZ,OAAO;CAGV"}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { ConnectionResponseReader } from '../protocol/connection-response-reader';
|
|
2
2
|
export class SocketConnector {
|
|
3
|
-
constructor(_socket,
|
|
3
|
+
constructor(_socket, onData, onError) {
|
|
4
4
|
this._socket = _socket;
|
|
5
|
-
this._onData = _onData;
|
|
6
|
-
this._onError = _onError;
|
|
7
5
|
this.residualBuffer = null;
|
|
8
|
-
this.
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
this._destroyed = false;
|
|
7
|
+
this._onError = (err) => {
|
|
8
|
+
if (this._destroyed)
|
|
9
|
+
return;
|
|
10
|
+
this._destroyed = true;
|
|
11
|
+
onError(err);
|
|
12
|
+
this.destroy();
|
|
13
|
+
};
|
|
14
|
+
this._onClose = () => {
|
|
15
|
+
if (this._destroyed)
|
|
16
|
+
return;
|
|
17
|
+
this._destroyed = true;
|
|
18
|
+
onError(new Error("Socket closed"));
|
|
19
|
+
this.destroy();
|
|
20
|
+
};
|
|
21
|
+
this._onData = buffer => {
|
|
11
22
|
const currentBuffer = this.residualBuffer
|
|
12
23
|
? Buffer.concat([this.residualBuffer, buffer])
|
|
13
24
|
: buffer;
|
|
@@ -19,28 +30,24 @@ export class SocketConnector {
|
|
|
19
30
|
return;
|
|
20
31
|
}
|
|
21
32
|
const { type, length } = reader.readType();
|
|
22
|
-
|
|
33
|
+
onData(type, length, reader);
|
|
23
34
|
}
|
|
24
|
-
}
|
|
25
|
-
_socket.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
});
|
|
35
|
+
};
|
|
36
|
+
_socket.setKeepAlive(true, 10000);
|
|
37
|
+
_socket.on('data', this._onData);
|
|
38
|
+
_socket.on('error', this._onError);
|
|
39
|
+
_socket.on('close', this._onClose);
|
|
30
40
|
}
|
|
31
41
|
write(writer) {
|
|
32
|
-
if (this._isDestroyed)
|
|
33
|
-
throw new Error("SocketConnector is destroyed");
|
|
34
42
|
this._socket.write(writer.asBuffer());
|
|
35
43
|
}
|
|
36
44
|
unwrapSocket() {
|
|
37
45
|
this._socket.off('error', this._onError);
|
|
38
46
|
this._socket.off("data", this._onData);
|
|
47
|
+
this._socket.off('close', this._onClose);
|
|
39
48
|
return this._socket;
|
|
40
49
|
}
|
|
41
50
|
destroy() {
|
|
42
|
-
this._isDestroyed = true;
|
|
43
51
|
this._socket.destroy();
|
|
44
52
|
}
|
|
45
|
-
get isDestroyed() { return this._isDestroyed; }
|
|
46
53
|
}
|
package/dist/query.d.ts
CHANGED
|
@@ -1,53 +1,44 @@
|
|
|
1
1
|
import { Future } from "fluent-future";
|
|
2
|
-
import {
|
|
3
|
-
import { ColumnDescription, ValueOF } from "./types";
|
|
2
|
+
import { ColumnDescription, QueryText, Row, StatementName } from "./types";
|
|
4
3
|
import { PostgresError } from "./error";
|
|
5
|
-
export declare const QueryState: {
|
|
6
|
-
readonly Parsing: 0;
|
|
7
|
-
readonly Executing: 1;
|
|
8
|
-
readonly Completed: 2;
|
|
9
|
-
readonly Failed: 3;
|
|
10
|
-
};
|
|
11
|
-
export type State = ValueOF<typeof QueryState>;
|
|
12
4
|
export declare abstract class Query {
|
|
13
5
|
statement: StatementName;
|
|
6
|
+
text: QueryText;
|
|
7
|
+
args: (string | null)[];
|
|
14
8
|
protected _timer?: NodeJS.Timeout;
|
|
15
|
-
constructor(statement: StatementName);
|
|
16
|
-
startTimeout(timeout: number): void;
|
|
9
|
+
constructor(statement: StatementName, text: QueryText, args: (string | null)[], timeout: number);
|
|
17
10
|
abstract reject(cause: PostgresError): void;
|
|
18
11
|
abstract resolve(...args: any[]): void;
|
|
12
|
+
abstract push(...args: any[]): void;
|
|
19
13
|
}
|
|
20
|
-
export declare class
|
|
21
|
-
|
|
22
|
-
args: (string | null)[];
|
|
23
|
-
columns: ColumnDescription[];
|
|
14
|
+
export declare class CollectQuery<T extends Row> extends Query {
|
|
15
|
+
columns: ColumnDescription[] | null;
|
|
24
16
|
future: Future<T[], PostgresError>;
|
|
25
17
|
private _resolve;
|
|
26
18
|
private _reject;
|
|
27
19
|
private _rows;
|
|
28
|
-
constructor(statement: StatementName, text: QueryText, args: (string | null)[], columns: ColumnDescription[]);
|
|
20
|
+
constructor(statement: StatementName, text: QueryText, args: (string | null)[], columns: ColumnDescription[] | null, timeout: number);
|
|
29
21
|
push(value: T): void;
|
|
30
22
|
reject(cause: PostgresError): void;
|
|
31
23
|
resolve(): void;
|
|
32
24
|
}
|
|
33
|
-
export declare class
|
|
34
|
-
|
|
35
|
-
future: Future<
|
|
25
|
+
export declare class ExecuteQuery extends Query {
|
|
26
|
+
columns: ColumnDescription[] | null;
|
|
27
|
+
future: Future<void, PostgresError>;
|
|
36
28
|
private _resolve;
|
|
37
29
|
private _reject;
|
|
38
|
-
constructor(statement: StatementName, text: QueryText);
|
|
30
|
+
constructor(statement: StatementName, text: QueryText, args: (string | null)[], columns: ColumnDescription[] | null, timeout: number);
|
|
39
31
|
reject(cause: PostgresError): void;
|
|
40
|
-
resolve(
|
|
32
|
+
resolve(): void;
|
|
33
|
+
push(): void;
|
|
41
34
|
}
|
|
42
35
|
export declare class StreamQuery<T> extends Query {
|
|
43
|
-
text: QueryText;
|
|
44
|
-
args: (string | null)[];
|
|
45
36
|
controller: ReadableStreamDefaultController<T>;
|
|
46
|
-
columns: ColumnDescription[];
|
|
47
|
-
constructor(statement: StatementName, text: QueryText, args: (string | null)[], controller: ReadableStreamDefaultController<T>, columns: ColumnDescription[]);
|
|
37
|
+
columns: ColumnDescription[] | null;
|
|
38
|
+
constructor(statement: StatementName, text: QueryText, args: (string | null)[], controller: ReadableStreamDefaultController<T>, columns: ColumnDescription[] | null, timeout: number);
|
|
48
39
|
push(value: T): void;
|
|
49
40
|
reject(cause: PostgresError): void;
|
|
50
41
|
resolve(): void;
|
|
51
42
|
}
|
|
52
|
-
export type PostgresQuery =
|
|
43
|
+
export type PostgresQuery = CollectQuery<any> | StreamQuery<any> | ExecuteQuery;
|
|
53
44
|
//# sourceMappingURL=query.d.ts.map
|