@m2k-5f/pgtx 2.2.0 → 2.3.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 +372 -307
- 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 +11 -7
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +108 -111
- 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 +9 -7
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +29 -42
- package/dist/protocol/connection-request-writer.js +13 -18
- package/dist/protocol/connection-response-reader.js +4 -9
- package/dist/protocol/constants.js +4 -7
- 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.js +3 -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 +9 -2
package/dist/pool.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Connection, ConnectionParams } from "./connection";
|
|
2
2
|
import { Transaction } from "./transaction";
|
|
3
|
+
import { Future } from "fluent-future";
|
|
4
|
+
import { PostgresError } from "./error";
|
|
3
5
|
type PoolParams = ConnectionParams & {
|
|
4
6
|
max?: number;
|
|
5
7
|
};
|
|
@@ -35,7 +37,7 @@ type PoolParams = ConnectionParams & {
|
|
|
35
37
|
* }
|
|
36
38
|
*
|
|
37
39
|
* // Clean up
|
|
38
|
-
*
|
|
40
|
+
* pool.close()
|
|
39
41
|
* ```
|
|
40
42
|
*/
|
|
41
43
|
export declare class Pool {
|
|
@@ -65,7 +67,7 @@ export declare class Pool {
|
|
|
65
67
|
* }
|
|
66
68
|
* ```
|
|
67
69
|
*/
|
|
68
|
-
acquire():
|
|
70
|
+
acquire(): Future<Connection, Error>;
|
|
69
71
|
/**
|
|
70
72
|
* Releases the connection back to the pool.
|
|
71
73
|
*
|
|
@@ -103,7 +105,7 @@ export declare class Pool {
|
|
|
103
105
|
* })
|
|
104
106
|
* ```
|
|
105
107
|
*/
|
|
106
|
-
begin<T>(txCallback: (transaction: Transaction) => Promise<T>):
|
|
108
|
+
begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Future<T, Error>;
|
|
107
109
|
/**
|
|
108
110
|
* Executes a one-off query using pipeline.
|
|
109
111
|
*
|
|
@@ -127,7 +129,7 @@ export declare class Pool {
|
|
|
127
129
|
* const users = await pool.query<User>`SELECT * FROM users`
|
|
128
130
|
* ```
|
|
129
131
|
*/
|
|
130
|
-
query<T extends Record<string, any>>(templates: TemplateStringsArray, ...args: any[]):
|
|
132
|
+
query<T extends Record<string, any>>(templates: TemplateStringsArray, ...args: any[]): Future<T[], Error>;
|
|
131
133
|
/**
|
|
132
134
|
* Sends an asynchronous notification to a channel via `pg_notify`.
|
|
133
135
|
*
|
|
@@ -139,7 +141,7 @@ export declare class Pool {
|
|
|
139
141
|
* await pool.notify('events', 'hello')
|
|
140
142
|
* ```
|
|
141
143
|
*/
|
|
142
|
-
notify(channelName: string, payload?: string):
|
|
144
|
+
notify(channelName: string, payload?: string): Future<[], PostgresError>;
|
|
143
145
|
/**
|
|
144
146
|
* Number of available (idle) connections in the pool.
|
|
145
147
|
*/
|
|
@@ -157,10 +159,10 @@ export declare class Pool {
|
|
|
157
159
|
*
|
|
158
160
|
* @example
|
|
159
161
|
* ```ts
|
|
160
|
-
*
|
|
162
|
+
* pool.close()
|
|
161
163
|
* ```
|
|
162
164
|
*/
|
|
163
|
-
close():
|
|
165
|
+
close(): void;
|
|
164
166
|
}
|
|
165
167
|
export {};
|
|
166
168
|
//# sourceMappingURL=pool.d.ts.map
|
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;
|
|
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,EAAE,MAAM,EAAW,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;IA0BP;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU;IAoBxB;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAW7D;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;IAiCpF;;;;;;;;;;OAUG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GACuB,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC;IAIhG;;OAEG;IACH,IAAI,IAAI,WAEP;IAGD;;;OAGG;IACH,IAAI,KAAK,WAER;IAGD;;;;;;;;;;OAUG;IACH,KAAK;CAeR"}
|
package/dist/pool.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const connection_1 = require("./connection");
|
|
5
|
-
const queue_1 = require("./queue");
|
|
1
|
+
import { Connection } from "./connection";
|
|
2
|
+
import { Queue } from "./queue";
|
|
3
|
+
import { Future, Resolve } from "fluent-future";
|
|
6
4
|
/**
|
|
7
5
|
* The main entry point for Pgtx.
|
|
8
6
|
* Manages a connection pool and provides high-level API for queries and transactions.
|
|
@@ -35,18 +33,18 @@ const queue_1 = require("./queue");
|
|
|
35
33
|
* }
|
|
36
34
|
*
|
|
37
35
|
* // Clean up
|
|
38
|
-
*
|
|
36
|
+
* pool.close()
|
|
39
37
|
* ```
|
|
40
38
|
*/
|
|
41
|
-
class Pool {
|
|
39
|
+
export class Pool {
|
|
42
40
|
_checkClosed() {
|
|
43
41
|
if (this._isClosed)
|
|
44
42
|
throw new Error('Pool closed');
|
|
45
43
|
}
|
|
46
44
|
constructor(params) {
|
|
47
|
-
this._available = new
|
|
45
|
+
this._available = new Queue();
|
|
48
46
|
this._total = 0;
|
|
49
|
-
this._waiting = new
|
|
47
|
+
this._waiting = new Queue();
|
|
50
48
|
this._isClosed = false;
|
|
51
49
|
this._config = params;
|
|
52
50
|
this._max = params.max || 20;
|
|
@@ -69,29 +67,24 @@ class Pool {
|
|
|
69
67
|
* }
|
|
70
68
|
* ```
|
|
71
69
|
*/
|
|
72
|
-
|
|
70
|
+
acquire() {
|
|
73
71
|
this._checkClosed();
|
|
74
72
|
while (this._available.hasMore) {
|
|
75
73
|
const conn = this._available.get();
|
|
76
74
|
this._available.next();
|
|
77
75
|
if (conn.isOpened) {
|
|
78
|
-
return conn;
|
|
76
|
+
return Resolve(conn);
|
|
79
77
|
}
|
|
80
78
|
this._total--;
|
|
81
79
|
}
|
|
82
80
|
if (this._total < this._max) {
|
|
83
81
|
this._total++;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
catch (err) {
|
|
88
|
-
this._total--;
|
|
89
|
-
throw err;
|
|
90
|
-
}
|
|
82
|
+
return Future.of(Connection.new(this._config))
|
|
83
|
+
.tapErr(() => this._total--);
|
|
91
84
|
}
|
|
92
|
-
return new Promise((resolve, reject) => {
|
|
85
|
+
return Future.of(new Promise((resolve, reject) => {
|
|
93
86
|
this._waiting.push({ resolve, reject });
|
|
94
|
-
});
|
|
87
|
+
}));
|
|
95
88
|
}
|
|
96
89
|
/**
|
|
97
90
|
* Releases the connection back to the pool.
|
|
@@ -143,15 +136,11 @@ class Pool {
|
|
|
143
136
|
* })
|
|
144
137
|
* ```
|
|
145
138
|
*/
|
|
146
|
-
|
|
139
|
+
begin(txCallback) {
|
|
147
140
|
this._checkClosed();
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
finally {
|
|
153
|
-
this.release(conn);
|
|
154
|
-
}
|
|
141
|
+
return this.acquire()
|
|
142
|
+
.andThen(conn => conn.begin(txCallback)
|
|
143
|
+
.finally(() => this.release(conn)));
|
|
155
144
|
}
|
|
156
145
|
/**
|
|
157
146
|
* Executes a one-off query using pipeline.
|
|
@@ -180,26 +169,25 @@ class Pool {
|
|
|
180
169
|
this._checkClosed();
|
|
181
170
|
while (this._available.hasMore) {
|
|
182
171
|
const conn = this._available.get();
|
|
183
|
-
if (conn.isOpened) {
|
|
184
|
-
return conn.query(templates, ...args);
|
|
185
|
-
}
|
|
186
172
|
this._available.next();
|
|
187
|
-
|
|
173
|
+
if (!conn.isOpened) {
|
|
174
|
+
this._total--;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
this._available.push(conn);
|
|
178
|
+
return conn.query(templates, ...args);
|
|
188
179
|
}
|
|
189
180
|
if (this._total < this._max) {
|
|
190
181
|
this._total++;
|
|
191
|
-
return
|
|
192
|
-
.
|
|
193
|
-
|
|
194
|
-
throw err;
|
|
195
|
-
})
|
|
196
|
-
.then(conn => {
|
|
182
|
+
return Future.of(Connection.new(this._config))
|
|
183
|
+
.tapErr(() => this._total--)
|
|
184
|
+
.andThen(conn => {
|
|
197
185
|
this.release(conn);
|
|
198
186
|
return conn.query(templates, ...args);
|
|
199
187
|
});
|
|
200
188
|
}
|
|
201
189
|
return this.acquire()
|
|
202
|
-
.
|
|
190
|
+
.andThen(conn => {
|
|
203
191
|
this.release(conn);
|
|
204
192
|
return conn.query(templates, ...args);
|
|
205
193
|
});
|
|
@@ -239,10 +227,10 @@ class Pool {
|
|
|
239
227
|
*
|
|
240
228
|
* @example
|
|
241
229
|
* ```ts
|
|
242
|
-
*
|
|
230
|
+
* pool.close()
|
|
243
231
|
* ```
|
|
244
232
|
*/
|
|
245
|
-
|
|
233
|
+
close() {
|
|
246
234
|
while (this._available.hasMore) {
|
|
247
235
|
const conn = this._available.get();
|
|
248
236
|
this._available.next();
|
|
@@ -256,4 +244,3 @@ class Pool {
|
|
|
256
244
|
this._total = 0;
|
|
257
245
|
}
|
|
258
246
|
}
|
|
259
|
-
exports.Pool = Pool;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.ConnectionRequestWriter = exports.ConnectionRequestBuffer = void 0;
|
|
4
|
-
const constants_1 = require("./constants");
|
|
5
|
-
class ConnectionRequestBuffer {
|
|
1
|
+
import { RequestTypes } from "./constants";
|
|
2
|
+
export class ConnectionRequestBuffer {
|
|
6
3
|
constructor(buffer, offset = 0, lastRequestLenByteOffset = 0) {
|
|
7
4
|
this.buffer = buffer;
|
|
8
5
|
this.offset = offset;
|
|
@@ -75,8 +72,7 @@ class ConnectionRequestBuffer {
|
|
|
75
72
|
this.lastRequestLenByteOffset = 0;
|
|
76
73
|
}
|
|
77
74
|
}
|
|
78
|
-
|
|
79
|
-
class ConnectionRequestWriter {
|
|
75
|
+
export class ConnectionRequestWriter {
|
|
80
76
|
constructor(buffer) {
|
|
81
77
|
this.buffer = buffer;
|
|
82
78
|
}
|
|
@@ -84,13 +80,13 @@ class ConnectionRequestWriter {
|
|
|
84
80
|
return new ConnectionRequestWriter(ConnectionRequestBuffer.new(65536));
|
|
85
81
|
}
|
|
86
82
|
writeQuery(text) {
|
|
87
|
-
this.buffer.startRequest(
|
|
83
|
+
this.buffer.startRequest(RequestTypes.SimpleQuery)
|
|
88
84
|
.writeCString(text)
|
|
89
85
|
.endRequest();
|
|
90
86
|
return this;
|
|
91
87
|
}
|
|
92
88
|
writeParse(name, text) {
|
|
93
|
-
this.buffer.startRequest(
|
|
89
|
+
this.buffer.startRequest(RequestTypes.Parse)
|
|
94
90
|
.writeCString(name)
|
|
95
91
|
.writeCString(text)
|
|
96
92
|
.writeInt16(0)
|
|
@@ -98,14 +94,14 @@ class ConnectionRequestWriter {
|
|
|
98
94
|
return this;
|
|
99
95
|
}
|
|
100
96
|
writeDescribe(statementName) {
|
|
101
|
-
this.buffer.startRequest(
|
|
97
|
+
this.buffer.startRequest(RequestTypes.Describe)
|
|
102
98
|
.writeChar('S')
|
|
103
99
|
.writeCString(statementName)
|
|
104
100
|
.endRequest();
|
|
105
101
|
return this;
|
|
106
102
|
}
|
|
107
103
|
writeBind(portName, statementName, params) {
|
|
108
|
-
const request = this.buffer.startRequest(
|
|
104
|
+
const request = this.buffer.startRequest(RequestTypes.Bind)
|
|
109
105
|
.writeCString(portName)
|
|
110
106
|
.writeCString(statementName)
|
|
111
107
|
.writeInt16(0)
|
|
@@ -118,7 +114,7 @@ class ConnectionRequestWriter {
|
|
|
118
114
|
return this;
|
|
119
115
|
}
|
|
120
116
|
writeClose(name) {
|
|
121
|
-
this.buffer.startRequest(
|
|
117
|
+
this.buffer.startRequest(RequestTypes.Close)
|
|
122
118
|
.writeChar("P")
|
|
123
119
|
.writeCString(name)
|
|
124
120
|
.endRequest();
|
|
@@ -134,24 +130,24 @@ class ConnectionRequestWriter {
|
|
|
134
130
|
return this;
|
|
135
131
|
}
|
|
136
132
|
writeExecute(portName) {
|
|
137
|
-
this.buffer.startRequest(
|
|
133
|
+
this.buffer.startRequest(RequestTypes.Execute)
|
|
138
134
|
.writeCString(portName)
|
|
139
135
|
.writeInt32(0)
|
|
140
136
|
.endRequest();
|
|
141
137
|
return this;
|
|
142
138
|
}
|
|
143
139
|
writeSync() {
|
|
144
|
-
this.buffer.startRequest(
|
|
140
|
+
this.buffer.startRequest(RequestTypes.Sync).endRequest();
|
|
145
141
|
return this;
|
|
146
142
|
}
|
|
147
143
|
writePassword(password) {
|
|
148
|
-
this.buffer.startRequest(
|
|
144
|
+
this.buffer.startRequest(RequestTypes.Password)
|
|
149
145
|
.writeCString(password)
|
|
150
146
|
.endRequest();
|
|
151
147
|
return this;
|
|
152
148
|
}
|
|
153
149
|
writeSaslInitial(mechanism, clientFirstMessage) {
|
|
154
|
-
this.buffer.startRequest(
|
|
150
|
+
this.buffer.startRequest(RequestTypes.Password)
|
|
155
151
|
.writeCString(mechanism)
|
|
156
152
|
.writeInt32(Buffer.byteLength(clientFirstMessage, 'utf-8'))
|
|
157
153
|
.writeString(clientFirstMessage)
|
|
@@ -159,7 +155,7 @@ class ConnectionRequestWriter {
|
|
|
159
155
|
return this;
|
|
160
156
|
}
|
|
161
157
|
writeSaslResponse(clientFinalMessage) {
|
|
162
|
-
this.buffer.startRequest(
|
|
158
|
+
this.buffer.startRequest(RequestTypes.Password)
|
|
163
159
|
.writeString(clientFinalMessage)
|
|
164
160
|
.endRequest();
|
|
165
161
|
return this;
|
|
@@ -172,4 +168,3 @@ class ConnectionRequestWriter {
|
|
|
172
168
|
return this;
|
|
173
169
|
}
|
|
174
170
|
}
|
|
175
|
-
exports.ConnectionRequestWriter = ConnectionRequestWriter;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.ConnectionResponseReader = exports.ConnectionResponseBuffer = void 0;
|
|
4
|
-
const error_1 = require("../error");
|
|
5
|
-
class ConnectionResponseBuffer {
|
|
1
|
+
import { PostgresError } from "../error";
|
|
2
|
+
export class ConnectionResponseBuffer {
|
|
6
3
|
constructor(buffer) {
|
|
7
4
|
this.buffer = buffer;
|
|
8
5
|
this.caret = 0;
|
|
@@ -57,8 +54,7 @@ class ConnectionResponseBuffer {
|
|
|
57
54
|
return this.buffer.subarray(this.caret);
|
|
58
55
|
}
|
|
59
56
|
}
|
|
60
|
-
|
|
61
|
-
class ConnectionResponseReader {
|
|
57
|
+
export class ConnectionResponseReader {
|
|
62
58
|
constructor(buffer) {
|
|
63
59
|
this.buffer = buffer;
|
|
64
60
|
this.currentPacketLength = 0;
|
|
@@ -136,7 +132,7 @@ class ConnectionResponseReader {
|
|
|
136
132
|
break;
|
|
137
133
|
}
|
|
138
134
|
}
|
|
139
|
-
return new
|
|
135
|
+
return new PostgresError(message, code, detail, severity, where, hint, position, dataType, constraint);
|
|
140
136
|
}
|
|
141
137
|
readReadyForQuery() {
|
|
142
138
|
this.buffer.readInt32();
|
|
@@ -225,4 +221,3 @@ class ConnectionResponseReader {
|
|
|
225
221
|
this.buffer.readInt32();
|
|
226
222
|
}
|
|
227
223
|
}
|
|
228
|
-
exports.ConnectionResponseReader = ConnectionResponseReader;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TransactionStatuses = exports.AuthenticationCodes = exports.ResponseTypes = exports.RequestTypes = void 0;
|
|
4
|
-
exports.RequestTypes = {
|
|
1
|
+
export const RequestTypes = {
|
|
5
2
|
SimpleQuery: "Q",
|
|
6
3
|
Parse: "P",
|
|
7
4
|
Bind: "B",
|
|
@@ -11,7 +8,7 @@ exports.RequestTypes = {
|
|
|
11
8
|
Describe: 'D',
|
|
12
9
|
Close: "C"
|
|
13
10
|
};
|
|
14
|
-
|
|
11
|
+
export const ResponseTypes = {
|
|
15
12
|
RowDescription: "T",
|
|
16
13
|
DataRow: "D",
|
|
17
14
|
ComandComplete: "C",
|
|
@@ -29,7 +26,7 @@ exports.ResponseTypes = {
|
|
|
29
26
|
Notice: "N",
|
|
30
27
|
NotificationResponse: "A"
|
|
31
28
|
};
|
|
32
|
-
|
|
29
|
+
export const AuthenticationCodes = {
|
|
33
30
|
Ok: 0,
|
|
34
31
|
CleartextPassword: 3,
|
|
35
32
|
MD5Password: 5,
|
|
@@ -37,7 +34,7 @@ exports.AuthenticationCodes = {
|
|
|
37
34
|
SASLContinue: 11,
|
|
38
35
|
SASLFinal: 12,
|
|
39
36
|
};
|
|
40
|
-
|
|
37
|
+
export const TransactionStatuses = {
|
|
41
38
|
Idle: "I",
|
|
42
39
|
InTransactionBlock: "T",
|
|
43
40
|
FailedTransactionBlock: "E",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Socket } from "node:net";
|
|
2
2
|
import { ConnectionRequestWriter } from "./connection-request-writer";
|
|
3
|
+
import { PostgresError } from "../error";
|
|
4
|
+
import { Future } from "fluent-future";
|
|
3
5
|
export type AuthorizationParams = {
|
|
4
6
|
host: string;
|
|
5
7
|
port: number;
|
|
@@ -7,5 +9,7 @@ export type AuthorizationParams = {
|
|
|
7
9
|
database: string;
|
|
8
10
|
password?: string;
|
|
9
11
|
};
|
|
10
|
-
export declare const
|
|
12
|
+
export declare const ErrNonceMismatch: PostgresError;
|
|
13
|
+
export declare const ErrPasswordRequired: PostgresError;
|
|
14
|
+
export declare const createAuthorizedSocket: (writer: ConnectionRequestWriter, params: AuthorizationParams) => Future<Socket, PostgresError>;
|
|
11
15
|
//# 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;
|
|
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,kCAwHlG,CAAA"}
|
|
@@ -1,85 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { createConnection } from "node:net";
|
|
2
|
+
import { calculateScramAuth, generateNonce } from "../security/sasl";
|
|
3
|
+
import { SocketConnector } from "./socket-connector";
|
|
4
|
+
import { AuthenticationCodes, ResponseTypes } from "./constants";
|
|
5
|
+
import { encryptMd5 } from "../security/md5";
|
|
6
|
+
import { PostgresError } from "../error";
|
|
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 createAuthorizedSocket = (writer, params) => {
|
|
11
|
+
return Future.of(new Promise((resolve, reject) => {
|
|
12
|
+
const nonce = generateNonce();
|
|
12
13
|
let clientMessage = '';
|
|
13
14
|
let serverMessage = '';
|
|
14
|
-
const socket =
|
|
15
|
-
const connector = new
|
|
15
|
+
const socket = createConnection({ host: params.host, port: params.port });
|
|
16
|
+
const connector = new SocketConnector(socket, (type, reader) => {
|
|
16
17
|
writer.clear();
|
|
17
18
|
switch (type) {
|
|
18
|
-
case
|
|
19
|
+
case ResponseTypes.Authentication: {
|
|
19
20
|
switch (reader.readAuthentication()) {
|
|
20
|
-
case
|
|
21
|
-
case
|
|
21
|
+
case AuthenticationCodes.Ok: break;
|
|
22
|
+
case AuthenticationCodes.CleartextPassword: {
|
|
22
23
|
if (!params.password)
|
|
23
|
-
throw
|
|
24
|
+
throw ErrPasswordRequired;
|
|
24
25
|
connector.write(writer.writePassword(params.password));
|
|
25
26
|
break;
|
|
26
27
|
}
|
|
27
|
-
case
|
|
28
|
+
case AuthenticationCodes.MD5Password: {
|
|
28
29
|
const salt = reader.readMD5Salt();
|
|
29
30
|
if (!params.password)
|
|
30
|
-
throw
|
|
31
|
-
const password =
|
|
31
|
+
throw ErrPasswordRequired;
|
|
32
|
+
const password = encryptMd5(params.password, params.user, salt);
|
|
32
33
|
connector.write(writer.writePassword(password));
|
|
33
34
|
break;
|
|
34
35
|
}
|
|
35
|
-
case
|
|
36
|
+
case AuthenticationCodes.SASL: {
|
|
36
37
|
reader.readSaslMechanisms();
|
|
37
38
|
if (!params.password)
|
|
38
|
-
throw
|
|
39
|
+
throw ErrPasswordRequired;
|
|
39
40
|
clientMessage = `n=${params.user},r=${nonce}`;
|
|
40
41
|
connector.write(writer.writeSaslInitial('SCRAM-SHA-256', `n,,${clientMessage}`));
|
|
41
42
|
break;
|
|
42
43
|
}
|
|
43
|
-
case
|
|
44
|
+
case AuthenticationCodes.SASLContinue: {
|
|
44
45
|
serverMessage = reader.readSaslMessage();
|
|
45
46
|
if (!params.password)
|
|
46
|
-
throw
|
|
47
|
+
throw ErrPasswordRequired;
|
|
47
48
|
const parts = Object.fromEntries(serverMessage.split(',').map(x => x.split('=')));
|
|
48
49
|
const serverNonce = parts.r;
|
|
49
50
|
const saltBase64 = parts.s;
|
|
50
51
|
const iterations = parseInt(parts.i, 10);
|
|
51
52
|
if (!serverNonce.startsWith(nonce)) {
|
|
52
53
|
connector.destroy();
|
|
53
|
-
return reject(
|
|
54
|
+
return reject(ErrNonceMismatch);
|
|
54
55
|
}
|
|
55
56
|
const clientFinalMessageWithoutProof = `c=biws,r=${serverNonce}`;
|
|
56
57
|
const authMessage = `${clientMessage},${serverMessage},${clientFinalMessageWithoutProof}`;
|
|
57
|
-
const { clientProof } =
|
|
58
|
+
const { clientProof } = calculateScramAuth(params.password, saltBase64, iterations, authMessage);
|
|
58
59
|
const clientFinalMessage = `${clientFinalMessageWithoutProof},p=${clientProof}`;
|
|
59
60
|
connector.write(writer.writeSaslResponse(clientFinalMessage));
|
|
60
61
|
break;
|
|
61
62
|
}
|
|
62
|
-
case
|
|
63
|
+
case AuthenticationCodes.SASLFinal: {
|
|
63
64
|
reader.readSaslMessage();
|
|
64
65
|
break;
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
break;
|
|
68
69
|
}
|
|
69
|
-
case
|
|
70
|
+
case ResponseTypes.ParamaterStatus: {
|
|
70
71
|
reader.readParameterStatus();
|
|
71
72
|
break;
|
|
72
73
|
}
|
|
73
|
-
case
|
|
74
|
-
const
|
|
74
|
+
case ResponseTypes.ErrorResponse: {
|
|
75
|
+
const error = reader.readErrorResponse();
|
|
75
76
|
connector.destroy();
|
|
76
|
-
reject(
|
|
77
|
+
reject(error);
|
|
77
78
|
return;
|
|
78
79
|
}
|
|
79
|
-
case
|
|
80
|
+
case ResponseTypes.BackendKeyData: {
|
|
80
81
|
reader.readBackendKeyData();
|
|
81
82
|
}
|
|
82
|
-
case
|
|
83
|
+
case ResponseTypes.ReadyForQuery: {
|
|
83
84
|
reader.readReadyForQuery();
|
|
84
85
|
resolve(connector.unwrapSocket());
|
|
85
86
|
return;
|
|
@@ -90,6 +91,9 @@ const createAuthorizedSocket = (writer, params) => {
|
|
|
90
91
|
});
|
|
91
92
|
connector.write(writer.writeStartup(params.user, params.database));
|
|
92
93
|
writer.clear();
|
|
94
|
+
}), error => {
|
|
95
|
+
if (error instanceof PostgresError)
|
|
96
|
+
return error;
|
|
97
|
+
return new PostgresError(error.message);
|
|
93
98
|
});
|
|
94
99
|
};
|
|
95
|
-
exports.createAuthorizedSocket = createAuthorizedSocket;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.SocketConnector = void 0;
|
|
4
|
-
const connection_response_reader_1 = require("../protocol/connection-response-reader");
|
|
5
|
-
class SocketConnector {
|
|
1
|
+
import { ConnectionResponseReader } from '../protocol/connection-response-reader';
|
|
2
|
+
export class SocketConnector {
|
|
6
3
|
constructor(_socket, _onData, _onError) {
|
|
7
4
|
this._socket = _socket;
|
|
8
5
|
this._onData = _onData;
|
|
@@ -15,7 +12,7 @@ class SocketConnector {
|
|
|
15
12
|
? Buffer.concat([this.residualBuffer, buffer])
|
|
16
13
|
: buffer;
|
|
17
14
|
this.residualBuffer = null;
|
|
18
|
-
const reader =
|
|
15
|
+
const reader = ConnectionResponseReader.from(currentBuffer);
|
|
19
16
|
while (reader.hasMore()) {
|
|
20
17
|
if (!reader.hasFullPacket()) {
|
|
21
18
|
this.residualBuffer = reader.getResidualBuffer();
|
|
@@ -46,4 +43,3 @@ class SocketConnector {
|
|
|
46
43
|
}
|
|
47
44
|
get isDestroyed() { return this._isDestroyed; }
|
|
48
45
|
}
|
|
49
|
-
exports.SocketConnector = SocketConnector;
|
package/dist/query.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Query = exports.QueryState = void 0;
|
|
4
|
-
exports.QueryState = {
|
|
1
|
+
export const QueryState = {
|
|
5
2
|
Parsing: 0,
|
|
6
3
|
Describing: 1,
|
|
7
4
|
Executing: 2,
|
|
8
5
|
Completed: 3,
|
|
9
6
|
Failed: 4
|
|
10
7
|
};
|
|
11
|
-
class Query {
|
|
8
|
+
export class Query {
|
|
12
9
|
constructor(text, args, state, statementName, columns) {
|
|
13
10
|
this.text = text;
|
|
14
11
|
this.args = args;
|
|
@@ -25,4 +22,3 @@ class Query {
|
|
|
25
22
|
this.state = state;
|
|
26
23
|
}
|
|
27
24
|
}
|
|
28
|
-
exports.Query = Query;
|
package/dist/queue.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Queue = void 0;
|
|
4
|
-
class Queue {
|
|
1
|
+
export class Queue {
|
|
5
2
|
constructor() {
|
|
6
3
|
this._queue = new Array();
|
|
7
4
|
this._pointer = 0;
|
|
@@ -36,4 +33,3 @@ class Queue {
|
|
|
36
33
|
}
|
|
37
34
|
get isFree() { return this._pointer >= this._queue.length; }
|
|
38
35
|
}
|
|
39
|
-
exports.Queue = Queue;
|
package/dist/security/md5.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const encryptMd5 = (password, user, salt) => {
|
|
6
|
-
const stage1 = (0, crypto_1.createHash)('md5').update(password + user).digest('hex');
|
|
7
|
-
const stage2 = (0, crypto_1.createHash)('md5')
|
|
1
|
+
import { createHash } from "crypto";
|
|
2
|
+
export const encryptMd5 = (password, user, salt) => {
|
|
3
|
+
const stage1 = createHash('md5').update(password + user).digest('hex');
|
|
4
|
+
const stage2 = createHash('md5')
|
|
8
5
|
.update(Buffer.concat([Buffer.from(stage1), salt]))
|
|
9
6
|
.digest('hex');
|
|
10
7
|
return 'md5' + stage2;
|
|
11
8
|
};
|
|
12
|
-
exports.encryptMd5 = encryptMd5;
|
package/dist/security/sasl.js
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
exports.calculateScramAuth = calculateScramAuth;
|
|
5
|
-
const crypto_1 = require("crypto");
|
|
6
|
-
function generateNonce() {
|
|
7
|
-
return (0, crypto_1.randomBytes)(18).toString('base64').replace(/[^a-zA-Z0-9]/g, '').substring(0, 24);
|
|
1
|
+
import { randomBytes, createHmac, pbkdf2Sync, createHash } from 'crypto';
|
|
2
|
+
export function generateNonce() {
|
|
3
|
+
return randomBytes(18).toString('base64').replace(/[^a-zA-Z0-9]/g, '').substring(0, 24);
|
|
8
4
|
}
|
|
9
5
|
function hmac(key, data) {
|
|
10
|
-
return
|
|
6
|
+
return createHmac('sha256', key).update(data).digest();
|
|
11
7
|
}
|
|
12
8
|
function hi(password, salt, iterations) {
|
|
13
|
-
return
|
|
9
|
+
return pbkdf2Sync(password, salt, iterations, 32, 'sha256');
|
|
14
10
|
}
|
|
15
|
-
function calculateScramAuth(password, saltBase64, iterations, authMessage) {
|
|
11
|
+
export function calculateScramAuth(password, saltBase64, iterations, authMessage) {
|
|
16
12
|
const salt = Buffer.from(saltBase64, 'base64');
|
|
17
13
|
const saltedPassword = hi(password, salt, iterations);
|
|
18
14
|
const clientKey = hmac(saltedPassword, 'Client Key');
|
|
19
|
-
const storedKey =
|
|
15
|
+
const storedKey = createHash('sha256').update(clientKey).digest();
|
|
20
16
|
const clientSignature = hmac(storedKey, authMessage);
|
|
21
17
|
const clientProofBuf = Buffer.alloc(32);
|
|
22
18
|
for (let i = 0; i < 32; i++) {
|