@t1mmen/srtd
Version:
Supabase Repeatable Template Definitions (srtd): 🪄 Live-reloading SQL templates for Supabase DX. Make your database changes reviewable and migrations maintainable! 🚀
106 lines (105 loc) • 3.13 kB
TypeScript
/**
* DatabaseService - Centralized database connection and SQL execution service
* Handles connection pooling, retry logic, and SQL execution with transaction management
*/
import { EventEmitter } from 'node:events';
import pg from 'pg';
import type { CLIConfig, MigrationError } from '../types.js';
export interface DatabaseServiceConfig {
connectionString: string;
connectionTimeoutMillis?: number;
maxConnections?: number;
idleTimeoutMillis?: number;
maxUses?: number;
maxRetries?: number;
retryDelayMs?: number;
wrapInTransaction?: boolean;
}
export interface ConnectionStats {
total: number;
idle: number;
active: number;
}
export declare enum DatabaseErrorType {
CONNECTION_ERROR = "CONNECTION_ERROR",
SYNTAX_ERROR = "SYNTAX_ERROR",
CONSTRAINT_VIOLATION = "CONSTRAINT_VIOLATION",
TIMEOUT_ERROR = "TIMEOUT_ERROR",
TRANSACTION_ERROR = "TRANSACTION_ERROR",
POOL_EXHAUSTED = "POOL_EXHAUSTED",
UNKNOWN_ERROR = "UNKNOWN_ERROR"
}
export interface DatabaseError {
type: DatabaseErrorType;
message: string;
originalError?: Error;
code?: string;
detail?: string;
hint?: string;
}
export interface SqlExecutionResult {
success: boolean;
error?: string;
databaseError?: DatabaseError;
rows?: unknown[];
rowCount?: number;
data?: unknown;
}
export interface ExecutionConfig {
templateName?: string;
useTransaction?: boolean;
silent?: boolean;
parameters?: unknown[];
isolationLevel?: 'READ UNCOMMITTED' | 'READ COMMITTED' | 'REPEATABLE READ' | 'SERIALIZABLE';
}
export declare class DatabaseService extends EventEmitter {
private config;
private pool;
private connectionAttempts;
private disposed;
constructor(config: DatabaseServiceConfig);
/**
* Categorize database errors for better error handling
*/
private categorizeError;
/**
* Create and configure database connection pool
*/
private createPool;
/**
* Establish database connection with retry logic
*/
private retryConnection;
/**
* Get a database connection with retry logic
*/
connect(params?: {
silent?: boolean;
}): Promise<pg.PoolClient>;
/**
* Test database connectivity
*/
testConnection(): Promise<boolean>;
/**
* Execute SQL with optional transaction wrapping and parameterized queries
* Core method for running template content or any SQL
*/
executeSQL(sql: string, config?: ExecutionConfig): Promise<SqlExecutionResult>;
/**
* Execute SQL and return migration-compatible result
* Used by migration/template application logic
*/
executeMigration(content: string, templateName: string, silent?: boolean): Promise<true | MigrationError>;
/**
* Get connection pool statistics
*/
getConnectionStats(): ConnectionStats | null;
/**
* Gracefully close all database connections
*/
dispose(): Promise<void>;
/**
* Create DatabaseService from CLI config
*/
static fromConfig(config: CLIConfig): DatabaseService;
}