Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

pglite-server

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pglite-server - npm Package Compare versions

Comparing version
0.1.4
to
0.1.5
+100
-95
dist/index.js
// src/server.ts
import * as net from "node:net";
import * as net from "net";

@@ -14,7 +14,9 @@ // src/messages.ts

["F".charCodeAt(0)]: "FunctionCall",
["p".charCodeAt(0)]: "GSSResponse",
["P".charCodeAt(0)]: "Parse",
["p".charCodeAt(0)]: "PasswordMessage",
// GSSResponse and SASLResponse share the same 0x70 identifier as PasswordMessage.
// They cannot be distinguished by identifier alone and require connection state context.
// ["p".charCodeAt(0)]: "GSSResponse",
// ["p".charCodeAt(0)]: "SASLResponse",
["Q".charCodeAt(0)]: "Query",
["p".charCodeAt(0)]: "SASLResponse",
["S".charCodeAt(0)]: "Sync",

@@ -29,3 +31,3 @@ ["X".charCodeAt(0)]: "Terminate"

var INSUFFICIENT_DATA = {
name: "Unknown",
name: "InsufficientData",
length: 0,

@@ -47,39 +49,33 @@ buffer: Buffer.alloc(0)

function parseMessage(buffer) {
if (buffer.length === 0) {
if (buffer.length < 5) {
return INSUFFICIENT_DATA;
}
if (isCancelRequest(buffer)) {
const length2 = buffer.readUint32BE(0);
return {
name: "CancelRequest",
length: length2,
buffer: Buffer.from(buffer.subarray(0, length2))
};
if (buffer.length >= 8) {
let unidentifiedName = null;
if (isCancelRequest(buffer)) {
unidentifiedName = "CancelRequest";
} else if (isGSSENCRequest(buffer)) {
unidentifiedName = "GSSENCRequest";
} else if (isSSLRequest(buffer)) {
unidentifiedName = "SSLRequest";
} else if (isStartupMessage(buffer)) {
unidentifiedName = "StartupMessage";
}
if (unidentifiedName) {
const length2 = buffer.readUint32BE(0);
if (buffer.length < length2) {
return INSUFFICIENT_DATA;
}
return {
name: unidentifiedName,
length: length2,
buffer: Buffer.from(buffer.subarray(0, length2))
};
}
}
if (isGSSENCRequest(buffer)) {
const length2 = buffer.readUint32BE(0);
return {
name: "GSSENCRequest",
length: length2,
buffer: Buffer.from(buffer.subarray(0, length2))
};
}
if (isSSLRequest(buffer)) {
const length2 = buffer.readUint32BE(0);
return {
name: "SSLRequest",
length: length2,
buffer: Buffer.from(buffer.subarray(0, length2))
};
}
if (isStartupMessage(buffer)) {
const length2 = buffer.readUint32BE(0);
return {
name: "StartupMessage",
length: length2,
buffer: Buffer.from(buffer.subarray(0, length2))
};
}
const name = IDENT_TO_MESSAGE_NAME[buffer.at(0)];
if (!name) {
if (buffer.length < 8) {
return INSUFFICIENT_DATA;
}
return UNKNOWN_MESSAGE;

@@ -103,5 +99,6 @@ }

write(data) {
this.updateCapacity(data.length);
const byteLength = Buffer.byteLength(data);
this.updateCapacity(byteLength);
this.#buffer.write(data, this.#offset);
this.#offset += data.length;
this.#offset += byteLength;
}

@@ -131,14 +128,6 @@ writeUint8(data) {

// src/responses.ts
function createCancelRequest() {
return new GrowableOffsetBuffer().toBuffer();
}
function createGSSENCRequest() {
return new GrowableOffsetBuffer().toBuffer();
}
function createSSLRequestReponse() {
const sslNegotiation = new GrowableOffsetBuffer();
sslNegotiation.write("N");
return sslNegotiation.toBuffer();
}
function createStartupMessageReponse() {
var GSSENC_REQUEST_RESPONSE = Buffer.from("N");
var SSL_REQUEST_RESPONSE = Buffer.from("N");
var STARTUP_MESSAGE_RESPONSE = buildStartupMessageResponse();
function buildStartupMessageResponse() {
const authOk = new GrowableOffsetBuffer();

@@ -152,3 +141,3 @@ authOk.write("R");

parameterStatus.write("S");
parameterStatus.writeUint32BE(6 + paramKey.length + paramValue.length);
parameterStatus.writeUint32BE(6 + Buffer.byteLength(paramKey) + Buffer.byteLength(paramValue));
parameterStatus.write(paramKey);

@@ -174,6 +163,6 @@ parameterStatus.writeUint8(0);

}
function createErrorReponse(message) {
function createErrorResponse(message) {
const errorResponse = new GrowableOffsetBuffer();
errorResponse.write("E");
errorResponse.writeUint32BE(7 + message.length);
errorResponse.writeUint32BE(7 + Buffer.byteLength(message));
errorResponse.write("M");

@@ -191,13 +180,16 @@ errorResponse.write(message);

switch (message.name) {
// https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-CANCELING-REQUESTS
// CancelRequest is sent on a separate connection and expects no response.
// The server should simply close the connection after receiving it.
case "CancelRequest": {
return createCancelRequest();
return null;
}
case "GSSENCRequest": {
return createGSSENCRequest();
return GSSENC_REQUEST_RESPONSE;
}
case "SSLRequest": {
return createSSLRequestReponse();
return SSL_REQUEST_RESPONSE;
}
case "StartupMessage": {
return createStartupMessageReponse();
return STARTUP_MESSAGE_RESPONSE;
}

@@ -209,4 +201,4 @@ default: {

} catch (e) {
const message2 = e instanceof Error ? e.message : "Unknown error message";
return createErrorReponse(message2);
const errorMessage = e instanceof Error ? e.message : "Unknown error message";
return createErrorResponse(errorMessage);
}

@@ -249,41 +241,57 @@ }

// src/server.ts
async function processBuffer(clientBuffer, socket, db, logger) {
while (clientBuffer.length > 0) {
const message = parseMessage(clientBuffer);
logger.debug(`${"-".repeat(42)}
`);
logger.debug(`> Current buffer`);
logger.debug(`> Length: ${clientBuffer.length}`);
logger.debug(`> Raw:`, clientBuffer);
logger.debug(`> Text: ${clientBuffer.toString()}`);
logger.debug(``);
logger.debug(`>> Message name: ${message.name}`);
logger.debug(`>> Message length: ${message.length}`);
logger.debug(`>> Message buffer raw:`, message.buffer);
logger.debug(`>> Message buffer text: ${message.buffer.toString()}`);
logger.debug(``);
if (message.name === "InsufficientData") {
break;
}
if (message.name === "Unknown" || message.name === "Terminate") {
socket.end();
return clientBuffer;
}
const response = await createMessageResponse(message, db);
if (response === null) {
socket.end();
return clientBuffer;
}
socket.write(response);
clientBuffer = Buffer.from(clientBuffer.subarray(message.length));
logger.debug(`> Remaining buffer`);
logger.debug(`> Length: ${clientBuffer.length}`);
logger.debug(`> Raw:`, clientBuffer);
logger.debug(`> Text: ${clientBuffer.toString() || "<empty>"}`);
logger.debug(``);
}
return clientBuffer;
}
function createServer2(db, options = { logLevel: 2 /* Info */ }) {
const server = net.createServer(options);
const { logLevel, ...serverOptions } = options;
const server = net.createServer(serverOptions);
server.on("connection", function(socket) {
let clientBuffer = Buffer.allocUnsafe(0);
const clientAddr = `${socket.remoteAddress}:${socket.remotePort}`;
const logger = new Logger(options.logLevel, clientAddr);
const logger = new Logger(logLevel, clientAddr);
logger.info(`Client connected`);
socket.on("data", async (data) => {
socket.on("data", (data) => {
clientBuffer = Buffer.concat([clientBuffer, data]);
while (clientBuffer.length > 0) {
const message = parseMessage(clientBuffer);
logger.debug(`${"-".repeat(42)}
`);
logger.debug(`> Current buffer`);
logger.debug(`> Length: ${clientBuffer.length}`);
logger.debug(`> Raw:`, clientBuffer);
logger.debug(`> Text: ${clientBuffer.toString()}`);
logger.debug(``);
logger.debug(`>> Message name: ${message.name}`);
logger.debug(`>> Message length: ${message.length}`);
logger.debug(`>> Message buffer raw:`, message.buffer);
logger.debug(`>> Message buffer text: ${message.buffer.toString()}`);
logger.debug(``);
if (message.name === "InsufficientData") {
continue;
}
if (message.name === "Unknown" || message.name === "Terminate") {
socket.end();
return;
}
const response = await createMessageResponse(message, db);
socket.write(response);
clientBuffer = Buffer.from(clientBuffer.subarray(message.length));
logger.debug(`> Remaining buffer`);
logger.debug(`> Length: ${clientBuffer.length}`);
logger.debug(`> Raw:`, clientBuffer);
logger.debug(`> Text: ${clientBuffer.toString() || "<empty>"}`);
logger.debug(``);
}
socket.pause();
processBuffer(clientBuffer, socket, db, logger).then((remaining) => {
clientBuffer = remaining;
socket.resume();
}).catch((err) => {
logger.error("Unhandled error processing buffer:", err);
socket.end();
});
});

@@ -298,5 +306,2 @@ socket.on("end", () => {

});
server.on("error", (err) => {
throw err;
});
return server;

@@ -303,0 +308,0 @@ }

{
"name": "pglite-server",
"description": "Wire Protocol Server for PGlite",
"version": "0.1.4",
"version": "0.1.5",
"repository": {

@@ -26,10 +26,13 @@ "type": "git",

},
"peerDependencies": {
"@electric-sql/pglite": ">=0.2.0"
},
"devDependencies": {
"@electric-sql/pglite": "^0.2.13",
"@types/node": "^22.9.3",
"@types/pg": "^8.11.10",
"pg": "^8.13.1",
"tsup": "^8.3.5",
"typescript": "^5.7.2"
"@electric-sql/pglite": "^0.3.15",
"@types/node": "^25.2.1",
"@types/pg": "^8.16.0",
"pg": "^8.18.0",
"tsup": "^8.5.1",
"typescript": "^5.9.3"
}
}