0.0.8 • Published 5 months ago

@electric-sql/pglite-socket v0.0.8

Weekly downloads
-
License
Apache-2.0
Repository
-
Last release
5 months ago

pglite-socket

A socket implementation for PGlite enabling remote connections. This package is a simple wrapper around the net module to allow PGlite to be used as a PostgreSQL server.

There are two main components to this package:

  • PGLiteSocketServer - A TCP server that allows PostgreSQL clients to connect to a PGlite database instance.
  • PGLiteSocketHandler - A low-level handler for a single socket connection to PGlite. This class handles the raw protocol communication between a socket and PGlite, and can be used to create a custom server.

The package also includes a CLI for quickly starting a PGlite socket server.

Note: As PGlite is a single-connection database, it is not possible to have multiple simultaneous connections open. This means that the socket server will only support a single client connection at a time. While a PGLiteSocketServer or PGLiteSocketHandler are attached to a PGlite instance they hold an exclusive lock preventing any other connections, or queries on the PGlite instance.

Installation

npm install @electric-sql/pglite-socket
# or
yarn add @electric-sql/pglite-socket
# or
pnpm add @electric-sql/pglite-socket

Usage

import { PGlite } from '@electric-sql/pglite'
import { PGLiteSocketServer } from '@electric-sql/pglite-socket'

// Create a PGlite instance
const db = await PGlite.create()

// Create and start a socket server
const server = new PGLiteSocketServer({
  db,
  port: 5432,
  host: '127.0.0.1',
})

await server.start()
console.log('Server started on 127.0.0.1:5432')

// Handle graceful shutdown
process.on('SIGINT', async () => {
  await server.stop()
  await db.close()
  console.log('Server stopped and database closed')
  process.exit(0)
})

API

PGLiteSocketServer

Creates a TCP server that allows PostgreSQL clients to connect to a PGlite database instance.

Options

  • db: PGlite - The PGlite database instance
  • port?: number - The port to listen on (default: 5432)
  • host?: string - The host to bind to (default: 127.0.0.1)
  • path?: string - Unix socket path to bind to (takes precedence over host:port)
  • inspect?: boolean - Print the incoming and outgoing data to the console (default: false)

Methods

  • start(): Promise<void> - Start the socket server
  • stop(): Promise<void> - Stop the socket server

Events

  • listening - Emitted when the server starts listening
  • connection - Emitted when a client connects
  • error - Emitted when an error occurs
  • close - Emitted when the server is closed

PGLiteSocketHandler

Low-level handler for a single socket connection to PGlite. This class handles the raw protocol communication between a socket and PGlite.

Options

  • db: PGlite - The PGlite database instance
  • closeOnDetach?: boolean - Whether to close the socket when detached (default: false)
  • inspect?: boolean - Print the incoming and outgoing data to the console in hex and ascii (default: false)

Methods

  • attach(socket: Socket): Promise<PGLiteSocketHandler> - Attach a socket to this handler
  • detach(close?: boolean): PGLiteSocketHandler - Detach the current socket from this handler
  • isAttached: boolean - Check if a socket is currently attached

Events

  • data - Emitted when data is processed through the handler
  • error - Emitted when an error occurs
  • close - Emitted when the socket is closed

Example

import { PGlite } from '@electric-sql/pglite'
import { PGLiteSocketHandler } from '@electric-sql/pglite-socket'
import { createServer, Socket } from 'net'

// Create a PGlite instance
const db = await PGlite.create()

// Create a handler
const handler = new PGLiteSocketHandler({
  db,
  closeOnDetach: true,
  inspect: false,
})

// Create a server that uses the handler
const server = createServer(async (socket: Socket) => {
  try {
    await handler.attach(socket)
    console.log('Client connected')
  } catch (err) {
    console.error('Error attaching socket', err)
    socket.end()
  }
})

server.listen(5432, '127.0.0.1')

Examples

See the examples directory for more usage examples.

CLI Usage

This package provides a command-line interface for quickly starting a PGlite socket server.

# Install globally
npm install -g @electric-sql/pglite-socket

# Start a server with default settings (in-memory database, port 5432)
pglite-server

# Start a server with custom options
pglite-server --db=/path/to/database --port=5433 --host=0.0.0.0 --debug=1

# Using short options
pglite-server -d /path/to/database -p 5433 -h 0.0.0.0 -v 1

# Show help
pglite-server --help

CLI Options

  • -d, --db=PATH - Database path (default: memory://)
  • -p, --port=PORT - Port to listen on (default: 5432)
  • -h, --host=HOST - Host to bind to (default: 127.0.0.1)
  • -u, --path=UNIX - Unix socket to bind to (takes precedence over host:port)
  • -v, --debug=LEVEL - Debug level 0-5 (default: 0)
  • -r, --run=COMMAND - Command to run after server starts
  • --include-database-url - Include DATABASE_URL in subprocess environment
  • --shutdown-timeout=MS - Timeout for graceful subprocess shutdown in ms (default: 5000)

Development Server Integration

The --run option is particularly useful for development workflows where you want to use PGlite as a drop-in replacement for PostgreSQL. This allows you to wrap your development server and automatically provide it with a DATABASE_URL pointing to your PGlite instance.

# Start your Next.js dev server with PGlite
pglite-server --run "npm run dev" --include-database-url

# Start a Node.js app with PGlite
pglite-server --db=./dev-db --run "node server.js" --include-database-url

# Start multiple services (using a process manager like concurrently)
pglite-server --run "npx concurrently 'npm run dev' 'npm run worker'" --include-database-url

When using --run with --include-database-url, the subprocess will receive a DATABASE_URL environment variable with the correct connection string for your PGlite server. This enables seamless integration with applications that expect a PostgreSQL connection string.

Using in npm scripts

You can add the CLI to your package.json scripts for convenient execution:

{
  "scripts": {
    "db:start": "pglite-server --db=./data/mydb --port=5433",
    "db:dev": "pglite-server --db=memory:// --debug=1",
    "dev": "pglite-server --db=./dev-db --run 'npm run start:dev' --include-database-url",
    "dev:clean": "pglite-server --run 'npm run start:dev' --include-database-url"
  }
}

Then run with:

npm run dev          # Start with persistent database
npm run dev:clean    # Start with in-memory database

Unix Socket Support

For better performance in local development, you can use Unix sockets instead of TCP:

# Start server on a Unix socket
pglite-server --path=/tmp/pglite.sock --run "npm run dev" --include-database-url

# The DATABASE_URL will be: postgresql://postgres:postgres@/postgres?host=/tmp

Connecting to the server

Once the server is running, you can connect to it using any PostgreSQL client:

Using psql

PGSSLMODE=disable psql -h localhost -p 5432 -d template1

Using Node.js clients

// Using node-postgres
import pg from 'pg'
const client = new pg.Client({
  host: 'localhost',
  port: 5432,
  database: 'template1'
})
await client.connect()

// Using postgres.js
import postgres from 'postgres'
const sql = postgres({
  host: 'localhost',
  port: 5432,
  database: 'template1'
})

// Using environment variable (when using --include-database-url)
const sql = postgres(process.env.DATABASE_URL)

Limitations and Tips

  • Remember that PGlite only supports one connection at a time. If you're unable to connect, make sure no other client is currently connected.
  • For development purposes, using an in-memory database (--db=memory://) is fastest but data won't persist after the server is stopped.
  • For persistent storage, specify a file path for the database (e.g., --db=./data/mydb).
  • When using debug mode (--debug=1 or higher), additional protocol information will be displayed in the console.
  • To allow connections from other machines, set the host to 0.0.0.0 with --host=0.0.0.0.
  • SSL connections are NOT supported. For psql, set env var PGSSLMODE=disable.
  • When using --run, the server will automatically shut down if the subprocess exits with a non-zero code.
  • Use --shutdown-timeout to adjust how long to wait for graceful subprocess termination (default: 5 seconds).

License

Apache 2.0

0.0.8

5 months ago

0.0.7

5 months ago

0.0.6

5 months ago

0.0.5

5 months ago

0.0.4

6 months ago

0.0.3

6 months ago

0.0.2

6 months ago