@m2k-5f/pgtx 2.4.0 → 2.5.0
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 +141 -36
- package/dist/connection.d.ts +30 -18
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +95 -18
- package/dist/pool.d.ts +72 -2
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +122 -28
- package/dist/protocol/connection-response-reader.d.ts +5 -2
- package/dist/protocol/connection-response-reader.d.ts.map +1 -1
- package/dist/protocol/connection-response-reader.js +6 -23
- package/dist/protocol/socket-authorization.d.ts.map +1 -1
- package/dist/protocol/socket-authorization.js +3 -3
- package/dist/protocol/socket-connector.d.ts +1 -1
- package/dist/protocol/socket-connector.d.ts.map +1 -1
- package/dist/protocol/socket-connector.js +2 -1
- package/dist/query.d.ts +21 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +42 -4
- package/dist/queue.d.ts +3 -2
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +3 -2
- package/package.json +55 -55
package/dist/pool.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Connection } from "./connection";
|
|
2
2
|
import { Queue } from "./queue";
|
|
3
|
-
import { Future, Resolve } from "fluent-future";
|
|
3
|
+
import { Begin, Future, Resolve } from "fluent-future";
|
|
4
|
+
import { PostgresError } from "./error";
|
|
5
|
+
const ErrPoolClosed = new PostgresError('Pool closed');
|
|
4
6
|
/**
|
|
5
7
|
* The main entry point for Pgtx.
|
|
6
8
|
* Manages a connection pool and provides high-level API for queries and transactions.
|
|
@@ -70,8 +72,7 @@ export class Pool {
|
|
|
70
72
|
acquire() {
|
|
71
73
|
this._checkClosed();
|
|
72
74
|
while (this._available.hasMore) {
|
|
73
|
-
const conn = this._available.
|
|
74
|
-
this._available.next();
|
|
75
|
+
const conn = this._available.shift;
|
|
75
76
|
if (conn.isOpened) {
|
|
76
77
|
return Resolve(conn);
|
|
77
78
|
}
|
|
@@ -79,12 +80,36 @@ export class Pool {
|
|
|
79
80
|
}
|
|
80
81
|
if (this._total < this._max) {
|
|
81
82
|
this._total++;
|
|
82
|
-
return
|
|
83
|
+
return Connection.new(this._config)
|
|
83
84
|
.tapErr(() => this._total--);
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
const { future, reject, resolve } = Future.withResolvers();
|
|
87
|
+
this._waiting.push({ resolve, reject });
|
|
88
|
+
return future;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Provides a safe execution context for performing low-level operations
|
|
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.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* // Executing low-level engine commands on a single, pinned connection
|
|
104
|
+
* const status = await pool.withAcquire(async (conn) => {
|
|
105
|
+
* return await conn.query`SELECT pg_is_in_recovery()`;
|
|
106
|
+
* });
|
|
107
|
+
*/
|
|
108
|
+
withAcquire(fn) {
|
|
109
|
+
return Begin()
|
|
110
|
+
.andThen(() => this.acquire())
|
|
111
|
+
.andThen(conn => Future.of(fn(conn))
|
|
112
|
+
.finally(() => this.release(conn)));
|
|
88
113
|
}
|
|
89
114
|
/**
|
|
90
115
|
* Releases the connection back to the pool.
|
|
@@ -111,9 +136,7 @@ export class Pool {
|
|
|
111
136
|
return;
|
|
112
137
|
}
|
|
113
138
|
if (this._waiting.hasMore) {
|
|
114
|
-
|
|
115
|
-
this._waiting.next();
|
|
116
|
-
waiter.resolve(conn);
|
|
139
|
+
this._waiting.shift.resolve(conn);
|
|
117
140
|
return;
|
|
118
141
|
}
|
|
119
142
|
this._available.push(conn);
|
|
@@ -138,7 +161,8 @@ export class Pool {
|
|
|
138
161
|
*/
|
|
139
162
|
begin(txCallback) {
|
|
140
163
|
this._checkClosed();
|
|
141
|
-
return
|
|
164
|
+
return Begin()
|
|
165
|
+
.andThen(() => this.acquire())
|
|
142
166
|
.andThen(conn => conn.begin(txCallback)
|
|
143
167
|
.finally(() => this.release(conn)));
|
|
144
168
|
}
|
|
@@ -168,8 +192,7 @@ export class Pool {
|
|
|
168
192
|
query(templates, ...args) {
|
|
169
193
|
this._checkClosed();
|
|
170
194
|
while (this._available.hasMore) {
|
|
171
|
-
const conn = this._available.
|
|
172
|
-
this._available.next();
|
|
195
|
+
const conn = this._available.shift;
|
|
173
196
|
if (!conn.isOpened) {
|
|
174
197
|
this._total--;
|
|
175
198
|
continue;
|
|
@@ -177,21 +200,64 @@ export class Pool {
|
|
|
177
200
|
this._available.push(conn);
|
|
178
201
|
return conn.query(templates, ...args);
|
|
179
202
|
}
|
|
180
|
-
if (this._total < this._max) {
|
|
181
|
-
this._total++;
|
|
182
|
-
return Future.of(Connection.new(this._config))
|
|
183
|
-
.tapErr(() => this._total--)
|
|
184
|
-
.andThen(conn => {
|
|
185
|
-
this.release(conn);
|
|
186
|
-
return conn.query(templates, ...args);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
203
|
return this.acquire()
|
|
190
204
|
.andThen(conn => {
|
|
191
205
|
this.release(conn);
|
|
192
206
|
return conn.query(templates, ...args);
|
|
193
207
|
});
|
|
194
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* Executes an SQL query in streaming mode.
|
|
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.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* // Streaming a giant table directly to an HTTP response (Bun.serve)
|
|
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
|
+
* }
|
|
233
|
+
*/
|
|
234
|
+
stream(templates, ...args) {
|
|
235
|
+
this._checkClosed();
|
|
236
|
+
while (this._available.hasMore) {
|
|
237
|
+
const conn = this._available.shift;
|
|
238
|
+
if (!conn.isOpened) {
|
|
239
|
+
this._total--;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
this._available.push(conn);
|
|
243
|
+
return conn.stream(templates, ...args);
|
|
244
|
+
}
|
|
245
|
+
let controller;
|
|
246
|
+
const stream = new ReadableStream({
|
|
247
|
+
start: c => {
|
|
248
|
+
controller = c;
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
this.acquire()
|
|
252
|
+
.tap(conn => {
|
|
253
|
+
this.release(conn);
|
|
254
|
+
conn['_streamWithController'](templates, args, controller);
|
|
255
|
+
})
|
|
256
|
+
.catch(err => {
|
|
257
|
+
controller.error(err);
|
|
258
|
+
});
|
|
259
|
+
return stream;
|
|
260
|
+
}
|
|
195
261
|
/**
|
|
196
262
|
* Sends an asynchronous notification to a channel via `pg_notify`.
|
|
197
263
|
*
|
|
@@ -206,6 +272,38 @@ export class Pool {
|
|
|
206
272
|
notify(channelName, payload = "") {
|
|
207
273
|
return this.query `select pg_notify(${channelName}, ${payload})`;
|
|
208
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Asynchronously subscribes to pub/sub events on a specific PostgreSQL channel (LISTEN).
|
|
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.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* // Subscribing to database events directly from the Pool
|
|
291
|
+
* const unlisten = await pool.listen('order_created', (payload) => {
|
|
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.
|
|
298
|
+
*/
|
|
299
|
+
listen(channel, callback) {
|
|
300
|
+
return this.acquire()
|
|
301
|
+
.andThen(conn => conn.listen(channel, callback)
|
|
302
|
+
.map(() => async () => {
|
|
303
|
+
await conn.unlisten(channel, callback);
|
|
304
|
+
this.release(conn);
|
|
305
|
+
}));
|
|
306
|
+
}
|
|
209
307
|
/**
|
|
210
308
|
* Number of available (idle) connections in the pool.
|
|
211
309
|
*/
|
|
@@ -232,14 +330,10 @@ export class Pool {
|
|
|
232
330
|
*/
|
|
233
331
|
close() {
|
|
234
332
|
while (this._available.hasMore) {
|
|
235
|
-
|
|
236
|
-
this._available.next();
|
|
237
|
-
conn.close();
|
|
333
|
+
this._available.shift.close();
|
|
238
334
|
}
|
|
239
335
|
while (this._waiting.hasMore) {
|
|
240
|
-
|
|
241
|
-
this._waiting.next();
|
|
242
|
-
waiter.reject(new Error('Pool closed'));
|
|
336
|
+
this._waiting.shift.reject(ErrPoolClosed);
|
|
243
337
|
}
|
|
244
338
|
this._total = 0;
|
|
245
339
|
}
|
|
@@ -32,7 +32,10 @@ export declare class ConnectionResponseReader {
|
|
|
32
32
|
private currentPacketLength;
|
|
33
33
|
private constructor();
|
|
34
34
|
static from(buffer: Buffer): ConnectionResponseReader;
|
|
35
|
-
readType():
|
|
35
|
+
readType(): {
|
|
36
|
+
type: ResponseType;
|
|
37
|
+
length: number;
|
|
38
|
+
};
|
|
36
39
|
readAuthentication(): AuthenticationCode;
|
|
37
40
|
readMD5Salt(): Buffer<ArrayBufferLike>;
|
|
38
41
|
readParameterStatus(): {
|
|
@@ -46,7 +49,7 @@ export declare class ConnectionResponseReader {
|
|
|
46
49
|
readErrorResponse(): PostgresError;
|
|
47
50
|
readReadyForQuery(): TransactionStatus;
|
|
48
51
|
readSaslMechanisms(): string[];
|
|
49
|
-
readSaslMessage(): string;
|
|
52
|
+
readSaslMessage(length: number): string;
|
|
50
53
|
readRowDescription(): ColumnDescription[];
|
|
51
54
|
readDataRow(descriptions: ColumnDescription[], int8toBigint?: boolean): Record<string, any>;
|
|
52
55
|
readNotificationResponse(): {
|
|
@@ -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,
|
|
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"}
|
|
@@ -123,31 +123,27 @@ export class ConnectionResponseReader {
|
|
|
123
123
|
return new ConnectionResponseReader(ConnectionResponseBuffer.from(buffer));
|
|
124
124
|
}
|
|
125
125
|
readType() {
|
|
126
|
-
return this.buffer.readChar();
|
|
126
|
+
return { type: this.buffer.readChar(), length: this.buffer.readInt32() };
|
|
127
127
|
}
|
|
128
128
|
readAuthentication() {
|
|
129
|
-
this.currentPacketLength = this.buffer.readInt32();
|
|
130
129
|
return this.buffer.readInt32();
|
|
131
130
|
}
|
|
132
131
|
readMD5Salt() {
|
|
133
132
|
return this.buffer.readBytes(4);
|
|
134
133
|
}
|
|
135
134
|
readParameterStatus() {
|
|
136
|
-
this.buffer.readInt32();
|
|
137
135
|
return {
|
|
138
136
|
name: this.buffer.readCString(),
|
|
139
137
|
value: this.buffer.readCString()
|
|
140
138
|
};
|
|
141
139
|
}
|
|
142
140
|
readBackendKeyData() {
|
|
143
|
-
this.buffer.readInt32();
|
|
144
141
|
return {
|
|
145
142
|
PID: this.buffer.readInt32(),
|
|
146
143
|
secret: this.buffer.readInt32()
|
|
147
144
|
};
|
|
148
145
|
}
|
|
149
146
|
readErrorResponse() {
|
|
150
|
-
this.buffer.readInt32();
|
|
151
147
|
let severity = '';
|
|
152
148
|
let code = '';
|
|
153
149
|
let message = '';
|
|
@@ -195,7 +191,6 @@ export class ConnectionResponseReader {
|
|
|
195
191
|
return new PostgresError(message, code, detail, severity, where, hint, position, dataType, constraint);
|
|
196
192
|
}
|
|
197
193
|
readReadyForQuery() {
|
|
198
|
-
this.buffer.readInt32();
|
|
199
194
|
return this.buffer.readChar();
|
|
200
195
|
}
|
|
201
196
|
readSaslMechanisms() {
|
|
@@ -208,12 +203,10 @@ export class ConnectionResponseReader {
|
|
|
208
203
|
}
|
|
209
204
|
return mechanisms;
|
|
210
205
|
}
|
|
211
|
-
readSaslMessage() {
|
|
212
|
-
|
|
213
|
-
return this.buffer.readRawString(dataLength);
|
|
206
|
+
readSaslMessage(length) {
|
|
207
|
+
return this.buffer.readRawString(length - 4 - 4);
|
|
214
208
|
}
|
|
215
209
|
readRowDescription() {
|
|
216
|
-
this.buffer.skipBytes(4);
|
|
217
210
|
const columnsCount = this.buffer.readInt16();
|
|
218
211
|
const columns = new Array(columnsCount);
|
|
219
212
|
for (let i = 0; i < columnsCount; i++) {
|
|
@@ -230,7 +223,6 @@ export class ConnectionResponseReader {
|
|
|
230
223
|
return columns;
|
|
231
224
|
}
|
|
232
225
|
readDataRow(descriptions, int8toBigint = false) {
|
|
233
|
-
this.buffer.skipBytes(4);
|
|
234
226
|
const fieldsCount = this.buffer.readInt16();
|
|
235
227
|
const row = {};
|
|
236
228
|
for (let i = 0; i < fieldsCount; i++) {
|
|
@@ -311,14 +303,12 @@ export class ConnectionResponseReader {
|
|
|
311
303
|
return row;
|
|
312
304
|
}
|
|
313
305
|
readNotificationResponse() {
|
|
314
|
-
this.buffer.readInt32();
|
|
315
306
|
this.buffer.readInt32();
|
|
316
307
|
const name = this.buffer.readCString();
|
|
317
308
|
const payload = this.buffer.readCString();
|
|
318
309
|
return { name, payload };
|
|
319
310
|
}
|
|
320
311
|
readCommandComplete() {
|
|
321
|
-
this.buffer.readInt32();
|
|
322
312
|
return this.buffer.readCString();
|
|
323
313
|
}
|
|
324
314
|
hasMore() {
|
|
@@ -330,20 +320,13 @@ export class ConnectionResponseReader {
|
|
|
330
320
|
getResidualBuffer() {
|
|
331
321
|
return this.buffer.getResidualBuffer();
|
|
332
322
|
}
|
|
333
|
-
readParseComplete() {
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
readBindComplete() {
|
|
337
|
-
this.buffer.readInt32();
|
|
338
|
-
}
|
|
323
|
+
readParseComplete() { }
|
|
324
|
+
readBindComplete() { }
|
|
339
325
|
readParameterDescription() {
|
|
340
|
-
this.buffer.readInt32();
|
|
341
326
|
const count = this.buffer.readInt16();
|
|
342
327
|
for (let i = 0; i < count; i++) {
|
|
343
328
|
this.buffer.readInt32();
|
|
344
329
|
}
|
|
345
330
|
}
|
|
346
|
-
readNoData() {
|
|
347
|
-
this.buffer.readInt32();
|
|
348
|
-
}
|
|
331
|
+
readNoData() { }
|
|
349
332
|
}
|
|
@@ -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,
|
|
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"}
|
|
@@ -13,7 +13,7 @@ export const createAuthorizedSocket = (writer, params) => {
|
|
|
13
13
|
let clientMessage = '';
|
|
14
14
|
let serverMessage = '';
|
|
15
15
|
const socket = createConnection({ host: params.host, port: params.port });
|
|
16
|
-
const connector = new SocketConnector(socket, (type, reader) => {
|
|
16
|
+
const connector = new SocketConnector(socket, (type, length, reader) => {
|
|
17
17
|
writer.clear();
|
|
18
18
|
switch (type) {
|
|
19
19
|
case ResponseTypes.Authentication: {
|
|
@@ -42,7 +42,7 @@ export const createAuthorizedSocket = (writer, params) => {
|
|
|
42
42
|
break;
|
|
43
43
|
}
|
|
44
44
|
case AuthenticationCodes.SASLContinue: {
|
|
45
|
-
serverMessage = reader.readSaslMessage();
|
|
45
|
+
serverMessage = reader.readSaslMessage(length);
|
|
46
46
|
if (!params.password)
|
|
47
47
|
throw ErrPasswordRequired;
|
|
48
48
|
const parts = Object.fromEntries(serverMessage.split(',').map(x => x.split('=')));
|
|
@@ -61,7 +61,7 @@ export const createAuthorizedSocket = (writer, params) => {
|
|
|
61
61
|
break;
|
|
62
62
|
}
|
|
63
63
|
case AuthenticationCodes.SASLFinal: {
|
|
64
|
-
reader.readSaslMessage();
|
|
64
|
+
reader.readSaslMessage(length);
|
|
65
65
|
break;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -8,7 +8,7 @@ export declare class SocketConnector {
|
|
|
8
8
|
private _onError;
|
|
9
9
|
private residualBuffer;
|
|
10
10
|
private _isDestroyed;
|
|
11
|
-
constructor(_socket: Socket, _onData: (type: ResponseType, reader: ConnectionResponseReader) => void, _onError: (error: Error) => void);
|
|
11
|
+
constructor(_socket: Socket, _onData: (type: ResponseType, length: number, reader: ConnectionResponseReader) => void, _onError: (error: Error) => void);
|
|
12
12
|
write(writer: ConnectionRequestWriter): void;
|
|
13
13
|
unwrapSocket(): Socket;
|
|
14
14
|
destroy(): void;
|
|
@@ -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;IAKpB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;IANpB,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,YAAY,CAAQ;gBAGhB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,wBAAwB,KAAK,IAAI,
|
|
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;IAKpB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;IANpB,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,YAAY,CAAQ;gBAGhB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,KAAK,IAAI,EACvF,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;IA8B5C,KAAK,CAAC,MAAM,EAAE,uBAAuB;IAOrC,YAAY;IAQZ,OAAO;IAMP,IAAI,WAAW,YAA6B;CAC/C"}
|
|
@@ -18,7 +18,8 @@ export class SocketConnector {
|
|
|
18
18
|
this.residualBuffer = reader.getResidualBuffer();
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const { type, length } = reader.readType();
|
|
22
|
+
this._onData(type, length, reader);
|
|
22
23
|
}
|
|
23
24
|
});
|
|
24
25
|
_socket.on('error', error => {
|
package/dist/query.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { Future } from "fluent-future";
|
|
1
2
|
import { QueryText, StatementName } from "./connection";
|
|
2
3
|
import { ColumnDescription, ValueOF } from "./types";
|
|
4
|
+
import { PostgresError } from "./error";
|
|
3
5
|
export declare const QueryState: {
|
|
4
6
|
readonly Parsing: 0;
|
|
5
7
|
readonly Describing: 1;
|
|
@@ -14,14 +16,31 @@ export declare class Query<T> {
|
|
|
14
16
|
state: State;
|
|
15
17
|
statementName: StatementName;
|
|
16
18
|
columns?: ColumnDescription[] | undefined;
|
|
17
|
-
|
|
19
|
+
future: Future<T[], PostgresError>;
|
|
18
20
|
private _resolve;
|
|
19
21
|
private _reject;
|
|
20
22
|
private _rows;
|
|
23
|
+
private _timer?;
|
|
21
24
|
constructor(text: QueryText, args: (string | null)[], state: State, statementName: StatementName, columns?: ColumnDescription[] | undefined);
|
|
25
|
+
startTimeout(timeout: number): void;
|
|
22
26
|
setState(state: State): void;
|
|
23
27
|
push(value: T): void;
|
|
24
|
-
reject(cause:
|
|
28
|
+
reject(cause: PostgresError): void;
|
|
29
|
+
resolve(): void;
|
|
30
|
+
}
|
|
31
|
+
export declare class StreamQuery<T> {
|
|
32
|
+
text: QueryText;
|
|
33
|
+
args: (string | null)[];
|
|
34
|
+
state: State;
|
|
35
|
+
statementName: StatementName;
|
|
36
|
+
private _controller;
|
|
37
|
+
columns?: ColumnDescription[] | undefined;
|
|
38
|
+
private _timer?;
|
|
39
|
+
constructor(text: QueryText, args: (string | null)[], state: State, statementName: StatementName, _controller: ReadableStreamDefaultController<T>, columns?: ColumnDescription[] | undefined);
|
|
40
|
+
setState(state: State): void;
|
|
41
|
+
startTimeout(timeout: number): void;
|
|
42
|
+
push(value: T): void;
|
|
43
|
+
reject(cause: PostgresError): void;
|
|
25
44
|
resolve(): void;
|
|
26
45
|
}
|
|
27
46
|
//# sourceMappingURL=query.d.ts.map
|
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,eAAO,MAAM,UAAU;;;;;;CAMb,CAAA;AAGV,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,UAAU,CAAC,CAAA;AAG9C,qBAAa,KAAK,CAAC,CAAC;IASL,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE;IACvB,KAAK,EAAE,KAAK;IACZ,aAAa,EAAE,aAAa;IAC5B,OAAO,CAAC,EAAE,iBAAiB,EAAE;IAZxC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,CAAA;IAClC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,KAAK,CAAU;IAEvB,OAAO,CAAC,MAAM,CAAC,CAAgB;gBAGpB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EACvB,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,aAAa,EAC5B,OAAO,CAAC,EAAE,iBAAiB,EAAE,YAAA;IAQxC,YAAY,CAAC,OAAO,EAAE,MAAM;IAO5B,QAAQ,CAAC,KAAK,EAAE,KAAK;IAKrB,IAAI,CAAC,KAAK,EAAE,CAAC;IAKb,MAAM,CAAC,KAAK,EAAE,aAAa;IAM3B,OAAO;CAIV;AAED,qBAAa,WAAW,CAAC,CAAC;IAKX,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE;IACvB,KAAK,EAAE,KAAK;IACZ,aAAa,EAAE,aAAa;IACnC,OAAO,CAAC,WAAW;IACZ,OAAO,CAAC,EAAE,iBAAiB,EAAE;IARxC,OAAO,CAAC,MAAM,CAAC,CAAgB;gBAGpB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EACvB,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,aAAa,EAC3B,WAAW,EAAE,+BAA+B,CAAC,CAAC,CAAC,EAChD,OAAO,CAAC,EAAE,iBAAiB,EAAE,YAAA;IAGxC,QAAQ,CAAC,KAAK,EAAE,KAAK;IAIrB,YAAY,CAAC,OAAO,EAAE,MAAM;IAM5B,IAAI,CAAC,KAAK,EAAE,CAAC;IAIb,MAAM,CAAC,KAAK,EAAE,aAAa;IAK3B,OAAO;CAIV"}
|
package/dist/query.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Future } from "fluent-future";
|
|
2
|
+
import { PostgresError } from "./error";
|
|
1
3
|
export const QueryState = {
|
|
2
4
|
Parsing: 0,
|
|
3
5
|
Describing: 1,
|
|
@@ -13,10 +15,15 @@ export class Query {
|
|
|
13
15
|
this.statementName = statementName;
|
|
14
16
|
this.columns = columns;
|
|
15
17
|
this._rows = [];
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const { future, reject, resolve } = Future.withResolvers();
|
|
19
|
+
this.future = future;
|
|
20
|
+
this._resolve = resolve;
|
|
21
|
+
this._reject = reject;
|
|
22
|
+
}
|
|
23
|
+
startTimeout(timeout) {
|
|
24
|
+
this._timer = setTimeout(() => {
|
|
25
|
+
this.reject(new PostgresError('Query timeout', '57014'));
|
|
26
|
+
}, timeout);
|
|
20
27
|
}
|
|
21
28
|
setState(state) {
|
|
22
29
|
this.state = state;
|
|
@@ -25,9 +32,40 @@ export class Query {
|
|
|
25
32
|
this._rows.push(value);
|
|
26
33
|
}
|
|
27
34
|
reject(cause) {
|
|
35
|
+
clearTimeout(this._timer);
|
|
28
36
|
this._reject(cause);
|
|
29
37
|
}
|
|
30
38
|
resolve() {
|
|
39
|
+
clearTimeout(this._timer);
|
|
31
40
|
this._resolve(this._rows);
|
|
32
41
|
}
|
|
33
42
|
}
|
|
43
|
+
export class StreamQuery {
|
|
44
|
+
constructor(text, args, state, statementName, _controller, columns) {
|
|
45
|
+
this.text = text;
|
|
46
|
+
this.args = args;
|
|
47
|
+
this.state = state;
|
|
48
|
+
this.statementName = statementName;
|
|
49
|
+
this._controller = _controller;
|
|
50
|
+
this.columns = columns;
|
|
51
|
+
}
|
|
52
|
+
setState(state) {
|
|
53
|
+
this.state = state;
|
|
54
|
+
}
|
|
55
|
+
startTimeout(timeout) {
|
|
56
|
+
this._timer = setTimeout(() => {
|
|
57
|
+
this.reject(new PostgresError('Query timeout', '57014'));
|
|
58
|
+
}, timeout);
|
|
59
|
+
}
|
|
60
|
+
push(value) {
|
|
61
|
+
this._controller.enqueue(value);
|
|
62
|
+
}
|
|
63
|
+
reject(cause) {
|
|
64
|
+
clearTimeout(this._timer);
|
|
65
|
+
this._controller.error(cause);
|
|
66
|
+
}
|
|
67
|
+
resolve() {
|
|
68
|
+
clearTimeout(this._timer);
|
|
69
|
+
this._controller.close();
|
|
70
|
+
}
|
|
71
|
+
}
|
package/dist/queue.d.ts
CHANGED
package/dist/queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA,qBAAa,KAAK,CAAC,CAAC;IAChB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAI;IAEpB,IAAI;IAcJ,
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA,qBAAa,KAAK,CAAC,CAAC;IAChB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAI;IAEpB,IAAI;IAcJ,IAAI,OAAO,MAEV;IAED,IAAI,IAAI,MAA+C;IAGvD,IAAI,KAAK,MAKR;IAGD,IAAI,CAAC,IAAI,EAAE,CAAC;IAIZ,IAAI,IAAI,WAEP;IAGD,IAAI,OAAO,YAEV;IAGD,IAAI,MAAM,YAA+C;CAC5D"}
|
package/dist/queue.js
CHANGED
|
@@ -14,10 +14,11 @@ export class Queue {
|
|
|
14
14
|
this._pointer = 0;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
get() {
|
|
17
|
+
get current() {
|
|
18
18
|
return this._queue[this._pointer];
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
get last() { return this._queue[this._queue.length - 1]; }
|
|
21
|
+
get shift() {
|
|
21
22
|
const item = this._queue[this._pointer];
|
|
22
23
|
this.next();
|
|
23
24
|
return item;
|