Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
createSimpleProxy
✓ import { createSimpleProxy } from 'pg-server';
✗ const { createSimpleProxy } = require('pg-server');
This is the primary factory function to create a simple Postgres proxy server instance. The library is primarily designed for TypeScript/ESM usage.
ISimpleProxySession
✓ import { ISimpleProxySession } from 'pg-server';
This TypeScript interface defines the contract for session handlers that determine how `pg-server` processes new connections and SQL queries.
Socket
✓ import { Socket } from 'net';
The `Socket` type used within the `onConnect` handler (e.g., `onConnect(socket: Socket)`) refers to Node.js's built-in `net.Socket` and is not exported directly by `pg-server`.
Demonstrates setting up a Postgres proxy that filters SELECT queries based on allowed tables, integrating with `pgsql-ast-parser`, and includes a test client to show both allowed and blocked queries.
import { createSimpleProxy, ISimpleProxySession } from 'pg-server';
import { parse, astVisitor } from 'pgsql-ast-parser';
import { Client } from 'pg'; // For testing the connection
import { Socket } from 'net'; // For the onConnect handler's socket type
// Define a session class to handle connections and queries
class QueryFilteringProxySession implements ISimpleProxySession {
onConnect(socket: Socket) {
console.log(`👤 Client connected from ${socket.remoteAddress}:${socket.remotePort}`);
}
onQuery(query: string) {
try {
// Parse the query using pgsql-ast-parser
const parsedQueries = parse(query);
if (parsedQueries.length !== 1) {
return { error: 'Error: Only single queries accepted by this proxy.' };
}
const [firstQuery] = parsedQueries;
if (firstQuery.type !== 'select') {
return { error: 'Error: Only SELECT queries allowed by this proxy.' };
}
let authorized = true;
astVisitor(m => ({
tableRef: r => authorized = authorized
&& !r.schema // Ensure no explicit schema references for simplicity
&& ['public_data', 'reports'].includes(r.name) // Allow specific tables
})).statement(firstQuery);
if (!authorized) {
return { error: `Error: Access denied to table or query type. Only 'public_data' and 'reports' are allowed.` };
}
console.log(`✅ Allowed query: ${query.substring(0, Math.min(query.length, 100))}...`);
return query; // Proceed with the original query to the real database
} catch (e: any) {
console.error(`❌ Query parsing error for '${query.substring(0, Math.min(query.length, 50))}...': ${e.message}`);
return { error: `Invalid query syntax or internal parsing error: ${e.message}` };
}
}
}
// Create the proxy server, forwarding to a real Postgres instance on default port 5432
const REAL_DB_HOST = 'localhost';
const REAL_DB_PORT = 5432;
const PROXY_PORT = 1234;
const PROXY_HOST = '127.0.0.1';
const proxyServer = createSimpleProxy(
{ port: REAL_DB_PORT, host: REAL_DB_HOST }, // The real DB to proxy
QueryFilteringProxySession
);
proxyServer.listen(PROXY_PORT, PROXY_HOST, () => {
console.log(`🚀 pg-server proxy listening on ${PROXY_HOST}:${PROXY_PORT}`);
console.log(`Forwarding requests to real database at ${REAL_DB_HOST}:${REAL_DB_PORT}`);
// Example: Connecting a pg client to the proxy to test
const client = new Client(`postgresql://user:password@${PROXY_HOST}:${PROXY_PORT}/mydatabase`);
client.connect()
.then(() => {
console.log('Client connected to proxy successfully.');
// This query should be allowed
return client.query('SELECT id, name FROM public_data WHERE active = true;');
})
.then(res => console.log('Client query to public_data successful, rows:', res.rows.length))
.then(() => {
// This query should be blocked by the proxy
return client.query('SELECT * FROM secret_table;').catch(err => {
console.error('Client query to secret_table blocked as expected:', err.message);
return Promise.resolve(); // Prevent crashing the test
});
})
.catch(err => console.error('An unexpected client error occurred:', err.message))
.finally(() => client.end());
});
// Handle server-level errors
proxyServer.on('error', (err: NodeJS.ErrnoException) => {
if (err.code === 'EADDRINUSE') {
console.error(`Error: Port ${PROXY_PORT} is already in use. Please choose another port or stop the conflicting process.`);
} else {
console.error('Proxy server encountered an error:', err.message);
}
process.exit(1);
});
Errors
Common errors & fixes
Error: listen EADDRINUSE: address already in use :::1234
The specified port (e.g., 1234) that `pg-server` attempts to listen on is already in use by another process on your system.
fixChoose an available port for `proxyServer.listen()` or identify and stop the process currently using the conflicting port. On Linux, `sudo lsof -i :1234` can help identify the process.
Client query failed: connect ECONNREFUSED 127.0.0.1:5432
When `pg-server` is configured as a proxy, this error indicates that the target Postgres server (the `host:port` provided in `createSimpleProxy`'s first argument) is not running or is inaccessible from where `pg-server` is executed.
fixEnsure your actual Postgres database server is running and accessible on the specified host and port (e.g., `localhost:5432`). Check network connectivity and firewall rules if applicable.
TypeError: Cannot read properties of undefined (reading 'Client')
This error typically occurs in the test client code (e.g., `new Client()`) if the `pg` client library is not installed or incorrectly imported.
fixInstall the `pg` client library: `npm install pg` (and `npm install --save-dev @types/pg` if using TypeScript).
Query parsing error: expecting EOF at 'FROM' but found 'blah'
Your `onQuery` handler attempts to parse an invalid or unexpectedly formatted SQL query string using `pgsql-ast-parser`, leading to a parsing error.
fixEnsure the SQL query string passed to `parse()` is valid PostgreSQL syntax. Implement robust `try/catch` blocks around `parse()` calls in `onQuery` to gracefully handle malformed queries and provide informative error messages to the client.
Audit
Dependencies
pg-memoptionalOften used for in-memory database emulation alongside pg-server for testing and development.
pgsql-ast-parseroptionalRecommended for parsing and analyzing SQL queries when intercepting requests to implement custom filtering or modification logic.