Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@pgtyped/wire

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pgtyped/wire - npm Package Compare versions

Comparing version 0.4.5 to 0.5.0

63

lib/helpers.js
"use strict";
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sumSize = function (array) { return array
.reduce(function (acc, e) { return (acc + e.length); }, 0); };
exports.dictToArray = function (dict) { return (Object
.entries(dict)
.reduce(function (acc, _a) {
var key = _a[0], val = _a[1];
return __spreadArrays(acc, [key, val]);
}, [])); };
exports.int16 = function (val) {
var buf = Buffer.alloc(2);
exports.sumSize = (array) => array.reduce((acc, e) => acc + e.length, 0);
exports.dictToArray = (dict) => Object.entries(dict).reduce((acc, [key, val]) => [...acc, key, val], []);
exports.int16 = (val) => {
const buf = Buffer.alloc(2);
buf.writeUInt16BE(val, 0);
return buf;
};
exports.int32 = function (val) {
var buf = Buffer.alloc(4);
exports.int32 = (val) => {
const buf = Buffer.alloc(4);
buf.writeUInt32BE(val, 0);
return buf;
};
exports.cByteDict = function (dict) { return null; };
exports.cStringDict = function (dict) {
var dictArray = exports.dictToArray(dict);
var count = exports.sumSize(dictArray) + dictArray.length;
exports.cByteDict = (dict) => null;
exports.cStringDict = (dict) => {
const dictArray = exports.dictToArray(dict);
const count = exports.sumSize(dictArray) + dictArray.length;
// extra byte for dict terminator
var buf = Buffer.alloc(count + 1, 0);
var offset = 0;
dictArray.forEach(function (str) {
const buf = Buffer.alloc(count + 1, 0);
let offset = 0;
dictArray.forEach((str) => {
offset = offset + buf.write(str, offset) + 1;

@@ -40,22 +27,22 @@ });

};
exports.byte1 = function (num) { return Buffer.from(num); };
exports.byte4 = function () { return null; };
exports.byteN = function (buf) { return null; };
exports.cString = function (str) {
var buf = Buffer.alloc(str.length + 1, 0);
exports.byte1 = (num) => Buffer.from(num);
exports.byte4 = () => null;
exports.byteN = (buf) => null;
exports.cString = (str) => {
const buf = Buffer.alloc(str.length + 1, 0);
buf.write(str);
return buf;
};
exports.fixedArray = function (builder, items) {
var builtItems = items.map(builder);
var size = builtItems.reduce(function (acc, item) { return acc + exports.sumSize(item); }, 2);
var result = Buffer.alloc(size, 0);
exports.fixedArray = (builder, items) => {
const builtItems = items.map(builder);
const size = builtItems.reduce((acc, item) => acc + exports.sumSize(item), 2);
const result = Buffer.alloc(size, 0);
result.writeUInt16BE(items.length, 0);
var offset = 2;
builtItems.forEach(function (bufferArray) { return bufferArray.forEach(function (buffer) {
let offset = 2;
builtItems.forEach((bufferArray) => bufferArray.forEach((buffer) => {
buffer.copy(result, offset);
offset = offset + buffer.length;
}); });
}));
return result;
};
//# sourceMappingURL=helpers.js.map

@@ -1,2 +0,2 @@

export { AsyncQueue, } from "./queue";
export { messages, PreparedObjectType, } from "./messages";
export { AsyncQueue } from './queue';
export { messages, PreparedObjectType } from './messages';
/// <reference types="node" />
export interface IClientMessage<Params extends object | void> {
name: string;
type: "CLIENT";
type: 'CLIENT';
indicator: string | null;

@@ -9,7 +9,7 @@ pattern: (params: Params) => Buffer[];

declare type MapFields<Params> = {
[P in keyof Params]: (void | (Params[P] extends Array<infer R> ? Array<MapFields<R>> : (arg: Params[P]) => Buffer));
[P in keyof Params]: void | (Params[P] extends Array<infer R> ? Array<MapFields<R>> : (arg: Params[P]) => Buffer);
};
export interface IServerMessage<Params extends object> {
name: string;
type: "SERVER";
type: 'SERVER';
size?: number;

@@ -16,0 +16,0 @@ indicator: string;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var helpers_1 = require("./helpers");
const helpers_1 = require("./helpers");
/** The status of the the server query executor */

@@ -23,5 +23,5 @@ var TransactionStatus;

readyForQuery: {
name: "ReadyForQuery",
type: "SERVER",
indicator: "Z",
name: 'ReadyForQuery',
type: 'SERVER',
indicator: 'Z',
size: 5,

@@ -34,5 +34,5 @@ pattern: {

authenticationOk: {
name: "AuthenticationOk",
type: "SERVER",
indicator: "R",
name: 'AuthenticationOk',
type: 'SERVER',
indicator: 'R',
size: 8,

@@ -45,5 +45,5 @@ pattern: {

authenticationCleartextPassword: {
name: "AuthenticationCleartextPassword",
type: "SERVER",
indicator: "R",
name: 'AuthenticationCleartextPassword',
type: 'SERVER',
indicator: 'R',
size: 8,

@@ -56,5 +56,5 @@ pattern: {

authenticationMD5Password: {
name: "AuthenticationMD5Password",
type: "SERVER",
indicator: "R",
name: 'AuthenticationMD5Password',
type: 'SERVER',
indicator: 'R',
size: 12,

@@ -71,5 +71,5 @@ pattern: {

backendKeyData: {
name: "BackendKeyData",
type: "SERVER",
indicator: "K",
name: 'BackendKeyData',
type: 'SERVER',
indicator: 'K',
size: 12,

@@ -86,6 +86,6 @@ pattern: {

startupMessage: {
name: "StartupMessage",
type: "CLIENT",
name: 'StartupMessage',
type: 'CLIENT',
indicator: null,
pattern: function (data) { return [
pattern: (data) => [
// The protocol version number.

@@ -97,9 +97,9 @@ // The most significant 16 bits are the major version number (3 for the protocol described here).

helpers_1.cStringDict(data.params),
]; },
],
},
/** ParameterStatus message informs the frontend about the current (initial) setting of backend parameters. */
parameterStatus: {
name: "ParameterStatus",
type: "SERVER",
indicator: "S",
name: 'ParameterStatus',
type: 'SERVER',
indicator: 'S',
pattern: {

@@ -112,17 +112,13 @@ name: helpers_1.cString,

passwordMessage: {
name: "PasswordMessage",
type: "CLIENT",
indicator: "p",
pattern: function (data) { return [
helpers_1.cString(data.password),
]; },
name: 'PasswordMessage',
type: 'CLIENT',
indicator: 'p',
pattern: (data) => [helpers_1.cString(data.password)],
},
/** Query message initiates a simple query cycle. */
query: {
name: "Query",
type: "CLIENT",
indicator: "Q",
pattern: function (data) { return [
helpers_1.cString(data.query),
]; },
name: 'Query',
type: 'CLIENT',
indicator: 'Q',
pattern: (data) => [helpers_1.cString(data.query)],
},

@@ -135,5 +131,5 @@ /**

rowDescription: {
name: "RowDescription",
type: "SERVER",
indicator: "T",
name: 'RowDescription',
type: 'SERVER',
indicator: 'T',
pattern: {

@@ -155,9 +151,11 @@ fields: [

dataRow: {
name: "DataRow",
type: "SERVER",
indicator: "D",
name: 'DataRow',
type: 'SERVER',
indicator: 'D',
pattern: {
columns: [{
columns: [
{
value: helpers_1.byteN,
}],
},
],
},

@@ -169,6 +167,6 @@ },

noData: {
name: "NoData",
type: "SERVER",
name: 'NoData',
type: 'SERVER',
size: 5,
indicator: "n",
indicator: 'n',
pattern: {},

@@ -181,9 +179,11 @@ },

parameterDescription: {
name: "ParameterDescription",
type: "SERVER",
indicator: "t",
name: 'ParameterDescription',
type: 'SERVER',
indicator: 't',
pattern: {
params: [{
params: [
{
oid: helpers_1.int32,
}],
},
],
},

@@ -195,34 +195,23 @@ },

parse: {
name: "Parse",
type: "CLIENT",
indicator: "P",
pattern: function (params) { return [
name: 'Parse',
type: 'CLIENT',
indicator: 'P',
pattern: (params) => [
helpers_1.cString(params.name),
helpers_1.cString(params.query),
helpers_1.fixedArray(function (_a) {
var oid = _a.oid;
return [
helpers_1.int32(oid),
];
}, params.dataTypes),
]; },
helpers_1.fixedArray(({ oid }) => [helpers_1.int32(oid)], params.dataTypes),
],
},
/** Descibe message asks the server to describe prepared object (by replying with RowDescription and ParameterDescription messages) */
describe: {
name: "Describe",
type: "CLIENT",
indicator: "D",
pattern: function (_a) {
var name = _a.name, type = _a.type;
return [
helpers_1.byte1(type),
helpers_1.cString(name),
];
},
name: 'Describe',
type: 'CLIENT',
indicator: 'D',
pattern: ({ name, type }) => [helpers_1.byte1(type), helpers_1.cString(name)],
},
/** ParseComplete informs the client that prepared object parsing was successful */
parseComplete: {
name: "ParseComplete",
type: "SERVER",
indicator: "1",
name: 'ParseComplete',
type: 'SERVER',
indicator: '1',
size: 4,

@@ -233,21 +222,21 @@ pattern: {},

sync: {
name: "Sync",
type: "CLIENT",
indicator: "S",
name: 'Sync',
type: 'CLIENT',
indicator: 'S',
size: helpers_1.int32(4),
pattern: function () { return []; },
pattern: () => [],
},
/** Flush message asks the server to send all queued messages */
flush: {
name: "Flush",
type: "CLIENT",
indicator: "H",
name: 'Flush',
type: 'CLIENT',
indicator: 'H',
size: helpers_1.int32(4),
pattern: function () { return []; },
pattern: () => [],
},
/** ErrorResponse message is sent by the server when an error has occurred. */
errorResponse: {
name: "ErrorResponse",
type: "SERVER",
indicator: "E",
name: 'ErrorResponse',
type: 'SERVER',
indicator: 'E',
pattern: {

@@ -262,15 +251,12 @@ fields: helpers_1.cByteDict,

close: {
name: "Close",
type: "CLIENT",
indicator: "C",
pattern: function (params) { return [
helpers_1.byte1(params.target),
helpers_1.cString(params.targetName),
]; },
name: 'Close',
type: 'CLIENT',
indicator: 'C',
pattern: (params) => [helpers_1.byte1(params.target), helpers_1.cString(params.targetName)],
},
/** CloseComplete is sent by the server to signify that the prepared object was successfully close */
closeComplete: {
name: "CloseComplete",
type: "SERVER",
indicator: "3",
name: 'CloseComplete',
type: 'SERVER',
indicator: '3',
size: 4,

@@ -280,5 +266,5 @@ pattern: {},

commandComplete: {
name: "CommandComplete",
type: "SERVER",
indicator: "C",
name: 'CommandComplete',
type: 'SERVER',
indicator: 'C',
pattern: {

@@ -285,0 +271,0 @@ /**

/// <reference types="node" />
import { IClientMessage, IServerMessage } from "./messages";
import { IClientMessage, IServerMessage } from './messages';
export declare const parseSimpleType: (type: any, buf: Buffer, offset: number) => {

@@ -8,3 +8,3 @@ result: any;

export interface IMessagePayload<Params> {
type: "MessagePayload";
type: 'MessagePayload';
data: Params;

@@ -15,3 +15,3 @@ messageName: string;

interface IMessageMismatchError {
type: "MessageMismatchError";
type: 'MessageMismatchError';
messageName: string;

@@ -21,4 +21,4 @@ bufferOffset: number;

interface IServerError {
type: "ServerError";
severity: "ERROR" | "FATAL" | "PANIC" | "WARNING" | "NOTICE" | "DEBUG" | "INFO" | "LOG";
type: 'ServerError';
severity: 'ERROR' | 'FATAL' | 'PANIC' | 'WARNING' | 'NOTICE' | 'DEBUG' | 'INFO' | 'LOG';
message: string;

@@ -25,0 +25,0 @@ bufferOffset: number;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var helpers_1 = require("./helpers");
var messages_1 = require("./messages");
exports.parseSimpleType = function (type, buf, offset) {
var result = null;
const helpers_1 = require("./helpers");
const messages_1 = require("./messages");
exports.parseSimpleType = (type, buf, offset) => {
let result = null;
if (type instanceof Buffer) {
var match = type.compare(buf, offset, offset + type.length) === 0;
const match = type.compare(buf, offset, offset + type.length) === 0;
offset += type.length;
if (!match) {
throw new Error("Field mismatch inside message");
throw new Error(`Field mismatch inside message`);
}
}
else if (type === helpers_1.byte1) {
var val = buf.readInt8(offset);
const val = buf.readInt8(offset);
result = String.fromCharCode(val);

@@ -24,11 +24,11 @@ offset++;

else if (type === helpers_1.cString) {
var stringStart = offset;
const stringStart = offset;
while (buf.readInt8(offset) !== 0) {
offset++;
}
result = buf.toString("utf8", stringStart, offset);
result = buf.toString('utf8', stringStart, offset);
offset++;
}
else if (type === helpers_1.byteN) {
var chunkSize = buf.readInt32BE(offset);
const chunkSize = buf.readInt32BE(offset);
offset += 4;

@@ -46,20 +46,18 @@ result = buf.slice(offset, offset + chunkSize);

}
return { result: result, offset: offset };
return { result, offset };
};
var errorResponseMessageIndicator = messages_1.messages.errorResponse.indicator.charCodeAt(0);
exports.parseMessage = function (message, buf, messageOffset) {
var _a;
if (messageOffset === void 0) { messageOffset = 0; }
var bufferOffset = messageOffset;
var indicator = buf.readInt8(bufferOffset);
var expectedIndicator = message.indicator.charCodeAt(0);
var isUnexpectedErrorMessage = (indicator === errorResponseMessageIndicator
&& expectedIndicator !== errorResponseMessageIndicator);
const errorResponseMessageIndicator = messages_1.messages.errorResponse.indicator.charCodeAt(0);
exports.parseMessage = (message, buf, messageOffset = 0) => {
let bufferOffset = messageOffset;
const indicator = buf.readInt8(bufferOffset);
const expectedIndicator = message.indicator.charCodeAt(0);
const isUnexpectedErrorMessage = indicator === errorResponseMessageIndicator &&
expectedIndicator !== errorResponseMessageIndicator;
bufferOffset++;
var messageSize = buf.readUInt32BE(bufferOffset);
const messageSize = buf.readUInt32BE(bufferOffset);
// Add extra one because message id isnt counted into size
var messageEnd = messageSize + messageOffset + 1;
const messageEnd = messageSize + messageOffset + 1;
if (indicator !== expectedIndicator && !isUnexpectedErrorMessage) {
return {
type: "MessageMismatchError",
type: 'MessageMismatchError',
messageName: message.name,

@@ -70,16 +68,16 @@ bufferOffset: messageEnd,

bufferOffset += 4;
var pattern = isUnexpectedErrorMessage
const pattern = isUnexpectedErrorMessage
? messages_1.messages.errorResponse.pattern
: message.pattern;
var result = {};
var patternPairs = Object.entries(pattern);
var pairIndex = 0;
const result = {};
const patternPairs = Object.entries(pattern);
let pairIndex = 0;
try {
while (bufferOffset !== messageEnd) {
var _b = patternPairs[pairIndex], key = _b[0], type = _b[1];
const [key, type] = patternPairs[pairIndex];
if (type === helpers_1.cByteDict) {
var dict = {};
var fieldKey = void 0;
while ((_a = exports.parseSimpleType(helpers_1.byte1, buf, bufferOffset), fieldKey = _a.result, bufferOffset = _a.offset, _a).result !== "\u0000") {
var _c = exports.parseSimpleType(helpers_1.cString, buf, bufferOffset), fieldValue = _c.result, valueOffset = _c.offset;
const dict = {};
let fieldKey;
while (({ result: fieldKey, offset: bufferOffset } = exports.parseSimpleType(helpers_1.byte1, buf, bufferOffset)).result !== '\u0000') {
const { result: fieldValue, offset: valueOffset } = exports.parseSimpleType(helpers_1.cString, buf, bufferOffset);
bufferOffset = valueOffset;

@@ -91,11 +89,10 @@ dict[fieldKey] = fieldValue;

else if (type instanceof Array) {
var arraySize = buf.readInt16BE(bufferOffset);
const arraySize = buf.readInt16BE(bufferOffset);
bufferOffset += 2;
var array = [];
for (var i = 0; i < arraySize; i++) {
var subPattern = Object.entries(type[0]);
var subResult = {};
for (var _i = 0, subPattern_1 = subPattern; _i < subPattern_1.length; _i++) {
var _d = subPattern_1[_i], subKey = _d[0], subType = _d[1];
var _e = exports.parseSimpleType(subType, buf, bufferOffset), fieldResult = _e.result, fieldOffset = _e.offset;
const array = [];
for (let i = 0; i < arraySize; i++) {
const subPattern = Object.entries(type[0]);
const subResult = {};
for (const [subKey, subType] of subPattern) {
const { result: fieldResult, offset: fieldOffset, } = exports.parseSimpleType(subType, buf, bufferOffset);
subResult[subKey] = fieldResult;

@@ -109,3 +106,3 @@ bufferOffset = fieldOffset;

else {
var _f = exports.parseSimpleType(type, buf, bufferOffset), fieldResult = _f.result, fieldOffset = _f.offset;
const { result: fieldResult, offset: fieldOffset } = exports.parseSimpleType(type, buf, bufferOffset);
result[key] = fieldResult;

@@ -119,3 +116,3 @@ bufferOffset = fieldOffset;

return {
type: "MessageMismatchError",
type: 'MessageMismatchError',
messageName: message.name,

@@ -127,4 +124,4 @@ bufferOffset: messageEnd,

return {
type: "ServerError",
bufferOffset: bufferOffset,
type: 'ServerError',
bufferOffset,
severity: result.fields.S,

@@ -135,15 +132,15 @@ message: result.fields.M,

return {
type: "MessagePayload",
type: 'MessagePayload',
data: result,
bufferOffset: bufferOffset,
bufferOffset,
messageName: message.name,
};
};
exports.buildMessage = function (message, parameters) {
var bufArray = message.pattern(parameters);
var bufferSize = +(message.indicator ? 1 : 0) // indicator byte if present
+ 4 // message size
+ helpers_1.sumSize(bufArray); // payload
var buf = Buffer.alloc(bufferSize);
var offset = 0;
exports.buildMessage = (message, parameters) => {
const bufArray = message.pattern(parameters);
const bufferSize = +(message.indicator ? 1 : 0) + // indicator byte if present
4 + // message size
helpers_1.sumSize(bufArray); // payload
const buf = Buffer.alloc(bufferSize);
let offset = 0;
if (message.indicator) {

@@ -153,6 +150,6 @@ buf[0] = message.indicator.charCodeAt(0);

}
var messageSize = bufferSize - (message.indicator ? 1 : 0);
const messageSize = bufferSize - (message.indicator ? 1 : 0);
buf.writeUInt32BE(messageSize, offset);
offset += 4;
bufArray.forEach(function (sbuf) {
bufArray.forEach((sbuf) => {
sbuf.copy(buf, offset);

@@ -163,9 +160,8 @@ offset = offset + sbuf.length;

};
exports.parseOneOf = function (messages, buffer, offset) {
var messageName = messages.map(function (m) { return m.name; }).join(" | ");
var lastBufferOffset = 0;
for (var _i = 0, messages_2 = messages; _i < messages_2.length; _i++) {
var message = messages_2[_i];
var parseResult = exports.parseMessage(message, buffer, offset);
if (parseResult.type !== "MessageMismatchError") {
exports.parseOneOf = (messages, buffer, offset) => {
const messageName = messages.map((m) => m.name).join(' | ');
let lastBufferOffset = 0;
for (const message of messages) {
const parseResult = exports.parseMessage(message, buffer, offset);
if (parseResult.type !== 'MessageMismatchError') {
return parseResult;

@@ -176,4 +172,4 @@ }

return {
type: "MessageMismatchError",
messageName: messageName,
type: 'MessageMismatchError',
messageName,
bufferOffset: lastBufferOffset,

@@ -180,0 +176,0 @@ };

/// <reference types="node" />
import * as net from "net";
import { ParseResult } from "./protocol";
import { IClientMessage, IServerMessage } from "./messages";
import * as net from 'net';
import { ParseResult } from './protocol';
import { IClientMessage, IServerMessage } from './messages';
declare type Box<T> = T extends IServerMessage<infer P> ? P : any;

@@ -6,0 +6,0 @@ declare type Boxified<T extends [any] | any[]> = {

@@ -11,29 +11,2 @@ "use strict";

};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importStar = (this && this.__importStar) || function (mod) {

@@ -50,9 +23,8 @@ if (mod && mod.__esModule) return mod;

Object.defineProperty(exports, "__esModule", { value: true });
var net = __importStar(require("net"));
var protocol_1 = require("./protocol");
var debug_1 = __importDefault(require("debug"));
var debug = debug_1.default("pg-wire:socket");
var AsyncQueue = /** @class */ (function () {
function AsyncQueue() {
var _this = this;
const net = __importStar(require("net"));
const protocol_1 = require("./protocol");
const debug_1 = __importDefault(require("debug"));
const debug = debug_1.default('pg-wire:socket');
class AsyncQueue {
constructor() {
this.queue = [];

@@ -62,42 +34,37 @@ this.bufferOffset = 0;

this.socket = new net.Socket({});
this.socket.on("data", function (buffer) {
debug("received %o bytes", buffer.length);
_this.queue.push(buffer);
_this.processQueue();
this.socket.on('data', (buffer) => {
debug('received %o bytes', buffer.length);
this.queue.push(buffer);
this.processQueue();
});
}
AsyncQueue.prototype.connect = function (passedOptions) {
var _this = this;
return new Promise(function (resolve) {
_this.socket.on("connect", function () {
debug("socket connected");
connect(passedOptions) {
return new Promise((resolve) => {
this.socket.on('connect', () => {
debug('socket connected');
resolve();
});
var defaultOptions = {
const defaultOptions = {
port: 5432,
host: "localhost",
host: 'localhost',
};
var options = Object.assign({}, defaultOptions, passedOptions || {});
_this.socket.connect(options);
const options = Object.assign({}, defaultOptions, passedOptions || {});
this.socket.connect(options);
});
};
AsyncQueue.prototype.send = function (message, params) {
return __awaiter(this, void 0, void 0, function () {
var buf;
var _this = this;
return __generator(this, function (_a) {
buf = protocol_1.buildMessage(message, params);
return [2 /*return*/, new Promise(function (resolve) {
_this.socket.write(buf, function () { return resolve(); });
debug("sent %o message", message.name);
})];
}
send(message, params) {
return __awaiter(this, void 0, void 0, function* () {
const buf = protocol_1.buildMessage(message, params);
return new Promise((resolve) => {
this.socket.write(buf, () => resolve());
debug('sent %o message', message.name);
});
});
};
AsyncQueue.prototype.processQueue = function () {
}
processQueue() {
if (!this.replyPending || this.queue.length === 0) {
return;
}
var buf = this.queue[0];
var parsed = this.replyPending.parser(buf, this.bufferOffset);
const buf = this.queue[0];
const parsed = this.replyPending.parser(buf, this.bufferOffset);
// Move queue cursor in any case

@@ -111,14 +78,14 @@ if (parsed.bufferOffset >= buf.length) {

}
if (parsed.type === "ServerError") {
if (parsed.type === 'ServerError') {
this.replyPending.reject(parsed);
}
else if (parsed.type === "MessagePayload") {
debug("resolved awaited %o message", parsed.messageName);
else if (parsed.type === 'MessagePayload') {
debug('resolved awaited %o message', parsed.messageName);
this.replyPending.resolve(parsed.data);
}
else {
debug("received ignored message");
debug('received ignored message');
this.processQueue();
}
};
}
/**

@@ -129,31 +96,23 @@ * Waits for the next message to arrive and parses it, resolving with the parsed value.

*/
AsyncQueue.prototype.reply = function () {
var messages = [];
for (var _i = 0; _i < arguments.length; _i++) {
messages[_i] = arguments[_i];
}
return __awaiter(this, void 0, void 0, function () {
var parser;
var _this = this;
return __generator(this, function (_a) {
if (messages instanceof Array) {
parser = function (buf, offset) { return protocol_1.parseOneOf(messages, buf, offset); };
}
else {
parser = function (buf, offset) { return protocol_1.parseMessage(messages, buf, offset); };
}
return [2 /*return*/, new Promise(function (resolve, reject) {
_this.replyPending = {
resolve: resolve,
reject: reject,
parser: parser,
};
_this.processQueue();
})];
reply(...messages) {
return __awaiter(this, void 0, void 0, function* () {
let parser;
if (messages instanceof Array) {
parser = (buf, offset) => protocol_1.parseOneOf(messages, buf, offset);
}
else {
parser = (buf, offset) => protocol_1.parseMessage(messages, buf, offset);
}
return new Promise((resolve, reject) => {
this.replyPending = {
resolve,
reject,
parser,
};
this.processQueue();
});
});
};
return AsyncQueue;
}());
}
}
exports.AsyncQueue = AsyncQueue;
//# sourceMappingURL=queue.js.map
{
"name": "@pgtyped/wire",
"version": "0.4.5",
"version": "0.5.0",
"main": "lib/index.js",

@@ -26,3 +26,3 @@ "types": "lib/index.d.ts",

},
"gitHead": "07cefb2dfd1b4cb9428aa7c7da29c8443ab07b22"
"gitHead": "402a85b9371411c50715e8198ded259ae464e956"
}

@@ -1,2 +0,2 @@

import { SSL_OP_TLS_D5_BUG } from "constants";
import { SSL_OP_TLS_D5_BUG } from 'constants';

@@ -6,11 +6,9 @@ interface ISized {

}
export const sumSize = (array: ISized[]): number => array
.reduce((acc, e) => (acc + e.length), 0);
export const sumSize = (array: ISized[]): number =>
array.reduce((acc, e) => acc + e.length, 0);
export const dictToArray = (
dict: { [key: string]: string },
): string[] => (
Object
.entries(dict)
.reduce((acc, [key, val]) => [...acc, key, val], [] as string[])
export const dictToArray = (dict: { [key: string]: string }): string[] =>
Object.entries(dict).reduce(
(acc, [key, val]) => [...acc, key, val],
[] as string[],
);

@@ -30,3 +28,4 @@

export const cByteDict = (dict: { [key: string]: string }): Buffer => (null as any);
export const cByteDict = (dict: { [key: string]: string }): Buffer =>
null as any;

@@ -49,5 +48,5 @@ export const cStringDict = (dict: { [key: string]: string }): Buffer => {

export const byte4 = (): Buffer => (null as any);
export const byte4 = (): Buffer => null as any;
export const byteN = (buf: Buffer): Buffer => (null as any);
export const byteN = (buf: Buffer): Buffer => null as any;

@@ -72,10 +71,9 @@ export const cString = (str: string): Buffer => {

let offset = 2;
builtItems.forEach(
(bufferArray) => bufferArray.forEach(
(buffer) => {
buffer.copy(result, offset);
offset = offset + buffer.length;
}),
builtItems.forEach((bufferArray) =>
bufferArray.forEach((buffer) => {
buffer.copy(result, offset);
offset = offset + buffer.length;
}),
);
return result;
};

@@ -1,8 +0,3 @@

export {
AsyncQueue,
} from "./queue";
export { AsyncQueue } from './queue';
export {
messages,
PreparedObjectType,
} from "./messages";
export { messages, PreparedObjectType } from './messages';

@@ -11,7 +11,7 @@ import {

int32,
} from "./helpers";
} from './helpers';
export interface IClientMessage<Params extends object | void> {
name: string;
type: "CLIENT";
type: 'CLIENT';
indicator: string | null;

@@ -22,6 +22,7 @@ pattern: (params: Params) => Buffer[];

type MapFields<Params> = {
[P in keyof Params]: (
void
| (Params[P] extends Array<infer R> ? Array<MapFields<R>> : (arg: Params[P]) => Buffer)
)
[P in keyof Params]:
| void
| (Params[P] extends Array<infer R>
? Array<MapFields<R>>
: (arg: Params[P]) => Buffer);
};

@@ -31,3 +32,3 @@

name: string;
type: "SERVER";
type: 'SERVER';
size?: number;

@@ -41,9 +42,9 @@ indicator: string;

/** Transaction idle (not in a transaction block) */
Idle = "I",
Idle = 'I',
/** In a transaction block */
Transaction = "T",
Transaction = 'T',
/** Failed transaction block (queries will be rejected until block is ended) */
Error = "E",
Error = 'E',
}

@@ -53,4 +54,4 @@

export enum PreparedObjectType {
Portal = "P",
Statement = "S",
Portal = 'P',
Statement = 'S',
}

@@ -61,5 +62,5 @@

readyForQuery: {
name: "ReadyForQuery",
type: "SERVER",
indicator: "Z",
name: 'ReadyForQuery',
type: 'SERVER',
indicator: 'Z',
size: 5,

@@ -72,5 +73,5 @@ pattern: {

authenticationOk: {
name: "AuthenticationOk",
type: "SERVER",
indicator: "R",
name: 'AuthenticationOk',
type: 'SERVER',
indicator: 'R',
size: 8,

@@ -83,5 +84,5 @@ pattern: {

authenticationCleartextPassword: {
name: "AuthenticationCleartextPassword",
type: "SERVER",
indicator: "R",
name: 'AuthenticationCleartextPassword',
type: 'SERVER',
indicator: 'R',
size: 8,

@@ -94,5 +95,5 @@ pattern: {

authenticationMD5Password: {
name: "AuthenticationMD5Password",
type: "SERVER",
indicator: "R",
name: 'AuthenticationMD5Password',
type: 'SERVER',
indicator: 'R',
size: 12,

@@ -105,3 +106,3 @@ pattern: {

/** md5 salt to use */
salt: Buffer,
salt: Buffer;
}>,

@@ -113,5 +114,5 @@ /**

backendKeyData: {
name: "BackendKeyData",
type: "SERVER",
indicator: "K",
name: 'BackendKeyData',
type: 'SERVER',
indicator: 'K',
size: 12,

@@ -124,5 +125,5 @@ pattern: {

/** The process ID of the backend. */
processId: number,
processId: number;
/** The secret key of the backend. */
secretKey: number,
secretKey: number;
}>,

@@ -134,4 +135,4 @@ /**

startupMessage: {
name: "StartupMessage",
type: "CLIENT",
name: 'StartupMessage',
type: 'CLIENT',
indicator: null,

@@ -162,9 +163,9 @@ pattern: (data) => [

*/
params: { [key: string]: string },
params: { [key: string]: string };
}>,
/** ParameterStatus message informs the frontend about the current (initial) setting of backend parameters. */
parameterStatus: {
name: "ParameterStatus",
type: "SERVER",
indicator: "S",
name: 'ParameterStatus',
type: 'SERVER',
indicator: 'S',
pattern: {

@@ -176,29 +177,25 @@ name: cString,

/** The name of the run-time parameter being reported */
name: string,
name: string;
/** The current value of the parameter */
value: string,
value: string;
}>,
/** PasswordMessage sends a password response on initial auth. */
passwordMessage: {
name: "PasswordMessage",
type: "CLIENT",
indicator: "p",
pattern: (data) => [
cString(data.password),
],
name: 'PasswordMessage',
type: 'CLIENT',
indicator: 'p',
pattern: (data) => [cString(data.password)],
} as IClientMessage<{
/** Password string either plain text or MD5 encrypted */
password: string,
password: string;
}>,
/** Query message initiates a simple query cycle. */
query: {
name: "Query",
type: "CLIENT",
indicator: "Q",
pattern: (data) => [
cString(data.query),
],
name: 'Query',
type: 'CLIENT',
indicator: 'Q',
pattern: (data) => [cString(data.query)],
} as IClientMessage<{
/** SQL command (or commands) expressed as a text string */
query: string,
query: string;
}>,

@@ -211,5 +208,5 @@ /**

rowDescription: {
name: "RowDescription",
type: "SERVER",
indicator: "T",
name: 'RowDescription',
type: 'SERVER',
indicator: 'T',
pattern: {

@@ -231,26 +228,28 @@ fields: [

/** The field name. */
name: string,
name: string;
/** If the field can be identified as a column of a specific table, the object ID of the table; otherwise zero. */
tableOID: number,
tableOID: number;
/** If the field can be identified as a column of a specific table, the attribute number of the column; otherwise zero. */
columnAttrNumber: number,
columnAttrNumber: number;
/** The object ID of the field's data type. */
typeOID: number,
typeOID: number;
/** The data type size (see pg_type.typlen). Note that negative values denote variable-width types. */
typeSize: number,
typeSize: number;
/** The type modifier (see pg_attribute.atttypmod). The meaning of the modifier is type-specific. */
typeModifier: number,
typeModifier: number;
/** The format code being used for the field. Currently will be zero (text) or one (binary). In a RowDescription returned from the statement variant of Describe, the format code is not yet known and will always be zero. */
formatCode: number,
}>,
formatCode: number;
}>;
}>,
/** DataRow message returns one of the set of rows returned by the query */
dataRow: {
name: "DataRow",
type: "SERVER",
indicator: "D",
name: 'DataRow',
type: 'SERVER',
indicator: 'D',
pattern: {
columns: [{
value: byteN,
}],
columns: [
{
value: byteN,
},
],
},

@@ -261,4 +260,4 @@ } as IServerMessage<{

/** The value of the column, in the format indicated by the associated format code. n is the above length. */
value: Buffer,
}>,
value: Buffer;
}>;
}>,

@@ -269,6 +268,6 @@ /**

noData: {
name: "NoData",
type: "SERVER",
name: 'NoData',
type: 'SERVER',
size: 5,
indicator: "n",
indicator: 'n',
pattern: {},

@@ -281,9 +280,11 @@ } as IServerMessage<{}>,

parameterDescription: {
name: "ParameterDescription",
type: "SERVER",
indicator: "t",
name: 'ParameterDescription',
type: 'SERVER',
indicator: 't',
pattern: {
params: [{
oid: int32,
}],
params: [
{
oid: int32,
},
],
},

@@ -294,4 +295,4 @@ } as IServerMessage<{

/** Specifies the object ID of the parameter data type. */
oid: number,
}>,
oid: number;
}>;
}>,

@@ -302,46 +303,38 @@ /**

parse: {
name: "Parse",
type: "CLIENT",
indicator: "P",
name: 'Parse',
type: 'CLIENT',
indicator: 'P',
pattern: (params) => [
cString(params.name),
cString(params.query),
fixedArray(
({ oid }) => [
int32(oid),
],
params.dataTypes,
),
fixedArray(({ oid }) => [int32(oid)], params.dataTypes),
],
} as IClientMessage<{
/** The name of the destination prepared statement (an empty string selects the unnamed prepared statement). */
name: string,
name: string;
/** The query string to be parsed. */
query: string,
query: string;
/** Parameter data types specified (can be empty). Note that this is not an indication of the number of parameters that might appear in the query string, only the number that the frontend wants to prespecify types for. */
dataTypes: Array<{
/** Specifies the object ID of the parameter data type. Placing a zero here is equivalent to leaving the type unspecified. */
oid: number,
}>,
oid: number;
}>;
}>,
/** Descibe message asks the server to describe prepared object (by replying with RowDescription and ParameterDescription messages) */
describe: {
name: "Describe",
type: "CLIENT",
indicator: "D",
pattern: ({ name, type }) => [
byte1(type),
cString(name),
],
name: 'Describe',
type: 'CLIENT',
indicator: 'D',
pattern: ({ name, type }) => [byte1(type), cString(name)],
} as IClientMessage<{
/** The name of the prepared statement or portal to describe (an empty string selects the unnamed prepared statement or portal). */
name: string,
name: string;
/** 'S' to describe a prepared statement; or 'P' to describe a portal. */
type: PreparedObjectType,
type: PreparedObjectType;
}>,
/** ParseComplete informs the client that prepared object parsing was successful */
parseComplete: {
name: "ParseComplete",
type: "SERVER",
indicator: "1",
name: 'ParseComplete',
type: 'SERVER',
indicator: '1',
size: 4,

@@ -352,5 +345,5 @@ pattern: {},

sync: {
name: "Sync",
type: "CLIENT",
indicator: "S",
name: 'Sync',
type: 'CLIENT',
indicator: 'S',
size: int32(4),

@@ -361,5 +354,5 @@ pattern: () => [],

flush: {
name: "Flush",
type: "CLIENT",
indicator: "H",
name: 'Flush',
type: 'CLIENT',
indicator: 'H',
size: int32(4),

@@ -370,5 +363,5 @@ pattern: () => [],

errorResponse: {
name: "ErrorResponse",
type: "SERVER",
indicator: "E",
name: 'ErrorResponse',
type: 'SERVER',
indicator: 'E',
pattern: {

@@ -381,10 +374,10 @@ fields: cByteDict,

/** PG routine reporting the error */
R: string,
R: string;
/** Error message */
M: string,
M: string;
/** Error hint */
H?: string,
H?: string;
/** Error position */
P?: string,
},
P?: string;
};
}>,

@@ -396,20 +389,17 @@ /**

close: {
name: "Close",
type: "CLIENT",
indicator: "C",
pattern: (params) => [
byte1(params.target),
cString(params.targetName),
],
name: 'Close',
type: 'CLIENT',
indicator: 'C',
pattern: (params) => [byte1(params.target), cString(params.targetName)],
} as IClientMessage<{
/** 'S' to close a prepared statement; or 'P' to close a portal. */
target: PreparedObjectType,
target: PreparedObjectType;
/** The name of the prepared statement or portal to close (an empty string selects the unnamed prepared statement or portal). */
targetName: string,
targetName: string;
}>,
/** CloseComplete is sent by the server to signify that the prepared object was successfully close */
closeComplete: {
name: "CloseComplete",
type: "SERVER",
indicator: "3",
name: 'CloseComplete',
type: 'SERVER',
indicator: '3',
size: 4,

@@ -419,5 +409,5 @@ pattern: {},

commandComplete: {
name: "CommandComplete",
type: "SERVER",
indicator: "C",
name: 'CommandComplete',
type: 'SERVER',
indicator: 'C',
pattern: {

@@ -439,8 +429,10 @@ /**

export type TMessage = IServerMessage<{ commandTag: string }> | IServerMessage<{
/** Row columns array */
columns: Array<{
/** The value of the column, in the format indicated by the associated format code. n is the above length. */
value: Buffer,
}>,
}>;
export type TMessage =
| IServerMessage<{ commandTag: string }>
| IServerMessage<{
/** Row columns array */
columns: Array<{
/** The value of the column, in the format indicated by the associated format code. n is the above length. */
value: Buffer;
}>;
}>;
import {
byte1, byte4,
byte1,
byte4,
byteN,

@@ -9,3 +10,3 @@ cByteDict,

sumSize,
} from "./helpers";
} from './helpers';

@@ -16,7 +17,11 @@ import {

IServerMessage,
} from "./messages";
} from './messages';
export const parseSimpleType = (type: any, buf: Buffer, offset: number): {
result: any,
export const parseSimpleType = (
type: any,
buf: Buffer,
offset: number,
): {
result: any;
offset: number;
} => {

@@ -42,3 +47,3 @@ let result = null;

}
result = buf.toString("utf8", stringStart, offset);
result = buf.toString('utf8', stringStart, offset);
offset++;

@@ -57,7 +62,7 @@ } else if (type === byteN) {

}
return {result, offset};
return { result, offset };
};
export interface IMessagePayload<Params> {
type: "MessagePayload";
type: 'MessagePayload';
data: Params;

@@ -69,3 +74,3 @@ messageName: string;

interface IMessageMismatchError {
type: "MessageMismatchError";
type: 'MessageMismatchError';
messageName: string;

@@ -76,4 +81,12 @@ bufferOffset: number;

interface IServerError {
type: "ServerError";
severity: "ERROR" | "FATAL" | "PANIC" | "WARNING" | "NOTICE" | "DEBUG" | "INFO" | "LOG";
type: 'ServerError';
severity:
| 'ERROR'
| 'FATAL'
| 'PANIC'
| 'WARNING'
| 'NOTICE'
| 'DEBUG'
| 'INFO'
| 'LOG';
message: string;

@@ -83,5 +96,10 @@ bufferOffset: number;

export type ParseResult<Params> = IMessagePayload<Params> | IMessageMismatchError | IServerError;
export type ParseResult<Params> =
| IMessagePayload<Params>
| IMessageMismatchError
| IServerError;
const errorResponseMessageIndicator = pgMessages.errorResponse.indicator.charCodeAt(0);
const errorResponseMessageIndicator = pgMessages.errorResponse.indicator.charCodeAt(
0,
);

@@ -96,6 +114,5 @@ export const parseMessage = <Params extends object>(

const expectedIndicator = message.indicator.charCodeAt(0);
const isUnexpectedErrorMessage = (
indicator === errorResponseMessageIndicator
&& expectedIndicator !== errorResponseMessageIndicator
);
const isUnexpectedErrorMessage =
indicator === errorResponseMessageIndicator &&
expectedIndicator !== errorResponseMessageIndicator;

@@ -111,3 +128,3 @@ bufferOffset++;

return {
type: "MessageMismatchError",
type: 'MessageMismatchError',
messageName: message.name,

@@ -133,10 +150,14 @@ bufferOffset: messageEnd,

let fieldKey;
while (({
result: fieldKey,
offset: bufferOffset,
} = parseSimpleType(byte1, buf, bufferOffset)).result !== "\u0000") {
const {
result: fieldValue,
offset: valueOffset,
} = parseSimpleType(cString, buf, bufferOffset);
while (
({ result: fieldKey, offset: bufferOffset } = parseSimpleType(
byte1,
buf,
bufferOffset,
)).result !== '\u0000'
) {
const { result: fieldValue, offset: valueOffset } = parseSimpleType(
cString,
buf,
bufferOffset,
);
bufferOffset = valueOffset;

@@ -165,6 +186,7 @@ dict[fieldKey] = fieldValue;

} else {
const {
result: fieldResult,
offset: fieldOffset,
} = parseSimpleType(type, buf, bufferOffset);
const { result: fieldResult, offset: fieldOffset } = parseSimpleType(
type,
buf,
bufferOffset,
);
result[key] = fieldResult;

@@ -177,3 +199,3 @@ bufferOffset = fieldOffset;

return {
type: "MessageMismatchError",
type: 'MessageMismatchError',
messageName: message.name,

@@ -186,3 +208,3 @@ bufferOffset: messageEnd,

return {
type: "ServerError",
type: 'ServerError',
bufferOffset,

@@ -194,3 +216,3 @@ severity: result.fields.S,

return {
type: "MessagePayload",
type: 'MessagePayload',
data: result as Params,

@@ -208,5 +230,5 @@ bufferOffset,

const bufferSize =
+(message.indicator ? 1 : 0) // indicator byte if present
+ 4 // message size
+ sumSize(bufArray); // payload
+(message.indicator ? 1 : 0) + // indicator byte if present
4 + // message size
sumSize(bufArray); // payload
const buf = Buffer.alloc(bufferSize);

@@ -235,7 +257,7 @@ let offset = 0;

): ParseResult<object> => {
const messageName = messages.map((m) => m.name).join(" | ");
const messageName = messages.map((m) => m.name).join(' | ');
let lastBufferOffset = 0;
for (const message of messages) {
const parseResult = parseMessage(message, buffer, offset);
if (parseResult.type !== "MessageMismatchError") {
if (parseResult.type !== 'MessageMismatchError') {
return parseResult;

@@ -246,3 +268,3 @@ }

return {
type: "MessageMismatchError",
type: 'MessageMismatchError',
messageName,

@@ -249,0 +271,0 @@ bufferOffset: lastBufferOffset,

@@ -1,3 +0,3 @@

import * as net from "net";
import * as util from "util";
import * as net from 'net';
import * as util from 'util';

@@ -9,12 +9,8 @@ import {

ParseResult,
} from "./protocol";
} from './protocol';
import {
IClientMessage,
TMessage,
IServerMessage,
} from "./messages";
import { IClientMessage, TMessage, IServerMessage } from './messages';
import debugBase from "debug";
const debug = debugBase("pg-wire:socket");
import debugBase from 'debug';
const debug = debugBase('pg-wire:socket');

@@ -29,10 +25,10 @@ type Box<T> = T extends IServerMessage<infer P> ? P : any;

public replyPending: {
resolve: (data: any) => any,
reject: (data: any) => any,
parser: (buf: Buffer, offset: number) => ParseResult<object>,
resolve: (data: any) => any;
reject: (data: any) => any;
parser: (buf: Buffer, offset: number) => ParseResult<object>;
} | null = null;
constructor() {
this.socket = new net.Socket({});
this.socket.on("data", (buffer: Buffer) => {
debug("received %o bytes", buffer.length);
this.socket.on('data', (buffer: Buffer) => {
debug('received %o bytes', buffer.length);
this.queue.push(buffer);

@@ -43,7 +39,8 @@ this.processQueue();

public connect(passedOptions?: {
port?: number, host?: string,
port?: number;
host?: string;
}): Promise<void> {
return new Promise((resolve) => {
this.socket.on("connect", () => {
debug("socket connected");
this.socket.on('connect', () => {
debug('socket connected');
resolve();

@@ -53,9 +50,5 @@ });

port: 5432,
host: "localhost",
host: 'localhost',
};
const options = Object.assign(
{},
defaultOptions,
passedOptions || {},
);
const options = Object.assign({}, defaultOptions, passedOptions || {});
this.socket.connect(options);

@@ -71,3 +64,3 @@ });

this.socket.write(buf, () => resolve());
debug("sent %o message", message.name);
debug('sent %o message', message.name);
});

@@ -90,9 +83,9 @@ }

if (parsed.type === "ServerError") {
if (parsed.type === 'ServerError') {
this.replyPending.reject(parsed);
} else if (parsed.type === "MessagePayload") {
debug("resolved awaited %o message", parsed.messageName);
} else if (parsed.type === 'MessagePayload') {
debug('resolved awaited %o message', parsed.messageName);
this.replyPending.resolve(parsed.data);
} else {
debug("received ignored message");
debug('received ignored message');
this.processQueue();

@@ -111,5 +104,7 @@ }

if (messages instanceof Array) {
parser = (buf: Buffer, offset: number) => parseOneOf(messages, buf, offset);
parser = (buf: Buffer, offset: number) =>
parseOneOf(messages, buf, offset);
} else {
parser = (buf: Buffer, offset: number) => parseMessage(messages, buf, offset);
parser = (buf: Buffer, offset: number) =>
parseMessage(messages, buf, offset);
}

@@ -116,0 +111,0 @@ return new Promise((resolve, reject) => {

@@ -8,6 +8,6 @@ import {

sumSize,
} from "../src/helpers";
} from '../src/helpers';
test("cString works", () => {
const str = "a";
test('cString works', () => {
const str = 'a';
const base = cString(str);

@@ -18,3 +18,3 @@ const expected = Buffer.from([str.charCodeAt(0), 0]);

test("int32 works", () => {
test('int32 works', () => {
const base = int32(1000000);

@@ -25,15 +25,18 @@ const expected = Buffer.from([0, 15, 66, 64]);

test("sumSize works", () => {
const base = sumSize([[1, 2], [3, 4]]);
test('sumSize works', () => {
const base = sumSize([
[1, 2],
[3, 4],
]);
expect(base).toBe(4);
});
test("dictToArray works", () => {
const base = dictToArray({ a: "x", b: "y" });
const expected = ["a", "x", "b", "y"];
test('dictToArray works', () => {
const base = dictToArray({ a: 'x', b: 'y' });
const expected = ['a', 'x', 'b', 'y'];
expect(base).toEqual(expected);
});
test("cStringDicts works", () => {
const base = cStringDict({ a: "x", b: "y" });
test('cStringDicts works', () => {
const base = cStringDict({ a: 'x', b: 'y' });
const expected = Buffer.from([97, 0, 120, 0, 98, 0, 121, 0, 0]);

@@ -43,19 +46,28 @@ expect(base).toEqual(expected);

test("fixedArray works", () => {
const base =
fixedArray(
({ a, b }) => [
int32(a),
int32(b),
],
[{ a: 1, b: 2 }, {a: 3, b: 4}],
);
test('fixedArray works', () => {
const base = fixedArray(({ a, b }) => [int32(a), int32(b)], [
{ a: 1, b: 2 },
{ a: 3, b: 4 },
]);
const expected = Buffer.from([
0, 2,
0, 0, 0, 1,
0, 0, 0, 2,
0, 0, 0, 3,
0, 0, 0, 4,
0,
2,
0,
0,
0,
1,
0,
0,
0,
2,
0,
0,
0,
3,
0,
0,
0,
4,
]);
expect(base).toEqual(expected);
});

@@ -7,66 +7,201 @@ import {

ParseResult,
} from "../src/protocol";
} from '../src/protocol';
import {
messages,
IServerMessage,
} from "../src/messages";
import { messages, IServerMessage } from '../src/messages';
test("buildMessage for StartupMessage works", () => {
const base = buildMessage(
messages.startupMessage,
{
params:
{
user: "testingdb-app",
database: "testingdb",
client_encoding: "'utf-8'",
},
test('buildMessage for StartupMessage works', () => {
const base = buildMessage(messages.startupMessage, {
params: {
user: 'testingdb-app',
database: 'testingdb',
client_encoding: "'utf-8'",
},
);
});
const expected = Buffer.from([
0x00, 0x00, 0x00, 0x47,
0x00, 0x03, 0x00, 0x00,
0x75, 0x73, 0x65, 0x72,
0x00, 0x74, 0x65, 0x73,
0x74, 0x69, 0x6e, 0x67,
0x64, 0x62, 0x2d, 0x61,
0x70, 0x70, 0x00, 0x64,
0x61, 0x74, 0x61, 0x62,
0x61, 0x73, 0x65, 0x00,
0x74, 0x65, 0x73, 0x74,
0x69, 0x6e, 0x67, 0x64,
0x62, 0x00, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74,
0x5f, 0x65, 0x6e, 0x63,
0x6f, 0x64, 0x69, 0x6e,
0x67, 0x00, 0x27, 0x75,
0x74, 0x66, 0x2d, 0x38,
0x27, 0x00, 0x00]);
0x00,
0x00,
0x00,
0x47,
0x00,
0x03,
0x00,
0x00,
0x75,
0x73,
0x65,
0x72,
0x00,
0x74,
0x65,
0x73,
0x74,
0x69,
0x6e,
0x67,
0x64,
0x62,
0x2d,
0x61,
0x70,
0x70,
0x00,
0x64,
0x61,
0x74,
0x61,
0x62,
0x61,
0x73,
0x65,
0x00,
0x74,
0x65,
0x73,
0x74,
0x69,
0x6e,
0x67,
0x64,
0x62,
0x00,
0x63,
0x6c,
0x69,
0x65,
0x6e,
0x74,
0x5f,
0x65,
0x6e,
0x63,
0x6f,
0x64,
0x69,
0x6e,
0x67,
0x00,
0x27,
0x75,
0x74,
0x66,
0x2d,
0x38,
0x27,
0x00,
0x00,
]);
expect(base).toEqual(expected);
});
test("parseMessage for ErrorResponse works", () => {
test('parseMessage for ErrorResponse works', () => {
const buf = Buffer.from([
0x45, 0x00, 0x00, 0x00, 0x5d, 0x53, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x00, 0x56,
0x46, 0x41, 0x54, 0x41, 0x4c, 0x00, 0x43, 0x33, 0x44, 0x30, 0x30, 0x30, 0x00,
0x4d, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x20, 0x22, 0x74, 0x65,
0x73, 0x74, 0x69, 0x6e, 0x64, 0x62, 0x22, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20,
0x6e, 0x6f, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x00, 0x46, 0x70, 0x6f,
0x73, 0x74, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x63, 0x00, 0x4c, 0x38, 0x34, 0x36,
0x00, 0x52, 0x49, 0x6e, 0x69, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x67, 0x72, 0x65,
0x73, 0x00, 0x00,
0x45,
0x00,
0x00,
0x00,
0x5d,
0x53,
0x46,
0x41,
0x54,
0x41,
0x4c,
0x00,
0x56,
0x46,
0x41,
0x54,
0x41,
0x4c,
0x00,
0x43,
0x33,
0x44,
0x30,
0x30,
0x30,
0x00,
0x4d,
0x64,
0x61,
0x74,
0x61,
0x62,
0x61,
0x73,
0x65,
0x20,
0x22,
0x74,
0x65,
0x73,
0x74,
0x69,
0x6e,
0x64,
0x62,
0x22,
0x20,
0x64,
0x6f,
0x65,
0x73,
0x20,
0x6e,
0x6f,
0x74,
0x20,
0x65,
0x78,
0x69,
0x73,
0x74,
0x00,
0x46,
0x70,
0x6f,
0x73,
0x74,
0x69,
0x6e,
0x69,
0x74,
0x2e,
0x63,
0x00,
0x4c,
0x38,
0x34,
0x36,
0x00,
0x52,
0x49,
0x6e,
0x69,
0x74,
0x50,
0x6f,
0x73,
0x74,
0x67,
0x72,
0x65,
0x73,
0x00,
0x00,
]);
const result = parseMessage(messages.errorResponse, buf);
if (result.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (result.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data, bufferOffset } = result;
const expected = {
fields: {
C: "3D000",
F: "postinit.c",
L: "846",
C: '3D000',
F: 'postinit.c',
L: '846',
M: 'database "testindb" does not exist',
R: "InitPostgres",
S: "FATAL",
V: "FATAL",
R: 'InitPostgres',
S: 'FATAL',
V: 'FATAL',
},

@@ -78,19 +213,107 @@ };

test("parseMessage for normal message returns ServerError if message is ErrorResponse", () => {
test('parseMessage for normal message returns ServerError if message is ErrorResponse', () => {
const buf = Buffer.from([
0x45, 0x00, 0x00, 0x00, 0x5d, 0x53, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x00, 0x56,
0x46, 0x41, 0x54, 0x41, 0x4c, 0x00, 0x43, 0x33, 0x44, 0x30, 0x30, 0x30, 0x00,
0x4d, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x20, 0x22, 0x74, 0x65,
0x73, 0x74, 0x69, 0x6e, 0x64, 0x62, 0x22, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20,
0x6e, 0x6f, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x00, 0x46, 0x70, 0x6f,
0x73, 0x74, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x63, 0x00, 0x4c, 0x38, 0x34, 0x36,
0x00, 0x52, 0x49, 0x6e, 0x69, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x67, 0x72, 0x65,
0x73, 0x00, 0x00,
0x45,
0x00,
0x00,
0x00,
0x5d,
0x53,
0x46,
0x41,
0x54,
0x41,
0x4c,
0x00,
0x56,
0x46,
0x41,
0x54,
0x41,
0x4c,
0x00,
0x43,
0x33,
0x44,
0x30,
0x30,
0x30,
0x00,
0x4d,
0x64,
0x61,
0x74,
0x61,
0x62,
0x61,
0x73,
0x65,
0x20,
0x22,
0x74,
0x65,
0x73,
0x74,
0x69,
0x6e,
0x64,
0x62,
0x22,
0x20,
0x64,
0x6f,
0x65,
0x73,
0x20,
0x6e,
0x6f,
0x74,
0x20,
0x65,
0x78,
0x69,
0x73,
0x74,
0x00,
0x46,
0x70,
0x6f,
0x73,
0x74,
0x69,
0x6e,
0x69,
0x74,
0x2e,
0x63,
0x00,
0x4c,
0x38,
0x34,
0x36,
0x00,
0x52,
0x49,
0x6e,
0x69,
0x74,
0x50,
0x6f,
0x73,
0x74,
0x67,
0x72,
0x65,
0x73,
0x00,
0x00,
]);
const result = parseMessage(messages.readyForQuery, buf);
if (result.type !== "ServerError") { throw new Error("Expected ServerError"); }
if (result.type !== 'ServerError') {
throw new Error('Expected ServerError');
}
const expected = {
type: "ServerError",
type: 'ServerError',
message: 'database "testindb" does not exist',
severity: "FATAL",
severity: 'FATAL',
bufferOffset: 94,

@@ -101,11 +324,67 @@ };

test("parseMessage for RowData works", () => {
test('parseMessage for RowData works', () => {
const buf = Buffer.from([
0x44, 0x00, 0x00, 0x00, 0x39, 0x00, 0x02, 0x00, 0x00, 0x00, 0x24, 0x35, 0x64, 0x30, 0x37, 0x38,
0x63, 0x33, 0x36, 0x2d, 0x37, 0x32, 0x37, 0x36, 0x2d, 0x31, 0x31, 0x65, 0x39, 0x2d, 0x38, 0x38,
0x32, 0x63, 0x2d, 0x31, 0x37, 0x37, 0x33, 0x64, 0x35, 0x38, 0x33, 0x61, 0x63, 0x61, 0x34, 0x00,
0x00, 0x00, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64,
0x44,
0x00,
0x00,
0x00,
0x39,
0x00,
0x02,
0x00,
0x00,
0x00,
0x24,
0x35,
0x64,
0x30,
0x37,
0x38,
0x63,
0x33,
0x36,
0x2d,
0x37,
0x32,
0x37,
0x36,
0x2d,
0x31,
0x31,
0x65,
0x39,
0x2d,
0x38,
0x38,
0x32,
0x63,
0x2d,
0x31,
0x37,
0x37,
0x33,
0x64,
0x35,
0x38,
0x33,
0x61,
0x63,
0x61,
0x34,
0x00,
0x00,
0x00,
0x07,
0x6f,
0x72,
0x64,
0x65,
0x72,
0x65,
0x64,
]);
const result = parseMessage(messages.dataRow, buf);
if (result.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (result.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data, bufferOffset } = result;

@@ -115,6 +394,6 @@ const expected = {

{
value: Buffer.from("5d078c36-7276-11e9-882c-1773d583aca4"),
value: Buffer.from('5d078c36-7276-11e9-882c-1773d583aca4'),
},
{
value: Buffer.from("ordered"),
value: Buffer.from('ordered'),
},

@@ -127,11 +406,61 @@ ],

test("parseMessage for RowDescription works", () => {
test('parseMessage for RowDescription works', () => {
const buf = Buffer.from([
0x54, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x69, 0x64, 0x00, 0x00, 0x01, 0x4c,
0x36, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x86, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x65, 0x00, 0x00, 0x01, 0x4c, 0x36, 0x00,
0x04, 0x00, 0x00, 0x00, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x54,
0x00,
0x00,
0x00,
0x33,
0x00,
0x02,
0x69,
0x64,
0x00,
0x00,
0x01,
0x4c,
0x36,
0x00,
0x01,
0x00,
0x00,
0x0b,
0x86,
0x00,
0x10,
0xff,
0xff,
0xff,
0xff,
0x00,
0x00,
0x73,
0x74,
0x61,
0x74,
0x65,
0x00,
0x00,
0x01,
0x4c,
0x36,
0x00,
0x04,
0x00,
0x00,
0x00,
0x19,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0x00,
0x00,
]);
const result = parseMessage(messages.rowDescription, buf);
if (result.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (result.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data, bufferOffset } = result;

@@ -141,3 +470,3 @@ const expected = {

{
name: "id",
name: 'id',
tableOID: 85046,

@@ -151,3 +480,3 @@ columnAttrNumber: 1,

{
name: "state",
name: 'state',
tableOID: 85046,

@@ -166,11 +495,11 @@ columnAttrNumber: 4,

test("parseMessage for ReadyForQuery works", () => {
const buf = Buffer.from([
0x5a, 0x00, 0x00, 0x00, 0x05, 0x49,
]);
test('parseMessage for ReadyForQuery works', () => {
const buf = Buffer.from([0x5a, 0x00, 0x00, 0x00, 0x05, 0x49]);
const result = parseMessage(messages.readyForQuery, buf);
if (result.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (result.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data, bufferOffset } = result;
const expected = {
trxStatus: "I",
trxStatus: 'I',
};

@@ -181,5 +510,17 @@ expect(bufferOffset).toBe(buf.length);

test("parseMessage for backendKeyData works", () => {
test('parseMessage for backendKeyData works', () => {
const buf = Buffer.from([
0x4b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x1b, 0x91, 0x25, 0x83, 0x8d, 0x83,
0x4b,
0x00,
0x00,
0x00,
0x0c,
0x00,
0x01,
0x1b,
0x91,
0x25,
0x83,
0x8d,
0x83,
]);

@@ -191,3 +532,5 @@ const expected = {

const result = parseMessage(messages.backendKeyData, buf);
if (result.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (result.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data, bufferOffset } = result;

@@ -199,14 +542,39 @@

test("parseMessage for ParameterStatus works", () => {
test('parseMessage for ParameterStatus works', () => {
const buf = Buffer.from([
0x53, 0x00, 0x00, 0x00, 0x19, 0x54, 0x69, 0x6d, 0x65,
0x5a, 0x6f, 0x6e, 0x65, 0x00, 0x45, 0x75, 0x72, 0x6f,
0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x00,
0x53,
0x00,
0x00,
0x00,
0x19,
0x54,
0x69,
0x6d,
0x65,
0x5a,
0x6f,
0x6e,
0x65,
0x00,
0x45,
0x75,
0x72,
0x6f,
0x70,
0x65,
0x2f,
0x4b,
0x69,
0x65,
0x76,
0x00,
]);
const expected = {
name: "TimeZone",
value: "Europe/Kiev",
name: 'TimeZone',
value: 'Europe/Kiev',
};
const result = parseMessage(messages.parameterStatus, buf);
if (result.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (result.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data, bufferOffset } = result;

@@ -218,6 +586,4 @@

test("parseMessage for NoData works", () => {
const buf = Buffer.from([
0x6e, 0x00, 0x00, 0x00, 0x04,
]);
test('parseMessage for NoData works', () => {
const buf = Buffer.from([0x6e, 0x00, 0x00, 0x00, 0x04]);

@@ -231,35 +597,98 @@ const result = parseMessage(messages.noData, buf);

test("parseMessage for Query works", () => {
test('parseMessage for Query works', () => {
const buf = Buffer.from([
0x51, 0x00, 0x00, 0x00, 0x16, 0x73, 0x65, 0x6c, 0x65,
0x63, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x28, 0x29, 0x3b, 0x00,
0x51,
0x00,
0x00,
0x00,
0x16,
0x73,
0x65,
0x6c,
0x65,
0x63,
0x74,
0x20,
0x76,
0x65,
0x72,
0x73,
0x69,
0x6f,
0x6e,
0x28,
0x29,
0x3b,
0x00,
]);
const base = buildMessage(
messages.query,
{ query: "select version();" },
);
const base = buildMessage(messages.query, { query: 'select version();' });
expect(base).toEqual(buf);
});
test("parseMessage works for sequence of ParameterStatus", () => {
test('parseMessage works for sequence of ParameterStatus', () => {
const buf = Buffer.from([
0x53, 0x00, 0x00, 0x00, 0x19, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x55,
0x54, 0x46, 0x38, 0x00,
0x53,
0x00,
0x00,
0x00,
0x19,
0x63,
0x6c,
0x69,
0x65,
0x6e,
0x74,
0x5f,
0x65,
0x6e,
0x63,
0x6f,
0x64,
0x69,
0x6e,
0x67,
0x00,
0x55,
0x54,
0x46,
0x38,
0x00,
0x53, 0x00, 0x00, 0x00, 0x17, 0x44, 0x61, 0x74, 0x65, 0x53, 0x74,
0x79, 0x6c, 0x65, 0x00, 0x49, 0x53, 0x4f, 0x2c, 0x20, 0x4d, 0x44,
0x59, 0x00,
0x53,
0x00,
0x00,
0x00,
0x17,
0x44,
0x61,
0x74,
0x65,
0x53,
0x74,
0x79,
0x6c,
0x65,
0x00,
0x49,
0x53,
0x4f,
0x2c,
0x20,
0x4d,
0x44,
0x59,
0x00,
]);
const expectedFirst = {
name: "client_encoding",
value: "UTF8",
name: 'client_encoding',
value: 'UTF8',
};
const expectedSecond = {
name: "DateStyle",
value: "ISO, MDY",
name: 'DateStyle',
value: 'ISO, MDY',
};
const resultOne = parseMessage(messages.parameterStatus, buf);
if (resultOne.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (resultOne.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data: dataOne, bufferOffset: offsetOne } = resultOne;

@@ -271,3 +700,5 @@

const resultTwo = parseMessage(messages.parameterStatus, buf, 26);
if (resultTwo.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (resultTwo.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data: dataTwo, bufferOffset: offsetTwo } = resultTwo;

@@ -279,17 +710,43 @@

test("parseOneOf works", () => {
test('parseOneOf works', () => {
const buf = Buffer.from([
0x53, 0x00, 0x00, 0x00, 0x19, 0x54, 0x69, 0x6d, 0x65,
0x5a, 0x6f, 0x6e, 0x65, 0x00, 0x45, 0x75, 0x72, 0x6f,
0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x00,
0x53,
0x00,
0x00,
0x00,
0x19,
0x54,
0x69,
0x6d,
0x65,
0x5a,
0x6f,
0x6e,
0x65,
0x00,
0x45,
0x75,
0x72,
0x6f,
0x70,
0x65,
0x2f,
0x4b,
0x69,
0x65,
0x76,
0x00,
]);
const expected = {
name: "TimeZone",
value: "Europe/Kiev",
name: 'TimeZone',
value: 'Europe/Kiev',
};
const result = parseOneOf(
[messages.authenticationOk, messages.parameterStatus],
buf, 0,
buf,
0,
);
if (result.type !== "MessagePayload") { throw new Error("Expected MessagePayload"); }
if (result.type !== 'MessagePayload') {
throw new Error('Expected MessagePayload');
}
const { data, bufferOffset } = result;

@@ -300,17 +757,41 @@ expect(bufferOffset).toBe(buf.length);

test("parseOneOf results in MessageMismatchError when no message matches buffer", () => {
test('parseOneOf results in MessageMismatchError when no message matches buffer', () => {
const buf = Buffer.from([
0x53, 0x00, 0x00, 0x00, 0x19, 0x54, 0x69, 0x6d, 0x65,
0x5a, 0x6f, 0x6e, 0x65, 0x00, 0x45, 0x75, 0x72, 0x6f,
0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x00,
0x53,
0x00,
0x00,
0x00,
0x19,
0x54,
0x69,
0x6d,
0x65,
0x5a,
0x6f,
0x6e,
0x65,
0x00,
0x45,
0x75,
0x72,
0x6f,
0x70,
0x65,
0x2f,
0x4b,
0x69,
0x65,
0x76,
0x00,
]);
const result = parseOneOf(
[messages.authenticationOk, messages.readyForQuery],
buf, 0,
buf,
0,
);
if (result.type !== "MessageMismatchError") {
throw new Error("Expected MessageMismatchError");
if (result.type !== 'MessageMismatchError') {
throw new Error('Expected MessageMismatchError');
}
expect(result.messageName).toBe("AuthenticationOk | ReadyForQuery");
expect(result.messageName).toBe('AuthenticationOk | ReadyForQuery');
expect(result.bufferOffset).toBe(buf.length);
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc