PostgreSQL Wire Protocol Parser/Serializer

1.13.0 · active · verified Sun Apr 19

pg-protocol is a foundational TypeScript library that implements the PostgreSQL client/server binary wire protocol. It provides low-level parsing and serialization capabilities for PostgreSQL messages, serving as a core internal dependency for the popular `node-postgres` client library. The version specified for this entry is 1.13.0 (though npm's 'latest' tag currently points to 1.12.0), and its release cadence is tied closely to the development of `node-postgres` itself, meaning updates are often driven by new PostgreSQL features or performance enhancements needed by the higher-level client. Its key differentiator is its precise, TypeScript-driven implementation of the PostgreSQL protocol specification, enabling robust and type-safe interaction at the binary level. While it can be used independently for specialized tasks like building custom PostgreSQL proxies or analytics tools, its primary role is to abstract away the intricate protocol details for database client developers.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates how to initialize the Parser to consume an incoming PostgreSQL `ReadyForQuery` message and how to use the Serializer to create an outgoing SQL `Query` message buffer. This highlights the low-level parsing and serialization capabilities.

import { Parser, Serializer } from 'pg-protocol';
import { Query, ReadyForQueryMessage, BackendMessageCode } from 'pg-protocol/dist/messages';

// 1. Simulate an incoming 'ReadyForQuery' message from the server
// (Type 'Z' for ReadyForQuery, length, transaction status 'I' for idle)
const readyForQueryBuffer = Buffer.from([BackendMessageCode.ReadyForQuery, 0, 0, 0, 5, 'I'.charCodeAt(0)]);

const parser = new Parser();
parser.parse(readyForQueryBuffer);

// In a real scenario, you'd listen to 'message' events
// For this example, we'll manually check the parsed queue
let parsedMessage: ReadyForQueryMessage | undefined;
while (true) {
    const msg = parser.shift();
    if (msg) {
        if (msg.name === 'ReadyForQuery') {
            parsedMessage = msg as ReadyForQueryMessage;
            console.log(`Parsed ReadyForQuery: Transaction Status = ${parsedMessage.transactionStatus}`);
            break;
        }
    } else {
        break;
    }
}

if (!parsedMessage) {
    console.error('Failed to parse ReadyForQuery message.');
}

// 2. Serialize an outgoing 'Query' message to the server
const query = 'SELECT 1 + 1 AS solution;';
const serializer = new Serializer();

// The Query message expects a string and can be serialized directly
const queryMessage = new Query(query);
const serializedBuffer = serializer.query(query);

console.log(`
Original Query: ${query}`);
console.log('Serialized Query Buffer (first 20 bytes):', serializedBuffer.toString('hex').substring(0, 40), '...');
console.log(`Buffer length: ${serializedBuffer.length} bytes`);

// Example: Basic structure of a 'Query' message buffer
// Message type 'Q', then length including length itself, then query string + null terminator
const expectedHeader = Buffer.from([0x51, 0x00, 0x00, 0x00, (query.length + 5) >> 8, 0x00, 0x00, 0x00, (query.length + 5) & 0xFF]);
// Note: Actual serialization includes the string and null terminator.
// This is a simplified check.

view raw JSON →