Aktueller Stand

This commit is contained in:
2026-01-23 01:33:35 +01:00
parent 082dc5e110
commit 2766dd12c5
10109 changed files with 1578841 additions and 77685 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,160 @@
import { PGlite } from '@electric-sql/pglite';
import { Socket } from 'net';
declare const CONNECTION_QUEUE_TIMEOUT = 60000;
/**
* Options for creating a PGLiteSocketHandler
*/
interface PGLiteSocketHandlerOptions {
/** The PGlite database instance */
db: PGlite;
/** Whether to close the socket when detached (default: false) */
closeOnDetach?: boolean;
/** Print the incoming and outgoing data to the console in hex and ascii */
inspect?: boolean;
/** Enable debug logging of method calls */
debug?: boolean;
}
/**
* Low-level handler for a single socket connection to PGLite
* Handles the raw protocol communication between a socket and PGLite
*/
declare class PGLiteSocketHandler extends EventTarget {
readonly db: PGlite;
private socket;
private active;
private closeOnDetach;
private resolveLock?;
private rejectLock?;
private inspect;
private debug;
private readonly id;
private static nextHandlerId;
/**
* Create a new PGLiteSocketHandler
* @param options Options for the handler
*/
constructor(options: PGLiteSocketHandlerOptions);
/**
* Get the unique ID of this handler
*/
get handlerId(): number;
/**
* Log a message if debug is enabled
* @private
*/
private log;
/**
* Attach a socket to this handler
* @param socket The socket to attach
* @returns this handler instance
* @throws Error if a socket is already attached
*/
attach(socket: Socket): Promise<PGLiteSocketHandler>;
/**
* Detach the current socket from this handler
* @param close Whether to close the socket when detaching (overrides constructor option)
* @returns this handler instance
*/
detach(close?: boolean): PGLiteSocketHandler;
/**
* Check if a socket is currently attached
*/
get isAttached(): boolean;
/**
* Handle incoming data from the socket
*/
private handleData;
/**
* Handle errors from the socket
*/
private handleError;
/**
* Handle socket close event
*/
private handleClose;
/**
* Print data in hex and ascii to the console
*/
private inspectData;
}
/**
* Options for creating a PGLiteSocketServer
*/
interface PGLiteSocketServerOptions {
/** The PGlite database instance */
db: PGlite;
/** The port to listen on (default: 5432) */
port?: number;
/** The host to bind to (default: 127.0.0.1) */
host?: string;
/** Unix socket path to bind to (default: undefined). If specified, takes precedence over host:port */
path?: string;
/** Print the incoming and outgoing data to the console in hex and ascii */
inspect?: boolean;
/** Connection queue timeout in milliseconds (default: 10000) */
connectionQueueTimeout?: number;
/** Enable debug logging of method calls */
debug?: boolean;
}
/**
* High-level server that manages socket connections to PGLite
* Creates and manages a TCP server and handles client connections
*/
declare class PGLiteSocketServer extends EventTarget {
readonly db: PGlite;
private server;
private port?;
private host?;
private path?;
private active;
private inspect;
private debug;
private connectionQueueTimeout;
private activeHandler;
private connectionQueue;
private handlerCount;
/**
* Create a new PGLiteSocketServer
* @param options Options for the server
*/
constructor(options: PGLiteSocketServerOptions);
/**
* Log a message if debug is enabled
* @private
*/
private log;
/**
* Start the socket server
* @returns Promise that resolves when the server is listening
*/
start(): Promise<void>;
getServerConn(): string;
/**
* Stop the socket server
* @returns Promise that resolves when the server is closed
*/
stop(): Promise<void>;
/**
* Get the active handler ID, or null if no active handler
*/
private get activeHandlerId();
/**
* Handle a new client connection
*/
private handleConnection;
/**
* Add a connection to the queue
*/
private enqueueConnection;
/**
* Process the next connection in the queue
*/
private processNextInQueue;
/**
* Attach a socket to a new handler
*/
private attachSocketToNewHandler;
}
export { CONNECTION_QUEUE_TIMEOUT, PGLiteSocketHandler, type PGLiteSocketHandlerOptions, PGLiteSocketServer, type PGLiteSocketServerOptions };

View File

@@ -0,0 +1,160 @@
import { PGlite } from '@electric-sql/pglite';
import { Socket } from 'net';
declare const CONNECTION_QUEUE_TIMEOUT = 60000;
/**
* Options for creating a PGLiteSocketHandler
*/
interface PGLiteSocketHandlerOptions {
/** The PGlite database instance */
db: PGlite;
/** Whether to close the socket when detached (default: false) */
closeOnDetach?: boolean;
/** Print the incoming and outgoing data to the console in hex and ascii */
inspect?: boolean;
/** Enable debug logging of method calls */
debug?: boolean;
}
/**
* Low-level handler for a single socket connection to PGLite
* Handles the raw protocol communication between a socket and PGLite
*/
declare class PGLiteSocketHandler extends EventTarget {
readonly db: PGlite;
private socket;
private active;
private closeOnDetach;
private resolveLock?;
private rejectLock?;
private inspect;
private debug;
private readonly id;
private static nextHandlerId;
/**
* Create a new PGLiteSocketHandler
* @param options Options for the handler
*/
constructor(options: PGLiteSocketHandlerOptions);
/**
* Get the unique ID of this handler
*/
get handlerId(): number;
/**
* Log a message if debug is enabled
* @private
*/
private log;
/**
* Attach a socket to this handler
* @param socket The socket to attach
* @returns this handler instance
* @throws Error if a socket is already attached
*/
attach(socket: Socket): Promise<PGLiteSocketHandler>;
/**
* Detach the current socket from this handler
* @param close Whether to close the socket when detaching (overrides constructor option)
* @returns this handler instance
*/
detach(close?: boolean): PGLiteSocketHandler;
/**
* Check if a socket is currently attached
*/
get isAttached(): boolean;
/**
* Handle incoming data from the socket
*/
private handleData;
/**
* Handle errors from the socket
*/
private handleError;
/**
* Handle socket close event
*/
private handleClose;
/**
* Print data in hex and ascii to the console
*/
private inspectData;
}
/**
* Options for creating a PGLiteSocketServer
*/
interface PGLiteSocketServerOptions {
/** The PGlite database instance */
db: PGlite;
/** The port to listen on (default: 5432) */
port?: number;
/** The host to bind to (default: 127.0.0.1) */
host?: string;
/** Unix socket path to bind to (default: undefined). If specified, takes precedence over host:port */
path?: string;
/** Print the incoming and outgoing data to the console in hex and ascii */
inspect?: boolean;
/** Connection queue timeout in milliseconds (default: 10000) */
connectionQueueTimeout?: number;
/** Enable debug logging of method calls */
debug?: boolean;
}
/**
* High-level server that manages socket connections to PGLite
* Creates and manages a TCP server and handles client connections
*/
declare class PGLiteSocketServer extends EventTarget {
readonly db: PGlite;
private server;
private port?;
private host?;
private path?;
private active;
private inspect;
private debug;
private connectionQueueTimeout;
private activeHandler;
private connectionQueue;
private handlerCount;
/**
* Create a new PGLiteSocketServer
* @param options Options for the server
*/
constructor(options: PGLiteSocketServerOptions);
/**
* Log a message if debug is enabled
* @private
*/
private log;
/**
* Start the socket server
* @returns Promise that resolves when the server is listening
*/
start(): Promise<void>;
getServerConn(): string;
/**
* Stop the socket server
* @returns Promise that resolves when the server is closed
*/
stop(): Promise<void>;
/**
* Get the active handler ID, or null if no active handler
*/
private get activeHandlerId();
/**
* Handle a new client connection
*/
private handleConnection;
/**
* Add a connection to the queue
*/
private enqueueConnection;
/**
* Process the next connection in the queue
*/
private processNextInQueue;
/**
* Attach a socket to a new handler
*/
private attachSocketToNewHandler;
}
export { CONNECTION_QUEUE_TIMEOUT, PGLiteSocketHandler, type PGLiteSocketHandlerOptions, PGLiteSocketServer, type PGLiteSocketServerOptions };

View File

@@ -0,0 +1,2 @@
import{a,b,c}from"./chunk-F6KLIXM7.js";export{a as CONNECTION_QUEUE_TIMEOUT,b as PGLiteSocketHandler,c as PGLiteSocketServer};
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
#!/usr/bin/env node

View File

@@ -0,0 +1 @@
#!/usr/bin/env node

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env node
import{c as d}from"../chunk-F6KLIXM7.js";import{PGlite as h}from"@electric-sql/pglite";import{parseArgs as u}from"node:util";import{spawn as p}from"node:child_process";var r=u({options:{db:{type:"string",short:"d",default:"memory://",help:"Database path (relative or absolute). Use memory:// for in-memory database."},port:{type:"string",short:"p",default:"5432",help:"Port to listen on"},host:{type:"string",short:"h",default:"127.0.0.1",help:"Host to bind to"},path:{type:"string",short:"u",default:void 0,help:"unix socket to bind to. Takes precedence over host:port"},debug:{type:"string",short:"v",default:"0",help:"Debug level (0-5)"},extensions:{type:"string",short:"e",default:void 0,help:"Comma-separated list of extensions to load (e.g., vector,pgcrypto)"},run:{type:"string",short:"r",default:void 0,help:"Command to run after server starts"},"include-database-url":{type:"boolean",default:!1,help:"Include DATABASE_URL in the environment of the subprocess"},"shutdown-timeout":{type:"string",default:"5000",help:"Timeout in milliseconds for graceful subprocess shutdown (default: 5000)"},help:{type:"boolean",short:"?",default:!1,help:"Show help"}}}),g=`PGlite Socket Server
Usage: pglite-server [options]
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 (default: undefined). Takes precedence over host:port
-v, --debug=LEVEL Debug level 0-5 (default: 0)
-e, --extensions=LIST Comma-separated list of extensions to load
Formats: vector, pgcrypto (built-in/contrib)
@org/package/path:exportedName (npm package)
-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)
`,l=class{constructor(e){this.db=null;this.server=null;this.subprocessManager=null;this.config=e}static parseConfig(){let e=r.values.extensions;return{dbPath:r.values.db,port:parseInt(r.values.port,10),host:r.values.host,path:r.values.path,debugLevel:parseInt(r.values.debug,10),extensionNames:e?e.split(",").map(o=>o.trim()):void 0,runCommand:r.values.run,includeDatabaseUrl:r.values["include-database-url"],shutdownTimeout:parseInt(r.values["shutdown-timeout"],10)}}createDatabaseUrl(){let{host:e,port:o,path:t}=this.config;if(t){let s=t.endsWith("/.s.PGSQL.5432")?t.slice(0,-13):t;return`postgresql://postgres:postgres@/postgres?host=${encodeURIComponent(s)}`}else return`postgresql://postgres:postgres@${e}:${o}/postgres`}async importExtensions(){if(!this.config.extensionNames?.length)return;let e={},o=["vector","live","pg_hashids","pg_ivm","pg_uuidv7","pgtap"];for(let t of this.config.extensionNames){let s=null;try{if(t.includes(":")){let[i,n]=t.split(":");if(!i||!n)throw new Error(`Invalid extension format '${t}'. Expected: package/path:exportedName`);s=(await import(i))[n],s&&(e[n]=s,console.log(`Imported extension '${n}' from '${i}'`))}else if(o.includes(t))s=(await import(`@electric-sql/pglite/${t}`))[t],s&&(e[t]=s,console.log(`Imported extension: ${t}`));else{try{s=(await import(`@electric-sql/pglite/contrib/${t}`))[t]}catch{s=(await import(`@electric-sql/pglite-${t}`))[t]}s&&(e[t]=s,console.log(`Imported extension: ${t}`))}}catch(i){throw console.error(`Failed to import extension '${t}':`,i),new Error(`Failed to import extension '${t}'`)}}return Object.keys(e).length>0?e:void 0}async initializeDatabase(){console.log(`Initializing PGLite with database: ${this.config.dbPath}`),console.log(`Debug level: ${this.config.debugLevel}`);let e=await this.importExtensions();this.db=new h(this.config.dbPath,{debug:this.config.debugLevel,extensions:e}),await this.db.waitReady,console.log("PGlite database initialized")}setupServerEventHandlers(){if(!this.server||!this.subprocessManager)throw new Error("Server or subprocess manager not initialized");this.server.addEventListener("listening",e=>{let o=e.detail;if(console.log(`PGLiteSocketServer listening on ${JSON.stringify(o)}`),this.config.runCommand&&this.subprocessManager){let t=this.createDatabaseUrl();this.subprocessManager.spawn(this.config.runCommand,t,this.config.includeDatabaseUrl)}}),this.server.addEventListener("connection",e=>{let{clientAddress:o,clientPort:t}=e.detail;console.log(`Client connected from ${o}:${t}`)}),this.server.addEventListener("error",e=>{let o=e.detail;console.error("Socket server error:",o)})}setupSignalHandlers(){process.on("SIGINT",()=>this.shutdown()),process.on("SIGTERM",()=>this.shutdown())}async start(){try{if(await this.initializeDatabase(),!this.db)throw new Error("Database initialization failed");this.server=new d({db:this.db,port:this.config.port,host:this.config.host,path:this.config.path,inspect:this.config.debugLevel>0}),this.subprocessManager=new c(e=>{this.shutdown(e)}),this.setupServerEventHandlers(),this.setupSignalHandlers(),await this.server.start()}catch(e){throw console.error("Failed to start PGLiteSocketServer:",e),e}}async shutdown(e=0){console.log(`
Shutting down PGLiteSocketServer...`),this.subprocessManager&&this.subprocessManager.terminate(this.config.shutdownTimeout),this.server&&await this.server.stop(),this.db&&await this.db.close(),console.log("Server stopped"),process.exit(e)}},c=class{constructor(e){this.childProcess=null;this.onExit=e}get process(){return this.childProcess}spawn(e,o,t){console.log(`Running command: ${e}`);let s={...process.env};t&&(s.DATABASE_URL=o,console.log(`Setting DATABASE_URL=${o}`));let i=e.trim().split(/\s+/);this.childProcess=p(i[0],i.slice(1),{env:s,stdio:"inherit"}),this.childProcess.on("error",n=>{console.error("Error running command:",n),console.log("Subprocess failed to start, shutting down..."),this.onExit(1)}),this.childProcess.on("close",n=>{console.log(`Command exited with code ${n}`),this.childProcess=null,n!==null&&n!==0&&(console.log(`Child process failed with exit code ${n}, shutting down...`),this.onExit(n))})}terminate(e){this.childProcess&&(console.log("Terminating child process..."),this.childProcess.kill("SIGTERM"),setTimeout(()=>{this.childProcess&&!this.childProcess.killed&&(console.log("Force killing child process..."),this.childProcess.kill("SIGKILL"))},e))}};async function m(){r.values.help&&(console.log(g),process.exit(0));try{let a=l.parseConfig();await new l(a).start()}catch(a){console.error("Unhandled error:",a),process.exit(1)}}m();
//# sourceMappingURL=server.js.map

File diff suppressed because one or more lines are too long