{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/transport/http.ts","../src/rpc/rpc-promise.ts","../src/transport/rpc.ts","../src/transport/cdc-ws.ts","../src/transport/cdc-sse.ts","../src/middleware.ts","../src/streaming.ts","../src/subscription.ts","../src/client.ts","../src/auth.ts","../src/connection.ts","../src/extensions.ts","../src/pool.ts"],"sourcesContent":["/**\n * postgres.do - PostgreSQL for Cloudflare Workers\n *\n * SQL tagged template client with Drizzle ORM compatibility\n *\n * @example\n * ```typescript\n * import postgres from 'postgres.do';\n *\n * const sql = postgres('postgres://db.postgres.do/mydb');\n *\n * // Tagged template queries\n * const users = await sql`SELECT * FROM users WHERE id = ${userId}`;\n *\n * // Works with Drizzle ORM\n * import { drizzle } from 'drizzle-orm/postgres-js';\n * const db = drizzle(sql);\n * ```\n */\n\n// Main client exports\nexport { postgres, createClient } from './client'\nexport { default } from './client'\n\n// Authentication integration with oauth.do\nexport {\n  createAuthenticatedClient,\n  createClientFromRequest,\n  withAuth,\n  extractUserId,\n  validateToken,\n  createUserScopedClient,\n  extractBearerToken,\n  generateDatabaseId,\n  type AuthenticatedClientOptions,\n  type AuthenticatedUser,\n  type AuthenticatedContext,\n  type TokenValidationResult,\n} from './auth'\n\n// Connection utilities\nexport { parseConnectionUrl, type ConnectionInfo } from './connection'\n\n// Transport implementations\nexport { createHttpTransport, HttpTransport } from './transport/http'\n// RpcTransport is the capnweb-based WebSocket transport (replaces legacy WsTransport)\nexport { createRpcTransport, RpcTransport, type RpcTransportConfig } from './transport/rpc'\n// Backward-compatible aliases for legacy code using WsTransport\nexport { RpcTransport as WsTransport, createRpcTransport as createWsTransport } from './transport/rpc'\n\n// CDC (Change Data Capture) Transports\nexport { CDCWsTransport, createCdcWsTransport } from './transport/cdc-ws'\nexport { CDCSseTransport, createCdcSseTransport } from './transport/cdc-sse'\n\n// CDC (Change Data Capture) Client Subscription\nexport {\n  CDCSubscription,\n  validateTableName,\n  generateSubscriptionId,\n  type Subscription,\n  type SubscribeOptions,\n  type TypedSubscribeOptions,\n} from './subscription'\n\n// Types\nexport type {\n  // Core types\n  Sql,\n  TransactionSql,\n  ReservedSql,\n  PendingQuery,\n  Row,\n  QueryResult,\n  FieldInfo,\n  TypeParser,\n\n  // Configuration\n  PostgresConfig,\n  TransactionOptions,\n  IsolationLevel,\n\n  // Transport types\n  Transport,\n  HttpTransportConfig,\n  WsTransportConfig,\n\n  // CDC (Change Data Capture) types\n  CDCOperation,\n  CDCChangeEvent,\n  CDCTransport,\n  CDCSubscriptionOptions,\n  CDCWsTransportConfig,\n  CDCSseTransportConfig,\n\n  // CDC Client types (high-level API)\n  CDCClientSubscription,\n  CDCClientSubscribeOptions,\n  CDCClientSubscriptionInfo,\n} from './types'\n\n// Errors\nexport {\n  PostgresError,\n  ConnectionError,\n  TimeoutError,\n  type PostgresErrorFields,\n} from './types'\n\n// Streaming API for large datasets\nexport type {\n  StreamOptions,\n  StreamResult,\n  Cursor,\n  CursorFetchResult,\n} from './types'\nexport {\n  createStreamResult,\n  createCursor,\n  buildParameterizedSql as buildStreamSql,\n} from './streaming'\n\n// Lazy Extension Loading\nexport {\n  LazyExtensionLoader,\n  createLazyExtensionLoader,\n  detectExtensions,\n  EXTENSION_REGISTRY,\n  type ExtensionName,\n  type ExtensionMetadata,\n  type QueryExecutor,\n  type ExtensionLoadResult,\n  type ExecuteWithAutoLoadResult,\n  type ExtensionLoaderStats,\n  type LazyExtensionLoaderOptions,\n} from './extensions'\n\n// Connection pool\nexport {\n  PGlitePool,\n  PoolError,\n  type PGLiteLike,\n  type PoolClient,\n  type PoolQueryResult,\n  type PGlitePoolConfig,\n  type PoolStats,\n  type PoolTransactionOptions,\n  type PoolIsolationLevel,\n} from './pool'\n\n// Query Middleware\nexport {\n  // Core middleware functions\n  generateQueryId,\n  executeWithMiddleware,\n  composeMiddleware,\n  // Built-in middlewares\n  loggingMiddleware,\n  metricsMiddleware,\n  rateLimitMiddleware,\n  tracingMiddleware,\n  transformMiddleware,\n  retryMiddleware,\n  // Types\n  type QueryRequest,\n  type QueryResponse,\n  type QueryMiddleware,\n  type NextFunction,\n  type LoggingMiddlewareOptions,\n  type MetricsMiddlewareOptions,\n  type QueryMetric,\n  type RateLimitMiddlewareOptions,\n  type TracingMiddlewareOptions,\n  type QueryTrace,\n  type TransformMiddlewareOptions,\n  type RetryMiddlewareOptions,\n} from './middleware'\n","/**\n * PostgreSQL client types for postgres.do\n * Compatible with Drizzle ORM and direct usage\n */\n\nimport {\n  PostgresError as SharedPostgresError,\n  ConnectionError as SharedConnectionError,\n  ConnectionTimeoutError as SharedConnectionTimeoutError,\n  type ErrorContext,\n} from '@dotdo/postgres-shared/errors'\n\n/** A single row returned from a query */\nexport type Row = Record<string, unknown>\n\n/** Result of a query execution */\nexport interface QueryResult<T extends Row = Row> {\n  /** Rows returned by the query */\n  rows: T[]\n  /** Number of rows affected (for INSERT/UPDATE/DELETE) */\n  rowCount: number\n  /** Column metadata */\n  fields: FieldInfo[]\n  /** Command type (SELECT, INSERT, etc.) */\n  command: string\n}\n\n/** Column/field metadata */\nexport interface FieldInfo {\n  /** Column name */\n  name: string\n  /** PostgreSQL OID for the column type */\n  dataTypeID: number\n  /** Table OID (0 if not from a table) */\n  tableID: number\n  /** Column position in table */\n  columnID: number\n  /** Data type size in bytes (-1 for variable) */\n  dataTypeSize: number\n  /** Type modifier */\n  dataTypeModifier: number\n  /** Format code (0 = text, 1 = binary) */\n  format: number\n}\n\n/** Type parser function */\nexport type TypeParser = (value: string) => unknown\n\n/** Configuration options for the postgres client */\nexport interface PostgresConfig {\n  /** Database connection URL (postgres://...) */\n  url?: string\n\n  /** API key for postgres.do authentication */\n  apiKey?: string\n\n  /** Transport type: 'http' (default) or 'ws' */\n  transport?: 'http' | 'ws'\n\n  /** Custom type parsers by OID */\n  parsers?: Record<number, TypeParser>\n\n  /** Connection timeout in milliseconds */\n  connectTimeout?: number\n\n  /** Query timeout in milliseconds */\n  queryTimeout?: number\n\n  /** Maximum number of retry attempts */\n  maxRetries?: number\n\n  /** Whether to use SSL/TLS */\n  ssl?: boolean | 'require' | 'prefer' | 'allow' | 'disable'\n\n  /** Custom fetch implementation (for Cloudflare Workers) */\n  fetch?: typeof fetch\n\n  /** Custom WebSocket implementation */\n  WebSocket?: typeof WebSocket\n\n  /** Enable debug logging */\n  debug?: boolean\n\n  /** Transform column names (e.g., snake_case to camelCase) */\n  transform?: {\n    column?: (name: string) => string\n    value?: (value: unknown, column: string) => unknown\n  }\n\n  /**\n   * Default transaction retry configuration.\n   * These settings are used as defaults for all transactions initiated with begin().\n   * Transaction-level options can override these defaults.\n   */\n  transactionRetry?: {\n    /** Automatically retry on serialization failure (error code 40001) */\n    retryOnSerializationFailure?: boolean\n    /** Automatically retry on deadlock (error code 40P01) */\n    retryOnDeadlock?: boolean\n    /** Maximum retry attempts (default: 3) */\n    maxRetries?: number\n    /** Base delay in milliseconds for exponential backoff (default: 10) */\n    backoffMs?: number\n  }\n}\n\n/** Pending query that can be executed */\nexport interface PendingQuery<T extends Row = Row> extends Promise<T[]> {\n  /** Execute the query and return rows */\n  execute(): Promise<T[]>\n\n  /** Get the parameterized SQL string */\n  toString(): string\n\n  /** Get query values/parameters */\n  values: unknown[]\n\n  /** Get the SQL template string */\n  strings: TemplateStringsArray\n}\n\n/** Transaction isolation levels */\nexport type IsolationLevel =\n  | 'read uncommitted'\n  | 'read committed'\n  | 'repeatable read'\n  | 'serializable'\n\n/** Lock mode types */\nexport type LockMode =\n  | 'access share'\n  | 'row share'\n  | 'row exclusive'\n  | 'share update exclusive'\n  | 'share'\n  | 'share row exclusive'\n  | 'exclusive'\n  | 'access exclusive'\n\n/** Transaction options */\nexport interface TransactionOptions {\n  /** Isolation level */\n  isolationLevel?: IsolationLevel\n  /** Read only transaction */\n  readOnly?: boolean\n  /** Deferrable (only with serializable + read only) */\n  deferrable?: boolean\n  /** Named transaction (for debugging/logging) */\n  name?: string\n  /**\n   * Transaction timeout in milliseconds.\n   * This is the total timeout across all retry attempts.\n   * When retries are enabled, the timeout counts from the start of the first attempt.\n   */\n  timeout?: number\n  /**\n   * Per-retry timeout in milliseconds.\n   * When set, each retry attempt gets a fresh timeout of this duration.\n   * This is useful when you want to allow each attempt to take up to N ms,\n   * but the total time can exceed that due to retries.\n   * If both `timeout` and `perRetryTimeout` are set, `timeout` takes precedence\n   * (the total timeout will be enforced).\n   */\n  perRetryTimeout?: number\n  /** Lock mode for explicit table locking */\n  lockMode?: LockMode\n  /** Automatically retry on serialization failure (error code 40001) */\n  retryOnSerializationFailure?: boolean\n  /** Automatically retry on deadlock (error code 40P01) */\n  retryOnDeadlock?: boolean\n  /** Maximum retry attempts (default: 3) */\n  maxRetries?: number\n  /** Base delay in milliseconds for exponential backoff (default: 10) */\n  backoffMs?: number\n  /** Callback called before each retry attempt */\n  onRetry?: (attempt: number, error: Error) => void | Promise<void>\n}\n\n/**\n * Options for streaming queries\n */\nexport interface StreamOptions {\n  /** Batch size for fetching rows (default: 100) */\n  batchSize?: number\n  /** Custom cursor name (auto-generated if not provided) */\n  cursorName?: string\n  /** Transaction isolation level for the cursor */\n  isolationLevel?: IsolationLevel\n  /** Whether the cursor should be read-only (default: true) */\n  readOnly?: boolean\n}\n\n/**\n * Result of a cursor fetch operation\n */\nexport interface CursorFetchResult<T extends Row = Row> {\n  /** Rows fetched in this batch */\n  rows: T[]\n  /** Whether there are more rows to fetch */\n  hasMore: boolean\n  /** Total number of rows fetched so far */\n  totalFetched: number\n}\n\n/**\n * Cursor interface for manual control over streaming\n */\nexport interface Cursor<T extends Row = Row> extends AsyncIterable<T> {\n  /** Whether the cursor is still open */\n  readonly isOpen: boolean\n  /** Total number of rows fetched so far */\n  readonly totalFetched: number\n  /** Column metadata from the query */\n  readonly fields: FieldInfo[]\n\n  /**\n   * Fetch the next batch of rows\n   * @param count - Number of rows to fetch (default: batch size)\n   * @returns Array of rows (empty array if no more rows)\n   */\n  fetch(count?: number): Promise<T[]>\n\n  /**\n   * Fetch the next batch of rows with additional metadata\n   * @param count - Number of rows to fetch (default: batch size)\n   * @returns Result object with rows, hasMore flag, and total fetched count\n   */\n  fetchWithInfo(count?: number): Promise<CursorFetchResult<T>>\n\n  /**\n   * Close the cursor and release resources\n   * Always call this when done, or use for-await-of which closes automatically\n   */\n  close(): Promise<void>\n}\n\n/**\n * Stream result interface for fluent streaming API\n */\nexport interface StreamResult<T extends Row = Row> extends AsyncIterable<T> {\n  /** The SQL query being streamed */\n  readonly sql: string\n  /** The query parameters */\n  readonly params: unknown[]\n\n  /**\n   * Stream rows in batches\n   * @param size - Number of rows per batch\n   * @returns AsyncIterable of row arrays\n   * @example\n   * for await (const batch of sql.stream`SELECT * FROM users`.batch(1000)) {\n   *   processBatch(batch)\n   * }\n   */\n  batch(size: number): AsyncIterable<T[]>\n\n  /**\n   * Get a cursor for manual control\n   * @returns A cursor that can be used to fetch rows manually\n   * @example\n   * const cursor = await sql.stream`SELECT * FROM users`.cursor()\n   * while (const rows = await cursor.fetch(100)) {\n   *   process(rows)\n   * }\n   * await cursor.close()\n   */\n  cursor(): Promise<Cursor<T>>\n}\n\n/**\n * Query middleware function signature (forward declaration for types)\n * Full implementation is in middleware.ts\n */\nexport type QueryMiddlewareFn<T extends Row = Row> = (\n  request: { sql: string; params: unknown[]; timestamp: number; queryId: string; context?: Record<string, unknown> },\n  next: () => Promise<{ result: QueryResult<T>; durationMs: number; success: boolean; error?: Error; metadata?: Record<string, unknown> }>\n) => Promise<{ result: QueryResult<T>; durationMs: number; success: boolean; error?: Error; metadata?: Record<string, unknown> }>\n\n/**\n * Main SQL client interface\n * Compatible with Drizzle ORM integration\n */\nexport interface Sql {\n  /**\n   * Execute a SQL query using tagged template literal\n   * @example\n   * const users = await sql`SELECT * FROM users WHERE id = ${userId}`\n   */\n  <T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): PendingQuery<T>\n\n  /**\n   * Execute raw SQL (use with caution - no parameterization)\n   * This is used by Drizzle ORM for generated queries\n   * @param query - Raw SQL query string\n   * @param params - Optional query parameters\n   */\n  unsafe<T extends Row = Row>(\n    query: string,\n    params?: unknown[]\n  ): Promise<T[]>\n\n  /**\n   * Begin a transaction\n   * Compatible with Drizzle ORM transaction interface\n   * @param fn - Transaction callback function\n   * @param options - Transaction options\n   */\n  begin<T>(\n    fn: (sql: TransactionSql) => Promise<T>,\n    options?: TransactionOptions\n  ): Promise<T>\n\n  /**\n   * Create a savepoint within a transaction\n   * For nested transaction support\n   * @param fn - Savepoint callback function\n   */\n  savepoint<T>(\n    fn: (sql: TransactionSql) => Promise<T>\n  ): Promise<T>\n\n  /**\n   * End the connection/session\n   */\n  end(): Promise<void>\n\n  /**\n   * Stream large result sets using PostgreSQL cursors\n   * Keeps memory usage constant regardless of result size\n   * @example\n   * // Stream rows one at a time\n   * for await (const row of sql.stream`SELECT * FROM huge_table`) {\n   *   process(row)\n   * }\n   *\n   * // Stream in batches\n   * for await (const batch of sql.stream`SELECT * FROM huge_table`.batch(1000)) {\n   *   processBatch(batch)\n   * }\n   *\n   * // Manual cursor control\n   * const cursor = await sql.stream`SELECT * FROM huge_table`.cursor()\n   * while (const rows = await cursor.fetch(100)) {\n   *   process(rows)\n   * }\n   * await cursor.close()\n   */\n  stream<T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): StreamResult<T>\n\n  /**\n   * Add a query middleware to the chain\n   * Middlewares are executed in the order they are added\n   * @param middleware - The middleware function to add\n   * @returns The same Sql instance for chaining\n   * @example\n   * const sql = postgres()\n   *   .use(loggingMiddleware({ level: 'info' }))\n   *   .use(metricsMiddleware({ onMetric: console.log }))\n   */\n  use(middleware: QueryMiddlewareFn): this\n\n  /**\n   * Client configuration options\n   * Includes type parsers and serializers for Drizzle compatibility\n   */\n  options: {\n    parsers: Record<number, TypeParser>\n    serializers: Record<number, (value: unknown) => string>\n    [key: string]: unknown\n  }\n\n  /**\n   * Reserve a connection from the pool\n   * Returns a client with exclusive connection\n   */\n  reserve(): Promise<ReservedSql>\n\n  /**\n   * Commit a prepared transaction (two-phase commit)\n   * @param transactionId - The ID returned from prepare()\n   */\n  commitPrepared(transactionId: string): Promise<void>\n\n  /**\n   * Rollback a prepared transaction (two-phase commit)\n   * @param transactionId - The ID returned from prepare()\n   */\n  rollbackPrepared(transactionId: string): Promise<void>\n\n  /**\n   * Subscribe to changes on a table\n   * @param table - Table name (optionally with schema: \"schema.table\")\n   * @param options - Subscription options\n   * @returns A subscription that can be iterated over or used with callbacks\n   * @example\n   * // Using async iteration\n   * const sub = await sql.subscribe('users')\n   * for await (const event of sub) {\n   *   console.log(event.operation, event.newRow)\n   * }\n   *\n   * // Using callbacks\n   * const sub = await sql.subscribe('users', {\n   *   onInsert: (row) => console.log('New user:', row),\n   *   onUpdate: (newRow, oldRow) => console.log('Updated:', newRow),\n   *   onDelete: (oldRow) => console.log('Deleted:', oldRow)\n   * })\n   */\n  subscribe<T extends Row = Row>(\n    table: string,\n    options?: CDCClientSubscribeOptions<T>\n  ): Promise<CDCClientSubscription<T>>\n\n  /**\n   * Unsubscribe from a subscription by ID\n   * @param subscriptionId - The subscription ID to unsubscribe from\n   */\n  unsubscribe(subscriptionId: string): Promise<void>\n\n  /**\n   * Get all active subscriptions\n   * @returns Array of active subscriptions\n   */\n  subscriptions(): CDCClientSubscriptionInfo[]\n}\n\n/** Transaction-specific SQL interface */\nexport interface TransactionSql extends Omit<Sql, 'begin' | 'end' | 'reserve' | 'commitPrepared' | 'rollbackPrepared'> {\n  /**\n   * Create a savepoint within the transaction\n   */\n  savepoint<T>(\n    fn: (sql: TransactionSql) => Promise<T>\n  ): Promise<T>\n\n  /**\n   * Acquire an exclusive advisory lock that is released when the transaction ends (blocking).\n   * @param lockId - Lock identifier (number or bigint for single-key)\n   * @example await tx.advisoryLock(12345)\n   */\n  advisoryLock(lockId: number | bigint): Promise<void>\n  /**\n   * Acquire an exclusive advisory lock with namespace (blocking).\n   * @param classId - Lock class/namespace identifier (int4)\n   * @param objId - Object identifier within the namespace (int4)\n   * @example await tx.advisoryLock(1, 42) // namespace 1, object 42\n   */\n  advisoryLock(classId: number, objId: number): Promise<void>\n\n  /**\n   * Try to acquire an exclusive advisory lock without blocking.\n   * @param lockId - Lock identifier (number or bigint for single-key)\n   * @returns true if lock was acquired, false otherwise\n   * @example const acquired = await tx.tryAdvisoryLock(12345)\n   */\n  tryAdvisoryLock(lockId: number | bigint): Promise<boolean>\n  /**\n   * Try to acquire an exclusive advisory lock with namespace without blocking.\n   * @param classId - Lock class/namespace identifier (int4)\n   * @param objId - Object identifier within the namespace (int4)\n   * @returns true if lock was acquired, false otherwise\n   * @example const acquired = await tx.tryAdvisoryLock(1, 42)\n   */\n  tryAdvisoryLock(classId: number, objId: number): Promise<boolean>\n\n  /**\n   * Acquire a shared advisory lock that is released when the transaction ends (blocking).\n   * Multiple sessions can hold a shared lock simultaneously; blocks only if exclusive lock is held.\n   * @param lockId - Lock identifier (number or bigint for single-key)\n   * @example await tx.advisoryLockShared(12345)\n   */\n  advisoryLockShared(lockId: number | bigint): Promise<void>\n  /**\n   * Acquire a shared advisory lock with namespace (blocking).\n   * @param classId - Lock class/namespace identifier (int4)\n   * @param objId - Object identifier within the namespace (int4)\n   * @example await tx.advisoryLockShared(1, 42)\n   */\n  advisoryLockShared(classId: number, objId: number): Promise<void>\n\n  /**\n   * Try to acquire a shared advisory lock without blocking.\n   * @param lockId - Lock identifier (number or bigint for single-key)\n   * @returns true if lock was acquired, false if exclusive lock is held\n   * @example const acquired = await tx.tryAdvisoryLockShared(12345)\n   */\n  tryAdvisoryLockShared(lockId: number | bigint): Promise<boolean>\n  /**\n   * Try to acquire a shared advisory lock with namespace without blocking.\n   * @param classId - Lock class/namespace identifier (int4)\n   * @param objId - Object identifier within the namespace (int4)\n   * @returns true if lock was acquired, false if exclusive lock is held\n   * @example const acquired = await tx.tryAdvisoryLockShared(1, 42)\n   */\n  tryAdvisoryLockShared(classId: number, objId: number): Promise<boolean>\n\n  /**\n   * Prepare transaction for two-phase commit\n   * After calling this, the transaction must be committed with commitPrepared()\n   * @param transactionId - Unique identifier for the prepared transaction\n   * @returns The transaction ID\n   */\n  prepare(transactionId: string): Promise<string>\n\n  /**\n   * Register a callback to run after transaction commits\n   * @param fn - Callback function\n   */\n  onCommit(fn: () => void | Promise<void>): void\n\n  /**\n   * Register a callback to run after transaction rolls back\n   * @param fn - Callback function\n   */\n  onRollback(fn: () => void | Promise<void>): void\n\n  /**\n   * Current transaction ID (xid)\n   * Lazily fetched from the database\n   */\n  readonly txid: string | undefined\n\n  /**\n   * Transaction name (if provided in options)\n   */\n  readonly name: string | undefined\n\n  /**\n   * Current retry attempt number (0 for first attempt, 1 for first retry, etc.)\n   * Only set when retryOnSerializationFailure or retryOnDeadlock is enabled.\n   */\n  readonly retryCount: number\n}\n\n/** Reserved connection SQL interface */\nexport interface ReservedSql extends Sql {\n  /**\n   * Release the reserved connection back to the pool\n   */\n  release(): Promise<void>\n}\n\n/** Transport interface for sending queries */\nexport interface Transport {\n  /** Send a query and receive results */\n  query<T extends Row = Row>(\n    sql: string,\n    params?: unknown[]\n  ): Promise<QueryResult<T>>\n\n  /** Execute multiple queries in a transaction */\n  transaction<T>(\n    queries: Array<{ sql: string; params?: unknown[] }>,\n    options?: TransactionOptions\n  ): Promise<T>\n\n  /** Close the transport connection */\n  close(): Promise<void>\n\n  /** Check if transport is connected */\n  isConnected(): boolean\n}\n\n/** HTTP transport configuration */\nexport interface HttpTransportConfig {\n  /** Base URL for the postgres.do API */\n  baseUrl: string\n  /** API key for authentication */\n  apiKey?: string | undefined\n  /** Custom fetch implementation */\n  fetch?: typeof fetch | undefined\n  /** Request timeout in milliseconds */\n  timeout?: number | undefined\n  /** Custom headers */\n  headers?: Record<string, string> | undefined\n}\n\n/** WebSocket transport configuration */\nexport interface WsTransportConfig {\n  /** WebSocket URL for postgres.do */\n  url: string\n  /** API key for authentication */\n  apiKey?: string | undefined\n  /** Custom WebSocket implementation */\n  WebSocket?: typeof WebSocket | undefined\n  /** Connection timeout in milliseconds */\n  connectTimeout?: number | undefined\n  /** Ping interval in milliseconds */\n  pingInterval?: number | undefined\n}\n\n// =============================================================================\n// CDC (Change Data Capture) Types\n// =============================================================================\n\n/**\n * CDC operation types for PostgreSQL change notifications\n */\nexport type CDCOperation = 'INSERT' | 'UPDATE' | 'DELETE' | 'TRUNCATE'\n\n/**\n * CDC change event representing a single database change\n */\nexport interface CDCChangeEvent {\n  /** Unique event ID (typically LSN-based) */\n  id: string\n  /** PostgreSQL Log Sequence Number for this change */\n  lsn: string\n  /** Type of operation that caused this change */\n  operation: CDCOperation\n  /** Table name where the change occurred */\n  table: string\n  /** Schema name */\n  schema: string\n  /** Timestamp when the change occurred */\n  timestamp: Date\n  /** New row data (for INSERT and UPDATE) */\n  newRow?: Row | undefined\n  /** Old row data (for UPDATE and DELETE) */\n  oldRow?: Row | undefined\n  /** Columns that were changed (for UPDATE) */\n  changedColumns?: string[] | undefined\n  /** Transaction ID */\n  xid: number\n  /** Whether this is the last change in the transaction */\n  isLastInTransaction: boolean\n}\n\n/**\n * Options for CDC subscriptions\n */\nexport interface CDCSubscriptionOptions {\n  /** Event types to subscribe to (default: all) */\n  events?: CDCOperation[] | undefined\n  /** SQL filter expression for row-level filtering */\n  filter?: string | undefined\n  /** Resume from this LSN (for exactly-once delivery) */\n  resumeFrom?: string | undefined\n  /** Include old row data for UPDATE/DELETE events */\n  includeOldRow?: boolean | undefined\n  /** Track which columns changed for UPDATE events */\n  trackChangedColumns?: boolean | undefined\n  /** Batch size for event delivery */\n  batchSize?: number | undefined\n  /** Heartbeat interval in milliseconds */\n  heartbeatInterval?: number | undefined\n}\n\n/**\n * CDC Transport interface for streaming database changes\n */\nexport interface CDCTransport {\n  /** Connect to the CDC stream */\n  connect(): Promise<void>\n  /** Disconnect from the CDC stream */\n  disconnect(): Promise<void>\n  /** Check if connected */\n  isConnected(): boolean\n  /** Get the last event ID received */\n  getLastEventId(): string | null\n  /** Subscribe to a table */\n  subscribe(\n    subscriptionId: string,\n    table: string,\n    schema: string,\n    options: CDCSubscriptionOptions\n  ): Promise<void>\n  /** Unsubscribe from a subscription */\n  unsubscribe(subscriptionId: string): Promise<void>\n  /** Set the event handler */\n  onEvent(handler: (subscriptionId: string, event: CDCChangeEvent) => void): void\n  /** Set the error handler */\n  onError(handler: (subscriptionId: string, error: Error) => void): void\n  /** Set the reconnect handler */\n  onReconnect(handler: (attempt: number, lastLsn: string | undefined) => void): void\n  /** Set the close handler */\n  onClose(handler: () => void): void\n}\n\n/**\n * CDC WebSocket transport configuration\n */\nexport interface CDCWsTransportConfig {\n  /** WebSocket URL for the CDC endpoint */\n  url: string\n  /** API key for authentication */\n  apiKey?: string | undefined\n  /** Custom WebSocket implementation */\n  WebSocket?: typeof WebSocket | undefined\n  /** Connection timeout in milliseconds */\n  connectTimeout?: number | undefined\n  /** Ping interval for keepalive in milliseconds */\n  pingInterval?: number | undefined\n}\n\n/**\n * CDC SSE (Server-Sent Events) transport configuration\n */\nexport interface CDCSseTransportConfig {\n  /** URL for the CDC SSE endpoint */\n  url: string\n  /** API key for authentication */\n  apiKey?: string\n  /** Resume from this event ID (Last-Event-ID) */\n  resumeFrom?: string\n  /** Reconnection delay in milliseconds */\n  retryMs?: number\n  /** Custom fetch implementation */\n  fetch?: typeof fetch\n  /** Custom headers */\n  headers?: Record<string, string>\n}\n\n/** PostgreSQL error fields specific to postgres.do */\nexport interface PostgresErrorFields {\n  /** PostgreSQL error code (e.g., '23505' for unique violation) */\n  code?: string | undefined\n  /** Error severity */\n  severity?: string | undefined\n  /** Detailed error message */\n  detail?: string | undefined\n  /** Hint for fixing the error */\n  hint?: string | undefined\n  /** Position in query where error occurred */\n  position?: number | undefined\n  /** Schema name if relevant */\n  schema?: string | undefined\n  /** Table name if relevant */\n  table?: string | undefined\n  /** Column name if relevant */\n  column?: string | undefined\n  /** Constraint name if relevant */\n  constraint?: string | undefined\n}\n\n/**\n * Error thrown by postgres.do client.\n * Extends the shared PostgresError with postgres.do-specific properties.\n */\nexport class PostgresError extends SharedPostgresError {\n  /** Error severity */\n  readonly severity: string\n  /** Detailed error message */\n  readonly detail: string | undefined\n  /** Hint for fixing the error */\n  readonly hint: string | undefined\n  /** Position in query where error occurred */\n  readonly position: number | undefined\n  /** PostgreSQL error code (e.g., '23505' for unique violation) */\n  readonly pgCode: string\n\n  constructor(message: string, fields: PostgresErrorFields = {}) {\n    // Build context object only with defined values to satisfy exactOptionalPropertyTypes\n    const context: ErrorContext = { pgCode: fields.code ?? 'UNKNOWN' }\n    if (fields.schema !== undefined) context.schema = fields.schema\n    if (fields.table !== undefined) context.table = fields.table\n    if (fields.column !== undefined) context.column = fields.column\n    if (fields.constraint !== undefined) context.constraint = fields.constraint\n\n    super(message, {\n      code: 'QUERY_ERROR',\n      context,\n    })\n    // Override name property\n    Object.defineProperty(this, 'name', { value: 'PostgresError', writable: true, configurable: true })\n    // Override code property to return the PostgreSQL error code instead of internal code\n    Object.defineProperty(this, 'code', { value: fields.code ?? 'UNKNOWN', writable: false, configurable: true })\n\n    this.severity = fields.severity ?? 'ERROR'\n    this.detail = fields.detail\n    this.hint = fields.hint\n    this.position = fields.position\n    this.pgCode = fields.code ?? 'UNKNOWN'\n  }\n\n  /** Schema name if relevant */\n  get schema(): string | undefined {\n    return this.context.schema\n  }\n\n  /** Table name if relevant */\n  get table(): string | undefined {\n    return this.context.table\n  }\n\n  /** Column name if relevant */\n  get column(): string | undefined {\n    return this.context.column\n  }\n\n  /** Constraint name if relevant */\n  get constraint(): string | undefined {\n    return this.context.constraint\n  }\n}\n\n/**\n * Connection error.\n * Extends the shared ConnectionError.\n */\nexport class ConnectionError extends SharedConnectionError {\n  constructor(message: string) {\n    super(message)\n    // Override name property\n    Object.defineProperty(this, 'name', { value: 'ConnectionError', writable: true, configurable: true })\n  }\n}\n\n/**\n * Query timeout error.\n * Extends the shared ConnectionTimeoutError.\n */\nexport class TimeoutError extends SharedConnectionTimeoutError {\n  constructor(message: string = 'Query timed out') {\n    // Extract timeout from message if possible, default to 0\n    const timeoutMatch = message.match(/(\\d+)\\s*ms/)\n    const matchedMs = timeoutMatch?.[1]\n    const timeoutMs = matchedMs ? parseInt(matchedMs, 10) : 0\n    super(timeoutMs)\n    // Override name property\n    Object.defineProperty(this, 'name', { value: 'TimeoutError', writable: true, configurable: true })\n    // Override the message if a custom one was provided\n    if (message !== 'Query timed out' && message !== `Connection timed out after ${timeoutMs}ms`) {\n      Object.defineProperty(this, 'message', { value: message, writable: true, configurable: true })\n    }\n  }\n}\n\n// =============================================================================\n// CDC Client Types (High-Level API)\n// =============================================================================\n\n/**\n * Options for CDC client subscription\n */\nexport interface CDCClientSubscribeOptions<T extends Row = Row> extends CDCSubscriptionOptions {\n  /** Called for every change event */\n  onChange?: (event: CDCChangeEvent & { newRow?: T; oldRow?: T }) => void | Promise<void>\n  /** Called for INSERT events */\n  onInsert?: (row: T) => void | Promise<void>\n  /** Called for UPDATE events */\n  onUpdate?: (newRow: T, oldRow?: T) => void | Promise<void>\n  /** Called for DELETE events */\n  onDelete?: (oldRow: T) => void | Promise<void>\n  /** Called when an error occurs */\n  onError?: (error: Error) => void\n}\n\n/**\n * Client subscription interface for CDC streaming\n */\nexport interface CDCClientSubscription<T extends Row = Row> extends AsyncIterable<CDCChangeEvent & { newRow?: T; oldRow?: T }> {\n  /** Unique subscription ID */\n  readonly id: string\n  /** Table name */\n  readonly table: string\n  /** Schema name */\n  readonly schema: string\n  /** Whether the subscription is currently active */\n  readonly isActive: boolean\n  /** Last processed LSN for resumption */\n  readonly lastLsn: string | null\n\n  /** Unsubscribe and stop receiving events */\n  unsubscribe(): Promise<void>\n\n  /** Register a handler for all change events */\n  onChange(handler: (event: CDCChangeEvent & { newRow?: T; oldRow?: T }) => void | Promise<void>): this\n\n  /** Register a handler for INSERT events */\n  onInsert(handler: (row: T) => void | Promise<void>): this\n\n  /** Register a handler for UPDATE events */\n  onUpdate(handler: (newRow: T, oldRow?: T) => void | Promise<void>): this\n\n  /** Register a handler for DELETE events */\n  onDelete(handler: (oldRow: T) => void | Promise<void>): this\n}\n\n/**\n * Information about an active subscription\n */\nexport interface CDCClientSubscriptionInfo {\n  /** Unique subscription ID */\n  id: string\n  /** Table name */\n  table: string\n  /** Schema name */\n  schema: string\n  /** Whether the subscription is currently active */\n  isActive: boolean\n}\n","/**\n * HTTP Transport for postgres.do\n * Sends SQL queries over HTTP to the postgres.do API\n */\n\nimport type {\n  Transport,\n  QueryResult,\n  Row,\n  TransactionOptions,\n  HttpTransportConfig,\n  FieldInfo,\n} from '../types'\nimport { PostgresError, ConnectionError, TimeoutError } from '../types'\n\n/** Default configuration values */\nconst DEFAULTS = {\n  timeout: 30000, // 30 seconds\n  baseUrl: 'https://db.postgres.do',\n}\n\n/**\n * HTTP Transport implementation\n * Stateless transport that sends each query as an HTTP request\n */\nexport class HttpTransport implements Transport {\n  private readonly config: Required<Pick<HttpTransportConfig, 'baseUrl' | 'timeout'>> & HttpTransportConfig\n  private readonly fetchImpl: typeof fetch\n  private connected = false\n\n  constructor(config: HttpTransportConfig) {\n    this.config = {\n      ...DEFAULTS,\n      ...config,\n    }\n    this.fetchImpl = config.fetch || globalThis.fetch\n    this.connected = true\n  }\n\n  /**\n   * Execute a SQL query\n   */\n  async query<T extends Row = Row>(\n    sql: string,\n    params?: unknown[]\n  ): Promise<QueryResult<T>> {\n    const response = await this.request<QueryResponse<T>>('/query', {\n      sql,\n      params: params || [],\n    })\n\n    return this.parseQueryResponse(response)\n  }\n\n  /**\n   * Execute multiple queries in a transaction\n   */\n  async transaction<T>(\n    queries: Array<{ sql: string; params?: unknown[] }>,\n    options?: TransactionOptions\n  ): Promise<T> {\n    const response = await this.request<TransactionResponse>('/transaction', {\n      queries,\n      options: options ? this.serializeTransactionOptions(options) : undefined,\n    })\n\n    // Return the results of all queries\n    return response.results as T\n  }\n\n  /**\n   * Close the transport (no-op for HTTP)\n   */\n  async close(): Promise<void> {\n    this.connected = false\n  }\n\n  /**\n   * Check if transport is connected\n   */\n  isConnected(): boolean {\n    return this.connected\n  }\n\n  /**\n   * Make an HTTP request to the postgres.do API\n   */\n  private async request<T>(\n    path: string,\n    body: unknown\n  ): Promise<T> {\n    const url = `${this.config.baseUrl}${path}`\n    const headers: Record<string, string> = {\n      'Content-Type': 'application/json',\n      ...this.config.headers,\n    }\n\n    if (this.config.apiKey) {\n      headers['Authorization'] = `Bearer ${this.config.apiKey}`\n    }\n\n    const controller = new AbortController()\n    const timeoutId = setTimeout(() => controller.abort(), this.config.timeout)\n\n    try {\n      const response = await this.fetchImpl(url, {\n        method: 'POST',\n        headers,\n        body: JSON.stringify(body),\n        signal: controller.signal,\n      })\n\n      clearTimeout(timeoutId)\n\n      if (!response.ok) {\n        const error = await this.parseErrorResponse(response)\n        throw error\n      }\n\n      return await response.json() as T\n    } catch (error) {\n      clearTimeout(timeoutId)\n\n      if (error instanceof Error) {\n        if (error.name === 'AbortError') {\n          throw new TimeoutError(`Request timed out after ${this.config.timeout}ms`)\n        }\n        if (error instanceof PostgresError || error instanceof ConnectionError) {\n          throw error\n        }\n      }\n\n      throw new ConnectionError(\n        `Failed to connect to postgres.do: ${error instanceof Error ? error.message : String(error)}`\n      )\n    }\n  }\n\n  /**\n   * Parse error response from the API\n   */\n  private async parseErrorResponse(response: Response): Promise<Error> {\n    try {\n      const body = await response.json() as ErrorResponse\n\n      if (body.error?.code) {\n        return new PostgresError(body.error.message || 'Database error', {\n          code: body.error.code,\n          severity: body.error.severity || 'ERROR',\n          detail: body.error.detail,\n          hint: body.error.hint,\n          position: body.error.position,\n          schema: body.error.schema,\n          table: body.error.table,\n          column: body.error.column,\n          constraint: body.error.constraint,\n        })\n      }\n\n      return new ConnectionError(body.error?.message || `HTTP ${response.status}: ${response.statusText}`)\n    } catch {\n      return new ConnectionError(`HTTP ${response.status}: ${response.statusText}`)\n    }\n  }\n\n  /**\n   * Parse query response into QueryResult\n   */\n  private parseQueryResponse<T extends Row>(response: QueryResponse<T>): QueryResult<T> {\n    return {\n      rows: response.rows || [],\n      rowCount: response.rowCount ?? response.rows?.length ?? 0,\n      fields: response.fields || [],\n      command: response.command || 'SELECT',\n    }\n  }\n\n  /**\n   * Serialize transaction options for the API\n   */\n  private serializeTransactionOptions(options: TransactionOptions): Record<string, unknown> {\n    return {\n      isolationLevel: options.isolationLevel,\n      readOnly: options.readOnly,\n      deferrable: options.deferrable,\n    }\n  }\n}\n\n/** API response types */\ninterface QueryResponse<T extends Row = Row> {\n  rows?: T[]\n  rowCount?: number\n  fields?: FieldInfo[]\n  command?: string\n}\n\ninterface TransactionResponse {\n  results: unknown[]\n}\n\ninterface ErrorResponse {\n  error?: {\n    message?: string\n    code?: string\n    severity?: string\n    detail?: string\n    hint?: string\n    position?: number\n    schema?: string\n    table?: string\n    column?: string\n    constraint?: string\n  }\n}\n\n/**\n * Create an HTTP transport instance\n */\nexport function createHttpTransport(config: HttpTransportConfig): HttpTransport {\n  return new HttpTransport(config)\n}\n","/**\n * RpcPromise - A promise wrapper that supports capnweb magic map and pipelining\n *\n * This class enables:\n * - Magic map support for N+1 query elimination\n * - Promise pipelining for batched operations\n * - Lazy execution (queries don't execute until awaited or .map()'d)\n *\n * @example Magic Map\n * ```typescript\n * const usersWithOrders = await db.query('SELECT * FROM users')\n *   .map(users => Promise.all(\n *     users.map(u => db.query('SELECT * FROM orders WHERE user_id = $1', [u.id]))\n *   ))\n * ```\n *\n * @example Promise Pipelining\n * ```typescript\n * const user = db.query('SELECT * FROM users WHERE id = $1', [id])\n * const posts = user.map(u => db.query('SELECT * FROM posts WHERE author = $1', [u.id]))\n * const comments = posts.map(p => db.query('SELECT * FROM comments WHERE post_id = ANY($1)', [p.map(x => x.id)]))\n * const result = await comments // Single round trip!\n * ```\n */\n\nimport type { Row } from '../types'\n\n/**\n * Execution context for RPC pipelining\n * Accumulates queries that can be batched together\n */\nexport interface RpcExecutionContext {\n  /** Add a query to the batch */\n  addQuery(sql: string, params?: unknown[]): number\n  /** Execute all batched queries */\n  executeBatch(): Promise<BatchResult[]>\n  /** Get a pending result by query ID */\n  getResult(queryId: number): Promise<unknown>\n  /** Check if the context is currently collecting queries */\n  isCollecting(): boolean\n  /** Start collecting queries for batching */\n  startCollecting(): void\n  /** Stop collecting and execute batch */\n  stopCollecting(): Promise<void>\n}\n\n/**\n * Result from a batched query\n */\nexport interface BatchResult<T = unknown> {\n  queryId: number\n  rows: T[]\n  fields: Array<{ name: string; dataTypeID: number }>\n  rowCount: number\n  durationMs: number\n}\n\n/**\n * Map function signature for RpcPromise\n */\nexport type MapFn<T, U> = (value: T) => U | Promise<U>\n\n/**\n * RpcPromise implementation\n * Wraps a query operation with magic map and pipelining support\n */\nexport class RpcPromise<T> implements PromiseLike<T> {\n  private executor: () => Promise<T>\n  private cachedResult: T | undefined\n  private executed = false\n  private executing: Promise<T> | null = null\n  private context: RpcExecutionContext | null\n\n  constructor(executor: () => Promise<T>, context?: RpcExecutionContext | null) {\n    this.executor = executor\n    this.context = context ?? null\n  }\n\n  /**\n   * Map over the result with magic map support\n   *\n   * The map function receives the resolved value and can return:\n   * - A plain value\n   * - A Promise\n   * - Another RpcPromise (for pipelining)\n   *\n   * When the callback returns RpcPromises, they are batched together\n   * with the original query for efficient execution.\n   *\n   * @example\n   * ```typescript\n   * const usersWithPosts = db.query('SELECT * FROM users')\n   *   .map(users => Promise.all(\n   *     users.map(u => db.query('SELECT * FROM posts WHERE user_id = $1', [u.id]))\n   *   ))\n   * ```\n   */\n  map<U>(fn: MapFn<T, U>): RpcPromise<U> {\n    return new RpcPromise<U>(async () => {\n      // If we have a context and it's collecting, use batched execution\n      if (this.context?.isCollecting()) {\n        const result = await this.execute()\n        const mapped = fn(result)\n\n        // If the mapped result is also collecting queries, batch them together\n        if (mapped instanceof RpcPromise) {\n          return mapped.execute()\n        }\n\n        return mapped\n      }\n\n      // Standard execution path\n      const result = await this.execute()\n      const mapped = fn(result)\n\n      if (mapped instanceof Promise || mapped instanceof RpcPromise) {\n        return mapped as Promise<U>\n      }\n\n      return mapped\n    }, this.context)\n  }\n\n  /**\n   * FlatMap for when the map function returns an RpcPromise\n   */\n  flatMap<U>(fn: (value: T) => RpcPromise<U>): RpcPromise<U> {\n    return new RpcPromise<U>(async () => {\n      const result = await this.execute()\n      const mapped = fn(result)\n      return mapped.execute()\n    }, this.context)\n  }\n\n  /**\n   * Execute the query and return the result\n   */\n  async execute(): Promise<T> {\n    // Return cached result if already executed\n    if (this.executed && this.cachedResult !== undefined) {\n      return this.cachedResult\n    }\n\n    // If already executing, wait for that execution\n    if (this.executing) {\n      return this.executing\n    }\n\n    // Start execution\n    this.executing = this.executor()\n\n    try {\n      this.cachedResult = await this.executing\n      this.executed = true\n      return this.cachedResult\n    } finally {\n      this.executing = null\n    }\n  }\n\n  /**\n   * Reset the execution state to allow re-execution\n   */\n  reset(): void {\n    this.executed = false\n    this.cachedResult = undefined\n    this.executing = null\n  }\n\n  /**\n   * Check if the promise has been executed\n   */\n  isExecuted(): boolean {\n    return this.executed\n  }\n\n  /**\n   * PromiseLike implementation - makes this thenable\n   */\n  then<TResult1 = T, TResult2 = never>(\n    onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\n    onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n  ): Promise<TResult1 | TResult2> {\n    return this.execute().then(onfulfilled, onrejected)\n  }\n\n  /**\n   * Catch handler\n   */\n  catch<TResult = never>(\n    onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null\n  ): Promise<T | TResult> {\n    return this.execute().catch(onrejected)\n  }\n\n  /**\n   * Finally handler\n   */\n  finally(onfinally?: (() => void) | null): Promise<T> {\n    return this.execute().finally(onfinally)\n  }\n}\n\n/**\n * Create an RpcPromise from a query function\n */\nexport function createRpcPromise<T>(\n  executor: () => Promise<T>,\n  context?: RpcExecutionContext | null\n): RpcPromise<T> {\n  return new RpcPromise(executor, context)\n}\n\n/**\n * Query result type for typed queries\n */\nexport interface RpcQueryResult<T extends Row = Row> {\n  rows: T[]\n  fields: Array<{ name: string; dataTypeID: number }>\n  rowCount: number\n  durationMs: number\n}\n\n/**\n * Create an RpcPromise that extracts rows from a query result\n */\nexport function createRowsPromise<T extends Row = Row>(\n  executor: () => Promise<RpcQueryResult<T>>,\n  context?: RpcExecutionContext | null\n): RpcPromise<T[]> {\n  return new RpcPromise(async () => {\n    const result = await executor()\n    return result.rows\n  }, context)\n}\n\n/**\n * Batch multiple RpcPromises for efficient execution\n *\n * This collects all queries from the provided promises and executes\n * them in a single batch, then distributes the results.\n *\n * @example\n * ```typescript\n * const [users, orders, products] = await batchExecute([\n *   db.query('SELECT * FROM users'),\n *   db.query('SELECT * FROM orders'),\n *   db.query('SELECT * FROM products'),\n * ])\n * ```\n */\nexport async function batchExecute<T extends readonly RpcPromise<unknown>[]>(\n  promises: T\n): Promise<{ [K in keyof T]: T[K] extends RpcPromise<infer U> ? U : never }> {\n  // Execute all promises in parallel\n  const results = await Promise.all(promises.map(p => p.execute()))\n  return results as { [K in keyof T]: T[K] extends RpcPromise<infer U> ? U : never }\n}\n\n/**\n * Create a magic map wrapper that batches nested queries\n *\n * This enables the N+1 query elimination pattern:\n * ```typescript\n * const usersWithOrders = await magicMap(\n *   db.query('SELECT * FROM users'),\n *   users => users.map(u => db.query('SELECT * FROM orders WHERE user_id = $1', [u.id]))\n * )\n * ```\n */\nexport async function magicMap<T, U>(\n  source: RpcPromise<T[]>,\n  mapFn: (items: T[]) => RpcPromise<U>[]\n): Promise<U[]> {\n  const items = await source.execute()\n  const promises = mapFn(items)\n  return Promise.all(promises.map(p => p.execute()))\n}\n","/**\n * RPC Transport for postgres.do\n *\n * Connects to PostgresDO via capnweb RPC for:\n * - Direct Worker-to-DO communication without HTTP overhead\n * - Promise pipelining for efficient batched operations\n * - Magic map support for N+1 query elimination\n *\n * @see packages/postgres/src/worker/rpc.ts for the server-side RPC API\n * @see packages/postgres/src/worker/proxy.ts for the proxy session pool\n */\n\nimport type {\n  Transport,\n  QueryResult,\n  Row,\n  TransactionOptions,\n  FieldInfo,\n} from '../types'\nimport { PostgresError, ConnectionError, TimeoutError } from '../types'\nimport { RpcPromise, createRpcPromise, type RpcExecutionContext, type BatchResult } from '../rpc/rpc-promise'\n\n/**\n * RPC Transport configuration\n */\nexport interface RpcTransportConfig {\n  /** WebSocket URL for the capnweb RPC endpoint */\n  url: string\n  /** API key for authentication */\n  apiKey?: string | undefined\n  /** Custom WebSocket implementation */\n  WebSocket?: typeof WebSocket | undefined\n  /** Connection timeout in milliseconds */\n  connectTimeout?: number | undefined\n  /** Request timeout in milliseconds */\n  requestTimeout?: number | undefined\n  /** Enable automatic batching */\n  autoBatch?: boolean | undefined\n  /** Batch delay in milliseconds (how long to wait for more queries) */\n  batchDelayMs?: number | undefined\n}\n\n/** Default configuration values */\nconst DEFAULTS = {\n  url: 'wss://db.postgres.do/rpc',\n  connectTimeout: 10000,\n  requestTimeout: 30000,\n  autoBatch: true,\n  batchDelayMs: 0, // No delay by default - use microtask batching\n}\n\n/** RPC message types */\nenum RpcMessageType {\n  // Requests\n  Query = 'query',\n  Batch = 'batch',\n  BatchTransaction = 'batch_tx',\n  Transaction = 'transaction',\n  TransactionQuery = 'tx_query',\n  TransactionCommit = 'tx_commit',\n  TransactionRollback = 'tx_rollback',\n  Ping = 'ping',\n  Auth = 'auth',\n\n  // Responses\n  QueryResult = 'query_result',\n  BatchResult = 'batch_result',\n  TransactionResult = 'tx_result',\n  Error = 'error',\n  Pong = 'pong',\n  AuthResult = 'auth_result',\n}\n\n/** Pending request waiting for a response */\ninterface PendingRequest<T = unknown> {\n  resolve: (value: T) => void\n  reject: (error: Error) => void\n  timeout: ReturnType<typeof setTimeout>\n}\n\n/** Pending batch of queries */\ninterface PendingBatch {\n  queries: Array<{ sql: string; params?: unknown[] }>\n  resolvers: Array<{\n    resolve: (value: BatchResult) => void\n    reject: (error: Error) => void\n  }>\n  timer: ReturnType<typeof setTimeout> | null\n}\n\n/** Resolved config with optional properties handled */\ninterface ResolvedConfig {\n  url: string\n  apiKey: string | undefined\n  WebSocket: typeof WebSocket | undefined\n  connectTimeout: number\n  requestTimeout: number\n  autoBatch: boolean\n  batchDelayMs: number\n}\n\n/**\n * RPC Transport implementation\n *\n * Provides capnweb-style RPC communication with PostgresDO:\n * - Automatic query batching for N+1 elimination\n * - Promise pipelining support\n * - WebSocket-based persistent connection\n */\nexport class RpcTransport implements Transport, RpcExecutionContext {\n  private readonly config: ResolvedConfig\n  private readonly WebSocketImpl: typeof WebSocket\n  private ws: WebSocket | null = null\n  private connected = false\n  private authenticated = false\n  private connecting: Promise<void> | null = null\n  private requestId = 0\n  private pendingRequests = new Map<number, PendingRequest>()\n  private pendingBatch: PendingBatch | null = null\n  private collecting = false\n\n  constructor(config: RpcTransportConfig) {\n    this.config = {\n      url: config.url ?? DEFAULTS.url,\n      apiKey: config.apiKey,\n      WebSocket: config.WebSocket,\n      connectTimeout: config.connectTimeout ?? DEFAULTS.connectTimeout,\n      requestTimeout: config.requestTimeout ?? DEFAULTS.requestTimeout,\n      autoBatch: config.autoBatch ?? DEFAULTS.autoBatch,\n      batchDelayMs: config.batchDelayMs ?? DEFAULTS.batchDelayMs,\n    }\n    this.WebSocketImpl = config.WebSocket || globalThis.WebSocket\n  }\n\n  // ========== RpcExecutionContext implementation ==========\n\n  /**\n   * Add a query to the current batch\n   */\n  addQuery(sql: string, params?: unknown[]): number {\n    if (!this.pendingBatch) {\n      this.pendingBatch = {\n        queries: [],\n        resolvers: [],\n        timer: null,\n      }\n\n      // Schedule batch execution on next microtask\n      if (this.config.batchDelayMs === 0) {\n        queueMicrotask(() => this.flushBatch())\n      } else {\n        this.pendingBatch.timer = setTimeout(\n          () => this.flushBatch(),\n          this.config.batchDelayMs\n        )\n      }\n    }\n\n    const queryId = this.pendingBatch.queries.length\n    this.pendingBatch.queries.push({ sql, params: params ?? [] })\n\n    return queryId\n  }\n\n  /**\n   * Execute all batched queries\n   */\n  async executeBatch(): Promise<BatchResult[]> {\n    if (!this.pendingBatch || this.pendingBatch.queries.length === 0) {\n      return []\n    }\n\n    await this.ensureConnected()\n\n    const batch = this.pendingBatch\n    this.pendingBatch = null\n\n    if (batch.timer) {\n      clearTimeout(batch.timer)\n    }\n\n    const id = this.nextRequestId()\n    const response = await this.sendRequest<RpcBatchResponse>(id, {\n      type: RpcMessageType.Batch,\n      id,\n      queries: batch.queries,\n    })\n\n    return response.results.map((r, i) => ({\n      queryId: i,\n      rows: r.rows,\n      fields: r.fields,\n      rowCount: r.rowCount,\n      durationMs: r.durationMs,\n    }))\n  }\n\n  /**\n   * Get a pending result by query ID\n   */\n  async getResult(_queryId: number): Promise<unknown> {\n    // Results are returned in order from executeBatch\n    // This method is for future optimization where results\n    // can be streamed as they complete\n    throw new Error('getResult is not yet implemented for streaming results')\n  }\n\n  /**\n   * Check if the context is currently collecting queries\n   */\n  isCollecting(): boolean {\n    return this.collecting\n  }\n\n  /**\n   * Start collecting queries for batching\n   */\n  startCollecting(): void {\n    this.collecting = true\n  }\n\n  /**\n   * Stop collecting and execute batch\n   */\n  async stopCollecting(): Promise<void> {\n    this.collecting = false\n    await this.flushBatch()\n  }\n\n  /**\n   * Flush the pending batch immediately\n   */\n  private async flushBatch(): Promise<void> {\n    if (!this.pendingBatch || this.pendingBatch.queries.length === 0) {\n      return\n    }\n\n    const batch = this.pendingBatch\n    this.pendingBatch = null\n\n    if (batch.timer) {\n      clearTimeout(batch.timer)\n    }\n\n    try {\n      await this.ensureConnected()\n\n      const id = this.nextRequestId()\n      const response = await this.sendRequest<RpcBatchResponse>(id, {\n        type: RpcMessageType.Batch,\n        id,\n        queries: batch.queries,\n      })\n\n      // Resolve all pending queries with their results\n      for (let i = 0; i < batch.resolvers.length; i++) {\n        const resolver = batch.resolvers[i]\n        const result = response.results[i]\n        if (resolver && result) {\n          resolver.resolve({\n            queryId: i,\n            rows: result.rows,\n            fields: result.fields,\n            rowCount: result.rowCount,\n            durationMs: result.durationMs,\n          })\n        } else if (resolver) {\n          resolver.reject(new Error(`No result for query ${i}`))\n        }\n      }\n    } catch (error) {\n      // Reject all pending queries with the error\n      for (const resolver of batch.resolvers) {\n        if (resolver) {\n          resolver.reject(error instanceof Error ? error : new Error(String(error)))\n        }\n      }\n    }\n  }\n\n  // ========== Transport interface implementation ==========\n\n  /**\n   * Execute a SQL query with RpcPromise support\n   */\n  queryRpc<T extends Row = Row>(\n    sql: string,\n    params?: unknown[]\n  ): RpcPromise<T[]> {\n    return createRpcPromise(async () => {\n      const result = await this.query<T>(sql, params)\n      return result.rows\n    }, this)\n  }\n\n  /**\n   * Execute a SQL query and return full result\n   */\n  async query<T extends Row = Row>(\n    sql: string,\n    params?: unknown[]\n  ): Promise<QueryResult<T>> {\n    // If autoBatch is enabled and we're in a batching context\n    if (this.config.autoBatch && this.collecting) {\n      return new Promise((resolve, reject) => {\n        const queryId = this.addQuery(sql, params)\n\n        if (!this.pendingBatch) {\n          reject(new Error('Batch was flushed before query could be added'))\n          return\n        }\n\n        this.pendingBatch.resolvers[queryId] = {\n          resolve: (result) => {\n            resolve({\n              rows: result.rows as T[],\n              fields: result.fields as FieldInfo[],\n              rowCount: result.rowCount,\n              command: 'SELECT',\n            })\n          },\n          reject,\n        }\n      })\n    }\n\n    await this.ensureConnected()\n\n    const id = this.nextRequestId()\n    const response = await this.sendRequest<RpcQueryResponse<T>>(id, {\n      type: RpcMessageType.Query,\n      id,\n      sql,\n      params: params || [],\n    })\n\n    return {\n      rows: response.rows || [],\n      fields: (response.fields || []) as FieldInfo[],\n      rowCount: response.rowCount ?? response.rows?.length ?? 0,\n      command: response.command || 'SELECT',\n    }\n  }\n\n  /**\n   * Execute a batch of queries\n   */\n  async batch<T extends Row = Row>(\n    queries: Array<{ sql: string; params?: unknown[] }>\n  ): Promise<Array<QueryResult<T>>> {\n    await this.ensureConnected()\n\n    const id = this.nextRequestId()\n    const response = await this.sendRequest<RpcBatchResponse>(id, {\n      type: RpcMessageType.Batch,\n      id,\n      queries,\n    })\n\n    return response.results.map(r => ({\n      rows: r.rows as T[],\n      fields: r.fields as FieldInfo[],\n      rowCount: r.rowCount,\n      command: 'SELECT',\n    }))\n  }\n\n  /**\n   * Execute a batch of queries within a transaction\n   */\n  async batchTransaction<T extends Row = Row>(\n    queries: Array<{ sql: string; params?: unknown[] }>,\n    options?: TransactionOptions\n  ): Promise<Array<QueryResult<T>>> {\n    await this.ensureConnected()\n\n    const id = this.nextRequestId()\n    const response = await this.sendRequest<RpcBatchResponse>(id, {\n      type: RpcMessageType.BatchTransaction,\n      id,\n      queries,\n      options: options ? this.serializeTransactionOptions(options) : undefined,\n    })\n\n    return response.results.map(r => ({\n      rows: r.rows as T[],\n      fields: r.fields as FieldInfo[],\n      rowCount: r.rowCount,\n      command: 'SELECT',\n    }))\n  }\n\n  /**\n   * Execute multiple queries in a transaction (Transport interface)\n   */\n  async transaction<T>(\n    queries: Array<{ sql: string; params?: unknown[] }>,\n    options?: TransactionOptions\n  ): Promise<T> {\n    const results = await this.batchTransaction(queries, options)\n    return results as T\n  }\n\n  /**\n   * Close the WebSocket connection\n   */\n  async close(): Promise<void> {\n    // Flush any pending batch\n    if (this.pendingBatch) {\n      await this.flushBatch()\n    }\n\n    this.rejectAllPending(new ConnectionError('Connection closed'))\n\n    if (this.ws) {\n      this.ws.close(1000, 'Client closing connection')\n      this.ws = null\n    }\n\n    this.connected = false\n    this.authenticated = false\n    this.connecting = null\n  }\n\n  /**\n   * Check if transport is connected\n   */\n  isConnected(): boolean {\n    return this.connected && this.authenticated\n  }\n\n  // ========== Private methods ==========\n\n  /**\n   * Ensure the WebSocket is connected and authenticated\n   */\n  private async ensureConnected(): Promise<void> {\n    if (this.isConnected()) {\n      return\n    }\n\n    if (this.connecting) {\n      return this.connecting\n    }\n\n    this.connecting = this.connect()\n    try {\n      await this.connecting\n    } finally {\n      this.connecting = null\n    }\n  }\n\n  /**\n   * Establish WebSocket connection\n   */\n  private async connect(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        reject(new TimeoutError(`WebSocket connection timed out after ${this.config.connectTimeout}ms`))\n        if (this.ws) {\n          this.ws.close()\n          this.ws = null\n        }\n      }, this.config.connectTimeout)\n\n      try {\n        this.ws = new this.WebSocketImpl(this.config.url)\n      } catch (error) {\n        clearTimeout(timeoutId)\n        reject(new ConnectionError(`Failed to create WebSocket: ${error instanceof Error ? error.message : String(error)}`))\n        return\n      }\n\n      this.ws.onopen = async () => {\n        this.connected = true\n\n        // Authenticate if API key is provided\n        if (this.config.apiKey) {\n          try {\n            await this.authenticate()\n            clearTimeout(timeoutId)\n            resolve()\n          } catch (error) {\n            clearTimeout(timeoutId)\n            reject(error)\n          }\n        } else {\n          this.authenticated = true\n          clearTimeout(timeoutId)\n          resolve()\n        }\n      }\n\n      this.ws.onmessage = (event) => {\n        this.handleMessage(event.data)\n      }\n\n      this.ws.onerror = () => {\n        clearTimeout(timeoutId)\n        const error = new ConnectionError('WebSocket error occurred')\n        this.rejectAllPending(error)\n        reject(error)\n      }\n\n      this.ws.onclose = (event) => {\n        clearTimeout(timeoutId)\n        this.connected = false\n        this.authenticated = false\n\n        if (!event.wasClean) {\n          const error = new ConnectionError(`WebSocket closed unexpectedly: ${event.code} ${event.reason}`)\n          this.rejectAllPending(error)\n          reject(error)\n        }\n      }\n    })\n  }\n\n  /**\n   * Authenticate with the API key\n   */\n  private async authenticate(): Promise<void> {\n    const id = this.nextRequestId()\n    const response = await this.sendRequest<RpcAuthResponse>(id, {\n      type: RpcMessageType.Auth,\n      id,\n      apiKey: this.config.apiKey,\n    })\n\n    if (!response.success) {\n      throw new ConnectionError('Authentication failed')\n    }\n\n    this.authenticated = true\n  }\n\n  /**\n   * Send a request and wait for response\n   */\n  private sendRequest<T>(id: number, message: unknown): Promise<T> {\n    return new Promise((resolve, reject) => {\n      const timeout = setTimeout(() => {\n        this.pendingRequests.delete(id)\n        reject(new TimeoutError('Request timed out'))\n      }, this.config.requestTimeout)\n\n      this.pendingRequests.set(id, {\n        resolve: resolve as (value: unknown) => void,\n        reject,\n        timeout,\n      })\n\n      if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n        this.ws.send(JSON.stringify(message))\n      } else {\n        clearTimeout(timeout)\n        this.pendingRequests.delete(id)\n        reject(new ConnectionError('WebSocket is not connected'))\n      }\n    })\n  }\n\n  /**\n   * Handle incoming WebSocket message\n   */\n  private handleMessage(data: string): void {\n    let message: RpcIncomingMessage\n\n    try {\n      message = JSON.parse(data)\n    } catch {\n      console.error('Failed to parse RPC message:', data)\n      return\n    }\n\n    // Handle pong messages\n    if (message.type === RpcMessageType.Pong) {\n      return\n    }\n\n    // Handle responses to pending requests\n    if ('id' in message && typeof message.id === 'number') {\n      const pending = this.pendingRequests.get(message.id)\n      if (pending) {\n        clearTimeout(pending.timeout)\n        this.pendingRequests.delete(message.id)\n\n        if (message.type === RpcMessageType.Error) {\n          const errorMessage = message as RpcErrorMessage\n          pending.reject(new PostgresError(errorMessage.error.message || 'Database error', {\n            code: errorMessage.error.code,\n            severity: errorMessage.error.severity || 'ERROR',\n            detail: errorMessage.error.detail,\n            hint: errorMessage.error.hint,\n            position: errorMessage.error.position,\n            schema: errorMessage.error.schema,\n            table: errorMessage.error.table,\n            column: errorMessage.error.column,\n            constraint: errorMessage.error.constraint,\n          }))\n        } else {\n          pending.resolve(message)\n        }\n      }\n    }\n  }\n\n  /**\n   * Reject all pending requests\n   */\n  private rejectAllPending(error: Error): void {\n    for (const [, pending] of this.pendingRequests) {\n      clearTimeout(pending.timeout)\n      pending.reject(error)\n    }\n    this.pendingRequests.clear()\n\n    // Also reject pending batch\n    if (this.pendingBatch) {\n      for (const resolver of this.pendingBatch.resolvers) {\n        resolver.reject(error)\n      }\n      if (this.pendingBatch.timer) {\n        clearTimeout(this.pendingBatch.timer)\n      }\n      this.pendingBatch = null\n    }\n  }\n\n  /**\n   * Get next request ID\n   */\n  private nextRequestId(): number {\n    return ++this.requestId\n  }\n\n  /**\n   * Serialize transaction options\n   */\n  private serializeTransactionOptions(options: TransactionOptions): Record<string, unknown> {\n    return {\n      isolationLevel: options.isolationLevel,\n      readOnly: options.readOnly,\n      deferrable: options.deferrable,\n    }\n  }\n}\n\n/** RPC message type definitions */\ninterface RpcQueryResponse<T extends Row = Row> {\n  type: RpcMessageType.QueryResult\n  id: number\n  rows?: T[]\n  rowCount?: number\n  fields?: Array<{ name: string; dataTypeID: number }>\n  command?: string\n}\n\ninterface RpcBatchResponse {\n  type: RpcMessageType.BatchResult\n  id: number\n  results: Array<{\n    rows: Row[]\n    fields: Array<{ name: string; dataTypeID: number }>\n    rowCount: number\n    durationMs: number\n  }>\n  durationMs: number\n}\n\ninterface RpcAuthResponse {\n  type: RpcMessageType.AuthResult\n  id: number\n  success: boolean\n}\n\ninterface RpcErrorMessage {\n  type: RpcMessageType.Error\n  id: number\n  error: {\n    message?: string\n    code?: string\n    severity?: string\n    detail?: string\n    hint?: string\n    position?: number\n    schema?: string\n    table?: string\n    column?: string\n    constraint?: string\n  }\n}\n\ntype RpcIncomingMessage =\n  | RpcQueryResponse\n  | RpcBatchResponse\n  | RpcAuthResponse\n  | RpcErrorMessage\n  | { type: RpcMessageType.Pong }\n\n/**\n * Create an RPC transport instance\n */\nexport function createRpcTransport(config: RpcTransportConfig): RpcTransport {\n  return new RpcTransport(config)\n}\n","/**\n * CDC WebSocket Transport for postgres.do\n *\n * Provides real-time change data capture streaming via WebSocket:\n * - Bidirectional communication for subscription management\n * - Automatic reconnection with exponential backoff\n * - LSN-based resumption for reliable delivery\n * - Heartbeat/ping-pong for connection keepalive\n */\n\nimport type {\n  Row,\n  CDCChangeEvent,\n  CDCTransport,\n  CDCSubscriptionOptions,\n  CDCWsTransportConfig,\n  CDCOperation,\n} from '../types'\nimport { ConnectionError, TimeoutError } from '../types'\nimport type { PendingRequest } from './base-transport'\n\n/**\n * CDC WebSocket message types\n */\nenum CDCMessageType {\n  // Client -> Server\n  Subscribe = 'subscribe',\n  Unsubscribe = 'unsubscribe',\n  Ping = 'ping',\n  Auth = 'auth',\n  Ack = 'ack',\n\n  // Server -> Client\n  Event = 'event',\n  Error = 'error',\n  Pong = 'pong',\n  AuthResult = 'auth_result',\n  SubscribeResult = 'subscribe_result',\n  UnsubscribeResult = 'unsubscribe_result',\n}\n\n/**\n * Incoming CDC event message from server\n */\ninterface CDCEventMessage {\n  type: CDCMessageType.Event\n  subscriptionId: string\n  event: {\n    id: string\n    lsn: string\n    operation: CDCOperation\n    table: string\n    schema: string\n    timestamp: string\n    newRow?: Row\n    oldRow?: Row\n    changedColumns?: string[]\n    xid: number\n    isLastInTransaction: boolean\n  }\n}\n\n/**\n * Error message from server\n */\ninterface CDCErrorMessage {\n  type: CDCMessageType.Error\n  subscriptionId?: string\n  error: {\n    message: string\n    code?: string\n  }\n}\n\n/**\n * Subscription result message\n */\ninterface CDCSubscribeResultMessage {\n  type: CDCMessageType.SubscribeResult\n  subscriptionId: string\n  success: boolean\n  error?: string\n}\n\n/**\n * Unsubscribe result message\n */\ninterface CDCUnsubscribeResultMessage {\n  type: CDCMessageType.UnsubscribeResult\n  subscriptionId: string\n  success: boolean\n}\n\n/**\n * Auth result message\n */\ninterface CDCAuthResultMessage {\n  type: CDCMessageType.AuthResult\n  success: boolean\n  error?: string\n}\n\ntype CDCIncomingMessage =\n  | CDCEventMessage\n  | CDCErrorMessage\n  | CDCSubscribeResultMessage\n  | CDCUnsubscribeResultMessage\n  | CDCAuthResultMessage\n  | { type: CDCMessageType.Pong }\n\n/**\n * Default configuration values\n */\nconst DEFAULTS = {\n  connectTimeout: 10000,\n  pingInterval: 0, // Disabled by default for test compatibility; production code should set explicitly\n  reconnectBaseDelay: 1000,\n  maxReconnectDelay: 30000,\n  maxReconnectAttempts: 10,\n} as const\n\n/**\n * CDC WebSocket Transport implementation\n *\n * Extends BaseCDCTransport for common functionality.\n */\nexport class CDCWsTransport implements CDCTransport {\n  private readonly config: {\n    readonly url: string\n    readonly apiKey?: string | undefined\n    readonly WebSocket?: typeof WebSocket | undefined\n    readonly connectTimeout: number\n    readonly pingInterval: number\n  }\n  private readonly WebSocketImpl: typeof WebSocket\n  private ws: WebSocket | null = null\n  private connected = false\n  private authenticated = false\n  private connecting: Promise<void> | null = null\n  private lastEventId: string | null = null\n  private reconnectAttempt = 0\n  private reconnectTimer: ReturnType<typeof setTimeout> | null = null\n  private pingTimer: ReturnType<typeof setInterval> | null = null\n  private shouldReconnect = true\n\n  // Pending requests\n  private pendingSubscriptions = new Map<string, PendingRequest<void>>()\n  private pendingUnsubscriptions = new Map<string, PendingRequest<void>>()\n  private pendingAuth: PendingRequest<void> | null = null\n\n  // Event handlers\n  private eventHandler: ((subscriptionId: string, event: CDCChangeEvent) => void) | null = null\n  private errorHandler: ((subscriptionId: string, error: Error) => void) | null = null\n  private reconnectHandler: ((attempt: number, lastLsn: string | undefined) => void) | null = null\n  private closeHandler: (() => void) | null = null\n\n  // Active subscriptions for reconnection\n  private activeSubscriptions = new Map<\n    string,\n    {\n      table: string\n      schema: string\n      options: CDCSubscriptionOptions\n    }\n  >()\n\n  constructor(config: CDCWsTransportConfig) {\n    this.config = {\n      url: config.url,\n      apiKey: config.apiKey,\n      WebSocket: config.WebSocket,\n      connectTimeout: config.connectTimeout ?? DEFAULTS.connectTimeout,\n      pingInterval: config.pingInterval ?? DEFAULTS.pingInterval,\n    }\n    this.WebSocketImpl = config.WebSocket || globalThis.WebSocket\n  }\n\n  /**\n   * Connect to the CDC stream\n   */\n  async connect(): Promise<void> {\n    if (this.connected && this.authenticated) {\n      return\n    }\n\n    if (this.connecting) {\n      return this.connecting\n    }\n\n    this.shouldReconnect = true\n    this.connecting = this._connect()\n\n    try {\n      await this.connecting\n    } finally {\n      this.connecting = null\n    }\n  }\n\n  /**\n   * Internal connect implementation\n   */\n  private _connect(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        reject(new TimeoutError(`WebSocket connection timed out after ${this.config.connectTimeout}ms`))\n        if (this.ws) {\n          this.ws.close()\n          this.ws = null\n        }\n      }, this.config.connectTimeout)\n\n      try {\n        this.ws = new this.WebSocketImpl(this.config.url)\n      } catch (error) {\n        clearTimeout(timeoutId)\n        reject(\n          new ConnectionError(\n            `Failed to create WebSocket: ${error instanceof Error ? error.message : String(error)}`\n          )\n        )\n        return\n      }\n\n      this.ws.onopen = () => {\n        this.connected = true\n        this.reconnectAttempt = 0\n\n        // Authenticate if API key is provided\n        if (this.config.apiKey) {\n          this.authenticate()\n            .then(() => {\n              clearTimeout(timeoutId)\n              resolve()\n              // Start ping interval after connect resolves\n              if (this.config.pingInterval > 0) {\n                this.startPingInterval()\n              }\n            })\n            .catch((error) => {\n              clearTimeout(timeoutId)\n              reject(error)\n            })\n        } else {\n          this.authenticated = true\n          clearTimeout(timeoutId)\n          resolve()\n          // Start ping interval after connect resolves\n          if (this.config.pingInterval > 0) {\n            this.startPingInterval()\n          }\n        }\n      }\n\n      this.ws.onmessage = (event) => {\n        this.handleMessage(event.data)\n      }\n\n      this.ws.onerror = () => {\n        clearTimeout(timeoutId)\n        const error = new ConnectionError('WebSocket error occurred')\n        this.rejectAllPending(error)\n        reject(error)\n      }\n\n      this.ws.onclose = (event) => {\n        clearTimeout(timeoutId)\n        this.connected = false\n        this.authenticated = false\n        this.stopPingInterval()\n\n        if (!event.wasClean && this.shouldReconnect) {\n          this.scheduleReconnect()\n        } else if (!this.shouldReconnect) {\n          this.closeHandler?.()\n        } else {\n          const error = new ConnectionError(`WebSocket closed: ${event.code} ${event.reason}`)\n          this.rejectAllPending(error)\n          reject(error)\n        }\n      }\n    })\n  }\n\n  /**\n   * Authenticate with the API key\n   */\n  private authenticate(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        this.pendingAuth = null\n        reject(new TimeoutError('Authentication timed out'))\n      }, this.config.connectTimeout)\n\n      this.pendingAuth = {\n        resolve: () => {\n          clearTimeout(timeoutId)\n          this.pendingAuth = null\n          this.authenticated = true\n          resolve()\n        },\n        reject: (error: Error) => {\n          clearTimeout(timeoutId)\n          this.pendingAuth = null\n          reject(error)\n        },\n        timeout: timeoutId,\n      }\n\n      this.send({\n        type: CDCMessageType.Auth,\n        apiKey: this.config.apiKey,\n      })\n    })\n  }\n\n  /**\n   * Disconnect from the CDC stream\n   */\n  async disconnect(): Promise<void> {\n    this.shouldReconnect = false\n\n    if (this.reconnectTimer) {\n      clearTimeout(this.reconnectTimer)\n      this.reconnectTimer = null\n    }\n\n    this.stopPingInterval()\n    this.rejectAllPending(new ConnectionError('Connection closed'))\n\n    if (this.ws) {\n      this.ws.close(1000, 'Client closing connection')\n      this.ws = null\n    }\n\n    this.connected = false\n    this.authenticated = false\n    this.activeSubscriptions.clear()\n    this.closeHandler?.()\n  }\n\n  /**\n   * Check if connected\n   */\n  isConnected(): boolean {\n    return this.connected && this.authenticated\n  }\n\n  /**\n   * Get the last event ID received\n   */\n  getLastEventId(): string | null {\n    return this.lastEventId\n  }\n\n  /**\n   * Subscribe to a table\n   */\n  async subscribe(\n    subscriptionId: string,\n    table: string,\n    schema: string,\n    options: CDCSubscriptionOptions\n  ): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        this.pendingSubscriptions.delete(subscriptionId)\n        reject(new TimeoutError('Subscription request timed out'))\n      }, this.config.connectTimeout)\n\n      this.pendingSubscriptions.set(subscriptionId, {\n        resolve: () => {\n          clearTimeout(timeoutId)\n          // Store for reconnection\n          this.activeSubscriptions.set(subscriptionId, { table, schema, options })\n          resolve()\n        },\n        reject: (error) => {\n          clearTimeout(timeoutId)\n          reject(error)\n        },\n        timeout: timeoutId,\n      })\n\n      this.send({\n        type: CDCMessageType.Subscribe,\n        subscriptionId,\n        table,\n        schema,\n        options: {\n          events: options.events,\n          filter: options.filter,\n          resumeFrom: options.resumeFrom,\n          includeOldRow: options.includeOldRow,\n          trackChangedColumns: options.trackChangedColumns,\n          batchSize: options.batchSize,\n          heartbeatInterval: options.heartbeatInterval,\n        },\n      })\n    })\n  }\n\n  /**\n   * Unsubscribe from a subscription\n   */\n  async unsubscribe(subscriptionId: string): Promise<void> {\n    this.activeSubscriptions.delete(subscriptionId)\n\n    return new Promise((resolve) => {\n      const timeoutId = setTimeout(() => {\n        this.pendingUnsubscriptions.delete(subscriptionId)\n        // Resolve anyway on timeout - server may have already processed\n        resolve()\n      }, this.config.connectTimeout)\n\n      this.pendingUnsubscriptions.set(subscriptionId, {\n        resolve: () => {\n          clearTimeout(timeoutId)\n          resolve()\n        },\n        reject: () => {\n          clearTimeout(timeoutId)\n          // Still resolve on reject for unsubscribe\n          resolve()\n        },\n        timeout: timeoutId,\n      })\n\n      this.send({\n        type: CDCMessageType.Unsubscribe,\n        subscriptionId,\n      })\n    })\n  }\n\n  /**\n   * Set the event handler\n   */\n  onEvent(handler: (subscriptionId: string, event: CDCChangeEvent) => void): void {\n    this.eventHandler = handler\n  }\n\n  /**\n   * Set the error handler\n   */\n  onError(handler: (subscriptionId: string, error: Error) => void): void {\n    this.errorHandler = handler\n  }\n\n  /**\n   * Set the reconnect handler\n   */\n  onReconnect(handler: (attempt: number, lastLsn: string | undefined) => void): void {\n    this.reconnectHandler = handler\n  }\n\n  /**\n   * Set the close handler\n   */\n  onClose(handler: () => void): void {\n    this.closeHandler = handler\n  }\n\n  /**\n   * Send a message\n   */\n  private send(message: unknown): void {\n    // Use WebSocketImpl for the OPEN constant to support custom WebSocket implementations in tests\n    if (this.ws && this.ws.readyState === this.WebSocketImpl.OPEN) {\n      this.ws.send(JSON.stringify(message))\n    }\n  }\n\n  /**\n   * Handle incoming message\n   */\n  private handleMessage(data: string): void {\n    let message: CDCIncomingMessage\n\n    try {\n      message = JSON.parse(data)\n    } catch {\n      console.error('Failed to parse CDC message:', data)\n      return\n    }\n\n    switch (message.type) {\n      case CDCMessageType.Event:\n        this.handleEventMessage(message)\n        break\n\n      case CDCMessageType.Error:\n        this.handleErrorMessage(message)\n        break\n\n      case CDCMessageType.SubscribeResult:\n        this.handleSubscribeResult(message)\n        break\n\n      case CDCMessageType.UnsubscribeResult:\n        this.handleUnsubscribeResult(message)\n        break\n\n      case CDCMessageType.AuthResult:\n        this.handleAuthResult(message)\n        break\n\n      case CDCMessageType.Pong:\n        // Heartbeat response - connection is alive\n        break\n\n      default:\n        // Unknown message type - ignore\n        break\n    }\n  }\n\n  /**\n   * Handle CDC event message\n   */\n  private handleEventMessage(message: CDCEventMessage): void {\n    const { subscriptionId, event } = message\n\n    // Update last event ID\n    this.lastEventId = event.lsn\n\n    // Convert to CDCChangeEvent\n    const changeEvent: CDCChangeEvent = {\n      id: event.id,\n      lsn: event.lsn,\n      operation: event.operation,\n      table: event.table,\n      schema: event.schema,\n      timestamp: new Date(event.timestamp),\n      newRow: event.newRow,\n      oldRow: event.oldRow,\n      changedColumns: event.changedColumns,\n      xid: event.xid,\n      isLastInTransaction: event.isLastInTransaction,\n    }\n\n    this.eventHandler?.(subscriptionId, changeEvent)\n\n    // Send ACK\n    this.send({\n      type: CDCMessageType.Ack,\n      subscriptionId,\n      lsn: event.lsn,\n    })\n  }\n\n  /**\n   * Handle error message\n   */\n  private handleErrorMessage(message: CDCErrorMessage): void {\n    const error = new Error(message.error.message)\n\n    if (message.subscriptionId) {\n      this.errorHandler?.(message.subscriptionId, error)\n    } else {\n      // Global error - notify all subscriptions\n      for (const subscriptionId of this.activeSubscriptions.keys()) {\n        this.errorHandler?.(subscriptionId, error)\n      }\n    }\n  }\n\n  /**\n   * Handle subscribe result\n   */\n  private handleSubscribeResult(message: CDCSubscribeResultMessage): void {\n    const pending = this.pendingSubscriptions.get(message.subscriptionId)\n    if (pending) {\n      this.pendingSubscriptions.delete(message.subscriptionId)\n      clearTimeout(pending.timeout)\n\n      if (message.success) {\n        pending.resolve()\n      } else {\n        pending.reject(new Error(message.error || 'Subscription failed'))\n      }\n    }\n  }\n\n  /**\n   * Handle unsubscribe result\n   */\n  private handleUnsubscribeResult(message: CDCUnsubscribeResultMessage): void {\n    const pending = this.pendingUnsubscriptions.get(message.subscriptionId)\n    if (pending) {\n      this.pendingUnsubscriptions.delete(message.subscriptionId)\n      clearTimeout(pending.timeout)\n      pending.resolve()\n    }\n  }\n\n  /**\n   * Handle auth result\n   */\n  private handleAuthResult(message: CDCAuthResultMessage): void {\n    if (this.pendingAuth) {\n      if (message.success) {\n        this.pendingAuth.resolve()\n      } else {\n        this.pendingAuth.reject(new ConnectionError(message.error || 'Authentication failed'))\n      }\n    }\n  }\n\n  /**\n   * Start ping interval for keepalive\n   */\n  private startPingInterval(): void {\n    this.stopPingInterval()\n    if (this.config.pingInterval > 0) {\n      this.pingTimer = setInterval(() => {\n        this.send({ type: CDCMessageType.Ping })\n      }, this.config.pingInterval)\n    }\n  }\n\n  /**\n   * Stop ping interval\n   */\n  private stopPingInterval(): void {\n    if (this.pingTimer) {\n      clearInterval(this.pingTimer)\n      this.pingTimer = null\n    }\n  }\n\n  /**\n   * Schedule reconnection with exponential backoff\n   */\n  private scheduleReconnect(): void {\n    if (!this.shouldReconnect) {\n      return\n    }\n\n    this.reconnectAttempt++\n\n    if (this.reconnectAttempt > DEFAULTS.maxReconnectAttempts) {\n      const error = new ConnectionError('Max reconnection attempts exceeded')\n      for (const subscriptionId of this.activeSubscriptions.keys()) {\n        this.errorHandler?.(subscriptionId, error)\n      }\n      this.closeHandler?.()\n      return\n    }\n\n    // Exponential backoff with jitter\n    const delay = Math.min(\n      DEFAULTS.reconnectBaseDelay * Math.pow(2, this.reconnectAttempt - 1) + Math.random() * 1000,\n      DEFAULTS.maxReconnectDelay\n    )\n\n    this.reconnectTimer = setTimeout(() => {\n      this.reconnectHandler?.(this.reconnectAttempt, this.lastEventId ?? undefined)\n      this.reconnect()\n    }, delay)\n  }\n\n  /**\n   * Reconnect and resubscribe\n   */\n  private async reconnect(): Promise<void> {\n    try {\n      await this._connect()\n\n      // Resubscribe to all active subscriptions\n      for (const [subscriptionId, { table, schema, options }] of this.activeSubscriptions) {\n        // Resume from last known LSN\n        const resumeOptions = {\n          ...options,\n          resumeFrom: this.lastEventId ?? options.resumeFrom,\n        }\n\n        try {\n          await this.subscribe(subscriptionId, table, schema, resumeOptions)\n        } catch (error) {\n          this.errorHandler?.(subscriptionId, error instanceof Error ? error : new Error(String(error)))\n        }\n      }\n    } catch {\n      // Schedule another reconnect\n      if (this.shouldReconnect) {\n        this.scheduleReconnect()\n      }\n    }\n  }\n\n  /**\n   * Reject all pending requests\n   */\n  private rejectAllPending(error: Error): void {\n    for (const pending of this.pendingSubscriptions.values()) {\n      clearTimeout(pending.timeout)\n      pending.reject(error)\n    }\n    this.pendingSubscriptions.clear()\n\n    for (const pending of this.pendingUnsubscriptions.values()) {\n      clearTimeout(pending.timeout)\n      pending.reject(error)\n    }\n    this.pendingUnsubscriptions.clear()\n\n    if (this.pendingAuth) {\n      clearTimeout(this.pendingAuth.timeout)\n      this.pendingAuth.reject(error)\n      this.pendingAuth = null\n    }\n  }\n}\n\n/**\n * Create a CDC WebSocket transport\n */\nexport function createCdcWsTransport(config: CDCWsTransportConfig): CDCWsTransport {\n  return new CDCWsTransport(config)\n}\n","/**\n * CDC SSE (Server-Sent Events) Transport for postgres.do\n *\n * Provides HTTP-based change data capture streaming via SSE:\n * - Works in environments where WebSocket is blocked\n * - Uses standard EventSource/fetch with streaming body\n * - Automatic reconnection with Last-Event-ID header\n * - LSN-based resumption for reliable delivery\n *\n * Performance optimizations:\n * - Event batching for high-throughput scenarios\n * - Adaptive heartbeat intervals based on activity\n * - Reusable TextDecoder for memory efficiency\n * - Exponential backoff with jitter for reconnection\n * - Compression support via Accept-Encoding\n */\n\nimport type {\n  Row,\n  CDCChangeEvent,\n  CDCTransport,\n  CDCSubscriptionOptions,\n  CDCSseTransportConfig,\n  CDCOperation,\n} from '../types'\nimport { ConnectionError } from '../types'\n\n/**\n * SSE event types for CDC\n */\ntype SseEventType = 'insert' | 'update' | 'delete' | 'truncate' | 'begin' | 'commit' | 'keepalive' | 'error' | 'subscribe_result' | 'unsubscribe_result'\n\n/**\n * SSE event data structure\n */\ninterface SseEventData {\n  type: SseEventType\n  subscriptionId?: string\n  table?: string\n  schema?: string\n  data?: Row\n  old?: Row\n  new?: Row\n  changedColumns?: string[]\n  xid?: number\n  isLastInTransaction?: boolean\n  success?: boolean\n  error?: string\n  message?: string\n  code?: string\n}\n\n/**\n * Batched event for high-throughput delivery\n */\ninterface BatchedEvent {\n  subscriptionId: string\n  event: CDCChangeEvent\n  timestamp: number\n}\n\n/**\n * Update event data with old and new row values\n */\ninterface UpdateEventData {\n  old?: Row\n  new?: Row\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULTS = {\n  retryMs: 3000,\n  connectTimeout: 10000,\n  maxReconnectAttempts: 10,\n  // Batching defaults\n  batchSize: 100,\n  batchTimeoutMs: 50,\n  // Adaptive heartbeat defaults\n  minHeartbeatMs: 5000,\n  maxHeartbeatMs: 60000,\n  heartbeatScaleFactor: 1.5,\n  // Memory optimization\n  maxBufferSize: 64 * 1024, // 64KB buffer limit\n}\n\n/**\n * Extended SSE transport configuration with optimization options\n */\nexport interface CDCSseTransportOptimizedConfig extends CDCSseTransportConfig {\n  /** Enable event batching for high-throughput scenarios */\n  enableBatching?: boolean\n  /** Maximum events to batch before flushing */\n  batchSize?: number\n  /** Maximum time to wait before flushing batch (ms) */\n  batchTimeoutMs?: number\n  /** Enable compression (gzip/deflate) if server supports it */\n  enableCompression?: boolean\n  /** Enable adaptive heartbeat intervals */\n  adaptiveHeartbeat?: boolean\n  /** Minimum heartbeat interval (ms) */\n  minHeartbeatMs?: number\n  /** Maximum heartbeat interval (ms) */\n  maxHeartbeatMs?: number\n  /** Maximum buffer size before applying backpressure (bytes) */\n  maxBufferSize?: number\n}\n\n/**\n * CDC SSE Transport implementation with streaming optimizations\n */\nexport class CDCSseTransport implements CDCTransport {\n  private config: {\n    url: string\n    apiKey?: string\n    resumeFrom?: string\n    retryMs: number\n    fetch?: typeof fetch\n    headers?: Record<string, string>\n  }\n  private fetchImpl: typeof fetch\n  private connected = false\n  private lastEventId: string | null = null\n  private shouldReconnect = true\n  private reconnectAttempt = 0\n  private reconnectTimer: ReturnType<typeof setTimeout> | null = null\n  private abortController: AbortController | null = null\n\n  // Event handlers\n  private eventHandler: ((subscriptionId: string, event: CDCChangeEvent) => void) | null = null\n  private errorHandler: ((subscriptionId: string, error: Error) => void) | null = null\n  private reconnectHandler: ((attempt: number, lastLsn: string | undefined) => void) | null = null\n  private closeHandler: (() => void) | null = null\n\n  // Active subscriptions for URL construction\n  private activeSubscriptions = new Map<string, {\n    table: string\n    schema: string\n    options: CDCSubscriptionOptions\n  }>()\n\n  // Pending subscription/unsubscription requests\n  private pendingSubscriptions = new Map<string, {\n    resolve: () => void\n    reject: (error: Error) => void\n  }>()\n  private pendingUnsubscriptions = new Map<string, {\n    resolve: () => void\n    reject: (error: Error) => void\n  }>()\n\n  // ========== Streaming Optimizations ==========\n\n  // Reusable TextDecoder for memory efficiency\n  private readonly decoder = new TextDecoder()\n\n  // Event batching state\n  private enableBatching: boolean\n  private batchSize: number\n  private batchTimeoutMs: number\n  private eventBatch: BatchedEvent[] = []\n  private batchTimer: ReturnType<typeof setTimeout> | null = null\n\n  // Adaptive heartbeat state\n  private adaptiveHeartbeat: boolean\n  private minHeartbeatMs: number\n  private maxHeartbeatMs: number\n  private currentHeartbeatMs: number\n  private lastEventTime = 0\n  private eventRateWindow: number[] = []\n  private heartbeatTimer: ReturnType<typeof setInterval> | null = null\n\n  // Buffer management for backpressure\n  private maxBufferSize: number\n  private currentBufferSize = 0\n\n  // Compression support\n  private enableCompression: boolean\n\n  // Performance metrics\n  private metrics = {\n    eventsReceived: 0,\n    eventsBatched: 0,\n    batchesFlushed: 0,\n    reconnections: 0,\n    bytesReceived: 0,\n  }\n\n  constructor(config: CDCSseTransportConfig | CDCSseTransportOptimizedConfig) {\n    const optimizedConfig = config as CDCSseTransportOptimizedConfig\n    this.config = {\n      url: config.url,\n      retryMs: config.retryMs ?? DEFAULTS.retryMs,\n    }\n    if (config.apiKey !== undefined) {\n      this.config.apiKey = config.apiKey\n    }\n    if (config.resumeFrom !== undefined) {\n      this.config.resumeFrom = config.resumeFrom\n    }\n    if (config.fetch !== undefined) {\n      this.config.fetch = config.fetch\n    }\n    if (config.headers !== undefined) {\n      this.config.headers = config.headers\n    }\n    this.fetchImpl = config.fetch || globalThis.fetch\n    this.lastEventId = config.resumeFrom ?? null\n\n    // Initialize optimization settings\n    this.enableBatching = optimizedConfig.enableBatching ?? false\n    this.batchSize = optimizedConfig.batchSize ?? DEFAULTS.batchSize\n    this.batchTimeoutMs = optimizedConfig.batchTimeoutMs ?? DEFAULTS.batchTimeoutMs\n    this.enableCompression = optimizedConfig.enableCompression ?? true\n    this.adaptiveHeartbeat = optimizedConfig.adaptiveHeartbeat ?? true\n    this.minHeartbeatMs = optimizedConfig.minHeartbeatMs ?? DEFAULTS.minHeartbeatMs\n    this.maxHeartbeatMs = optimizedConfig.maxHeartbeatMs ?? DEFAULTS.maxHeartbeatMs\n    this.currentHeartbeatMs = this.minHeartbeatMs\n    this.maxBufferSize = optimizedConfig.maxBufferSize ?? DEFAULTS.maxBufferSize\n  }\n\n  /**\n   * Connect to the CDC stream\n   */\n  async connect(): Promise<void> {\n    if (this.connected) {\n      return\n    }\n\n    this.shouldReconnect = true\n    this.abortController = new AbortController()\n\n    await this._connect()\n  }\n\n  /**\n   * Internal connect implementation with optimized headers\n   */\n  private async _connect(): Promise<void> {\n    const headers: Record<string, string> = {\n      Accept: 'text/event-stream',\n      'Cache-Control': 'no-cache',\n      // Keep-alive connection for persistent streaming\n      Connection: 'keep-alive',\n      ...this.config.headers,\n    }\n\n    // Request compression if enabled\n    if (this.enableCompression) {\n      headers['Accept-Encoding'] = 'gzip, deflate'\n    }\n\n    if (this.config.apiKey) {\n      headers['Authorization'] = `Bearer ${this.config.apiKey}`\n    }\n\n    if (this.lastEventId) {\n      headers['Last-Event-ID'] = this.lastEventId\n    }\n\n    // Build URL with subscription filters\n    const url = this.buildSubscriptionUrl()\n\n    try {\n      const requestInit: RequestInit = {\n        method: 'GET',\n        headers,\n        keepalive: true,\n      }\n      if (this.abortController?.signal) {\n        requestInit.signal = this.abortController.signal\n      }\n      const response = await this.fetchImpl(url, requestInit)\n\n      if (!response.ok) {\n        const errorBody = await response.text().catch(() => '')\n        throw new ConnectionError(`SSE connection failed: ${response.status} ${response.statusText}${errorBody ? ` - ${errorBody}` : ''}`)\n      }\n\n      const contentType = response.headers.get('Content-Type')\n      if (!contentType || !contentType.includes('text/event-stream')) {\n        throw new ConnectionError(`Invalid Content-Type: expected text/event-stream, got ${contentType}`)\n      }\n\n      this.connected = true\n      this.reconnectAttempt = 0\n\n      // Resolve any pending subscriptions since SSE subscriptions are URL-based\n      for (const [subscriptionId, { resolve }] of this.pendingSubscriptions) {\n        resolve()\n        this.pendingSubscriptions.delete(subscriptionId)\n      }\n\n      // Process the stream\n      await this.processStream(response)\n    } catch (error) {\n      if (error instanceof Error && error.name === 'AbortError') {\n        // Intentional abort - don't reconnect\n        return\n      }\n\n      // Reject pending subscriptions on error\n      for (const [subscriptionId, { reject }] of this.pendingSubscriptions) {\n        reject(error instanceof Error ? error : new Error(String(error)))\n        this.pendingSubscriptions.delete(subscriptionId)\n      }\n\n      throw error\n    }\n  }\n\n  /**\n   * Build URL with subscription parameters\n   */\n  private buildSubscriptionUrl(): string {\n    const url = new URL(this.config.url)\n\n    // Add table filter if there are active subscriptions\n    const tables = Array.from(this.activeSubscriptions.values()).map(s => s.table)\n    if (tables.length > 0) {\n      url.searchParams.set('tables', tables.join(','))\n    }\n\n    // Add schema filter\n    const schemas = new Set(Array.from(this.activeSubscriptions.values()).map(s => s.schema))\n    if (schemas.size > 0) {\n      url.searchParams.set('schemas', Array.from(schemas).join(','))\n    }\n\n    // Add subscription IDs\n    const subscriptionIds = Array.from(this.activeSubscriptions.keys())\n    if (subscriptionIds.length > 0) {\n      url.searchParams.set('subscriptionIds', subscriptionIds.join(','))\n    }\n\n    // Add common options from first subscription\n    const firstSub = Array.from(this.activeSubscriptions.values())[0]\n    if (firstSub) {\n      if (firstSub.options.events) {\n        url.searchParams.set('events', firstSub.options.events.join(','))\n      }\n      if (firstSub.options.filter) {\n        url.searchParams.set('filter', firstSub.options.filter)\n      }\n      if (firstSub.options.includeOldRow) {\n        url.searchParams.set('includeOldRow', 'true')\n      }\n      if (firstSub.options.trackChangedColumns) {\n        url.searchParams.set('trackChangedColumns', 'true')\n      }\n      if (firstSub.options.batchSize) {\n        url.searchParams.set('batchSize', String(firstSub.options.batchSize))\n      }\n    }\n\n    return url.toString()\n  }\n\n  /**\n   * Process the SSE stream with optimized buffering and memory management\n   */\n  private async processStream(response: Response): Promise<void> {\n    if (!response.body) {\n      throw new ConnectionError('Response body is null')\n    }\n\n    const reader = response.body.getReader()\n    let buffer = ''\n\n    // Start adaptive heartbeat monitoring if enabled\n    if (this.adaptiveHeartbeat) {\n      this.startHeartbeatMonitor()\n    }\n\n    try {\n      while (true) {\n        const { done, value } = await reader.read()\n\n        if (done) {\n          // Stream ended - flush any remaining batched events\n          this.flushEventBatch()\n          this.stopHeartbeatMonitor()\n\n          // Stream ended - schedule reconnect\n          this.connected = false\n          if (this.shouldReconnect) {\n            this.scheduleReconnect()\n          }\n          return\n        }\n\n        // Track bytes received for metrics\n        if (value) {\n          this.metrics.bytesReceived += value.length\n          this.currentBufferSize += value.length\n        }\n\n        // Use reusable decoder for memory efficiency\n        buffer += this.decoder.decode(value, { stream: true })\n\n        // Apply backpressure if buffer is too large\n        if (this.currentBufferSize > this.maxBufferSize) {\n          // Process events immediately to reduce memory pressure\n          await this.processBufferWithBackpressure(buffer)\n          buffer = ''\n          this.currentBufferSize = 0\n          continue\n        }\n\n        // Process complete events (separated by double newline)\n        const events = buffer.split('\\n\\n')\n        buffer = events.pop() || '' // Keep incomplete event in buffer\n\n        // Update current buffer size estimate\n        this.currentBufferSize = buffer.length\n\n        for (const eventText of events) {\n          if (eventText.trim()) {\n            this.parseAndHandleEvent(eventText)\n          }\n        }\n      }\n    } catch (error) {\n      this.connected = false\n      this.flushEventBatch()\n      this.stopHeartbeatMonitor()\n\n      if (error instanceof Error && error.name === 'AbortError') {\n        // Intentional abort\n        return\n      }\n\n      // Emit error and schedule reconnect\n      for (const subscriptionId of this.activeSubscriptions.keys()) {\n        this.errorHandler?.(subscriptionId, error instanceof Error ? error : new Error(String(error)))\n      }\n\n      if (this.shouldReconnect) {\n        this.scheduleReconnect()\n      }\n    }\n  }\n\n  /**\n   * Process buffer when under backpressure - yields to event loop\n   */\n  private async processBufferWithBackpressure(buffer: string): Promise<void> {\n    const events = buffer.split('\\n\\n')\n\n    for (let i = 0; i < events.length; i++) {\n      const eventText = events[i]\n      if (eventText && eventText.trim()) {\n        this.parseAndHandleEvent(eventText)\n      }\n\n      // Yield to event loop every 50 events to prevent blocking\n      if (i > 0 && i % 50 === 0) {\n        await new Promise(resolve => setTimeout(resolve, 0))\n      }\n    }\n  }\n\n  /**\n   * Parse and handle an SSE event\n   */\n  private parseAndHandleEvent(eventText: string): void {\n    let id: string | undefined\n    let eventType: string | undefined\n    let data: string | undefined\n\n    const lines = eventText.split('\\n')\n    for (const line of lines) {\n      if (line.startsWith(':')) {\n        // Comment line - ignore\n        continue\n      }\n\n      const colonIndex = line.indexOf(':')\n      if (colonIndex === -1) {\n        continue\n      }\n\n      const field = line.substring(0, colonIndex)\n      // Skip the space after colon if present\n      const value = line.substring(colonIndex + 1).trimStart()\n\n      switch (field) {\n        case 'id':\n          id = value\n          break\n        case 'event':\n          eventType = value\n          break\n        case 'data':\n          data = data ? data + '\\n' + value : value\n          break\n        case 'retry': {\n          const retryMs = parseInt(value, 10)\n          if (!isNaN(retryMs)) {\n            this.config.retryMs = retryMs\n          }\n          break\n        }\n      }\n    }\n\n    // Update last event ID\n    if (id) {\n      this.lastEventId = id\n    }\n\n    if (!data) {\n      return\n    }\n\n    // Parse data JSON\n    let eventData: SseEventData\n    try {\n      eventData = JSON.parse(data)\n    } catch (error) {\n      // Emit parse error\n      for (const subscriptionId of this.activeSubscriptions.keys()) {\n        this.errorHandler?.(subscriptionId, new Error(`Failed to parse SSE event data: ${error instanceof Error ? error.message : String(error)}`))\n      }\n      return\n    }\n\n    // Handle different event types\n    this.handleParsedEvent(id, eventType || eventData.type, eventData)\n  }\n\n  /**\n   * Handle a parsed event with optional batching\n   */\n  private handleParsedEvent(id: string | undefined, eventType: string, eventData: SseEventData): void {\n    const subscriptionId = eventData.subscriptionId || Array.from(this.activeSubscriptions.keys())[0]\n\n    // Update event timing for adaptive heartbeat\n    this.lastEventTime = Date.now()\n    this.metrics.eventsReceived++\n\n    switch (eventType) {\n      case 'insert':\n      case 'update':\n      case 'delete':\n      case 'truncate': {\n        if (!subscriptionId) return\n\n        const changeEvent: CDCChangeEvent = {\n          id: id || `${Date.now()}-${Math.random()}`,\n          lsn: id || '',\n          operation: eventType.toUpperCase() as CDCOperation,\n          table: eventData.table || '',\n          schema: eventData.schema || 'public',\n          timestamp: new Date(),\n          xid: eventData.xid || 0,\n          isLastInTransaction: eventData.isLastInTransaction || false,\n        }\n\n        if (eventType === 'update' && eventData.data) {\n          const updateData = eventData.data as UpdateEventData\n          changeEvent.oldRow = updateData.old ?? eventData.old\n          changeEvent.newRow = updateData.new ?? eventData.new\n        } else if (eventType === 'insert') {\n          changeEvent.newRow = eventData.data\n        } else if (eventType === 'delete') {\n          changeEvent.oldRow = eventData.data\n        }\n\n        if (eventData.changedColumns) {\n          changeEvent.changedColumns = eventData.changedColumns\n        }\n\n        // Use batching if enabled, otherwise emit immediately\n        if (this.enableBatching) {\n          this.addToBatch(subscriptionId, changeEvent)\n        } else {\n          this.eventHandler?.(subscriptionId, changeEvent)\n        }\n        break\n      }\n\n      case 'keepalive':\n        // Update heartbeat timing - used for adaptive intervals\n        this.updateHeartbeatFromServer()\n        break\n\n      case 'begin':\n      case 'commit':\n        // Transaction boundaries - flush batch on commit for consistency\n        if (eventType === 'commit' && this.enableBatching) {\n          this.flushEventBatch()\n        }\n        break\n\n      case 'error':\n        if (subscriptionId) {\n          this.errorHandler?.(subscriptionId, new Error(eventData.message || eventData.error || 'Unknown error'))\n        }\n        break\n\n      case 'subscribe_result':\n        if (eventData.subscriptionId) {\n          const pending = this.pendingSubscriptions.get(eventData.subscriptionId)\n          if (pending) {\n            if (eventData.success) {\n              pending.resolve()\n            } else {\n              pending.reject(new Error(eventData.error || 'Subscription failed'))\n            }\n            this.pendingSubscriptions.delete(eventData.subscriptionId)\n          }\n        }\n        break\n\n      case 'unsubscribe_result':\n        if (eventData.subscriptionId) {\n          const pending = this.pendingUnsubscriptions.get(eventData.subscriptionId)\n          if (pending) {\n            pending.resolve()\n            this.pendingUnsubscriptions.delete(eventData.subscriptionId)\n          }\n        }\n        break\n    }\n  }\n\n  // ========== Event Batching ==========\n\n  /**\n   * Add event to batch for coalesced delivery\n   */\n  private addToBatch(subscriptionId: string, event: CDCChangeEvent): void {\n    this.eventBatch.push({\n      subscriptionId,\n      event,\n      timestamp: Date.now(),\n    })\n    this.metrics.eventsBatched++\n\n    // Flush if batch is full\n    if (this.eventBatch.length >= this.batchSize) {\n      this.flushEventBatch()\n      return\n    }\n\n    // Start batch timer if not already running\n    if (!this.batchTimer) {\n      this.batchTimer = setTimeout(() => {\n        this.flushEventBatch()\n      }, this.batchTimeoutMs)\n    }\n  }\n\n  /**\n   * Flush all batched events to handlers\n   */\n  private flushEventBatch(): void {\n    if (this.batchTimer) {\n      clearTimeout(this.batchTimer)\n      this.batchTimer = null\n    }\n\n    if (this.eventBatch.length === 0) {\n      return\n    }\n\n    // Group events by subscription for efficient delivery\n    const eventsBySubscription = new Map<string, CDCChangeEvent[]>()\n\n    for (const { subscriptionId, event } of this.eventBatch) {\n      const events = eventsBySubscription.get(subscriptionId) || []\n      events.push(event)\n      eventsBySubscription.set(subscriptionId, events)\n    }\n\n    // Emit events grouped by subscription\n    for (const [subscriptionId, events] of eventsBySubscription) {\n      for (const event of events) {\n        this.eventHandler?.(subscriptionId, event)\n      }\n    }\n\n    this.metrics.batchesFlushed++\n    this.eventBatch = []\n  }\n\n  // ========== Adaptive Heartbeat ==========\n\n  /**\n   * Start monitoring connection health with adaptive intervals\n   */\n  private startHeartbeatMonitor(): void {\n    if (!this.adaptiveHeartbeat) return\n\n    this.stopHeartbeatMonitor()\n    this.lastEventTime = Date.now()\n    this.eventRateWindow = []\n\n    this.heartbeatTimer = setInterval(() => {\n      this.checkConnectionHealth()\n    }, this.currentHeartbeatMs)\n  }\n\n  /**\n   * Stop the heartbeat monitor\n   */\n  private stopHeartbeatMonitor(): void {\n    if (this.heartbeatTimer) {\n      clearInterval(this.heartbeatTimer)\n      this.heartbeatTimer = null\n    }\n  }\n\n  /**\n   * Check connection health and adjust heartbeat interval\n   */\n  private checkConnectionHealth(): void {\n    const now = Date.now()\n    const timeSinceLastEvent = now - this.lastEventTime\n\n    // If no events for 3x the current heartbeat interval, connection may be stale\n    if (timeSinceLastEvent > this.currentHeartbeatMs * 3) {\n      // Emit warning - connection might be stale\n      for (const subscriptionId of this.activeSubscriptions.keys()) {\n        this.errorHandler?.(subscriptionId, new Error('Connection appears stale - no events received'))\n      }\n    }\n\n    // Adapt heartbeat interval based on event rate\n    this.adaptHeartbeatInterval()\n  }\n\n  /**\n   * Adapt heartbeat interval based on observed event rate\n   */\n  private adaptHeartbeatInterval(): void {\n    // Track event rate in sliding window (last 10 samples)\n    this.eventRateWindow.push(this.metrics.eventsReceived)\n    if (this.eventRateWindow.length > 10) {\n      this.eventRateWindow.shift()\n    }\n\n    // Calculate events per second\n    const recentEvents = this.eventRateWindow.length > 1\n      ? this.eventRateWindow[this.eventRateWindow.length - 1]! - this.eventRateWindow[0]!\n      : 0\n    const eventsPerSecond = recentEvents / (this.eventRateWindow.length * (this.currentHeartbeatMs / 1000))\n\n    // High event rate = shorter heartbeat (faster detection of issues)\n    // Low event rate = longer heartbeat (reduce overhead)\n    let newInterval: number\n\n    if (eventsPerSecond > 100) {\n      // High throughput - use minimum interval\n      newInterval = this.minHeartbeatMs\n    } else if (eventsPerSecond < 1) {\n      // Low throughput - increase interval\n      newInterval = Math.min(\n        this.currentHeartbeatMs * DEFAULTS.heartbeatScaleFactor,\n        this.maxHeartbeatMs\n      )\n    } else {\n      // Moderate throughput - decrease interval slightly\n      newInterval = Math.max(\n        this.currentHeartbeatMs / DEFAULTS.heartbeatScaleFactor,\n        this.minHeartbeatMs\n      )\n    }\n\n    // Update interval if changed significantly (>10% difference)\n    if (Math.abs(newInterval - this.currentHeartbeatMs) / this.currentHeartbeatMs > 0.1) {\n      this.currentHeartbeatMs = Math.round(newInterval)\n      this.stopHeartbeatMonitor()\n      this.startHeartbeatMonitor()\n    }\n  }\n\n  /**\n   * Update heartbeat timing when server sends keepalive\n   */\n  private updateHeartbeatFromServer(): void {\n    this.lastEventTime = Date.now()\n  }\n\n  /**\n   * Schedule reconnection with exponential backoff and jitter\n   *\n   * Uses a decorrelated jitter algorithm for optimal reconnection behavior:\n   * - Exponential backoff: delay = retryMs * 1.5^attempt\n   * - Jitter: adds random variation to prevent thundering herd\n   * - Capped at maxReconnectDelay to prevent excessive waits\n   */\n  private scheduleReconnect(): void {\n    if (!this.shouldReconnect) {\n      return\n    }\n\n    this.reconnectAttempt++\n    this.metrics.reconnections++\n\n    if (this.reconnectAttempt > DEFAULTS.maxReconnectAttempts) {\n      const error = new ConnectionError('Max reconnection attempts exceeded')\n      for (const subscriptionId of this.activeSubscriptions.keys()) {\n        this.errorHandler?.(subscriptionId, error)\n      }\n      this.closeHandler?.()\n      return\n    }\n\n    // Calculate base delay with exponential backoff\n    const baseDelay = this.config.retryMs * Math.pow(1.5, this.reconnectAttempt - 1)\n\n    // Add jitter: random value between 0 and 50% of base delay\n    // This helps prevent thundering herd when many clients reconnect\n    const jitter = Math.random() * baseDelay * 0.5\n\n    // Final delay with cap at 60 seconds\n    const maxDelay = 60000\n    const delay = Math.min(baseDelay + jitter, maxDelay)\n\n    this.reconnectTimer = setTimeout(async () => {\n      this.reconnectHandler?.(this.reconnectAttempt, this.lastEventId ?? undefined)\n\n      try {\n        this.abortController = new AbortController()\n        await this._connect()\n      } catch (error) {\n        // Will schedule another reconnect\n        if (this.shouldReconnect) {\n          this.scheduleReconnect()\n        }\n      }\n    }, delay)\n  }\n\n  /**\n   * Disconnect from the CDC stream\n   */\n  async disconnect(): Promise<void> {\n    this.shouldReconnect = false\n\n    // Clean up all timers\n    if (this.reconnectTimer) {\n      clearTimeout(this.reconnectTimer)\n      this.reconnectTimer = null\n    }\n\n    if (this.batchTimer) {\n      clearTimeout(this.batchTimer)\n      this.batchTimer = null\n    }\n\n    this.stopHeartbeatMonitor()\n\n    // Flush any remaining batched events before disconnecting\n    this.flushEventBatch()\n\n    if (this.abortController) {\n      this.abortController.abort()\n      this.abortController = null\n    }\n\n    this.connected = false\n    this.activeSubscriptions.clear()\n\n    // Reset buffer state\n    this.currentBufferSize = 0\n\n    // Reject all pending requests\n    for (const [, { reject }] of this.pendingSubscriptions) {\n      reject(new ConnectionError('Connection closed'))\n    }\n    this.pendingSubscriptions.clear()\n\n    for (const [, { resolve }] of this.pendingUnsubscriptions) {\n      resolve() // Unsubscriptions resolve on disconnect\n    }\n    this.pendingUnsubscriptions.clear()\n\n    this.closeHandler?.()\n  }\n\n  /**\n   * Get transport performance metrics\n   */\n  getMetrics(): Readonly<typeof this.metrics> {\n    return { ...this.metrics }\n  }\n\n  /**\n   * Reset performance metrics\n   */\n  resetMetrics(): void {\n    this.metrics = {\n      eventsReceived: 0,\n      eventsBatched: 0,\n      batchesFlushed: 0,\n      reconnections: 0,\n      bytesReceived: 0,\n    }\n  }\n\n  /**\n   * Get current heartbeat interval (useful for monitoring)\n   */\n  getCurrentHeartbeatMs(): number {\n    return this.currentHeartbeatMs\n  }\n\n  /**\n   * Check if connected\n   */\n  isConnected(): boolean {\n    return this.connected\n  }\n\n  /**\n   * Get the last event ID received\n   */\n  getLastEventId(): string | null {\n    return this.lastEventId\n  }\n\n  /**\n   * Subscribe to a table\n   * For SSE, this adds to the subscription set and reconnects\n   */\n  async subscribe(\n    subscriptionId: string,\n    table: string,\n    schema: string,\n    options: CDCSubscriptionOptions\n  ): Promise<void> {\n    // Store the subscription\n    this.activeSubscriptions.set(subscriptionId, { table, schema, options })\n\n    // If already connected, need to reconnect with new subscription\n    if (this.connected) {\n      // Create a pending subscription promise that resolves after reconnect\n      const promise = new Promise<void>((resolve, reject) => {\n        this.pendingSubscriptions.set(subscriptionId, { resolve, reject })\n      })\n\n      // Reconnect with updated subscriptions\n      if (this.abortController) {\n        this.abortController.abort()\n      }\n      this.abortController = new AbortController()\n      this._connect().catch(() => {\n        // Error handled in _connect\n      })\n\n      return promise\n    } else {\n      // Not connected yet - subscription will be included when connecting\n      return new Promise<void>((resolve, reject) => {\n        this.pendingSubscriptions.set(subscriptionId, { resolve, reject })\n        resolve() // Resolve immediately for pre-connect subscriptions\n      })\n    }\n  }\n\n  /**\n   * Unsubscribe from a subscription\n   * For SSE, this removes from the subscription set and reconnects\n   */\n  async unsubscribe(subscriptionId: string): Promise<void> {\n    this.activeSubscriptions.delete(subscriptionId)\n\n    // If no more subscriptions, just disconnect\n    if (this.activeSubscriptions.size === 0) {\n      await this.disconnect()\n      return\n    }\n\n    // Otherwise reconnect with remaining subscriptions\n    if (this.connected) {\n      return new Promise<void>((resolve, reject) => {\n        this.pendingUnsubscriptions.set(subscriptionId, { resolve, reject })\n\n        // Reconnect with updated subscriptions\n        if (this.abortController) {\n          this.abortController.abort()\n        }\n        this.abortController = new AbortController()\n        this._connect().catch(() => {\n          // Error handled in _connect\n        })\n\n        // Resolve immediately for SSE since unsubscription is URL-based\n        setTimeout(() => {\n          const pending = this.pendingUnsubscriptions.get(subscriptionId)\n          if (pending) {\n            pending.resolve()\n            this.pendingUnsubscriptions.delete(subscriptionId)\n          }\n        }, 100)\n      })\n    }\n  }\n\n  /**\n   * Set the event handler\n   */\n  onEvent(handler: (subscriptionId: string, event: CDCChangeEvent) => void): void {\n    this.eventHandler = handler\n  }\n\n  /**\n   * Set the error handler\n   */\n  onError(handler: (subscriptionId: string, error: Error) => void): void {\n    this.errorHandler = handler\n  }\n\n  /**\n   * Set the reconnect handler\n   */\n  onReconnect(handler: (attempt: number, lastLsn: string | undefined) => void): void {\n    this.reconnectHandler = handler\n  }\n\n  /**\n   * Set the close handler\n   */\n  onClose(handler: () => void): void {\n    this.closeHandler = handler\n  }\n}\n\n/**\n * Create a CDC SSE transport\n */\nexport function createCdcSseTransport(config: CDCSseTransportConfig): CDCSseTransport {\n  return new CDCSseTransport(config)\n}\n","/**\n * Query Middleware Layer for postgres.do\n *\n * Provides a middleware chain pattern for intercepting and transforming queries.\n * Enables cross-cutting concerns like logging, metrics, rate limiting, and tracing.\n *\n * ## Architecture\n *\n * Middleware functions follow an \"onion\" pattern where each middleware wraps\n * the next one in the chain. Execution flows inward through all middlewares,\n * reaches the executor, then flows outward back through the middlewares.\n *\n * ```\n * Request → [Middleware A] → [Middleware B] → [Executor]\n * Response ← [Middleware A] ← [Middleware B] ←\n * ```\n *\n * ## Creating Custom Middleware\n *\n * A middleware is an async function that receives a request and a `next` function.\n * Call `next()` to proceed to the next middleware or executor. You can:\n *\n * - Modify the request before calling `next()`\n * - Modify the response after calling `next()`\n * - Short-circuit by returning a response without calling `next()`\n * - Handle errors by wrapping `next()` in try/catch\n *\n * @example Basic usage\n * ```typescript\n * import postgres from 'postgres.do'\n * import { loggingMiddleware, metricsMiddleware } from 'postgres.do/middleware'\n *\n * const sql = postgres('postgres://db.postgres.do/mydb')\n *   .use(loggingMiddleware({ level: 'debug' }))\n *   .use(metricsMiddleware({ onMetric: console.log }))\n *\n * // All queries now flow through the middleware chain\n * const users = await sql`SELECT * FROM users`\n * ```\n *\n * @example Custom middleware\n * ```typescript\n * import type { QueryMiddleware } from 'postgres.do/middleware'\n *\n * const myMiddleware: QueryMiddleware = async (request, next) => {\n *   console.log('Before query:', request.sql)\n *   const response = await next()\n *   console.log('After query:', response.durationMs, 'ms')\n *   return response\n * }\n * ```\n *\n * @module middleware\n */\n\nimport type { QueryResult, Row } from './types'\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Maximum length for query strings in metrics to prevent memory bloat.\n * Queries longer than this will be truncated.\n */\nconst METRICS_QUERY_TRUNCATE_LENGTH = 100\n\n/**\n * Milliseconds per second for rate limit time calculations.\n */\nconst MS_PER_SECOND = 1000\n\n/**\n * Default maximum number of retry attempts for retryMiddleware.\n */\nconst DEFAULT_MAX_RETRIES = 3\n\n/**\n * Default base delay in milliseconds between retry attempts.\n */\nconst DEFAULT_RETRY_BASE_DELAY_MS = 100\n\n/**\n * Default maximum delay in milliseconds between retry attempts.\n * Used as an upper bound when exponential backoff is enabled.\n */\nconst DEFAULT_RETRY_MAX_DELAY_MS = 5000\n\n/**\n * Default histogram bucket boundaries in milliseconds for query duration metrics.\n * Based on typical web application latency percentiles.\n */\nconst DEFAULT_HISTOGRAM_BUCKETS = [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000]\n\n/**\n * Length of the random suffix in generated query IDs.\n */\nconst QUERY_ID_RANDOM_SUFFIX_LENGTH = 9\n\n/**\n * Start index for slicing the random portion of query IDs.\n */\nconst QUERY_ID_RANDOM_SLICE_START = 2\n\n/**\n * Length of span IDs generated for distributed tracing.\n */\nconst SPAN_ID_LENGTH = 10\n\n// ============================================================================\n// Core Types\n// ============================================================================\n\n/**\n * Query request passed to middleware.\n *\n * Contains all information about a query before execution.\n * Middleware can read and modify this object before passing to `next()`.\n *\n * @example\n * ```typescript\n * const middleware: QueryMiddleware = async (request, next) => {\n *   console.log('Query:', request.sql)\n *   console.log('Params:', request.params)\n *   console.log('Query ID:', request.queryId)\n *   return next()\n * }\n * ```\n */\nexport interface QueryRequest {\n  /** The SQL query string (with parameter placeholders) */\n  sql: string\n  /** Query parameters */\n  params: unknown[]\n  /** Timestamp when the query was initiated */\n  timestamp: number\n  /** Unique ID for this query (useful for tracing) */\n  queryId: string\n  /** Optional context passed through the middleware chain */\n  context?: Record<string, unknown>\n}\n\n/**\n * Query response returned from middleware.\n *\n * Contains the result of query execution along with timing and status information.\n * Middleware can modify this object before returning it to the caller.\n *\n * @example\n * ```typescript\n * const middleware: QueryMiddleware = async (request, next) => {\n *   const response = await next()\n *   if (!response.success) {\n *     console.error('Query failed:', response.error)\n *   }\n *   return response\n * }\n * ```\n */\nexport interface QueryResponse<T extends Row = Row> {\n  /** Query result */\n  result: QueryResult<T>\n  /** Duration in milliseconds */\n  durationMs: number\n  /** Was the query successful */\n  success: boolean\n  /** Error if query failed */\n  error?: Error\n  /** Optional metadata added by middleware */\n  metadata?: Record<string, unknown>\n}\n\n/**\n * Next function to call the next middleware in the chain.\n *\n * Calling `next()` invokes the next middleware in the chain, or the query\n * executor if this is the last middleware. Always returns a Promise that\n * resolves to a QueryResponse.\n *\n * @remarks\n * - You must call `next()` exactly once to continue the chain\n * - Not calling `next()` short-circuits the chain (useful for caching, auth)\n * - Calling `next()` multiple times may cause unexpected behavior\n */\nexport type NextFunction<T extends Row = Row> = () => Promise<QueryResponse<T>>\n\n/**\n * Query middleware function signature.\n *\n * Middleware functions receive a request and a `next` function, and must return\n * a Promise that resolves to a QueryResponse. This is the core type for building\n * custom middleware.\n *\n * @param request - The query request containing SQL, params, and context\n * @param next - Function to call the next middleware or executor\n * @returns The query response (possibly transformed)\n *\n * @example Simple logging middleware\n * ```typescript\n * const loggingMiddleware: QueryMiddleware = async (request, next) => {\n *   console.log('Query:', request.sql)\n *   const response = await next()\n *   console.log('Duration:', response.durationMs, 'ms')\n *   return response\n * }\n * ```\n *\n * @example Error handling middleware\n * ```typescript\n * const errorHandler: QueryMiddleware = async (request, next) => {\n *   try {\n *     return await next()\n *   } catch (error) {\n *     // Handle or transform the error\n *     return {\n *       result: { rows: [], rowCount: 0, fields: [], command: 'ERROR' },\n *       durationMs: 0,\n *       success: false,\n *       error: error instanceof Error ? error : new Error(String(error)),\n *     }\n *   }\n * }\n * ```\n */\nexport type QueryMiddleware<T extends Row = Row> = (\n  request: QueryRequest,\n  next: NextFunction<T>\n) => Promise<QueryResponse<T>>\n\n// ============================================================================\n// Core Functions\n// ============================================================================\n\n/**\n * Generate a unique query ID for tracing and logging.\n *\n * The ID format is `q_<timestamp>_<random>` where:\n * - `q_` is a fixed prefix for easy identification\n * - `<timestamp>` is the current time in base-36 encoding\n * - `<random>` is a random string for uniqueness within the same millisecond\n *\n * @returns A unique query identifier string\n *\n * @example\n * ```typescript\n * const queryId = generateQueryId()\n * // => \"q_lz4k8x_abc123d\"\n * ```\n */\nexport function generateQueryId(): string {\n  const timestamp = Date.now().toString(36)\n  const random = Math.random().toString(36).slice(QUERY_ID_RANDOM_SLICE_START, QUERY_ID_RANDOM_SUFFIX_LENGTH)\n  return `q_${timestamp}_${random}`\n}\n\n/**\n * Execute a query through a middleware chain.\n *\n * This is the core function that orchestrates middleware execution.\n * It builds a chain from the provided middlewares using a right-to-left\n * reduction, where each middleware wraps the next one.\n *\n * @param middlewares - Array of middleware functions to execute in order\n * @param request - The query request containing SQL, params, and context\n * @param executor - The final query executor function that runs the actual query\n * @returns The query response, possibly transformed by middlewares\n *\n * @remarks\n * - Middlewares execute in array order (first middleware runs first)\n * - Errors in the executor are caught and returned as failed responses\n * - Errors thrown by middleware propagate up and must be caught by the caller\n *\n * @example\n * ```typescript\n * const response = await executeWithMiddleware(\n *   [loggingMiddleware(), metricsMiddleware({ onMetric: console.log })],\n *   { sql: 'SELECT 1', params: [], timestamp: Date.now(), queryId: 'q_123' },\n *   async () => ({ rows: [{ id: 1 }], rowCount: 1, fields: [], command: 'SELECT' })\n * )\n * ```\n */\nexport async function executeWithMiddleware<T extends Row = Row>(\n  middlewares: QueryMiddleware<T>[],\n  request: QueryRequest,\n  executor: () => Promise<QueryResult<T>>\n): Promise<QueryResponse<T>> {\n  const startTime = Date.now()\n\n  // Build the middleware chain from right to left\n  // The last middleware calls the executor\n  const chain = middlewares.reduceRight<NextFunction<T>>(\n    (next, middleware) => {\n      return () => middleware(request, next)\n    },\n    // Base executor (innermost function)\n    async (): Promise<QueryResponse<T>> => {\n      try {\n        const result = await executor()\n        return {\n          result,\n          durationMs: Date.now() - startTime,\n          success: true,\n        }\n      } catch (error) {\n        return {\n          result: {\n            rows: [],\n            rowCount: 0,\n            fields: [],\n            command: 'ERROR',\n          },\n          durationMs: Date.now() - startTime,\n          success: false,\n          error: error instanceof Error ? error : new Error(String(error)),\n        }\n      }\n    }\n  )\n\n  // Execute the chain\n  return chain()\n}\n\n// ============================================================================\n// Built-in Middlewares\n// ============================================================================\n\n/**\n * Options for configuring the logging middleware.\n */\nexport interface LoggingMiddlewareOptions {\n  /** Log level: 'debug' | 'info' | 'warn' | 'error'. Defaults to 'info'. */\n  level?: 'debug' | 'info' | 'warn' | 'error'\n  /** Custom logger function. Defaults to console methods. */\n  logger?: (level: string, message: string, data?: Record<string, unknown>) => void\n  /** Whether to log query parameters (default: false for security) */\n  logParams?: boolean\n  /** Only log queries slower than this threshold (ms). Omit to log all queries. */\n  slowQueryThreshold?: number\n  /** Custom prefix for log messages. Defaults to '[postgres.do]'. */\n  prefix?: string\n}\n\n/**\n * Create a logging middleware for query observability.\n *\n * Logs query execution details including SQL, duration, row count, and errors.\n * By default, query parameters are not logged for security reasons.\n *\n * @param options - Configuration options for the logging middleware\n * @returns A middleware function that logs query information\n *\n * @example Basic usage\n * ```typescript\n * const sql = postgres()\n *   .use(loggingMiddleware({ level: 'info', logParams: false }))\n * ```\n *\n * @example Slow query logging\n * ```typescript\n * const sql = postgres()\n *   .use(loggingMiddleware({\n *     slowQueryThreshold: 100, // Only log queries taking > 100ms\n *     level: 'warn'\n *   }))\n * ```\n *\n * @example Custom logger\n * ```typescript\n * const sql = postgres()\n *   .use(loggingMiddleware({\n *     logger: (level, message, data) => {\n *       myLogger[level](message, data)\n *     }\n *   }))\n * ```\n */\nexport function loggingMiddleware(options: LoggingMiddlewareOptions = {}): QueryMiddleware {\n  const {\n    level = 'info',\n    logger = defaultLogger,\n    logParams = false,\n    slowQueryThreshold,\n    prefix = '[postgres.do]',\n  } = options\n\n  return async (request, next) => {\n    const response = await next()\n\n    // Skip logging if below slow query threshold\n    if (slowQueryThreshold !== undefined && response.durationMs < slowQueryThreshold) {\n      return response\n    }\n\n    const logData: Record<string, unknown> = {\n      queryId: request.queryId,\n      sql: request.sql,\n      durationMs: response.durationMs,\n      success: response.success,\n      rowCount: response.result.rowCount,\n    }\n\n    if (logParams) {\n      logData.params = request.params\n    }\n\n    if (!response.success && response.error) {\n      logData.error = response.error.message\n    }\n\n    const message = response.success\n      ? `${prefix} Query completed in ${response.durationMs}ms`\n      : `${prefix} Query failed after ${response.durationMs}ms: ${response.error?.message}`\n\n    logger(response.success ? level : 'error', message, logData)\n\n    return response\n  }\n}\n\n/**\n * Default console logger implementation.\n * Maps log levels to appropriate console methods.\n *\n * @internal\n */\nfunction defaultLogger(level: string, message: string, data?: Record<string, unknown>): void {\n  const logFn =\n    level === 'error'\n      ? console.error\n      : level === 'warn'\n        ? console.warn\n        : level === 'debug'\n          ? console.debug\n          : console.info\n\n  if (data) {\n    logFn(message, data)\n  } else {\n    logFn(message)\n  }\n}\n\n/**\n * Options for configuring the metrics middleware.\n */\nexport interface MetricsMiddlewareOptions {\n  /** Callback invoked for each metric event. Required. */\n  onMetric: (metric: QueryMetric) => void\n  /** Custom tags to add to all metrics. */\n  tags?: Record<string, string>\n  /** Whether to include histogram bucket information. Defaults to false. */\n  histogram?: boolean\n  /** Custom histogram bucket boundaries (ms). Defaults to standard latency percentiles. */\n  buckets?: number[]\n}\n\n/**\n * Query metric data emitted by the metrics middleware.\n *\n * Each query execution emits multiple metrics:\n * - `query_duration`: Time taken to execute the query (ms)\n * - `query_count`: Incremented for each query (value is always 1)\n * - `query_rows`: Number of rows returned\n * - `query_error`: Incremented for failed queries (value is always 1)\n */\nexport interface QueryMetric {\n  /** Metric type */\n  type: 'query_duration' | 'query_count' | 'query_error' | 'query_rows'\n  /** Metric value */\n  value: number\n  /** Query ID for correlation */\n  queryId: string\n  /** SQL query (truncated to prevent memory bloat) */\n  query: string\n  /** Whether the query succeeded */\n  success: boolean\n  /** Command type (SELECT, INSERT, UPDATE, DELETE, etc.) */\n  command: string\n  /** Timestamp when the metric was recorded */\n  timestamp: number\n  /** Custom tags */\n  tags?: Record<string, string>\n  /** Histogram bucket label (if enabled) */\n  bucket?: string\n}\n\n/**\n * Create a metrics middleware for query instrumentation.\n *\n * Emits metrics for query duration, count, row count, and errors.\n * Useful for monitoring, alerting, and performance analysis.\n *\n * @param options - Configuration options for the metrics middleware\n * @returns A middleware function that emits query metrics\n *\n * @example Basic usage\n * ```typescript\n * const metrics: QueryMetric[] = []\n * const sql = postgres()\n *   .use(metricsMiddleware({\n *     onMetric: (m) => metrics.push(m),\n *     tags: { service: 'api', env: 'production' }\n *   }))\n * ```\n *\n * @example With histogram buckets\n * ```typescript\n * const sql = postgres()\n *   .use(metricsMiddleware({\n *     onMetric: (m) => prometheus.observe(m.type, m.value, m.tags),\n *     histogram: true,\n *     buckets: [5, 10, 25, 50, 100, 250, 500, 1000]\n *   }))\n * ```\n */\nexport function metricsMiddleware(options: MetricsMiddlewareOptions): QueryMiddleware {\n  const {\n    onMetric,\n    tags = {},\n    histogram = false,\n    buckets = DEFAULT_HISTOGRAM_BUCKETS,\n  } = options\n\n  return async (request, next) => {\n    const response = await next()\n\n    const baseMetric = {\n      queryId: request.queryId,\n      query: request.sql.slice(0, METRICS_QUERY_TRUNCATE_LENGTH),\n      success: response.success,\n      command: response.result.command,\n      timestamp: Date.now(),\n      tags,\n    }\n\n    // Duration metric\n    const durationMetric: QueryMetric = {\n      ...baseMetric,\n      type: 'query_duration',\n      value: response.durationMs,\n    }\n\n    if (histogram) {\n      durationMetric.bucket = findBucket(response.durationMs, buckets)\n    }\n\n    onMetric(durationMetric)\n\n    // Count metric\n    onMetric({\n      ...baseMetric,\n      type: 'query_count',\n      value: 1,\n    })\n\n    // Row count metric\n    onMetric({\n      ...baseMetric,\n      type: 'query_rows',\n      value: response.result.rowCount,\n    })\n\n    // Error metric (if failed)\n    if (!response.success) {\n      onMetric({\n        ...baseMetric,\n        type: 'query_error',\n        value: 1,\n      })\n    }\n\n    return response\n  }\n}\n\n/**\n * Find the histogram bucket for a duration value.\n *\n * Returns a bucket label in the format `le_<value>` for Prometheus-style\n * histogram metrics. Values exceeding all buckets return `le_inf`.\n *\n * @internal\n */\nfunction findBucket(value: number, buckets: number[]): string {\n  for (const bucket of buckets) {\n    if (value <= bucket) {\n      return `le_${bucket}`\n    }\n  }\n  return 'le_inf'\n}\n\n/**\n * Options for configuring the rate limiting middleware.\n */\nexport interface RateLimitMiddlewareOptions {\n  /** Maximum queries allowed per window. Required. */\n  maxQueries: number\n  /** Window size in milliseconds. Required. */\n  windowMs: number\n  /** Function to determine the rate limit key (e.g., by user). Defaults to 'default'. */\n  keyFn?: (request: QueryRequest) => string\n  /** Callback invoked when rate limit is exceeded. */\n  onRateLimited?: (request: QueryRequest, remainingSeconds: number) => void\n}\n\n/**\n * Create a rate limiting middleware to prevent query abuse.\n *\n * Uses a sliding window algorithm to track query counts per key.\n * When the limit is exceeded, returns an error response with retry information.\n *\n * @param options - Configuration options for the rate limiting middleware\n * @returns A middleware function that enforces rate limits\n *\n * @example Basic usage\n * ```typescript\n * const sql = postgres()\n *   .use(rateLimitMiddleware({\n *     maxQueries: 100,\n *     windowMs: 60000, // 1 minute\n *   }))\n * ```\n *\n * @example Per-user rate limiting\n * ```typescript\n * const sql = postgres()\n *   .use(rateLimitMiddleware({\n *     maxQueries: 100,\n *     windowMs: 60000,\n *     keyFn: (req) => req.context?.userId as string || 'anonymous',\n *     onRateLimited: (req, remaining) => {\n *       console.warn(`Rate limited user ${req.context?.userId}, retry in ${remaining}s`)\n *     }\n *   }))\n * ```\n */\nexport function rateLimitMiddleware(options: RateLimitMiddlewareOptions): QueryMiddleware {\n  const { maxQueries, windowMs, keyFn = () => 'default', onRateLimited } = options\n\n  const windows = new Map<string, { count: number; resetAt: number }>()\n\n  return async (request, next) => {\n    const key = keyFn(request)\n    const now = Date.now()\n\n    let window = windows.get(key)\n    if (!window || now >= window.resetAt) {\n      window = { count: 0, resetAt: now + windowMs }\n      windows.set(key, window)\n    }\n\n    window.count++\n\n    if (window.count > maxQueries) {\n      const remainingSeconds = Math.ceil((window.resetAt - now) / MS_PER_SECOND)\n      onRateLimited?.(request, remainingSeconds)\n\n      return {\n        result: {\n          rows: [],\n          rowCount: 0,\n          fields: [],\n          command: 'ERROR',\n        },\n        durationMs: 0,\n        success: false,\n        error: new Error(`Rate limit exceeded. Try again in ${remainingSeconds} seconds.`),\n        metadata: { rateLimited: true, retryAfter: remainingSeconds },\n      }\n    }\n\n    return next()\n  }\n}\n\n/**\n * Options for configuring the tracing middleware.\n */\nexport interface TracingMiddlewareOptions {\n  /** Trace ID: a static string, generator function, or undefined to use context/auto-generate. */\n  traceId?: string | ((request: QueryRequest) => string)\n  /** Span ID generator function. Defaults to random base-36 string. */\n  spanId?: () => string\n  /** Callback invoked with trace data after each query. */\n  onTrace?: (trace: QueryTrace) => void\n}\n\n/**\n * Query trace data for distributed tracing.\n *\n * Compatible with OpenTelemetry and similar tracing systems.\n */\nexport interface QueryTrace {\n  /** Unique trace identifier (spans same trace across services) */\n  traceId: string\n  /** Unique span identifier for this query */\n  spanId: string\n  /** Parent span ID if this query is part of a larger operation */\n  parentSpanId?: string | undefined\n  /** Query identifier for correlation with other middleware */\n  queryId: string\n  /** SQL query string */\n  sql: string\n  /** Unix timestamp when query started */\n  startTime: number\n  /** Unix timestamp when query completed */\n  endTime: number\n  /** Query duration in milliseconds */\n  durationMs: number\n  /** Whether the query succeeded */\n  success: boolean\n  /** Error message if query failed */\n  error?: string | undefined\n}\n\n/**\n * Create a tracing middleware for distributed tracing.\n *\n * Generates trace and span IDs for each query, enabling correlation\n * across services and query analysis.\n *\n * @param options - Configuration options for the tracing middleware\n * @returns A middleware function that adds trace information\n *\n * @example Basic usage\n * ```typescript\n * const sql = postgres()\n *   .use(tracingMiddleware({\n *     onTrace: (trace) => tracer.export(trace)\n *   }))\n * ```\n *\n * @example With OpenTelemetry\n * ```typescript\n * const sql = postgres()\n *   .use(tracingMiddleware({\n *     traceId: (req) => req.context?.traceId as string,\n *     onTrace: (trace) => {\n *       const span = tracer.startSpan('postgres.query', {\n *         attributes: { 'db.statement': trace.sql }\n *       })\n *       span.end()\n *     }\n *   }))\n * ```\n */\nexport function tracingMiddleware(options: TracingMiddlewareOptions = {}): QueryMiddleware {\n  const {\n    traceId: traceIdOption,\n    spanId = () => Math.random().toString(36).slice(QUERY_ID_RANDOM_SLICE_START, SPAN_ID_LENGTH),\n    onTrace,\n  } = options\n\n  return async (request, next) => {\n    const startTime = Date.now()\n    const currentSpanId = spanId()\n\n    const traceId =\n      typeof traceIdOption === 'function'\n        ? traceIdOption(request)\n        : traceIdOption || (request.context?.traceId as string) || generateQueryId()\n\n    const response = await next()\n\n    const trace: QueryTrace = {\n      traceId,\n      spanId: currentSpanId,\n      parentSpanId: request.context?.spanId as string | undefined,\n      queryId: request.queryId,\n      sql: request.sql,\n      startTime,\n      endTime: Date.now(),\n      durationMs: response.durationMs,\n      success: response.success,\n      error: response.error?.message,\n    }\n\n    onTrace?.(trace)\n\n    // Add trace info to response metadata\n    return {\n      ...response,\n      metadata: {\n        ...response.metadata,\n        traceId,\n        spanId: currentSpanId,\n      },\n    }\n  }\n}\n\n/**\n * Options for configuring the transformation middleware.\n */\nexport interface TransformMiddlewareOptions {\n  /** Transform the SQL query and params before execution. */\n  transformQuery?: (sql: string, params: unknown[]) => { sql: string; params: unknown[] }\n  /** Transform the result after successful execution. */\n  transformResult?: <T extends Row>(result: QueryResult<T>) => QueryResult<T>\n}\n\n/**\n * Create a query transformation middleware.\n *\n * Allows modifying queries before execution and results after execution.\n * Useful for query rewriting, result mapping, and data sanitization.\n *\n * @param options - Configuration options for the transformation middleware\n * @returns A middleware function that transforms queries and/or results\n *\n * @example Query rewriting\n * ```typescript\n * const sql = postgres()\n *   .use(transformMiddleware({\n *     transformQuery: (query, params) => ({\n *       sql: query.replace('SELECT *', 'SELECT id, name, email'),\n *       params\n *     })\n *   }))\n * ```\n *\n * @example Result transformation\n * ```typescript\n * const sql = postgres()\n *   .use(transformMiddleware({\n *     transformResult: (result) => ({\n *       ...result,\n *       rows: result.rows.map(row => ({\n *         ...row,\n *         createdAt: new Date(row.created_at)\n *       }))\n *     })\n *   }))\n * ```\n */\nexport function transformMiddleware(options: TransformMiddlewareOptions): QueryMiddleware {\n  const { transformQuery, transformResult } = options\n\n  return async (request, next) => {\n    // Transform the query if transformer is provided\n    if (transformQuery) {\n      const transformed = transformQuery(request.sql, request.params)\n      request.sql = transformed.sql\n      request.params = transformed.params\n    }\n\n    const response = await next()\n\n    // Transform the result if transformer is provided\n    if (transformResult && response.success) {\n      return {\n        ...response,\n        result: transformResult(response.result),\n      }\n    }\n\n    return response\n  }\n}\n\n/**\n * Options for configuring the retry middleware.\n */\nexport interface RetryMiddlewareOptions {\n  /** Maximum number of retry attempts. Defaults to 3. */\n  maxRetries?: number\n  /** Base delay between retries in milliseconds. Defaults to 100. */\n  baseDelayMs?: number\n  /** Maximum delay between retries in milliseconds. Defaults to 5000. */\n  maxDelayMs?: number\n  /** Whether to use exponential backoff. Defaults to true. */\n  exponentialBackoff?: boolean\n  /** Function to determine if an error is retryable. Defaults to always true. */\n  isRetryable?: (error: Error) => boolean\n  /** Callback invoked before each retry attempt. */\n  onRetry?: (attempt: number, error: Error, request: QueryRequest) => void\n}\n\n/**\n * Create a retry middleware with exponential backoff.\n *\n * Automatically retries failed queries based on configurable rules.\n * Supports exponential backoff to prevent overwhelming the database.\n *\n * @param options - Configuration options for the retry middleware\n * @returns A middleware function that retries failed queries\n *\n * @example Basic usage\n * ```typescript\n * const sql = postgres()\n *   .use(retryMiddleware({\n *     maxRetries: 3,\n *     baseDelayMs: 100,\n *   }))\n * ```\n *\n * @example Selective retry\n * ```typescript\n * const sql = postgres()\n *   .use(retryMiddleware({\n *     maxRetries: 5,\n *     baseDelayMs: 200,\n *     isRetryable: (error) => {\n *       // Only retry connection errors\n *       return error.message.includes('connection') ||\n *              error.message.includes('timeout')\n *     },\n *     onRetry: (attempt, error) => {\n *       console.warn(`Retry attempt ${attempt}: ${error.message}`)\n *     }\n *   }))\n * ```\n */\nexport function retryMiddleware(options: RetryMiddlewareOptions = {}): QueryMiddleware {\n  const {\n    maxRetries = DEFAULT_MAX_RETRIES,\n    baseDelayMs = DEFAULT_RETRY_BASE_DELAY_MS,\n    maxDelayMs = DEFAULT_RETRY_MAX_DELAY_MS,\n    exponentialBackoff = true,\n    isRetryable = () => true,\n    onRetry,\n  } = options\n\n  return async (request, next) => {\n    let lastResponse: QueryResponse\n    let attempt = 0\n\n    while (attempt <= maxRetries) {\n      lastResponse = await next()\n\n      if (lastResponse.success) {\n        return lastResponse\n      }\n\n      if (!lastResponse.error || !isRetryable(lastResponse.error)) {\n        return lastResponse\n      }\n\n      if (attempt < maxRetries) {\n        const delay = exponentialBackoff\n          ? Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs)\n          : baseDelayMs\n\n        onRetry?.(attempt + 1, lastResponse.error, request)\n\n        await new Promise((resolve) => setTimeout(resolve, delay))\n      }\n\n      attempt++\n    }\n\n    return lastResponse!\n  }\n}\n\n// ============================================================================\n// Composition Utilities\n// ============================================================================\n\n/**\n * Combine multiple middlewares into a single middleware.\n *\n * Useful for creating reusable middleware bundles or organizing\n * middleware by concern.\n *\n * @param middlewares - Middleware functions to compose\n * @returns A single middleware that executes all provided middlewares in order\n *\n * @example Creating a middleware bundle\n * ```typescript\n * const observabilityMiddleware = composeMiddleware(\n *   loggingMiddleware({ level: 'info' }),\n *   metricsMiddleware({ onMetric: console.log }),\n *   tracingMiddleware({ onTrace: tracer.export })\n * )\n *\n * const sql = postgres().use(observabilityMiddleware)\n * ```\n *\n * @example Conditional composition\n * ```typescript\n * const prodMiddleware = composeMiddleware(\n *   metricsMiddleware({ onMetric: prometheus.record }),\n *   rateLimitMiddleware({ maxQueries: 1000, windowMs: 60000 })\n * )\n *\n * const devMiddleware = composeMiddleware(\n *   loggingMiddleware({ level: 'debug', logParams: true })\n * )\n *\n * const sql = postgres()\n *   .use(process.env.NODE_ENV === 'production' ? prodMiddleware : devMiddleware)\n * ```\n */\nexport function composeMiddleware(...middlewares: QueryMiddleware[]): QueryMiddleware {\n  return async (request, next) => {\n    const chain = middlewares.reduceRight<NextFunction>(\n      (nextFn, middleware) => () => middleware(request, nextFn),\n      next\n    )\n    return chain()\n  }\n}\n","/**\n * Streaming API for postgres.do\n *\n * Provides cursor-based streaming for large datasets to avoid OOM errors\n * in Cloudflare Workers' 128MB memory limit.\n *\n * Uses PostgreSQL cursors under the hood:\n * - DECLARE cursor FOR SELECT ...\n * - FETCH n FROM cursor\n * - CLOSE cursor\n *\n * @example\n * ```typescript\n * // Stream rows one at a time\n * for await (const row of sql.stream`SELECT * FROM huge_table`) {\n *   process(row)\n * }\n *\n * // Stream in batches\n * for await (const batch of sql.stream`SELECT * FROM huge_table`.batch(1000)) {\n *   processBatch(batch)\n * }\n *\n * // Manual cursor control\n * const cursor = sql.cursor`SELECT * FROM huge_table`\n * while (const rows = await cursor.fetch(100)) {\n *   process(rows)\n * }\n * await cursor.close()\n * ```\n *\n * ## Security Considerations\n *\n * ### Cursor Name Injection Prevention\n *\n * Cursor names are used in SQL statements (DECLARE, FETCH, CLOSE) and must be\n * carefully validated to prevent SQL injection attacks. This module implements\n * multiple layers of protection:\n *\n * 1. **PostgreSQL Identifier Validation**: Cursor names must conform to PostgreSQL\n *    identifier rules - start with letter or underscore, contain only alphanumeric\n *    characters and underscores, max 63 characters.\n *\n * 2. **Cryptographic Randomness**: Auto-generated cursor names use crypto.getRandomValues()\n *    to prevent name prediction attacks. The format is:\n *    `pg_cursor_{timestamp}_{counter}_{8-char-hex-random}`\n *\n * 3. **Double-Quote Escaping**: Cursor names are always wrapped in double quotes\n *    in SQL statements, preventing injection through special characters.\n *\n * 4. **No User Input Echoing**: Error messages do not echo potentially malicious\n *    cursor names back to the user, preventing information leakage.\n *\n * ### Isolation Level Validation\n *\n * Transaction isolation levels are validated against a whitelist to prevent\n * SQL injection through the isolationLevel option.\n *\n * ### Defense in Depth\n *\n * Even if validation were bypassed, the cursor name quoting provides additional\n * protection. However, users should never rely solely on quoting - always use\n * validated cursor names or let the system generate them automatically.\n *\n * @see validateCursorName for the validation implementation\n * @see generateCursorName for the secure name generation\n */\n\nimport type { Row, Transport, QueryResult, FieldInfo, TypeParser, StreamOptions, Cursor, CursorFetchResult, StreamResult } from './types'\nimport { isValidIdentifier, MAX_IDENTIFIER_LENGTH } from '@dotdo/postgres-shared/validation'\n\n/**\n * Valid PostgreSQL transaction isolation levels (case-insensitive).\n * Used to validate the isolationLevel option and prevent SQL injection.\n */\nconst VALID_ISOLATION_LEVELS = Object.freeze([\n  'read uncommitted',\n  'read committed',\n  'repeatable read',\n  'serializable',\n] as const)\n\n/**\n * Type for valid isolation levels\n */\ntype IsolationLevel = typeof VALID_ISOLATION_LEVELS[number]\n\n/**\n * Default batch size for streaming operations\n */\nconst DEFAULT_BATCH_SIZE = 100\n\n/**\n * Parse rows using type parsers\n */\nfunction parseRows<T extends Row>(\n  rows: T[],\n  fields: FieldInfo[],\n  parsers: Record<number, TypeParser>\n): T[] {\n  if (!fields || fields.length === 0 || Object.keys(parsers).length === 0) {\n    return rows\n  }\n\n  // Create a map of column name to parser\n  const columnParsers = new Map<string, TypeParser>()\n  for (const field of fields) {\n    const parser = parsers[field.dataTypeID]\n    if (parser) {\n      columnParsers.set(field.name, parser)\n    }\n  }\n\n  // If no parsers apply, return rows as-is\n  if (columnParsers.size === 0) {\n    return rows\n  }\n\n  // Parse each row\n  return rows.map((row) => {\n    const parsed: Record<string, unknown> = {}\n    for (const [key, value] of Object.entries(row)) {\n      const parser = columnParsers.get(key)\n      if (parser && typeof value === 'string') {\n        try {\n          parsed[key] = parser(value)\n        } catch {\n          parsed[key] = value // Keep original if parsing fails\n        }\n      } else {\n        parsed[key] = value\n      }\n    }\n    return parsed as T\n  })\n}\n\n/**\n * Generate a cryptographically random hex string\n */\nfunction randomHex(length: number): string {\n  // Use crypto.getRandomValues for secure randomness\n  // Works in both browser and Node.js environments\n  if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n    const bytes = new Uint8Array(Math.ceil(length / 2))\n    crypto.getRandomValues(bytes)\n    return Array.from(bytes, (b) => b.toString(16).padStart(2, '0'))\n      .join('')\n      .slice(0, length)\n  }\n  // Fallback for environments without crypto (should not happen in Workers)\n  let result = ''\n  const chars = '0123456789abcdef'\n  for (let i = 0; i < length; i++) {\n    result += chars[Math.floor(Math.random() * chars.length)]\n  }\n  return result\n}\n\n/**\n * Counter for generating unique cursor names within a session.\n * Combined with timestamp and cryptographic random bytes for uniqueness.\n *\n * ## Serverless Safety\n *\n * In serverless environments, this counter persists across requests within the\n * same isolate. This is acceptable because:\n *\n * 1. The primary uniqueness comes from the 8-char cryptographic random component\n * 2. The timestamp provides time-based uniqueness\n * 3. The counter only needs to be unique within the same millisecond\n * 4. Counter is periodically reset with jitter to reduce predictability\n *\n * The counter adds defense-in-depth but is not the sole uniqueness mechanism.\n */\nlet cursorCounter = 0\n\n/**\n * Track number of cursor names generated to periodically reset counter.\n */\nlet cursorsSinceReset = 0\n\n/**\n * Number of cursor names before resetting counter with jitter.\n * Prevents long-lived predictable counter sequences.\n */\nconst CURSOR_COUNTER_RESET_INTERVAL = 1000\n\n/**\n * Prefix for all auto-generated cursor names.\n * This prefix is part of the security model - it ensures generated names\n * follow a predictable, safe format.\n */\nconst CURSOR_NAME_PREFIX = 'pg_cursor_' as const\n\n/**\n * Generate a unique cursor name\n *\n * Uses cryptographic randomness to prevent name prediction attacks.\n * The generated format is: `pg_cursor_{timestamp}_{counter}_{random}`\n *\n * Security properties:\n * - Timestamp provides uniqueness across time\n * - Counter provides uniqueness within millisecond (with periodic jitter reset)\n * - 8 hex chars (32 bits) of cryptographic randomness prevents prediction\n * - Prefix ensures name always starts with letter (pg)\n * - Format guarantees valid PostgreSQL identifier\n *\n * Serverless safety:\n * - Counter is reset with random jitter every 1000 generations\n * - 8 random hex chars provide primary unpredictability\n * - Timestamp ensures no collision across time\n *\n * @returns A unique, cryptographically unpredictable cursor name\n */\nfunction generateCursorName(): string {\n  // Periodically reset counter with random jitter for serverless safety\n  if (cursorsSinceReset >= CURSOR_COUNTER_RESET_INTERVAL) {\n    cursorCounter = Math.floor(Math.random() * 1000000)\n    cursorsSinceReset = 0\n  }\n\n  const timestamp = Date.now()\n  const counter = ++cursorCounter\n  cursorsSinceReset++\n  const random = randomHex(8)\n  // Format: pg_cursor_1234567890123_1_a1b2c3d4\n  // Always valid: starts with 'p', contains only alphanumerics and underscores\n  return `${CURSOR_NAME_PREFIX}${timestamp}_${counter}_${random}`\n}\n\n/**\n * Reset cursor counter state. Intended for testing only.\n *\n * @security In production, this should never be exposed to external callers.\n *           Only exported for use in test cleanup between test cases.\n */\nexport function resetCursorCounterState(): void {\n  cursorCounter = 0\n  cursorsSinceReset = 0\n}\n\n/**\n * Error class for cursor validation failures.\n * Provides structured error information without leaking potentially malicious input.\n */\nexport class CursorValidationError extends Error {\n  /** Error code for programmatic handling */\n  readonly code: string\n\n  constructor(message: string, code: string = 'INVALID_CURSOR_NAME') {\n    super(message)\n    this.name = 'CursorValidationError'\n    this.code = code\n  }\n}\n\n/**\n * Validate a cursor name against PostgreSQL identifier rules\n * and security requirements.\n *\n * This function implements multiple layers of validation:\n *\n * 1. **Non-empty check**: Cursor names cannot be empty\n * 2. **Length check**: Cannot exceed PostgreSQL's 63-character limit\n * 3. **PostgreSQL identifier rules**: Must start with letter or underscore,\n *    contain only alphanumeric characters and underscores\n *\n * Security notes:\n * - Error messages do not echo the input back to prevent information leakage\n * - The regex pattern in isValidIdentifier explicitly rejects:\n *   - Quotes (single, double, backtick)\n *   - Semicolons and other SQL delimiters\n *   - Whitespace (spaces, tabs, newlines)\n *   - Dollar signs (used for dollar-quoting in PostgreSQL)\n *   - All other special characters\n *\n * @param cursorName - The cursor name to validate\n * @throws CursorValidationError if the cursor name is invalid\n *\n * @example\n * ```typescript\n * validateCursorName('my_cursor')      // OK\n * validateCursorName('_private')       // OK\n * validateCursorName('Cursor123')      // OK\n * validateCursorName('123cursor')      // Throws - starts with number\n * validateCursorName('my cursor')      // Throws - contains space\n * validateCursorName('cursor\"; DROP')  // Throws - contains special chars\n * ```\n */\nexport function validateCursorName(cursorName: string): void {\n  // Empty check with clear error\n  if (!cursorName || cursorName.length === 0) {\n    throw new CursorValidationError(\n      'Invalid cursor name: cannot be empty',\n      'CURSOR_NAME_EMPTY'\n    )\n  }\n\n  // Length check - PostgreSQL truncates identifiers silently at 63 chars,\n  // but we reject to prevent unexpected behavior\n  if (cursorName.length > MAX_IDENTIFIER_LENGTH) {\n    throw new CursorValidationError(\n      `Invalid cursor name: exceeds maximum length of ${MAX_IDENTIFIER_LENGTH} characters`,\n      'CURSOR_NAME_TOO_LONG'\n    )\n  }\n\n  // Use the shared validation function for PostgreSQL identifier rules\n  // This rejects names with:\n  // - Special characters (quotes, semicolons, spaces, etc.)\n  // - Names not starting with letter or underscore\n  // - SQL injection payloads\n  // - Dollar signs (valid in PG but excluded for security)\n  if (!isValidIdentifier(cursorName)) {\n    throw new CursorValidationError(\n      'Invalid cursor name: must start with a letter or underscore, and contain only letters, numbers, and underscores',\n      'CURSOR_NAME_INVALID_FORMAT'\n    )\n  }\n}\n\n/**\n * Validates an isolation level against the allowed whitelist.\n *\n * @param level - The isolation level to validate\n * @returns The normalized (lowercase) isolation level\n * @throws CursorValidationError if the isolation level is invalid\n */\nfunction validateIsolationLevel(level: string): IsolationLevel {\n  const normalized = level.toLowerCase() as IsolationLevel\n  if (!VALID_ISOLATION_LEVELS.includes(normalized)) {\n    throw new CursorValidationError(\n      'Invalid isolation level: must be one of: read uncommitted, read committed, repeatable read, serializable',\n      'INVALID_ISOLATION_LEVEL'\n    )\n  }\n  return normalized\n}\n\n/**\n * Internal cursor implementation\n */\nclass CursorImpl<T extends Row = Row> implements Cursor<T> {\n  private _isOpen = true\n  private _totalFetched = 0\n  private _fields: FieldInfo[] = []\n  private readonly cursorName: string\n  private readonly batchSize: number\n  private readonly transport: Transport\n  private readonly parsers: Record<number, TypeParser>\n  private inTransaction = false\n\n  constructor(\n    transport: Transport,\n    cursorName: string,\n    batchSize: number,\n    parsers: Record<number, TypeParser>\n  ) {\n    this.transport = transport\n    this.cursorName = cursorName\n    this.batchSize = batchSize\n    this.parsers = parsers\n  }\n\n  /**\n   * Initialize the cursor (called after DECLARE)\n   */\n  _setFields(fields: FieldInfo[]): void {\n    this._fields = fields\n  }\n\n  _setInTransaction(inTransaction: boolean): void {\n    this.inTransaction = inTransaction\n  }\n\n  get isOpen(): boolean {\n    return this._isOpen\n  }\n\n  get totalFetched(): number {\n    return this._totalFetched\n  }\n\n  get fields(): FieldInfo[] {\n    return this._fields\n  }\n\n  async fetch(count?: number): Promise<T[]> {\n    const result = await this.fetchWithInfo(count)\n    return result.rows\n  }\n\n  async fetchWithInfo(count?: number): Promise<CursorFetchResult<T>> {\n    if (!this._isOpen) {\n      return { rows: [], hasMore: false, totalFetched: this._totalFetched }\n    }\n\n    const fetchCount = count ?? this.batchSize\n    const result = await this.transport.query<T>(\n      `FETCH ${fetchCount} FROM \"${this.cursorName}\"`\n    )\n\n    // Store fields from first fetch if not already set\n    if (this._fields.length === 0 && result.fields.length > 0) {\n      this._fields = result.fields\n    }\n\n    const parsedRows = parseRows(result.rows, this._fields, this.parsers)\n    this._totalFetched += parsedRows.length\n\n    const hasMore = parsedRows.length === fetchCount\n\n    return {\n      rows: parsedRows,\n      hasMore,\n      totalFetched: this._totalFetched,\n    }\n  }\n\n  async close(): Promise<void> {\n    if (!this._isOpen) {\n      return\n    }\n\n    this._isOpen = false\n\n    try {\n      // Close the cursor\n      await this.transport.query(`CLOSE \"${this.cursorName}\"`)\n\n      // Commit the transaction if we started one\n      if (this.inTransaction) {\n        await this.transport.query('COMMIT')\n      }\n    } catch (error) {\n      // Try to rollback on error\n      if (this.inTransaction) {\n        try {\n          await this.transport.query('ROLLBACK')\n        } catch {\n          // Ignore rollback errors\n        }\n      }\n      throw error\n    }\n  }\n\n  async *[Symbol.asyncIterator](): AsyncIterableIterator<T> {\n    try {\n      while (this._isOpen) {\n        const { rows, hasMore } = await this.fetchWithInfo()\n\n        for (const row of rows) {\n          yield row\n        }\n\n        if (!hasMore) {\n          break\n        }\n      }\n    } finally {\n      await this.close()\n    }\n  }\n}\n\n/**\n * Create a cursor for a query\n */\nexport async function createCursor<T extends Row = Row>(\n  transport: Transport,\n  sql: string,\n  params: unknown[],\n  parsers: Record<number, TypeParser>,\n  options: StreamOptions = {}\n): Promise<Cursor<T>> {\n  // Generate or validate cursor name\n  const cursorName = options.cursorName ?? generateCursorName()\n\n  // Validate the cursor name (whether user-provided or generated)\n  // This prevents SQL injection attacks through cursor names\n  validateCursorName(cursorName)\n\n  const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE\n  const readOnly = options.readOnly ?? true\n\n  // Build transaction options\n  const txParts: string[] = ['BEGIN']\n  if (options.isolationLevel) {\n    // Validate isolation level to prevent SQL injection\n    // This uses a whitelist approach - only known-safe values are accepted\n    const normalized = validateIsolationLevel(options.isolationLevel)\n    txParts.push(`ISOLATION LEVEL ${normalized.toUpperCase()}`)\n  }\n  if (readOnly) {\n    txParts.push('READ ONLY')\n  }\n\n  // Start transaction and declare cursor\n  await transport.query(txParts.join(' '))\n\n  try {\n    // Declare the cursor\n    // For parameterized queries, we need to use a prepared statement approach\n    // PostgreSQL cursors don't directly support parameters in DECLARE\n    // So we build the query with proper escaping for the cursor\n    const declareResult = await declareCursor<T>(transport, cursorName, sql, params)\n\n    const cursor = new CursorImpl<T>(transport, cursorName, batchSize, parsers)\n    cursor._setFields(declareResult.fields)\n    cursor._setInTransaction(true)\n\n    return cursor\n  } catch (error) {\n    // Rollback on error\n    try {\n      await transport.query('ROLLBACK')\n    } catch {\n      // Ignore rollback errors\n    }\n    throw error\n  }\n}\n\n/**\n * Declare a cursor for a query with parameters\n */\nasync function declareCursor<T extends Row>(\n  transport: Transport,\n  cursorName: string,\n  sql: string,\n  params: unknown[]\n): Promise<QueryResult<T>> {\n  // For queries without parameters, declare directly\n  if (params.length === 0) {\n    return transport.query<T>(`DECLARE \"${cursorName}\" CURSOR FOR ${sql}`)\n  }\n\n  // For parameterized queries, we use a slightly different approach\n  // PostgreSQL's DECLARE doesn't support $n parameters directly,\n  // but the transport will handle parameter substitution\n  // We can use EXECUTE with a prepared statement\n  //\n  // However, for HTTP transport, parameters are handled server-side\n  // So we send the DECLARE with the query and parameters\n  return transport.query<T>(\n    `DECLARE \"${cursorName}\" CURSOR FOR ${sql}`,\n    params\n  )\n}\n\n/**\n * Create a stream result for a query\n */\nexport function createStreamResult<T extends Row = Row>(\n  transport: Transport,\n  sql: string,\n  params: unknown[],\n  parsers: Record<number, TypeParser>,\n  options: StreamOptions = {}\n): StreamResult<T> {\n  const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE\n\n  return {\n    sql,\n    params,\n\n    async *[Symbol.asyncIterator](): AsyncIterableIterator<T> {\n      const cursor = await createCursor<T>(transport, sql, params, parsers, {\n        ...options,\n        batchSize,\n      })\n\n      try {\n        for await (const row of cursor) {\n          yield row\n        }\n      } finally {\n        if (cursor.isOpen) {\n          await cursor.close()\n        }\n      }\n    },\n\n    batch(size: number): AsyncIterable<T[]> {\n      return {\n        async *[Symbol.asyncIterator](): AsyncIterableIterator<T[]> {\n          const cursor = await createCursor<T>(transport, sql, params, parsers, {\n            ...options,\n            batchSize: size,\n          })\n\n          try {\n            while (cursor.isOpen) {\n              const { rows, hasMore } = await cursor.fetchWithInfo(size)\n\n              if (rows.length > 0) {\n                yield rows\n              }\n\n              if (!hasMore) {\n                break\n              }\n            }\n          } finally {\n            if (cursor.isOpen) {\n              await cursor.close()\n            }\n          }\n        },\n      }\n    },\n\n    async cursor(): Promise<Cursor<T>> {\n      return createCursor<T>(transport, sql, params, parsers, options)\n    },\n  }\n}\n\n/**\n * Build parameterized SQL string from template\n */\nexport function buildParameterizedSql(\n  strings: TemplateStringsArray,\n  values: unknown[]\n): { sql: string; params: unknown[] } {\n  const parts: string[] = []\n  for (let i = 0; i < strings.length; i++) {\n    parts.push(strings[i]!)\n    if (i < values.length) {\n      parts.push(`$${i + 1}`)\n    }\n  }\n  return {\n    sql: parts.join(''),\n    params: values,\n  }\n}\n","/**\n * CDC Subscription for postgres.do\n *\n * Provides a user-friendly API for subscribing to database changes:\n * - Callback API (onChange, onInsert, onUpdate, onDelete)\n * - Async iterator API for use with for-await-of loops\n * - TypeScript generics for typed change payloads\n * - Automatic connection management and reconnection\n */\n\nimport type {\n  Row,\n  CDCChangeEvent,\n  CDCSubscriptionOptions,\n} from './types'\nimport type { CDCTransport } from './types'\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Options for creating a subscription\n */\nexport interface SubscribeOptions extends CDCSubscriptionOptions {\n  /** Called for every change event */\n  onChange?: (event: CDCChangeEvent) => void | Promise<void>\n  /** Called for INSERT events */\n  onInsert?: (row: Row) => void | Promise<void>\n  /** Called for UPDATE events */\n  onUpdate?: (newRow: Row, oldRow?: Row) => void | Promise<void>\n  /** Called for DELETE events */\n  onDelete?: (oldRow: Row) => void | Promise<void>\n  /** Called when an error occurs */\n  onError?: (error: Error) => void\n}\n\n/**\n * Typed subscribe options with generics\n */\nexport interface TypedSubscribeOptions<T extends Row> extends Omit<SubscribeOptions, 'onChange' | 'onInsert' | 'onUpdate' | 'onDelete'> {\n  /** Called for every change event */\n  onChange?: (event: CDCChangeEvent & { newRow?: T; oldRow?: T }) => void | Promise<void>\n  /** Called for INSERT events */\n  onInsert?: (row: T) => void | Promise<void>\n  /** Called for UPDATE events */\n  onUpdate?: (newRow: T, oldRow?: T) => void | Promise<void>\n  /** Called for DELETE events */\n  onDelete?: (oldRow: T) => void | Promise<void>\n  /** Called when an error occurs */\n  onError?: (error: Error) => void\n}\n\n/**\n * Subscription interface for CDC streaming\n */\nexport interface Subscription<T extends Row = Row> extends AsyncIterable<CDCChangeEvent & { newRow?: T; oldRow?: T }> {\n  /** Unique subscription ID */\n  readonly id: string\n  /** Table name */\n  readonly table: string\n  /** Schema name */\n  readonly schema: string\n  /** Whether the subscription is currently active */\n  readonly isActive: boolean\n  /** Last processed LSN for resumption */\n  readonly lastLsn: string | null\n\n  /** Unsubscribe and stop receiving events */\n  unsubscribe(): Promise<void>\n\n  /** Register a handler for all change events */\n  onChange(handler: (event: CDCChangeEvent & { newRow?: T; oldRow?: T }) => void | Promise<void>): this\n\n  /** Register a handler for INSERT events */\n  onInsert(handler: (row: T) => void | Promise<void>): this\n\n  /** Register a handler for UPDATE events */\n  onUpdate(handler: (newRow: T, oldRow?: T) => void | Promise<void>): this\n\n  /** Register a handler for DELETE events */\n  onDelete(handler: (oldRow: T) => void | Promise<void>): this\n}\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\n/**\n * Internal state for managing the subscription\n */\ninterface SubscriptionState {\n  active: boolean\n  lastLsn: string | null\n  changeHandlers: Array<(event: CDCChangeEvent) => void | Promise<void>>\n  insertHandlers: Array<(row: Row) => void | Promise<void>>\n  updateHandlers: Array<(newRow: Row, oldRow?: Row) => void | Promise<void>>\n  deleteHandlers: Array<(oldRow: Row) => void | Promise<void>>\n  errorHandler: ((error: Error) => void) | null\n  eventQueue: CDCChangeEvent[]\n  eventResolvers: Array<(result: IteratorResult<CDCChangeEvent>) => void>\n  iteratorDone: boolean\n}\n\n/**\n * CDC Subscription implementation\n */\nexport class CDCSubscription<T extends Row = Row> implements Subscription<T> {\n  readonly id: string\n  readonly table: string\n  readonly schema: string\n\n  private state: SubscriptionState\n  private unsubscribeCallback: () => Promise<void>\n\n  constructor(\n    id: string,\n    table: string,\n    schema: string,\n    transport: CDCTransport,\n    unsubscribeCallback: () => Promise<void>,\n    options: SubscribeOptions = {}\n  ) {\n    this.id = id\n    this.table = table\n    this.schema = schema\n    void transport // Transport reference kept for future reconnection support\n    this.unsubscribeCallback = unsubscribeCallback\n\n    this.state = {\n      active: true,\n      lastLsn: options.resumeFrom ?? null,\n      changeHandlers: [],\n      insertHandlers: [],\n      updateHandlers: [],\n      deleteHandlers: [],\n      errorHandler: options.onError ?? null,\n      eventQueue: [],\n      eventResolvers: [],\n      iteratorDone: false,\n    }\n\n    // Register initial handlers from options\n    if (options.onChange) {\n      this.state.changeHandlers.push(options.onChange)\n    }\n    if (options.onInsert) {\n      this.state.insertHandlers.push(options.onInsert)\n    }\n    if (options.onUpdate) {\n      this.state.updateHandlers.push(options.onUpdate)\n    }\n    if (options.onDelete) {\n      this.state.deleteHandlers.push(options.onDelete)\n    }\n  }\n\n  get isActive(): boolean {\n    return this.state.active\n  }\n\n  get lastLsn(): string | null {\n    return this.state.lastLsn\n  }\n\n  /**\n   * Handle an incoming event from the transport\n   */\n  handleEvent(event: CDCChangeEvent): void {\n    if (!this.state.active) return\n\n    // Update last LSN\n    this.state.lastLsn = event.lsn\n\n    // Call change handlers\n    for (const handler of this.state.changeHandlers) {\n      try {\n        void handler(event)\n      } catch (error) {\n        this.handleError(error instanceof Error ? error : new Error(String(error)))\n      }\n    }\n\n    // Call operation-specific handlers\n    switch (event.operation) {\n      case 'INSERT':\n        if (event.newRow) {\n          for (const handler of this.state.insertHandlers) {\n            try {\n              void handler(event.newRow)\n            } catch (error) {\n              this.handleError(error instanceof Error ? error : new Error(String(error)))\n            }\n          }\n        }\n        break\n\n      case 'UPDATE':\n        if (event.newRow) {\n          for (const handler of this.state.updateHandlers) {\n            try {\n              void handler(event.newRow, event.oldRow)\n            } catch (error) {\n              this.handleError(error instanceof Error ? error : new Error(String(error)))\n            }\n          }\n        }\n        break\n\n      case 'DELETE':\n        if (event.oldRow) {\n          for (const handler of this.state.deleteHandlers) {\n            try {\n              void handler(event.oldRow)\n            } catch (error) {\n              this.handleError(error instanceof Error ? error : new Error(String(error)))\n            }\n          }\n        }\n        break\n    }\n\n    // If there are pending iterator resolvers, resolve the next one\n    if (this.state.eventResolvers.length > 0) {\n      const resolver = this.state.eventResolvers.shift()!\n      resolver({ value: event, done: false })\n    } else {\n      // Otherwise queue the event\n      this.state.eventQueue.push(event)\n    }\n  }\n\n  /**\n   * Handle an error from the transport\n   */\n  handleError(error: Error): void {\n    if (this.state.errorHandler) {\n      this.state.errorHandler(error)\n    }\n  }\n\n  /**\n   * Mark the subscription as inactive\n   */\n  setInactive(): void {\n    this.state.active = false\n    this.state.iteratorDone = true\n\n    // Resolve any pending iterator requests with done\n    while (this.state.eventResolvers.length > 0) {\n      const resolver = this.state.eventResolvers.shift()!\n      resolver({ value: undefined as unknown as CDCChangeEvent, done: true })\n    }\n  }\n\n  async unsubscribe(): Promise<void> {\n    if (!this.state.active) return\n\n    await this.unsubscribeCallback()\n    this.setInactive()\n  }\n\n  onChange(handler: (event: CDCChangeEvent & { newRow?: T; oldRow?: T }) => void | Promise<void>): this {\n    this.state.changeHandlers.push(handler as (event: CDCChangeEvent) => void | Promise<void>)\n    return this\n  }\n\n  onInsert(handler: (row: T) => void | Promise<void>): this {\n    this.state.insertHandlers.push(handler as (row: Row) => void | Promise<void>)\n    return this\n  }\n\n  onUpdate(handler: (newRow: T, oldRow?: T) => void | Promise<void>): this {\n    this.state.updateHandlers.push(handler as (newRow: Row, oldRow?: Row) => void | Promise<void>)\n    return this\n  }\n\n  onDelete(handler: (oldRow: T) => void | Promise<void>): this {\n    this.state.deleteHandlers.push(handler as (oldRow: Row) => void | Promise<void>)\n    return this\n  }\n\n  /**\n   * Async iterator implementation for for-await-of support\n   */\n  [Symbol.asyncIterator](): AsyncIterator<CDCChangeEvent & { newRow?: T; oldRow?: T }> {\n    return {\n      next: async (): Promise<IteratorResult<CDCChangeEvent & { newRow?: T; oldRow?: T }>> => {\n        // If subscription is inactive and queue is empty, we're done\n        if (this.state.iteratorDone && this.state.eventQueue.length === 0) {\n          return { value: undefined as unknown as CDCChangeEvent, done: true }\n        }\n\n        // If there's an event in the queue, return it\n        if (this.state.eventQueue.length > 0) {\n          const event = this.state.eventQueue.shift()!\n          return { value: event as CDCChangeEvent & { newRow?: T; oldRow?: T }, done: false }\n        }\n\n        // Wait for the next event\n        return new Promise((resolve) => {\n          this.state.eventResolvers.push(resolve as (result: IteratorResult<CDCChangeEvent>) => void)\n        })\n      },\n\n      return: async (): Promise<IteratorResult<CDCChangeEvent & { newRow?: T; oldRow?: T }>> => {\n        // Called when breaking out of for-await-of\n        // Don't unsubscribe - allow the user to continue later\n        return { value: undefined as unknown as CDCChangeEvent, done: true }\n      },\n    }\n  }\n}\n\n// =============================================================================\n// Validation Helpers\n// =============================================================================\n\n/**\n * Regular expression for valid table/schema names\n * Must start with letter or underscore, contain only alphanumeric and underscores\n */\nconst VALID_IDENTIFIER_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/\n\n/**\n * Validate a table name to prevent SQL injection\n */\nexport function validateTableName(name: string): { table: string; schema: string } {\n  if (!name || name.trim() === '') {\n    throw new Error('Table name cannot be empty')\n  }\n\n  // Check for SQL injection patterns\n  if (name.includes(';') || name.includes('--') || name.includes('/*') || name.includes('*/')) {\n    throw new Error('Invalid table name: contains forbidden characters')\n  }\n\n  // Split into schema.table if present\n  const parts = name.split('.')\n  if (parts.length > 2) {\n    throw new Error('Invalid table name: too many parts')\n  }\n\n  let schema = 'public'\n  let table: string\n\n  if (parts.length === 2) {\n    schema = parts[0]!\n    table = parts[1]!\n  } else {\n    table = parts[0]!\n  }\n\n  // Validate schema name\n  if (!VALID_IDENTIFIER_REGEX.test(schema)) {\n    throw new Error(`Invalid schema name: \"${schema}\"`)\n  }\n\n  // Validate table name\n  if (!VALID_IDENTIFIER_REGEX.test(table)) {\n    throw new Error(`Invalid table name: \"${table}\"`)\n  }\n\n  return { table, schema }\n}\n\n/**\n * Generate a unique subscription ID\n */\nexport function generateSubscriptionId(): string {\n  return `sub-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`\n}\n","/**\n * PostgreSQL client for postgres.do\n * SQL tagged template function with Drizzle ORM compatibility\n */\n\nimport type {\n  Sql,\n  TransactionSql,\n  ReservedSql,\n  PendingQuery,\n  Row,\n  PostgresConfig,\n  Transport,\n  TransactionOptions,\n  TypeParser,\n  QueryResult,\n  StreamResult,\n  CDCTransport,\n  CDCClientSubscription,\n  CDCClientSubscribeOptions,\n  CDCClientSubscriptionInfo,\n} from './types'\nimport { PostgresError, ConnectionError, TimeoutError } from './types'\nimport { createHttpTransport } from './transport/http'\nimport { createRpcTransport } from './transport/rpc'\nimport { createCdcWsTransport } from './transport/cdc-ws'\nimport { createCdcSseTransport } from './transport/cdc-sse'\nimport type { QueryMiddleware, QueryRequest } from './middleware'\nimport { generateQueryId, executeWithMiddleware } from './middleware'\nimport { createStreamResult, buildParameterizedSql as buildStreamSql } from './streaming'\nimport {\n  CDCSubscription,\n  validateTableName,\n  generateSubscriptionId,\n  type SubscribeOptions,\n} from './subscription'\n\n/** Default type parsers for common PostgreSQL types */\nconst DEFAULT_PARSERS: Record<number, TypeParser> = {\n  // Boolean\n  16: (value: string) => value === 't' || value === 'true',\n  // Integer types\n  20: (value: string) => BigInt(value), // int8/bigint\n  21: (value: string) => parseInt(value, 10), // int2\n  23: (value: string) => parseInt(value, 10), // int4\n  26: (value: string) => parseInt(value, 10), // oid\n  // Float types\n  700: (value: string) => parseFloat(value), // float4\n  701: (value: string) => parseFloat(value), // float8\n  1700: (value: string) => parseFloat(value), // numeric\n  // Date/time types\n  1082: (value: string) => value, // date (keep as string for flexibility)\n  1083: (value: string) => value, // time\n  1114: (value: string) => new Date(value), // timestamp\n  1184: (value: string) => new Date(value), // timestamptz\n  // JSON types\n  114: (value: string) => JSON.parse(value), // json\n  3802: (value: string) => JSON.parse(value), // jsonb\n  // Array types are handled by the server\n}\n\n/**\n * Parse a postgres:// URL into config\n */\nfunction parseConnectionUrl(url: string): Partial<PostgresConfig> {\n  try {\n    const parsed = new URL(url)\n    const config: Partial<PostgresConfig> = {}\n\n    // Extract protocol (postgres:// or postgresql://)\n    if (!parsed.protocol.startsWith('postgres')) {\n      throw new Error('Invalid protocol: must be postgres:// or postgresql://')\n    }\n\n    // Use the host directly for postgres.do\n    // URL format: postgres://db.postgres.do/database_name\n    const baseUrl = `https://${parsed.host}`\n\n    // Extract API key from password or query param\n    if (parsed.password) {\n      config.apiKey = decodeURIComponent(parsed.password)\n    }\n    if (parsed.searchParams.has('apiKey')) {\n      config.apiKey = parsed.searchParams.get('apiKey')!\n    }\n\n    // SSL setting - use conditional to avoid exactOptionalPropertyTypes issue\n    const sslMode = parsed.searchParams.get('sslmode')\n    if (sslMode && (sslMode === 'require' || sslMode === 'prefer' || sslMode === 'allow' || sslMode === 'disable')) {\n      config.ssl = sslMode\n    }\n\n    // Store the URL for transport\n    config.url = baseUrl + parsed.pathname\n\n    return config\n  } catch (error) {\n    throw new ConnectionError(`Invalid connection URL: ${error instanceof Error ? error.message : String(error)}`)\n  }\n}\n\n/**\n * Build parameterized SQL from template strings\n */\nfunction buildParameterizedSql(\n  strings: TemplateStringsArray,\n  values: unknown[]\n): string {\n  const parts: string[] = []\n  for (let i = 0; i < strings.length; i++) {\n    parts.push(strings[i]!)\n    if (i < values.length) {\n      parts.push(`$${i + 1}`)\n    }\n  }\n  return parts.join('')\n}\n\n/**\n * Create a pending query that can be executed\n */\nfunction createPendingQuery<T extends Row>(\n  transport: Transport,\n  strings: TemplateStringsArray,\n  values: unknown[],\n  parsers: Record<number, TypeParser>,\n  middlewares: QueryMiddleware[] = []\n): PendingQuery<T> {\n  const sql = buildParameterizedSql(strings, values)\n\n  // Create the promise that executes the query\n  const execute = async (): Promise<T[]> => {\n    if (middlewares.length === 0) {\n      // No middlewares - execute directly\n      const result = await transport.query<T>(sql, values)\n      return parseRows(result.rows, result.fields, parsers)\n    }\n\n    // Execute through middleware chain\n    const request: QueryRequest = {\n      sql,\n      params: values,\n      timestamp: Date.now(),\n      queryId: generateQueryId(),\n    }\n\n    const response = await executeWithMiddleware<T>(\n      middlewares as QueryMiddleware<T>[],\n      request,\n      async () => transport.query<T>(sql, values)\n    )\n\n    if (!response.success && response.error) {\n      throw response.error\n    }\n\n    return parseRows(response.result.rows, response.result.fields, parsers)\n  }\n\n  // Create the pending query object\n  const promise = execute() as PendingQuery<T>\n\n  // Add metadata\n  Object.defineProperty(promise, 'strings', { value: strings })\n  Object.defineProperty(promise, 'values', { value: values })\n  Object.defineProperty(promise, 'execute', { value: execute })\n  Object.defineProperty(promise, 'toString', {\n    value: () => sql,\n  })\n\n  return promise\n}\n\n/**\n * Parse rows using type parsers\n */\nfunction parseRows<T extends Row>(\n  rows: T[],\n  fields: QueryResult['fields'],\n  parsers: Record<number, TypeParser>\n): T[] {\n  if (!fields || fields.length === 0) {\n    return rows\n  }\n\n  // Create a map of column name to parser\n  const columnParsers = new Map<string, TypeParser>()\n  for (const field of fields) {\n    const parser = parsers[field.dataTypeID]\n    if (parser) {\n      columnParsers.set(field.name, parser)\n    }\n  }\n\n  // If no parsers apply, return rows as-is\n  if (columnParsers.size === 0) {\n    return rows\n  }\n\n  // Parse each row\n  return rows.map((row) => {\n    const parsed: Record<string, unknown> = {}\n    for (const [key, value] of Object.entries(row)) {\n      const parser = columnParsers.get(key)\n      if (parser && typeof value === 'string') {\n        try {\n          parsed[key] = parser(value)\n        } catch {\n          parsed[key] = value // Keep original if parsing fails\n        }\n      } else {\n        parsed[key] = value\n      }\n    }\n    return parsed as T\n  })\n}\n\n// ============================================================================\n// Advisory Lock Helpers\n// ============================================================================\n\n/** PostgreSQL bigint max value: 2^63 - 1 */\nconst BIGINT_MAX = BigInt('9223372036854775807')\n\n/** PostgreSQL int4 max value: 2^31 - 1 */\nconst INT4_MAX = 2147483647\n\n/**\n * Validate a single advisory lock key.\n *\n * Lock keys must be:\n * - Non-negative integers\n * - Within PostgreSQL bigint range (0 to 2^63 - 1)\n *\n * @param key - The lock key to validate\n * @throws {PostgresError} If the key is invalid (PostgreSQL error code '22023')\n */\nfunction validateLockKey(key: number | bigint): void {\n  // Check for non-integer FIRST (before BigInt conversion throws its own error)\n  if (typeof key === 'number' && !Number.isInteger(key)) {\n    throw new PostgresError('Advisory lock key must be an integer', {\n      code: '22023',\n      severity: 'ERROR',\n    })\n  }\n\n  const keyBigInt = BigInt(key)\n\n  // Check for negative values\n  if (keyBigInt < BigInt(0)) {\n    throw new PostgresError('Advisory lock key must be non-negative', {\n      code: '22023',\n      severity: 'ERROR',\n    })\n  }\n\n  // Check for overflow (PostgreSQL bigint max)\n  if (keyBigInt > BIGINT_MAX) {\n    throw new PostgresError('Advisory lock key exceeds PostgreSQL bigint maximum', {\n      code: '22023',\n      severity: 'ERROR',\n    })\n  }\n}\n\n/**\n * Validate a two-key advisory lock pair.\n *\n * Two-key locks use PostgreSQL's int4 range for both classid and objid:\n * - Non-negative integers\n * - Within int4 range (0 to 2^31 - 1)\n *\n * @param classId - The lock class/namespace identifier\n * @param objId - The object identifier within the namespace\n * @throws {PostgresError} If either key is invalid (PostgreSQL error code '22023')\n */\nfunction validateTwoKeyLock(classId: number, objId: number): void {\n  // Check for non-integers\n  if (!Number.isInteger(classId) || !Number.isInteger(objId)) {\n    throw new PostgresError('Advisory lock keys must be integers', {\n      code: '22023',\n      severity: 'ERROR',\n    })\n  }\n\n  // Check for negative values\n  if (classId < 0 || objId < 0) {\n    throw new PostgresError('Advisory lock keys must be non-negative', {\n      code: '22023',\n      severity: 'ERROR',\n    })\n  }\n\n  // Check for int4 overflow\n  if (classId > INT4_MAX || objId > INT4_MAX) {\n    throw new PostgresError('Advisory lock key exceeds PostgreSQL int4 maximum', {\n      code: '22023',\n      severity: 'ERROR',\n    })\n  }\n}\n\n/**\n * Build the SQL for an advisory lock operation.\n *\n * @param lockFn - The PostgreSQL lock function name\n * @param args - The lock key arguments (single bigint or two int4s)\n * @returns The SQL string for the lock operation\n */\nfunction buildAdvisoryLockSql(lockFn: string, ...args: Array<number | bigint>): string {\n  if (args.length === 1) {\n    return `SELECT ${lockFn}(${BigInt(args[0]!)})`\n  }\n  return `SELECT ${lockFn}(${args[0]}, ${args[1]})`\n}\n\n// ============================================================================\n// Two-Phase Commit (2PC) Helpers\n// ============================================================================\n\n/**\n * Regular expression for validating two-phase commit transaction IDs.\n *\n * Transaction IDs must:\n * - Start with a letter or underscore\n * - Contain only alphanumeric characters and underscores\n * - Be non-empty\n *\n * This prevents SQL injection in PREPARE TRANSACTION, COMMIT PREPARED,\n * and ROLLBACK PREPARED statements.\n */\nconst TRANSACTION_ID_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/\n\n/**\n * Validate a transaction ID for two-phase commit operations.\n *\n * Two-phase commit (2PC) allows a transaction to be prepared on one\n * connection and committed/rolled back on another, enabling distributed\n * transactions across multiple databases or services.\n *\n * @param transactionId - The transaction ID to validate\n * @throws {PostgresError} If the transaction ID is invalid (PostgreSQL error code '22023')\n *\n * @example\n * ```typescript\n * validateTransactionId('my_tx_123')  // OK\n * validateTransactionId('_private')   // OK\n * validateTransactionId('123_bad')    // throws - cannot start with number\n * validateTransactionId('has space')  // throws - no spaces allowed\n * validateTransactionId(\"'; DROP\")    // throws - SQL injection attempt blocked\n * ```\n */\nfunction validateTransactionId(transactionId: string): void {\n  if (!TRANSACTION_ID_REGEX.test(transactionId)) {\n    throw new PostgresError(\n      'Invalid transaction ID: must be alphanumeric with underscores, starting with letter or underscore',\n      {\n        code: '22023',\n        severity: 'ERROR',\n      }\n    )\n  }\n}\n\n// ============================================================================\n// Transaction Hook Helpers\n// ============================================================================\n\n/**\n * Execute an array of transaction lifecycle callbacks sequentially.\n *\n * This is used for transaction hooks (onCommit/onRollback) where:\n * - All callbacks should be attempted even if earlier ones fail\n * - Callback errors are logged but not propagated to the caller\n * - Callbacks execute in registration order (FIFO)\n *\n * @param callbacks - Array of callback functions to execute\n * @param phase - The phase name for error logging ('commit' or 'rollback')\n */\nasync function executeTransactionCallbacks(\n  callbacks: Array<() => void | Promise<void>>,\n  phase: 'commit' | 'rollback'\n): Promise<void> {\n  for (const callback of callbacks) {\n    try {\n      await callback()\n    } catch (error) {\n      // Log but don't propagate - ensures all callbacks are attempted\n      console.error(`Transaction ${phase} callback error:`, error)\n    }\n  }\n}\n\n// ============================================================================\n// Transaction Context and State\n// ============================================================================\n\n/**\n * Transaction context for tracking mutable state during a transaction.\n *\n * This context is created fresh for each transaction attempt and holds:\n * - Transaction metadata (txid, name)\n * - Lifecycle hooks (onCommit, onRollback callbacks)\n * - Two-phase commit state (prepared flag and transaction ID)\n * - Retry state (current attempt number)\n */\ninterface TransactionContext {\n  /** PostgreSQL transaction ID fetched via txid_current() */\n  txid: string | undefined\n  /** User-provided transaction name for debugging/logging */\n  txName: string | undefined\n  /** Callbacks to execute after successful COMMIT */\n  onCommitCallbacks: Array<() => void | Promise<void>>\n  /** Callbacks to execute after ROLLBACK (errors ignored) */\n  onRollbackCallbacks: Array<() => void | Promise<void>>\n  /** Whether PREPARE TRANSACTION has been called (2PC mode) */\n  isPrepared: boolean\n  /** The transaction ID used in PREPARE TRANSACTION */\n  preparedTxId: string | undefined\n  /** Current retry attempt number (0 for first attempt, 1 for first retry, etc.) */\n  retryCount: number\n}\n\n/**\n * Create a transaction SQL client\n */\nfunction createTransactionSql(\n  transport: Transport,\n  parsers: Record<number, TypeParser>,\n  savepointCounter: { count: number },\n  txContext: TransactionContext\n): TransactionSql {\n  // Create the base tagged template function\n  const taggedTemplate = <T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): PendingQuery<T> => {\n    return createPendingQuery<T>(transport, strings, values, parsers)\n  }\n\n  // Middleware array for TransactionSql (usually empty within transaction)\n  const txMiddlewares: QueryMiddleware[] = []\n\n  // Create the transaction sql object with all required methods\n  const txSql = Object.assign(taggedTemplate, {\n    unsafe: async <T extends Row = Row>(\n      query: string,\n      params?: unknown[]\n    ): Promise<T[]> => {\n      const result = await transport.query<T>(query, params)\n      return parseRows(result.rows, result.fields, parsers)\n    },\n\n    savepoint: async <T>(\n      fn: (sql: TransactionSql) => Promise<T>\n    ): Promise<T> => {\n      const savepointName = `sp_${++savepointCounter.count}`\n\n      // Create savepoint\n      await transport.query(`SAVEPOINT ${savepointName}`)\n\n      try {\n        const result = await fn(txSql as unknown as TransactionSql)\n        // Release savepoint on success\n        await transport.query(`RELEASE SAVEPOINT ${savepointName}`)\n        return result\n      } catch (error) {\n        // Rollback to savepoint on error\n        await transport.query(`ROLLBACK TO SAVEPOINT ${savepointName}`)\n        throw error\n      }\n    },\n\n    stream: <T extends Row = Row>(\n      strings: TemplateStringsArray,\n      ...values: unknown[]\n    ): StreamResult<T> => {\n      const { sql: query, params } = buildStreamSql(strings, values)\n      return createStreamResult<T>(transport, query, params, parsers)\n    },\n\n    use: function (middleware: QueryMiddleware): TransactionSql {\n      txMiddlewares.push(middleware)\n      return txSql as unknown as TransactionSql\n    },\n\n    options: {\n      parsers,\n      serializers: {} as Record<number, (value: unknown) => string>,\n    },\n\n    // =========================================================================\n    // Advisory Lock Methods\n    // =========================================================================\n    // PostgreSQL advisory locks are application-level cooperative locks.\n    // Transaction-scoped locks (*_xact_*) are automatically released when\n    // the transaction ends (commit or rollback).\n\n    /**\n     * Acquire an exclusive advisory lock (blocking).\n     * Supports single-key (bigint) and two-key (int4, int4) variants.\n     */\n    advisoryLock: async (keyOrClassId: number | bigint, objId?: number): Promise<void> => {\n      if (objId !== undefined) {\n        // Two-key variant: pg_advisory_xact_lock(classid, objid)\n        validateTwoKeyLock(keyOrClassId as number, objId)\n        await transport.query(buildAdvisoryLockSql('pg_advisory_xact_lock', keyOrClassId as number, objId))\n      } else {\n        // Single-key variant: pg_advisory_xact_lock(key)\n        validateLockKey(keyOrClassId)\n        await transport.query(buildAdvisoryLockSql('pg_advisory_xact_lock', keyOrClassId))\n      }\n    },\n\n    /**\n     * Try to acquire an exclusive advisory lock (non-blocking).\n     * Returns true if lock acquired, false if lock is held by another session.\n     */\n    tryAdvisoryLock: async (keyOrClassId: number | bigint, objId?: number): Promise<boolean> => {\n      let sql: string\n      if (objId !== undefined) {\n        validateTwoKeyLock(keyOrClassId as number, objId)\n        sql = buildAdvisoryLockSql('pg_try_advisory_xact_lock', keyOrClassId as number, objId)\n      } else {\n        validateLockKey(keyOrClassId)\n        sql = buildAdvisoryLockSql('pg_try_advisory_xact_lock', keyOrClassId)\n      }\n      const result = await transport.query<{ pg_try_advisory_xact_lock: boolean }>(sql)\n      return result.rows[0]?.pg_try_advisory_xact_lock ?? false\n    },\n\n    /**\n     * Acquire a shared advisory lock (blocking).\n     * Multiple sessions can hold a shared lock simultaneously.\n     * Blocks if an exclusive lock is held.\n     */\n    advisoryLockShared: async (keyOrClassId: number | bigint, objId?: number): Promise<void> => {\n      if (objId !== undefined) {\n        validateTwoKeyLock(keyOrClassId as number, objId)\n        await transport.query(buildAdvisoryLockSql('pg_advisory_xact_lock_shared', keyOrClassId as number, objId))\n      } else {\n        validateLockKey(keyOrClassId)\n        await transport.query(buildAdvisoryLockSql('pg_advisory_xact_lock_shared', keyOrClassId))\n      }\n    },\n\n    /**\n     * Try to acquire a shared advisory lock (non-blocking).\n     * Returns true if lock acquired, false if an exclusive lock is held.\n     */\n    tryAdvisoryLockShared: async (keyOrClassId: number | bigint, objId?: number): Promise<boolean> => {\n      let sql: string\n      if (objId !== undefined) {\n        validateTwoKeyLock(keyOrClassId as number, objId)\n        sql = buildAdvisoryLockSql('pg_try_advisory_xact_lock_shared', keyOrClassId as number, objId)\n      } else {\n        validateLockKey(keyOrClassId)\n        sql = buildAdvisoryLockSql('pg_try_advisory_xact_lock_shared', keyOrClassId)\n      }\n      const result = await transport.query<{ pg_try_advisory_xact_lock_shared: boolean }>(sql)\n      return result.rows[0]?.pg_try_advisory_xact_lock_shared ?? false\n    },\n\n    // Two-phase commit support - allows distributed transaction coordination\n    prepare: async (transactionId: string): Promise<string> => {\n      validateTransactionId(transactionId)\n      txContext.isPrepared = true\n      txContext.preparedTxId = transactionId\n      await transport.query(`PREPARE TRANSACTION '${transactionId}'`)\n      return transactionId\n    },\n\n    // Transaction hooks\n    onCommit: (fn: () => void | Promise<void>): void => {\n      txContext.onCommitCallbacks.push(fn)\n    },\n\n    onRollback: (fn: () => void | Promise<void>): void => {\n      txContext.onRollbackCallbacks.push(fn)\n    },\n  }) as unknown as TransactionSql\n\n  // Define 'txid' as a getter that reads from context (Object.assign doesn't preserve getters).\n  // The txid is eagerly fetched after BEGIN via txid_current() and stored in txContext.\n  Object.defineProperty(txSql, 'txid', {\n    get: () => txContext.txid,\n    configurable: true,\n    enumerable: true,\n  })\n\n  // Define 'name' as a getter for the user-provided transaction name (function.name is read-only)\n  Object.defineProperty(txSql, 'name', {\n    get: () => txContext.txName,\n    configurable: true,\n    enumerable: true,\n  })\n\n  // Define 'retryCount' as a getter for the current retry attempt number\n  Object.defineProperty(txSql, 'retryCount', {\n    get: () => txContext.retryCount,\n    configurable: true,\n    enumerable: true,\n  })\n\n  return txSql\n}\n\n/**\n * Create the main SQL client\n */\nexport function createClient(config: PostgresConfig = {}): Sql {\n  // Merge default parsers with custom parsers\n  const parsers: Record<number, TypeParser> = {\n    ...DEFAULT_PARSERS,\n    ...config.parsers,\n  }\n\n  // Determine base URL\n  let baseUrl = config.url || 'https://db.postgres.do'\n  if (!baseUrl.startsWith('http')) {\n    // Parse as postgres:// URL\n    const parsed = parseConnectionUrl(baseUrl)\n    baseUrl = parsed.url || 'https://db.postgres.do'\n    config = { ...config, ...parsed }\n  }\n\n  // Create transport\n  const transport: Transport = config.transport === 'ws'\n    ? createRpcTransport({\n        url: baseUrl.replace('https://', 'wss://').replace('http://', 'ws://') + '/rpc',\n        apiKey: config.apiKey,\n        WebSocket: config.WebSocket,\n        connectTimeout: config.connectTimeout,\n      })\n    : createHttpTransport({\n        baseUrl,\n        apiKey: config.apiKey,\n        fetch: config.fetch,\n        timeout: config.queryTimeout,\n      })\n\n  // Middleware array - mutable to support .use() chaining\n  const middlewares: QueryMiddleware[] = []\n\n  /**\n   * Main SQL tagged template function\n   */\n  const sql = function <T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): PendingQuery<T> {\n    return createPendingQuery<T>(transport, strings, values, parsers, middlewares)\n  } as Sql\n\n  /**\n   * Execute raw SQL query (used by Drizzle ORM)\n   */\n  sql.unsafe = async <T extends Row = Row>(\n    query: string,\n    params?: unknown[]\n  ): Promise<T[]> => {\n    if (middlewares.length === 0) {\n      const result = await transport.query<T>(query, params)\n      return parseRows(result.rows, result.fields, parsers)\n    }\n\n    // Execute through middleware chain\n    const request: QueryRequest = {\n      sql: query,\n      params: params || [],\n      timestamp: Date.now(),\n      queryId: generateQueryId(),\n    }\n\n    const response = await executeWithMiddleware<T>(\n      middlewares as QueryMiddleware<T>[],\n      request,\n      async () => transport.query<T>(query, params)\n    )\n\n    if (!response.success && response.error) {\n      throw response.error\n    }\n\n    return parseRows(response.result.rows, response.result.fields, parsers)\n  }\n\n  /**\n   * Begin a transaction\n   */\n  sql.begin = async <T>(\n    fn: (sql: TransactionSql) => Promise<T>,\n    options?: TransactionOptions\n  ): Promise<T> => {\n    // Merge client-level transactionRetry defaults with transaction-level options\n    // Transaction-level options override client-level defaults\n    const clientRetryConfig = config.transactionRetry ?? {}\n    const maxRetries = options?.maxRetries ?? clientRetryConfig.maxRetries ?? 3\n    const shouldRetryOnSerializationFailure = options?.retryOnSerializationFailure ?? clientRetryConfig.retryOnSerializationFailure ?? false\n    const shouldRetryOnDeadlock = options?.retryOnDeadlock ?? clientRetryConfig.retryOnDeadlock ?? false\n    const backoffMs = options?.backoffMs ?? clientRetryConfig.backoffMs ?? 10\n    const onRetry = options?.onRetry\n\n    /**\n     * Check if an error is retryable based on the configured options.\n     * Retryable errors are:\n     * - 40001: Serialization failure (when retryOnSerializationFailure is enabled)\n     * - 40P01: Deadlock detected (when retryOnDeadlock is enabled)\n     */\n    const isRetryableError = (error: unknown): boolean => {\n      if (!(error instanceof PostgresError)) {\n        return false\n      }\n      if (shouldRetryOnSerializationFailure && error.pgCode === '40001') {\n        return true\n      }\n      if (shouldRetryOnDeadlock && error.pgCode === '40P01') {\n        return true\n      }\n      return false\n    }\n\n    // Track start time for total timeout across retries\n    // Note: totalTimeout can be 0 (immediate timeout), undefined (no timeout), or negative (treated as no timeout)\n    // Fall back to client-level queryTimeout if transaction-level timeout is not specified\n    const effectiveTimeout = options?.timeout ?? config.queryTimeout\n    // Negative timeouts are treated as \"no timeout\" for backward compatibility\n    const hasTotalTimeout = effectiveTimeout !== undefined && effectiveTimeout >= 0\n    const totalTimeout = hasTotalTimeout ? effectiveTimeout : undefined\n    const startTime = hasTotalTimeout ? Date.now() : 0\n    const perRetryTimeout = options?.perRetryTimeout\n\n    /**\n     * Calculate the timeout for the current attempt.\n     *\n     * Timeout precedence:\n     * 1. If `timeout` is set (including 0), use the remaining time from the total timeout\n     * 2. If only `perRetryTimeout` is set, use it directly (fresh timeout per attempt)\n     * 3. If neither is set, return undefined (no timeout)\n     *\n     * Returns undefined if no timeout is set.\n     * Throws TimeoutError if total timeout has been exceeded.\n     */\n    const getAttemptTimeout = (): number | undefined => {\n      // Total timeout takes precedence (including 0)\n      if (hasTotalTimeout && totalTimeout !== undefined) {\n        const elapsed = Date.now() - startTime\n        const remaining = totalTimeout - elapsed\n        if (remaining <= 0) {\n          throw new TimeoutError(`Transaction timed out after ${totalTimeout}ms`)\n        }\n        return remaining\n      }\n\n      // Per-retry timeout: each attempt gets a fresh timeout\n      if (perRetryTimeout) {\n        return perRetryTimeout\n      }\n\n      return undefined\n    }\n\n    const executeTransaction = async (attempt: number): Promise<T> => {\n      // Check if we've exceeded total timeout before starting a new attempt\n      // This check is for retry attempts where time has already elapsed\n      if (hasTotalTimeout && attempt > 1) {\n        getAttemptTimeout() // Throws if timeout exceeded during retries\n      }\n\n      // Build BEGIN statement with options\n      const beginParts = ['BEGIN']\n\n      if (options?.isolationLevel) {\n        // Validate isolation level to prevent SQL injection\n        const validLevels = ['read uncommitted', 'read committed', 'repeatable read', 'serializable']\n        const normalized = options.isolationLevel.toLowerCase()\n        if (!validLevels.includes(normalized)) {\n          throw new Error(`Invalid isolation level: \"${options.isolationLevel}\"`)\n        }\n        beginParts.push(`ISOLATION LEVEL ${normalized.toUpperCase()}`)\n      }\n      if (options?.readOnly) {\n        beginParts.push('READ ONLY')\n      }\n      if (options?.deferrable) {\n        beginParts.push('DEFERRABLE')\n      }\n\n      // Start transaction - may fail with serialization failure in rare cases\n      try {\n        await transport.query(beginParts.join(' '))\n      } catch (beginError) {\n        // Check if BEGIN failed with a retryable error\n        if (isRetryableError(beginError) && attempt < maxRetries) {\n          // Call onRetry callback if provided\n          if (onRetry) {\n            await onRetry(attempt, beginError as Error)\n          }\n          // Exponential backoff\n          const delay = backoffMs * Math.pow(2, attempt - 1)\n          await new Promise((resolve) => setTimeout(resolve, delay))\n          return executeTransaction(attempt + 1)\n        }\n        throw beginError\n      }\n\n      // Create transaction context\n      const txContext: TransactionContext = {\n        txid: undefined,\n        txName: options?.name,\n        onCommitCallbacks: [],\n        onRollbackCallbacks: [],\n        isPrepared: false,\n        preparedTxId: undefined,\n        retryCount: attempt - 1, // 0 for first attempt, 1 for first retry, etc.\n      }\n\n      const savepointCounter = { count: 0 }\n      const txSql = createTransactionSql(transport, parsers, savepointCounter, txContext)\n\n      // Eagerly fetch PostgreSQL transaction ID (xid) so it's available throughout the callback.\n      // This queries txid_current() which returns the internal transaction identifier,\n      // useful for debugging, logging, and correlating with pg_stat_activity or pg_locks.\n      // Errors are silently ignored since txid is optional debugging metadata.\n      try {\n        const txidResult = await transport.query<{ txid_current: string }>('SELECT txid_current()::text')\n        txContext.txid = txidResult.rows[0]?.txid_current\n      } catch {\n        // Non-fatal: txid is optional metadata for debugging/logging\n      }\n\n      // Handle timeout if specified - uses remaining time from total timeout or per-retry timeout\n      // The timeout wraps the entire transaction including user callback AND COMMIT\n      let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n      let timedOut = false\n\n      const attemptTimeout = getAttemptTimeout()\n      if (attemptTimeout !== undefined) {\n        timeoutHandle = setTimeout(() => {\n          timedOut = true\n        }, attemptTimeout)\n      }\n\n      /**\n       * Check if we've timed out and throw if so.\n       * This is called at key points during the transaction.\n       */\n      const checkTimeout = (): void => {\n        if (timedOut) {\n          const timeoutForMessage = totalTimeout ?? perRetryTimeout ?? attemptTimeout\n          throw new TimeoutError(`Transaction timed out after ${timeoutForMessage}ms`)\n        }\n      }\n\n      try {\n        // Execute user callback\n        const result = await fn(txSql)\n\n        // Check for timeout after user callback\n        checkTimeout()\n\n        // If transaction was prepared for 2PC, don't COMMIT\n        if (txContext.isPrepared) {\n          // onCommit callbacks will be called when commitPrepared is called\n          if (timeoutHandle) clearTimeout(timeoutHandle)\n          return result\n        }\n\n        // COMMIT is also covered by the timeout\n        await transport.query('COMMIT')\n\n        // Check for timeout after COMMIT\n        checkTimeout()\n\n        // Clear timeout after successful commit\n        if (timeoutHandle) clearTimeout(timeoutHandle)\n\n        // Execute onCommit callbacks (errors logged but not propagated)\n        await executeTransactionCallbacks(txContext.onCommitCallbacks, 'commit')\n\n        return result\n      } catch (error) {\n        // Clear timeout if still pending\n        if (timeoutHandle) {\n          clearTimeout(timeoutHandle)\n        }\n\n        // If we timed out during execution, throw TimeoutError\n        if (timedOut && !(error instanceof TimeoutError)) {\n          const timeoutForMessage = totalTimeout ?? perRetryTimeout ?? attemptTimeout\n          throw new TimeoutError(`Transaction timed out after ${timeoutForMessage}ms`)\n        }\n\n        // Always attempt ROLLBACK on error (including timeout) unless prepared for 2PC.\n        // Even if the transaction timed out, PostgreSQL still has an open transaction\n        // that needs cleanup to avoid leaving connections in bad state.\n        if (!txContext.isPrepared) {\n          try {\n            await transport.query('ROLLBACK')\n          } catch {\n            // Ignore rollback errors - connection might be in invalid state\n          }\n        }\n\n        // Execute onRollback callbacks (errors logged but not propagated)\n        await executeTransactionCallbacks(txContext.onRollbackCallbacks, 'rollback')\n\n        // Don't retry if we've hit a timeout\n        if (error instanceof TimeoutError) {\n          throw error\n        }\n\n        // Check for retryable errors (serialization failure or deadlock)\n        if (isRetryableError(error) && attempt < maxRetries) {\n          // Call onRetry callback if provided\n          if (onRetry) {\n            await onRetry(attempt, error as Error)\n          }\n          // Exponential backoff\n          const delay = backoffMs * Math.pow(2, attempt - 1)\n          await new Promise((resolve) => setTimeout(resolve, delay))\n          return executeTransaction(attempt + 1)\n        }\n\n        throw error\n      }\n    }\n\n    return executeTransaction(1)\n  }\n\n  /**\n   * Create a savepoint (only valid within a transaction)\n   */\n  sql.savepoint = async <T>(\n    _fn: (sql: TransactionSql) => Promise<T>\n  ): Promise<T> => {\n    throw new PostgresError('savepoint() can only be called within a transaction', {\n      code: '25001',\n      severity: 'ERROR',\n    })\n  }\n\n  /**\n   * Stream large result sets using PostgreSQL cursors\n   * Memory stays constant regardless of result size\n   */\n  sql.stream = <T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): StreamResult<T> => {\n    const { sql: query, params } = buildStreamSql(strings, values)\n    return createStreamResult<T>(transport, query, params, parsers)\n  }\n\n  /**\n   * End the connection\n   */\n  sql.end = async (): Promise<void> => {\n    await transport.close()\n  }\n\n  /**\n   * Reserve a connection (for connection pooling scenarios)\n   */\n  sql.reserve = async (): Promise<ReservedSql> => {\n    // For HTTP transport, we create a new instance\n    // For WS transport, we could potentially implement true connection reservation\n    const reservedSql = createClient(config) as ReservedSql\n    reservedSql.release = async () => {\n      await reservedSql.end()\n    }\n    return reservedSql\n  }\n\n  /**\n   * Commit a prepared transaction (two-phase commit)\n   */\n  sql.commitPrepared = async (transactionId: string): Promise<void> => {\n    validateTransactionId(transactionId)\n    await transport.query(`COMMIT PREPARED '${transactionId}'`)\n  }\n\n  /**\n   * Rollback a prepared transaction (two-phase commit)\n   */\n  sql.rollbackPrepared = async (transactionId: string): Promise<void> => {\n    validateTransactionId(transactionId)\n    await transport.query(`ROLLBACK PREPARED '${transactionId}'`)\n  }\n\n  /**\n   * Add a middleware to the chain\n   * Returns the same Sql instance for chaining\n   */\n  sql.use = function (middleware: QueryMiddleware): Sql {\n    middlewares.push(middleware)\n    return sql\n  }\n\n  /**\n   * Options object (for Drizzle compatibility)\n   * Includes both parsers and serializers that Drizzle expects\n   */\n  sql.options = {\n    parsers,\n    serializers: {} as Record<number, (value: unknown) => string>,\n  }\n\n  // ===========================================================================\n  // CDC Subscription Implementation\n  // ===========================================================================\n  //\n  // CDC (Change Data Capture) provides real-time streaming of database changes.\n  // This implementation uses a single shared transport (WebSocket or SSE) for\n  // all subscriptions to minimize resource usage and connection overhead.\n\n  // ---------------------------------------------------------------------------\n  // CDC State Management\n  // ---------------------------------------------------------------------------\n  //\n  // Transport lifecycle:\n  //   null -> pending (creating) -> connected -> null (disconnected)\n  //\n  // cdcTransport: Holds the active connection once established\n  // cdcTransportPending: Acts as a mutex/lock to prevent duplicate transports\n  //                      when multiple subscribe() calls race during initialization\n  let cdcTransport: CDCTransport | null = null\n  let cdcTransportPending: Promise<CDCTransport> | null = null\n  const activeSubscriptions = new Map<string, CDCSubscription>()\n\n  /**\n   * Create a CDC transport instance based on configuration.\n   *\n   * Encapsulates transport creation logic, keeping the main concurrency\n   * control function focused on its primary responsibility.\n   *\n   * @param cdcUrl - The CDC endpoint URL (wss:// for WebSocket, https:// for SSE)\n   * @returns The created transport instance (not yet connected)\n   */\n  function createCdcTransportInstance(cdcUrl: string): CDCTransport {\n    if (config.transport === 'ws') {\n      // WebSocket transport: bidirectional, lower latency, requires WS support\n      const wsConfig: Parameters<typeof createCdcWsTransport>[0] = { url: cdcUrl }\n      if (config.apiKey !== undefined) wsConfig.apiKey = config.apiKey\n      if (config.WebSocket !== undefined) wsConfig.WebSocket = config.WebSocket\n      if (config.connectTimeout !== undefined) wsConfig.connectTimeout = config.connectTimeout\n      return createCdcWsTransport(wsConfig)\n    } else {\n      // SSE transport: HTTP-based, works through proxies, wider compatibility\n      const sseConfig: Parameters<typeof createCdcSseTransport>[0] = { url: cdcUrl }\n      if (config.apiKey !== undefined) sseConfig.apiKey = config.apiKey\n      if (config.fetch !== undefined) sseConfig.fetch = config.fetch\n      return createCdcSseTransport(sseConfig)\n    }\n  }\n\n  /**\n   * Configure event handlers for a CDC transport.\n   *\n   * Routes transport-level events to the appropriate subscription instances\n   * and handles transport lifecycle events (close/disconnect).\n   *\n   * @param transport - The CDC transport to configure\n   */\n  function configureCdcTransportHandlers(transport: CDCTransport): void {\n    // Route CDC change events to the subscription that owns them\n    transport.onEvent((subscriptionId: string, event) => {\n      const subscription = activeSubscriptions.get(subscriptionId)\n      if (subscription) {\n        subscription.handleEvent(event)\n      }\n    })\n\n    // Route errors to the subscription that should handle them\n    transport.onError((subscriptionId: string, error) => {\n      const subscription = activeSubscriptions.get(subscriptionId)\n      if (subscription) {\n        subscription.handleError(error)\n      }\n    })\n\n    // Handle transport close: mark all subscriptions inactive and reset state\n    transport.onClose(() => {\n      activeSubscriptions.forEach(subscription => {\n        subscription.setInactive()\n      })\n      activeSubscriptions.clear()\n      // Reset transport state to allow fresh reconnection on next subscribe()\n      cdcTransport = null\n      cdcTransportPending = null\n    })\n  }\n\n  /**\n   * Get or create the shared CDC transport.\n   *\n   * CONCURRENCY CONTROL - PENDING PROMISE PATTERN:\n   * -----------------------------------------------\n   * This function uses a \"pending promise\" pattern to serialize transport\n   * creation and prevent race conditions when multiple subscribe() calls\n   * happen concurrently. Without this pattern, the following race occurs:\n   *\n   *   Call A: checks cdcTransport (null) -> starts creating transport\n   *   Call B: checks cdcTransport (null) -> starts creating ANOTHER transport\n   *   Call A: finishes, sets cdcTransport\n   *   Call B: finishes, OVERWRITES cdcTransport (resource leak!)\n   *\n   * The pattern works in four steps:\n   *\n   * STEP 1 - FAST PATH: If cdcTransport exists, return it immediately.\n   *          This is the common case after initial connection.\n   *\n   * STEP 2 - AWAIT PENDING: If cdcTransportPending is set, another call is\n   *          already creating the transport. Await that same promise to share\n   *          the result. This prevents duplicate transports.\n   *\n   * STEP 3 - CREATE NEW: We're the first caller. Set cdcTransportPending\n   *          SYNCHRONOUSLY (before any await) so concurrent calls will see it\n   *          and wait for our promise. Then perform async creation.\n   *\n   * STEP 4 - CLEANUP: In the finally block, clear cdcTransportPending.\n   *          On success: cdcTransport is set, subsequent calls use fast path\n   *          On failure: cdcTransport is null, next call can retry fresh\n   *\n   * @returns The shared CDC transport instance\n   * @throws {ConnectionError} If transport creation or connection fails\n   */\n  const getOrCreateCdcTransport = async (): Promise<CDCTransport> => {\n    // -------------------------------------------------------------------------\n    // STEP 1: FAST PATH - Return existing transport\n    // -------------------------------------------------------------------------\n    if (cdcTransport) {\n      return cdcTransport\n    }\n\n    // -------------------------------------------------------------------------\n    // STEP 2: AWAIT PENDING - Join existing creation in progress\n    // -------------------------------------------------------------------------\n    // CRITICAL: This check must happen BEFORE we set cdcTransportPending below.\n    // cdcTransportPending acts as a mutex - if set, await it instead of racing.\n    if (cdcTransportPending) {\n      return cdcTransportPending\n    }\n\n    // -------------------------------------------------------------------------\n    // STEP 3: CREATE NEW - We're first, set pending SYNCHRONOUSLY then await\n    // -------------------------------------------------------------------------\n    // Set cdcTransportPending IMMEDIATELY (no await before this line).\n    // Any concurrent calls arriving during our async work will see this\n    // pending promise and await it instead of starting their own creation.\n    cdcTransportPending = (async (): Promise<CDCTransport> => {\n      // Build CDC endpoint URL (wss:// for WebSocket, https:// for SSE)\n      const cdcUrl = baseUrl.replace('https://', config.transport === 'ws' ? 'wss://' : 'https://') + '/cdc'\n\n      // Create transport instance (helper function for clarity)\n      const transport = createCdcTransportInstance(cdcUrl)\n\n      // Wire up event handlers to route events to subscriptions\n      configureCdcTransportHandlers(transport)\n\n      // Connect to server - THIS is the async operation that creates the race\n      // window that cdcTransportPending protects against\n      await transport.connect()\n\n      // Store for fast path on subsequent calls\n      cdcTransport = transport\n      return transport\n    })()\n\n    try {\n      return await cdcTransportPending\n    } finally {\n      // -----------------------------------------------------------------------\n      // STEP 4: CLEANUP - Clear pending regardless of success/failure\n      // -----------------------------------------------------------------------\n      // SUCCESS: cdcTransport is set -> subsequent calls use fast path\n      // FAILURE: cdcTransport is null -> next call retries fresh\n      //\n      // The finally block ensures we never leave cdcTransportPending set\n      // indefinitely, which would block all future subscribe() calls.\n      cdcTransportPending = null\n    }\n  }\n\n  /**\n   * Subscribe to changes on a table\n   */\n  sql.subscribe = async <T extends Row = Row>(\n    tableName: string,\n    options?: CDCClientSubscribeOptions<T>\n  ): Promise<CDCClientSubscription<T>> => {\n    // Validate table name to prevent SQL injection\n    const { table, schema } = validateTableName(tableName)\n\n    // Get or create CDC transport\n    const transport = await getOrCreateCdcTransport()\n\n    // Generate subscription ID\n    const subscriptionId = generateSubscriptionId()\n\n    // Create unsubscribe callback\n    const unsubscribeCallback = async (): Promise<void> => {\n      activeSubscriptions.delete(subscriptionId)\n      await transport.unsubscribe(subscriptionId)\n\n      // If no more subscriptions, disconnect the transport\n      if (activeSubscriptions.size === 0 && cdcTransport) {\n        await cdcTransport.disconnect()\n        cdcTransport = null\n      }\n    }\n\n    // Create subscription instance\n    const subscription = new CDCSubscription<T>(\n      subscriptionId,\n      table,\n      schema,\n      transport,\n      unsubscribeCallback,\n      options as SubscribeOptions\n    )\n\n    // Register subscription\n    activeSubscriptions.set(subscriptionId, subscription as CDCSubscription)\n\n    // Subscribe via transport - build options object only with defined values\n    const subscriptionOptions: Parameters<typeof transport.subscribe>[3] = {}\n    if (options?.events !== undefined) subscriptionOptions.events = options.events\n    if (options?.filter !== undefined) subscriptionOptions.filter = options.filter\n    if (options?.resumeFrom !== undefined) subscriptionOptions.resumeFrom = options.resumeFrom\n    if (options?.includeOldRow !== undefined) subscriptionOptions.includeOldRow = options.includeOldRow\n    if (options?.trackChangedColumns !== undefined) subscriptionOptions.trackChangedColumns = options.trackChangedColumns\n    if (options?.batchSize !== undefined) subscriptionOptions.batchSize = options.batchSize\n    if (options?.heartbeatInterval !== undefined) subscriptionOptions.heartbeatInterval = options.heartbeatInterval\n    await transport.subscribe(subscriptionId, table, schema, subscriptionOptions)\n\n    return subscription\n  }\n\n  /**\n   * Unsubscribe from a subscription by ID\n   */\n  sql.unsubscribe = async (subscriptionId: string): Promise<void> => {\n    const subscription = activeSubscriptions.get(subscriptionId)\n    if (subscription) {\n      await subscription.unsubscribe()\n    }\n    // If subscription not found, silently succeed (idempotent behavior)\n  }\n\n  /**\n   * Get all active subscriptions\n   */\n  sql.subscriptions = (): CDCClientSubscriptionInfo[] => {\n    return Array.from(activeSubscriptions.values()).map(sub => ({\n      id: sub.id,\n      table: sub.table,\n      schema: sub.schema,\n      isActive: sub.isActive,\n    }))\n  }\n\n  return sql\n}\n\n/**\n * Main entry point - create a postgres client\n * @param urlOrConfig - Connection URL or config object\n * @param options - Additional options\n */\nexport function postgres(\n  urlOrConfig?: string | PostgresConfig,\n  options?: PostgresConfig\n): Sql {\n  if (typeof urlOrConfig === 'string') {\n    const parsed = parseConnectionUrl(urlOrConfig)\n    return createClient({ ...parsed, ...options })\n  }\n\n  return createClient({ ...urlOrConfig, ...options })\n}\n\n// Default export\nexport default postgres\n","/**\n * Authentication integration for postgres.do\n *\n * Provides authentication helpers using oauth.do for both\n * client-side (browser) and server-side (Node.js/Cloudflare Workers) usage.\n *\n * The DO-based architecture means each authenticated user can have their own\n * database, simplifying security by eliminating row-level access control.\n */\n\n// Re-export from oauth.do based on environment\n// Users should import from the appropriate subpath for their environment:\n// - Server: import { ensureLoggedIn } from 'oauth.do/node'\n// - Browser: import { ensureLoggedIn } from 'oauth.do/browser'\n\nimport type { Sql, PostgresConfig } from './types'\nimport { createClient } from './client'\nimport {\n  // Re-export shared auth types and utilities\n  type AuthenticatedUser,\n  type AuthTokenValidationResult as TokenValidationResult,\n  extractBearerToken,\n  generateDatabaseId,\n  validateToken as sharedValidateToken,\n  DEFAULT_OAUTH_URL,\n} from '@dotdo/postgres-shared'\n\n// Re-export for backwards compatibility\nexport type { AuthenticatedUser, TokenValidationResult }\nexport { extractBearerToken, generateDatabaseId }\n\nexport interface AuthenticatedClientOptions extends PostgresConfig {\n  /** OAuth API URL (default: https://oauth.do) */\n  oauthUrl?: string\n}\n\nexport interface AuthenticatedContext {\n  user: AuthenticatedUser\n  token: string\n}\n\n/**\n * Create an authenticated postgres client for server-side usage\n *\n * This function verifies the user's authentication token and returns\n * a postgres client configured for their specific database.\n *\n * @example\n * ```typescript\n * import { createAuthenticatedClient } from 'postgres.do'\n * import { ensureLoggedIn } from 'oauth.do/node'\n *\n * export default {\n *   async fetch(request: Request) {\n *     // Verify authentication\n *     const auth = await ensureLoggedIn(request)\n *\n *     // Create client for this user's database\n *     const sql = createAuthenticatedClient(auth.token, {\n *       url: `https://db.postgres.do/${auth.user.id}`\n *     })\n *\n *     const users = await sql`SELECT * FROM users`\n *     return Response.json(users)\n *   }\n * }\n * ```\n */\nexport function createAuthenticatedClient(\n  token: string,\n  options: AuthenticatedClientOptions = {}\n): Sql {\n  return createClient({\n    ...options,\n    apiKey: token,\n  })\n}\n\n/**\n * Create a postgres client from an authenticated request (server-side)\n *\n * This is a convenience function that extracts the Bearer token from\n * the request Authorization header.\n *\n * @example\n * ```typescript\n * import { createClientFromRequest } from 'postgres.do'\n *\n * export default {\n *   async fetch(request: Request) {\n *     const sql = createClientFromRequest(request, {\n *       url: 'https://db.postgres.do/mydb'\n *     })\n *\n *     const users = await sql`SELECT * FROM users`\n *     return Response.json(users)\n *   }\n * }\n * ```\n */\nexport function createClientFromRequest(\n  request: Request,\n  options: AuthenticatedClientOptions = {}\n): Sql {\n  const authHeader = request.headers.get('Authorization')\n  const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : undefined\n\n  const clientOptions = { ...options }\n  if (token !== undefined) {\n    clientOptions.apiKey = token\n  }\n  return createClient(clientOptions)\n}\n\n/**\n * Higher-order function to wrap a request handler with authentication\n *\n * @example\n * ```typescript\n * import { withAuth } from 'postgres.do'\n *\n * export default {\n *   fetch: withAuth(async (request, { user, sql }) => {\n *     // user is guaranteed to be authenticated\n *     // sql is configured for this user's database\n *     const data = await sql`SELECT * FROM my_table`\n *     return Response.json({ user, data })\n *   })\n * }\n * ```\n */\nexport function withAuth(\n  handler: (\n    request: Request,\n    context: { user: AuthenticatedUser; sql: Sql; token: string }\n  ) => Promise<Response>,\n  options: AuthenticatedClientOptions & {\n    /** Custom function to verify and extract user from token */\n    verifyToken?: (token: string) => Promise<AuthenticatedUser | null>\n    /** URL to get database URL for user (default: uses user.id) */\n    getDatabaseUrl?: (user: AuthenticatedUser) => string\n    /** Custom unauthorized response */\n    onUnauthorized?: (request: Request) => Response\n  } = {}\n): (request: Request) => Promise<Response> {\n  return async (request: Request): Promise<Response> => {\n    // Extract token from Authorization header\n    const authHeader = request.headers.get('Authorization')\n    const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null\n\n    if (!token) {\n      if (options.onUnauthorized) {\n        return options.onUnauthorized(request)\n      }\n      return new Response(JSON.stringify({ error: 'Unauthorized' }), {\n        status: 401,\n        headers: { 'Content-Type': 'application/json' },\n      })\n    }\n\n    // Verify token and get user\n    let user: AuthenticatedUser | null = null\n\n    if (options.verifyToken) {\n      user = await options.verifyToken(token)\n    } else {\n      // Default: verify with oauth.do using shared validateToken\n      const oauthUrl = options.oauthUrl || DEFAULT_OAUTH_URL\n      const result = await sharedValidateToken(token, { oauthUrl })\n      if (result.valid && result.user) {\n        user = result.user\n      }\n    }\n\n    if (!user) {\n      if (options.onUnauthorized) {\n        return options.onUnauthorized(request)\n      }\n      return new Response(JSON.stringify({ error: 'Invalid token' }), {\n        status: 401,\n        headers: { 'Content-Type': 'application/json' },\n      })\n    }\n\n    // Get database URL for this user\n    const dbUrl = options.getDatabaseUrl\n      ? options.getDatabaseUrl(user)\n      : `https://db.postgres.do/${user.id}`\n\n    // Create authenticated SQL client\n    const sql = createClient({\n      ...options,\n      url: dbUrl,\n      apiKey: token,\n    })\n\n    try {\n      return await handler(request, { user, sql, token })\n    } finally {\n      // Clean up connection\n      await sql.end()\n    }\n  }\n}\n\n/**\n * Extract user ID from a request's authentication token\n * Useful when you need just the user ID without creating a client\n */\nexport async function extractUserId(\n  request: Request,\n  options: { oauthUrl?: string } = {}\n): Promise<string | null> {\n  const token = extractBearerToken(request)\n\n  if (!token) {\n    return null\n  }\n\n  const oauthUrl = options.oauthUrl || DEFAULT_OAUTH_URL\n  const result = await sharedValidateToken(token, { oauthUrl })\n\n  if (result.valid && result.user) {\n    return result.user.id\n  }\n\n  return null\n}\n\n/**\n * Validate a token and return the full result\n */\nexport async function validateToken(\n  token: string,\n  options: { oauthUrl?: string } = {}\n): Promise<TokenValidationResult> {\n  const oauthUrl = options.oauthUrl || DEFAULT_OAUTH_URL\n  return sharedValidateToken(token, { oauthUrl })\n}\n\n/**\n * Create a user-scoped database client\n * The database URL is derived from the user's ID\n *\n * @example\n * ```typescript\n * import { createUserScopedClient } from 'postgres.do'\n *\n * // After validating the user\n * const sql = createUserScopedClient(user.id, token)\n *\n * const data = await sql`SELECT * FROM my_table`\n * ```\n */\nexport function createUserScopedClient(\n  userId: string,\n  token: string,\n  options: AuthenticatedClientOptions = {}\n): Sql {\n  // Generate user-scoped database URL using shared generateDatabaseId\n  const baseUrl = options.url || 'https://db.postgres.do'\n  const userDbUrl = `${baseUrl}/${generateDatabaseId(userId)}`\n\n  return createClient({\n    ...options,\n    url: userDbUrl,\n    apiKey: token,\n  })\n}\n","/**\n * Connection URL parsing for postgres.do\n *\n * Parses postgres:// URLs into configuration objects\n */\n\nimport type { PostgresConfig } from './types'\nimport { ConnectionError } from './types'\n\n/**\n * Parsed connection information\n */\nexport interface ConnectionInfo {\n  /** The https base URL for postgres.do */\n  url: string\n  /** Database name */\n  database?: string\n  /** API key for authentication */\n  apiKey?: string\n  /** SSL mode */\n  ssl?: PostgresConfig['ssl']\n  /** Additional parameters from URL query string */\n  params: Record<string, string>\n}\n\n/**\n * Parse a postgres:// connection URL\n *\n * @param connectionUrl - The postgres:// or postgresql:// URL\n * @returns Parsed connection information\n *\n * @example\n * ```typescript\n * // Basic URL\n * parseConnectionUrl('postgres://db.postgres.do/mydb')\n * // => { url: 'https://db.postgres.do/mydb', database: 'mydb', params: {} }\n *\n * // With API key in password\n * parseConnectionUrl('postgres://user:apikey123@db.postgres.do/mydb')\n * // => { url: 'https://db.postgres.do/mydb', apiKey: 'apikey123', params: {} }\n *\n * // With query parameters\n * parseConnectionUrl('postgres://db.postgres.do/mydb?sslmode=require')\n * // => { url: 'https://db.postgres.do/mydb', ssl: 'require', params: { sslmode: 'require' } }\n * ```\n */\nexport function parseConnectionUrl(connectionUrl: string): ConnectionInfo {\n  let parsed: URL\n\n  try {\n    parsed = new URL(connectionUrl)\n  } catch (error) {\n    throw new ConnectionError(\n      `Invalid connection URL: ${error instanceof Error ? error.message : String(error)}`\n    )\n  }\n\n  // Validate protocol\n  if (!parsed.protocol.startsWith('postgres')) {\n    throw new ConnectionError(\n      `Invalid protocol \"${parsed.protocol}\": must be postgres:// or postgresql://`\n    )\n  }\n\n  // Validate host is present\n  if (!parsed.host) {\n    throw new ConnectionError('Invalid connection URL: missing host')\n  }\n\n  // Extract components\n  const info: ConnectionInfo = {\n    url: `https://${parsed.host}${parsed.pathname}`,\n    params: {},\n  }\n\n  // Database name from pathname\n  const pathname = parsed.pathname\n  if (pathname && pathname !== '/') {\n    info.database = pathname.slice(1) // Remove leading /\n  }\n\n  // API key from password field\n  if (parsed.password) {\n    info.apiKey = decodeURIComponent(parsed.password)\n  }\n\n  // API key from query parameter (takes precedence)\n  const apiKeyParam = parsed.searchParams.get('apiKey') || parsed.searchParams.get('apikey')\n  if (apiKeyParam) {\n    info.apiKey = apiKeyParam\n  }\n\n  // SSL mode\n  const sslMode = parsed.searchParams.get('sslmode') || parsed.searchParams.get('ssl')\n  if (sslMode) {\n    info.ssl = sslMode as PostgresConfig['ssl']\n  }\n\n  // Collect all query parameters\n  for (const [key, value] of parsed.searchParams) {\n    info.params[key] = value\n  }\n\n  return info\n}\n\n/**\n * Convert ConnectionInfo to PostgresConfig\n */\nexport function connectionInfoToConfig(info: ConnectionInfo): Partial<PostgresConfig> {\n  const config: Partial<PostgresConfig> = {\n    url: info.url,\n  }\n\n  if (info.apiKey) {\n    config.apiKey = info.apiKey\n  }\n\n  if (info.ssl) {\n    config.ssl = info.ssl\n  }\n\n  // Handle transport parameter\n  const transport = info.params['transport']\n  if (transport === 'ws' || transport === 'websocket') {\n    config.transport = 'ws'\n  }\n\n  // Handle timeout parameters\n  const connectTimeout = info.params['connect_timeout'] || info.params['connectTimeout']\n  if (connectTimeout) {\n    config.connectTimeout = parseInt(connectTimeout, 10) * 1000 // Convert to ms\n  }\n\n  const queryTimeout = info.params['statement_timeout'] || info.params['queryTimeout']\n  if (queryTimeout) {\n    config.queryTimeout = parseInt(queryTimeout, 10) * 1000 // Convert to ms\n  }\n\n  return config\n}\n\n/**\n * Build a connection URL from config options\n */\nexport function buildConnectionUrl(config: PostgresConfig): string {\n  const baseUrl = config.url || 'https://db.postgres.do'\n  const url = new URL(baseUrl.replace('https://', 'postgres://').replace('http://', 'postgres://'))\n\n  if (config.apiKey) {\n    url.password = config.apiKey\n  }\n\n  if (config.ssl) {\n    url.searchParams.set('sslmode', typeof config.ssl === 'boolean' ? 'require' : config.ssl)\n  }\n\n  if (config.transport === 'ws') {\n    url.searchParams.set('transport', 'ws')\n  }\n\n  return url.toString()\n}\n\n/**\n * Validate a connection URL without parsing\n */\nexport function isValidConnectionUrl(connectionUrl: string): boolean {\n  try {\n    const url = new URL(connectionUrl)\n    return url.protocol.startsWith('postgres')\n  } catch {\n    return false\n  }\n}\n","/**\n * Lazy Extension Loader for PostgreSQL\n *\n * Provides lazy loading of PostgreSQL extensions to improve cold start times.\n * Extensions are loaded on-demand when they are first needed, either through\n * explicit calls or automatic detection from SQL queries.\n *\n * @module extensions\n *\n * @example\n * ```typescript\n * import { LazyExtensionLoader, createLazyExtensionLoader } from 'postgres.do/extensions'\n *\n * // Create a loader with a query executor\n * const loader = new LazyExtensionLoader({\n *   query: async (sql) => pg.exec(sql)\n * })\n *\n * // Explicitly ensure an extension is loaded\n * await loader.ensureLoaded('vector')\n *\n * // Auto-detect and load extensions from SQL\n * await loader.executeWithAutoLoad(\"SELECT embedding <-> '[1,2,3]' FROM items\")\n * ```\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Supported PostgreSQL extension names\n */\nexport type ExtensionName =\n  | 'vector'\n  | 'pg_trgm'\n  | 'pgcrypto'\n  | 'hstore'\n  | 'citext'\n  | 'uuid-ossp'\n  | 'cube'\n  | 'earthdistance'\n  | 'fuzzystrmatch'\n  | 'intarray'\n  | 'ltree'\n  | 'tablefunc'\n  | 'unaccent'\n  | 'btree_gin'\n  | 'btree_gist'\n  | 'bloom'\n\n/**\n * Metadata for a PostgreSQL extension\n */\nexport interface ExtensionMetadata {\n  /** Extension identifier used in our registry */\n  name: ExtensionName\n  /** Display name for the extension */\n  displayName: string\n  /** The actual PostgreSQL extension name (used in CREATE EXTENSION) */\n  extensionName: string\n  /** Description of what the extension provides */\n  description: string\n  /** Whether the extension is available in PGLite WASM */\n  available: boolean\n  /** Dependencies that must be loaded first */\n  dependencies?: ExtensionName[]\n  /** Regex patterns to detect when this extension is needed in SQL */\n  detectionPatterns: RegExp[]\n  /** Common functions provided by this extension */\n  functions?: string[]\n  /** Custom types provided by this extension */\n  types?: string[]\n  /** Custom operators provided by this extension */\n  operators?: string[]\n}\n\n/**\n * Interface for executing queries\n */\nexport interface QueryExecutor {\n  query(sql: string, params?: unknown[]): Promise<{ rows: unknown[] }>\n}\n\n/**\n * Result of loading a single extension\n */\nexport interface ExtensionLoadResult {\n  /** Extension name */\n  name: ExtensionName\n  /** Whether the extension was loaded successfully */\n  success: boolean\n  /** Whether the extension was already loaded (cache hit) */\n  wasAlreadyLoaded: boolean\n  /** Time taken to load in milliseconds (0 if already loaded) */\n  loadTimeMs: number\n  /** Error message if loading failed */\n  error?: string\n}\n\n/**\n * Result of executing a query with auto-loading\n */\nexport interface ExecuteWithAutoLoadResult {\n  /** Extensions that were loaded for this query */\n  extensionsLoaded: ExtensionName[]\n  /** Query result */\n  result: { rows: unknown[] }\n  /** Total time spent loading extensions */\n  extensionLoadTimeMs: number\n}\n\n/**\n * Statistics about extension loading\n */\nexport interface ExtensionLoaderStats {\n  /** Number of extensions currently loaded */\n  totalLoaded: number\n  /** Names of loaded extensions */\n  loadedExtensions: ExtensionName[]\n  /** Number of cache hits (requests for already-loaded extensions) */\n  cacheHits: number\n  /** Load times for each extension in milliseconds */\n  loadTimes: Record<string, number>\n  /** Number of times auto-detection was run */\n  autoDetectionCount: number\n}\n\n/**\n * Options for the LazyExtensionLoader\n */\nexport interface LazyExtensionLoaderOptions {\n  /** Whether to log debug information */\n  debug?: boolean\n  /** Whether to disable automatic extension detection */\n  disableAutoDetection?: boolean\n  /** Timeout for loading each extension in milliseconds */\n  loadTimeoutMs?: number\n}\n\n// ============================================================================\n// Extension Registry\n// ============================================================================\n\n/**\n * Registry of supported PostgreSQL extensions with their metadata\n */\nexport const EXTENSION_REGISTRY: Record<ExtensionName, ExtensionMetadata> = {\n  vector: {\n    name: 'vector',\n    displayName: 'pgvector',\n    extensionName: 'vector',\n    description: 'Vector similarity search for PostgreSQL',\n    available: true,\n    detectionPatterns: [\n      /::vector\\b/i,\n      /\\bvector\\s*\\(/i,\n      /<->/,\n      /<=>/,\n      /<#>/,\n      /\\bl2_distance\\s*\\(/i,\n      /\\bcosine_distance\\s*\\(/i,\n      /\\binner_product\\s*\\(/i,\n      /\\bivfflat\\b/i,\n      /\\bhnsw\\b/i,\n    ],\n    functions: ['l2_distance', 'cosine_distance', 'inner_product', 'vector'],\n    types: ['vector'],\n    operators: ['<->', '<=>', '<#>'],\n  },\n\n  pg_trgm: {\n    name: 'pg_trgm',\n    displayName: 'pg_trgm',\n    extensionName: 'pg_trgm',\n    description: 'Trigram matching for text similarity',\n    available: true,\n    detectionPatterns: [\n      /\\bsimilarity\\s*\\(/i,\n      /\\bshow_trgm\\s*\\(/i,\n      /\\bword_similarity\\s*\\(/i,\n      /\\bstrict_word_similarity\\s*\\(/i,\n      /\\bgin_trgm_ops\\b/i,\n      /\\bgist_trgm_ops\\b/i,\n      /%>/,\n      /<%/,\n      /<<%/,\n      /%>>/,\n    ],\n    functions: ['similarity', 'show_trgm', 'word_similarity', 'strict_word_similarity'],\n    operators: ['%', '%>', '<%', '<<%', '%>>'],\n  },\n\n  pgcrypto: {\n    name: 'pgcrypto',\n    displayName: 'pgcrypto',\n    extensionName: 'pgcrypto',\n    description: 'Cryptographic functions',\n    available: true,\n    detectionPatterns: [\n      /\\bcrypt\\s*\\(/i,\n      /\\bgen_salt\\s*\\(/i,\n      /\\bgen_random_uuid\\s*\\(/i,\n      /\\bgen_random_bytes\\s*\\(/i,\n      /\\bdigest\\s*\\(/i,\n      /\\bhmac\\s*\\(/i,\n      /\\bencrypt\\s*\\(/i,\n      /\\bdecrypt\\s*\\(/i,\n      /\\bpgp_sym_encrypt\\s*\\(/i,\n      /\\bpgp_sym_decrypt\\s*\\(/i,\n      /\\bpgp_pub_encrypt\\s*\\(/i,\n      /\\bpgp_pub_decrypt\\s*\\(/i,\n      /\\barmor\\s*\\(/i,\n      /\\bdearmor\\s*\\(/i,\n    ],\n    functions: [\n      'crypt',\n      'gen_salt',\n      'gen_random_uuid',\n      'gen_random_bytes',\n      'digest',\n      'hmac',\n      'encrypt',\n      'decrypt',\n      'pgp_sym_encrypt',\n      'pgp_sym_decrypt',\n    ],\n  },\n\n  hstore: {\n    name: 'hstore',\n    displayName: 'hstore',\n    extensionName: 'hstore',\n    description: 'Key-value store data type',\n    available: true,\n    detectionPatterns: [\n      /::hstore\\b/i,\n      /\\bhstore\\s*\\(/i,\n      /\\bhstore_to_json\\s*\\(/i,\n      /\\bhstore_to_jsonb\\s*\\(/i,\n      /\\beach\\s*\\(/i,\n      /\\bexist\\s*\\(/i,\n      /\\bdefined\\s*\\(/i,\n      /\\bdelete\\s*\\(/i,\n      /\\bpopulate_record\\s*\\(/i,\n      /->\\s*'[^']+'/,\n      /=>/,\n    ],\n    functions: ['hstore', 'hstore_to_json', 'hstore_to_jsonb', 'each', 'exist', 'defined'],\n    types: ['hstore'],\n    operators: ['->', '=>', '?', '?&', '?|', '@>', '<@'],\n  },\n\n  citext: {\n    name: 'citext',\n    displayName: 'citext',\n    extensionName: 'citext',\n    description: 'Case-insensitive text data type',\n    available: true,\n    detectionPatterns: [/::citext\\b/i, /\\bcitext\\b/i],\n    types: ['citext'],\n  },\n\n  'uuid-ossp': {\n    name: 'uuid-ossp',\n    displayName: 'uuid-ossp',\n    extensionName: 'uuid-ossp',\n    description: 'UUID generation functions',\n    available: true,\n    detectionPatterns: [\n      /\\buuid_generate_v1\\s*\\(/i,\n      /\\buuid_generate_v1mc\\s*\\(/i,\n      /\\buuid_generate_v3\\s*\\(/i,\n      /\\buuid_generate_v4\\s*\\(/i,\n      /\\buuid_generate_v5\\s*\\(/i,\n      /\\buuid_nil\\s*\\(/i,\n      /\\buuid_ns_dns\\s*\\(/i,\n      /\\buuid_ns_url\\s*\\(/i,\n      /\\buuid_ns_oid\\s*\\(/i,\n      /\\buuid_ns_x500\\s*\\(/i,\n    ],\n    functions: [\n      'uuid_generate_v1',\n      'uuid_generate_v1mc',\n      'uuid_generate_v3',\n      'uuid_generate_v4',\n      'uuid_generate_v5',\n      'uuid_nil',\n    ],\n  },\n\n  cube: {\n    name: 'cube',\n    displayName: 'cube',\n    extensionName: 'cube',\n    description: 'Multi-dimensional cube data type',\n    available: true,\n    detectionPatterns: [/::cube\\b/i, /\\bcube\\s*\\(/i, /\\bcube_distance\\s*\\(/i, /\\bcube_dim\\s*\\(/i],\n    functions: ['cube', 'cube_distance', 'cube_dim', 'cube_ll_coord', 'cube_ur_coord'],\n    types: ['cube'],\n  },\n\n  earthdistance: {\n    name: 'earthdistance',\n    displayName: 'earthdistance',\n    extensionName: 'earthdistance',\n    description: 'Earth distance calculations using cube',\n    available: true,\n    dependencies: ['cube'],\n    detectionPatterns: [\n      /\\bearth\\s*\\(/i,\n      /\\bearth_distance\\s*\\(/i,\n      /\\bearth_box\\s*\\(/i,\n      /\\bll_to_earth\\s*\\(/i,\n      /\\blatitude\\s*\\(/i,\n      /\\blongitude\\s*\\(/i,\n      /\\bgc_to_sec\\s*\\(/i,\n      /\\bsec_to_gc\\s*\\(/i,\n    ],\n    functions: [\n      'earth',\n      'earth_distance',\n      'earth_box',\n      'll_to_earth',\n      'latitude',\n      'longitude',\n      'gc_to_sec',\n      'sec_to_gc',\n    ],\n  },\n\n  fuzzystrmatch: {\n    name: 'fuzzystrmatch',\n    displayName: 'fuzzystrmatch',\n    extensionName: 'fuzzystrmatch',\n    description: 'Fuzzy string matching functions',\n    available: true,\n    detectionPatterns: [\n      /\\bsoundex\\s*\\(/i,\n      /\\bdifference\\s*\\(/i,\n      /\\blevenshtein\\s*\\(/i,\n      /\\blevenshtein_less_equal\\s*\\(/i,\n      /\\bmetaphone\\s*\\(/i,\n      /\\bdmetaphone\\s*\\(/i,\n    ],\n    functions: ['soundex', 'difference', 'levenshtein', 'levenshtein_less_equal', 'metaphone', 'dmetaphone'],\n  },\n\n  intarray: {\n    name: 'intarray',\n    displayName: 'intarray',\n    extensionName: 'intarray',\n    description: 'Integer array functions and operators',\n    available: true,\n    detectionPatterns: [\n      /\\bicount\\s*\\(/i,\n      /\\bsort\\s*\\(/i,\n      /\\bsort_asc\\s*\\(/i,\n      /\\bsort_desc\\s*\\(/i,\n      /\\buniq\\s*\\(/i,\n      /\\bidx\\s*\\(/i,\n      /\\bsubarray\\s*\\(/i,\n      /\\bintset\\s*\\(/i,\n    ],\n    functions: ['icount', 'sort', 'sort_asc', 'sort_desc', 'uniq', 'idx', 'subarray', 'intset'],\n  },\n\n  ltree: {\n    name: 'ltree',\n    displayName: 'ltree',\n    extensionName: 'ltree',\n    description: 'Hierarchical tree-like data',\n    available: true,\n    detectionPatterns: [\n      /::ltree\\b/i,\n      /\\bltree\\s*\\(/i,\n      /\\blquery\\b/i,\n      /\\bltxtquery\\b/i,\n      /\\bsubltree\\s*\\(/i,\n      /\\bsubpath\\s*\\(/i,\n      /\\bnlevel\\s*\\(/i,\n      /\\bindex\\s*\\(/i,\n      /\\blca\\s*\\(/i,\n      /@>/,\n      /<@/,\n      /~/,\n      /\\?/,\n    ],\n    functions: ['subltree', 'subpath', 'nlevel', 'index', 'lca'],\n    types: ['ltree', 'lquery', 'ltxtquery'],\n  },\n\n  tablefunc: {\n    name: 'tablefunc',\n    displayName: 'tablefunc',\n    extensionName: 'tablefunc',\n    description: 'Table-returning functions including crosstab',\n    available: true,\n    detectionPatterns: [\n      /\\bcrosstab\\s*\\(/i,\n      /\\bcrosstab2\\s*\\(/i,\n      /\\bcrosstab3\\s*\\(/i,\n      /\\bcrosstab4\\s*\\(/i,\n      /\\bconnectby\\s*\\(/i,\n      /\\bnormal_rand\\s*\\(/i,\n    ],\n    functions: ['crosstab', 'crosstab2', 'crosstab3', 'crosstab4', 'connectby', 'normal_rand'],\n  },\n\n  unaccent: {\n    name: 'unaccent',\n    displayName: 'unaccent',\n    extensionName: 'unaccent',\n    description: 'Remove accents from text',\n    available: true,\n    detectionPatterns: [/\\bunaccent\\s*\\(/i],\n    functions: ['unaccent'],\n  },\n\n  btree_gin: {\n    name: 'btree_gin',\n    displayName: 'btree_gin',\n    extensionName: 'btree_gin',\n    description: 'GIN operator classes for btree-indexable data types',\n    available: true,\n    detectionPatterns: [/\\bUSING\\s+gin\\s*\\(/i, /\\bgin_btree_ops\\b/i],\n  },\n\n  btree_gist: {\n    name: 'btree_gist',\n    displayName: 'btree_gist',\n    extensionName: 'btree_gist',\n    description: 'GiST operator classes for btree-indexable data types',\n    available: true,\n    detectionPatterns: [/\\bUSING\\s+gist\\s*\\(/i, /\\bgist_btree_ops\\b/i],\n  },\n\n  bloom: {\n    name: 'bloom',\n    displayName: 'bloom',\n    extensionName: 'bloom',\n    description: 'Bloom filter index access method',\n    available: true,\n    detectionPatterns: [/\\bUSING\\s+bloom\\s*\\(/i, /\\bbloom_ops\\b/i],\n  },\n}\n\n// ============================================================================\n// Extension Detection\n// ============================================================================\n\n/**\n * Detect which extensions are needed for a SQL query\n *\n * Analyzes the SQL string and returns a list of extensions that should be\n * loaded before executing the query.\n *\n * @param sql - The SQL query to analyze\n * @returns Array of extension names that were detected\n *\n * @example\n * ```typescript\n * const extensions = detectExtensions(\"SELECT embedding <-> '[1,2,3]' FROM items\")\n * // Returns: ['vector']\n *\n * const extensions = detectExtensions(\"SELECT similarity(name, 'test') FROM users\")\n * // Returns: ['pg_trgm']\n * ```\n */\nexport function detectExtensions(sql: string): ExtensionName[] {\n  const detected = new Set<ExtensionName>()\n\n  for (const [name, metadata] of Object.entries(EXTENSION_REGISTRY)) {\n    for (const pattern of metadata.detectionPatterns) {\n      if (pattern.test(sql)) {\n        detected.add(name as ExtensionName)\n        break // No need to check more patterns for this extension\n      }\n    }\n  }\n\n  return Array.from(detected)\n}\n\n// ============================================================================\n// LazyExtensionLoader Class\n// ============================================================================\n\n/**\n * Lazy extension loader for PostgreSQL\n *\n * Loads extensions on-demand when they are first needed, improving cold start\n * times by avoiding loading all extensions at initialization.\n *\n * @example\n * ```typescript\n * const loader = new LazyExtensionLoader({\n *   query: async (sql) => pg.exec(sql)\n * })\n *\n * // Load a specific extension\n * await loader.ensureLoaded('vector')\n *\n * // Auto-detect and load from SQL\n * await loader.executeWithAutoLoad(\"SELECT embedding <-> '[1,2,3]' FROM items\")\n *\n * // Get statistics\n * console.log(loader.getStats())\n * ```\n */\nexport class LazyExtensionLoader {\n  private executor: QueryExecutor\n  private options: Required<LazyExtensionLoaderOptions>\n  private loadedExtensions: Set<ExtensionName> = new Set()\n  private loadingPromises: Map<ExtensionName, Promise<ExtensionLoadResult>> = new Map()\n  private loadTimes: Map<ExtensionName, number> = new Map()\n  private cacheHits: number = 0\n  private autoDetectionCount: number = 0\n\n  constructor(executor: QueryExecutor, options: LazyExtensionLoaderOptions = {}) {\n    this.executor = executor\n    this.options = {\n      debug: options.debug ?? false,\n      disableAutoDetection: options.disableAutoDetection ?? false,\n      loadTimeoutMs: options.loadTimeoutMs ?? 10000,\n    }\n  }\n\n  /**\n   * Ensure an extension is loaded, loading it if necessary\n   *\n   * @param name - The extension to load\n   * @returns Result of the load operation\n   */\n  async ensureLoaded(name: ExtensionName): Promise<ExtensionLoadResult> {\n    // Check if already loaded\n    if (this.loadedExtensions.has(name)) {\n      this.cacheHits++\n      return {\n        name,\n        success: true,\n        wasAlreadyLoaded: true,\n        loadTimeMs: 0,\n      }\n    }\n\n    // Check if currently loading (dedup concurrent requests)\n    const existingPromise = this.loadingPromises.get(name)\n    if (existingPromise) {\n      return existingPromise\n    }\n\n    // Start loading\n    const loadPromise = this.loadExtension(name)\n    this.loadingPromises.set(name, loadPromise)\n\n    try {\n      const result = await loadPromise\n      return result\n    } finally {\n      this.loadingPromises.delete(name)\n    }\n  }\n\n  /**\n   * Internal method to load an extension\n   */\n  private async loadExtension(name: ExtensionName): Promise<ExtensionLoadResult> {\n    const startTime = performance.now()\n\n    // Check if extension exists in registry\n    const metadata = EXTENSION_REGISTRY[name]\n    if (!metadata) {\n      return {\n        name,\n        success: false,\n        wasAlreadyLoaded: false,\n        loadTimeMs: performance.now() - startTime,\n        error: `Unknown extension: ${name}`,\n      }\n    }\n\n    // Load dependencies first\n    if (metadata.dependencies) {\n      for (const dep of metadata.dependencies) {\n        const depResult = await this.ensureLoaded(dep)\n        if (!depResult.success) {\n          return {\n            name,\n            success: false,\n            wasAlreadyLoaded: false,\n            loadTimeMs: performance.now() - startTime,\n            error: `Failed to load dependency \"${dep}\": ${depResult.error}`,\n          }\n        }\n      }\n    }\n\n    try {\n      // Create the extension\n      const sql = `CREATE EXTENSION IF NOT EXISTS \"${metadata.extensionName}\"`\n      await this.executor.query(sql)\n\n      const loadTimeMs = performance.now() - startTime\n      this.loadedExtensions.add(name)\n      this.loadTimes.set(name, loadTimeMs)\n\n      if (this.options.debug) {\n        console.log(`[LazyExtensionLoader] Loaded extension \"${name}\" in ${loadTimeMs.toFixed(2)}ms`)\n      }\n\n      return {\n        name,\n        success: true,\n        wasAlreadyLoaded: false,\n        loadTimeMs,\n      }\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error)\n\n      if (this.options.debug) {\n        console.error(`[LazyExtensionLoader] Failed to load extension \"${name}\":`, error)\n      }\n\n      return {\n        name,\n        success: false,\n        wasAlreadyLoaded: false,\n        loadTimeMs: performance.now() - startTime,\n        error: errorMessage,\n      }\n    }\n  }\n\n  /**\n   * Load multiple extensions\n   *\n   * @param names - Array of extension names to load\n   * @returns Array of load results\n   */\n  async loadExtensions(names: ExtensionName[]): Promise<ExtensionLoadResult[]> {\n    // Sort by dependencies - extensions without dependencies first\n    const sorted = this.sortByDependencies(names)\n\n    const results: ExtensionLoadResult[] = []\n    for (const name of sorted) {\n      const result = await this.ensureLoaded(name)\n      results.push(result)\n    }\n\n    return results\n  }\n\n  /**\n   * Sort extensions by dependencies (topological sort)\n   */\n  private sortByDependencies(names: ExtensionName[]): ExtensionName[] {\n    const nameSet = new Set(names)\n    const sorted: ExtensionName[] = []\n    const visited = new Set<ExtensionName>()\n\n    const visit = (name: ExtensionName) => {\n      if (visited.has(name)) return\n      visited.add(name)\n\n      const metadata = EXTENSION_REGISTRY[name]\n      if (metadata?.dependencies) {\n        for (const dep of metadata.dependencies) {\n          if (nameSet.has(dep) || !this.loadedExtensions.has(dep)) {\n            nameSet.add(dep)\n            visit(dep)\n          }\n        }\n      }\n\n      sorted.push(name)\n    }\n\n    for (const name of names) {\n      visit(name)\n    }\n\n    return sorted\n  }\n\n  /**\n   * Detect extensions needed for a SQL query\n   *\n   * @param sql - The SQL query to analyze\n   * @returns Array of extension names detected\n   */\n  detectExtensions(sql: string): ExtensionName[] {\n    this.autoDetectionCount++\n    return detectExtensions(sql)\n  }\n\n  /**\n   * Execute a query with automatic extension loading\n   *\n   * Analyzes the SQL, loads any detected extensions, then executes the query.\n   *\n   * @param sql - The SQL query to execute\n   * @param params - Optional query parameters\n   * @returns Result including loaded extensions and query result\n   */\n  async executeWithAutoLoad(sql: string, params?: unknown[]): Promise<ExecuteWithAutoLoadResult> {\n    const extensionsLoaded: ExtensionName[] = []\n    let extensionLoadTimeMs = 0\n\n    // Detect and load extensions if auto-detection is enabled\n    if (!this.options.disableAutoDetection) {\n      const detected = this.detectExtensions(sql)\n\n      for (const name of detected) {\n        if (!this.loadedExtensions.has(name)) {\n          // Note: performance timing handled by ensureLoaded\n          const result = await this.ensureLoaded(name)\n          if (result.success && !result.wasAlreadyLoaded) {\n            extensionsLoaded.push(name)\n            extensionLoadTimeMs += result.loadTimeMs\n          }\n        }\n      }\n    }\n\n    // Execute the query\n    const result = await this.executor.query(sql, params)\n\n    return {\n      extensionsLoaded,\n      result,\n      extensionLoadTimeMs,\n    }\n  }\n\n  /**\n   * Preload a set of extensions\n   *\n   * Useful for preloading extensions you know will be needed.\n   *\n   * @param names - Array of extension names to preload\n   * @returns Array of load results\n   */\n  async preload(names: ExtensionName[]): Promise<ExtensionLoadResult[]> {\n    return this.loadExtensions(names)\n  }\n\n  /**\n   * Check if an extension is loaded\n   *\n   * @param name - The extension name to check\n   * @returns True if the extension is loaded\n   */\n  isLoaded(name: ExtensionName): boolean {\n    return this.loadedExtensions.has(name)\n  }\n\n  /**\n   * Get list of loaded extensions\n   *\n   * @returns Array of loaded extension names\n   */\n  getLoadedExtensions(): ExtensionName[] {\n    return Array.from(this.loadedExtensions)\n  }\n\n  /**\n   * Get loading statistics\n   *\n   * @returns Statistics about extension loading\n   */\n  getStats(): ExtensionLoaderStats {\n    return {\n      totalLoaded: this.loadedExtensions.size,\n      loadedExtensions: Array.from(this.loadedExtensions),\n      cacheHits: this.cacheHits,\n      loadTimes: Object.fromEntries(this.loadTimes),\n      autoDetectionCount: this.autoDetectionCount,\n    }\n  }\n\n  /**\n   * Reset the loader state\n   *\n   * Clears loaded extensions and statistics. Useful for testing or\n   * when you need to reload extensions (e.g., after a database reset).\n   */\n  reset(): void {\n    this.loadedExtensions.clear()\n    this.loadingPromises.clear()\n    this.loadTimes.clear()\n    this.cacheHits = 0\n    this.autoDetectionCount = 0\n  }\n\n  // ============================================================================\n  // Static Methods\n  // ============================================================================\n\n  /**\n   * Get metadata for an extension\n   *\n   * @param name - The extension name\n   * @returns Extension metadata or undefined if not found\n   */\n  static getMetadata(name: ExtensionName): ExtensionMetadata | undefined {\n    return EXTENSION_REGISTRY[name]\n  }\n\n  /**\n   * Get all available extensions\n   *\n   * @returns Array of extension metadata for available extensions\n   */\n  static getAvailableExtensions(): ExtensionMetadata[] {\n    return Object.values(EXTENSION_REGISTRY).filter((m) => m.available)\n  }\n\n  /**\n   * Check if a SQL query would trigger detection of a specific extension\n   *\n   * @param sql - The SQL query to check\n   * @param extensionName - The extension to check for\n   * @returns True if the extension would be detected\n   */\n  static wouldDetect(sql: string, extensionName: ExtensionName): boolean {\n    const detected = detectExtensions(sql)\n    return detected.includes(extensionName)\n  }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a LazyExtensionLoader instance\n *\n * @param executor - Query executor for running SQL\n * @param options - Loader options\n * @returns New LazyExtensionLoader instance\n *\n * @example\n * ```typescript\n * const loader = createLazyExtensionLoader({\n *   query: async (sql) => pg.exec(sql)\n * })\n *\n * await loader.ensureLoaded('vector')\n * ```\n */\nexport function createLazyExtensionLoader(\n  executor: QueryExecutor,\n  options?: LazyExtensionLoaderOptions\n): LazyExtensionLoader {\n  return new LazyExtensionLoader(executor, options)\n}\n","/**\n * PGLite Connection Pool\n *\n * A connection pool implementation for PGLite that efficiently manages\n * database connections, particularly optimized for Cloudflare Workers\n * where memory is constrained and each Durable Object is the sole client.\n *\n * ## Design Philosophy\n *\n * Unlike traditional connection pools that manage multiple physical database\n * connections, this pool manages \"virtual\" clients over a single PGLite instance.\n * Since PGLite runs PostgreSQL in-process (WASM), there's no network latency,\n * making client acquisition essentially free. The pool's value comes from:\n *\n * 1. **Controlled concurrency** - Prevents overwhelming the single-threaded WASM\n *    instance with parallel operations that could cause memory pressure\n * 2. **Familiar API** - Provides the standard pool.query/transaction interface\n *    that developers expect from postgres.js, pg-pool, etc.\n * 3. **Queue management** - FIFO request queuing with configurable timeouts\n *\n * ## Key Features\n *\n * - **Configurable pool size** - Defaults to 1 (optimal for Workers with max_connections=1)\n * - **FIFO queue** - Requests are processed in order with timeout support\n * - **Automatic cleanup** - Clients released after query/transaction completion\n * - **Transaction support** - Full isolation level and read-only transaction support\n * - **Statistics tracking** - Real-time pool metrics for monitoring\n * - **Idempotent operations** - Safe to call release() multiple times\n *\n * ## Memory Optimization\n *\n * For Cloudflare Workers (128MB limit), use maxSize=1 to serialize operations.\n * This prevents memory spikes from concurrent queries and aligns with PGLite's\n * max_connections=1 optimization in WASM builds.\n *\n * @example Basic usage\n * ```typescript\n * import { PGlitePool } from './pool'\n *\n * const pool = new PGlitePool({\n *   pglite: myPGLiteInstance,\n *   maxSize: 1,  // Optimal for Workers (max_connections=1)\n *   acquireTimeout: 30000,\n * })\n *\n * // Simple query - client automatically acquired and released\n * const result = await pool.query('SELECT * FROM users WHERE id = $1', [1])\n * ```\n *\n * @example Transactions\n * ```typescript\n * // Transaction with automatic commit/rollback\n * const user = await pool.transaction(async (client) => {\n *   await client.query('INSERT INTO users (name) VALUES ($1)', ['Alice'])\n *   return await client.query('SELECT * FROM users WHERE name = $1', ['Alice'])\n * })\n * ```\n *\n * @example Manual client management\n * ```typescript\n * // Manual acquire/release when you need more control\n * const client = await pool.acquire()\n * try {\n *   await client.query('SELECT 1')\n *   await client.query('SELECT 2')\n * } finally {\n *   pool.release(client)\n * }\n *\n * await pool.end()\n * ```\n *\n * @example Statistics monitoring\n * ```typescript\n * const stats = pool.getStats()\n * console.log(`Active: ${stats.activeCount}/${stats.maxSize}`)\n * console.log(`Waiting: ${stats.waitingCount}`)\n * ```\n *\n * @module\n */\n\nimport { PoolError } from '@dotdo/postgres-shared'\n\n// Re-export PoolError for backwards compatibility\nexport { PoolError }\n\n// =============================================================================\n// Type Definitions\n// =============================================================================\n\n/**\n * PGLite-like interface that the pool works with.\n *\n * This interface defines the minimal contract required from a PGLite instance.\n * It allows the pool to work with different PGLite variants (full, tiny) and\n * enables easy mocking in tests.\n *\n * @remarks\n * The pool does not own the PGLite instance lifecycle - call {@link PGlitePool.destroy}\n * if you want the pool to also close the underlying connection.\n */\nexport interface PGLiteLike {\n  /**\n   * Promise that resolves when PGLite is ready to accept queries.\n   * The pool awaits this before creating clients.\n   */\n  waitReady: Promise<void>\n\n  /**\n   * Synchronous ready check. True after waitReady resolves.\n   */\n  ready: boolean\n\n  /**\n   * Execute a SQL query with optional parameters.\n   *\n   * @typeParam T - The row type for the query result\n   * @param sql - SQL query string with $1, $2, etc. placeholders\n   * @param params - Parameter values to bind to placeholders\n   * @returns Query result with rows, field metadata, and affected row count\n   */\n  query<T = unknown>(sql: string, params?: unknown[]): Promise<{\n    rows: T[]\n    fields: Array<{ name: string; dataTypeID: number }>\n    affectedRows?: number\n  }>\n\n  /**\n   * Close the PGLite connection and release resources.\n   */\n  close(): Promise<void>\n}\n\n/**\n * Query result from a pool client operation.\n *\n * @typeParam T - The row type for typed queries\n */\nexport interface PoolQueryResult<T = unknown> {\n  /** Array of result rows, typed as T */\n  rows: T[]\n  /** Field metadata including column names and PostgreSQL type OIDs */\n  fields: Array<{ name: string; dataTypeID: number }>\n  /** Number of rows affected (for INSERT/UPDATE/DELETE) */\n  affectedRows?: number\n}\n\n/**\n * Pool client that wraps access to the underlying PGLite connection.\n *\n * Clients are acquired from the pool, used for queries, and then released back.\n * The pool tracks client state to prevent use-after-release bugs.\n *\n * @example\n * ```typescript\n * const client = await pool.acquire()\n * try {\n *   const result = await client.query<User>('SELECT * FROM users WHERE id = $1', [1])\n *   console.log(result.rows[0])\n * } finally {\n *   pool.release(client)\n * }\n * ```\n */\nexport interface PoolClient {\n  /** Unique client ID within the pool (monotonically increasing) */\n  readonly id: number\n\n  /** Whether this client is currently in use (acquired but not released) */\n  inUse: boolean\n\n  /** Reference to the underlying PGLite instance */\n  readonly pglite: PGLiteLike\n\n  /** Timestamp when the client was acquired, undefined when idle */\n  acquiredAt?: Date | undefined\n\n  /**\n   * Execute a query using this client.\n   *\n   * @typeParam T - The expected row type for typed results\n   * @param sql - SQL query string with $1, $2, etc. placeholders\n   * @param params - Parameter values to bind to placeholders\n   * @returns Query result with typed rows\n   * @throws {PoolError} If the client has been released (use-after-release)\n   *\n   * @example\n   * ```typescript\n   * const result = await client.query<User>(\n   *   'SELECT * FROM users WHERE id = $1',\n   *   [userId]\n   * )\n   * ```\n   */\n  query<T = unknown>(sql: string, params?: unknown[]): Promise<PoolQueryResult<T>>\n}\n\n/**\n * PostgreSQL transaction isolation levels.\n *\n * @see {@link https://www.postgresql.org/docs/current/transaction-iso.html PostgreSQL Isolation Levels}\n *\n * - `'read uncommitted'` - Allows dirty reads (PostgreSQL treats as read committed)\n * - `'read committed'` - Default level, prevents dirty reads\n * - `'repeatable read'` - Snapshot isolation, prevents non-repeatable reads\n * - `'serializable'` - Strictest level, prevents phantom reads\n */\nexport type PoolIsolationLevel =\n  | 'read uncommitted'\n  | 'read committed'\n  | 'repeatable read'\n  | 'serializable'\n\n/**\n * Options for transaction execution.\n */\nexport interface PoolTransactionOptions {\n  /**\n   * Transaction isolation level.\n   * Higher isolation levels provide stronger consistency guarantees\n   * but may reduce concurrency.\n   *\n   * @default 'read committed' (PostgreSQL default)\n   */\n  isolationLevel?: PoolIsolationLevel\n\n  /**\n   * Whether the transaction is read-only.\n   * Read-only transactions can be optimized by the database engine\n   * and will error if write operations are attempted.\n   *\n   * @default false\n   */\n  readOnly?: boolean\n}\n\n/**\n * Configuration for creating a PGLite pool.\n */\nexport interface PGlitePoolConfig {\n  /**\n   * The PGLite instance to pool.\n   * The pool does not own this instance - it will not be closed\n   * when {@link PGlitePool.end} is called. Use {@link PGlitePool.destroy}\n   * to close both the pool and the underlying PGLite instance.\n   */\n  pglite: PGLiteLike\n\n  /**\n   * Maximum number of virtual clients in the pool.\n   *\n   * Since PGLite runs in-process (no network), this effectively controls\n   * how many concurrent operations can execute before new requests queue.\n   *\n   * **Cloudflare Workers recommendation:** Use `maxSize: 1` to serialize\n   * operations and prevent memory spikes from concurrent WASM execution.\n   * This aligns with PGLite's `max_connections=1` optimization.\n   *\n   * @default 1\n   */\n  maxSize?: number\n\n  /**\n   * Timeout in milliseconds for acquiring a client from the pool.\n   *\n   * When the pool is at capacity, new acquire requests wait in a queue.\n   * If a client cannot be acquired within this timeout, the request fails\n   * with a {@link PoolError}.\n   *\n   * Set to `0` for no timeout (wait indefinitely - not recommended for production).\n   *\n   * @default 30000 (30 seconds)\n   */\n  acquireTimeout?: number\n}\n\n/**\n * Real-time pool statistics for monitoring and debugging.\n *\n * Use {@link PGlitePool.getStats} to retrieve current statistics.\n *\n * @example\n * ```typescript\n * const stats = pool.getStats()\n *\n * // Check pool utilization\n * const utilization = stats.activeCount / stats.maxSize\n *\n * // Alert if requests are queuing\n * if (stats.waitingCount > 10) {\n *   console.warn('High queue depth:', stats.waitingCount)\n * }\n * ```\n */\nexport interface PoolStats {\n  /** Total number of clients created (active + idle) */\n  totalCount: number\n  /** Number of idle clients ready to be acquired */\n  idleCount: number\n  /** Number of clients currently in use */\n  activeCount: number\n  /** Number of requests waiting in queue for a client */\n  waitingCount: number\n  /** Maximum pool size from configuration */\n  maxSize: number\n}\n\n// =============================================================================\n// Internal Types and Implementation\n// =============================================================================\n\n/**\n * Queued request waiting for a client.\n * @internal\n */\ninterface QueuedRequest {\n  resolve: (client: PoolClient) => void\n  reject: (error: Error) => void\n  timeoutId: ReturnType<typeof setTimeout>\n}\n\n/**\n * Internal pool client implementation.\n *\n * This class tracks the client lifecycle (acquired/released) and prevents\n * use-after-release bugs by checking state before every query.\n *\n * @internal\n */\nclass PoolClientImpl implements PoolClient {\n  readonly id: number\n  inUse: boolean = false\n  readonly pglite: PGLiteLike\n  acquiredAt?: Date | undefined\n\n  /** True after release, prevents use-after-release */\n  private released: boolean = false\n\n  constructor(id: number, pglite: PGLiteLike) {\n    this.id = id\n    this.pglite = pglite\n  }\n\n  async query<T = unknown>(sql: string, params?: unknown[]): Promise<PoolQueryResult<T>> {\n    if (!this.inUse || this.released) {\n      throw new PoolError('Cannot use a released client', {\n        context: { clientId: this.id },\n      })\n    }\n    return this.pglite.query<T>(sql, params)\n  }\n\n  /**\n   * Mark this client as released.\n   * Called by the pool when releasing - resets state for reuse.\n   * @internal\n   */\n  _markReleased(): void {\n    this.released = true\n    this.inUse = false\n    this.acquiredAt = undefined\n  }\n\n  /**\n   * Mark this client as acquired.\n   * Called by the pool when acquiring - prepares for use.\n   * @internal\n   */\n  _markAcquired(): void {\n    this.released = false\n    this.inUse = true\n    this.acquiredAt = new Date()\n  }\n}\n\n// =============================================================================\n// PGlitePool Class\n// =============================================================================\n\n/**\n * PGLite Connection Pool.\n *\n * Manages virtual connections to a PGLite instance, providing connection\n * pooling semantics even though PGLite is a single-connection in-process\n * database.\n *\n * @see {@link PGlitePoolConfig} for configuration options\n * @see {@link PoolStats} for available statistics\n */\nexport class PGlitePool {\n  // ---------------------------------------------------------------------------\n  // Configuration (immutable after construction)\n  // ---------------------------------------------------------------------------\n  private readonly pglite: PGLiteLike\n  private readonly maxSize: number\n  private readonly acquireTimeout: number\n\n  // ---------------------------------------------------------------------------\n  // Client tracking\n  // ---------------------------------------------------------------------------\n  /** All clients in the pool (by ID) */\n  private readonly clients: Map<number, PoolClientImpl> = new Map()\n  /** Stack of idle clients available for acquisition (LIFO for cache locality) */\n  private readonly idleClients: PoolClientImpl[] = []\n  /** Queue of requests waiting for a client (FIFO for fairness) */\n  private readonly waitingRequests: QueuedRequest[] = []\n\n  // ---------------------------------------------------------------------------\n  // Pool state\n  // ---------------------------------------------------------------------------\n  /** Auto-incrementing client ID counter */\n  private nextClientId: number = 0\n  /** Whether the pool has been closed via end() or destroy() */\n  private closed: boolean = false\n  /** Cached ready promise to avoid re-awaiting */\n  private readyPromise: Promise<void> | null = null\n\n  /**\n   * Create a new PGLite connection pool.\n   *\n   * @param config - Pool configuration options\n   *\n   * @example\n   * ```typescript\n   * const pool = new PGlitePool({\n   *   pglite: myPGLiteInstance,\n   *   maxSize: 1,\n   *   acquireTimeout: 30000,\n   * })\n   * ```\n   */\n  constructor(config: PGlitePoolConfig) {\n    this.pglite = config.pglite\n    this.maxSize = config.maxSize ?? 1\n    this.acquireTimeout = config.acquireTimeout ?? 30000\n  }\n\n  // ---------------------------------------------------------------------------\n  // Statistics Getters\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Total number of clients created in the pool.\n   * Clients are created lazily as needed, up to maxSize.\n   */\n  get totalCount(): number {\n    return this.clients.size\n  }\n\n  /**\n   * Number of idle clients available for immediate acquisition.\n   */\n  get idleCount(): number {\n    return this.idleClients.length\n  }\n\n  /**\n   * Number of clients currently in use (acquired but not released).\n   */\n  get activeCount(): number {\n    let count = 0\n    for (const client of this.clients.values()) {\n      if (client.inUse) {\n        count++\n      }\n    }\n    return count\n  }\n\n  /**\n   * Number of requests waiting in queue for a client.\n   * Non-zero indicates pool is at capacity.\n   */\n  get waitingCount(): number {\n    return this.waitingRequests.length\n  }\n\n  /**\n   * Whether the pool has been closed via {@link end} or {@link destroy}.\n   * Closed pools reject all new acquire requests.\n   */\n  get isClosed(): boolean {\n    return this.closed\n  }\n\n  /**\n   * Get a snapshot of current pool statistics.\n   *\n   * @returns Current pool statistics for monitoring\n   *\n   * @example\n   * ```typescript\n   * const stats = pool.getStats()\n   * console.log(`Pool: ${stats.activeCount}/${stats.maxSize} active, ${stats.waitingCount} waiting`)\n   * ```\n   */\n  getStats(): PoolStats {\n    return {\n      totalCount: this.totalCount,\n      idleCount: this.idleCount,\n      activeCount: this.activeCount,\n      waitingCount: this.waitingCount,\n      maxSize: this.maxSize,\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Private Helper Methods\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Check if PGLite is ready (synchronous check).\n   * Used to determine if we can skip the async ready wait.\n   */\n  private isReady(): boolean {\n    return this.readyPromise !== null || this.pglite.ready\n  }\n\n  /**\n   * Ensure PGLite is ready before operations.\n   * Caches the ready promise to avoid re-awaiting.\n   */\n  private async ensureReady(): Promise<void> {\n    if (!this.readyPromise) {\n      this.readyPromise = this.pglite.waitReady\n    }\n    await this.readyPromise\n  }\n\n  /**\n   * Create a new pool client.\n   * Called when pool capacity allows expansion.\n   */\n  private createClient(): PoolClientImpl {\n    const id = ++this.nextClientId\n    const client = new PoolClientImpl(id, this.pglite)\n    this.clients.set(id, client)\n    return client\n  }\n\n  /**\n   * Create a queued request that waits for a client with timeout.\n   * This encapsulates the common pattern of timeout-bounded waiting.\n   *\n   * @returns Promise that resolves with a client or rejects on timeout\n   */\n  private createQueuedRequest(): Promise<PoolClient> {\n    return new Promise<PoolClient>((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        // Remove from waiting queue on timeout\n        const index = this.waitingRequests.findIndex(\n          (r) => r.resolve === resolve\n        )\n        if (index !== -1) {\n          this.waitingRequests.splice(index, 1)\n        }\n        reject(new PoolError('Timeout waiting for available client', {\n          context: {\n            timeoutMs: this.acquireTimeout,\n            waitingCount: this.waitingRequests.length,\n            activeCount: this.activeCount,\n          },\n        }))\n      }, this.acquireTimeout)\n\n      this.waitingRequests.push({ resolve, reject, timeoutId })\n    })\n  }\n\n  // ---------------------------------------------------------------------------\n  // Client Acquisition and Release\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Acquire a client from the pool.\n   *\n   * If a client is immediately available (idle client exists or pool can grow),\n   * the acquisition is nearly instantaneous. Otherwise, the request is queued\n   * and waits until a client becomes available or the timeout is reached.\n   *\n   * **Important:** Always release the client when done, preferably using\n   * try/finally to ensure release even on errors.\n   *\n   * @returns A pool client that must be released after use\n   * @throws {PoolError} If the pool is closed\n   * @throws {PoolError} If timeout is reached while waiting for a client\n   *\n   * @example\n   * ```typescript\n   * const client = await pool.acquire()\n   * try {\n   *   await client.query('SELECT * FROM users')\n   * } finally {\n   *   pool.release(client)\n   * }\n   * ```\n   */\n  acquire(): Promise<PoolClient> {\n    if (this.closed) {\n      return Promise.reject(new PoolError('Pool has been closed'))\n    }\n\n    // Fast path: If PGLite is ready and pool is at capacity with no idle clients,\n    // queue immediately. This makes queuing synchronous which is important for\n    // correct waitingCount tracking in tests and monitoring.\n    if (this.isReady() && this.clients.size >= this.maxSize && this.idleClients.length === 0) {\n      return this.createQueuedRequest()\n    }\n\n    // Otherwise, do the full async flow\n    return this.acquireAsync()\n  }\n\n  /**\n   * Internal async acquisition logic.\n   * Handles the full flow: wait for ready, check idle, create new, or queue.\n   */\n  private async acquireAsync(): Promise<PoolClient> {\n    // Ensure PGLite is ready before proceeding\n    await this.ensureReady()\n\n    // Check if closed after awaiting (pool may have closed while waiting)\n    if (this.closed) {\n      throw new PoolError('Pool has been closed')\n    }\n\n    // Try to reuse an idle client (LIFO for better cache locality)\n    const idleClient = this.idleClients.pop()\n    if (idleClient) {\n      idleClient._markAcquired()\n      return idleClient\n    }\n\n    // If we can create more clients, expand the pool\n    if (this.clients.size < this.maxSize) {\n      const client = this.createClient()\n      client._markAcquired()\n      return client\n    }\n\n    // Pool at capacity - queue and wait for a client to be released\n    return this.createQueuedRequest()\n  }\n\n  /**\n   * Release a client back to the pool.\n   *\n   * This operation is idempotent - calling release() multiple times on the\n   * same client is safe and will only have effect the first time.\n   *\n   * When released, if there are queued requests waiting for a client,\n   * the first waiting request receives this client immediately (FIFO).\n   * Otherwise, the client is added to the idle pool for reuse.\n   *\n   * @param client - The client to release (must have been acquired from this pool)\n   * @throws {PoolError} If the client is not from this pool (wrong pool or invalid)\n   *\n   * @example\n   * ```typescript\n   * const client = await pool.acquire()\n   * try {\n   *   await client.query('SELECT 1')\n   * } finally {\n   *   pool.release(client) // Always release, even on error\n   * }\n   * ```\n   */\n  release(client: PoolClient): void {\n    const poolClient = this.clients.get(client.id)\n    if (!poolClient) {\n      throw new PoolError('Invalid client', {\n        context: { clientId: client.id },\n      })\n    }\n\n    // Idempotent: already released, no-op\n    if (!poolClient.inUse) {\n      return\n    }\n\n    // Mark as released\n    poolClient._markReleased()\n\n    // If there are waiting requests and pool isn't closed, fulfill the first one\n    if (this.waitingRequests.length > 0 && !this.closed) {\n      const request = this.waitingRequests.shift()!\n      clearTimeout(request.timeoutId)\n      poolClient._markAcquired()\n      request.resolve(poolClient)\n      return\n    }\n\n    // Otherwise, add to idle pool for reuse\n    this.idleClients.push(poolClient)\n  }\n\n  // ---------------------------------------------------------------------------\n  // Query Execution\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Execute a query using a pooled client.\n   *\n   * This is the simplest way to execute queries - the client is automatically\n   * acquired before the query and released after, even if the query fails.\n   *\n   * For multiple queries in sequence, consider using {@link acquire} manually\n   * or {@link transaction} to avoid acquire/release overhead per query.\n   *\n   * @typeParam T - The expected row type for typed results\n   * @param sql - SQL query string with $1, $2, etc. placeholders\n   * @param params - Parameter values to bind to placeholders\n   * @returns Query result with typed rows\n   * @throws {PoolError} If client acquisition fails\n   * @throws {Error} If the query execution fails\n   *\n   * @example\n   * ```typescript\n   * // Simple query\n   * const result = await pool.query('SELECT * FROM users WHERE id = $1', [userId])\n   *\n   * // Typed query\n   * interface User { id: number; name: string }\n   * const { rows } = await pool.query<User>('SELECT * FROM users')\n   * const user = rows[0] // Type: User\n   * ```\n   */\n  async query<T = unknown>(\n    sql: string,\n    params?: unknown[]\n  ): Promise<PoolQueryResult<T>> {\n    const client = await this.acquire()\n    try {\n      return await client.query<T>(sql, params)\n    } finally {\n      this.release(client)\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Transaction Support\n  // ---------------------------------------------------------------------------\n\n  /** Valid PostgreSQL isolation levels (lowercase for comparison) */\n  private static readonly VALID_ISOLATION_LEVELS = [\n    'read uncommitted',\n    'read committed',\n    'repeatable read',\n    'serializable',\n  ] as const\n\n  /**\n   * Build the BEGIN statement for a transaction with options.\n   *\n   * @param options - Transaction options\n   * @returns SQL string for BEGIN with isolation level and access mode\n   * @throws {Error} If isolation level is invalid\n   */\n  private buildBeginStatement(options?: PoolTransactionOptions): string {\n    let beginSql = 'BEGIN'\n\n    if (options?.isolationLevel) {\n      const normalized = options.isolationLevel.toLowerCase()\n      if (!PGlitePool.VALID_ISOLATION_LEVELS.includes(normalized as PoolIsolationLevel)) {\n        throw new Error(`Invalid isolation level: \"${options.isolationLevel}\"`)\n      }\n      beginSql += ` ISOLATION LEVEL ${normalized.toUpperCase()}`\n    }\n\n    if (options?.readOnly) {\n      beginSql += ' READ ONLY'\n    }\n\n    return beginSql\n  }\n\n  /**\n   * Execute a transaction using a pooled client.\n   *\n   * The client is held for the duration of the transaction and automatically\n   * released when complete. The transaction is committed on success or rolled\n   * back if the callback throws an error.\n   *\n   * @typeParam T - The return type of the transaction callback\n   * @param fn - Transaction callback function that receives the client\n   * @param options - Transaction options (isolation level, read-only)\n   * @returns Result of the transaction callback\n   * @throws {PoolError} If client acquisition fails\n   * @throws {Error} If isolation level validation fails\n   * @throws {Error} Any error thrown by the callback (transaction is rolled back)\n   *\n   * @example\n   * ```typescript\n   * // Basic transaction\n   * const result = await pool.transaction(async (client) => {\n   *   await client.query('INSERT INTO users (name) VALUES ($1)', ['Alice'])\n   *   const { rows } = await client.query('SELECT * FROM users WHERE name = $1', ['Alice'])\n   *   return rows[0]\n   * })\n   *\n   * // Transaction with options\n   * await pool.transaction(async (client) => {\n   *   const { rows } = await client.query('SELECT * FROM accounts')\n   *   return rows\n   * }, { isolationLevel: 'serializable', readOnly: true })\n   * ```\n   */\n  async transaction<T>(\n    fn: (client: PoolClient) => Promise<T>,\n    options?: PoolTransactionOptions\n  ): Promise<T> {\n    const client = await this.acquire()\n    try {\n      const beginSql = this.buildBeginStatement(options)\n      await client.query(beginSql)\n\n      try {\n        const result = await fn(client)\n        await client.query('COMMIT')\n        return result\n      } catch (error) {\n        // Always attempt rollback on error\n        try {\n          await client.query('ROLLBACK')\n        } catch {\n          // Ignore rollback errors - original error is more important\n        }\n        throw error\n      }\n    } finally {\n      this.release(client)\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Pool Lifecycle\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Close the pool and release all clients.\n   *\n   * This operation:\n   * 1. Marks the pool as closed (rejects new acquire requests)\n   * 2. Rejects all pending queued requests with PoolError\n   * 3. Clears all client references\n   *\n   * The underlying PGLite instance is NOT closed - use {@link destroy}\n   * if you want to close both the pool and the PGLite connection.\n   *\n   * This operation is idempotent - calling end() multiple times is safe.\n   *\n   * @example\n   * ```typescript\n   * // Clean shutdown\n   * await pool.end()\n   * // Pool is now closed, but PGLite can still be used directly\n   * ```\n   */\n  async end(): Promise<void> {\n    if (this.closed) {\n      return\n    }\n\n    this.closed = true\n\n    // Reject all waiting requests with clear error message\n    for (const request of this.waitingRequests) {\n      clearTimeout(request.timeoutId)\n      request.reject(new PoolError('Pool is closing'))\n    }\n    this.waitingRequests.length = 0\n\n    // Clear idle clients\n    this.idleClients.length = 0\n\n    // Clear all clients\n    this.clients.clear()\n  }\n\n  /**\n   * Destroy the pool and close the underlying PGLite instance.\n   *\n   * This is the \"full shutdown\" method that:\n   * 1. Calls {@link end} to close the pool\n   * 2. Calls close() on the PGLite instance\n   *\n   * After destroy(), neither the pool nor the PGLite instance can be used.\n   *\n   * @example\n   * ```typescript\n   * // Full cleanup when completely done with the database\n   * await pool.destroy()\n   * ```\n   */\n  async destroy(): Promise<void> {\n    await this.end()\n    await this.pglite.close()\n  }\n}\n"],"mappings":"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","names":["parseConnectionUrl","SharedPostgresError","SharedConnectionError","SharedConnectionTimeoutError","result","mapped","DEFAULTS","DEFAULTS","DEFAULTS","DEFAULTS","buildParameterizedSql","parseRows","transport","sharedValidateToken","parseConnectionUrl","result","import_postgres_shared"]}