@m2k-5f/pgtx 2.7.1 → 2.7.3
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 +48 -31
- package/dist/batch.d.ts +4 -1
- package/dist/batch.d.ts.map +1 -1
- package/dist/batch.js +14 -7
- package/dist/clauses/fragment.clause.js +1 -1
- package/dist/connection.d.ts +17 -16
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +182 -166
- package/dist/error.d.ts +4 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +15 -7
- package/dist/pool.d.ts +1 -1
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +5 -3
- package/dist/protocol/connection-request-writer.d.ts +24 -11
- package/dist/protocol/connection-request-writer.d.ts.map +1 -1
- package/dist/protocol/connection-request-writer.js +217 -47
- package/dist/protocol/connection-response-reader.d.ts +5 -15
- package/dist/protocol/connection-response-reader.d.ts.map +1 -1
- package/dist/protocol/connection-response-reader.js +116 -76
- package/dist/protocol/constants.d.ts +37 -30
- package/dist/protocol/constants.d.ts.map +1 -1
- package/dist/protocol/constants.js +35 -29
- package/dist/protocol/socket-authorization.d.ts.map +1 -1
- package/dist/protocol/socket-authorization.js +7 -7
- package/dist/protocol/socket-connector.d.ts +4 -4
- package/dist/protocol/socket-connector.d.ts.map +1 -1
- package/dist/protocol/socket-connector.js +2 -2
- package/dist/query.d.ts +16 -20
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +15 -22
- package/dist/queue.d.ts +1 -0
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +1 -0
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/template-compiler.d.ts +5 -2
- package/dist/utils/template-compiler.d.ts.map +1 -1
- package/dist/utils/template-compiler.js +4 -1
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +73 -0
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataTypeOids } from "./constants";
|
|
1
|
+
import { DataTypeOids, INT4Length } from "./constants";
|
|
2
2
|
import { PostgresError } from "../error";
|
|
3
3
|
const columnValueCache = new Map();
|
|
4
4
|
const POSTGRES_EPOCH_MS = 946684800000;
|
|
@@ -39,16 +39,14 @@ export class ConnectionResponseBuffer {
|
|
|
39
39
|
hasMore() {
|
|
40
40
|
return this.caret < this.buffer.length;
|
|
41
41
|
}
|
|
42
|
-
readRawBinaryString(length) {
|
|
43
|
-
const text = this.buffer.toString('latin1', this.caret, this.caret + length);
|
|
44
|
-
this.caret += length;
|
|
45
|
-
return text;
|
|
46
|
-
}
|
|
47
42
|
readBinaryDate() {
|
|
48
43
|
const daysSince2000 = this.readInt32();
|
|
49
44
|
const ms = POSTGRES_EPOCH_MS + (daysSince2000 * 86400000);
|
|
50
45
|
return new Date(ms);
|
|
51
46
|
}
|
|
47
|
+
readByte() {
|
|
48
|
+
return this.buffer[this.caret++];
|
|
49
|
+
}
|
|
52
50
|
readBinaryTimestamp() {
|
|
53
51
|
const microSecondsSince2000 = this.readInt64();
|
|
54
52
|
const msSince2000 = Number(microSecondsSince2000 / 1000);
|
|
@@ -94,6 +92,53 @@ export class ConnectionResponseBuffer {
|
|
|
94
92
|
this.caret += 8;
|
|
95
93
|
return (hi * 4294967296) + lo;
|
|
96
94
|
}
|
|
95
|
+
readNumeric() {
|
|
96
|
+
const ndigits = this.readInt16();
|
|
97
|
+
const weight = this.readInt16();
|
|
98
|
+
const sign = this.readInt16();
|
|
99
|
+
const dscale = this.readInt16();
|
|
100
|
+
if (sign === 0xC000 || sign === -16384)
|
|
101
|
+
return 'NaN';
|
|
102
|
+
const digits = new Array(ndigits);
|
|
103
|
+
for (let i = 0; i < ndigits; i++) {
|
|
104
|
+
digits[i] = this.readInt16();
|
|
105
|
+
}
|
|
106
|
+
const highExp = Math.max(weight, 0);
|
|
107
|
+
const lowExp = Math.min(weight - ndigits + 1, -1);
|
|
108
|
+
let intPart = '';
|
|
109
|
+
for (let exp = highExp; exp >= 0; exp--) {
|
|
110
|
+
const idx = weight - exp;
|
|
111
|
+
const digit = (idx >= 0 && idx < ndigits) ? digits[idx] : 0;
|
|
112
|
+
intPart += exp === highExp ? String(digit) : String(digit).padStart(4, '0');
|
|
113
|
+
}
|
|
114
|
+
if (intPart === '')
|
|
115
|
+
intPart = '0';
|
|
116
|
+
let fracPart = '';
|
|
117
|
+
for (let exp = -1; exp >= lowExp; exp--) {
|
|
118
|
+
const idx = weight - exp;
|
|
119
|
+
const digit = (idx >= 0 && idx < ndigits) ? digits[idx] : 0;
|
|
120
|
+
fracPart += String(digit).padStart(4, '0');
|
|
121
|
+
}
|
|
122
|
+
if (dscale > 0) {
|
|
123
|
+
fracPart = fracPart.padEnd(dscale, '0').slice(0, dscale);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
fracPart = '';
|
|
127
|
+
}
|
|
128
|
+
const negative = sign === 0x4000 || sign === 16384;
|
|
129
|
+
const result = fracPart ? `${intPart}.${fracPart}` : intPart;
|
|
130
|
+
return negative ? `-${result}` : result;
|
|
131
|
+
}
|
|
132
|
+
readBinaryTimetz() {
|
|
133
|
+
const time = this.readBinaryTime();
|
|
134
|
+
const zoneOffsetSeconds = this.readInt32();
|
|
135
|
+
const offsetMinutesTotal = -zoneOffsetSeconds / 60;
|
|
136
|
+
const sign = offsetMinutesTotal >= 0 ? '+' : '-';
|
|
137
|
+
const abs = Math.abs(offsetMinutesTotal);
|
|
138
|
+
const offH = Math.floor(abs / 60);
|
|
139
|
+
const offM = abs % 60;
|
|
140
|
+
return `${time}${sign}${String(offH).padStart(2, '0')}:${String(offM).padStart(2, '0')}`;
|
|
141
|
+
}
|
|
97
142
|
readFloat32() {
|
|
98
143
|
const value = this.buffer.readFloatBE(this.caret);
|
|
99
144
|
this.caret += 4;
|
|
@@ -127,33 +172,25 @@ export class ConnectionResponseBuffer {
|
|
|
127
172
|
}
|
|
128
173
|
return hash >>> 0;
|
|
129
174
|
}
|
|
130
|
-
}
|
|
131
|
-
export class ConnectionResponseReader {
|
|
132
|
-
constructor(buffer) {
|
|
133
|
-
this.buffer = buffer;
|
|
134
|
-
}
|
|
135
|
-
static from(buffer) {
|
|
136
|
-
return new ConnectionResponseReader(ConnectionResponseBuffer.from(buffer));
|
|
137
|
-
}
|
|
138
175
|
readType() {
|
|
139
|
-
return { type: this.
|
|
176
|
+
return { type: this.readByte(), length: this.readInt32() - INT4Length };
|
|
140
177
|
}
|
|
141
178
|
readAuthentication() {
|
|
142
|
-
return this.
|
|
179
|
+
return this.readInt32();
|
|
143
180
|
}
|
|
144
181
|
readMD5Salt() {
|
|
145
|
-
return this.
|
|
182
|
+
return this.readBytes(4);
|
|
146
183
|
}
|
|
147
184
|
readParameterStatus() {
|
|
148
185
|
return {
|
|
149
|
-
name: this.
|
|
150
|
-
value: this.
|
|
186
|
+
name: this.readCString(),
|
|
187
|
+
value: this.readCString()
|
|
151
188
|
};
|
|
152
189
|
}
|
|
153
190
|
readBackendKeyData() {
|
|
154
191
|
return {
|
|
155
|
-
PID: this.
|
|
156
|
-
secret: this.
|
|
192
|
+
PID: this.readInt32(),
|
|
193
|
+
secret: this.readInt32()
|
|
157
194
|
};
|
|
158
195
|
}
|
|
159
196
|
readErrorResponse() {
|
|
@@ -167,10 +204,10 @@ export class ConnectionResponseReader {
|
|
|
167
204
|
let dataType = '';
|
|
168
205
|
let constraint = '';
|
|
169
206
|
while (true) {
|
|
170
|
-
const marker = this.
|
|
207
|
+
const marker = this.readChar();
|
|
171
208
|
if (marker === '\0')
|
|
172
209
|
break;
|
|
173
|
-
const text = this.
|
|
210
|
+
const text = this.readCString();
|
|
174
211
|
switch (marker) {
|
|
175
212
|
case 'S':
|
|
176
213
|
severity = text;
|
|
@@ -204,12 +241,12 @@ export class ConnectionResponseReader {
|
|
|
204
241
|
return new PostgresError(message, code, detail, severity, where, hint, position, dataType, constraint);
|
|
205
242
|
}
|
|
206
243
|
readReadyForQuery() {
|
|
207
|
-
return this.
|
|
244
|
+
return this.readByte();
|
|
208
245
|
}
|
|
209
246
|
readSaslMechanisms() {
|
|
210
247
|
const mechanisms = [];
|
|
211
248
|
while (true) {
|
|
212
|
-
const mech = this.
|
|
249
|
+
const mech = this.readCString();
|
|
213
250
|
if (mech === "")
|
|
214
251
|
break;
|
|
215
252
|
mechanisms.push(mech);
|
|
@@ -217,29 +254,29 @@ export class ConnectionResponseReader {
|
|
|
217
254
|
return mechanisms;
|
|
218
255
|
}
|
|
219
256
|
readSaslMessage(length) {
|
|
220
|
-
return this.
|
|
257
|
+
return this.readRawString(length - 4);
|
|
221
258
|
}
|
|
222
259
|
readRowDescription() {
|
|
223
|
-
const columnsCount = this.
|
|
260
|
+
const columnsCount = this.readInt16();
|
|
224
261
|
const columns = new Array(columnsCount);
|
|
225
262
|
for (let i = 0; i < columnsCount; i++) {
|
|
226
|
-
const name = this.
|
|
227
|
-
this.
|
|
228
|
-
this.
|
|
263
|
+
const name = this.readCString();
|
|
264
|
+
this.readInt32();
|
|
265
|
+
this.readInt16();
|
|
229
266
|
columns[i] = {
|
|
230
267
|
name: name,
|
|
231
|
-
typeOID: this.
|
|
268
|
+
typeOID: this.readInt32(),
|
|
232
269
|
};
|
|
233
|
-
this.
|
|
234
|
-
this.
|
|
270
|
+
this.readInt32();
|
|
271
|
+
this.readInt32();
|
|
235
272
|
}
|
|
236
273
|
return columns;
|
|
237
274
|
}
|
|
238
275
|
readDataRow(descriptions, int8toBigint) {
|
|
239
|
-
const fieldsCount = this.
|
|
276
|
+
const fieldsCount = this.readInt16();
|
|
240
277
|
const row = {};
|
|
241
278
|
for (let i = 0; i < fieldsCount; i++) {
|
|
242
|
-
const fieldLength = this.
|
|
279
|
+
const fieldLength = this.readInt32();
|
|
243
280
|
const desc = descriptions[i];
|
|
244
281
|
const key = desc.name;
|
|
245
282
|
if (fieldLength === -1) {
|
|
@@ -259,89 +296,105 @@ export class ConnectionResponseReader {
|
|
|
259
296
|
cacheForColumn = new Map();
|
|
260
297
|
columnValueCache.set(i, cacheForColumn);
|
|
261
298
|
}
|
|
262
|
-
const byteHash = this.
|
|
299
|
+
const byteHash = this.getBufferHash(fieldLength);
|
|
263
300
|
let cachedString = cacheForColumn.get(byteHash);
|
|
264
301
|
if (cachedString === undefined) {
|
|
265
|
-
cachedString = this.
|
|
266
|
-
if (cacheForColumn.size
|
|
267
|
-
cacheForColumn.
|
|
302
|
+
cachedString = this.readRawString(fieldLength);
|
|
303
|
+
if (cacheForColumn.size > 512) {
|
|
304
|
+
cacheForColumn.clear();
|
|
268
305
|
}
|
|
306
|
+
cacheForColumn.set(byteHash, cachedString);
|
|
269
307
|
}
|
|
270
308
|
else {
|
|
271
|
-
this.
|
|
309
|
+
this.skipBytes(fieldLength);
|
|
272
310
|
}
|
|
273
311
|
row[key] = cachedString;
|
|
274
312
|
}
|
|
275
313
|
else {
|
|
276
|
-
row[key] = this.
|
|
314
|
+
row[key] = this.readRawString(fieldLength);
|
|
277
315
|
}
|
|
278
316
|
}
|
|
279
317
|
break;
|
|
280
318
|
case DataTypeOids.Int2:
|
|
281
319
|
{
|
|
282
|
-
row[key] = this.
|
|
320
|
+
row[key] = this.readInt16();
|
|
283
321
|
}
|
|
284
322
|
break;
|
|
285
323
|
case DataTypeOids.Int4:
|
|
286
324
|
{
|
|
287
|
-
row[key] = this.
|
|
325
|
+
row[key] = this.readInt32();
|
|
288
326
|
}
|
|
289
327
|
break;
|
|
290
328
|
case DataTypeOids.Int8:
|
|
291
329
|
{
|
|
292
|
-
row[key] = int8toBigint ? this.
|
|
330
|
+
row[key] = int8toBigint ? this.readBigInt64() : this.readInt64();
|
|
293
331
|
}
|
|
294
332
|
break;
|
|
295
333
|
case DataTypeOids.Float4:
|
|
296
334
|
{
|
|
297
|
-
row[key] = this.
|
|
335
|
+
row[key] = this.readFloat32();
|
|
298
336
|
}
|
|
299
337
|
break;
|
|
300
338
|
case DataTypeOids.Float8:
|
|
301
339
|
{
|
|
302
|
-
row[key] = this.
|
|
340
|
+
row[key] = this.readFloat64();
|
|
303
341
|
}
|
|
304
342
|
break;
|
|
305
343
|
case DataTypeOids.Bool:
|
|
306
344
|
{
|
|
307
|
-
row[key] = this.
|
|
345
|
+
row[key] = this.readBool();
|
|
308
346
|
}
|
|
309
347
|
break;
|
|
310
348
|
case DataTypeOids.Bytea:
|
|
311
349
|
{
|
|
312
|
-
row[key] = this.
|
|
350
|
+
row[key] = this.readBytes(fieldLength);
|
|
313
351
|
}
|
|
314
352
|
break;
|
|
315
353
|
case DataTypeOids.Jsonb:
|
|
316
354
|
{
|
|
317
|
-
this.
|
|
318
|
-
row[key] = JSON.parse(this.
|
|
355
|
+
this.skipBytes(1);
|
|
356
|
+
row[key] = JSON.parse(this.readRawString(fieldLength - 1));
|
|
319
357
|
}
|
|
320
358
|
break;
|
|
321
359
|
case DataTypeOids.Json:
|
|
322
360
|
{
|
|
323
|
-
row[key] = JSON.parse(this.
|
|
361
|
+
row[key] = JSON.parse(this.readRawString(fieldLength));
|
|
324
362
|
}
|
|
325
363
|
break;
|
|
326
364
|
case DataTypeOids.Date:
|
|
327
365
|
{
|
|
328
|
-
row[key] = this.
|
|
366
|
+
row[key] = this.readBinaryDate();
|
|
329
367
|
}
|
|
330
368
|
break;
|
|
331
369
|
case DataTypeOids.Timestamp:
|
|
332
370
|
case DataTypeOids.Timestamptz:
|
|
333
371
|
{
|
|
334
|
-
row[key] = this.
|
|
372
|
+
row[key] = this.readBinaryTimestamp();
|
|
335
373
|
}
|
|
336
374
|
break;
|
|
337
375
|
case DataTypeOids.Uuid:
|
|
338
376
|
{
|
|
339
|
-
row[key] = this.
|
|
377
|
+
row[key] = this.readUuid();
|
|
378
|
+
}
|
|
379
|
+
break;
|
|
380
|
+
case DataTypeOids.Time:
|
|
381
|
+
{
|
|
382
|
+
row[key] = this.readBinaryTime();
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
case DataTypeOids.Timetz:
|
|
386
|
+
{
|
|
387
|
+
row[key] = this.readBinaryTimetz();
|
|
388
|
+
}
|
|
389
|
+
break;
|
|
390
|
+
case DataTypeOids.Numeric:
|
|
391
|
+
{
|
|
392
|
+
row[key] = this.readNumeric();
|
|
340
393
|
}
|
|
341
394
|
break;
|
|
342
395
|
default:
|
|
343
396
|
{
|
|
344
|
-
this.
|
|
397
|
+
this.skipBytes(fieldLength);
|
|
345
398
|
row[key] = null;
|
|
346
399
|
}
|
|
347
400
|
break;
|
|
@@ -350,33 +403,20 @@ export class ConnectionResponseReader {
|
|
|
350
403
|
return row;
|
|
351
404
|
}
|
|
352
405
|
readNotificationResponse() {
|
|
353
|
-
this.
|
|
354
|
-
const name = this.
|
|
355
|
-
const payload = this.
|
|
406
|
+
this.readInt32();
|
|
407
|
+
const name = this.readCString();
|
|
408
|
+
const payload = this.readCString();
|
|
356
409
|
return { name, payload };
|
|
357
410
|
}
|
|
358
411
|
readCommandComplete() {
|
|
359
|
-
return this.
|
|
360
|
-
}
|
|
361
|
-
hasMore() {
|
|
362
|
-
return this.buffer.hasMore();
|
|
363
|
-
}
|
|
364
|
-
hasFullPacket() {
|
|
365
|
-
return this.buffer.hasFullPacket();
|
|
366
|
-
}
|
|
367
|
-
getResidualBuffer() {
|
|
368
|
-
return this.buffer.getResidualBuffer();
|
|
412
|
+
return this.readCString();
|
|
369
413
|
}
|
|
370
|
-
readParseComplete() { }
|
|
371
|
-
readBindComplete() { }
|
|
372
414
|
readParameterDescription() {
|
|
373
|
-
const count = this.
|
|
415
|
+
const count = this.readInt16();
|
|
416
|
+
const description = Array(count);
|
|
374
417
|
for (let i = 0; i < count; i++) {
|
|
375
|
-
this.
|
|
418
|
+
description[i] = this.readInt32();
|
|
376
419
|
}
|
|
377
|
-
|
|
378
|
-
readNoData() { }
|
|
379
|
-
skip(count) {
|
|
380
|
-
this.buffer.skipBytes(count);
|
|
420
|
+
return description;
|
|
381
421
|
}
|
|
382
422
|
}
|
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
import { ValueOF } from "../types";
|
|
2
2
|
export declare const RequestTypes: {
|
|
3
|
-
readonly SimpleQuery:
|
|
4
|
-
readonly Parse:
|
|
5
|
-
readonly Bind:
|
|
6
|
-
readonly Execute:
|
|
7
|
-
readonly Sync:
|
|
8
|
-
readonly Password:
|
|
9
|
-
readonly Describe:
|
|
10
|
-
readonly Close:
|
|
3
|
+
readonly SimpleQuery: 81;
|
|
4
|
+
readonly Parse: 80;
|
|
5
|
+
readonly Bind: 66;
|
|
6
|
+
readonly Execute: 69;
|
|
7
|
+
readonly Sync: 83;
|
|
8
|
+
readonly Password: 112;
|
|
9
|
+
readonly Describe: 68;
|
|
10
|
+
readonly Close: 67;
|
|
11
11
|
};
|
|
12
12
|
export type RequestType = ValueOF<typeof RequestTypes>;
|
|
13
13
|
export declare const ResponseTypes: {
|
|
14
|
-
readonly RowDescription:
|
|
15
|
-
readonly DataRow:
|
|
16
|
-
readonly ComandComplete:
|
|
17
|
-
readonly ReadyForQuery:
|
|
18
|
-
readonly ErrorResponse:
|
|
19
|
-
readonly NoticeResponse:
|
|
20
|
-
readonly Authentication:
|
|
21
|
-
readonly BackendKeyData:
|
|
22
|
-
readonly ParamaterStatus:
|
|
23
|
-
readonly ParseComplete:
|
|
24
|
-
readonly BindComplete:
|
|
25
|
-
readonly CloseComplete:
|
|
26
|
-
readonly ParameterDescription:
|
|
27
|
-
readonly NoData:
|
|
28
|
-
readonly Notice:
|
|
29
|
-
readonly NotificationResponse:
|
|
30
|
-
readonly SSLOk:
|
|
31
|
-
readonly SSLDenied:
|
|
14
|
+
readonly RowDescription: 84;
|
|
15
|
+
readonly DataRow: 68;
|
|
16
|
+
readonly ComandComplete: 67;
|
|
17
|
+
readonly ReadyForQuery: 90;
|
|
18
|
+
readonly ErrorResponse: 69;
|
|
19
|
+
readonly NoticeResponse: 78;
|
|
20
|
+
readonly Authentication: 82;
|
|
21
|
+
readonly BackendKeyData: 75;
|
|
22
|
+
readonly ParamaterStatus: 83;
|
|
23
|
+
readonly ParseComplete: 49;
|
|
24
|
+
readonly BindComplete: 50;
|
|
25
|
+
readonly CloseComplete: 51;
|
|
26
|
+
readonly ParameterDescription: 116;
|
|
27
|
+
readonly NoData: 110;
|
|
28
|
+
readonly Notice: 78;
|
|
29
|
+
readonly NotificationResponse: 65;
|
|
30
|
+
readonly SSLOk: 83;
|
|
31
|
+
readonly SSLDenied: 78;
|
|
32
32
|
};
|
|
33
|
+
export type ResponseType = ValueOF<typeof ResponseTypes>;
|
|
33
34
|
export declare const DataTypeOids: {
|
|
34
35
|
readonly Bool: 16;
|
|
35
36
|
readonly Bytea: 17;
|
|
@@ -78,7 +79,7 @@ export declare const DataTypeOids: {
|
|
|
78
79
|
readonly NumericArray: 1231;
|
|
79
80
|
};
|
|
80
81
|
export type DataTypeOid = typeof DataTypeOids[keyof typeof DataTypeOids];
|
|
81
|
-
export
|
|
82
|
+
export declare const INT4Length = 4;
|
|
82
83
|
export declare const AuthenticationCodes: {
|
|
83
84
|
readonly Ok: 0;
|
|
84
85
|
readonly CleartextPassword: 3;
|
|
@@ -89,9 +90,15 @@ export declare const AuthenticationCodes: {
|
|
|
89
90
|
};
|
|
90
91
|
export type AuthenticationCode = ValueOF<typeof AuthenticationCodes>;
|
|
91
92
|
export declare const TransactionStatuses: {
|
|
92
|
-
readonly Idle:
|
|
93
|
-
readonly InTransactionBlock:
|
|
94
|
-
readonly FailedTransactionBlock:
|
|
93
|
+
readonly Idle: 73;
|
|
94
|
+
readonly InTransactionBlock: 84;
|
|
95
|
+
readonly FailedTransactionBlock: 69;
|
|
95
96
|
};
|
|
96
97
|
export type TransactionStatus = ValueOF<typeof TransactionStatuses>;
|
|
98
|
+
export declare const DescribeType: {
|
|
99
|
+
readonly Statement: "S";
|
|
100
|
+
readonly Portal: "P";
|
|
101
|
+
};
|
|
102
|
+
export type DescribeType = ValueOF<typeof DescribeType>;
|
|
103
|
+
export declare const EMPTY_ARRAY: never[];
|
|
97
104
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAElC,eAAO,MAAM,YAAY;;;;;;;;;CASf,CAAA;AAEV,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,YAAY,CAAC,CAAA;AAGtD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;CAmBhB,CAAA;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAElC,eAAO,MAAM,YAAY;;;;;;;;;CASf,CAAA;AAEV,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,YAAY,CAAC,CAAA;AAGtD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;CAmBhB,CAAA;AAEV,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,aAAa,CAAC,CAAA;AAGxD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuDf,CAAA;AAEV,MAAM,MAAM,WAAW,GAAG,OAAO,YAAY,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAEzE,eAAO,MAAM,UAAU,IAAI,CAAA;AAG3B,eAAO,MAAM,mBAAmB;;;;;;;CAOtB,CAAA;AAEV,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAGpE,eAAO,MAAM,mBAAmB;;;;CAItB,CAAA;AAEV,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAGnE,eAAO,MAAM,YAAY;;;CAGf,CAAA;AAEV,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,YAAY,CAAC,CAAA;AAEvD,eAAO,MAAM,WAAW,EAAwB,KAAK,EAAE,CAAA"}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
export const RequestTypes = {
|
|
2
|
-
SimpleQuery: "Q"
|
|
3
|
-
Parse: "P"
|
|
4
|
-
Bind: "B"
|
|
5
|
-
Execute: "E"
|
|
6
|
-
Sync: "S"
|
|
7
|
-
Password: "p"
|
|
8
|
-
Describe:
|
|
9
|
-
Close: "C"
|
|
2
|
+
SimpleQuery: 81, // "Q"
|
|
3
|
+
Parse: 80, // "P"
|
|
4
|
+
Bind: 66, // "B"
|
|
5
|
+
Execute: 69, // "E"
|
|
6
|
+
Sync: 83, // "S"
|
|
7
|
+
Password: 112, // "p"
|
|
8
|
+
Describe: 68, // "D"
|
|
9
|
+
Close: 67 // "C"
|
|
10
10
|
};
|
|
11
11
|
export const ResponseTypes = {
|
|
12
|
-
RowDescription: "T"
|
|
13
|
-
DataRow: "D"
|
|
14
|
-
ComandComplete: "C"
|
|
15
|
-
ReadyForQuery: "Z"
|
|
16
|
-
ErrorResponse: "E"
|
|
17
|
-
NoticeResponse: "N"
|
|
18
|
-
Authentication: "R"
|
|
19
|
-
BackendKeyData: "K"
|
|
20
|
-
ParamaterStatus: "S"
|
|
21
|
-
ParseComplete: "1"
|
|
22
|
-
BindComplete: "2"
|
|
23
|
-
CloseComplete: "3"
|
|
24
|
-
ParameterDescription: "t"
|
|
25
|
-
NoData: "n"
|
|
26
|
-
Notice: "N"
|
|
27
|
-
NotificationResponse: "A"
|
|
28
|
-
SSLOk: "S"
|
|
29
|
-
SSLDenied: "N"
|
|
12
|
+
RowDescription: 84, // "T"
|
|
13
|
+
DataRow: 68, // "D"
|
|
14
|
+
ComandComplete: 67, // "C"
|
|
15
|
+
ReadyForQuery: 90, // "Z"
|
|
16
|
+
ErrorResponse: 69, // "E"
|
|
17
|
+
NoticeResponse: 78, // "N"
|
|
18
|
+
Authentication: 82, // "R"
|
|
19
|
+
BackendKeyData: 75, // "K"
|
|
20
|
+
ParamaterStatus: 83, // "S"
|
|
21
|
+
ParseComplete: 49, // "1"
|
|
22
|
+
BindComplete: 50, // "2"
|
|
23
|
+
CloseComplete: 51, // "3"
|
|
24
|
+
ParameterDescription: 116, // "t"
|
|
25
|
+
NoData: 110, // "n"
|
|
26
|
+
Notice: 78, // "N"
|
|
27
|
+
NotificationResponse: 65, // "A"
|
|
28
|
+
SSLOk: 83, // "S"
|
|
29
|
+
SSLDenied: 78 // "N"
|
|
30
30
|
};
|
|
31
31
|
export const DataTypeOids = {
|
|
32
32
|
Bool: 16,
|
|
@@ -75,6 +75,7 @@ export const DataTypeOids = {
|
|
|
75
75
|
UuidArray: 2951,
|
|
76
76
|
NumericArray: 1231
|
|
77
77
|
};
|
|
78
|
+
export const INT4Length = 4;
|
|
78
79
|
export const AuthenticationCodes = {
|
|
79
80
|
Ok: 0,
|
|
80
81
|
CleartextPassword: 3,
|
|
@@ -84,7 +85,12 @@ export const AuthenticationCodes = {
|
|
|
84
85
|
SASLFinal: 12,
|
|
85
86
|
};
|
|
86
87
|
export const TransactionStatuses = {
|
|
87
|
-
Idle: "I"
|
|
88
|
-
InTransactionBlock: "T"
|
|
89
|
-
FailedTransactionBlock: "E"
|
|
88
|
+
Idle: 73, // "I"
|
|
89
|
+
InTransactionBlock: 84, // "T"
|
|
90
|
+
FailedTransactionBlock: 69, // "E"
|
|
90
91
|
};
|
|
92
|
+
export const DescribeType = {
|
|
93
|
+
Statement: "S",
|
|
94
|
+
Portal: "P",
|
|
95
|
+
};
|
|
96
|
+
export const EMPTY_ARRAY = Object.freeze([]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-authorization.d.ts","sourceRoot":"","sources":["../../src/protocol/socket-authorization.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"socket-authorization.d.ts","sourceRoot":"","sources":["../../src/protocol/socket-authorization.ts"],"names":[],"mappings":"AAIA,OAAO,EAA4J,aAAa,EAAE,MAAM,UAAU,CAAA;AAClM,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEtC,OAAO,EAAoB,MAAM,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAM3C,eAAO,MAAM,YAAY,GAAI,QAAQ,gBAAgB,kCASpD,CAAA;AAGD,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,EAAE,QAAQ,gBAAgB,kCA+ErE,CAAA;AAGD,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,QAAQ,gBAAgB,kCAyHvE,CAAA"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ConnectionRequestWriter } from "./connection-request-writer";
|
|
2
1
|
import { calculateScramAuth, generateNonce } from "../security/sasl";
|
|
3
2
|
import { SocketConnector } from "./socket-connector";
|
|
4
3
|
import { AuthenticationCodes, ResponseTypes } from "./constants";
|
|
@@ -8,6 +7,7 @@ import { Future } from "fluent-future";
|
|
|
8
7
|
import { connect } from "node:tls";
|
|
9
8
|
import { createConnection } from "node:net";
|
|
10
9
|
import { readFileSync } from "node:fs";
|
|
10
|
+
import { ConnectionRequestBuffer } from "./connection-request-writer";
|
|
11
11
|
export const createSocket = (config) => {
|
|
12
12
|
const { future, resolve, reject } = Future.withResolvers();
|
|
13
13
|
const socket = createConnection({ host: config.host, port: config.port });
|
|
@@ -19,7 +19,7 @@ export const upgradeSocket = (socket, config) => {
|
|
|
19
19
|
if (config.ssl === 'disable')
|
|
20
20
|
return Future.resolve(socket);
|
|
21
21
|
const { future, reject, resolve } = Future.withResolvers();
|
|
22
|
-
const writer =
|
|
22
|
+
const writer = ConnectionRequestBuffer.new(2048);
|
|
23
23
|
const onError = () => {
|
|
24
24
|
cleanup();
|
|
25
25
|
reject(ErrSocketFailedDuringAuth);
|
|
@@ -84,7 +84,7 @@ export const upgradeSocket = (socket, config) => {
|
|
|
84
84
|
};
|
|
85
85
|
export const authorizeSocket = (socket, config) => {
|
|
86
86
|
const { future, reject, resolve } = Future.withResolvers();
|
|
87
|
-
const writer =
|
|
87
|
+
const writer = ConnectionRequestBuffer.new(2048);
|
|
88
88
|
const nonce = generateNonce();
|
|
89
89
|
let clientMessage = '';
|
|
90
90
|
let serverMessage = '';
|
|
@@ -127,7 +127,7 @@ export const authorizeSocket = (socket, config) => {
|
|
|
127
127
|
case AuthenticationCodes.CleartextPassword:
|
|
128
128
|
{
|
|
129
129
|
if (!config.password)
|
|
130
|
-
|
|
130
|
+
return reject(ErrPasswordRequired);
|
|
131
131
|
connector.write(writer.writePassword(config.password));
|
|
132
132
|
writer.clear();
|
|
133
133
|
}
|
|
@@ -136,7 +136,7 @@ export const authorizeSocket = (socket, config) => {
|
|
|
136
136
|
{
|
|
137
137
|
const salt = reader.readMD5Salt();
|
|
138
138
|
if (!config.password)
|
|
139
|
-
|
|
139
|
+
return reject(ErrPasswordRequired);
|
|
140
140
|
const password = encryptMd5(config.password, config.user, salt);
|
|
141
141
|
connector.write(writer.writePassword(password));
|
|
142
142
|
writer.clear();
|
|
@@ -146,7 +146,7 @@ export const authorizeSocket = (socket, config) => {
|
|
|
146
146
|
{
|
|
147
147
|
reader.readSaslMechanisms();
|
|
148
148
|
if (!config.password)
|
|
149
|
-
|
|
149
|
+
return reject(ErrPasswordRequired);
|
|
150
150
|
clientMessage = `n=${config.user},r=${nonce}`;
|
|
151
151
|
connector.write(writer.writeSaslInitial('SCRAM-SHA-256', `n,,${clientMessage}`));
|
|
152
152
|
writer.clear();
|
|
@@ -156,7 +156,7 @@ export const authorizeSocket = (socket, config) => {
|
|
|
156
156
|
{
|
|
157
157
|
serverMessage = reader.readSaslMessage(length);
|
|
158
158
|
if (!config.password)
|
|
159
|
-
|
|
159
|
+
return reject(ErrPasswordRequired);
|
|
160
160
|
const parts = Object.fromEntries(serverMessage.split(',').map(x => x.split('=')));
|
|
161
161
|
const serverNonce = parts.r;
|
|
162
162
|
const saltBase64 = parts.s;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Socket } from 'net';
|
|
2
2
|
import { ResponseType } from './constants';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { ConnectionResponseBuffer } from './connection-response-reader';
|
|
4
|
+
import { ConnectionRequestBuffer } from './connection-request-writer';
|
|
5
5
|
export declare class SocketConnector {
|
|
6
6
|
private _socket;
|
|
7
7
|
private residualBuffer;
|
|
@@ -9,8 +9,8 @@ export declare class SocketConnector {
|
|
|
9
9
|
private _onClose;
|
|
10
10
|
private _onData;
|
|
11
11
|
private _destroyed;
|
|
12
|
-
constructor(_socket: Socket, onData: (type: ResponseType, length: number, reader:
|
|
13
|
-
write(writer:
|
|
12
|
+
constructor(_socket: Socket, onData: (type: ResponseType, length: number, reader: ConnectionResponseBuffer) => void, onError: (error: unknown) => void);
|
|
13
|
+
write(writer: ConnectionRequestBuffer): void;
|
|
14
14
|
unwrapSocket(): Socket;
|
|
15
15
|
destroy(): void;
|
|
16
16
|
}
|
|
@@ -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,
|
|
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,8BAA8B,CAAA;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAA;AAErE,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,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConnectionResponseBuffer } from './connection-response-reader';
|
|
2
2
|
export class SocketConnector {
|
|
3
3
|
constructor(_socket, onData, onError) {
|
|
4
4
|
this._socket = _socket;
|
|
@@ -23,7 +23,7 @@ export class SocketConnector {
|
|
|
23
23
|
? Buffer.concat([this.residualBuffer, buffer])
|
|
24
24
|
: buffer;
|
|
25
25
|
this.residualBuffer = null;
|
|
26
|
-
const reader =
|
|
26
|
+
const reader = ConnectionResponseBuffer.from(currentBuffer);
|
|
27
27
|
while (reader.hasMore()) {
|
|
28
28
|
if (!reader.hasFullPacket()) {
|
|
29
29
|
this.residualBuffer = reader.getResidualBuffer();
|