@m2k-5f/pgtx 2.1.0 → 2.3.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 +66 -13
- package/dist/clauses/abstract.clause.js +1 -5
- package/dist/clauses/array.clause.js +3 -7
- package/dist/clauses/empty.clause.js +3 -7
- package/dist/clauses/exclude.clause.js +2 -6
- package/dist/clauses/fragment.clause.js +4 -8
- package/dist/clauses/iden.caluse.js +2 -6
- package/dist/clauses/index.js +9 -25
- package/dist/clauses/insert.clause.js +2 -6
- package/dist/clauses/literal.clause.js +2 -6
- package/dist/clauses/update.clause.js +2 -6
- package/dist/clauses/where.clause.js +2 -6
- package/dist/connection.d.ts +56 -10
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +220 -117
- package/dist/error.d.ts +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +2 -6
- package/dist/index.js +24 -37
- package/dist/pool.d.ts +20 -6
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +40 -41
- package/dist/protocol/connection-request-writer.js +13 -18
- package/dist/protocol/connection-response-reader.d.ts +5 -0
- package/dist/protocol/connection-response-reader.d.ts.map +1 -1
- package/dist/protocol/connection-response-reader.js +11 -9
- package/dist/protocol/constants.d.ts +1 -0
- package/dist/protocol/constants.d.ts.map +1 -1
- package/dist/protocol/constants.js +6 -8
- package/dist/protocol/socket-authorization.d.ts +5 -1
- package/dist/protocol/socket-authorization.d.ts.map +1 -1
- package/dist/protocol/socket-authorization.js +38 -34
- package/dist/protocol/socket-connector.d.ts.map +1 -1
- package/dist/protocol/socket-connector.js +4 -7
- package/dist/query.js +2 -6
- package/dist/queue.js +1 -5
- package/dist/security/md5.js +4 -8
- package/dist/security/sasl.js +7 -11
- package/dist/transaction.d.ts +7 -5
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +18 -26
- package/dist/types.js +0 -2
- package/dist/utils/template-compiler.js +3 -6
- package/dist/utils/value-parser.js +2 -7
- package/package.json +5 -2
package/dist/connection.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
1
|
+
import { nextTick } from "process";
|
|
2
|
+
import { ConnectionRequestWriter } from "./protocol/connection-request-writer";
|
|
3
|
+
import { createAuthorizedSocket } from "./protocol/socket-authorization";
|
|
4
|
+
import { ResponseTypes } from "./protocol/constants";
|
|
5
|
+
import { parseRowValues } from "./utils/value-parser";
|
|
6
|
+
import { compileSqlTemplate } from "./utils/template-compiler";
|
|
7
|
+
import { Transaction } from "./transaction";
|
|
8
|
+
import { SocketConnector } from "./protocol/socket-connector";
|
|
9
|
+
import { Queue } from "./queue";
|
|
10
|
+
import { Query, QueryState } from "./query";
|
|
11
|
+
import { sql } from ".";
|
|
12
|
+
import { Begin, Future, Resolve } from 'fluent-future';
|
|
13
|
+
import { PostgresError } from "./error";
|
|
14
|
+
const ErrConnectionClosed = new PostgresError("Connection is closed", 'connection_closed', "", "ERROR");
|
|
15
|
+
const ErrConnectionReconnecring = new PostgresError("Connection are reconnecting", "connection_reconnecting", "", "ERROR");
|
|
15
16
|
/**
|
|
16
17
|
* Represents a single dedicated connection to the PostgreSQL database.
|
|
17
18
|
*
|
|
@@ -42,23 +43,28 @@ const ErrConnectionDead = new Error("Connection is Dead");
|
|
|
42
43
|
* conn.close()
|
|
43
44
|
* ```
|
|
44
45
|
*/
|
|
45
|
-
class Connection {
|
|
46
|
+
export class Connection {
|
|
46
47
|
_nextStatement() {
|
|
47
48
|
return `s-${this._stmtCounter++}`;
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
+
_checkOpened() {
|
|
51
|
+
if (!this.isOpened)
|
|
52
|
+
throw ErrConnectionClosed;
|
|
53
|
+
}
|
|
54
|
+
constructor(socket, writer, logLevel, params) {
|
|
50
55
|
this._isFlushing = false;
|
|
51
|
-
this.
|
|
52
|
-
this.
|
|
56
|
+
this._isOpened = true;
|
|
57
|
+
this._isReconnecting = false;
|
|
58
|
+
this._pipelinesQueue = new Queue();
|
|
53
59
|
this._described = new Map();
|
|
54
60
|
this._describingPending = new Set();
|
|
55
61
|
this._parsed = new Map();
|
|
56
62
|
this._parsingPending = new Map();
|
|
63
|
+
this._listeningCallbacks = new Map();
|
|
57
64
|
this._stmtCounter = 0;
|
|
65
|
+
this.params = params;
|
|
58
66
|
this._logLevel = logLevel;
|
|
59
|
-
this._socket = new
|
|
60
|
-
this._destroyConnection();
|
|
61
|
-
});
|
|
67
|
+
this._socket = new SocketConnector(socket, (type, reader) => this._handlePacket(type, reader), (err) => this._registerReconnect());
|
|
62
68
|
this._writer = writer;
|
|
63
69
|
}
|
|
64
70
|
/**
|
|
@@ -79,10 +85,10 @@ class Connection {
|
|
|
79
85
|
* })
|
|
80
86
|
* ```
|
|
81
87
|
*/
|
|
82
|
-
static
|
|
83
|
-
const writer =
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
static new(params) {
|
|
89
|
+
const writer = ConnectionRequestWriter.new();
|
|
90
|
+
return createAuthorizedSocket(writer, params)
|
|
91
|
+
.andThen(socket => Resolve(new Connection(socket, writer, params.logLevel || 'error', params)));
|
|
86
92
|
}
|
|
87
93
|
/**
|
|
88
94
|
* Executes a query using tagged template literals.
|
|
@@ -109,127 +115,219 @@ class Connection {
|
|
|
109
115
|
* ```
|
|
110
116
|
*/
|
|
111
117
|
query(templates, ...params) {
|
|
118
|
+
this._checkOpened();
|
|
112
119
|
this._registerFlush();
|
|
113
|
-
|
|
114
|
-
throw ErrConnectionDead;
|
|
115
|
-
const { text, args } = (0, template_compiler_1.compileSqlTemplate)({ templates, args: params });
|
|
120
|
+
const { text, args } = compileSqlTemplate({ templates, args: params });
|
|
116
121
|
if (this._logLevel === 'query') {
|
|
117
122
|
console.log(`\nQUERY: ${text}\n${args.length !== 0 ? `ARGUMENTS: [${args}]\n` : ""}`);
|
|
118
123
|
}
|
|
119
124
|
const query = this._createQuery(text, args);
|
|
120
125
|
this._writeQuery(query);
|
|
121
|
-
return query.promise
|
|
126
|
+
return Future.of(query.promise, error => {
|
|
127
|
+
if (error instanceof PostgresError)
|
|
128
|
+
return error;
|
|
129
|
+
return new PostgresError(error.message);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Starts a managed transaction on this connection.
|
|
134
|
+
*
|
|
135
|
+
* Automatically handles:
|
|
136
|
+
* - `BEGIN` before the callback
|
|
137
|
+
* - `COMMIT` on successful completion
|
|
138
|
+
* - `ROLLBACK` if an error is thrown
|
|
139
|
+
*
|
|
140
|
+
* @param txCallback - Async function that receives a `Transaction` instance
|
|
141
|
+
* @returns The value returned from the callback
|
|
142
|
+
* @throws {Error} If connection is dead or transaction fails
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* const result = await conn.begin(async tx => {
|
|
147
|
+
* await tx.query`INSERT INTO accounts (id, balance) VALUES (1, 100)`
|
|
148
|
+
* await tx.query`UPDATE accounts SET balance = balance - 10 WHERE id = 1`
|
|
149
|
+
* return { success: true }
|
|
150
|
+
* })
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
begin(txCallback) {
|
|
154
|
+
this._checkOpened();
|
|
155
|
+
const tx = new Transaction(this);
|
|
156
|
+
return Begin()
|
|
157
|
+
.andThen(() => tx.query `BEGIN`)
|
|
158
|
+
.andThen(() => Future.of(txCallback(tx))
|
|
159
|
+
.tap(() => {
|
|
160
|
+
if (tx.isActive)
|
|
161
|
+
return tx.commit();
|
|
162
|
+
})
|
|
163
|
+
.tapErr(() => {
|
|
164
|
+
if (tx.isActive)
|
|
165
|
+
return tx.rollback();
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Sends an asynchronous notification to a channel via `pg_notify`.
|
|
170
|
+
*
|
|
171
|
+
* @param channelName - The channel identifier
|
|
172
|
+
* @param payload - Optional string data (max 8000 bytes)
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* await conn.notify('events', 'hello')
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
notify(channelName, payload = "") {
|
|
180
|
+
this._checkOpened();
|
|
181
|
+
return this.query `select pg_notify(${channelName}, ${payload})`;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Subscribes a callback to a channel. Sends `LISTEN` on the first subscription.
|
|
185
|
+
*
|
|
186
|
+
* @param channelName - The channel identifier
|
|
187
|
+
* @param callback - Function invoked when a notification arrives
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```ts
|
|
191
|
+
* await conn.listen('events', data => console.log(data))
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
listen(channelName, callback) {
|
|
195
|
+
this._checkOpened();
|
|
196
|
+
if (!this._listeningCallbacks.has(channelName)) {
|
|
197
|
+
this._listeningCallbacks.set(channelName, new Set());
|
|
198
|
+
}
|
|
199
|
+
const callbackSet = this._listeningCallbacks.get(channelName);
|
|
200
|
+
callbackSet.add(callback);
|
|
201
|
+
return this.query `listen ${sql.ident(channelName)};`;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Unsubscribes a callback. Sends `UNLISTEN` if no callbacks remain for the channel.
|
|
205
|
+
*
|
|
206
|
+
* @param channelName - The channel identifier
|
|
207
|
+
* @param callback - The registered callback to remove
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* await conn.unlisten('events', callback)
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
unlisten(channelName, callback) {
|
|
215
|
+
this._checkOpened();
|
|
216
|
+
if (!this._listeningCallbacks.has(channelName)) {
|
|
217
|
+
return Resolve([]);
|
|
218
|
+
}
|
|
219
|
+
const callbackSet = this._listeningCallbacks.get(channelName);
|
|
220
|
+
callbackSet.delete(callback);
|
|
221
|
+
if (callbackSet.size === 0) {
|
|
222
|
+
this._listeningCallbacks.delete(channelName);
|
|
223
|
+
return this.query `unlisten ${sql.ident(channelName)};`;
|
|
224
|
+
}
|
|
225
|
+
return Resolve([]);
|
|
122
226
|
}
|
|
123
227
|
_createQuery(text, args) {
|
|
124
228
|
if (this._parsed.has(text)) {
|
|
125
229
|
const statementName = this._parsed.get(text);
|
|
126
230
|
if (this._described.has(statementName)) {
|
|
127
231
|
const columns = this._described.get(statementName);
|
|
128
|
-
return new
|
|
232
|
+
return new Query(text, args, QueryState.Executing, statementName, columns);
|
|
129
233
|
}
|
|
130
234
|
else {
|
|
131
235
|
if (this._describingPending.has(statementName)) {
|
|
132
|
-
return new
|
|
236
|
+
return new Query(text, args, QueryState.Executing, statementName);
|
|
133
237
|
}
|
|
134
238
|
else {
|
|
135
239
|
this._describingPending.add(statementName);
|
|
136
|
-
return new
|
|
240
|
+
return new Query(text, args, QueryState.Describing, statementName);
|
|
137
241
|
}
|
|
138
242
|
}
|
|
139
243
|
}
|
|
140
244
|
else {
|
|
141
245
|
if (this._parsingPending.has(text)) {
|
|
142
246
|
const statementName = this._parsingPending.get(text);
|
|
143
|
-
return new
|
|
247
|
+
return new Query(text, args, QueryState.Describing, statementName);
|
|
144
248
|
}
|
|
145
249
|
else {
|
|
146
250
|
const statementName = this._nextStatement();
|
|
147
251
|
this._parsingPending.set(text, statementName);
|
|
148
|
-
return new
|
|
252
|
+
return new Query(text, args, QueryState.Parsing, statementName);
|
|
149
253
|
}
|
|
150
254
|
}
|
|
151
255
|
}
|
|
152
256
|
_writeQuery(query) {
|
|
153
|
-
if (query.state ===
|
|
257
|
+
if (query.state === QueryState.Parsing) {
|
|
154
258
|
this._writer
|
|
155
259
|
.writeParse(query.statementName, query.text)
|
|
156
260
|
.writeDescribe(query.statementName)
|
|
157
261
|
.writeBind("", query.statementName, query.args)
|
|
158
262
|
.writeExecute("");
|
|
159
263
|
}
|
|
160
|
-
if (query.state ===
|
|
264
|
+
if (query.state === QueryState.Describing) {
|
|
161
265
|
this._writer
|
|
162
266
|
.writeDescribe(query.statementName)
|
|
163
267
|
.writeBind("", query.statementName, query.args)
|
|
164
268
|
.writeExecute("");
|
|
165
269
|
}
|
|
166
|
-
if (query.state ===
|
|
270
|
+
if (query.state === QueryState.Executing) {
|
|
167
271
|
this._writer
|
|
168
272
|
.writeBind("", query.statementName, query.args)
|
|
169
273
|
.writeExecute("");
|
|
170
274
|
}
|
|
171
275
|
this._pipelinesQueue.get().push(query);
|
|
172
276
|
}
|
|
173
|
-
/**
|
|
174
|
-
* Starts a managed transaction on this connection.
|
|
175
|
-
*
|
|
176
|
-
* Automatically handles:
|
|
177
|
-
* - `BEGIN` before the callback
|
|
178
|
-
* - `COMMIT` on successful completion
|
|
179
|
-
* - `ROLLBACK` if an error is thrown
|
|
180
|
-
*
|
|
181
|
-
* @param txCallback - Async function that receives a `Transaction` instance
|
|
182
|
-
* @returns The value returned from the callback
|
|
183
|
-
* @throws {Error} If connection is dead or transaction fails
|
|
184
|
-
*
|
|
185
|
-
* @example
|
|
186
|
-
* ```ts
|
|
187
|
-
* const result = await conn.begin(async tx => {
|
|
188
|
-
* await tx.query`INSERT INTO accounts (id, balance) VALUES (1, 100)`
|
|
189
|
-
* await tx.query`UPDATE accounts SET balance = balance - 10 WHERE id = 1`
|
|
190
|
-
* return { success: true }
|
|
191
|
-
* })
|
|
192
|
-
* ```
|
|
193
|
-
*/
|
|
194
|
-
async begin(txCallback) {
|
|
195
|
-
if (!this._isAlive)
|
|
196
|
-
throw ErrConnectionDead;
|
|
197
|
-
const tx = new transaction_1.Transaction(this);
|
|
198
|
-
try {
|
|
199
|
-
await tx.query `BEGIN`;
|
|
200
|
-
const result = await txCallback(tx);
|
|
201
|
-
if (tx.isActive)
|
|
202
|
-
await tx.commit();
|
|
203
|
-
return result;
|
|
204
|
-
}
|
|
205
|
-
catch (err) {
|
|
206
|
-
if (tx.isActive)
|
|
207
|
-
await tx.rollback();
|
|
208
|
-
throw err;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
277
|
_registerFlush() {
|
|
212
278
|
if (!this._isFlushing) {
|
|
213
279
|
this._isFlushing = true;
|
|
214
|
-
this._pipelinesQueue.push(new
|
|
215
|
-
|
|
280
|
+
this._pipelinesQueue.push(new Queue());
|
|
281
|
+
nextTick(() => {
|
|
216
282
|
this._flush();
|
|
217
283
|
});
|
|
218
284
|
}
|
|
219
285
|
}
|
|
220
286
|
_flush() {
|
|
221
|
-
this.
|
|
222
|
-
|
|
223
|
-
this._rejectPipeline(ErrConnectionDead);
|
|
287
|
+
if (!this._isOpened) {
|
|
288
|
+
this._rejectPipeline(ErrConnectionClosed);
|
|
224
289
|
return;
|
|
225
290
|
}
|
|
226
|
-
|
|
291
|
+
if (this._isReconnecting) {
|
|
292
|
+
this._reconnect().then(() => {
|
|
293
|
+
this._isFlushing = false;
|
|
294
|
+
this._socket.write(this._writer.writeSync());
|
|
295
|
+
this._writer.clear();
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
this._isFlushing = false;
|
|
227
300
|
this._socket.write(this._writer.writeSync());
|
|
228
301
|
this._writer.clear();
|
|
229
302
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
303
|
+
}
|
|
304
|
+
_registerReconnect() {
|
|
305
|
+
this._isReconnecting = true;
|
|
306
|
+
this._rejectPipeline(ErrConnectionReconnecring);
|
|
307
|
+
}
|
|
308
|
+
_resetConnectionState(cause) {
|
|
309
|
+
this._parsed.clear();
|
|
310
|
+
this._described.clear();
|
|
311
|
+
this._describingPending.clear();
|
|
312
|
+
this._parsingPending.clear();
|
|
313
|
+
this._writer.clear();
|
|
314
|
+
this._rejectPipeline(cause);
|
|
315
|
+
}
|
|
316
|
+
async _reconnect() {
|
|
317
|
+
this._resetConnectionState(ErrConnectionReconnecring);
|
|
318
|
+
const socket = await createAuthorizedSocket(ConnectionRequestWriter.new(), this.params);
|
|
319
|
+
const connector = new SocketConnector(socket, (type, reader) => this._handlePacket(type, reader), (err) => this._registerReconnect());
|
|
320
|
+
this._socket = connector;
|
|
321
|
+
void this._restoreSubscriptions();
|
|
322
|
+
this._isReconnecting = false;
|
|
323
|
+
}
|
|
324
|
+
_restoreSubscriptions() {
|
|
325
|
+
if (this._listeningCallbacks.size === 0)
|
|
326
|
+
return Promise.resolve();
|
|
327
|
+
const promises = Array.from(this._listeningCallbacks.keys()).map(channel => {
|
|
328
|
+
return this.query `LISTEN ${sql.ident(channel)};`;
|
|
329
|
+
});
|
|
330
|
+
return Promise.all(promises);
|
|
233
331
|
}
|
|
234
332
|
_getCurrentQuery() {
|
|
235
333
|
return this._pipelinesQueue.get().get();
|
|
@@ -245,76 +343,76 @@ class Connection {
|
|
|
245
343
|
}
|
|
246
344
|
_handlePacket(type, reader) {
|
|
247
345
|
switch (type) {
|
|
248
|
-
case
|
|
346
|
+
case ResponseTypes.ParseComplete:
|
|
249
347
|
{
|
|
250
348
|
reader.readParseComplete();
|
|
251
349
|
const query = this._getCurrentQuery();
|
|
252
350
|
this._parsingPending.delete(query.text);
|
|
253
351
|
this._parsed.set(query.text, query.statementName);
|
|
254
|
-
query.state =
|
|
352
|
+
query.state = QueryState.Describing;
|
|
255
353
|
}
|
|
256
354
|
break;
|
|
257
|
-
case
|
|
355
|
+
case ResponseTypes.BindComplete:
|
|
258
356
|
{
|
|
259
357
|
reader.readBindComplete();
|
|
260
358
|
}
|
|
261
359
|
break;
|
|
262
|
-
case
|
|
360
|
+
case ResponseTypes.CloseComplete:
|
|
263
361
|
{
|
|
264
362
|
reader.readBindComplete();
|
|
265
363
|
}
|
|
266
364
|
break;
|
|
267
|
-
case
|
|
365
|
+
case ResponseTypes.ParameterDescription:
|
|
268
366
|
{
|
|
269
367
|
reader.readParameterDescription();
|
|
270
368
|
}
|
|
271
369
|
break;
|
|
272
|
-
case
|
|
370
|
+
case ResponseTypes.NoData:
|
|
273
371
|
{
|
|
274
372
|
reader.readNoData();
|
|
275
373
|
const query = this._getCurrentQuery();
|
|
276
374
|
this._describingPending.delete(query.statementName);
|
|
277
375
|
this._described.set(query.statementName, []);
|
|
278
|
-
query.state =
|
|
376
|
+
query.state = QueryState.Executing;
|
|
279
377
|
}
|
|
280
378
|
break;
|
|
281
|
-
case
|
|
379
|
+
case ResponseTypes.RowDescription:
|
|
282
380
|
{
|
|
283
381
|
const columns = reader.readRowDescription();
|
|
284
382
|
const query = this._getCurrentQuery();
|
|
285
383
|
this._describingPending.delete(query.statementName);
|
|
286
384
|
this._described.set(query.statementName, columns);
|
|
287
|
-
query.state =
|
|
385
|
+
query.state = QueryState.Executing;
|
|
288
386
|
query.columns = columns;
|
|
289
387
|
}
|
|
290
388
|
break;
|
|
291
|
-
case
|
|
389
|
+
case ResponseTypes.DataRow:
|
|
292
390
|
{
|
|
293
391
|
const query = this._getCurrentQuery();
|
|
294
392
|
query.rows.push(reader.readDataRow());
|
|
295
393
|
}
|
|
296
394
|
break;
|
|
297
|
-
case
|
|
395
|
+
case ResponseTypes.ComandComplete:
|
|
298
396
|
{
|
|
299
397
|
reader.readCommandComplete();
|
|
300
398
|
if (this._pipelinesQueue.isFree) {
|
|
301
|
-
this.
|
|
399
|
+
this.close();
|
|
302
400
|
break;
|
|
303
401
|
}
|
|
304
402
|
const query = this._getCurrentQuery();
|
|
305
403
|
if (!query) {
|
|
306
|
-
this.
|
|
404
|
+
this.close();
|
|
307
405
|
break;
|
|
308
406
|
}
|
|
309
407
|
if (!query.columns) {
|
|
310
408
|
query.columns = this._described.get(query.statementName);
|
|
311
409
|
}
|
|
312
|
-
query.state =
|
|
410
|
+
query.state = QueryState.Completed;
|
|
313
411
|
this._pipelinesQueue.get().next();
|
|
314
|
-
query.resolve(
|
|
412
|
+
query.resolve(parseRowValues(query.columns, query.rows));
|
|
315
413
|
}
|
|
316
414
|
break;
|
|
317
|
-
case
|
|
415
|
+
case ResponseTypes.ErrorResponse:
|
|
318
416
|
{
|
|
319
417
|
const error = reader.readErrorResponse();
|
|
320
418
|
if (this._logLevel === 'error' || this._logLevel === 'notice' || this._logLevel === 'query') {
|
|
@@ -322,18 +420,18 @@ class Connection {
|
|
|
322
420
|
}
|
|
323
421
|
const query = this._getCurrentQuery();
|
|
324
422
|
switch (query.state) {
|
|
325
|
-
case
|
|
423
|
+
case QueryState.Parsing:
|
|
326
424
|
this._parsingPending.delete(query.text);
|
|
327
425
|
break;
|
|
328
|
-
case
|
|
426
|
+
case QueryState.Describing:
|
|
329
427
|
this._describingPending.delete(query.statementName);
|
|
330
428
|
break;
|
|
331
429
|
}
|
|
332
|
-
query.state =
|
|
430
|
+
query.state = QueryState.Failed;
|
|
333
431
|
this._rejectPipeline(error);
|
|
334
432
|
}
|
|
335
433
|
break;
|
|
336
|
-
case
|
|
434
|
+
case ResponseTypes.ReadyForQuery:
|
|
337
435
|
{
|
|
338
436
|
reader.readReadyForQuery();
|
|
339
437
|
const pipeline = this._pipelinesQueue.get();
|
|
@@ -342,7 +440,7 @@ class Connection {
|
|
|
342
440
|
}
|
|
343
441
|
}
|
|
344
442
|
break;
|
|
345
|
-
case
|
|
443
|
+
case ResponseTypes.Notice:
|
|
346
444
|
{
|
|
347
445
|
const message = reader.readErrorResponse();
|
|
348
446
|
if (this._logLevel === 'notice' || this._logLevel === 'query') {
|
|
@@ -350,6 +448,15 @@ class Connection {
|
|
|
350
448
|
}
|
|
351
449
|
}
|
|
352
450
|
break;
|
|
451
|
+
case ResponseTypes.NotificationResponse:
|
|
452
|
+
{
|
|
453
|
+
const { name, payload } = reader.readNotificationResponse();
|
|
454
|
+
const callbackSet = this._listeningCallbacks.get(name);
|
|
455
|
+
if (!callbackSet)
|
|
456
|
+
break;
|
|
457
|
+
callbackSet.forEach(cb => cb(payload));
|
|
458
|
+
}
|
|
459
|
+
break;
|
|
353
460
|
default: console.warn('Undeclared response type: ', type);
|
|
354
461
|
}
|
|
355
462
|
}
|
|
@@ -357,16 +464,8 @@ class Connection {
|
|
|
357
464
|
* Checks if the connection is still alive and usable.
|
|
358
465
|
* Returns `false` if the socket is destroyed or connection is dead.
|
|
359
466
|
*/
|
|
360
|
-
get
|
|
361
|
-
return this.
|
|
362
|
-
}
|
|
363
|
-
_destroyConnection() {
|
|
364
|
-
this._isAlive = false;
|
|
365
|
-
this._socket.destroy();
|
|
366
|
-
while (this._pipelinesQueue.hasMore) {
|
|
367
|
-
this._rejectPipeline(ErrConnectionDead);
|
|
368
|
-
this._pipelinesQueue.next();
|
|
369
|
-
}
|
|
467
|
+
get isOpened() {
|
|
468
|
+
return this._isOpened;
|
|
370
469
|
}
|
|
371
470
|
/**
|
|
372
471
|
* Closes the connection immediately.
|
|
@@ -379,7 +478,11 @@ class Connection {
|
|
|
379
478
|
* ```
|
|
380
479
|
*/
|
|
381
480
|
close() {
|
|
382
|
-
this.
|
|
481
|
+
this._isOpened = false;
|
|
482
|
+
this._socket.destroy();
|
|
483
|
+
while (this._pipelinesQueue.hasMore) {
|
|
484
|
+
this._rejectPipeline(ErrConnectionClosed);
|
|
485
|
+
this._pipelinesQueue.next();
|
|
486
|
+
}
|
|
383
487
|
}
|
|
384
488
|
}
|
|
385
|
-
exports.Connection = Connection;
|
package/dist/error.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export declare class PostgresError extends Error {
|
|
|
8
8
|
position: string;
|
|
9
9
|
dataType: string;
|
|
10
10
|
constraint: string;
|
|
11
|
-
constructor(message: string, code
|
|
11
|
+
constructor(message: string, code?: string, detail?: string, severity?: string, where?: string, hint?: string, position?: string, dataType?: string, constraint?: string);
|
|
12
12
|
get isParseError(): boolean;
|
|
13
13
|
get isDeadlock(): boolean;
|
|
14
14
|
get isConstraintViolation(): boolean;
|
package/dist/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;IAEhB,OAAO,EAAE,MAAM;IACxB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;gBART,OAAO,EAAE,MAAM,EACxB,IAAI,
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;IAEhB,OAAO,EAAE,MAAM;IACxB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;gBART,OAAO,EAAE,MAAM,EACxB,IAAI,GAAE,MAAqB,EAC3B,MAAM,GAAE,MAAW,EACnB,QAAQ,GAAE,MAAW,EACrB,KAAK,GAAE,MAAW,EAClB,IAAI,GAAE,MAAW,EACjB,QAAQ,GAAE,MAAW,EACrB,QAAQ,GAAE,MAAW,EACrB,UAAU,GAAE,MAAW;IAQlC,IAAI,YAAY,IAAI,OAAO,CAE1B;IAID,IAAI,UAAU,IAAI,OAAO,CAExB;IAID,IAAI,qBAAqB,IAAI,OAAO,CAEnC;IAGD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAGD,IAAI,mBAAmB,IAAI,OAAO,CAEjC;CACJ"}
|
package/dist/error.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.PostgresError = void 0;
|
|
4
|
-
class PostgresError extends Error {
|
|
5
|
-
constructor(message, code, detail, severity, where, hint, position, dataType, constraint) {
|
|
1
|
+
export class PostgresError extends Error {
|
|
2
|
+
constructor(message, code = 'undeclared', detail = '', severity = '', where = '', hint = '', position = '', dataType = '', constraint = '') {
|
|
6
3
|
super(message);
|
|
7
4
|
this.message = message;
|
|
8
5
|
this.code = code;
|
|
@@ -34,4 +31,3 @@ class PostgresError extends Error {
|
|
|
34
31
|
return this.code.startsWith('08') || this.code.startsWith('57') && this.code !== '57014';
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
|
-
exports.PostgresError = PostgresError;
|