add websocket server to this dir. fix stuff for client
This commit is contained in:
21
websocket_server/node_modules/pg-protocol/LICENSE
generated
vendored
Normal file
21
websocket_server/node_modules/pg-protocol/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2010 - 2021 Brian Carlson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
3
websocket_server/node_modules/pg-protocol/README.md
generated
vendored
Normal file
3
websocket_server/node_modules/pg-protocol/README.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# pg-protocol
|
||||
|
||||
Low level postgres wire protocol parser and serializer written in Typescript. Used by node-postgres. Needs more documentation. :smile:
|
1
websocket_server/node_modules/pg-protocol/dist/b.d.ts
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/b.d.ts
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
export {};
|
23
websocket_server/node_modules/pg-protocol/dist/b.js
generated
vendored
Normal file
23
websocket_server/node_modules/pg-protocol/dist/b.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
// file for microbenchmarking
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const buffer_reader_1 = require("./buffer-reader");
|
||||
const LOOPS = 1000;
|
||||
let count = 0;
|
||||
let start = Date.now();
|
||||
const reader = new buffer_reader_1.BufferReader();
|
||||
const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0]);
|
||||
const run = () => {
|
||||
if (count > LOOPS) {
|
||||
console.log(Date.now() - start);
|
||||
return;
|
||||
}
|
||||
count++;
|
||||
for (let i = 0; i < LOOPS; i++) {
|
||||
reader.setBuffer(0, buffer);
|
||||
reader.cstring();
|
||||
}
|
||||
setImmediate(run);
|
||||
};
|
||||
run();
|
||||
//# sourceMappingURL=b.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/b.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/b.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"b.js","sourceRoot":"","sources":["../src/b.ts"],"names":[],"mappings":";AAAA,6BAA6B;;AAE7B,mDAA8C;AAE9C,MAAM,KAAK,GAAG,IAAI,CAAA;AAClB,IAAI,KAAK,GAAG,CAAC,CAAA;AACb,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;AAEtB,MAAM,MAAM,GAAG,IAAI,4BAAY,EAAE,CAAA;AACjC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;AAE3D,MAAM,GAAG,GAAG,GAAG,EAAE;IACf,IAAI,KAAK,GAAG,KAAK,EAAE;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAA;QAC/B,OAAM;KACP;IACD,KAAK,EAAE,CAAA;IACP,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;QAC9B,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;QAC3B,MAAM,CAAC,OAAO,EAAE,CAAA;KACjB;IACD,YAAY,CAAC,GAAG,CAAC,CAAA;AACnB,CAAC,CAAA;AAED,GAAG,EAAE,CAAA"}
|
14
websocket_server/node_modules/pg-protocol/dist/buffer-reader.d.ts
generated
vendored
Normal file
14
websocket_server/node_modules/pg-protocol/dist/buffer-reader.d.ts
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/// <reference types="node" />
|
||||
export declare class BufferReader {
|
||||
private offset;
|
||||
private buffer;
|
||||
private encoding;
|
||||
constructor(offset?: number);
|
||||
setBuffer(offset: number, buffer: Buffer): void;
|
||||
int16(): number;
|
||||
byte(): number;
|
||||
int32(): number;
|
||||
string(length: number): string;
|
||||
cstring(): string;
|
||||
bytes(length: number): Buffer;
|
||||
}
|
50
websocket_server/node_modules/pg-protocol/dist/buffer-reader.js
generated
vendored
Normal file
50
websocket_server/node_modules/pg-protocol/dist/buffer-reader.js
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BufferReader = void 0;
|
||||
const emptyBuffer = Buffer.allocUnsafe(0);
|
||||
class BufferReader {
|
||||
constructor(offset = 0) {
|
||||
this.offset = offset;
|
||||
this.buffer = emptyBuffer;
|
||||
// TODO(bmc): support non-utf8 encoding?
|
||||
this.encoding = 'utf-8';
|
||||
}
|
||||
setBuffer(offset, buffer) {
|
||||
this.offset = offset;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
int16() {
|
||||
const result = this.buffer.readInt16BE(this.offset);
|
||||
this.offset += 2;
|
||||
return result;
|
||||
}
|
||||
byte() {
|
||||
const result = this.buffer[this.offset];
|
||||
this.offset++;
|
||||
return result;
|
||||
}
|
||||
int32() {
|
||||
const result = this.buffer.readInt32BE(this.offset);
|
||||
this.offset += 4;
|
||||
return result;
|
||||
}
|
||||
string(length) {
|
||||
const result = this.buffer.toString(this.encoding, this.offset, this.offset + length);
|
||||
this.offset += length;
|
||||
return result;
|
||||
}
|
||||
cstring() {
|
||||
const start = this.offset;
|
||||
let end = start;
|
||||
while (this.buffer[end++] !== 0) { }
|
||||
this.offset = end;
|
||||
return this.buffer.toString(this.encoding, start, end - 1);
|
||||
}
|
||||
bytes(length) {
|
||||
const result = this.buffer.slice(this.offset, this.offset + length);
|
||||
this.offset += length;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.BufferReader = BufferReader;
|
||||
//# sourceMappingURL=buffer-reader.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/buffer-reader.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/buffer-reader.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"buffer-reader.js","sourceRoot":"","sources":["../src/buffer-reader.ts"],"names":[],"mappings":";;;AAAA,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;AAEzC,MAAa,YAAY;IAMvB,YAAoB,SAAiB,CAAC;QAAlB,WAAM,GAAN,MAAM,CAAY;QAL9B,WAAM,GAAW,WAAW,CAAA;QAEpC,wCAAwC;QAChC,aAAQ,GAAW,OAAO,CAAA;IAEO,CAAC;IAEnC,SAAS,CAAC,MAAc,EAAE,MAAc;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAEM,KAAK;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACnD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAA;QAChB,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,IAAI;QACT,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvC,IAAI,CAAC,MAAM,EAAE,CAAA;QACb,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,KAAK;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACnD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAA;QAChB,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,MAAM,CAAC,MAAc;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;QACrF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAA;QACrB,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,OAAO;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAA;QACzB,IAAI,GAAG,GAAG,KAAK,CAAA;QACf,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,GAAE;QACnC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAA;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAA;IAC5D,CAAC;IAEM,KAAK,CAAC,MAAc;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;QACnE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAA;QACrB,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAlDD,oCAkDC"}
|
16
websocket_server/node_modules/pg-protocol/dist/buffer-writer.d.ts
generated
vendored
Normal file
16
websocket_server/node_modules/pg-protocol/dist/buffer-writer.d.ts
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/// <reference types="node" />
|
||||
export declare class Writer {
|
||||
private size;
|
||||
private buffer;
|
||||
private offset;
|
||||
private headerPosition;
|
||||
constructor(size?: number);
|
||||
private ensure;
|
||||
addInt32(num: number): Writer;
|
||||
addInt16(num: number): Writer;
|
||||
addCString(string: string): Writer;
|
||||
addString(string?: string): Writer;
|
||||
add(otherBuffer: Buffer): Writer;
|
||||
private join;
|
||||
flush(code?: number): Buffer;
|
||||
}
|
81
websocket_server/node_modules/pg-protocol/dist/buffer-writer.js
generated
vendored
Normal file
81
websocket_server/node_modules/pg-protocol/dist/buffer-writer.js
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
//binary data writer tuned for encoding binary specific to the postgres binary protocol
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Writer = void 0;
|
||||
class Writer {
|
||||
constructor(size = 256) {
|
||||
this.size = size;
|
||||
this.offset = 5;
|
||||
this.headerPosition = 0;
|
||||
this.buffer = Buffer.allocUnsafe(size);
|
||||
}
|
||||
ensure(size) {
|
||||
var remaining = this.buffer.length - this.offset;
|
||||
if (remaining < size) {
|
||||
var oldBuffer = this.buffer;
|
||||
// exponential growth factor of around ~ 1.5
|
||||
// https://stackoverflow.com/questions/2269063/buffer-growth-strategy
|
||||
var newSize = oldBuffer.length + (oldBuffer.length >> 1) + size;
|
||||
this.buffer = Buffer.allocUnsafe(newSize);
|
||||
oldBuffer.copy(this.buffer);
|
||||
}
|
||||
}
|
||||
addInt32(num) {
|
||||
this.ensure(4);
|
||||
this.buffer[this.offset++] = (num >>> 24) & 0xff;
|
||||
this.buffer[this.offset++] = (num >>> 16) & 0xff;
|
||||
this.buffer[this.offset++] = (num >>> 8) & 0xff;
|
||||
this.buffer[this.offset++] = (num >>> 0) & 0xff;
|
||||
return this;
|
||||
}
|
||||
addInt16(num) {
|
||||
this.ensure(2);
|
||||
this.buffer[this.offset++] = (num >>> 8) & 0xff;
|
||||
this.buffer[this.offset++] = (num >>> 0) & 0xff;
|
||||
return this;
|
||||
}
|
||||
addCString(string) {
|
||||
if (!string) {
|
||||
this.ensure(1);
|
||||
}
|
||||
else {
|
||||
var len = Buffer.byteLength(string);
|
||||
this.ensure(len + 1); // +1 for null terminator
|
||||
this.buffer.write(string, this.offset, 'utf-8');
|
||||
this.offset += len;
|
||||
}
|
||||
this.buffer[this.offset++] = 0; // null terminator
|
||||
return this;
|
||||
}
|
||||
addString(string = '') {
|
||||
var len = Buffer.byteLength(string);
|
||||
this.ensure(len);
|
||||
this.buffer.write(string, this.offset);
|
||||
this.offset += len;
|
||||
return this;
|
||||
}
|
||||
add(otherBuffer) {
|
||||
this.ensure(otherBuffer.length);
|
||||
otherBuffer.copy(this.buffer, this.offset);
|
||||
this.offset += otherBuffer.length;
|
||||
return this;
|
||||
}
|
||||
join(code) {
|
||||
if (code) {
|
||||
this.buffer[this.headerPosition] = code;
|
||||
//length is everything in this packet minus the code
|
||||
const length = this.offset - (this.headerPosition + 1);
|
||||
this.buffer.writeInt32BE(length, this.headerPosition + 1);
|
||||
}
|
||||
return this.buffer.slice(code ? 0 : 5, this.offset);
|
||||
}
|
||||
flush(code) {
|
||||
var result = this.join(code);
|
||||
this.offset = 5;
|
||||
this.headerPosition = 0;
|
||||
this.buffer = Buffer.allocUnsafe(this.size);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.Writer = Writer;
|
||||
//# sourceMappingURL=buffer-writer.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/buffer-writer.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/buffer-writer.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"buffer-writer.js","sourceRoot":"","sources":["../src/buffer-writer.ts"],"names":[],"mappings":";AAAA,uFAAuF;;;AAEvF,MAAa,MAAM;IAIjB,YAAoB,OAAO,GAAG;QAAV,SAAI,GAAJ,IAAI,CAAM;QAFtB,WAAM,GAAW,CAAC,CAAA;QAClB,mBAAc,GAAW,CAAC,CAAA;QAEhC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC;IAEO,MAAM,CAAC,IAAY;QACzB,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAChD,IAAI,SAAS,GAAG,IAAI,EAAE;YACpB,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,CAAA;YAC3B,4CAA4C;YAC5C,qEAAqE;YACrE,IAAI,OAAO,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA;YAC/D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;YACzC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;SAC5B;IACH,CAAC;IAEM,QAAQ,CAAC,GAAW;QACzB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;QAChD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;QAChD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QAC/C,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,QAAQ,CAAC,GAAW;QACzB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;QAC/C,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,UAAU,CAAC,MAAc;QAC9B,IAAI,CAAC,MAAM,EAAE;YACX,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;SACf;aAAM;YACL,IAAI,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;YACnC,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA,CAAC,yBAAyB;YAC9C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAC/C,IAAI,CAAC,MAAM,IAAI,GAAG,CAAA;SACnB;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAA,CAAC,kBAAkB;QACjD,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,SAAS,CAAC,SAAiB,EAAE;QAClC,IAAI,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QACnC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACtC,IAAI,CAAC,MAAM,IAAI,GAAG,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,GAAG,CAAC,WAAmB;QAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAC/B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1C,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM,CAAA;QACjC,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,IAAI,CAAC,IAAa;QACxB,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,IAAI,CAAA;YACvC,oDAAoD;YACpD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAA;YACtD,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAA;SAC1D;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACrD,CAAC;IAEM,KAAK,CAAC,IAAa;QACxB,IAAI,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,cAAc,GAAG,CAAC,CAAA;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3C,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAlFD,wBAkFC"}
|
1
websocket_server/node_modules/pg-protocol/dist/inbound-parser.test.d.ts
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/inbound-parser.test.d.ts
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
export {};
|
501
websocket_server/node_modules/pg-protocol/dist/inbound-parser.test.js
generated
vendored
Normal file
501
websocket_server/node_modules/pg-protocol/dist/inbound-parser.test.js
generated
vendored
Normal file
@ -0,0 +1,501 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const test_buffers_1 = __importDefault(require("./testing/test-buffers"));
|
||||
const buffer_list_1 = __importDefault(require("./testing/buffer-list"));
|
||||
const _1 = require(".");
|
||||
const assert_1 = __importDefault(require("assert"));
|
||||
const stream_1 = require("stream");
|
||||
var authOkBuffer = test_buffers_1.default.authenticationOk();
|
||||
var paramStatusBuffer = test_buffers_1.default.parameterStatus('client_encoding', 'UTF8');
|
||||
var readyForQueryBuffer = test_buffers_1.default.readyForQuery();
|
||||
var backendKeyDataBuffer = test_buffers_1.default.backendKeyData(1, 2);
|
||||
var commandCompleteBuffer = test_buffers_1.default.commandComplete('SELECT 3');
|
||||
var parseCompleteBuffer = test_buffers_1.default.parseComplete();
|
||||
var bindCompleteBuffer = test_buffers_1.default.bindComplete();
|
||||
var portalSuspendedBuffer = test_buffers_1.default.portalSuspended();
|
||||
var row1 = {
|
||||
name: 'id',
|
||||
tableID: 1,
|
||||
attributeNumber: 2,
|
||||
dataTypeID: 3,
|
||||
dataTypeSize: 4,
|
||||
typeModifier: 5,
|
||||
formatCode: 0,
|
||||
};
|
||||
var oneRowDescBuff = test_buffers_1.default.rowDescription([row1]);
|
||||
row1.name = 'bang';
|
||||
var twoRowBuf = test_buffers_1.default.rowDescription([
|
||||
row1,
|
||||
{
|
||||
name: 'whoah',
|
||||
tableID: 10,
|
||||
attributeNumber: 11,
|
||||
dataTypeID: 12,
|
||||
dataTypeSize: 13,
|
||||
typeModifier: 14,
|
||||
formatCode: 0,
|
||||
},
|
||||
]);
|
||||
var emptyRowFieldBuf = new buffer_list_1.default().addInt16(0).join(true, 'D');
|
||||
var emptyRowFieldBuf = test_buffers_1.default.dataRow([]);
|
||||
var oneFieldBuf = new buffer_list_1.default()
|
||||
.addInt16(1) // number of fields
|
||||
.addInt32(5) // length of bytes of fields
|
||||
.addCString('test')
|
||||
.join(true, 'D');
|
||||
var oneFieldBuf = test_buffers_1.default.dataRow(['test']);
|
||||
var expectedAuthenticationOkayMessage = {
|
||||
name: 'authenticationOk',
|
||||
length: 8,
|
||||
};
|
||||
var expectedParameterStatusMessage = {
|
||||
name: 'parameterStatus',
|
||||
parameterName: 'client_encoding',
|
||||
parameterValue: 'UTF8',
|
||||
length: 25,
|
||||
};
|
||||
var expectedBackendKeyDataMessage = {
|
||||
name: 'backendKeyData',
|
||||
processID: 1,
|
||||
secretKey: 2,
|
||||
};
|
||||
var expectedReadyForQueryMessage = {
|
||||
name: 'readyForQuery',
|
||||
length: 5,
|
||||
status: 'I',
|
||||
};
|
||||
var expectedCommandCompleteMessage = {
|
||||
name: 'commandComplete',
|
||||
length: 13,
|
||||
text: 'SELECT 3',
|
||||
};
|
||||
var emptyRowDescriptionBuffer = new buffer_list_1.default()
|
||||
.addInt16(0) // number of fields
|
||||
.join(true, 'T');
|
||||
var expectedEmptyRowDescriptionMessage = {
|
||||
name: 'rowDescription',
|
||||
length: 6,
|
||||
fieldCount: 0,
|
||||
fields: [],
|
||||
};
|
||||
var expectedOneRowMessage = {
|
||||
name: 'rowDescription',
|
||||
length: 27,
|
||||
fieldCount: 1,
|
||||
fields: [
|
||||
{
|
||||
name: 'id',
|
||||
tableID: 1,
|
||||
columnID: 2,
|
||||
dataTypeID: 3,
|
||||
dataTypeSize: 4,
|
||||
dataTypeModifier: 5,
|
||||
format: 'text',
|
||||
},
|
||||
],
|
||||
};
|
||||
var expectedTwoRowMessage = {
|
||||
name: 'rowDescription',
|
||||
length: 53,
|
||||
fieldCount: 2,
|
||||
fields: [
|
||||
{
|
||||
name: 'bang',
|
||||
tableID: 1,
|
||||
columnID: 2,
|
||||
dataTypeID: 3,
|
||||
dataTypeSize: 4,
|
||||
dataTypeModifier: 5,
|
||||
format: 'text',
|
||||
},
|
||||
{
|
||||
name: 'whoah',
|
||||
tableID: 10,
|
||||
columnID: 11,
|
||||
dataTypeID: 12,
|
||||
dataTypeSize: 13,
|
||||
dataTypeModifier: 14,
|
||||
format: 'text',
|
||||
},
|
||||
],
|
||||
};
|
||||
var emptyParameterDescriptionBuffer = new buffer_list_1.default()
|
||||
.addInt16(0) // number of parameters
|
||||
.join(true, 't');
|
||||
var oneParameterDescBuf = test_buffers_1.default.parameterDescription([1111]);
|
||||
var twoParameterDescBuf = test_buffers_1.default.parameterDescription([2222, 3333]);
|
||||
var expectedEmptyParameterDescriptionMessage = {
|
||||
name: 'parameterDescription',
|
||||
length: 6,
|
||||
parameterCount: 0,
|
||||
dataTypeIDs: [],
|
||||
};
|
||||
var expectedOneParameterMessage = {
|
||||
name: 'parameterDescription',
|
||||
length: 10,
|
||||
parameterCount: 1,
|
||||
dataTypeIDs: [1111],
|
||||
};
|
||||
var expectedTwoParameterMessage = {
|
||||
name: 'parameterDescription',
|
||||
length: 14,
|
||||
parameterCount: 2,
|
||||
dataTypeIDs: [2222, 3333],
|
||||
};
|
||||
var testForMessage = function (buffer, expectedMessage) {
|
||||
it('recieves and parses ' + expectedMessage.name, () => __awaiter(this, void 0, void 0, function* () {
|
||||
const messages = yield parseBuffers([buffer]);
|
||||
const [lastMessage] = messages;
|
||||
for (const key in expectedMessage) {
|
||||
assert_1.default.deepEqual(lastMessage[key], expectedMessage[key]);
|
||||
}
|
||||
}));
|
||||
};
|
||||
var plainPasswordBuffer = test_buffers_1.default.authenticationCleartextPassword();
|
||||
var md5PasswordBuffer = test_buffers_1.default.authenticationMD5Password();
|
||||
var SASLBuffer = test_buffers_1.default.authenticationSASL();
|
||||
var SASLContinueBuffer = test_buffers_1.default.authenticationSASLContinue();
|
||||
var SASLFinalBuffer = test_buffers_1.default.authenticationSASLFinal();
|
||||
var expectedPlainPasswordMessage = {
|
||||
name: 'authenticationCleartextPassword',
|
||||
};
|
||||
var expectedMD5PasswordMessage = {
|
||||
name: 'authenticationMD5Password',
|
||||
salt: Buffer.from([1, 2, 3, 4]),
|
||||
};
|
||||
var expectedSASLMessage = {
|
||||
name: 'authenticationSASL',
|
||||
mechanisms: ['SCRAM-SHA-256'],
|
||||
};
|
||||
var expectedSASLContinueMessage = {
|
||||
name: 'authenticationSASLContinue',
|
||||
data: 'data',
|
||||
};
|
||||
var expectedSASLFinalMessage = {
|
||||
name: 'authenticationSASLFinal',
|
||||
data: 'data',
|
||||
};
|
||||
var notificationResponseBuffer = test_buffers_1.default.notification(4, 'hi', 'boom');
|
||||
var expectedNotificationResponseMessage = {
|
||||
name: 'notification',
|
||||
processId: 4,
|
||||
channel: 'hi',
|
||||
payload: 'boom',
|
||||
};
|
||||
const parseBuffers = (buffers) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const stream = new stream_1.PassThrough();
|
||||
for (const buffer of buffers) {
|
||||
stream.write(buffer);
|
||||
}
|
||||
stream.end();
|
||||
const msgs = [];
|
||||
yield (0, _1.parse)(stream, (msg) => msgs.push(msg));
|
||||
return msgs;
|
||||
});
|
||||
describe('PgPacketStream', function () {
|
||||
testForMessage(authOkBuffer, expectedAuthenticationOkayMessage);
|
||||
testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage);
|
||||
testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage);
|
||||
testForMessage(SASLBuffer, expectedSASLMessage);
|
||||
testForMessage(SASLContinueBuffer, expectedSASLContinueMessage);
|
||||
// this exercises a found bug in the parser:
|
||||
// https://github.com/brianc/node-postgres/pull/2210#issuecomment-627626084
|
||||
// and adds a test which is deterministic, rather than relying on network packet chunking
|
||||
const extendedSASLContinueBuffer = Buffer.concat([SASLContinueBuffer, Buffer.from([1, 2, 3, 4])]);
|
||||
testForMessage(extendedSASLContinueBuffer, expectedSASLContinueMessage);
|
||||
testForMessage(SASLFinalBuffer, expectedSASLFinalMessage);
|
||||
// this exercises a found bug in the parser:
|
||||
// https://github.com/brianc/node-postgres/pull/2210#issuecomment-627626084
|
||||
// and adds a test which is deterministic, rather than relying on network packet chunking
|
||||
const extendedSASLFinalBuffer = Buffer.concat([SASLFinalBuffer, Buffer.from([1, 2, 4, 5])]);
|
||||
testForMessage(extendedSASLFinalBuffer, expectedSASLFinalMessage);
|
||||
testForMessage(paramStatusBuffer, expectedParameterStatusMessage);
|
||||
testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage);
|
||||
testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage);
|
||||
testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage);
|
||||
testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage);
|
||||
testForMessage(test_buffers_1.default.emptyQuery(), {
|
||||
name: 'emptyQuery',
|
||||
length: 4,
|
||||
});
|
||||
testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), {
|
||||
name: 'noData',
|
||||
});
|
||||
describe('rowDescription messages', function () {
|
||||
testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage);
|
||||
testForMessage(oneRowDescBuff, expectedOneRowMessage);
|
||||
testForMessage(twoRowBuf, expectedTwoRowMessage);
|
||||
});
|
||||
describe('parameterDescription messages', function () {
|
||||
testForMessage(emptyParameterDescriptionBuffer, expectedEmptyParameterDescriptionMessage);
|
||||
testForMessage(oneParameterDescBuf, expectedOneParameterMessage);
|
||||
testForMessage(twoParameterDescBuf, expectedTwoParameterMessage);
|
||||
});
|
||||
describe('parsing rows', function () {
|
||||
describe('parsing empty row', function () {
|
||||
testForMessage(emptyRowFieldBuf, {
|
||||
name: 'dataRow',
|
||||
fieldCount: 0,
|
||||
});
|
||||
});
|
||||
describe('parsing data row with fields', function () {
|
||||
testForMessage(oneFieldBuf, {
|
||||
name: 'dataRow',
|
||||
fieldCount: 1,
|
||||
fields: ['test'],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('notice message', function () {
|
||||
// this uses the same logic as error message
|
||||
var buff = test_buffers_1.default.notice([{ type: 'C', value: 'code' }]);
|
||||
testForMessage(buff, {
|
||||
name: 'notice',
|
||||
code: 'code',
|
||||
});
|
||||
});
|
||||
testForMessage(test_buffers_1.default.error([]), {
|
||||
name: 'error',
|
||||
});
|
||||
describe('with all the fields', function () {
|
||||
var buffer = test_buffers_1.default.error([
|
||||
{
|
||||
type: 'S',
|
||||
value: 'ERROR',
|
||||
},
|
||||
{
|
||||
type: 'C',
|
||||
value: 'code',
|
||||
},
|
||||
{
|
||||
type: 'M',
|
||||
value: 'message',
|
||||
},
|
||||
{
|
||||
type: 'D',
|
||||
value: 'details',
|
||||
},
|
||||
{
|
||||
type: 'H',
|
||||
value: 'hint',
|
||||
},
|
||||
{
|
||||
type: 'P',
|
||||
value: '100',
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
value: '101',
|
||||
},
|
||||
{
|
||||
type: 'q',
|
||||
value: 'query',
|
||||
},
|
||||
{
|
||||
type: 'W',
|
||||
value: 'where',
|
||||
},
|
||||
{
|
||||
type: 'F',
|
||||
value: 'file',
|
||||
},
|
||||
{
|
||||
type: 'L',
|
||||
value: 'line',
|
||||
},
|
||||
{
|
||||
type: 'R',
|
||||
value: 'routine',
|
||||
},
|
||||
{
|
||||
type: 'Z',
|
||||
value: 'alsdkf',
|
||||
},
|
||||
]);
|
||||
testForMessage(buffer, {
|
||||
name: 'error',
|
||||
severity: 'ERROR',
|
||||
code: 'code',
|
||||
message: 'message',
|
||||
detail: 'details',
|
||||
hint: 'hint',
|
||||
position: '100',
|
||||
internalPosition: '101',
|
||||
internalQuery: 'query',
|
||||
where: 'where',
|
||||
file: 'file',
|
||||
line: 'line',
|
||||
routine: 'routine',
|
||||
});
|
||||
});
|
||||
testForMessage(parseCompleteBuffer, {
|
||||
name: 'parseComplete',
|
||||
});
|
||||
testForMessage(bindCompleteBuffer, {
|
||||
name: 'bindComplete',
|
||||
});
|
||||
testForMessage(bindCompleteBuffer, {
|
||||
name: 'bindComplete',
|
||||
});
|
||||
testForMessage(test_buffers_1.default.closeComplete(), {
|
||||
name: 'closeComplete',
|
||||
});
|
||||
describe('parses portal suspended message', function () {
|
||||
testForMessage(portalSuspendedBuffer, {
|
||||
name: 'portalSuspended',
|
||||
});
|
||||
});
|
||||
describe('parses replication start message', function () {
|
||||
testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), {
|
||||
name: 'replicationStart',
|
||||
length: 4,
|
||||
});
|
||||
});
|
||||
describe('copy', () => {
|
||||
testForMessage(test_buffers_1.default.copyIn(0), {
|
||||
name: 'copyInResponse',
|
||||
length: 7,
|
||||
binary: false,
|
||||
columnTypes: [],
|
||||
});
|
||||
testForMessage(test_buffers_1.default.copyIn(2), {
|
||||
name: 'copyInResponse',
|
||||
length: 11,
|
||||
binary: false,
|
||||
columnTypes: [0, 1],
|
||||
});
|
||||
testForMessage(test_buffers_1.default.copyOut(0), {
|
||||
name: 'copyOutResponse',
|
||||
length: 7,
|
||||
binary: false,
|
||||
columnTypes: [],
|
||||
});
|
||||
testForMessage(test_buffers_1.default.copyOut(3), {
|
||||
name: 'copyOutResponse',
|
||||
length: 13,
|
||||
binary: false,
|
||||
columnTypes: [0, 1, 2],
|
||||
});
|
||||
testForMessage(test_buffers_1.default.copyDone(), {
|
||||
name: 'copyDone',
|
||||
length: 4,
|
||||
});
|
||||
testForMessage(test_buffers_1.default.copyData(Buffer.from([5, 6, 7])), {
|
||||
name: 'copyData',
|
||||
length: 7,
|
||||
chunk: Buffer.from([5, 6, 7]),
|
||||
});
|
||||
});
|
||||
// since the data message on a stream can randomly divide the incomming
|
||||
// tcp packets anywhere, we need to make sure we can parse every single
|
||||
// split on a tcp message
|
||||
describe('split buffer, single message parsing', function () {
|
||||
var fullBuffer = test_buffers_1.default.dataRow([null, 'bang', 'zug zug', null, '!']);
|
||||
it('parses when full buffer comes in', function () {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const messages = yield parseBuffers([fullBuffer]);
|
||||
const message = messages[0];
|
||||
assert_1.default.equal(message.fields.length, 5);
|
||||
assert_1.default.equal(message.fields[0], null);
|
||||
assert_1.default.equal(message.fields[1], 'bang');
|
||||
assert_1.default.equal(message.fields[2], 'zug zug');
|
||||
assert_1.default.equal(message.fields[3], null);
|
||||
assert_1.default.equal(message.fields[4], '!');
|
||||
});
|
||||
});
|
||||
var testMessageRecievedAfterSpiltAt = function (split) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var firstBuffer = Buffer.alloc(fullBuffer.length - split);
|
||||
var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length);
|
||||
fullBuffer.copy(firstBuffer, 0, 0);
|
||||
fullBuffer.copy(secondBuffer, 0, firstBuffer.length);
|
||||
const messages = yield parseBuffers([fullBuffer]);
|
||||
const message = messages[0];
|
||||
assert_1.default.equal(message.fields.length, 5);
|
||||
assert_1.default.equal(message.fields[0], null);
|
||||
assert_1.default.equal(message.fields[1], 'bang');
|
||||
assert_1.default.equal(message.fields[2], 'zug zug');
|
||||
assert_1.default.equal(message.fields[3], null);
|
||||
assert_1.default.equal(message.fields[4], '!');
|
||||
});
|
||||
};
|
||||
it('parses when split in the middle', function () {
|
||||
testMessageRecievedAfterSpiltAt(6);
|
||||
});
|
||||
it('parses when split at end', function () {
|
||||
testMessageRecievedAfterSpiltAt(2);
|
||||
});
|
||||
it('parses when split at beginning', function () {
|
||||
testMessageRecievedAfterSpiltAt(fullBuffer.length - 2);
|
||||
testMessageRecievedAfterSpiltAt(fullBuffer.length - 1);
|
||||
testMessageRecievedAfterSpiltAt(fullBuffer.length - 5);
|
||||
});
|
||||
});
|
||||
describe('split buffer, multiple message parsing', function () {
|
||||
var dataRowBuffer = test_buffers_1.default.dataRow(['!']);
|
||||
var readyForQueryBuffer = test_buffers_1.default.readyForQuery();
|
||||
var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length);
|
||||
dataRowBuffer.copy(fullBuffer, 0, 0);
|
||||
readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0);
|
||||
var verifyMessages = function (messages) {
|
||||
assert_1.default.strictEqual(messages.length, 2);
|
||||
assert_1.default.deepEqual(messages[0], {
|
||||
name: 'dataRow',
|
||||
fieldCount: 1,
|
||||
length: 11,
|
||||
fields: ['!'],
|
||||
});
|
||||
assert_1.default.equal(messages[0].fields[0], '!');
|
||||
assert_1.default.deepEqual(messages[1], {
|
||||
name: 'readyForQuery',
|
||||
length: 5,
|
||||
status: 'I',
|
||||
});
|
||||
};
|
||||
// sanity check
|
||||
it('recieves both messages when packet is not split', function () {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const messages = yield parseBuffers([fullBuffer]);
|
||||
verifyMessages(messages);
|
||||
});
|
||||
});
|
||||
var splitAndVerifyTwoMessages = function (split) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var firstBuffer = Buffer.alloc(fullBuffer.length - split);
|
||||
var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length);
|
||||
fullBuffer.copy(firstBuffer, 0, 0);
|
||||
fullBuffer.copy(secondBuffer, 0, firstBuffer.length);
|
||||
const messages = yield parseBuffers([firstBuffer, secondBuffer]);
|
||||
verifyMessages(messages);
|
||||
});
|
||||
};
|
||||
describe('recieves both messages when packet is split', function () {
|
||||
it('in the middle', function () {
|
||||
return splitAndVerifyTwoMessages(11);
|
||||
});
|
||||
it('at the front', function () {
|
||||
return Promise.all([
|
||||
splitAndVerifyTwoMessages(fullBuffer.length - 1),
|
||||
splitAndVerifyTwoMessages(fullBuffer.length - 4),
|
||||
splitAndVerifyTwoMessages(fullBuffer.length - 6),
|
||||
]);
|
||||
});
|
||||
it('at the end', function () {
|
||||
return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=inbound-parser.test.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/inbound-parser.test.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/inbound-parser.test.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
6
websocket_server/node_modules/pg-protocol/dist/index.d.ts
generated
vendored
Normal file
6
websocket_server/node_modules/pg-protocol/dist/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/// <reference types="node" />
|
||||
import { DatabaseError } from './messages';
|
||||
import { serialize } from './serializer';
|
||||
import { MessageCallback } from './parser';
|
||||
export declare function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise<void>;
|
||||
export { serialize, DatabaseError };
|
15
websocket_server/node_modules/pg-protocol/dist/index.js
generated
vendored
Normal file
15
websocket_server/node_modules/pg-protocol/dist/index.js
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DatabaseError = exports.serialize = exports.parse = void 0;
|
||||
const messages_1 = require("./messages");
|
||||
Object.defineProperty(exports, "DatabaseError", { enumerable: true, get: function () { return messages_1.DatabaseError; } });
|
||||
const serializer_1 = require("./serializer");
|
||||
Object.defineProperty(exports, "serialize", { enumerable: true, get: function () { return serializer_1.serialize; } });
|
||||
const parser_1 = require("./parser");
|
||||
function parse(stream, callback) {
|
||||
const parser = new parser_1.Parser();
|
||||
stream.on('data', (buffer) => parser.parse(buffer, callback));
|
||||
return new Promise((resolve) => stream.on('end', () => resolve()));
|
||||
}
|
||||
exports.parse = parse;
|
||||
//# sourceMappingURL=index.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/index.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/index.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA0C;AAUtB,8FAVX,wBAAa,OAUW;AATjC,6CAAwC;AAS/B,0FATA,sBAAS,OASA;AARlB,qCAAkD;AAElD,SAAgB,KAAK,CAAC,MAA6B,EAAE,QAAyB;IAC5E,MAAM,MAAM,GAAG,IAAI,eAAM,EAAE,CAAA;IAC3B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;IACrE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;AACpE,CAAC;AAJD,sBAIC"}
|
162
websocket_server/node_modules/pg-protocol/dist/messages.d.ts
generated
vendored
Normal file
162
websocket_server/node_modules/pg-protocol/dist/messages.d.ts
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
/// <reference types="node" />
|
||||
export declare type Mode = 'text' | 'binary';
|
||||
export declare type MessageName = 'parseComplete' | 'bindComplete' | 'closeComplete' | 'noData' | 'portalSuspended' | 'replicationStart' | 'emptyQuery' | 'copyDone' | 'copyData' | 'rowDescription' | 'parameterDescription' | 'parameterStatus' | 'backendKeyData' | 'notification' | 'readyForQuery' | 'commandComplete' | 'dataRow' | 'copyInResponse' | 'copyOutResponse' | 'authenticationOk' | 'authenticationMD5Password' | 'authenticationCleartextPassword' | 'authenticationSASL' | 'authenticationSASLContinue' | 'authenticationSASLFinal' | 'error' | 'notice';
|
||||
export interface BackendMessage {
|
||||
name: MessageName;
|
||||
length: number;
|
||||
}
|
||||
export declare const parseComplete: BackendMessage;
|
||||
export declare const bindComplete: BackendMessage;
|
||||
export declare const closeComplete: BackendMessage;
|
||||
export declare const noData: BackendMessage;
|
||||
export declare const portalSuspended: BackendMessage;
|
||||
export declare const replicationStart: BackendMessage;
|
||||
export declare const emptyQuery: BackendMessage;
|
||||
export declare const copyDone: BackendMessage;
|
||||
interface NoticeOrError {
|
||||
message: string | undefined;
|
||||
severity: string | undefined;
|
||||
code: string | undefined;
|
||||
detail: string | undefined;
|
||||
hint: string | undefined;
|
||||
position: string | undefined;
|
||||
internalPosition: string | undefined;
|
||||
internalQuery: string | undefined;
|
||||
where: string | undefined;
|
||||
schema: string | undefined;
|
||||
table: string | undefined;
|
||||
column: string | undefined;
|
||||
dataType: string | undefined;
|
||||
constraint: string | undefined;
|
||||
file: string | undefined;
|
||||
line: string | undefined;
|
||||
routine: string | undefined;
|
||||
}
|
||||
export declare class DatabaseError extends Error implements NoticeOrError {
|
||||
readonly length: number;
|
||||
readonly name: MessageName;
|
||||
severity: string | undefined;
|
||||
code: string | undefined;
|
||||
detail: string | undefined;
|
||||
hint: string | undefined;
|
||||
position: string | undefined;
|
||||
internalPosition: string | undefined;
|
||||
internalQuery: string | undefined;
|
||||
where: string | undefined;
|
||||
schema: string | undefined;
|
||||
table: string | undefined;
|
||||
column: string | undefined;
|
||||
dataType: string | undefined;
|
||||
constraint: string | undefined;
|
||||
file: string | undefined;
|
||||
line: string | undefined;
|
||||
routine: string | undefined;
|
||||
constructor(message: string, length: number, name: MessageName);
|
||||
}
|
||||
export declare class CopyDataMessage {
|
||||
readonly length: number;
|
||||
readonly chunk: Buffer;
|
||||
readonly name = "copyData";
|
||||
constructor(length: number, chunk: Buffer);
|
||||
}
|
||||
export declare class CopyResponse {
|
||||
readonly length: number;
|
||||
readonly name: MessageName;
|
||||
readonly binary: boolean;
|
||||
readonly columnTypes: number[];
|
||||
constructor(length: number, name: MessageName, binary: boolean, columnCount: number);
|
||||
}
|
||||
export declare class Field {
|
||||
readonly name: string;
|
||||
readonly tableID: number;
|
||||
readonly columnID: number;
|
||||
readonly dataTypeID: number;
|
||||
readonly dataTypeSize: number;
|
||||
readonly dataTypeModifier: number;
|
||||
readonly format: Mode;
|
||||
constructor(name: string, tableID: number, columnID: number, dataTypeID: number, dataTypeSize: number, dataTypeModifier: number, format: Mode);
|
||||
}
|
||||
export declare class RowDescriptionMessage {
|
||||
readonly length: number;
|
||||
readonly fieldCount: number;
|
||||
readonly name: MessageName;
|
||||
readonly fields: Field[];
|
||||
constructor(length: number, fieldCount: number);
|
||||
}
|
||||
export declare class ParameterDescriptionMessage {
|
||||
readonly length: number;
|
||||
readonly parameterCount: number;
|
||||
readonly name: MessageName;
|
||||
readonly dataTypeIDs: number[];
|
||||
constructor(length: number, parameterCount: number);
|
||||
}
|
||||
export declare class ParameterStatusMessage {
|
||||
readonly length: number;
|
||||
readonly parameterName: string;
|
||||
readonly parameterValue: string;
|
||||
readonly name: MessageName;
|
||||
constructor(length: number, parameterName: string, parameterValue: string);
|
||||
}
|
||||
export declare class AuthenticationMD5Password implements BackendMessage {
|
||||
readonly length: number;
|
||||
readonly salt: Buffer;
|
||||
readonly name: MessageName;
|
||||
constructor(length: number, salt: Buffer);
|
||||
}
|
||||
export declare class BackendKeyDataMessage {
|
||||
readonly length: number;
|
||||
readonly processID: number;
|
||||
readonly secretKey: number;
|
||||
readonly name: MessageName;
|
||||
constructor(length: number, processID: number, secretKey: number);
|
||||
}
|
||||
export declare class NotificationResponseMessage {
|
||||
readonly length: number;
|
||||
readonly processId: number;
|
||||
readonly channel: string;
|
||||
readonly payload: string;
|
||||
readonly name: MessageName;
|
||||
constructor(length: number, processId: number, channel: string, payload: string);
|
||||
}
|
||||
export declare class ReadyForQueryMessage {
|
||||
readonly length: number;
|
||||
readonly status: string;
|
||||
readonly name: MessageName;
|
||||
constructor(length: number, status: string);
|
||||
}
|
||||
export declare class CommandCompleteMessage {
|
||||
readonly length: number;
|
||||
readonly text: string;
|
||||
readonly name: MessageName;
|
||||
constructor(length: number, text: string);
|
||||
}
|
||||
export declare class DataRowMessage {
|
||||
length: number;
|
||||
fields: any[];
|
||||
readonly fieldCount: number;
|
||||
readonly name: MessageName;
|
||||
constructor(length: number, fields: any[]);
|
||||
}
|
||||
export declare class NoticeMessage implements BackendMessage, NoticeOrError {
|
||||
readonly length: number;
|
||||
readonly message: string | undefined;
|
||||
constructor(length: number, message: string | undefined);
|
||||
readonly name = "notice";
|
||||
severity: string | undefined;
|
||||
code: string | undefined;
|
||||
detail: string | undefined;
|
||||
hint: string | undefined;
|
||||
position: string | undefined;
|
||||
internalPosition: string | undefined;
|
||||
internalQuery: string | undefined;
|
||||
where: string | undefined;
|
||||
schema: string | undefined;
|
||||
table: string | undefined;
|
||||
column: string | undefined;
|
||||
dataType: string | undefined;
|
||||
constraint: string | undefined;
|
||||
file: string | undefined;
|
||||
line: string | undefined;
|
||||
routine: string | undefined;
|
||||
}
|
||||
export {};
|
160
websocket_server/node_modules/pg-protocol/dist/messages.js
generated
vendored
Normal file
160
websocket_server/node_modules/pg-protocol/dist/messages.js
generated
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NoticeMessage = exports.DataRowMessage = exports.CommandCompleteMessage = exports.ReadyForQueryMessage = exports.NotificationResponseMessage = exports.BackendKeyDataMessage = exports.AuthenticationMD5Password = exports.ParameterStatusMessage = exports.ParameterDescriptionMessage = exports.RowDescriptionMessage = exports.Field = exports.CopyResponse = exports.CopyDataMessage = exports.DatabaseError = exports.copyDone = exports.emptyQuery = exports.replicationStart = exports.portalSuspended = exports.noData = exports.closeComplete = exports.bindComplete = exports.parseComplete = void 0;
|
||||
exports.parseComplete = {
|
||||
name: 'parseComplete',
|
||||
length: 5,
|
||||
};
|
||||
exports.bindComplete = {
|
||||
name: 'bindComplete',
|
||||
length: 5,
|
||||
};
|
||||
exports.closeComplete = {
|
||||
name: 'closeComplete',
|
||||
length: 5,
|
||||
};
|
||||
exports.noData = {
|
||||
name: 'noData',
|
||||
length: 5,
|
||||
};
|
||||
exports.portalSuspended = {
|
||||
name: 'portalSuspended',
|
||||
length: 5,
|
||||
};
|
||||
exports.replicationStart = {
|
||||
name: 'replicationStart',
|
||||
length: 4,
|
||||
};
|
||||
exports.emptyQuery = {
|
||||
name: 'emptyQuery',
|
||||
length: 4,
|
||||
};
|
||||
exports.copyDone = {
|
||||
name: 'copyDone',
|
||||
length: 4,
|
||||
};
|
||||
class DatabaseError extends Error {
|
||||
constructor(message, length, name) {
|
||||
super(message);
|
||||
this.length = length;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
exports.DatabaseError = DatabaseError;
|
||||
class CopyDataMessage {
|
||||
constructor(length, chunk) {
|
||||
this.length = length;
|
||||
this.chunk = chunk;
|
||||
this.name = 'copyData';
|
||||
}
|
||||
}
|
||||
exports.CopyDataMessage = CopyDataMessage;
|
||||
class CopyResponse {
|
||||
constructor(length, name, binary, columnCount) {
|
||||
this.length = length;
|
||||
this.name = name;
|
||||
this.binary = binary;
|
||||
this.columnTypes = new Array(columnCount);
|
||||
}
|
||||
}
|
||||
exports.CopyResponse = CopyResponse;
|
||||
class Field {
|
||||
constructor(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, format) {
|
||||
this.name = name;
|
||||
this.tableID = tableID;
|
||||
this.columnID = columnID;
|
||||
this.dataTypeID = dataTypeID;
|
||||
this.dataTypeSize = dataTypeSize;
|
||||
this.dataTypeModifier = dataTypeModifier;
|
||||
this.format = format;
|
||||
}
|
||||
}
|
||||
exports.Field = Field;
|
||||
class RowDescriptionMessage {
|
||||
constructor(length, fieldCount) {
|
||||
this.length = length;
|
||||
this.fieldCount = fieldCount;
|
||||
this.name = 'rowDescription';
|
||||
this.fields = new Array(this.fieldCount);
|
||||
}
|
||||
}
|
||||
exports.RowDescriptionMessage = RowDescriptionMessage;
|
||||
class ParameterDescriptionMessage {
|
||||
constructor(length, parameterCount) {
|
||||
this.length = length;
|
||||
this.parameterCount = parameterCount;
|
||||
this.name = 'parameterDescription';
|
||||
this.dataTypeIDs = new Array(this.parameterCount);
|
||||
}
|
||||
}
|
||||
exports.ParameterDescriptionMessage = ParameterDescriptionMessage;
|
||||
class ParameterStatusMessage {
|
||||
constructor(length, parameterName, parameterValue) {
|
||||
this.length = length;
|
||||
this.parameterName = parameterName;
|
||||
this.parameterValue = parameterValue;
|
||||
this.name = 'parameterStatus';
|
||||
}
|
||||
}
|
||||
exports.ParameterStatusMessage = ParameterStatusMessage;
|
||||
class AuthenticationMD5Password {
|
||||
constructor(length, salt) {
|
||||
this.length = length;
|
||||
this.salt = salt;
|
||||
this.name = 'authenticationMD5Password';
|
||||
}
|
||||
}
|
||||
exports.AuthenticationMD5Password = AuthenticationMD5Password;
|
||||
class BackendKeyDataMessage {
|
||||
constructor(length, processID, secretKey) {
|
||||
this.length = length;
|
||||
this.processID = processID;
|
||||
this.secretKey = secretKey;
|
||||
this.name = 'backendKeyData';
|
||||
}
|
||||
}
|
||||
exports.BackendKeyDataMessage = BackendKeyDataMessage;
|
||||
class NotificationResponseMessage {
|
||||
constructor(length, processId, channel, payload) {
|
||||
this.length = length;
|
||||
this.processId = processId;
|
||||
this.channel = channel;
|
||||
this.payload = payload;
|
||||
this.name = 'notification';
|
||||
}
|
||||
}
|
||||
exports.NotificationResponseMessage = NotificationResponseMessage;
|
||||
class ReadyForQueryMessage {
|
||||
constructor(length, status) {
|
||||
this.length = length;
|
||||
this.status = status;
|
||||
this.name = 'readyForQuery';
|
||||
}
|
||||
}
|
||||
exports.ReadyForQueryMessage = ReadyForQueryMessage;
|
||||
class CommandCompleteMessage {
|
||||
constructor(length, text) {
|
||||
this.length = length;
|
||||
this.text = text;
|
||||
this.name = 'commandComplete';
|
||||
}
|
||||
}
|
||||
exports.CommandCompleteMessage = CommandCompleteMessage;
|
||||
class DataRowMessage {
|
||||
constructor(length, fields) {
|
||||
this.length = length;
|
||||
this.fields = fields;
|
||||
this.name = 'dataRow';
|
||||
this.fieldCount = fields.length;
|
||||
}
|
||||
}
|
||||
exports.DataRowMessage = DataRowMessage;
|
||||
class NoticeMessage {
|
||||
constructor(length, message) {
|
||||
this.length = length;
|
||||
this.message = message;
|
||||
this.name = 'notice';
|
||||
}
|
||||
}
|
||||
exports.NoticeMessage = NoticeMessage;
|
||||
//# sourceMappingURL=messages.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/messages.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/messages.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":";;;AAoCa,QAAA,aAAa,GAAmB;IAC3C,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,YAAY,GAAmB;IAC1C,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,aAAa,GAAmB;IAC3C,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,MAAM,GAAmB;IACpC,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,eAAe,GAAmB;IAC7C,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,gBAAgB,GAAmB;IAC9C,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,UAAU,GAAmB;IACxC,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,QAAQ,GAAmB;IACtC,IAAI,EAAE,UAAU;IAChB,MAAM,EAAE,CAAC;CACV,CAAA;AAsBD,MAAa,aAAc,SAAQ,KAAK;IAiBtC,YACE,OAAe,EACC,MAAc,EACd,IAAiB;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAA;QAHE,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAa;IAGnC,CAAC;CACF;AAxBD,sCAwBC;AAED,MAAa,eAAe;IAE1B,YACkB,MAAc,EACd,KAAa;QADb,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAAQ;QAHf,SAAI,GAAG,UAAU,CAAA;IAI9B,CAAC;CACL;AAND,0CAMC;AAED,MAAa,YAAY;IAEvB,YACkB,MAAc,EACd,IAAiB,EACjB,MAAe,EAC/B,WAAmB;QAHH,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAa;QACjB,WAAM,GAAN,MAAM,CAAS;QAG/B,IAAI,CAAC,WAAW,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAA;IAC3C,CAAC;CACF;AAVD,oCAUC;AAED,MAAa,KAAK;IAChB,YACkB,IAAY,EACZ,OAAe,EACf,QAAgB,EAChB,UAAkB,EAClB,YAAoB,EACpB,gBAAwB,EACxB,MAAY;QANZ,SAAI,GAAJ,IAAI,CAAQ;QACZ,YAAO,GAAP,OAAO,CAAQ;QACf,aAAQ,GAAR,QAAQ,CAAQ;QAChB,eAAU,GAAV,UAAU,CAAQ;QAClB,iBAAY,GAAZ,YAAY,CAAQ;QACpB,qBAAgB,GAAhB,gBAAgB,CAAQ;QACxB,WAAM,GAAN,MAAM,CAAM;IAC3B,CAAC;CACL;AAVD,sBAUC;AAED,MAAa,qBAAqB;IAGhC,YACkB,MAAc,EACd,UAAkB;QADlB,WAAM,GAAN,MAAM,CAAQ;QACd,eAAU,GAAV,UAAU,CAAQ;QAJpB,SAAI,GAAgB,gBAAgB,CAAA;QAMlD,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC1C,CAAC;CACF;AATD,sDASC;AAED,MAAa,2BAA2B;IAGtC,YACkB,MAAc,EACd,cAAsB;QADtB,WAAM,GAAN,MAAM,CAAQ;QACd,mBAAc,GAAd,cAAc,CAAQ;QAJxB,SAAI,GAAgB,sBAAsB,CAAA;QAMxD,IAAI,CAAC,WAAW,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IACnD,CAAC;CACF;AATD,kEASC;AAED,MAAa,sBAAsB;IAEjC,YACkB,MAAc,EACd,aAAqB,EACrB,cAAsB;QAFtB,WAAM,GAAN,MAAM,CAAQ;QACd,kBAAa,GAAb,aAAa,CAAQ;QACrB,mBAAc,GAAd,cAAc,CAAQ;QAJxB,SAAI,GAAgB,iBAAiB,CAAA;IAKlD,CAAC;CACL;AAPD,wDAOC;AAED,MAAa,yBAAyB;IAEpC,YACkB,MAAc,EACd,IAAY;QADZ,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QAHd,SAAI,GAAgB,2BAA2B,CAAA;IAI5D,CAAC;CACL;AAND,8DAMC;AAED,MAAa,qBAAqB;IAEhC,YACkB,MAAc,EACd,SAAiB,EACjB,SAAiB;QAFjB,WAAM,GAAN,MAAM,CAAQ;QACd,cAAS,GAAT,SAAS,CAAQ;QACjB,cAAS,GAAT,SAAS,CAAQ;QAJnB,SAAI,GAAgB,gBAAgB,CAAA;IAKjD,CAAC;CACL;AAPD,sDAOC;AAED,MAAa,2BAA2B;IAEtC,YACkB,MAAc,EACd,SAAiB,EACjB,OAAe,EACf,OAAe;QAHf,WAAM,GAAN,MAAM,CAAQ;QACd,cAAS,GAAT,SAAS,CAAQ;QACjB,YAAO,GAAP,OAAO,CAAQ;QACf,YAAO,GAAP,OAAO,CAAQ;QALjB,SAAI,GAAgB,cAAc,CAAA;IAM/C,CAAC;CACL;AARD,kEAQC;AAED,MAAa,oBAAoB;IAE/B,YACkB,MAAc,EACd,MAAc;QADd,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAQ;QAHhB,SAAI,GAAgB,eAAe,CAAA;IAIhD,CAAC;CACL;AAND,oDAMC;AAED,MAAa,sBAAsB;IAEjC,YACkB,MAAc,EACd,IAAY;QADZ,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QAHd,SAAI,GAAgB,iBAAiB,CAAA;IAIlD,CAAC;CACL;AAND,wDAMC;AAED,MAAa,cAAc;IAGzB,YACS,MAAc,EACd,MAAa;QADb,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAO;QAHN,SAAI,GAAgB,SAAS,CAAA;QAK3C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAA;IACjC,CAAC;CACF;AATD,wCASC;AAED,MAAa,aAAa;IACxB,YACkB,MAAc,EACd,OAA2B;QAD3B,WAAM,GAAN,MAAM,CAAQ;QACd,YAAO,GAAP,OAAO,CAAoB;QAE7B,SAAI,GAAG,QAAQ,CAAA;IAD5B,CAAC;CAkBL;AAtBD,sCAsBC"}
|
1
websocket_server/node_modules/pg-protocol/dist/outbound-serializer.test.d.ts
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/outbound-serializer.test.d.ts
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
export {};
|
248
websocket_server/node_modules/pg-protocol/dist/outbound-serializer.test.js
generated
vendored
Normal file
248
websocket_server/node_modules/pg-protocol/dist/outbound-serializer.test.js
generated
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const assert_1 = __importDefault(require("assert"));
|
||||
const serializer_1 = require("./serializer");
|
||||
const buffer_list_1 = __importDefault(require("./testing/buffer-list"));
|
||||
describe('serializer', () => {
|
||||
it('builds startup message', function () {
|
||||
const actual = serializer_1.serialize.startup({
|
||||
user: 'brian',
|
||||
database: 'bang',
|
||||
});
|
||||
assert_1.default.deepEqual(actual, new buffer_list_1.default()
|
||||
.addInt16(3)
|
||||
.addInt16(0)
|
||||
.addCString('user')
|
||||
.addCString('brian')
|
||||
.addCString('database')
|
||||
.addCString('bang')
|
||||
.addCString('client_encoding')
|
||||
.addCString('UTF8')
|
||||
.addCString('')
|
||||
.join(true));
|
||||
});
|
||||
it('builds password message', function () {
|
||||
const actual = serializer_1.serialize.password('!');
|
||||
assert_1.default.deepEqual(actual, new buffer_list_1.default().addCString('!').join(true, 'p'));
|
||||
});
|
||||
it('builds request ssl message', function () {
|
||||
const actual = serializer_1.serialize.requestSsl();
|
||||
const expected = new buffer_list_1.default().addInt32(80877103).join(true);
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('builds SASLInitialResponseMessage message', function () {
|
||||
const actual = serializer_1.serialize.sendSASLInitialResponseMessage('mech', 'data');
|
||||
assert_1.default.deepEqual(actual, new buffer_list_1.default().addCString('mech').addInt32(4).addString('data').join(true, 'p'));
|
||||
});
|
||||
it('builds SCRAMClientFinalMessage message', function () {
|
||||
const actual = serializer_1.serialize.sendSCRAMClientFinalMessage('data');
|
||||
assert_1.default.deepEqual(actual, new buffer_list_1.default().addString('data').join(true, 'p'));
|
||||
});
|
||||
it('builds query message', function () {
|
||||
var txt = 'select * from boom';
|
||||
const actual = serializer_1.serialize.query(txt);
|
||||
assert_1.default.deepEqual(actual, new buffer_list_1.default().addCString(txt).join(true, 'Q'));
|
||||
});
|
||||
describe('parse message', () => {
|
||||
it('builds parse message', function () {
|
||||
const actual = serializer_1.serialize.parse({ text: '!' });
|
||||
var expected = new buffer_list_1.default().addCString('').addCString('!').addInt16(0).join(true, 'P');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('builds parse message with named query', function () {
|
||||
const actual = serializer_1.serialize.parse({
|
||||
name: 'boom',
|
||||
text: 'select * from boom',
|
||||
types: [],
|
||||
});
|
||||
var expected = new buffer_list_1.default().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('with multiple parameters', function () {
|
||||
const actual = serializer_1.serialize.parse({
|
||||
name: 'force',
|
||||
text: 'select * from bang where name = $1',
|
||||
types: [1, 2, 3, 4],
|
||||
});
|
||||
var expected = new buffer_list_1.default()
|
||||
.addCString('force')
|
||||
.addCString('select * from bang where name = $1')
|
||||
.addInt16(4)
|
||||
.addInt32(1)
|
||||
.addInt32(2)
|
||||
.addInt32(3)
|
||||
.addInt32(4)
|
||||
.join(true, 'P');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
describe('bind messages', function () {
|
||||
it('with no values', function () {
|
||||
const actual = serializer_1.serialize.bind();
|
||||
var expectedBuffer = new buffer_list_1.default()
|
||||
.addCString('')
|
||||
.addCString('')
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.join(true, 'B');
|
||||
assert_1.default.deepEqual(actual, expectedBuffer);
|
||||
});
|
||||
it('with named statement, portal, and values', function () {
|
||||
const actual = serializer_1.serialize.bind({
|
||||
portal: 'bang',
|
||||
statement: 'woo',
|
||||
values: ['1', 'hi', null, 'zing'],
|
||||
});
|
||||
var expectedBuffer = new buffer_list_1.default()
|
||||
.addCString('bang') // portal name
|
||||
.addCString('woo') // statement name
|
||||
.addInt16(4)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(4)
|
||||
.addInt32(1)
|
||||
.add(Buffer.from('1'))
|
||||
.addInt32(2)
|
||||
.add(Buffer.from('hi'))
|
||||
.addInt32(-1)
|
||||
.addInt32(4)
|
||||
.add(Buffer.from('zing'))
|
||||
.addInt16(0)
|
||||
.join(true, 'B');
|
||||
assert_1.default.deepEqual(actual, expectedBuffer);
|
||||
});
|
||||
});
|
||||
it('with custom valueMapper', function () {
|
||||
const actual = serializer_1.serialize.bind({
|
||||
portal: 'bang',
|
||||
statement: 'woo',
|
||||
values: ['1', 'hi', null, 'zing'],
|
||||
valueMapper: () => null,
|
||||
});
|
||||
var expectedBuffer = new buffer_list_1.default()
|
||||
.addCString('bang') // portal name
|
||||
.addCString('woo') // statement name
|
||||
.addInt16(4)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(4)
|
||||
.addInt32(-1)
|
||||
.addInt32(-1)
|
||||
.addInt32(-1)
|
||||
.addInt32(-1)
|
||||
.addInt16(0)
|
||||
.join(true, 'B');
|
||||
assert_1.default.deepEqual(actual, expectedBuffer);
|
||||
});
|
||||
it('with named statement, portal, and buffer value', function () {
|
||||
const actual = serializer_1.serialize.bind({
|
||||
portal: 'bang',
|
||||
statement: 'woo',
|
||||
values: ['1', 'hi', null, Buffer.from('zing', 'utf8')],
|
||||
});
|
||||
var expectedBuffer = new buffer_list_1.default()
|
||||
.addCString('bang') // portal name
|
||||
.addCString('woo') // statement name
|
||||
.addInt16(4) // value count
|
||||
.addInt16(0) // string
|
||||
.addInt16(0) // string
|
||||
.addInt16(0) // string
|
||||
.addInt16(1) // binary
|
||||
.addInt16(4)
|
||||
.addInt32(1)
|
||||
.add(Buffer.from('1'))
|
||||
.addInt32(2)
|
||||
.add(Buffer.from('hi'))
|
||||
.addInt32(-1)
|
||||
.addInt32(4)
|
||||
.add(Buffer.from('zing', 'utf-8'))
|
||||
.addInt16(0)
|
||||
.join(true, 'B');
|
||||
assert_1.default.deepEqual(actual, expectedBuffer);
|
||||
});
|
||||
describe('builds execute message', function () {
|
||||
it('for unamed portal with no row limit', function () {
|
||||
const actual = serializer_1.serialize.execute();
|
||||
var expectedBuffer = new buffer_list_1.default().addCString('').addInt32(0).join(true, 'E');
|
||||
assert_1.default.deepEqual(actual, expectedBuffer);
|
||||
});
|
||||
it('for named portal with row limit', function () {
|
||||
const actual = serializer_1.serialize.execute({
|
||||
portal: 'my favorite portal',
|
||||
rows: 100,
|
||||
});
|
||||
var expectedBuffer = new buffer_list_1.default().addCString('my favorite portal').addInt32(100).join(true, 'E');
|
||||
assert_1.default.deepEqual(actual, expectedBuffer);
|
||||
});
|
||||
});
|
||||
it('builds flush command', function () {
|
||||
const actual = serializer_1.serialize.flush();
|
||||
var expected = new buffer_list_1.default().join(true, 'H');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('builds sync command', function () {
|
||||
const actual = serializer_1.serialize.sync();
|
||||
var expected = new buffer_list_1.default().join(true, 'S');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('builds end command', function () {
|
||||
const actual = serializer_1.serialize.end();
|
||||
var expected = Buffer.from([0x58, 0, 0, 0, 4]);
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
describe('builds describe command', function () {
|
||||
it('describe statement', function () {
|
||||
const actual = serializer_1.serialize.describe({ type: 'S', name: 'bang' });
|
||||
var expected = new buffer_list_1.default().addChar('S').addCString('bang').join(true, 'D');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('describe unnamed portal', function () {
|
||||
const actual = serializer_1.serialize.describe({ type: 'P' });
|
||||
var expected = new buffer_list_1.default().addChar('P').addCString('').join(true, 'D');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
describe('builds close command', function () {
|
||||
it('describe statement', function () {
|
||||
const actual = serializer_1.serialize.close({ type: 'S', name: 'bang' });
|
||||
var expected = new buffer_list_1.default().addChar('S').addCString('bang').join(true, 'C');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('describe unnamed portal', function () {
|
||||
const actual = serializer_1.serialize.close({ type: 'P' });
|
||||
var expected = new buffer_list_1.default().addChar('P').addCString('').join(true, 'C');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
describe('copy messages', function () {
|
||||
it('builds copyFromChunk', () => {
|
||||
const actual = serializer_1.serialize.copyData(Buffer.from([1, 2, 3]));
|
||||
const expected = new buffer_list_1.default().add(Buffer.from([1, 2, 3])).join(true, 'd');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('builds copy fail', () => {
|
||||
const actual = serializer_1.serialize.copyFail('err!');
|
||||
const expected = new buffer_list_1.default().addCString('err!').join(true, 'f');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
it('builds copy done', () => {
|
||||
const actual = serializer_1.serialize.copyDone();
|
||||
const expected = new buffer_list_1.default().join(true, 'c');
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
it('builds cancel message', () => {
|
||||
const actual = serializer_1.serialize.cancel(3, 4);
|
||||
const expected = new buffer_list_1.default().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true);
|
||||
assert_1.default.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=outbound-serializer.test.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/outbound-serializer.test.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/outbound-serializer.test.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
39
websocket_server/node_modules/pg-protocol/dist/parser.d.ts
generated
vendored
Normal file
39
websocket_server/node_modules/pg-protocol/dist/parser.d.ts
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference types="node" />
|
||||
import { TransformOptions } from 'stream';
|
||||
import { Mode, BackendMessage } from './messages';
|
||||
export declare type Packet = {
|
||||
code: number;
|
||||
packet: Buffer;
|
||||
};
|
||||
declare type StreamOptions = TransformOptions & {
|
||||
mode: Mode;
|
||||
};
|
||||
export declare type MessageCallback = (msg: BackendMessage) => void;
|
||||
export declare class Parser {
|
||||
private buffer;
|
||||
private bufferLength;
|
||||
private bufferOffset;
|
||||
private reader;
|
||||
private mode;
|
||||
constructor(opts?: StreamOptions);
|
||||
parse(buffer: Buffer, callback: MessageCallback): void;
|
||||
private mergeBuffer;
|
||||
private handlePacket;
|
||||
private parseReadyForQueryMessage;
|
||||
private parseCommandCompleteMessage;
|
||||
private parseCopyData;
|
||||
private parseCopyInMessage;
|
||||
private parseCopyOutMessage;
|
||||
private parseCopyMessage;
|
||||
private parseNotificationMessage;
|
||||
private parseRowDescriptionMessage;
|
||||
private parseField;
|
||||
private parseParameterDescriptionMessage;
|
||||
private parseDataRowMessage;
|
||||
private parseParameterStatusMessage;
|
||||
private parseBackendKeyData;
|
||||
parseAuthenticationResponse(offset: number, length: number, bytes: Buffer): any;
|
||||
private parseErrorMessage;
|
||||
}
|
||||
export {};
|
304
websocket_server/node_modules/pg-protocol/dist/parser.js
generated
vendored
Normal file
304
websocket_server/node_modules/pg-protocol/dist/parser.js
generated
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Parser = void 0;
|
||||
const messages_1 = require("./messages");
|
||||
const buffer_reader_1 = require("./buffer-reader");
|
||||
// every message is prefixed with a single bye
|
||||
const CODE_LENGTH = 1;
|
||||
// every message has an int32 length which includes itself but does
|
||||
// NOT include the code in the length
|
||||
const LEN_LENGTH = 4;
|
||||
const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH;
|
||||
const emptyBuffer = Buffer.allocUnsafe(0);
|
||||
class Parser {
|
||||
constructor(opts) {
|
||||
this.buffer = emptyBuffer;
|
||||
this.bufferLength = 0;
|
||||
this.bufferOffset = 0;
|
||||
this.reader = new buffer_reader_1.BufferReader();
|
||||
if ((opts === null || opts === void 0 ? void 0 : opts.mode) === 'binary') {
|
||||
throw new Error('Binary mode not supported yet');
|
||||
}
|
||||
this.mode = (opts === null || opts === void 0 ? void 0 : opts.mode) || 'text';
|
||||
}
|
||||
parse(buffer, callback) {
|
||||
this.mergeBuffer(buffer);
|
||||
const bufferFullLength = this.bufferOffset + this.bufferLength;
|
||||
let offset = this.bufferOffset;
|
||||
while (offset + HEADER_LENGTH <= bufferFullLength) {
|
||||
// code is 1 byte long - it identifies the message type
|
||||
const code = this.buffer[offset];
|
||||
// length is 1 Uint32BE - it is the length of the message EXCLUDING the code
|
||||
const length = this.buffer.readUInt32BE(offset + CODE_LENGTH);
|
||||
const fullMessageLength = CODE_LENGTH + length;
|
||||
if (fullMessageLength + offset <= bufferFullLength) {
|
||||
const message = this.handlePacket(offset + HEADER_LENGTH, code, length, this.buffer);
|
||||
callback(message);
|
||||
offset += fullMessageLength;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (offset === bufferFullLength) {
|
||||
// No more use for the buffer
|
||||
this.buffer = emptyBuffer;
|
||||
this.bufferLength = 0;
|
||||
this.bufferOffset = 0;
|
||||
}
|
||||
else {
|
||||
// Adjust the cursors of remainingBuffer
|
||||
this.bufferLength = bufferFullLength - offset;
|
||||
this.bufferOffset = offset;
|
||||
}
|
||||
}
|
||||
mergeBuffer(buffer) {
|
||||
if (this.bufferLength > 0) {
|
||||
const newLength = this.bufferLength + buffer.byteLength;
|
||||
const newFullLength = newLength + this.bufferOffset;
|
||||
if (newFullLength > this.buffer.byteLength) {
|
||||
// We can't concat the new buffer with the remaining one
|
||||
let newBuffer;
|
||||
if (newLength <= this.buffer.byteLength && this.bufferOffset >= this.bufferLength) {
|
||||
// We can move the relevant part to the beginning of the buffer instead of allocating a new buffer
|
||||
newBuffer = this.buffer;
|
||||
}
|
||||
else {
|
||||
// Allocate a new larger buffer
|
||||
let newBufferLength = this.buffer.byteLength * 2;
|
||||
while (newLength >= newBufferLength) {
|
||||
newBufferLength *= 2;
|
||||
}
|
||||
newBuffer = Buffer.allocUnsafe(newBufferLength);
|
||||
}
|
||||
// Move the remaining buffer to the new one
|
||||
this.buffer.copy(newBuffer, 0, this.bufferOffset, this.bufferOffset + this.bufferLength);
|
||||
this.buffer = newBuffer;
|
||||
this.bufferOffset = 0;
|
||||
}
|
||||
// Concat the new buffer with the remaining one
|
||||
buffer.copy(this.buffer, this.bufferOffset + this.bufferLength);
|
||||
this.bufferLength = newLength;
|
||||
}
|
||||
else {
|
||||
this.buffer = buffer;
|
||||
this.bufferOffset = 0;
|
||||
this.bufferLength = buffer.byteLength;
|
||||
}
|
||||
}
|
||||
handlePacket(offset, code, length, bytes) {
|
||||
switch (code) {
|
||||
case 50 /* MessageCodes.BindComplete */:
|
||||
return messages_1.bindComplete;
|
||||
case 49 /* MessageCodes.ParseComplete */:
|
||||
return messages_1.parseComplete;
|
||||
case 51 /* MessageCodes.CloseComplete */:
|
||||
return messages_1.closeComplete;
|
||||
case 110 /* MessageCodes.NoData */:
|
||||
return messages_1.noData;
|
||||
case 115 /* MessageCodes.PortalSuspended */:
|
||||
return messages_1.portalSuspended;
|
||||
case 99 /* MessageCodes.CopyDone */:
|
||||
return messages_1.copyDone;
|
||||
case 87 /* MessageCodes.ReplicationStart */:
|
||||
return messages_1.replicationStart;
|
||||
case 73 /* MessageCodes.EmptyQuery */:
|
||||
return messages_1.emptyQuery;
|
||||
case 68 /* MessageCodes.DataRow */:
|
||||
return this.parseDataRowMessage(offset, length, bytes);
|
||||
case 67 /* MessageCodes.CommandComplete */:
|
||||
return this.parseCommandCompleteMessage(offset, length, bytes);
|
||||
case 90 /* MessageCodes.ReadyForQuery */:
|
||||
return this.parseReadyForQueryMessage(offset, length, bytes);
|
||||
case 65 /* MessageCodes.NotificationResponse */:
|
||||
return this.parseNotificationMessage(offset, length, bytes);
|
||||
case 82 /* MessageCodes.AuthenticationResponse */:
|
||||
return this.parseAuthenticationResponse(offset, length, bytes);
|
||||
case 83 /* MessageCodes.ParameterStatus */:
|
||||
return this.parseParameterStatusMessage(offset, length, bytes);
|
||||
case 75 /* MessageCodes.BackendKeyData */:
|
||||
return this.parseBackendKeyData(offset, length, bytes);
|
||||
case 69 /* MessageCodes.ErrorMessage */:
|
||||
return this.parseErrorMessage(offset, length, bytes, 'error');
|
||||
case 78 /* MessageCodes.NoticeMessage */:
|
||||
return this.parseErrorMessage(offset, length, bytes, 'notice');
|
||||
case 84 /* MessageCodes.RowDescriptionMessage */:
|
||||
return this.parseRowDescriptionMessage(offset, length, bytes);
|
||||
case 116 /* MessageCodes.ParameterDescriptionMessage */:
|
||||
return this.parseParameterDescriptionMessage(offset, length, bytes);
|
||||
case 71 /* MessageCodes.CopyIn */:
|
||||
return this.parseCopyInMessage(offset, length, bytes);
|
||||
case 72 /* MessageCodes.CopyOut */:
|
||||
return this.parseCopyOutMessage(offset, length, bytes);
|
||||
case 100 /* MessageCodes.CopyData */:
|
||||
return this.parseCopyData(offset, length, bytes);
|
||||
default:
|
||||
return new messages_1.DatabaseError('received invalid response: ' + code.toString(16), length, 'error');
|
||||
}
|
||||
}
|
||||
parseReadyForQueryMessage(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const status = this.reader.string(1);
|
||||
return new messages_1.ReadyForQueryMessage(length, status);
|
||||
}
|
||||
parseCommandCompleteMessage(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const text = this.reader.cstring();
|
||||
return new messages_1.CommandCompleteMessage(length, text);
|
||||
}
|
||||
parseCopyData(offset, length, bytes) {
|
||||
const chunk = bytes.slice(offset, offset + (length - 4));
|
||||
return new messages_1.CopyDataMessage(length, chunk);
|
||||
}
|
||||
parseCopyInMessage(offset, length, bytes) {
|
||||
return this.parseCopyMessage(offset, length, bytes, 'copyInResponse');
|
||||
}
|
||||
parseCopyOutMessage(offset, length, bytes) {
|
||||
return this.parseCopyMessage(offset, length, bytes, 'copyOutResponse');
|
||||
}
|
||||
parseCopyMessage(offset, length, bytes, messageName) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const isBinary = this.reader.byte() !== 0;
|
||||
const columnCount = this.reader.int16();
|
||||
const message = new messages_1.CopyResponse(length, messageName, isBinary, columnCount);
|
||||
for (let i = 0; i < columnCount; i++) {
|
||||
message.columnTypes[i] = this.reader.int16();
|
||||
}
|
||||
return message;
|
||||
}
|
||||
parseNotificationMessage(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const processId = this.reader.int32();
|
||||
const channel = this.reader.cstring();
|
||||
const payload = this.reader.cstring();
|
||||
return new messages_1.NotificationResponseMessage(length, processId, channel, payload);
|
||||
}
|
||||
parseRowDescriptionMessage(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const fieldCount = this.reader.int16();
|
||||
const message = new messages_1.RowDescriptionMessage(length, fieldCount);
|
||||
for (let i = 0; i < fieldCount; i++) {
|
||||
message.fields[i] = this.parseField();
|
||||
}
|
||||
return message;
|
||||
}
|
||||
parseField() {
|
||||
const name = this.reader.cstring();
|
||||
const tableID = this.reader.int32();
|
||||
const columnID = this.reader.int16();
|
||||
const dataTypeID = this.reader.int32();
|
||||
const dataTypeSize = this.reader.int16();
|
||||
const dataTypeModifier = this.reader.int32();
|
||||
const mode = this.reader.int16() === 0 ? 'text' : 'binary';
|
||||
return new messages_1.Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode);
|
||||
}
|
||||
parseParameterDescriptionMessage(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const parameterCount = this.reader.int16();
|
||||
const message = new messages_1.ParameterDescriptionMessage(length, parameterCount);
|
||||
for (let i = 0; i < parameterCount; i++) {
|
||||
message.dataTypeIDs[i] = this.reader.int32();
|
||||
}
|
||||
return message;
|
||||
}
|
||||
parseDataRowMessage(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const fieldCount = this.reader.int16();
|
||||
const fields = new Array(fieldCount);
|
||||
for (let i = 0; i < fieldCount; i++) {
|
||||
const len = this.reader.int32();
|
||||
// a -1 for length means the value of the field is null
|
||||
fields[i] = len === -1 ? null : this.reader.string(len);
|
||||
}
|
||||
return new messages_1.DataRowMessage(length, fields);
|
||||
}
|
||||
parseParameterStatusMessage(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const name = this.reader.cstring();
|
||||
const value = this.reader.cstring();
|
||||
return new messages_1.ParameterStatusMessage(length, name, value);
|
||||
}
|
||||
parseBackendKeyData(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const processID = this.reader.int32();
|
||||
const secretKey = this.reader.int32();
|
||||
return new messages_1.BackendKeyDataMessage(length, processID, secretKey);
|
||||
}
|
||||
parseAuthenticationResponse(offset, length, bytes) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const code = this.reader.int32();
|
||||
// TODO(bmc): maybe better types here
|
||||
const message = {
|
||||
name: 'authenticationOk',
|
||||
length,
|
||||
};
|
||||
switch (code) {
|
||||
case 0: // AuthenticationOk
|
||||
break;
|
||||
case 3: // AuthenticationCleartextPassword
|
||||
if (message.length === 8) {
|
||||
message.name = 'authenticationCleartextPassword';
|
||||
}
|
||||
break;
|
||||
case 5: // AuthenticationMD5Password
|
||||
if (message.length === 12) {
|
||||
message.name = 'authenticationMD5Password';
|
||||
const salt = this.reader.bytes(4);
|
||||
return new messages_1.AuthenticationMD5Password(length, salt);
|
||||
}
|
||||
break;
|
||||
case 10: // AuthenticationSASL
|
||||
message.name = 'authenticationSASL';
|
||||
message.mechanisms = [];
|
||||
let mechanism;
|
||||
do {
|
||||
mechanism = this.reader.cstring();
|
||||
if (mechanism) {
|
||||
message.mechanisms.push(mechanism);
|
||||
}
|
||||
} while (mechanism);
|
||||
break;
|
||||
case 11: // AuthenticationSASLContinue
|
||||
message.name = 'authenticationSASLContinue';
|
||||
message.data = this.reader.string(length - 8);
|
||||
break;
|
||||
case 12: // AuthenticationSASLFinal
|
||||
message.name = 'authenticationSASLFinal';
|
||||
message.data = this.reader.string(length - 8);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown authenticationOk message type ' + code);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
parseErrorMessage(offset, length, bytes, name) {
|
||||
this.reader.setBuffer(offset, bytes);
|
||||
const fields = {};
|
||||
let fieldType = this.reader.string(1);
|
||||
while (fieldType !== '\0') {
|
||||
fields[fieldType] = this.reader.cstring();
|
||||
fieldType = this.reader.string(1);
|
||||
}
|
||||
const messageValue = fields.M;
|
||||
const message = name === 'notice' ? new messages_1.NoticeMessage(length, messageValue) : new messages_1.DatabaseError(messageValue, length, name);
|
||||
message.severity = fields.S;
|
||||
message.code = fields.C;
|
||||
message.detail = fields.D;
|
||||
message.hint = fields.H;
|
||||
message.position = fields.P;
|
||||
message.internalPosition = fields.p;
|
||||
message.internalQuery = fields.q;
|
||||
message.where = fields.W;
|
||||
message.schema = fields.s;
|
||||
message.table = fields.t;
|
||||
message.column = fields.c;
|
||||
message.dataType = fields.d;
|
||||
message.constraint = fields.n;
|
||||
message.file = fields.F;
|
||||
message.line = fields.L;
|
||||
message.routine = fields.R;
|
||||
return message;
|
||||
}
|
||||
}
|
||||
exports.Parser = Parser;
|
||||
//# sourceMappingURL=parser.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/parser.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/parser.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
42
websocket_server/node_modules/pg-protocol/dist/serializer.d.ts
generated
vendored
Normal file
42
websocket_server/node_modules/pg-protocol/dist/serializer.d.ts
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
declare type ParseOpts = {
|
||||
name?: string;
|
||||
types?: number[];
|
||||
text: string;
|
||||
};
|
||||
declare type ValueMapper = (param: any, index: number) => any;
|
||||
declare type BindOpts = {
|
||||
portal?: string;
|
||||
binary?: boolean;
|
||||
statement?: string;
|
||||
values?: any[];
|
||||
valueMapper?: ValueMapper;
|
||||
};
|
||||
declare type ExecOpts = {
|
||||
portal?: string;
|
||||
rows?: number;
|
||||
};
|
||||
declare type PortalOpts = {
|
||||
type: 'S' | 'P';
|
||||
name?: string;
|
||||
};
|
||||
declare const serialize: {
|
||||
startup: (opts: Record<string, string>) => Buffer;
|
||||
password: (password: string) => Buffer;
|
||||
requestSsl: () => Buffer;
|
||||
sendSASLInitialResponseMessage: (mechanism: string, initialResponse: string) => Buffer;
|
||||
sendSCRAMClientFinalMessage: (additionalData: string) => Buffer;
|
||||
query: (text: string) => Buffer;
|
||||
parse: (query: ParseOpts) => Buffer;
|
||||
bind: (config?: BindOpts) => Buffer;
|
||||
execute: (config?: ExecOpts) => Buffer;
|
||||
describe: (msg: PortalOpts) => Buffer;
|
||||
close: (msg: PortalOpts) => Buffer;
|
||||
flush: () => Buffer;
|
||||
sync: () => Buffer;
|
||||
end: () => Buffer;
|
||||
copyData: (chunk: Buffer) => Buffer;
|
||||
copyDone: () => Buffer;
|
||||
copyFail: (message: string) => Buffer;
|
||||
cancel: (processID: number, secretKey: number) => Buffer;
|
||||
};
|
||||
export { serialize };
|
189
websocket_server/node_modules/pg-protocol/dist/serializer.js
generated
vendored
Normal file
189
websocket_server/node_modules/pg-protocol/dist/serializer.js
generated
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.serialize = void 0;
|
||||
const buffer_writer_1 = require("./buffer-writer");
|
||||
const writer = new buffer_writer_1.Writer();
|
||||
const startup = (opts) => {
|
||||
// protocol version
|
||||
writer.addInt16(3).addInt16(0);
|
||||
for (const key of Object.keys(opts)) {
|
||||
writer.addCString(key).addCString(opts[key]);
|
||||
}
|
||||
writer.addCString('client_encoding').addCString('UTF8');
|
||||
var bodyBuffer = writer.addCString('').flush();
|
||||
// this message is sent without a code
|
||||
var length = bodyBuffer.length + 4;
|
||||
return new buffer_writer_1.Writer().addInt32(length).add(bodyBuffer).flush();
|
||||
};
|
||||
const requestSsl = () => {
|
||||
const response = Buffer.allocUnsafe(8);
|
||||
response.writeInt32BE(8, 0);
|
||||
response.writeInt32BE(80877103, 4);
|
||||
return response;
|
||||
};
|
||||
const password = (password) => {
|
||||
return writer.addCString(password).flush(112 /* code.startup */);
|
||||
};
|
||||
const sendSASLInitialResponseMessage = function (mechanism, initialResponse) {
|
||||
// 0x70 = 'p'
|
||||
writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse);
|
||||
return writer.flush(112 /* code.startup */);
|
||||
};
|
||||
const sendSCRAMClientFinalMessage = function (additionalData) {
|
||||
return writer.addString(additionalData).flush(112 /* code.startup */);
|
||||
};
|
||||
const query = (text) => {
|
||||
return writer.addCString(text).flush(81 /* code.query */);
|
||||
};
|
||||
const emptyArray = [];
|
||||
const parse = (query) => {
|
||||
// expect something like this:
|
||||
// { name: 'queryName',
|
||||
// text: 'select * from blah',
|
||||
// types: ['int8', 'bool'] }
|
||||
// normalize missing query names to allow for null
|
||||
const name = query.name || '';
|
||||
if (name.length > 63) {
|
||||
/* eslint-disable no-console */
|
||||
console.error('Warning! Postgres only supports 63 characters for query names.');
|
||||
console.error('You supplied %s (%s)', name, name.length);
|
||||
console.error('This can cause conflicts and silent errors executing queries');
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
const types = query.types || emptyArray;
|
||||
var len = types.length;
|
||||
var buffer = writer
|
||||
.addCString(name) // name of query
|
||||
.addCString(query.text) // actual query text
|
||||
.addInt16(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
buffer.addInt32(types[i]);
|
||||
}
|
||||
return writer.flush(80 /* code.parse */);
|
||||
};
|
||||
const paramWriter = new buffer_writer_1.Writer();
|
||||
const writeValues = function (values, valueMapper) {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
const mappedVal = valueMapper ? valueMapper(values[i], i) : values[i];
|
||||
if (mappedVal == null) {
|
||||
// add the param type (string) to the writer
|
||||
writer.addInt16(0 /* ParamType.STRING */);
|
||||
// write -1 to the param writer to indicate null
|
||||
paramWriter.addInt32(-1);
|
||||
}
|
||||
else if (mappedVal instanceof Buffer) {
|
||||
// add the param type (binary) to the writer
|
||||
writer.addInt16(1 /* ParamType.BINARY */);
|
||||
// add the buffer to the param writer
|
||||
paramWriter.addInt32(mappedVal.length);
|
||||
paramWriter.add(mappedVal);
|
||||
}
|
||||
else {
|
||||
// add the param type (string) to the writer
|
||||
writer.addInt16(0 /* ParamType.STRING */);
|
||||
paramWriter.addInt32(Buffer.byteLength(mappedVal));
|
||||
paramWriter.addString(mappedVal);
|
||||
}
|
||||
}
|
||||
};
|
||||
const bind = (config = {}) => {
|
||||
// normalize config
|
||||
const portal = config.portal || '';
|
||||
const statement = config.statement || '';
|
||||
const binary = config.binary || false;
|
||||
const values = config.values || emptyArray;
|
||||
const len = values.length;
|
||||
writer.addCString(portal).addCString(statement);
|
||||
writer.addInt16(len);
|
||||
writeValues(values, config.valueMapper);
|
||||
writer.addInt16(len);
|
||||
writer.add(paramWriter.flush());
|
||||
// format code
|
||||
writer.addInt16(binary ? 1 /* ParamType.BINARY */ : 0 /* ParamType.STRING */);
|
||||
return writer.flush(66 /* code.bind */);
|
||||
};
|
||||
const emptyExecute = Buffer.from([69 /* code.execute */, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
const execute = (config) => {
|
||||
// this is the happy path for most queries
|
||||
if (!config || (!config.portal && !config.rows)) {
|
||||
return emptyExecute;
|
||||
}
|
||||
const portal = config.portal || '';
|
||||
const rows = config.rows || 0;
|
||||
const portalLength = Buffer.byteLength(portal);
|
||||
const len = 4 + portalLength + 1 + 4;
|
||||
// one extra bit for code
|
||||
const buff = Buffer.allocUnsafe(1 + len);
|
||||
buff[0] = 69 /* code.execute */;
|
||||
buff.writeInt32BE(len, 1);
|
||||
buff.write(portal, 5, 'utf-8');
|
||||
buff[portalLength + 5] = 0; // null terminate portal cString
|
||||
buff.writeUInt32BE(rows, buff.length - 4);
|
||||
return buff;
|
||||
};
|
||||
const cancel = (processID, secretKey) => {
|
||||
const buffer = Buffer.allocUnsafe(16);
|
||||
buffer.writeInt32BE(16, 0);
|
||||
buffer.writeInt16BE(1234, 4);
|
||||
buffer.writeInt16BE(5678, 6);
|
||||
buffer.writeInt32BE(processID, 8);
|
||||
buffer.writeInt32BE(secretKey, 12);
|
||||
return buffer;
|
||||
};
|
||||
const cstringMessage = (code, string) => {
|
||||
const stringLen = Buffer.byteLength(string);
|
||||
const len = 4 + stringLen + 1;
|
||||
// one extra bit for code
|
||||
const buffer = Buffer.allocUnsafe(1 + len);
|
||||
buffer[0] = code;
|
||||
buffer.writeInt32BE(len, 1);
|
||||
buffer.write(string, 5, 'utf-8');
|
||||
buffer[len] = 0; // null terminate cString
|
||||
return buffer;
|
||||
};
|
||||
const emptyDescribePortal = writer.addCString('P').flush(68 /* code.describe */);
|
||||
const emptyDescribeStatement = writer.addCString('S').flush(68 /* code.describe */);
|
||||
const describe = (msg) => {
|
||||
return msg.name
|
||||
? cstringMessage(68 /* code.describe */, `${msg.type}${msg.name || ''}`)
|
||||
: msg.type === 'P'
|
||||
? emptyDescribePortal
|
||||
: emptyDescribeStatement;
|
||||
};
|
||||
const close = (msg) => {
|
||||
const text = `${msg.type}${msg.name || ''}`;
|
||||
return cstringMessage(67 /* code.close */, text);
|
||||
};
|
||||
const copyData = (chunk) => {
|
||||
return writer.add(chunk).flush(100 /* code.copyFromChunk */);
|
||||
};
|
||||
const copyFail = (message) => {
|
||||
return cstringMessage(102 /* code.copyFail */, message);
|
||||
};
|
||||
const codeOnlyBuffer = (code) => Buffer.from([code, 0x00, 0x00, 0x00, 0x04]);
|
||||
const flushBuffer = codeOnlyBuffer(72 /* code.flush */);
|
||||
const syncBuffer = codeOnlyBuffer(83 /* code.sync */);
|
||||
const endBuffer = codeOnlyBuffer(88 /* code.end */);
|
||||
const copyDoneBuffer = codeOnlyBuffer(99 /* code.copyDone */);
|
||||
const serialize = {
|
||||
startup,
|
||||
password,
|
||||
requestSsl,
|
||||
sendSASLInitialResponseMessage,
|
||||
sendSCRAMClientFinalMessage,
|
||||
query,
|
||||
parse,
|
||||
bind,
|
||||
execute,
|
||||
describe,
|
||||
close,
|
||||
flush: () => flushBuffer,
|
||||
sync: () => syncBuffer,
|
||||
end: () => endBuffer,
|
||||
copyData,
|
||||
copyDone: () => copyDoneBuffer,
|
||||
copyFail,
|
||||
cancel,
|
||||
};
|
||||
exports.serialize = serialize;
|
||||
//# sourceMappingURL=serializer.js.map
|
1
websocket_server/node_modules/pg-protocol/dist/serializer.js.map
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/dist/serializer.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
35
websocket_server/node_modules/pg-protocol/package.json
generated
vendored
Normal file
35
websocket_server/node_modules/pg-protocol/package.json
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "pg-protocol",
|
||||
"version": "1.7.0",
|
||||
"description": "The postgres client/server binary protocol, implemented in TypeScript",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.7",
|
||||
"@types/mocha": "^10.0.7",
|
||||
"@types/node": "^12.12.21",
|
||||
"chai": "^4.2.0",
|
||||
"chunky": "^0.0.0",
|
||||
"mocha": "^10.5.2",
|
||||
"ts-node": "^8.5.4",
|
||||
"typescript": "^4.0.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha dist/**/*.test.js",
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc --watch",
|
||||
"prepublish": "yarn build",
|
||||
"pretest": "yarn build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/brianc/node-postgres.git",
|
||||
"directory": "packages/pg-protocol"
|
||||
},
|
||||
"files": [
|
||||
"/dist/*{js,ts,map}",
|
||||
"/src"
|
||||
],
|
||||
"gitHead": "92cb640fd316972e323ced6256b2acd89b1b58e0"
|
||||
}
|
25
websocket_server/node_modules/pg-protocol/src/b.ts
generated
vendored
Normal file
25
websocket_server/node_modules/pg-protocol/src/b.ts
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// file for microbenchmarking
|
||||
|
||||
import { BufferReader } from './buffer-reader'
|
||||
|
||||
const LOOPS = 1000
|
||||
let count = 0
|
||||
let start = Date.now()
|
||||
|
||||
const reader = new BufferReader()
|
||||
const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0])
|
||||
|
||||
const run = () => {
|
||||
if (count > LOOPS) {
|
||||
console.log(Date.now() - start)
|
||||
return
|
||||
}
|
||||
count++
|
||||
for (let i = 0; i < LOOPS; i++) {
|
||||
reader.setBuffer(0, buffer)
|
||||
reader.cstring()
|
||||
}
|
||||
setImmediate(run)
|
||||
}
|
||||
|
||||
run()
|
53
websocket_server/node_modules/pg-protocol/src/buffer-reader.ts
generated
vendored
Normal file
53
websocket_server/node_modules/pg-protocol/src/buffer-reader.ts
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
const emptyBuffer = Buffer.allocUnsafe(0)
|
||||
|
||||
export class BufferReader {
|
||||
private buffer: Buffer = emptyBuffer
|
||||
|
||||
// TODO(bmc): support non-utf8 encoding?
|
||||
private encoding: string = 'utf-8'
|
||||
|
||||
constructor(private offset: number = 0) {}
|
||||
|
||||
public setBuffer(offset: number, buffer: Buffer): void {
|
||||
this.offset = offset
|
||||
this.buffer = buffer
|
||||
}
|
||||
|
||||
public int16(): number {
|
||||
const result = this.buffer.readInt16BE(this.offset)
|
||||
this.offset += 2
|
||||
return result
|
||||
}
|
||||
|
||||
public byte(): number {
|
||||
const result = this.buffer[this.offset]
|
||||
this.offset++
|
||||
return result
|
||||
}
|
||||
|
||||
public int32(): number {
|
||||
const result = this.buffer.readInt32BE(this.offset)
|
||||
this.offset += 4
|
||||
return result
|
||||
}
|
||||
|
||||
public string(length: number): string {
|
||||
const result = this.buffer.toString(this.encoding, this.offset, this.offset + length)
|
||||
this.offset += length
|
||||
return result
|
||||
}
|
||||
|
||||
public cstring(): string {
|
||||
const start = this.offset
|
||||
let end = start
|
||||
while (this.buffer[end++] !== 0) {}
|
||||
this.offset = end
|
||||
return this.buffer.toString(this.encoding, start, end - 1)
|
||||
}
|
||||
|
||||
public bytes(length: number): Buffer {
|
||||
const result = this.buffer.slice(this.offset, this.offset + length)
|
||||
this.offset += length
|
||||
return result
|
||||
}
|
||||
}
|
85
websocket_server/node_modules/pg-protocol/src/buffer-writer.ts
generated
vendored
Normal file
85
websocket_server/node_modules/pg-protocol/src/buffer-writer.ts
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
//binary data writer tuned for encoding binary specific to the postgres binary protocol
|
||||
|
||||
export class Writer {
|
||||
private buffer: Buffer
|
||||
private offset: number = 5
|
||||
private headerPosition: number = 0
|
||||
constructor(private size = 256) {
|
||||
this.buffer = Buffer.allocUnsafe(size)
|
||||
}
|
||||
|
||||
private ensure(size: number): void {
|
||||
var remaining = this.buffer.length - this.offset
|
||||
if (remaining < size) {
|
||||
var oldBuffer = this.buffer
|
||||
// exponential growth factor of around ~ 1.5
|
||||
// https://stackoverflow.com/questions/2269063/buffer-growth-strategy
|
||||
var newSize = oldBuffer.length + (oldBuffer.length >> 1) + size
|
||||
this.buffer = Buffer.allocUnsafe(newSize)
|
||||
oldBuffer.copy(this.buffer)
|
||||
}
|
||||
}
|
||||
|
||||
public addInt32(num: number): Writer {
|
||||
this.ensure(4)
|
||||
this.buffer[this.offset++] = (num >>> 24) & 0xff
|
||||
this.buffer[this.offset++] = (num >>> 16) & 0xff
|
||||
this.buffer[this.offset++] = (num >>> 8) & 0xff
|
||||
this.buffer[this.offset++] = (num >>> 0) & 0xff
|
||||
return this
|
||||
}
|
||||
|
||||
public addInt16(num: number): Writer {
|
||||
this.ensure(2)
|
||||
this.buffer[this.offset++] = (num >>> 8) & 0xff
|
||||
this.buffer[this.offset++] = (num >>> 0) & 0xff
|
||||
return this
|
||||
}
|
||||
|
||||
public addCString(string: string): Writer {
|
||||
if (!string) {
|
||||
this.ensure(1)
|
||||
} else {
|
||||
var len = Buffer.byteLength(string)
|
||||
this.ensure(len + 1) // +1 for null terminator
|
||||
this.buffer.write(string, this.offset, 'utf-8')
|
||||
this.offset += len
|
||||
}
|
||||
|
||||
this.buffer[this.offset++] = 0 // null terminator
|
||||
return this
|
||||
}
|
||||
|
||||
public addString(string: string = ''): Writer {
|
||||
var len = Buffer.byteLength(string)
|
||||
this.ensure(len)
|
||||
this.buffer.write(string, this.offset)
|
||||
this.offset += len
|
||||
return this
|
||||
}
|
||||
|
||||
public add(otherBuffer: Buffer): Writer {
|
||||
this.ensure(otherBuffer.length)
|
||||
otherBuffer.copy(this.buffer, this.offset)
|
||||
this.offset += otherBuffer.length
|
||||
return this
|
||||
}
|
||||
|
||||
private join(code?: number): Buffer {
|
||||
if (code) {
|
||||
this.buffer[this.headerPosition] = code
|
||||
//length is everything in this packet minus the code
|
||||
const length = this.offset - (this.headerPosition + 1)
|
||||
this.buffer.writeInt32BE(length, this.headerPosition + 1)
|
||||
}
|
||||
return this.buffer.slice(code ? 0 : 5, this.offset)
|
||||
}
|
||||
|
||||
public flush(code?: number): Buffer {
|
||||
var result = this.join(code)
|
||||
this.offset = 5
|
||||
this.headerPosition = 0
|
||||
this.buffer = Buffer.allocUnsafe(this.size)
|
||||
return result
|
||||
}
|
||||
}
|
546
websocket_server/node_modules/pg-protocol/src/inbound-parser.test.ts
generated
vendored
Normal file
546
websocket_server/node_modules/pg-protocol/src/inbound-parser.test.ts
generated
vendored
Normal file
@ -0,0 +1,546 @@
|
||||
import buffers from './testing/test-buffers'
|
||||
import BufferList from './testing/buffer-list'
|
||||
import { parse } from '.'
|
||||
import assert from 'assert'
|
||||
import { PassThrough } from 'stream'
|
||||
import { BackendMessage } from './messages'
|
||||
|
||||
var authOkBuffer = buffers.authenticationOk()
|
||||
var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8')
|
||||
var readyForQueryBuffer = buffers.readyForQuery()
|
||||
var backendKeyDataBuffer = buffers.backendKeyData(1, 2)
|
||||
var commandCompleteBuffer = buffers.commandComplete('SELECT 3')
|
||||
var parseCompleteBuffer = buffers.parseComplete()
|
||||
var bindCompleteBuffer = buffers.bindComplete()
|
||||
var portalSuspendedBuffer = buffers.portalSuspended()
|
||||
|
||||
var row1 = {
|
||||
name: 'id',
|
||||
tableID: 1,
|
||||
attributeNumber: 2,
|
||||
dataTypeID: 3,
|
||||
dataTypeSize: 4,
|
||||
typeModifier: 5,
|
||||
formatCode: 0,
|
||||
}
|
||||
var oneRowDescBuff = buffers.rowDescription([row1])
|
||||
row1.name = 'bang'
|
||||
|
||||
var twoRowBuf = buffers.rowDescription([
|
||||
row1,
|
||||
{
|
||||
name: 'whoah',
|
||||
tableID: 10,
|
||||
attributeNumber: 11,
|
||||
dataTypeID: 12,
|
||||
dataTypeSize: 13,
|
||||
typeModifier: 14,
|
||||
formatCode: 0,
|
||||
},
|
||||
])
|
||||
|
||||
var emptyRowFieldBuf = new BufferList().addInt16(0).join(true, 'D')
|
||||
|
||||
var emptyRowFieldBuf = buffers.dataRow([])
|
||||
|
||||
var oneFieldBuf = new BufferList()
|
||||
.addInt16(1) // number of fields
|
||||
.addInt32(5) // length of bytes of fields
|
||||
.addCString('test')
|
||||
.join(true, 'D')
|
||||
|
||||
var oneFieldBuf = buffers.dataRow(['test'])
|
||||
|
||||
var expectedAuthenticationOkayMessage = {
|
||||
name: 'authenticationOk',
|
||||
length: 8,
|
||||
}
|
||||
|
||||
var expectedParameterStatusMessage = {
|
||||
name: 'parameterStatus',
|
||||
parameterName: 'client_encoding',
|
||||
parameterValue: 'UTF8',
|
||||
length: 25,
|
||||
}
|
||||
|
||||
var expectedBackendKeyDataMessage = {
|
||||
name: 'backendKeyData',
|
||||
processID: 1,
|
||||
secretKey: 2,
|
||||
}
|
||||
|
||||
var expectedReadyForQueryMessage = {
|
||||
name: 'readyForQuery',
|
||||
length: 5,
|
||||
status: 'I',
|
||||
}
|
||||
|
||||
var expectedCommandCompleteMessage = {
|
||||
name: 'commandComplete',
|
||||
length: 13,
|
||||
text: 'SELECT 3',
|
||||
}
|
||||
var emptyRowDescriptionBuffer = new BufferList()
|
||||
.addInt16(0) // number of fields
|
||||
.join(true, 'T')
|
||||
|
||||
var expectedEmptyRowDescriptionMessage = {
|
||||
name: 'rowDescription',
|
||||
length: 6,
|
||||
fieldCount: 0,
|
||||
fields: [],
|
||||
}
|
||||
var expectedOneRowMessage = {
|
||||
name: 'rowDescription',
|
||||
length: 27,
|
||||
fieldCount: 1,
|
||||
fields: [
|
||||
{
|
||||
name: 'id',
|
||||
tableID: 1,
|
||||
columnID: 2,
|
||||
dataTypeID: 3,
|
||||
dataTypeSize: 4,
|
||||
dataTypeModifier: 5,
|
||||
format: 'text',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
var expectedTwoRowMessage = {
|
||||
name: 'rowDescription',
|
||||
length: 53,
|
||||
fieldCount: 2,
|
||||
fields: [
|
||||
{
|
||||
name: 'bang',
|
||||
tableID: 1,
|
||||
columnID: 2,
|
||||
dataTypeID: 3,
|
||||
dataTypeSize: 4,
|
||||
dataTypeModifier: 5,
|
||||
format: 'text',
|
||||
},
|
||||
{
|
||||
name: 'whoah',
|
||||
tableID: 10,
|
||||
columnID: 11,
|
||||
dataTypeID: 12,
|
||||
dataTypeSize: 13,
|
||||
dataTypeModifier: 14,
|
||||
format: 'text',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
var emptyParameterDescriptionBuffer = new BufferList()
|
||||
.addInt16(0) // number of parameters
|
||||
.join(true, 't')
|
||||
|
||||
var oneParameterDescBuf = buffers.parameterDescription([1111])
|
||||
|
||||
var twoParameterDescBuf = buffers.parameterDescription([2222, 3333])
|
||||
|
||||
var expectedEmptyParameterDescriptionMessage = {
|
||||
name: 'parameterDescription',
|
||||
length: 6,
|
||||
parameterCount: 0,
|
||||
dataTypeIDs: [],
|
||||
}
|
||||
|
||||
var expectedOneParameterMessage = {
|
||||
name: 'parameterDescription',
|
||||
length: 10,
|
||||
parameterCount: 1,
|
||||
dataTypeIDs: [1111],
|
||||
}
|
||||
|
||||
var expectedTwoParameterMessage = {
|
||||
name: 'parameterDescription',
|
||||
length: 14,
|
||||
parameterCount: 2,
|
||||
dataTypeIDs: [2222, 3333],
|
||||
}
|
||||
|
||||
var testForMessage = function (buffer: Buffer, expectedMessage: any) {
|
||||
it('recieves and parses ' + expectedMessage.name, async () => {
|
||||
const messages = await parseBuffers([buffer])
|
||||
const [lastMessage] = messages
|
||||
|
||||
for (const key in expectedMessage) {
|
||||
assert.deepEqual((lastMessage as any)[key], expectedMessage[key])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var plainPasswordBuffer = buffers.authenticationCleartextPassword()
|
||||
var md5PasswordBuffer = buffers.authenticationMD5Password()
|
||||
var SASLBuffer = buffers.authenticationSASL()
|
||||
var SASLContinueBuffer = buffers.authenticationSASLContinue()
|
||||
var SASLFinalBuffer = buffers.authenticationSASLFinal()
|
||||
|
||||
var expectedPlainPasswordMessage = {
|
||||
name: 'authenticationCleartextPassword',
|
||||
}
|
||||
|
||||
var expectedMD5PasswordMessage = {
|
||||
name: 'authenticationMD5Password',
|
||||
salt: Buffer.from([1, 2, 3, 4]),
|
||||
}
|
||||
|
||||
var expectedSASLMessage = {
|
||||
name: 'authenticationSASL',
|
||||
mechanisms: ['SCRAM-SHA-256'],
|
||||
}
|
||||
|
||||
var expectedSASLContinueMessage = {
|
||||
name: 'authenticationSASLContinue',
|
||||
data: 'data',
|
||||
}
|
||||
|
||||
var expectedSASLFinalMessage = {
|
||||
name: 'authenticationSASLFinal',
|
||||
data: 'data',
|
||||
}
|
||||
|
||||
var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom')
|
||||
var expectedNotificationResponseMessage = {
|
||||
name: 'notification',
|
||||
processId: 4,
|
||||
channel: 'hi',
|
||||
payload: 'boom',
|
||||
}
|
||||
|
||||
const parseBuffers = async (buffers: Buffer[]): Promise<BackendMessage[]> => {
|
||||
const stream = new PassThrough()
|
||||
for (const buffer of buffers) {
|
||||
stream.write(buffer)
|
||||
}
|
||||
stream.end()
|
||||
const msgs: BackendMessage[] = []
|
||||
await parse(stream, (msg) => msgs.push(msg))
|
||||
return msgs
|
||||
}
|
||||
|
||||
describe('PgPacketStream', function () {
|
||||
testForMessage(authOkBuffer, expectedAuthenticationOkayMessage)
|
||||
testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage)
|
||||
testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage)
|
||||
testForMessage(SASLBuffer, expectedSASLMessage)
|
||||
testForMessage(SASLContinueBuffer, expectedSASLContinueMessage)
|
||||
|
||||
// this exercises a found bug in the parser:
|
||||
// https://github.com/brianc/node-postgres/pull/2210#issuecomment-627626084
|
||||
// and adds a test which is deterministic, rather than relying on network packet chunking
|
||||
const extendedSASLContinueBuffer = Buffer.concat([SASLContinueBuffer, Buffer.from([1, 2, 3, 4])])
|
||||
testForMessage(extendedSASLContinueBuffer, expectedSASLContinueMessage)
|
||||
|
||||
testForMessage(SASLFinalBuffer, expectedSASLFinalMessage)
|
||||
|
||||
// this exercises a found bug in the parser:
|
||||
// https://github.com/brianc/node-postgres/pull/2210#issuecomment-627626084
|
||||
// and adds a test which is deterministic, rather than relying on network packet chunking
|
||||
const extendedSASLFinalBuffer = Buffer.concat([SASLFinalBuffer, Buffer.from([1, 2, 4, 5])])
|
||||
testForMessage(extendedSASLFinalBuffer, expectedSASLFinalMessage)
|
||||
|
||||
testForMessage(paramStatusBuffer, expectedParameterStatusMessage)
|
||||
testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage)
|
||||
testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage)
|
||||
testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage)
|
||||
testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage)
|
||||
testForMessage(buffers.emptyQuery(), {
|
||||
name: 'emptyQuery',
|
||||
length: 4,
|
||||
})
|
||||
|
||||
testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), {
|
||||
name: 'noData',
|
||||
})
|
||||
|
||||
describe('rowDescription messages', function () {
|
||||
testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage)
|
||||
testForMessage(oneRowDescBuff, expectedOneRowMessage)
|
||||
testForMessage(twoRowBuf, expectedTwoRowMessage)
|
||||
})
|
||||
|
||||
describe('parameterDescription messages', function () {
|
||||
testForMessage(emptyParameterDescriptionBuffer, expectedEmptyParameterDescriptionMessage)
|
||||
testForMessage(oneParameterDescBuf, expectedOneParameterMessage)
|
||||
testForMessage(twoParameterDescBuf, expectedTwoParameterMessage)
|
||||
})
|
||||
|
||||
describe('parsing rows', function () {
|
||||
describe('parsing empty row', function () {
|
||||
testForMessage(emptyRowFieldBuf, {
|
||||
name: 'dataRow',
|
||||
fieldCount: 0,
|
||||
})
|
||||
})
|
||||
|
||||
describe('parsing data row with fields', function () {
|
||||
testForMessage(oneFieldBuf, {
|
||||
name: 'dataRow',
|
||||
fieldCount: 1,
|
||||
fields: ['test'],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('notice message', function () {
|
||||
// this uses the same logic as error message
|
||||
var buff = buffers.notice([{ type: 'C', value: 'code' }])
|
||||
testForMessage(buff, {
|
||||
name: 'notice',
|
||||
code: 'code',
|
||||
})
|
||||
})
|
||||
|
||||
testForMessage(buffers.error([]), {
|
||||
name: 'error',
|
||||
})
|
||||
|
||||
describe('with all the fields', function () {
|
||||
var buffer = buffers.error([
|
||||
{
|
||||
type: 'S',
|
||||
value: 'ERROR',
|
||||
},
|
||||
{
|
||||
type: 'C',
|
||||
value: 'code',
|
||||
},
|
||||
{
|
||||
type: 'M',
|
||||
value: 'message',
|
||||
},
|
||||
{
|
||||
type: 'D',
|
||||
value: 'details',
|
||||
},
|
||||
{
|
||||
type: 'H',
|
||||
value: 'hint',
|
||||
},
|
||||
{
|
||||
type: 'P',
|
||||
value: '100',
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
value: '101',
|
||||
},
|
||||
{
|
||||
type: 'q',
|
||||
value: 'query',
|
||||
},
|
||||
{
|
||||
type: 'W',
|
||||
value: 'where',
|
||||
},
|
||||
{
|
||||
type: 'F',
|
||||
value: 'file',
|
||||
},
|
||||
{
|
||||
type: 'L',
|
||||
value: 'line',
|
||||
},
|
||||
{
|
||||
type: 'R',
|
||||
value: 'routine',
|
||||
},
|
||||
{
|
||||
type: 'Z', // ignored
|
||||
value: 'alsdkf',
|
||||
},
|
||||
])
|
||||
|
||||
testForMessage(buffer, {
|
||||
name: 'error',
|
||||
severity: 'ERROR',
|
||||
code: 'code',
|
||||
message: 'message',
|
||||
detail: 'details',
|
||||
hint: 'hint',
|
||||
position: '100',
|
||||
internalPosition: '101',
|
||||
internalQuery: 'query',
|
||||
where: 'where',
|
||||
file: 'file',
|
||||
line: 'line',
|
||||
routine: 'routine',
|
||||
})
|
||||
})
|
||||
|
||||
testForMessage(parseCompleteBuffer, {
|
||||
name: 'parseComplete',
|
||||
})
|
||||
|
||||
testForMessage(bindCompleteBuffer, {
|
||||
name: 'bindComplete',
|
||||
})
|
||||
|
||||
testForMessage(bindCompleteBuffer, {
|
||||
name: 'bindComplete',
|
||||
})
|
||||
|
||||
testForMessage(buffers.closeComplete(), {
|
||||
name: 'closeComplete',
|
||||
})
|
||||
|
||||
describe('parses portal suspended message', function () {
|
||||
testForMessage(portalSuspendedBuffer, {
|
||||
name: 'portalSuspended',
|
||||
})
|
||||
})
|
||||
|
||||
describe('parses replication start message', function () {
|
||||
testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), {
|
||||
name: 'replicationStart',
|
||||
length: 4,
|
||||
})
|
||||
})
|
||||
|
||||
describe('copy', () => {
|
||||
testForMessage(buffers.copyIn(0), {
|
||||
name: 'copyInResponse',
|
||||
length: 7,
|
||||
binary: false,
|
||||
columnTypes: [],
|
||||
})
|
||||
|
||||
testForMessage(buffers.copyIn(2), {
|
||||
name: 'copyInResponse',
|
||||
length: 11,
|
||||
binary: false,
|
||||
columnTypes: [0, 1],
|
||||
})
|
||||
|
||||
testForMessage(buffers.copyOut(0), {
|
||||
name: 'copyOutResponse',
|
||||
length: 7,
|
||||
binary: false,
|
||||
columnTypes: [],
|
||||
})
|
||||
|
||||
testForMessage(buffers.copyOut(3), {
|
||||
name: 'copyOutResponse',
|
||||
length: 13,
|
||||
binary: false,
|
||||
columnTypes: [0, 1, 2],
|
||||
})
|
||||
|
||||
testForMessage(buffers.copyDone(), {
|
||||
name: 'copyDone',
|
||||
length: 4,
|
||||
})
|
||||
|
||||
testForMessage(buffers.copyData(Buffer.from([5, 6, 7])), {
|
||||
name: 'copyData',
|
||||
length: 7,
|
||||
chunk: Buffer.from([5, 6, 7]),
|
||||
})
|
||||
})
|
||||
|
||||
// since the data message on a stream can randomly divide the incomming
|
||||
// tcp packets anywhere, we need to make sure we can parse every single
|
||||
// split on a tcp message
|
||||
describe('split buffer, single message parsing', function () {
|
||||
var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!'])
|
||||
|
||||
it('parses when full buffer comes in', async function () {
|
||||
const messages = await parseBuffers([fullBuffer])
|
||||
const message = messages[0] as any
|
||||
assert.equal(message.fields.length, 5)
|
||||
assert.equal(message.fields[0], null)
|
||||
assert.equal(message.fields[1], 'bang')
|
||||
assert.equal(message.fields[2], 'zug zug')
|
||||
assert.equal(message.fields[3], null)
|
||||
assert.equal(message.fields[4], '!')
|
||||
})
|
||||
|
||||
var testMessageRecievedAfterSpiltAt = async function (split: number) {
|
||||
var firstBuffer = Buffer.alloc(fullBuffer.length - split)
|
||||
var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length)
|
||||
fullBuffer.copy(firstBuffer, 0, 0)
|
||||
fullBuffer.copy(secondBuffer, 0, firstBuffer.length)
|
||||
const messages = await parseBuffers([fullBuffer])
|
||||
const message = messages[0] as any
|
||||
assert.equal(message.fields.length, 5)
|
||||
assert.equal(message.fields[0], null)
|
||||
assert.equal(message.fields[1], 'bang')
|
||||
assert.equal(message.fields[2], 'zug zug')
|
||||
assert.equal(message.fields[3], null)
|
||||
assert.equal(message.fields[4], '!')
|
||||
}
|
||||
|
||||
it('parses when split in the middle', function () {
|
||||
testMessageRecievedAfterSpiltAt(6)
|
||||
})
|
||||
|
||||
it('parses when split at end', function () {
|
||||
testMessageRecievedAfterSpiltAt(2)
|
||||
})
|
||||
|
||||
it('parses when split at beginning', function () {
|
||||
testMessageRecievedAfterSpiltAt(fullBuffer.length - 2)
|
||||
testMessageRecievedAfterSpiltAt(fullBuffer.length - 1)
|
||||
testMessageRecievedAfterSpiltAt(fullBuffer.length - 5)
|
||||
})
|
||||
})
|
||||
|
||||
describe('split buffer, multiple message parsing', function () {
|
||||
var dataRowBuffer = buffers.dataRow(['!'])
|
||||
var readyForQueryBuffer = buffers.readyForQuery()
|
||||
var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length)
|
||||
dataRowBuffer.copy(fullBuffer, 0, 0)
|
||||
readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0)
|
||||
|
||||
var verifyMessages = function (messages: any[]) {
|
||||
assert.strictEqual(messages.length, 2)
|
||||
assert.deepEqual(messages[0], {
|
||||
name: 'dataRow',
|
||||
fieldCount: 1,
|
||||
length: 11,
|
||||
fields: ['!'],
|
||||
})
|
||||
assert.equal(messages[0].fields[0], '!')
|
||||
assert.deepEqual(messages[1], {
|
||||
name: 'readyForQuery',
|
||||
length: 5,
|
||||
status: 'I',
|
||||
})
|
||||
}
|
||||
// sanity check
|
||||
it('recieves both messages when packet is not split', async function () {
|
||||
const messages = await parseBuffers([fullBuffer])
|
||||
verifyMessages(messages)
|
||||
})
|
||||
|
||||
var splitAndVerifyTwoMessages = async function (split: number) {
|
||||
var firstBuffer = Buffer.alloc(fullBuffer.length - split)
|
||||
var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length)
|
||||
fullBuffer.copy(firstBuffer, 0, 0)
|
||||
fullBuffer.copy(secondBuffer, 0, firstBuffer.length)
|
||||
const messages = await parseBuffers([firstBuffer, secondBuffer])
|
||||
verifyMessages(messages)
|
||||
}
|
||||
|
||||
describe('recieves both messages when packet is split', function () {
|
||||
it('in the middle', function () {
|
||||
return splitAndVerifyTwoMessages(11)
|
||||
})
|
||||
it('at the front', function () {
|
||||
return Promise.all([
|
||||
splitAndVerifyTwoMessages(fullBuffer.length - 1),
|
||||
splitAndVerifyTwoMessages(fullBuffer.length - 4),
|
||||
splitAndVerifyTwoMessages(fullBuffer.length - 6),
|
||||
])
|
||||
})
|
||||
|
||||
it('at the end', function () {
|
||||
return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
11
websocket_server/node_modules/pg-protocol/src/index.ts
generated
vendored
Normal file
11
websocket_server/node_modules/pg-protocol/src/index.ts
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
import { DatabaseError } from './messages'
|
||||
import { serialize } from './serializer'
|
||||
import { Parser, MessageCallback } from './parser'
|
||||
|
||||
export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise<void> {
|
||||
const parser = new Parser()
|
||||
stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback))
|
||||
return new Promise((resolve) => stream.on('end', () => resolve()))
|
||||
}
|
||||
|
||||
export { serialize, DatabaseError }
|
262
websocket_server/node_modules/pg-protocol/src/messages.ts
generated
vendored
Normal file
262
websocket_server/node_modules/pg-protocol/src/messages.ts
generated
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
export type Mode = 'text' | 'binary'
|
||||
|
||||
export type MessageName =
|
||||
| 'parseComplete'
|
||||
| 'bindComplete'
|
||||
| 'closeComplete'
|
||||
| 'noData'
|
||||
| 'portalSuspended'
|
||||
| 'replicationStart'
|
||||
| 'emptyQuery'
|
||||
| 'copyDone'
|
||||
| 'copyData'
|
||||
| 'rowDescription'
|
||||
| 'parameterDescription'
|
||||
| 'parameterStatus'
|
||||
| 'backendKeyData'
|
||||
| 'notification'
|
||||
| 'readyForQuery'
|
||||
| 'commandComplete'
|
||||
| 'dataRow'
|
||||
| 'copyInResponse'
|
||||
| 'copyOutResponse'
|
||||
| 'authenticationOk'
|
||||
| 'authenticationMD5Password'
|
||||
| 'authenticationCleartextPassword'
|
||||
| 'authenticationSASL'
|
||||
| 'authenticationSASLContinue'
|
||||
| 'authenticationSASLFinal'
|
||||
| 'error'
|
||||
| 'notice'
|
||||
|
||||
export interface BackendMessage {
|
||||
name: MessageName
|
||||
length: number
|
||||
}
|
||||
|
||||
export const parseComplete: BackendMessage = {
|
||||
name: 'parseComplete',
|
||||
length: 5,
|
||||
}
|
||||
|
||||
export const bindComplete: BackendMessage = {
|
||||
name: 'bindComplete',
|
||||
length: 5,
|
||||
}
|
||||
|
||||
export const closeComplete: BackendMessage = {
|
||||
name: 'closeComplete',
|
||||
length: 5,
|
||||
}
|
||||
|
||||
export const noData: BackendMessage = {
|
||||
name: 'noData',
|
||||
length: 5,
|
||||
}
|
||||
|
||||
export const portalSuspended: BackendMessage = {
|
||||
name: 'portalSuspended',
|
||||
length: 5,
|
||||
}
|
||||
|
||||
export const replicationStart: BackendMessage = {
|
||||
name: 'replicationStart',
|
||||
length: 4,
|
||||
}
|
||||
|
||||
export const emptyQuery: BackendMessage = {
|
||||
name: 'emptyQuery',
|
||||
length: 4,
|
||||
}
|
||||
|
||||
export const copyDone: BackendMessage = {
|
||||
name: 'copyDone',
|
||||
length: 4,
|
||||
}
|
||||
|
||||
interface NoticeOrError {
|
||||
message: string | undefined
|
||||
severity: string | undefined
|
||||
code: string | undefined
|
||||
detail: string | undefined
|
||||
hint: string | undefined
|
||||
position: string | undefined
|
||||
internalPosition: string | undefined
|
||||
internalQuery: string | undefined
|
||||
where: string | undefined
|
||||
schema: string | undefined
|
||||
table: string | undefined
|
||||
column: string | undefined
|
||||
dataType: string | undefined
|
||||
constraint: string | undefined
|
||||
file: string | undefined
|
||||
line: string | undefined
|
||||
routine: string | undefined
|
||||
}
|
||||
|
||||
export class DatabaseError extends Error implements NoticeOrError {
|
||||
public severity: string | undefined
|
||||
public code: string | undefined
|
||||
public detail: string | undefined
|
||||
public hint: string | undefined
|
||||
public position: string | undefined
|
||||
public internalPosition: string | undefined
|
||||
public internalQuery: string | undefined
|
||||
public where: string | undefined
|
||||
public schema: string | undefined
|
||||
public table: string | undefined
|
||||
public column: string | undefined
|
||||
public dataType: string | undefined
|
||||
public constraint: string | undefined
|
||||
public file: string | undefined
|
||||
public line: string | undefined
|
||||
public routine: string | undefined
|
||||
constructor(
|
||||
message: string,
|
||||
public readonly length: number,
|
||||
public readonly name: MessageName
|
||||
) {
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
|
||||
export class CopyDataMessage {
|
||||
public readonly name = 'copyData'
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly chunk: Buffer
|
||||
) {}
|
||||
}
|
||||
|
||||
export class CopyResponse {
|
||||
public readonly columnTypes: number[]
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly name: MessageName,
|
||||
public readonly binary: boolean,
|
||||
columnCount: number
|
||||
) {
|
||||
this.columnTypes = new Array(columnCount)
|
||||
}
|
||||
}
|
||||
|
||||
export class Field {
|
||||
constructor(
|
||||
public readonly name: string,
|
||||
public readonly tableID: number,
|
||||
public readonly columnID: number,
|
||||
public readonly dataTypeID: number,
|
||||
public readonly dataTypeSize: number,
|
||||
public readonly dataTypeModifier: number,
|
||||
public readonly format: Mode
|
||||
) {}
|
||||
}
|
||||
|
||||
export class RowDescriptionMessage {
|
||||
public readonly name: MessageName = 'rowDescription'
|
||||
public readonly fields: Field[]
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly fieldCount: number
|
||||
) {
|
||||
this.fields = new Array(this.fieldCount)
|
||||
}
|
||||
}
|
||||
|
||||
export class ParameterDescriptionMessage {
|
||||
public readonly name: MessageName = 'parameterDescription'
|
||||
public readonly dataTypeIDs: number[]
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly parameterCount: number
|
||||
) {
|
||||
this.dataTypeIDs = new Array(this.parameterCount)
|
||||
}
|
||||
}
|
||||
|
||||
export class ParameterStatusMessage {
|
||||
public readonly name: MessageName = 'parameterStatus'
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly parameterName: string,
|
||||
public readonly parameterValue: string
|
||||
) {}
|
||||
}
|
||||
|
||||
export class AuthenticationMD5Password implements BackendMessage {
|
||||
public readonly name: MessageName = 'authenticationMD5Password'
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly salt: Buffer
|
||||
) {}
|
||||
}
|
||||
|
||||
export class BackendKeyDataMessage {
|
||||
public readonly name: MessageName = 'backendKeyData'
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly processID: number,
|
||||
public readonly secretKey: number
|
||||
) {}
|
||||
}
|
||||
|
||||
export class NotificationResponseMessage {
|
||||
public readonly name: MessageName = 'notification'
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly processId: number,
|
||||
public readonly channel: string,
|
||||
public readonly payload: string
|
||||
) {}
|
||||
}
|
||||
|
||||
export class ReadyForQueryMessage {
|
||||
public readonly name: MessageName = 'readyForQuery'
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly status: string
|
||||
) {}
|
||||
}
|
||||
|
||||
export class CommandCompleteMessage {
|
||||
public readonly name: MessageName = 'commandComplete'
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly text: string
|
||||
) {}
|
||||
}
|
||||
|
||||
export class DataRowMessage {
|
||||
public readonly fieldCount: number
|
||||
public readonly name: MessageName = 'dataRow'
|
||||
constructor(
|
||||
public length: number,
|
||||
public fields: any[]
|
||||
) {
|
||||
this.fieldCount = fields.length
|
||||
}
|
||||
}
|
||||
|
||||
export class NoticeMessage implements BackendMessage, NoticeOrError {
|
||||
constructor(
|
||||
public readonly length: number,
|
||||
public readonly message: string | undefined
|
||||
) {}
|
||||
public readonly name = 'notice'
|
||||
public severity: string | undefined
|
||||
public code: string | undefined
|
||||
public detail: string | undefined
|
||||
public hint: string | undefined
|
||||
public position: string | undefined
|
||||
public internalPosition: string | undefined
|
||||
public internalQuery: string | undefined
|
||||
public where: string | undefined
|
||||
public schema: string | undefined
|
||||
public table: string | undefined
|
||||
public column: string | undefined
|
||||
public dataType: string | undefined
|
||||
public constraint: string | undefined
|
||||
public file: string | undefined
|
||||
public line: string | undefined
|
||||
public routine: string | undefined
|
||||
}
|
272
websocket_server/node_modules/pg-protocol/src/outbound-serializer.test.ts
generated
vendored
Normal file
272
websocket_server/node_modules/pg-protocol/src/outbound-serializer.test.ts
generated
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
import assert from 'assert'
|
||||
import { serialize } from './serializer'
|
||||
import BufferList from './testing/buffer-list'
|
||||
|
||||
describe('serializer', () => {
|
||||
it('builds startup message', function () {
|
||||
const actual = serialize.startup({
|
||||
user: 'brian',
|
||||
database: 'bang',
|
||||
})
|
||||
assert.deepEqual(
|
||||
actual,
|
||||
new BufferList()
|
||||
.addInt16(3)
|
||||
.addInt16(0)
|
||||
.addCString('user')
|
||||
.addCString('brian')
|
||||
.addCString('database')
|
||||
.addCString('bang')
|
||||
.addCString('client_encoding')
|
||||
.addCString('UTF8')
|
||||
.addCString('')
|
||||
.join(true)
|
||||
)
|
||||
})
|
||||
|
||||
it('builds password message', function () {
|
||||
const actual = serialize.password('!')
|
||||
assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p'))
|
||||
})
|
||||
|
||||
it('builds request ssl message', function () {
|
||||
const actual = serialize.requestSsl()
|
||||
const expected = new BufferList().addInt32(80877103).join(true)
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('builds SASLInitialResponseMessage message', function () {
|
||||
const actual = serialize.sendSASLInitialResponseMessage('mech', 'data')
|
||||
assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p'))
|
||||
})
|
||||
|
||||
it('builds SCRAMClientFinalMessage message', function () {
|
||||
const actual = serialize.sendSCRAMClientFinalMessage('data')
|
||||
assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p'))
|
||||
})
|
||||
|
||||
it('builds query message', function () {
|
||||
var txt = 'select * from boom'
|
||||
const actual = serialize.query(txt)
|
||||
assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q'))
|
||||
})
|
||||
|
||||
describe('parse message', () => {
|
||||
it('builds parse message', function () {
|
||||
const actual = serialize.parse({ text: '!' })
|
||||
var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('builds parse message with named query', function () {
|
||||
const actual = serialize.parse({
|
||||
name: 'boom',
|
||||
text: 'select * from boom',
|
||||
types: [],
|
||||
})
|
||||
var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('with multiple parameters', function () {
|
||||
const actual = serialize.parse({
|
||||
name: 'force',
|
||||
text: 'select * from bang where name = $1',
|
||||
types: [1, 2, 3, 4],
|
||||
})
|
||||
var expected = new BufferList()
|
||||
.addCString('force')
|
||||
.addCString('select * from bang where name = $1')
|
||||
.addInt16(4)
|
||||
.addInt32(1)
|
||||
.addInt32(2)
|
||||
.addInt32(3)
|
||||
.addInt32(4)
|
||||
.join(true, 'P')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('bind messages', function () {
|
||||
it('with no values', function () {
|
||||
const actual = serialize.bind()
|
||||
|
||||
var expectedBuffer = new BufferList()
|
||||
.addCString('')
|
||||
.addCString('')
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.join(true, 'B')
|
||||
assert.deepEqual(actual, expectedBuffer)
|
||||
})
|
||||
|
||||
it('with named statement, portal, and values', function () {
|
||||
const actual = serialize.bind({
|
||||
portal: 'bang',
|
||||
statement: 'woo',
|
||||
values: ['1', 'hi', null, 'zing'],
|
||||
})
|
||||
var expectedBuffer = new BufferList()
|
||||
.addCString('bang') // portal name
|
||||
.addCString('woo') // statement name
|
||||
.addInt16(4)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(4)
|
||||
.addInt32(1)
|
||||
.add(Buffer.from('1'))
|
||||
.addInt32(2)
|
||||
.add(Buffer.from('hi'))
|
||||
.addInt32(-1)
|
||||
.addInt32(4)
|
||||
.add(Buffer.from('zing'))
|
||||
.addInt16(0)
|
||||
.join(true, 'B')
|
||||
assert.deepEqual(actual, expectedBuffer)
|
||||
})
|
||||
})
|
||||
|
||||
it('with custom valueMapper', function () {
|
||||
const actual = serialize.bind({
|
||||
portal: 'bang',
|
||||
statement: 'woo',
|
||||
values: ['1', 'hi', null, 'zing'],
|
||||
valueMapper: () => null,
|
||||
})
|
||||
var expectedBuffer = new BufferList()
|
||||
.addCString('bang') // portal name
|
||||
.addCString('woo') // statement name
|
||||
.addInt16(4)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(0)
|
||||
.addInt16(4)
|
||||
.addInt32(-1)
|
||||
.addInt32(-1)
|
||||
.addInt32(-1)
|
||||
.addInt32(-1)
|
||||
.addInt16(0)
|
||||
.join(true, 'B')
|
||||
assert.deepEqual(actual, expectedBuffer)
|
||||
})
|
||||
|
||||
it('with named statement, portal, and buffer value', function () {
|
||||
const actual = serialize.bind({
|
||||
portal: 'bang',
|
||||
statement: 'woo',
|
||||
values: ['1', 'hi', null, Buffer.from('zing', 'utf8')],
|
||||
})
|
||||
var expectedBuffer = new BufferList()
|
||||
.addCString('bang') // portal name
|
||||
.addCString('woo') // statement name
|
||||
.addInt16(4) // value count
|
||||
.addInt16(0) // string
|
||||
.addInt16(0) // string
|
||||
.addInt16(0) // string
|
||||
.addInt16(1) // binary
|
||||
.addInt16(4)
|
||||
.addInt32(1)
|
||||
.add(Buffer.from('1'))
|
||||
.addInt32(2)
|
||||
.add(Buffer.from('hi'))
|
||||
.addInt32(-1)
|
||||
.addInt32(4)
|
||||
.add(Buffer.from('zing', 'utf-8'))
|
||||
.addInt16(0)
|
||||
.join(true, 'B')
|
||||
assert.deepEqual(actual, expectedBuffer)
|
||||
})
|
||||
|
||||
describe('builds execute message', function () {
|
||||
it('for unamed portal with no row limit', function () {
|
||||
const actual = serialize.execute()
|
||||
var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E')
|
||||
assert.deepEqual(actual, expectedBuffer)
|
||||
})
|
||||
|
||||
it('for named portal with row limit', function () {
|
||||
const actual = serialize.execute({
|
||||
portal: 'my favorite portal',
|
||||
rows: 100,
|
||||
})
|
||||
var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E')
|
||||
assert.deepEqual(actual, expectedBuffer)
|
||||
})
|
||||
})
|
||||
|
||||
it('builds flush command', function () {
|
||||
const actual = serialize.flush()
|
||||
var expected = new BufferList().join(true, 'H')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('builds sync command', function () {
|
||||
const actual = serialize.sync()
|
||||
var expected = new BufferList().join(true, 'S')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('builds end command', function () {
|
||||
const actual = serialize.end()
|
||||
var expected = Buffer.from([0x58, 0, 0, 0, 4])
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
describe('builds describe command', function () {
|
||||
it('describe statement', function () {
|
||||
const actual = serialize.describe({ type: 'S', name: 'bang' })
|
||||
var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('describe unnamed portal', function () {
|
||||
const actual = serialize.describe({ type: 'P' })
|
||||
var expected = new BufferList().addChar('P').addCString('').join(true, 'D')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('builds close command', function () {
|
||||
it('describe statement', function () {
|
||||
const actual = serialize.close({ type: 'S', name: 'bang' })
|
||||
var expected = new BufferList().addChar('S').addCString('bang').join(true, 'C')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('describe unnamed portal', function () {
|
||||
const actual = serialize.close({ type: 'P' })
|
||||
var expected = new BufferList().addChar('P').addCString('').join(true, 'C')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('copy messages', function () {
|
||||
it('builds copyFromChunk', () => {
|
||||
const actual = serialize.copyData(Buffer.from([1, 2, 3]))
|
||||
const expected = new BufferList().add(Buffer.from([1, 2, 3])).join(true, 'd')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('builds copy fail', () => {
|
||||
const actual = serialize.copyFail('err!')
|
||||
const expected = new BufferList().addCString('err!').join(true, 'f')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
|
||||
it('builds copy done', () => {
|
||||
const actual = serialize.copyDone()
|
||||
const expected = new BufferList().join(true, 'c')
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('builds cancel message', () => {
|
||||
const actual = serialize.cancel(3, 4)
|
||||
const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true)
|
||||
assert.deepEqual(actual, expected)
|
||||
})
|
||||
})
|
388
websocket_server/node_modules/pg-protocol/src/parser.ts
generated
vendored
Normal file
388
websocket_server/node_modules/pg-protocol/src/parser.ts
generated
vendored
Normal file
@ -0,0 +1,388 @@
|
||||
import { TransformOptions } from 'stream'
|
||||
import {
|
||||
Mode,
|
||||
bindComplete,
|
||||
parseComplete,
|
||||
closeComplete,
|
||||
noData,
|
||||
portalSuspended,
|
||||
copyDone,
|
||||
replicationStart,
|
||||
emptyQuery,
|
||||
ReadyForQueryMessage,
|
||||
CommandCompleteMessage,
|
||||
CopyDataMessage,
|
||||
CopyResponse,
|
||||
NotificationResponseMessage,
|
||||
RowDescriptionMessage,
|
||||
ParameterDescriptionMessage,
|
||||
Field,
|
||||
DataRowMessage,
|
||||
ParameterStatusMessage,
|
||||
BackendKeyDataMessage,
|
||||
DatabaseError,
|
||||
BackendMessage,
|
||||
MessageName,
|
||||
AuthenticationMD5Password,
|
||||
NoticeMessage,
|
||||
} from './messages'
|
||||
import { BufferReader } from './buffer-reader'
|
||||
|
||||
// every message is prefixed with a single bye
|
||||
const CODE_LENGTH = 1
|
||||
// every message has an int32 length which includes itself but does
|
||||
// NOT include the code in the length
|
||||
const LEN_LENGTH = 4
|
||||
|
||||
const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH
|
||||
|
||||
export type Packet = {
|
||||
code: number
|
||||
packet: Buffer
|
||||
}
|
||||
|
||||
const emptyBuffer = Buffer.allocUnsafe(0)
|
||||
|
||||
type StreamOptions = TransformOptions & {
|
||||
mode: Mode
|
||||
}
|
||||
|
||||
const enum MessageCodes {
|
||||
DataRow = 0x44, // D
|
||||
ParseComplete = 0x31, // 1
|
||||
BindComplete = 0x32, // 2
|
||||
CloseComplete = 0x33, // 3
|
||||
CommandComplete = 0x43, // C
|
||||
ReadyForQuery = 0x5a, // Z
|
||||
NoData = 0x6e, // n
|
||||
NotificationResponse = 0x41, // A
|
||||
AuthenticationResponse = 0x52, // R
|
||||
ParameterStatus = 0x53, // S
|
||||
BackendKeyData = 0x4b, // K
|
||||
ErrorMessage = 0x45, // E
|
||||
NoticeMessage = 0x4e, // N
|
||||
RowDescriptionMessage = 0x54, // T
|
||||
ParameterDescriptionMessage = 0x74, // t
|
||||
PortalSuspended = 0x73, // s
|
||||
ReplicationStart = 0x57, // W
|
||||
EmptyQuery = 0x49, // I
|
||||
CopyIn = 0x47, // G
|
||||
CopyOut = 0x48, // H
|
||||
CopyDone = 0x63, // c
|
||||
CopyData = 0x64, // d
|
||||
}
|
||||
|
||||
export type MessageCallback = (msg: BackendMessage) => void
|
||||
|
||||
export class Parser {
|
||||
private buffer: Buffer = emptyBuffer
|
||||
private bufferLength: number = 0
|
||||
private bufferOffset: number = 0
|
||||
private reader = new BufferReader()
|
||||
private mode: Mode
|
||||
|
||||
constructor(opts?: StreamOptions) {
|
||||
if (opts?.mode === 'binary') {
|
||||
throw new Error('Binary mode not supported yet')
|
||||
}
|
||||
this.mode = opts?.mode || 'text'
|
||||
}
|
||||
|
||||
public parse(buffer: Buffer, callback: MessageCallback) {
|
||||
this.mergeBuffer(buffer)
|
||||
const bufferFullLength = this.bufferOffset + this.bufferLength
|
||||
let offset = this.bufferOffset
|
||||
while (offset + HEADER_LENGTH <= bufferFullLength) {
|
||||
// code is 1 byte long - it identifies the message type
|
||||
const code = this.buffer[offset]
|
||||
// length is 1 Uint32BE - it is the length of the message EXCLUDING the code
|
||||
const length = this.buffer.readUInt32BE(offset + CODE_LENGTH)
|
||||
const fullMessageLength = CODE_LENGTH + length
|
||||
if (fullMessageLength + offset <= bufferFullLength) {
|
||||
const message = this.handlePacket(offset + HEADER_LENGTH, code, length, this.buffer)
|
||||
callback(message)
|
||||
offset += fullMessageLength
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (offset === bufferFullLength) {
|
||||
// No more use for the buffer
|
||||
this.buffer = emptyBuffer
|
||||
this.bufferLength = 0
|
||||
this.bufferOffset = 0
|
||||
} else {
|
||||
// Adjust the cursors of remainingBuffer
|
||||
this.bufferLength = bufferFullLength - offset
|
||||
this.bufferOffset = offset
|
||||
}
|
||||
}
|
||||
|
||||
private mergeBuffer(buffer: Buffer): void {
|
||||
if (this.bufferLength > 0) {
|
||||
const newLength = this.bufferLength + buffer.byteLength
|
||||
const newFullLength = newLength + this.bufferOffset
|
||||
if (newFullLength > this.buffer.byteLength) {
|
||||
// We can't concat the new buffer with the remaining one
|
||||
let newBuffer: Buffer
|
||||
if (newLength <= this.buffer.byteLength && this.bufferOffset >= this.bufferLength) {
|
||||
// We can move the relevant part to the beginning of the buffer instead of allocating a new buffer
|
||||
newBuffer = this.buffer
|
||||
} else {
|
||||
// Allocate a new larger buffer
|
||||
let newBufferLength = this.buffer.byteLength * 2
|
||||
while (newLength >= newBufferLength) {
|
||||
newBufferLength *= 2
|
||||
}
|
||||
newBuffer = Buffer.allocUnsafe(newBufferLength)
|
||||
}
|
||||
// Move the remaining buffer to the new one
|
||||
this.buffer.copy(newBuffer, 0, this.bufferOffset, this.bufferOffset + this.bufferLength)
|
||||
this.buffer = newBuffer
|
||||
this.bufferOffset = 0
|
||||
}
|
||||
// Concat the new buffer with the remaining one
|
||||
buffer.copy(this.buffer, this.bufferOffset + this.bufferLength)
|
||||
this.bufferLength = newLength
|
||||
} else {
|
||||
this.buffer = buffer
|
||||
this.bufferOffset = 0
|
||||
this.bufferLength = buffer.byteLength
|
||||
}
|
||||
}
|
||||
|
||||
private handlePacket(offset: number, code: number, length: number, bytes: Buffer): BackendMessage {
|
||||
switch (code) {
|
||||
case MessageCodes.BindComplete:
|
||||
return bindComplete
|
||||
case MessageCodes.ParseComplete:
|
||||
return parseComplete
|
||||
case MessageCodes.CloseComplete:
|
||||
return closeComplete
|
||||
case MessageCodes.NoData:
|
||||
return noData
|
||||
case MessageCodes.PortalSuspended:
|
||||
return portalSuspended
|
||||
case MessageCodes.CopyDone:
|
||||
return copyDone
|
||||
case MessageCodes.ReplicationStart:
|
||||
return replicationStart
|
||||
case MessageCodes.EmptyQuery:
|
||||
return emptyQuery
|
||||
case MessageCodes.DataRow:
|
||||
return this.parseDataRowMessage(offset, length, bytes)
|
||||
case MessageCodes.CommandComplete:
|
||||
return this.parseCommandCompleteMessage(offset, length, bytes)
|
||||
case MessageCodes.ReadyForQuery:
|
||||
return this.parseReadyForQueryMessage(offset, length, bytes)
|
||||
case MessageCodes.NotificationResponse:
|
||||
return this.parseNotificationMessage(offset, length, bytes)
|
||||
case MessageCodes.AuthenticationResponse:
|
||||
return this.parseAuthenticationResponse(offset, length, bytes)
|
||||
case MessageCodes.ParameterStatus:
|
||||
return this.parseParameterStatusMessage(offset, length, bytes)
|
||||
case MessageCodes.BackendKeyData:
|
||||
return this.parseBackendKeyData(offset, length, bytes)
|
||||
case MessageCodes.ErrorMessage:
|
||||
return this.parseErrorMessage(offset, length, bytes, 'error')
|
||||
case MessageCodes.NoticeMessage:
|
||||
return this.parseErrorMessage(offset, length, bytes, 'notice')
|
||||
case MessageCodes.RowDescriptionMessage:
|
||||
return this.parseRowDescriptionMessage(offset, length, bytes)
|
||||
case MessageCodes.ParameterDescriptionMessage:
|
||||
return this.parseParameterDescriptionMessage(offset, length, bytes)
|
||||
case MessageCodes.CopyIn:
|
||||
return this.parseCopyInMessage(offset, length, bytes)
|
||||
case MessageCodes.CopyOut:
|
||||
return this.parseCopyOutMessage(offset, length, bytes)
|
||||
case MessageCodes.CopyData:
|
||||
return this.parseCopyData(offset, length, bytes)
|
||||
default:
|
||||
return new DatabaseError('received invalid response: ' + code.toString(16), length, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
private parseReadyForQueryMessage(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const status = this.reader.string(1)
|
||||
return new ReadyForQueryMessage(length, status)
|
||||
}
|
||||
|
||||
private parseCommandCompleteMessage(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const text = this.reader.cstring()
|
||||
return new CommandCompleteMessage(length, text)
|
||||
}
|
||||
|
||||
private parseCopyData(offset: number, length: number, bytes: Buffer) {
|
||||
const chunk = bytes.slice(offset, offset + (length - 4))
|
||||
return new CopyDataMessage(length, chunk)
|
||||
}
|
||||
|
||||
private parseCopyInMessage(offset: number, length: number, bytes: Buffer) {
|
||||
return this.parseCopyMessage(offset, length, bytes, 'copyInResponse')
|
||||
}
|
||||
|
||||
private parseCopyOutMessage(offset: number, length: number, bytes: Buffer) {
|
||||
return this.parseCopyMessage(offset, length, bytes, 'copyOutResponse')
|
||||
}
|
||||
|
||||
private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: MessageName) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const isBinary = this.reader.byte() !== 0
|
||||
const columnCount = this.reader.int16()
|
||||
const message = new CopyResponse(length, messageName, isBinary, columnCount)
|
||||
for (let i = 0; i < columnCount; i++) {
|
||||
message.columnTypes[i] = this.reader.int16()
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
private parseNotificationMessage(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const processId = this.reader.int32()
|
||||
const channel = this.reader.cstring()
|
||||
const payload = this.reader.cstring()
|
||||
return new NotificationResponseMessage(length, processId, channel, payload)
|
||||
}
|
||||
|
||||
private parseRowDescriptionMessage(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const fieldCount = this.reader.int16()
|
||||
const message = new RowDescriptionMessage(length, fieldCount)
|
||||
for (let i = 0; i < fieldCount; i++) {
|
||||
message.fields[i] = this.parseField()
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
private parseField(): Field {
|
||||
const name = this.reader.cstring()
|
||||
const tableID = this.reader.int32()
|
||||
const columnID = this.reader.int16()
|
||||
const dataTypeID = this.reader.int32()
|
||||
const dataTypeSize = this.reader.int16()
|
||||
const dataTypeModifier = this.reader.int32()
|
||||
const mode = this.reader.int16() === 0 ? 'text' : 'binary'
|
||||
return new Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode)
|
||||
}
|
||||
|
||||
private parseParameterDescriptionMessage(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const parameterCount = this.reader.int16()
|
||||
const message = new ParameterDescriptionMessage(length, parameterCount)
|
||||
for (let i = 0; i < parameterCount; i++) {
|
||||
message.dataTypeIDs[i] = this.reader.int32()
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
private parseDataRowMessage(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const fieldCount = this.reader.int16()
|
||||
const fields: any[] = new Array(fieldCount)
|
||||
for (let i = 0; i < fieldCount; i++) {
|
||||
const len = this.reader.int32()
|
||||
// a -1 for length means the value of the field is null
|
||||
fields[i] = len === -1 ? null : this.reader.string(len)
|
||||
}
|
||||
return new DataRowMessage(length, fields)
|
||||
}
|
||||
|
||||
private parseParameterStatusMessage(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const name = this.reader.cstring()
|
||||
const value = this.reader.cstring()
|
||||
return new ParameterStatusMessage(length, name, value)
|
||||
}
|
||||
|
||||
private parseBackendKeyData(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const processID = this.reader.int32()
|
||||
const secretKey = this.reader.int32()
|
||||
return new BackendKeyDataMessage(length, processID, secretKey)
|
||||
}
|
||||
|
||||
public parseAuthenticationResponse(offset: number, length: number, bytes: Buffer) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const code = this.reader.int32()
|
||||
// TODO(bmc): maybe better types here
|
||||
const message: BackendMessage & any = {
|
||||
name: 'authenticationOk',
|
||||
length,
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case 0: // AuthenticationOk
|
||||
break
|
||||
case 3: // AuthenticationCleartextPassword
|
||||
if (message.length === 8) {
|
||||
message.name = 'authenticationCleartextPassword'
|
||||
}
|
||||
break
|
||||
case 5: // AuthenticationMD5Password
|
||||
if (message.length === 12) {
|
||||
message.name = 'authenticationMD5Password'
|
||||
const salt = this.reader.bytes(4)
|
||||
return new AuthenticationMD5Password(length, salt)
|
||||
}
|
||||
break
|
||||
case 10: // AuthenticationSASL
|
||||
message.name = 'authenticationSASL'
|
||||
message.mechanisms = []
|
||||
let mechanism: string
|
||||
do {
|
||||
mechanism = this.reader.cstring()
|
||||
|
||||
if (mechanism) {
|
||||
message.mechanisms.push(mechanism)
|
||||
}
|
||||
} while (mechanism)
|
||||
break
|
||||
case 11: // AuthenticationSASLContinue
|
||||
message.name = 'authenticationSASLContinue'
|
||||
message.data = this.reader.string(length - 8)
|
||||
break
|
||||
case 12: // AuthenticationSASLFinal
|
||||
message.name = 'authenticationSASLFinal'
|
||||
message.data = this.reader.string(length - 8)
|
||||
break
|
||||
default:
|
||||
throw new Error('Unknown authenticationOk message type ' + code)
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: MessageName) {
|
||||
this.reader.setBuffer(offset, bytes)
|
||||
const fields: Record<string, string> = {}
|
||||
let fieldType = this.reader.string(1)
|
||||
while (fieldType !== '\0') {
|
||||
fields[fieldType] = this.reader.cstring()
|
||||
fieldType = this.reader.string(1)
|
||||
}
|
||||
|
||||
const messageValue = fields.M
|
||||
|
||||
const message =
|
||||
name === 'notice' ? new NoticeMessage(length, messageValue) : new DatabaseError(messageValue, length, name)
|
||||
|
||||
message.severity = fields.S
|
||||
message.code = fields.C
|
||||
message.detail = fields.D
|
||||
message.hint = fields.H
|
||||
message.position = fields.P
|
||||
message.internalPosition = fields.p
|
||||
message.internalQuery = fields.q
|
||||
message.where = fields.W
|
||||
message.schema = fields.s
|
||||
message.table = fields.t
|
||||
message.column = fields.c
|
||||
message.dataType = fields.d
|
||||
message.constraint = fields.n
|
||||
message.file = fields.F
|
||||
message.line = fields.L
|
||||
message.routine = fields.R
|
||||
return message
|
||||
}
|
||||
}
|
274
websocket_server/node_modules/pg-protocol/src/serializer.ts
generated
vendored
Normal file
274
websocket_server/node_modules/pg-protocol/src/serializer.ts
generated
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
import { Writer } from './buffer-writer'
|
||||
|
||||
const enum code {
|
||||
startup = 0x70,
|
||||
query = 0x51,
|
||||
parse = 0x50,
|
||||
bind = 0x42,
|
||||
execute = 0x45,
|
||||
flush = 0x48,
|
||||
sync = 0x53,
|
||||
end = 0x58,
|
||||
close = 0x43,
|
||||
describe = 0x44,
|
||||
copyFromChunk = 0x64,
|
||||
copyDone = 0x63,
|
||||
copyFail = 0x66,
|
||||
}
|
||||
|
||||
const writer = new Writer()
|
||||
|
||||
const startup = (opts: Record<string, string>): Buffer => {
|
||||
// protocol version
|
||||
writer.addInt16(3).addInt16(0)
|
||||
for (const key of Object.keys(opts)) {
|
||||
writer.addCString(key).addCString(opts[key])
|
||||
}
|
||||
|
||||
writer.addCString('client_encoding').addCString('UTF8')
|
||||
|
||||
var bodyBuffer = writer.addCString('').flush()
|
||||
// this message is sent without a code
|
||||
|
||||
var length = bodyBuffer.length + 4
|
||||
|
||||
return new Writer().addInt32(length).add(bodyBuffer).flush()
|
||||
}
|
||||
|
||||
const requestSsl = (): Buffer => {
|
||||
const response = Buffer.allocUnsafe(8)
|
||||
response.writeInt32BE(8, 0)
|
||||
response.writeInt32BE(80877103, 4)
|
||||
return response
|
||||
}
|
||||
|
||||
const password = (password: string): Buffer => {
|
||||
return writer.addCString(password).flush(code.startup)
|
||||
}
|
||||
|
||||
const sendSASLInitialResponseMessage = function (mechanism: string, initialResponse: string): Buffer {
|
||||
// 0x70 = 'p'
|
||||
writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse)
|
||||
|
||||
return writer.flush(code.startup)
|
||||
}
|
||||
|
||||
const sendSCRAMClientFinalMessage = function (additionalData: string): Buffer {
|
||||
return writer.addString(additionalData).flush(code.startup)
|
||||
}
|
||||
|
||||
const query = (text: string): Buffer => {
|
||||
return writer.addCString(text).flush(code.query)
|
||||
}
|
||||
|
||||
type ParseOpts = {
|
||||
name?: string
|
||||
types?: number[]
|
||||
text: string
|
||||
}
|
||||
|
||||
const emptyArray: any[] = []
|
||||
|
||||
const parse = (query: ParseOpts): Buffer => {
|
||||
// expect something like this:
|
||||
// { name: 'queryName',
|
||||
// text: 'select * from blah',
|
||||
// types: ['int8', 'bool'] }
|
||||
|
||||
// normalize missing query names to allow for null
|
||||
const name = query.name || ''
|
||||
if (name.length > 63) {
|
||||
/* eslint-disable no-console */
|
||||
console.error('Warning! Postgres only supports 63 characters for query names.')
|
||||
console.error('You supplied %s (%s)', name, name.length)
|
||||
console.error('This can cause conflicts and silent errors executing queries')
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
|
||||
const types = query.types || emptyArray
|
||||
|
||||
var len = types.length
|
||||
|
||||
var buffer = writer
|
||||
.addCString(name) // name of query
|
||||
.addCString(query.text) // actual query text
|
||||
.addInt16(len)
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
buffer.addInt32(types[i])
|
||||
}
|
||||
|
||||
return writer.flush(code.parse)
|
||||
}
|
||||
|
||||
type ValueMapper = (param: any, index: number) => any
|
||||
|
||||
type BindOpts = {
|
||||
portal?: string
|
||||
binary?: boolean
|
||||
statement?: string
|
||||
values?: any[]
|
||||
// optional map from JS value to postgres value per parameter
|
||||
valueMapper?: ValueMapper
|
||||
}
|
||||
|
||||
const paramWriter = new Writer()
|
||||
|
||||
// make this a const enum so typescript will inline the value
|
||||
const enum ParamType {
|
||||
STRING = 0,
|
||||
BINARY = 1,
|
||||
}
|
||||
|
||||
const writeValues = function (values: any[], valueMapper?: ValueMapper): void {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
const mappedVal = valueMapper ? valueMapper(values[i], i) : values[i]
|
||||
if (mappedVal == null) {
|
||||
// add the param type (string) to the writer
|
||||
writer.addInt16(ParamType.STRING)
|
||||
// write -1 to the param writer to indicate null
|
||||
paramWriter.addInt32(-1)
|
||||
} else if (mappedVal instanceof Buffer) {
|
||||
// add the param type (binary) to the writer
|
||||
writer.addInt16(ParamType.BINARY)
|
||||
// add the buffer to the param writer
|
||||
paramWriter.addInt32(mappedVal.length)
|
||||
paramWriter.add(mappedVal)
|
||||
} else {
|
||||
// add the param type (string) to the writer
|
||||
writer.addInt16(ParamType.STRING)
|
||||
paramWriter.addInt32(Buffer.byteLength(mappedVal))
|
||||
paramWriter.addString(mappedVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bind = (config: BindOpts = {}): Buffer => {
|
||||
// normalize config
|
||||
const portal = config.portal || ''
|
||||
const statement = config.statement || ''
|
||||
const binary = config.binary || false
|
||||
const values = config.values || emptyArray
|
||||
const len = values.length
|
||||
|
||||
writer.addCString(portal).addCString(statement)
|
||||
writer.addInt16(len)
|
||||
|
||||
writeValues(values, config.valueMapper)
|
||||
|
||||
writer.addInt16(len)
|
||||
writer.add(paramWriter.flush())
|
||||
|
||||
// format code
|
||||
writer.addInt16(binary ? ParamType.BINARY : ParamType.STRING)
|
||||
return writer.flush(code.bind)
|
||||
}
|
||||
|
||||
type ExecOpts = {
|
||||
portal?: string
|
||||
rows?: number
|
||||
}
|
||||
|
||||
const emptyExecute = Buffer.from([code.execute, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00])
|
||||
|
||||
const execute = (config?: ExecOpts): Buffer => {
|
||||
// this is the happy path for most queries
|
||||
if (!config || (!config.portal && !config.rows)) {
|
||||
return emptyExecute
|
||||
}
|
||||
|
||||
const portal = config.portal || ''
|
||||
const rows = config.rows || 0
|
||||
|
||||
const portalLength = Buffer.byteLength(portal)
|
||||
const len = 4 + portalLength + 1 + 4
|
||||
// one extra bit for code
|
||||
const buff = Buffer.allocUnsafe(1 + len)
|
||||
buff[0] = code.execute
|
||||
buff.writeInt32BE(len, 1)
|
||||
buff.write(portal, 5, 'utf-8')
|
||||
buff[portalLength + 5] = 0 // null terminate portal cString
|
||||
buff.writeUInt32BE(rows, buff.length - 4)
|
||||
return buff
|
||||
}
|
||||
|
||||
const cancel = (processID: number, secretKey: number): Buffer => {
|
||||
const buffer = Buffer.allocUnsafe(16)
|
||||
buffer.writeInt32BE(16, 0)
|
||||
buffer.writeInt16BE(1234, 4)
|
||||
buffer.writeInt16BE(5678, 6)
|
||||
buffer.writeInt32BE(processID, 8)
|
||||
buffer.writeInt32BE(secretKey, 12)
|
||||
return buffer
|
||||
}
|
||||
|
||||
type PortalOpts = {
|
||||
type: 'S' | 'P'
|
||||
name?: string
|
||||
}
|
||||
|
||||
const cstringMessage = (code: code, string: string): Buffer => {
|
||||
const stringLen = Buffer.byteLength(string)
|
||||
const len = 4 + stringLen + 1
|
||||
// one extra bit for code
|
||||
const buffer = Buffer.allocUnsafe(1 + len)
|
||||
buffer[0] = code
|
||||
buffer.writeInt32BE(len, 1)
|
||||
buffer.write(string, 5, 'utf-8')
|
||||
buffer[len] = 0 // null terminate cString
|
||||
return buffer
|
||||
}
|
||||
|
||||
const emptyDescribePortal = writer.addCString('P').flush(code.describe)
|
||||
const emptyDescribeStatement = writer.addCString('S').flush(code.describe)
|
||||
|
||||
const describe = (msg: PortalOpts): Buffer => {
|
||||
return msg.name
|
||||
? cstringMessage(code.describe, `${msg.type}${msg.name || ''}`)
|
||||
: msg.type === 'P'
|
||||
? emptyDescribePortal
|
||||
: emptyDescribeStatement
|
||||
}
|
||||
|
||||
const close = (msg: PortalOpts): Buffer => {
|
||||
const text = `${msg.type}${msg.name || ''}`
|
||||
return cstringMessage(code.close, text)
|
||||
}
|
||||
|
||||
const copyData = (chunk: Buffer): Buffer => {
|
||||
return writer.add(chunk).flush(code.copyFromChunk)
|
||||
}
|
||||
|
||||
const copyFail = (message: string): Buffer => {
|
||||
return cstringMessage(code.copyFail, message)
|
||||
}
|
||||
|
||||
const codeOnlyBuffer = (code: code): Buffer => Buffer.from([code, 0x00, 0x00, 0x00, 0x04])
|
||||
|
||||
const flushBuffer = codeOnlyBuffer(code.flush)
|
||||
const syncBuffer = codeOnlyBuffer(code.sync)
|
||||
const endBuffer = codeOnlyBuffer(code.end)
|
||||
const copyDoneBuffer = codeOnlyBuffer(code.copyDone)
|
||||
|
||||
const serialize = {
|
||||
startup,
|
||||
password,
|
||||
requestSsl,
|
||||
sendSASLInitialResponseMessage,
|
||||
sendSCRAMClientFinalMessage,
|
||||
query,
|
||||
parse,
|
||||
bind,
|
||||
execute,
|
||||
describe,
|
||||
close,
|
||||
flush: () => flushBuffer,
|
||||
sync: () => syncBuffer,
|
||||
end: () => endBuffer,
|
||||
copyData,
|
||||
copyDone: () => copyDoneBuffer,
|
||||
copyFail,
|
||||
cancel,
|
||||
}
|
||||
|
||||
export { serialize }
|
75
websocket_server/node_modules/pg-protocol/src/testing/buffer-list.ts
generated
vendored
Normal file
75
websocket_server/node_modules/pg-protocol/src/testing/buffer-list.ts
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
export default class BufferList {
|
||||
constructor(public buffers: Buffer[] = []) {}
|
||||
|
||||
public add(buffer: Buffer, front?: boolean) {
|
||||
this.buffers[front ? 'unshift' : 'push'](buffer)
|
||||
return this
|
||||
}
|
||||
|
||||
public addInt16(val: number, front?: boolean) {
|
||||
return this.add(Buffer.from([val >>> 8, val >>> 0]), front)
|
||||
}
|
||||
|
||||
public getByteLength(initial?: number) {
|
||||
return this.buffers.reduce(function (previous, current) {
|
||||
return previous + current.length
|
||||
}, initial || 0)
|
||||
}
|
||||
|
||||
public addInt32(val: number, first?: boolean) {
|
||||
return this.add(
|
||||
Buffer.from([(val >>> 24) & 0xff, (val >>> 16) & 0xff, (val >>> 8) & 0xff, (val >>> 0) & 0xff]),
|
||||
first
|
||||
)
|
||||
}
|
||||
|
||||
public addCString(val: string, front?: boolean) {
|
||||
var len = Buffer.byteLength(val)
|
||||
var buffer = Buffer.alloc(len + 1)
|
||||
buffer.write(val)
|
||||
buffer[len] = 0
|
||||
return this.add(buffer, front)
|
||||
}
|
||||
|
||||
public addString(val: string, front?: boolean) {
|
||||
var len = Buffer.byteLength(val)
|
||||
var buffer = Buffer.alloc(len)
|
||||
buffer.write(val)
|
||||
return this.add(buffer, front)
|
||||
}
|
||||
|
||||
public addChar(char: string, first?: boolean) {
|
||||
return this.add(Buffer.from(char, 'utf8'), first)
|
||||
}
|
||||
|
||||
public addByte(byte: number) {
|
||||
return this.add(Buffer.from([byte]))
|
||||
}
|
||||
|
||||
public join(appendLength?: boolean, char?: string): Buffer {
|
||||
var length = this.getByteLength()
|
||||
if (appendLength) {
|
||||
this.addInt32(length + 4, true)
|
||||
return this.join(false, char)
|
||||
}
|
||||
if (char) {
|
||||
this.addChar(char, true)
|
||||
length++
|
||||
}
|
||||
var result = Buffer.alloc(length)
|
||||
var index = 0
|
||||
this.buffers.forEach(function (buffer) {
|
||||
buffer.copy(result, index, 0)
|
||||
index += buffer.length
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
public static concat(): Buffer {
|
||||
var total = new BufferList()
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
total.add(arguments[i])
|
||||
}
|
||||
return total.join()
|
||||
}
|
||||
}
|
166
websocket_server/node_modules/pg-protocol/src/testing/test-buffers.ts
generated
vendored
Normal file
166
websocket_server/node_modules/pg-protocol/src/testing/test-buffers.ts
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
// https://www.postgresql.org/docs/current/protocol-message-formats.html
|
||||
import BufferList from './buffer-list'
|
||||
|
||||
const buffers = {
|
||||
readyForQuery: function () {
|
||||
return new BufferList().add(Buffer.from('I')).join(true, 'Z')
|
||||
},
|
||||
|
||||
authenticationOk: function () {
|
||||
return new BufferList().addInt32(0).join(true, 'R')
|
||||
},
|
||||
|
||||
authenticationCleartextPassword: function () {
|
||||
return new BufferList().addInt32(3).join(true, 'R')
|
||||
},
|
||||
|
||||
authenticationMD5Password: function () {
|
||||
return new BufferList()
|
||||
.addInt32(5)
|
||||
.add(Buffer.from([1, 2, 3, 4]))
|
||||
.join(true, 'R')
|
||||
},
|
||||
|
||||
authenticationSASL: function () {
|
||||
return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R')
|
||||
},
|
||||
|
||||
authenticationSASLContinue: function () {
|
||||
return new BufferList().addInt32(11).addString('data').join(true, 'R')
|
||||
},
|
||||
|
||||
authenticationSASLFinal: function () {
|
||||
return new BufferList().addInt32(12).addString('data').join(true, 'R')
|
||||
},
|
||||
|
||||
parameterStatus: function (name: string, value: string) {
|
||||
return new BufferList().addCString(name).addCString(value).join(true, 'S')
|
||||
},
|
||||
|
||||
backendKeyData: function (processID: number, secretKey: number) {
|
||||
return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K')
|
||||
},
|
||||
|
||||
commandComplete: function (string: string) {
|
||||
return new BufferList().addCString(string).join(true, 'C')
|
||||
},
|
||||
|
||||
rowDescription: function (fields: any[]) {
|
||||
fields = fields || []
|
||||
var buf = new BufferList()
|
||||
buf.addInt16(fields.length)
|
||||
fields.forEach(function (field) {
|
||||
buf
|
||||
.addCString(field.name)
|
||||
.addInt32(field.tableID || 0)
|
||||
.addInt16(field.attributeNumber || 0)
|
||||
.addInt32(field.dataTypeID || 0)
|
||||
.addInt16(field.dataTypeSize || 0)
|
||||
.addInt32(field.typeModifier || 0)
|
||||
.addInt16(field.formatCode || 0)
|
||||
})
|
||||
return buf.join(true, 'T')
|
||||
},
|
||||
|
||||
parameterDescription: function (dataTypeIDs: number[]) {
|
||||
dataTypeIDs = dataTypeIDs || []
|
||||
var buf = new BufferList()
|
||||
buf.addInt16(dataTypeIDs.length)
|
||||
dataTypeIDs.forEach(function (dataTypeID) {
|
||||
buf.addInt32(dataTypeID)
|
||||
})
|
||||
return buf.join(true, 't')
|
||||
},
|
||||
|
||||
dataRow: function (columns: any[]) {
|
||||
columns = columns || []
|
||||
var buf = new BufferList()
|
||||
buf.addInt16(columns.length)
|
||||
columns.forEach(function (col) {
|
||||
if (col == null) {
|
||||
buf.addInt32(-1)
|
||||
} else {
|
||||
var strBuf = Buffer.from(col, 'utf8')
|
||||
buf.addInt32(strBuf.length)
|
||||
buf.add(strBuf)
|
||||
}
|
||||
})
|
||||
return buf.join(true, 'D')
|
||||
},
|
||||
|
||||
error: function (fields: any) {
|
||||
return buffers.errorOrNotice(fields).join(true, 'E')
|
||||
},
|
||||
|
||||
notice: function (fields: any) {
|
||||
return buffers.errorOrNotice(fields).join(true, 'N')
|
||||
},
|
||||
|
||||
errorOrNotice: function (fields: any) {
|
||||
fields = fields || []
|
||||
var buf = new BufferList()
|
||||
fields.forEach(function (field: any) {
|
||||
buf.addChar(field.type)
|
||||
buf.addCString(field.value)
|
||||
})
|
||||
return buf.add(Buffer.from([0])) // terminator
|
||||
},
|
||||
|
||||
parseComplete: function () {
|
||||
return new BufferList().join(true, '1')
|
||||
},
|
||||
|
||||
bindComplete: function () {
|
||||
return new BufferList().join(true, '2')
|
||||
},
|
||||
|
||||
notification: function (id: number, channel: string, payload: string) {
|
||||
return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A')
|
||||
},
|
||||
|
||||
emptyQuery: function () {
|
||||
return new BufferList().join(true, 'I')
|
||||
},
|
||||
|
||||
portalSuspended: function () {
|
||||
return new BufferList().join(true, 's')
|
||||
},
|
||||
|
||||
closeComplete: function () {
|
||||
return new BufferList().join(true, '3')
|
||||
},
|
||||
|
||||
copyIn: function (cols: number) {
|
||||
const list = new BufferList()
|
||||
// text mode
|
||||
.addByte(0)
|
||||
// column count
|
||||
.addInt16(cols)
|
||||
for (let i = 0; i < cols; i++) {
|
||||
list.addInt16(i)
|
||||
}
|
||||
return list.join(true, 'G')
|
||||
},
|
||||
|
||||
copyOut: function (cols: number) {
|
||||
const list = new BufferList()
|
||||
// text mode
|
||||
.addByte(0)
|
||||
// column count
|
||||
.addInt16(cols)
|
||||
for (let i = 0; i < cols; i++) {
|
||||
list.addInt16(i)
|
||||
}
|
||||
return list.join(true, 'H')
|
||||
},
|
||||
|
||||
copyData: function (bytes: Buffer) {
|
||||
return new BufferList().add(bytes).join(true, 'd')
|
||||
},
|
||||
|
||||
copyDone: function () {
|
||||
return new BufferList().join(true, 'c')
|
||||
},
|
||||
}
|
||||
|
||||
export default buffers
|
1
websocket_server/node_modules/pg-protocol/src/types/chunky.d.ts
generated
vendored
Normal file
1
websocket_server/node_modules/pg-protocol/src/types/chunky.d.ts
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module 'chunky'
|
Reference in New Issue
Block a user