drizzle-multitenant 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config.ts","../src/types.ts","../src/debug.ts","../src/pool/cache/pool-cache.ts","../src/pool/retry/retry-handler.ts","../src/pool/health/health-checker.ts","../src/pool.ts","../src/manager.ts","../src/context.ts","../src/migrator/table-format.ts","../src/migrator/schema-manager.ts","../src/migrator/drift/column-analyzer.ts","../src/migrator/drift/index-analyzer.ts","../src/migrator/drift/constraint-analyzer.ts","../src/migrator/drift/drift-detector.ts","../src/migrator/seed/seeder.ts","../src/migrator/sync/sync-manager.ts","../src/migrator/executor/migration-executor.ts","../src/migrator/executor/batch-executor.ts","../src/migrator/clone/ddl-generator.ts","../src/migrator/clone/data-copier.ts","../src/migrator/clone/cloner.ts","../src/migrator/migrator.ts","../src/cross-schema/cross-schema.ts","../src/cross-schema/with-shared.ts","../src/retry.ts"],"names":["Pool","DEFAULT_MIGRATIONS_TABLE","drizzle","join","sql","getTableName","isRetryableError","sleep"],"mappings":"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","file":"index.js","sourcesContent":["import type { Config } from './types.js';\n\n/**\n * Define configuration for drizzle-multitenant\n *\n * @example\n * ```typescript\n * import { defineConfig } from 'drizzle-multitenant';\n * import * as tenantSchema from './schemas/tenant';\n * import * as sharedSchema from './schemas/shared';\n *\n * export default defineConfig({\n * connection: {\n * url: process.env.DATABASE_URL!,\n * poolConfig: {\n * max: 10,\n * idleTimeoutMillis: 30000,\n * },\n * },\n * isolation: {\n * strategy: 'schema',\n * schemaNameTemplate: (tenantId) => `tenant_${tenantId.replace(/-/g, '_')}`,\n * maxPools: 50,\n * poolTtlMs: 60 * 60 * 1000,\n * },\n * schemas: {\n * tenant: tenantSchema,\n * shared: sharedSchema,\n * },\n * });\n * ```\n */\nexport function defineConfig<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): Config<TTenantSchema, TSharedSchema> {\n validateConfig(config);\n return config;\n}\n\n/**\n * Validate configuration at runtime\n */\nfunction validateConfig<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): void {\n // Connection validation\n if (!config.connection.url) {\n throw new Error('[drizzle-multitenant] connection.url is required');\n }\n\n // Isolation validation\n if (!config.isolation.strategy) {\n throw new Error('[drizzle-multitenant] isolation.strategy is required');\n }\n\n if (config.isolation.strategy !== 'schema') {\n throw new Error(\n `[drizzle-multitenant] isolation.strategy \"${config.isolation.strategy}\" is not yet supported. Only \"schema\" is currently available.`\n );\n }\n\n if (!config.isolation.schemaNameTemplate) {\n throw new Error('[drizzle-multitenant] isolation.schemaNameTemplate is required');\n }\n\n if (typeof config.isolation.schemaNameTemplate !== 'function') {\n throw new Error('[drizzle-multitenant] isolation.schemaNameTemplate must be a function');\n }\n\n // Schema validation\n if (!config.schemas.tenant) {\n throw new Error('[drizzle-multitenant] schemas.tenant is required');\n }\n\n // Pool limits validation\n if (config.isolation.maxPools !== undefined && config.isolation.maxPools < 1) {\n throw new Error('[drizzle-multitenant] isolation.maxPools must be at least 1');\n }\n\n if (config.isolation.poolTtlMs !== undefined && config.isolation.poolTtlMs < 0) {\n throw new Error('[drizzle-multitenant] isolation.poolTtlMs must be non-negative');\n }\n\n // Retry config validation\n if (config.connection.retry) {\n const retry = config.connection.retry;\n\n if (retry.maxAttempts !== undefined && retry.maxAttempts < 1) {\n throw new Error('[drizzle-multitenant] connection.retry.maxAttempts must be at least 1');\n }\n\n if (retry.initialDelayMs !== undefined && retry.initialDelayMs < 0) {\n throw new Error('[drizzle-multitenant] connection.retry.initialDelayMs must be non-negative');\n }\n\n if (retry.maxDelayMs !== undefined && retry.maxDelayMs < 0) {\n throw new Error('[drizzle-multitenant] connection.retry.maxDelayMs must be non-negative');\n }\n\n if (retry.backoffMultiplier !== undefined && retry.backoffMultiplier < 1) {\n throw new Error('[drizzle-multitenant] connection.retry.backoffMultiplier must be at least 1');\n }\n\n if (\n retry.initialDelayMs !== undefined &&\n retry.maxDelayMs !== undefined &&\n retry.initialDelayMs > retry.maxDelayMs\n ) {\n throw new Error(\n '[drizzle-multitenant] connection.retry.initialDelayMs cannot be greater than maxDelayMs'\n );\n }\n }\n}\n","import type { Pool, PoolConfig } from 'pg';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\n\n/**\n * Isolation strategy for multi-tenancy\n */\nexport type IsolationStrategy = 'schema' | 'database' | 'row';\n\n/**\n * Retry configuration for connection attempts\n */\nexport interface RetryConfig {\n /** Maximum number of retry attempts (default: 3) */\n maxAttempts?: number;\n /** Initial delay in milliseconds before first retry (default: 100) */\n initialDelayMs?: number;\n /** Maximum delay in milliseconds between retries (default: 5000) */\n maxDelayMs?: number;\n /** Multiplier for exponential backoff (default: 2) */\n backoffMultiplier?: number;\n /** Whether to add jitter to delays to avoid thundering herd (default: true) */\n jitter?: boolean;\n /** Custom function to determine if an error is retryable */\n isRetryable?: (error: Error) => boolean;\n /** Called on each retry attempt */\n onRetry?: (attempt: number, error: Error, delayMs: number) => void;\n}\n\n/**\n * Connection configuration\n */\nexport interface ConnectionConfig {\n /** PostgreSQL connection URL */\n url: string;\n /** Pool configuration options */\n poolConfig?: Omit<PoolConfig, 'connectionString'>;\n /** Retry configuration for connection failures */\n retry?: RetryConfig;\n}\n\n/**\n * Isolation configuration\n */\nexport interface IsolationConfig {\n /** Isolation strategy (currently only 'schema' is supported) */\n strategy: IsolationStrategy;\n /** Function to generate schema name from tenant ID */\n schemaNameTemplate: (tenantId: string) => string;\n /** Maximum number of simultaneous pools (LRU eviction) */\n maxPools?: number;\n /** TTL in milliseconds before pool cleanup */\n poolTtlMs?: number;\n}\n\n/**\n * Schema definitions\n */\nexport interface SchemasConfig<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Schema applied per tenant */\n tenant: TTenantSchema;\n /** Shared schema (public) */\n shared?: TSharedSchema;\n}\n\n/**\n * Lifecycle hooks\n */\nexport interface Hooks {\n /** Called when a new pool is created */\n onPoolCreated?: (tenantId: string) => void | Promise<void>;\n /** Called when a pool is evicted */\n onPoolEvicted?: (tenantId: string) => void | Promise<void>;\n /** Called on pool error */\n onError?: (tenantId: string, error: Error) => void | Promise<void>;\n}\n\n/**\n * Metrics configuration\n */\nexport interface MetricsConfig {\n /** Enable metrics collection */\n enabled: boolean;\n /** Prefix for metric names */\n prefix?: string;\n}\n\n/**\n * Debug configuration for development and troubleshooting\n */\nexport interface DebugConfig {\n /** Enable debug mode */\n enabled: boolean;\n /** Log SQL queries with tenant context */\n logQueries?: boolean;\n /** Log pool lifecycle events (created, evicted) */\n logPoolEvents?: boolean;\n /** Threshold in ms to log slow queries (default: 1000) */\n slowQueryThreshold?: number;\n /** Custom logger function (default: console.log) */\n logger?: (message: string, context?: DebugContext) => void;\n}\n\n/**\n * Context passed to debug logger\n */\nexport interface DebugContext {\n /** Event type */\n type: 'query' | 'slow_query' | 'pool_created' | 'pool_evicted' | 'pool_error' | 'warmup' | 'connection_retry';\n /** Tenant ID */\n tenantId?: string;\n /** Schema name */\n schemaName?: string;\n /** SQL query (for query events) */\n query?: string;\n /** Query duration in ms */\n durationMs?: number;\n /** Error message */\n error?: string;\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Main configuration interface\n */\nexport interface Config<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Database connection settings */\n connection: ConnectionConfig;\n /** Tenant isolation settings */\n isolation: IsolationConfig;\n /** Drizzle schemas */\n schemas: SchemasConfig<TTenantSchema, TSharedSchema>;\n /** Lifecycle hooks */\n hooks?: Hooks;\n /** Metrics configuration */\n metrics?: MetricsConfig;\n /** Debug configuration */\n debug?: DebugConfig;\n}\n\n/**\n * Internal pool entry for LRU cache\n */\nexport interface PoolEntry<TSchema extends Record<string, unknown> = Record<string, unknown>> {\n /** Drizzle database instance */\n db: NodePgDatabase<TSchema>;\n /** PostgreSQL pool */\n pool: Pool;\n /** Last access timestamp */\n lastAccess: number;\n /** Schema name */\n schemaName: string;\n}\n\n/**\n * Type for tenant database instance\n */\nexport type TenantDb<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n NodePgDatabase<TSchema>;\n\n/**\n * Type for shared database instance\n */\nexport type SharedDb<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n NodePgDatabase<TSchema>;\n\n/**\n * Options for pool warmup\n */\nexport interface WarmupOptions {\n /** Number of concurrent warmup operations */\n concurrency?: number;\n /** Execute a ping query to verify connection */\n ping?: boolean;\n /** Callback for progress updates */\n onProgress?: (tenantId: string, status: 'starting' | 'completed' | 'failed') => void;\n}\n\n/**\n * Result for a single tenant warmup\n */\nexport interface TenantWarmupResult {\n tenantId: string;\n success: boolean;\n /** Whether the pool was already warm */\n alreadyWarm: boolean;\n durationMs: number;\n error?: string;\n}\n\n/**\n * Aggregate warmup results\n */\nexport interface WarmupResult {\n total: number;\n succeeded: number;\n failed: number;\n alreadyWarm: number;\n durationMs: number;\n details: TenantWarmupResult[];\n}\n\n/**\n * Health status for a pool\n */\nexport type PoolHealthStatus = 'ok' | 'degraded' | 'unhealthy';\n\n/**\n * Health information for a single pool\n */\nexport interface PoolHealth {\n /** Tenant ID */\n tenantId: string;\n /** Schema name */\n schemaName: string;\n /** Health status */\n status: PoolHealthStatus;\n /** Total connections in pool */\n totalConnections: number;\n /** Idle connections available */\n idleConnections: number;\n /** Waiting requests in queue */\n waitingRequests: number;\n /** Response time of health ping in ms */\n responseTimeMs?: number;\n /** Error message if unhealthy */\n error?: string;\n}\n\n/**\n * Options for health check\n */\nexport interface HealthCheckOptions {\n /** Execute ping query to verify connection (default: true) */\n ping?: boolean;\n /** Timeout for ping query in ms (default: 5000) */\n pingTimeoutMs?: number;\n /** Include shared database in check (default: true) */\n includeShared?: boolean;\n /** Check specific tenant IDs only */\n tenantIds?: string[];\n}\n\n/**\n * Connection metrics for a pool\n */\nexport interface ConnectionMetrics {\n /** Total connections in pool */\n total: number;\n /** Idle connections available */\n idle: number;\n /** Waiting requests in queue */\n waiting: number;\n}\n\n/**\n * Metrics for a single tenant pool\n */\nexport interface TenantPoolMetrics {\n /** Tenant ID */\n tenantId: string;\n /** Schema name */\n schemaName: string;\n /** Connection metrics */\n connections: ConnectionMetrics;\n /** Last access timestamp */\n lastAccessedAt: string;\n}\n\n/**\n * Aggregate metrics result\n */\nexport interface MetricsResult {\n /** Pool metrics */\n pools: {\n /** Total active pools */\n total: number;\n /** Maximum pools allowed */\n maxPools: number;\n /** Individual tenant pool metrics */\n tenants: TenantPoolMetrics[];\n };\n /** Shared database metrics (if initialized) */\n shared: {\n /** Whether shared pool is initialized */\n initialized: boolean;\n /** Connection metrics */\n connections: ConnectionMetrics | null;\n };\n /** Timestamp of metrics collection */\n timestamp: string;\n}\n\n/**\n * Health check result\n */\nexport interface HealthCheckResult {\n /** Overall health status */\n healthy: boolean;\n /** Health of tenant pools */\n pools: PoolHealth[];\n /** Health status of shared database */\n sharedDb: PoolHealthStatus;\n /** Response time of shared db ping in ms */\n sharedDbResponseTimeMs?: number;\n /** Error on shared db if any */\n sharedDbError?: string;\n /** Total active pools */\n totalPools: number;\n /** Pools with degraded status */\n degradedPools: number;\n /** Pools with unhealthy status */\n unhealthyPools: number;\n /** Timestamp of health check */\n timestamp: string;\n /** Total duration of health check in ms */\n durationMs: number;\n}\n\n/**\n * Tenant manager interface\n */\nexport interface TenantManager<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Get database instance for a specific tenant (sync, no validation) */\n getDb(tenantId: string): TenantDb<TTenantSchema>;\n /** Get database instance for a specific tenant with retry and validation */\n getDbAsync(tenantId: string): Promise<TenantDb<TTenantSchema>>;\n /** Get shared database instance (sync, no validation) */\n getSharedDb(): SharedDb<TSharedSchema>;\n /** Get shared database instance with retry and validation */\n getSharedDbAsync(): Promise<SharedDb<TSharedSchema>>;\n /** Get the schema name for a tenant */\n getSchemaName(tenantId: string): string;\n /** Check if a tenant pool exists */\n hasPool(tenantId: string): boolean;\n /** Get active pool count */\n getPoolCount(): number;\n /** Get all active tenant IDs */\n getActiveTenantIds(): string[];\n /** Get the retry configuration */\n getRetryConfig(): Required<RetryConfig>;\n /** Manually evict a tenant pool */\n evictPool(tenantId: string): Promise<void>;\n /** Pre-warm pools for specified tenants to reduce cold start latency */\n warmup(tenantIds: string[], options?: WarmupOptions): Promise<WarmupResult>;\n /** Check health of all pools and connections */\n healthCheck(options?: HealthCheckOptions): Promise<HealthCheckResult>;\n /** Get current metrics for all pools (zero overhead, collected on demand) */\n getMetrics(): MetricsResult;\n /** Dispose all pools and cleanup */\n dispose(): Promise<void>;\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG = {\n maxPools: 50,\n poolTtlMs: 60 * 60 * 1000, // 1 hour\n cleanupIntervalMs: 60_000, // 1 minute\n poolConfig: {\n max: 10,\n idleTimeoutMillis: 30_000,\n connectionTimeoutMillis: 5_000,\n },\n retry: {\n maxAttempts: 3,\n initialDelayMs: 100,\n maxDelayMs: 5_000,\n backoffMultiplier: 2,\n jitter: true,\n },\n} as const;\n","import type { DebugConfig, DebugContext } from './types.js';\n\nconst PREFIX = '[drizzle-multitenant]';\nconst DEFAULT_SLOW_QUERY_THRESHOLD = 1000;\n\n/**\n * Debug logger for drizzle-multitenant\n * Provides structured logging for queries, pool events, and performance monitoring\n */\nexport class DebugLogger {\n private readonly enabled: boolean;\n private readonly logQueries: boolean;\n private readonly logPoolEvents: boolean;\n private readonly slowQueryThreshold: number;\n private readonly logger: (message: string, context?: DebugContext) => void;\n\n constructor(config?: DebugConfig) {\n this.enabled = config?.enabled ?? false;\n this.logQueries = config?.logQueries ?? true;\n this.logPoolEvents = config?.logPoolEvents ?? true;\n this.slowQueryThreshold = config?.slowQueryThreshold ?? DEFAULT_SLOW_QUERY_THRESHOLD;\n this.logger = config?.logger ?? this.defaultLogger;\n }\n\n /**\n * Check if debug mode is enabled\n */\n isEnabled(): boolean {\n return this.enabled;\n }\n\n /**\n * Log a query execution\n */\n logQuery(tenantId: string, query: string, durationMs: number): void {\n if (!this.enabled || !this.logQueries) return;\n\n const isSlowQuery = durationMs >= this.slowQueryThreshold;\n const type = isSlowQuery ? 'slow_query' : 'query';\n\n const context: DebugContext = {\n type,\n tenantId,\n query: this.truncateQuery(query),\n durationMs,\n };\n\n if (isSlowQuery) {\n this.logger(\n `${PREFIX} tenant=${tenantId} SLOW_QUERY duration=${durationMs}ms query=\"${this.truncateQuery(query)}\"`,\n context\n );\n } else {\n this.logger(\n `${PREFIX} tenant=${tenantId} query=\"${this.truncateQuery(query)}\" duration=${durationMs}ms`,\n context\n );\n }\n }\n\n /**\n * Log pool creation\n */\n logPoolCreated(tenantId: string, schemaName: string): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'pool_created',\n tenantId,\n schemaName,\n };\n\n this.logger(\n `${PREFIX} tenant=${tenantId} POOL_CREATED schema=${schemaName}`,\n context\n );\n }\n\n /**\n * Log pool eviction\n */\n logPoolEvicted(tenantId: string, schemaName: string, reason?: string): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'pool_evicted',\n tenantId,\n schemaName,\n metadata: reason ? { reason } : undefined,\n };\n\n const reasonStr = reason ? ` reason=${reason}` : '';\n this.logger(\n `${PREFIX} tenant=${tenantId} POOL_EVICTED schema=${schemaName}${reasonStr}`,\n context\n );\n }\n\n /**\n * Log pool error\n */\n logPoolError(tenantId: string, error: Error): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'pool_error',\n tenantId,\n error: error.message,\n };\n\n this.logger(\n `${PREFIX} tenant=${tenantId} POOL_ERROR error=\"${error.message}\"`,\n context\n );\n }\n\n /**\n * Log warmup event\n */\n logWarmup(tenantId: string, success: boolean, durationMs: number, alreadyWarm: boolean): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'warmup',\n tenantId,\n durationMs,\n metadata: { success, alreadyWarm },\n };\n\n const status = alreadyWarm ? 'already_warm' : (success ? 'success' : 'failed');\n this.logger(\n `${PREFIX} tenant=${tenantId} WARMUP status=${status} duration=${durationMs}ms`,\n context\n );\n }\n\n /**\n * Log connection retry event\n */\n logConnectionRetry(\n identifier: string,\n attempt: number,\n maxAttempts: number,\n error: Error,\n delayMs: number\n ): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'connection_retry',\n tenantId: identifier,\n error: error.message,\n metadata: { attempt, maxAttempts, delayMs },\n };\n\n this.logger(\n `${PREFIX} tenant=${identifier} CONNECTION_RETRY attempt=${attempt}/${maxAttempts} delay=${delayMs}ms error=\"${error.message}\"`,\n context\n );\n }\n\n /**\n * Log connection success after retries\n */\n logConnectionSuccess(identifier: string, attempts: number, totalTimeMs: number): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'pool_created',\n tenantId: identifier,\n durationMs: totalTimeMs,\n metadata: { attempts },\n };\n\n if (attempts > 1) {\n this.logger(\n `${PREFIX} tenant=${identifier} CONNECTION_SUCCESS attempts=${attempts} totalTime=${totalTimeMs}ms`,\n context\n );\n }\n }\n\n /**\n * Log a custom debug message\n */\n log(message: string, context?: Partial<DebugContext>): void {\n if (!this.enabled) return;\n\n this.logger(`${PREFIX} ${message}`, context as DebugContext);\n }\n\n /**\n * Default logger implementation using console\n */\n private defaultLogger(message: string, _context?: DebugContext): void {\n console.log(message);\n }\n\n /**\n * Truncate long queries for readability\n */\n private truncateQuery(query: string, maxLength = 100): string {\n const normalized = query.replace(/\\s+/g, ' ').trim();\n if (normalized.length <= maxLength) {\n return normalized;\n }\n return normalized.substring(0, maxLength - 3) + '...';\n }\n}\n\n/**\n * Create a debug logger instance\n */\nexport function createDebugLogger(config?: DebugConfig): DebugLogger {\n return new DebugLogger(config);\n}\n","/**\n * PoolCache - LRU cache for tenant database pools\n *\n * Extracted from PoolManager as part of the god component refactoring.\n * Handles all cache-related operations with LRU eviction.\n *\n * @see REFACTOR_PROPOSAL.md\n */\n\nimport { LRUCache } from 'lru-cache';\nimport type { PoolEntry } from '../../types.js';\nimport type { IPoolCache, PoolCacheOptions } from '../interfaces.js';\n\n/**\n * LRU cache for tenant database pools\n *\n * Provides efficient pool management with automatic LRU eviction\n * when the maximum pool count is reached.\n *\n * @example\n * ```typescript\n * const cache = new PoolCache<MySchema>({\n * maxPools: 50,\n * poolTtlMs: 3600000, // 1 hour\n * onDispose: async (schemaName, entry) => {\n * await entry.pool.end();\n * },\n * });\n *\n * cache.set('tenant_abc', poolEntry);\n * const entry = cache.get('tenant_abc');\n * ```\n */\nexport class PoolCache<TSchema extends Record<string, unknown> = Record<string, unknown>>\n implements IPoolCache<TSchema>\n{\n private readonly cache: LRUCache<string, PoolEntry<TSchema>>;\n private readonly poolTtlMs?: number;\n private readonly onDispose?: (\n schemaName: string,\n entry: PoolEntry<TSchema>\n ) => void | Promise<void>;\n\n constructor(options: PoolCacheOptions) {\n this.poolTtlMs = options.poolTtlMs;\n this.onDispose = options.onDispose as typeof this.onDispose;\n\n this.cache = new LRUCache<string, PoolEntry<TSchema>>({\n max: options.maxPools,\n dispose: (entry, key) => {\n void this.handleDispose(key, entry);\n },\n noDisposeOnSet: true,\n });\n }\n\n /**\n * Get a pool entry from cache\n *\n * This does NOT update the last access time automatically.\n * Use `touch()` to update access time when needed.\n */\n get(schemaName: string): PoolEntry<TSchema> | undefined {\n return this.cache.get(schemaName);\n }\n\n /**\n * Set a pool entry in cache\n *\n * If the cache is full, the least recently used entry will be evicted.\n */\n set(schemaName: string, entry: PoolEntry<TSchema>): void {\n this.cache.set(schemaName, entry);\n }\n\n /**\n * Check if a pool exists in cache\n */\n has(schemaName: string): boolean {\n return this.cache.has(schemaName);\n }\n\n /**\n * Delete a pool from cache\n *\n * Note: This triggers the dispose callback if configured.\n */\n delete(schemaName: string): boolean {\n return this.cache.delete(schemaName);\n }\n\n /**\n * Get the number of pools in cache\n */\n size(): number {\n return this.cache.size;\n }\n\n /**\n * Get all schema names in cache\n */\n keys(): string[] {\n return Array.from(this.cache.keys());\n }\n\n /**\n * Iterate over all entries in cache\n *\n * @yields [schemaName, entry] pairs\n */\n *entries(): IterableIterator<[string, PoolEntry<TSchema>]> {\n for (const [key, value] of this.cache.entries()) {\n yield [key, value];\n }\n }\n\n /**\n * Clear all pools from cache\n *\n * Each pool's dispose callback will be triggered by the LRU cache.\n */\n async clear(): Promise<void> {\n // Clear the cache (triggers dispose for each via LRU callback)\n this.cache.clear();\n\n // Small delay to allow dispose callbacks to complete\n await Promise.resolve();\n }\n\n /**\n * Evict the least recently used pool\n *\n * @returns The schema name of the evicted pool, or undefined if cache is empty\n */\n evictLRU(): string | undefined {\n // Get keys in LRU order (least recently used first)\n const keys = Array.from(this.cache.keys());\n if (keys.length === 0) {\n return undefined;\n }\n\n // The last key in iteration is the least recently used\n // because LRUCache iterates from newest to oldest\n const lruKey = keys[keys.length - 1];\n this.cache.delete(lruKey);\n return lruKey;\n }\n\n /**\n * Evict pools that have exceeded TTL\n *\n * @returns Array of schema names that were evicted\n */\n async evictExpired(): Promise<string[]> {\n if (!this.poolTtlMs) {\n return [];\n }\n\n const now = Date.now();\n const toEvict: string[] = [];\n\n for (const [schemaName, entry] of this.cache.entries()) {\n if (now - entry.lastAccess > this.poolTtlMs) {\n toEvict.push(schemaName);\n }\n }\n\n // Evict expired pools\n for (const schemaName of toEvict) {\n this.cache.delete(schemaName);\n }\n\n return toEvict;\n }\n\n /**\n * Update last access time for a pool\n *\n * This moves the pool to the front of the LRU list.\n */\n touch(schemaName: string): void {\n const entry = this.cache.get(schemaName);\n if (entry) {\n entry.lastAccess = Date.now();\n }\n }\n\n /**\n * Get the maximum number of pools allowed in cache\n */\n getMaxPools(): number {\n return this.cache.max;\n }\n\n /**\n * Get the configured TTL in milliseconds\n */\n getTtlMs(): number | undefined {\n return this.poolTtlMs;\n }\n\n /**\n * Check if an entry has expired based on TTL\n */\n isExpired(entry: PoolEntry<TSchema>): boolean {\n if (!this.poolTtlMs) {\n return false;\n }\n return Date.now() - entry.lastAccess > this.poolTtlMs;\n }\n\n /**\n * Handle disposal of a cache entry\n */\n private async handleDispose(schemaName: string, entry: PoolEntry<TSchema>): Promise<void> {\n if (this.onDispose) {\n await this.onDispose(schemaName, entry);\n }\n }\n}\n","/**\n * RetryHandler - Retry logic with exponential backoff\n *\n * Extracted from PoolManager as part of the god component refactoring.\n * Provides configurable retry logic for connection operations.\n *\n * @see REFACTOR_PROPOSAL.md\n */\n\nimport type { RetryConfig } from '../../types.js';\nimport { DEFAULT_CONFIG } from '../../types.js';\nimport type { IRetryHandler, RetryResult } from '../interfaces.js';\n\n/**\n * Default function to determine if an error is retryable\n * Focuses on transient connection errors\n */\nexport function isRetryableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n\n // Connection errors\n if (\n message.includes('econnrefused') ||\n message.includes('econnreset') ||\n message.includes('etimedout') ||\n message.includes('enotfound') ||\n message.includes('connection refused') ||\n message.includes('connection reset') ||\n message.includes('connection terminated') ||\n message.includes('connection timed out') ||\n message.includes('timeout expired') ||\n message.includes('socket hang up')\n ) {\n return true;\n }\n\n // PostgreSQL specific transient errors\n if (\n message.includes('too many connections') ||\n message.includes('sorry, too many clients') ||\n message.includes('the database system is starting up') ||\n message.includes('the database system is shutting down') ||\n message.includes('server closed the connection unexpectedly') ||\n message.includes('could not connect to server')\n ) {\n return true;\n }\n\n // SSL/TLS errors that might be transient\n if (message.includes('ssl connection') || message.includes('ssl handshake')) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Sleep for a given number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retry handler with exponential backoff\n *\n * Provides configurable retry logic for operations that may fail\n * with transient errors. Uses exponential backoff with optional jitter\n * to avoid thundering herd problems.\n *\n * @example\n * ```typescript\n * const handler = new RetryHandler({\n * maxAttempts: 3,\n * initialDelayMs: 100,\n * maxDelayMs: 5000,\n * backoffMultiplier: 2,\n * jitter: true,\n * });\n *\n * const result = await handler.withRetry(() => connectToDb());\n * console.log(`Succeeded after ${result.attempts} attempts`);\n * ```\n */\nexport class RetryHandler implements IRetryHandler {\n private readonly config: Required<RetryConfig>;\n\n constructor(config?: Partial<RetryConfig>) {\n this.config = {\n maxAttempts: config?.maxAttempts ?? DEFAULT_CONFIG.retry.maxAttempts,\n initialDelayMs: config?.initialDelayMs ?? DEFAULT_CONFIG.retry.initialDelayMs,\n maxDelayMs: config?.maxDelayMs ?? DEFAULT_CONFIG.retry.maxDelayMs,\n backoffMultiplier: config?.backoffMultiplier ?? DEFAULT_CONFIG.retry.backoffMultiplier,\n jitter: config?.jitter ?? DEFAULT_CONFIG.retry.jitter,\n isRetryable: config?.isRetryable ?? isRetryableError,\n onRetry: config?.onRetry,\n };\n }\n\n /**\n * Execute an operation with retry logic\n *\n * @param operation - The async operation to execute\n * @param overrideConfig - Optional config to override defaults for this call\n * @returns Result with metadata about attempts and timing\n */\n async withRetry<T>(\n operation: () => Promise<T>,\n overrideConfig?: Partial<RetryConfig>\n ): Promise<RetryResult<T>> {\n const config = overrideConfig\n ? { ...this.config, ...overrideConfig }\n : this.config;\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < config.maxAttempts; attempt++) {\n try {\n const result = await operation();\n return {\n result,\n attempts: attempt + 1,\n totalTimeMs: Date.now() - startTime,\n };\n } catch (error) {\n lastError = error as Error;\n\n // Check if this is the last attempt\n const isLastAttempt = attempt >= config.maxAttempts - 1;\n\n // Check if error is retryable\n const checkRetryable = config.isRetryable ?? this.isRetryable;\n if (isLastAttempt || !checkRetryable(lastError)) {\n throw lastError;\n }\n\n // Calculate delay for this attempt\n const delay = this.calculateDelay(attempt, config);\n\n // Call onRetry hook\n config.onRetry?.(attempt + 1, lastError, delay);\n\n // Wait before next attempt\n await sleep(delay);\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError ?? new Error('Retry failed with no error');\n }\n\n /**\n * Calculate delay with exponential backoff and optional jitter\n *\n * @param attempt - Current attempt number (0-indexed)\n * @param config - Retry configuration\n * @returns Delay in milliseconds\n */\n calculateDelay(attempt: number, config?: Partial<RetryConfig>): number {\n const cfg = config\n ? { ...this.config, ...config }\n : this.config;\n\n // Exponential backoff: initialDelay * (multiplier ^ attempt)\n const exponentialDelay = cfg.initialDelayMs * Math.pow(cfg.backoffMultiplier, attempt);\n\n // Cap at maxDelay\n const cappedDelay = Math.min(exponentialDelay, cfg.maxDelayMs);\n\n // Add jitter to avoid thundering herd\n if (cfg.jitter) {\n // Random jitter between 0% and 25% of the delay\n const jitterFactor = 1 + Math.random() * 0.25;\n return Math.floor(cappedDelay * jitterFactor);\n }\n\n return Math.floor(cappedDelay);\n }\n\n /**\n * Check if an error is retryable\n *\n * Uses the configured isRetryable function or the default implementation.\n */\n isRetryable(error: Error): boolean {\n return (this.config.isRetryable ?? isRetryableError)(error);\n }\n\n /**\n * Get the current configuration\n */\n getConfig(): Required<RetryConfig> {\n return { ...this.config };\n }\n\n /**\n * Get the maximum number of attempts\n */\n getMaxAttempts(): number {\n return this.config.maxAttempts;\n }\n}\n\n/**\n * Create a retry handler with pre-configured options\n *\n * @example\n * ```typescript\n * const handler = createRetryHandler({\n * maxAttempts: 5,\n * initialDelayMs: 200,\n * });\n *\n * const result = await handler.withRetry(() => connectToDb());\n * ```\n */\nexport function createRetryHandler(config?: Partial<RetryConfig>): RetryHandler {\n return new RetryHandler(config);\n}\n","import type { Pool } from 'pg';\nimport type {\n PoolEntry,\n HealthCheckOptions,\n HealthCheckResult,\n PoolHealth,\n PoolHealthStatus,\n} from '../../types.js';\n\n/**\n * Ping query result\n */\nexport interface PingResult {\n success: boolean;\n responseTimeMs?: number;\n error?: string;\n}\n\n/**\n * Shared database health result\n */\nexport interface SharedDbHealthResult {\n status: PoolHealthStatus;\n responseTimeMs?: number;\n error?: string;\n}\n\n/**\n * Pool info for health checking\n */\nexport interface PoolInfo<TSchema extends Record<string, unknown> = Record<string, unknown>> {\n schemaName: string;\n tenantId: string;\n entry: PoolEntry<TSchema>;\n}\n\n/**\n * Dependencies for HealthChecker\n */\nexport interface HealthCheckerDeps<TSchema extends Record<string, unknown> = Record<string, unknown>> {\n /** Function to get all pool entries */\n getPoolEntries: () => Iterable<[string, PoolEntry<TSchema>]>;\n /** Function to get tenantId from schemaName */\n getTenantIdBySchema: (schemaName: string) => string | undefined;\n /** Function to get pool entry by schemaName */\n getPoolEntry: (schemaName: string) => PoolEntry<TSchema> | undefined;\n /** Function to get schema name from tenantId */\n getSchemaName: (tenantId: string) => string;\n /** Function to get shared pool (may be null if not initialized) */\n getSharedPool: () => Pool | null;\n}\n\n/**\n * Health checker for database pools\n *\n * Responsible for checking the health of tenant pools and shared database.\n * Extracted from PoolManager as part of the refactoring effort.\n *\n * @example\n * ```typescript\n * const healthChecker = new HealthChecker({\n * getPoolEntries: () => poolCache.entries(),\n * getTenantIdBySchema: (schema) => tenantMap.get(schema),\n * getPoolEntry: (schema) => poolCache.get(schema),\n * getSchemaName: (tenantId) => `tenant_${tenantId}`,\n * getSharedPool: () => sharedPool,\n * });\n *\n * const result = await healthChecker.checkHealth({ ping: true });\n * console.log(result.healthy); // true/false\n * ```\n */\nexport class HealthChecker<TSchema extends Record<string, unknown> = Record<string, unknown>> {\n constructor(private readonly deps: HealthCheckerDeps<TSchema>) {}\n\n /**\n * Check health of all pools and connections\n *\n * Verifies the health of tenant pools and optionally the shared database.\n * Returns detailed status information for monitoring and load balancer integration.\n *\n * @example\n * ```typescript\n * // Basic health check\n * const health = await healthChecker.checkHealth();\n * console.log(health.healthy); // true/false\n *\n * // Check specific tenants only\n * const health = await healthChecker.checkHealth({\n * tenantIds: ['tenant-1', 'tenant-2'],\n * ping: true,\n * pingTimeoutMs: 3000,\n * });\n * ```\n */\n async checkHealth(options: HealthCheckOptions = {}): Promise<HealthCheckResult> {\n const startTime = Date.now();\n const {\n ping = true,\n pingTimeoutMs = 5000,\n includeShared = true,\n tenantIds,\n } = options;\n\n const poolHealthResults: PoolHealth[] = [];\n let sharedDbStatus: PoolHealthStatus = 'ok';\n let sharedDbResponseTimeMs: number | undefined;\n let sharedDbError: string | undefined;\n\n // Determine which pools to check\n const poolsToCheck = this.getPoolsToCheck(tenantIds);\n\n // Check tenant pools in parallel\n const poolChecks = poolsToCheck.map(async ({ schemaName, tenantId, entry }) => {\n return this.checkPoolHealth(tenantId, schemaName, entry, ping, pingTimeoutMs);\n });\n\n poolHealthResults.push(...(await Promise.all(poolChecks)));\n\n // Check shared database\n const sharedPool = this.deps.getSharedPool();\n if (includeShared && sharedPool) {\n const sharedResult = await this.checkSharedDbHealth(sharedPool, ping, pingTimeoutMs);\n sharedDbStatus = sharedResult.status;\n sharedDbResponseTimeMs = sharedResult.responseTimeMs;\n sharedDbError = sharedResult.error;\n }\n\n // Calculate aggregate stats\n const degradedPools = poolHealthResults.filter((p) => p.status === 'degraded').length;\n const unhealthyPools = poolHealthResults.filter((p) => p.status === 'unhealthy').length;\n\n // Overall health: healthy if no unhealthy pools and shared db is ok\n const healthy = unhealthyPools === 0 && sharedDbStatus !== 'unhealthy';\n\n const result: HealthCheckResult = {\n healthy,\n pools: poolHealthResults,\n sharedDb: sharedDbStatus,\n totalPools: poolHealthResults.length,\n degradedPools,\n unhealthyPools,\n timestamp: new Date().toISOString(),\n durationMs: Date.now() - startTime,\n };\n\n // Only add optional properties if they have values\n if (sharedDbResponseTimeMs !== undefined) {\n result.sharedDbResponseTimeMs = sharedDbResponseTimeMs;\n }\n if (sharedDbError !== undefined) {\n result.sharedDbError = sharedDbError;\n }\n\n return result;\n }\n\n /**\n * Get pools to check based on options\n */\n private getPoolsToCheck(tenantIds?: string[]): PoolInfo<TSchema>[] {\n const poolsToCheck: PoolInfo<TSchema>[] = [];\n\n if (tenantIds && tenantIds.length > 0) {\n // Check only specified tenants\n for (const tenantId of tenantIds) {\n const schemaName = this.deps.getSchemaName(tenantId);\n const entry = this.deps.getPoolEntry(schemaName);\n if (entry) {\n poolsToCheck.push({ schemaName, tenantId, entry });\n }\n }\n } else {\n // Check all active pools\n for (const [schemaName, entry] of this.deps.getPoolEntries()) {\n const tenantId = this.deps.getTenantIdBySchema(schemaName) ?? schemaName;\n poolsToCheck.push({ schemaName, tenantId, entry });\n }\n }\n\n return poolsToCheck;\n }\n\n /**\n * Check health of a single tenant pool\n */\n async checkPoolHealth(\n tenantId: string,\n schemaName: string,\n entry: PoolEntry<TSchema>,\n ping: boolean,\n pingTimeoutMs: number\n ): Promise<PoolHealth> {\n const pool = entry.pool;\n const totalConnections = pool.totalCount;\n const idleConnections = pool.idleCount;\n const waitingRequests = pool.waitingCount;\n\n let status: PoolHealthStatus = 'ok';\n let responseTimeMs: number | undefined;\n let error: string | undefined;\n\n // Determine status based on pool metrics\n if (waitingRequests > 0) {\n status = 'degraded';\n }\n\n // Execute ping query if requested\n if (ping) {\n const pingResult = await this.executePingQuery(pool, pingTimeoutMs);\n responseTimeMs = pingResult.responseTimeMs;\n\n if (!pingResult.success) {\n status = 'unhealthy';\n error = pingResult.error;\n } else if (pingResult.responseTimeMs && pingResult.responseTimeMs > pingTimeoutMs / 2) {\n // Slow response indicates degraded status\n if (status === 'ok') {\n status = 'degraded';\n }\n }\n }\n\n const result: PoolHealth = {\n tenantId,\n schemaName,\n status,\n totalConnections,\n idleConnections,\n waitingRequests,\n };\n\n // Only add optional properties if they have values\n if (responseTimeMs !== undefined) {\n result.responseTimeMs = responseTimeMs;\n }\n if (error !== undefined) {\n result.error = error;\n }\n\n return result;\n }\n\n /**\n * Check health of shared database\n */\n async checkSharedDbHealth(\n sharedPool: Pool,\n ping: boolean,\n pingTimeoutMs: number\n ): Promise<SharedDbHealthResult> {\n let status: PoolHealthStatus = 'ok';\n let responseTimeMs: number | undefined;\n let error: string | undefined;\n\n const waitingRequests = sharedPool.waitingCount;\n if (waitingRequests > 0) {\n status = 'degraded';\n }\n\n if (ping) {\n const pingResult = await this.executePingQuery(sharedPool, pingTimeoutMs);\n responseTimeMs = pingResult.responseTimeMs;\n\n if (!pingResult.success) {\n status = 'unhealthy';\n error = pingResult.error;\n } else if (pingResult.responseTimeMs && pingResult.responseTimeMs > pingTimeoutMs / 2) {\n if (status === 'ok') {\n status = 'degraded';\n }\n }\n }\n\n const result: SharedDbHealthResult = { status };\n\n // Only add optional properties if they have values\n if (responseTimeMs !== undefined) {\n result.responseTimeMs = responseTimeMs;\n }\n if (error !== undefined) {\n result.error = error;\n }\n\n return result;\n }\n\n /**\n * Execute a ping query with timeout\n */\n async executePingQuery(pool: Pool, timeoutMs: number): Promise<PingResult> {\n const startTime = Date.now();\n\n try {\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Health check ping timeout')), timeoutMs);\n });\n\n const queryPromise = pool.query('SELECT 1');\n\n await Promise.race([queryPromise, timeoutPromise]);\n\n return {\n success: true,\n responseTimeMs: Date.now() - startTime,\n };\n } catch (err) {\n return {\n success: false,\n responseTimeMs: Date.now() - startTime,\n error: (err as Error).message,\n };\n }\n }\n\n /**\n * Determine overall health status from pool health results\n */\n determineOverallHealth(pools: PoolHealth[], sharedDbStatus: PoolHealthStatus = 'ok'): boolean {\n const unhealthyPools = pools.filter((p) => p.status === 'unhealthy').length;\n return unhealthyPools === 0 && sharedDbStatus !== 'unhealthy';\n }\n}\n","import { Pool } from 'pg';\nimport { drizzle } from 'drizzle-orm/node-postgres';\nimport type {\n Config,\n PoolEntry,\n TenantDb,\n SharedDb,\n WarmupOptions,\n WarmupResult,\n TenantWarmupResult,\n RetryConfig,\n HealthCheckOptions,\n HealthCheckResult,\n MetricsResult,\n TenantPoolMetrics,\n} from './types.js';\nimport { DEFAULT_CONFIG as defaults } from './types.js';\nimport { createDebugLogger, DebugLogger } from './debug.js';\nimport { PoolCache } from './pool/cache/index.js';\nimport { RetryHandler } from './pool/retry/index.js';\nimport { HealthChecker } from './pool/health/index.js';\n\n/**\n * Pool manager that handles tenant database connections with LRU eviction\n */\nexport class PoolManager<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly poolCache: PoolCache<TTenantSchema>;\n private readonly tenantIdBySchema: Map<string, string> = new Map();\n private readonly pendingConnections: Map<string, Promise<PoolEntry<TTenantSchema>>> = new Map();\n private sharedPool: Pool | null = null;\n private sharedDb: SharedDb<TSharedSchema> | null = null;\n private sharedDbPending: Promise<SharedDb<TSharedSchema>> | null = null;\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n private disposed = false;\n private readonly debugLogger: DebugLogger;\n private readonly retryHandler: RetryHandler;\n private readonly healthChecker: HealthChecker<TTenantSchema>;\n\n constructor(private readonly config: Config<TTenantSchema, TSharedSchema>) {\n const maxPools = config.isolation.maxPools ?? defaults.maxPools;\n const poolTtlMs = config.isolation.poolTtlMs ?? defaults.poolTtlMs;\n\n this.debugLogger = createDebugLogger(config.debug);\n\n // Initialize retry handler with config\n this.retryHandler = new RetryHandler(config.connection.retry);\n\n this.poolCache = new PoolCache<TTenantSchema>({\n maxPools,\n poolTtlMs,\n onDispose: (schemaName, entry) => {\n this.disposePoolEntry(entry, schemaName);\n },\n });\n\n // Initialize health checker with dependencies\n this.healthChecker = new HealthChecker<TTenantSchema>({\n getPoolEntries: () => this.poolCache.entries(),\n getTenantIdBySchema: (schemaName) => this.tenantIdBySchema.get(schemaName),\n getPoolEntry: (schemaName) => this.poolCache.get(schemaName),\n getSchemaName: (tenantId) => this.config.isolation.schemaNameTemplate(tenantId),\n getSharedPool: () => this.sharedPool,\n });\n }\n\n /**\n * Get or create a database connection for a tenant\n */\n getDb(tenantId: string): TenantDb<TTenantSchema> {\n this.ensureNotDisposed();\n\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n let entry = this.poolCache.get(schemaName);\n\n if (!entry) {\n entry = this.createPoolEntry(tenantId, schemaName);\n this.poolCache.set(schemaName, entry);\n this.tenantIdBySchema.set(schemaName, tenantId);\n\n // Log pool creation\n this.debugLogger.logPoolCreated(tenantId, schemaName);\n\n // Fire hook asynchronously\n void this.config.hooks?.onPoolCreated?.(tenantId);\n }\n\n this.poolCache.touch(schemaName);\n return entry.db;\n }\n\n /**\n * Get or create a database connection for a tenant with retry and validation\n *\n * This async version validates the connection by executing a ping query\n * and retries on transient failures with exponential backoff.\n *\n * @example\n * ```typescript\n * // Get tenant database with automatic retry\n * const db = await manager.getDbAsync('tenant-123');\n *\n * // Queries will use the validated connection\n * const users = await db.select().from(users);\n * ```\n */\n async getDbAsync(tenantId: string): Promise<TenantDb<TTenantSchema>> {\n this.ensureNotDisposed();\n\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n let entry = this.poolCache.get(schemaName);\n\n if (entry) {\n this.poolCache.touch(schemaName);\n return entry.db;\n }\n\n // Check if there's already a pending connection for this tenant\n const pending = this.pendingConnections.get(schemaName);\n if (pending) {\n entry = await pending;\n this.poolCache.touch(schemaName);\n return entry.db;\n }\n\n // Create connection with retry\n const connectionPromise = this.connectWithRetry(tenantId, schemaName);\n this.pendingConnections.set(schemaName, connectionPromise);\n\n try {\n entry = await connectionPromise;\n this.poolCache.set(schemaName, entry);\n this.tenantIdBySchema.set(schemaName, tenantId);\n\n // Log pool creation\n this.debugLogger.logPoolCreated(tenantId, schemaName);\n\n // Fire hook asynchronously\n void this.config.hooks?.onPoolCreated?.(tenantId);\n\n this.poolCache.touch(schemaName);\n return entry.db;\n } finally {\n this.pendingConnections.delete(schemaName);\n }\n }\n\n /**\n * Connect to a tenant database with retry logic\n */\n private async connectWithRetry(\n tenantId: string,\n schemaName: string\n ): Promise<PoolEntry<TTenantSchema>> {\n const retryConfig = this.retryHandler.getConfig();\n const maxAttempts = retryConfig.maxAttempts;\n\n const result = await this.retryHandler.withRetry(\n async () => {\n // Create pool entry\n const entry = this.createPoolEntry(tenantId, schemaName);\n\n try {\n // Validate connection with ping query\n await entry.pool.query('SELECT 1');\n return entry;\n } catch (error) {\n // Clean up failed pool before retrying\n try {\n await entry.pool.end();\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n },\n {\n onRetry: (attempt, error, delayMs) => {\n // Log retry event\n this.debugLogger.logConnectionRetry(tenantId, attempt, maxAttempts, error, delayMs);\n\n // Call user-provided onRetry hook\n retryConfig.onRetry?.(attempt, error, delayMs);\n },\n }\n );\n\n // Log success if multiple attempts were needed\n this.debugLogger.logConnectionSuccess(tenantId, result.attempts, result.totalTimeMs);\n\n return result.result;\n }\n\n /**\n * Get or create the shared database connection\n */\n getSharedDb(): SharedDb<TSharedSchema> {\n this.ensureNotDisposed();\n\n if (!this.sharedDb) {\n this.sharedPool = new Pool({\n connectionString: this.config.connection.url,\n ...defaults.poolConfig,\n ...this.config.connection.poolConfig,\n });\n\n this.sharedPool.on('error', (err) => {\n void this.config.hooks?.onError?.('shared', err);\n });\n\n this.sharedDb = drizzle(this.sharedPool, {\n schema: this.config.schemas.shared,\n }) as SharedDb<TSharedSchema>;\n }\n\n return this.sharedDb;\n }\n\n /**\n * Get or create the shared database connection with retry and validation\n *\n * This async version validates the connection by executing a ping query\n * and retries on transient failures with exponential backoff.\n *\n * @example\n * ```typescript\n * // Get shared database with automatic retry\n * const sharedDb = await manager.getSharedDbAsync();\n *\n * // Queries will use the validated connection\n * const plans = await sharedDb.select().from(plans);\n * ```\n */\n async getSharedDbAsync(): Promise<SharedDb<TSharedSchema>> {\n this.ensureNotDisposed();\n\n if (this.sharedDb) {\n return this.sharedDb;\n }\n\n // Check if there's already a pending connection\n if (this.sharedDbPending) {\n return this.sharedDbPending;\n }\n\n // Create connection with retry\n this.sharedDbPending = this.connectSharedWithRetry();\n\n try {\n const db = await this.sharedDbPending;\n return db;\n } finally {\n this.sharedDbPending = null;\n }\n }\n\n /**\n * Connect to shared database with retry logic\n */\n private async connectSharedWithRetry(): Promise<SharedDb<TSharedSchema>> {\n const retryConfig = this.retryHandler.getConfig();\n const maxAttempts = retryConfig.maxAttempts;\n\n const result = await this.retryHandler.withRetry(\n async () => {\n const pool = new Pool({\n connectionString: this.config.connection.url,\n ...defaults.poolConfig,\n ...this.config.connection.poolConfig,\n });\n\n try {\n // Validate connection with ping query\n await pool.query('SELECT 1');\n\n pool.on('error', (err) => {\n void this.config.hooks?.onError?.('shared', err);\n });\n\n this.sharedPool = pool;\n this.sharedDb = drizzle(pool, {\n schema: this.config.schemas.shared,\n }) as SharedDb<TSharedSchema>;\n\n return this.sharedDb;\n } catch (error) {\n // Clean up failed pool before retrying\n try {\n await pool.end();\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n },\n {\n onRetry: (attempt, error, delayMs) => {\n // Log retry event\n this.debugLogger.logConnectionRetry('shared', attempt, maxAttempts, error, delayMs);\n\n // Call user-provided onRetry hook\n retryConfig.onRetry?.(attempt, error, delayMs);\n },\n }\n );\n\n // Log success if multiple attempts were needed\n this.debugLogger.logConnectionSuccess('shared', result.attempts, result.totalTimeMs);\n\n return result.result;\n }\n\n /**\n * Get schema name for a tenant\n */\n getSchemaName(tenantId: string): string {\n return this.config.isolation.schemaNameTemplate(tenantId);\n }\n\n /**\n * Check if a pool exists for a tenant\n */\n hasPool(tenantId: string): boolean {\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n return this.poolCache.has(schemaName);\n }\n\n /**\n * Get count of active pools\n */\n getPoolCount(): number {\n return this.poolCache.size();\n }\n\n /**\n * Get all active tenant IDs\n */\n getActiveTenantIds(): string[] {\n return Array.from(this.tenantIdBySchema.values());\n }\n\n /**\n * Get the retry configuration\n */\n getRetryConfig(): Required<RetryConfig> {\n return this.retryHandler.getConfig();\n }\n\n /**\n * Pre-warm pools for specified tenants to reduce cold start latency\n *\n * Uses automatic retry with exponential backoff for connection failures.\n */\n async warmup(tenantIds: string[], options: WarmupOptions = {}): Promise<WarmupResult> {\n this.ensureNotDisposed();\n\n const startTime = Date.now();\n const { concurrency = 10, ping = true, onProgress } = options;\n const results: TenantWarmupResult[] = [];\n\n // Process in batches\n for (let i = 0; i < tenantIds.length; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n const tenantStart = Date.now();\n onProgress?.(tenantId, 'starting');\n\n try {\n const alreadyWarm = this.hasPool(tenantId);\n\n // Use getDbAsync which includes retry logic and ping validation\n if (ping) {\n await this.getDbAsync(tenantId);\n } else {\n // For backward compatibility: sync version without ping\n this.getDb(tenantId);\n }\n\n const durationMs = Date.now() - tenantStart;\n onProgress?.(tenantId, 'completed');\n\n // Log warmup\n this.debugLogger.logWarmup(tenantId, true, durationMs, alreadyWarm);\n\n return {\n tenantId,\n success: true,\n alreadyWarm,\n durationMs,\n };\n } catch (error) {\n const durationMs = Date.now() - tenantStart;\n onProgress?.(tenantId, 'failed');\n\n // Log warmup failure\n this.debugLogger.logWarmup(tenantId, false, durationMs, false);\n\n return {\n tenantId,\n success: false,\n alreadyWarm: false,\n durationMs,\n error: (error as Error).message,\n };\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success).length,\n alreadyWarm: results.filter((r) => r.alreadyWarm).length,\n durationMs: Date.now() - startTime,\n details: results,\n };\n }\n\n /**\n * Get current metrics for all pools\n *\n * Collects metrics on demand with zero overhead when not called.\n * Returns raw data that can be formatted for any monitoring system.\n *\n * @example\n * ```typescript\n * const metrics = manager.getMetrics();\n * console.log(metrics.pools.total); // 15\n *\n * // Format for Prometheus\n * for (const pool of metrics.pools.tenants) {\n * gauge.labels(pool.tenantId).set(pool.connections.idle);\n * }\n * ```\n */\n getMetrics(): MetricsResult {\n this.ensureNotDisposed();\n\n const maxPools = this.config.isolation.maxPools ?? defaults.maxPools;\n const tenantMetrics: TenantPoolMetrics[] = [];\n\n for (const [schemaName, entry] of this.poolCache.entries()) {\n const tenantId = this.tenantIdBySchema.get(schemaName) ?? schemaName;\n const pool = entry.pool;\n\n tenantMetrics.push({\n tenantId,\n schemaName,\n connections: {\n total: pool.totalCount,\n idle: pool.idleCount,\n waiting: pool.waitingCount,\n },\n lastAccessedAt: new Date(entry.lastAccess).toISOString(),\n });\n }\n\n return {\n pools: {\n total: tenantMetrics.length,\n maxPools,\n tenants: tenantMetrics,\n },\n shared: {\n initialized: this.sharedPool !== null,\n connections: this.sharedPool\n ? {\n total: this.sharedPool.totalCount,\n idle: this.sharedPool.idleCount,\n waiting: this.sharedPool.waitingCount,\n }\n : null,\n },\n timestamp: new Date().toISOString(),\n };\n }\n\n /**\n * Check health of all pools and connections\n *\n * Verifies the health of tenant pools and optionally the shared database.\n * Returns detailed status information for monitoring and load balancer integration.\n *\n * @example\n * ```typescript\n * // Basic health check\n * const health = await manager.healthCheck();\n * console.log(health.healthy); // true/false\n *\n * // Use with Express endpoint\n * app.get('/health', async (req, res) => {\n * const health = await manager.healthCheck();\n * res.status(health.healthy ? 200 : 503).json(health);\n * });\n *\n * // Check specific tenants only\n * const health = await manager.healthCheck({\n * tenantIds: ['tenant-1', 'tenant-2'],\n * ping: true,\n * pingTimeoutMs: 3000,\n * });\n * ```\n */\n async healthCheck(options: HealthCheckOptions = {}): Promise<HealthCheckResult> {\n this.ensureNotDisposed();\n return this.healthChecker.checkHealth(options);\n }\n\n /**\n * Manually evict a tenant pool\n */\n async evictPool(tenantId: string, reason: string = 'manual'): Promise<void> {\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n const entry = this.poolCache.get(schemaName);\n\n if (entry) {\n // Log eviction\n this.debugLogger.logPoolEvicted(tenantId, schemaName, reason);\n\n this.poolCache.delete(schemaName);\n this.tenantIdBySchema.delete(schemaName);\n await this.closePool(entry.pool, tenantId);\n }\n }\n\n /**\n * Start automatic cleanup of idle pools\n */\n startCleanup(): void {\n if (this.cleanupInterval) return;\n\n const cleanupIntervalMs = defaults.cleanupIntervalMs;\n\n this.cleanupInterval = setInterval(() => {\n void this.cleanupIdlePools();\n }, cleanupIntervalMs);\n\n // Don't prevent process exit\n this.cleanupInterval.unref();\n }\n\n /**\n * Stop automatic cleanup\n */\n stopCleanup(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n }\n\n /**\n * Dispose all pools and cleanup resources\n */\n async dispose(): Promise<void> {\n if (this.disposed) return;\n\n this.disposed = true;\n this.stopCleanup();\n\n // Close all tenant pools\n const closePromises: Promise<void>[] = [];\n\n for (const [schemaName, entry] of this.poolCache.entries()) {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n closePromises.push(this.closePool(entry.pool, tenantId ?? schemaName));\n }\n\n await this.poolCache.clear();\n this.tenantIdBySchema.clear();\n\n // Close shared pool\n if (this.sharedPool) {\n closePromises.push(this.closePool(this.sharedPool, 'shared'));\n this.sharedPool = null;\n this.sharedDb = null;\n }\n\n await Promise.all(closePromises);\n }\n\n /**\n * Create a new pool entry for a tenant\n */\n private createPoolEntry(tenantId: string, schemaName: string): PoolEntry<TTenantSchema> {\n const pool = new Pool({\n connectionString: this.config.connection.url,\n ...defaults.poolConfig,\n ...this.config.connection.poolConfig,\n options: `-c search_path=${schemaName},public`,\n });\n\n pool.on('error', async (err) => {\n // Log pool error\n this.debugLogger.logPoolError(tenantId, err);\n\n void this.config.hooks?.onError?.(tenantId, err);\n await this.evictPool(tenantId, 'error');\n });\n\n const db = drizzle(pool, {\n schema: this.config.schemas.tenant,\n }) as TenantDb<TTenantSchema>;\n\n return {\n db,\n pool,\n lastAccess: Date.now(),\n schemaName,\n };\n }\n\n /**\n * Dispose a pool entry (called by LRU cache)\n */\n private disposePoolEntry(entry: PoolEntry<TTenantSchema>, schemaName: string): void {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n this.tenantIdBySchema.delete(schemaName);\n\n // Log pool eviction\n if (tenantId) {\n this.debugLogger.logPoolEvicted(tenantId, schemaName, 'lru_eviction');\n }\n\n void this.closePool(entry.pool, tenantId ?? schemaName).then(() => {\n if (tenantId) {\n void this.config.hooks?.onPoolEvicted?.(tenantId);\n }\n });\n }\n\n /**\n * Close a pool gracefully\n */\n private async closePool(pool: Pool, identifier: string): Promise<void> {\n try {\n await pool.end();\n } catch (error) {\n void this.config.hooks?.onError?.(identifier, error as Error);\n }\n }\n\n /**\n * Cleanup pools that have been idle for too long\n */\n private async cleanupIdlePools(): Promise<void> {\n const evictedSchemas = await this.poolCache.evictExpired();\n\n for (const schemaName of evictedSchemas) {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n if (tenantId) {\n this.debugLogger.logPoolEvicted(tenantId, schemaName, 'ttl_expired');\n this.tenantIdBySchema.delete(schemaName);\n }\n }\n }\n\n /**\n * Ensure the manager hasn't been disposed\n */\n private ensureNotDisposed(): void {\n if (this.disposed) {\n throw new Error('[drizzle-multitenant] TenantManager has been disposed');\n }\n }\n}\n","import { PoolManager } from './pool.js';\nimport type {\n Config,\n TenantManager,\n TenantDb,\n SharedDb,\n WarmupOptions,\n WarmupResult,\n RetryConfig,\n HealthCheckOptions,\n HealthCheckResult,\n MetricsResult,\n} from './types.js';\n\n/**\n * Create a tenant manager instance\n *\n * @example\n * ```typescript\n * import { createTenantManager, defineConfig } from 'drizzle-multitenant';\n *\n * const config = defineConfig({\n * connection: { url: process.env.DATABASE_URL! },\n * isolation: {\n * strategy: 'schema',\n * schemaNameTemplate: (id) => `tenant_${id}`,\n * },\n * schemas: { tenant: tenantSchema },\n * });\n *\n * const tenants = createTenantManager(config);\n *\n * // Get database for a specific tenant\n * const db = tenants.getDb('tenant-uuid');\n * const users = await db.select().from(schema.users);\n *\n * // Get shared database\n * const sharedDb = tenants.getSharedDb();\n * const plans = await sharedDb.select().from(sharedSchema.plans);\n * ```\n */\nexport function createTenantManager<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): TenantManager<TTenantSchema, TSharedSchema> {\n const poolManager = new PoolManager(config);\n\n // Start automatic cleanup\n poolManager.startCleanup();\n\n return {\n getDb(tenantId: string): TenantDb<TTenantSchema> {\n return poolManager.getDb(tenantId);\n },\n\n async getDbAsync(tenantId: string): Promise<TenantDb<TTenantSchema>> {\n return poolManager.getDbAsync(tenantId);\n },\n\n getSharedDb(): SharedDb<TSharedSchema> {\n return poolManager.getSharedDb();\n },\n\n async getSharedDbAsync(): Promise<SharedDb<TSharedSchema>> {\n return poolManager.getSharedDbAsync();\n },\n\n getSchemaName(tenantId: string): string {\n return poolManager.getSchemaName(tenantId);\n },\n\n hasPool(tenantId: string): boolean {\n return poolManager.hasPool(tenantId);\n },\n\n getPoolCount(): number {\n return poolManager.getPoolCount();\n },\n\n getActiveTenantIds(): string[] {\n return poolManager.getActiveTenantIds();\n },\n\n getRetryConfig(): Required<RetryConfig> {\n return poolManager.getRetryConfig();\n },\n\n async evictPool(tenantId: string): Promise<void> {\n await poolManager.evictPool(tenantId);\n },\n\n async warmup(tenantIds: string[], options?: WarmupOptions): Promise<WarmupResult> {\n return poolManager.warmup(tenantIds, options);\n },\n\n async healthCheck(options?: HealthCheckOptions): Promise<HealthCheckResult> {\n return poolManager.healthCheck(options);\n },\n\n getMetrics(): MetricsResult {\n return poolManager.getMetrics();\n },\n\n async dispose(): Promise<void> {\n await poolManager.dispose();\n },\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { TenantManager, TenantDb, SharedDb } from './types.js';\n\n/**\n * Base tenant context data\n */\nexport interface BaseTenantContext {\n tenantId: string;\n}\n\n/**\n * Tenant context with optional custom data\n */\nexport type TenantContextData<TCustom extends Record<string, unknown> = Record<string, unknown>> =\n BaseTenantContext & TCustom;\n\n/**\n * Tenant context API\n */\nexport interface TenantContext<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n> {\n /**\n * Run a callback with tenant context\n */\n runWithTenant<T>(\n context: TenantContextData<TCustom>,\n callback: () => T | Promise<T>\n ): T | Promise<T>;\n\n /**\n * Get current tenant context (throws if not in context)\n */\n getTenant(): TenantContextData<TCustom>;\n\n /**\n * Get current tenant context or undefined\n */\n getTenantOrNull(): TenantContextData<TCustom> | undefined;\n\n /**\n * Get current tenant ID (throws if not in context)\n */\n getTenantId(): string;\n\n /**\n * Get database for current tenant (throws if not in context)\n */\n getTenantDb(): TenantDb<TTenantSchema>;\n\n /**\n * Get shared database\n */\n getSharedDb(): SharedDb<TSharedSchema>;\n\n /**\n * Check if currently running within a tenant context\n */\n isInTenantContext(): boolean;\n}\n\n/**\n * Create a tenant context with AsyncLocalStorage\n *\n * @example\n * ```typescript\n * import { createTenantContext, createTenantManager } from 'drizzle-multitenant';\n *\n * const manager = createTenantManager(config);\n *\n * const {\n * runWithTenant,\n * getTenant,\n * getTenantDb,\n * getSharedDb,\n * } = createTenantContext(manager);\n *\n * // Use in request handler\n * app.get('/users', async (req, res) => {\n * const tenantId = req.headers['x-tenant-id'];\n *\n * await runWithTenant({ tenantId }, async () => {\n * const db = getTenantDb();\n * const users = await db.select().from(schema.users);\n * res.json(users);\n * });\n * });\n * ```\n */\nexport function createTenantContext<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n>(\n manager: TenantManager<TTenantSchema, TSharedSchema>\n): TenantContext<TTenantSchema, TSharedSchema, TCustom> {\n const storage = new AsyncLocalStorage<TenantContextData<TCustom>>();\n\n function getTenantOrNull(): TenantContextData<TCustom> | undefined {\n return storage.getStore();\n }\n\n function getTenant(): TenantContextData<TCustom> {\n const context = getTenantOrNull();\n if (!context) {\n throw new Error(\n '[drizzle-multitenant] No tenant context found. ' +\n 'Make sure you are calling this within runWithTenant().'\n );\n }\n return context;\n }\n\n function getTenantId(): string {\n return getTenant().tenantId;\n }\n\n function getTenantDb(): TenantDb<TTenantSchema> {\n const tenantId = getTenantId();\n return manager.getDb(tenantId);\n }\n\n function getSharedDb(): SharedDb<TSharedSchema> {\n return manager.getSharedDb();\n }\n\n function isInTenantContext(): boolean {\n return getTenantOrNull() !== undefined;\n }\n\n function runWithTenant<T>(\n context: TenantContextData<TCustom>,\n callback: () => T | Promise<T>\n ): T | Promise<T> {\n if (!context.tenantId) {\n throw new Error('[drizzle-multitenant] tenantId is required in context');\n }\n return storage.run(context, callback);\n }\n\n return {\n runWithTenant,\n getTenant,\n getTenantOrNull,\n getTenantId,\n getTenantDb,\n getSharedDb,\n isInTenantContext,\n };\n}\n","import type { Pool } from 'pg';\n\n/**\n * Table format for tracking migrations\n * - \"name\": drizzle-multitenant native (filename-based)\n * - \"hash\": SHA-256 hash with timestamp\n * - \"drizzle-kit\": Exact drizzle-kit format (hash + bigint timestamp)\n */\nexport type TableFormat = 'name' | 'hash' | 'drizzle-kit';\n\n/**\n * Detected table format information\n */\nexport interface DetectedFormat {\n /** The detected format type */\n format: TableFormat;\n /** The table name */\n tableName: string;\n /** Column configuration */\n columns: {\n /** Column used for identifying migrations */\n identifier: 'name' | 'hash';\n /** Column used for timestamp */\n timestamp: 'applied_at' | 'created_at';\n /** Data type of timestamp column */\n timestampType: 'timestamp' | 'bigint';\n };\n}\n\n/**\n * Default format configuration for new tables\n */\nexport const DEFAULT_FORMAT: DetectedFormat = {\n format: 'name',\n tableName: '__drizzle_migrations',\n columns: {\n identifier: 'name',\n timestamp: 'applied_at',\n timestampType: 'timestamp',\n },\n};\n\n/**\n * drizzle-kit format configuration\n */\nexport const DRIZZLE_KIT_FORMAT: DetectedFormat = {\n format: 'drizzle-kit',\n tableName: '__drizzle_migrations',\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n};\n\ninterface ColumnInfo {\n column_name: string;\n data_type: string;\n}\n\n/**\n * Detect the format of an existing migrations table\n *\n * @param pool - Database connection pool\n * @param schemaName - Schema to check\n * @param tableName - Migrations table name\n * @returns Detected format or null if table doesn't exist\n */\nexport async function detectTableFormat(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<DetectedFormat | null> {\n // Check if table exists\n const tableExists = await pool.query<{ exists: boolean }>(\n `SELECT EXISTS (\n SELECT 1 FROM information_schema.tables\n WHERE table_schema = $1 AND table_name = $2\n ) as exists`,\n [schemaName, tableName]\n );\n\n if (!tableExists.rows[0]?.exists) {\n return null;\n }\n\n // Get column information\n const columnsResult = await pool.query<ColumnInfo>(\n `SELECT column_name, data_type\n FROM information_schema.columns\n WHERE table_schema = $1 AND table_name = $2`,\n [schemaName, tableName]\n );\n\n const columnMap = new Map<string, string>(\n columnsResult.rows.map((r) => [r.column_name, r.data_type])\n );\n\n // Detect format based on columns\n if (columnMap.has('name')) {\n // drizzle-multitenant native format\n return {\n format: 'name',\n tableName,\n columns: {\n identifier: 'name',\n timestamp: columnMap.has('applied_at') ? 'applied_at' : 'created_at',\n timestampType: 'timestamp',\n },\n };\n }\n\n if (columnMap.has('hash')) {\n const createdAtType = columnMap.get('created_at');\n\n // drizzle-kit uses bigint for created_at\n if (createdAtType === 'bigint') {\n return {\n format: 'drizzle-kit',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n };\n }\n\n // Custom hash-based format with regular timestamp\n return {\n format: 'hash',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'timestamp',\n },\n };\n }\n\n // Unknown format - return null to trigger error handling\n return null;\n}\n\n/**\n * Get the format configuration for a specific format type\n */\nexport function getFormatConfig(\n format: TableFormat,\n tableName: string = '__drizzle_migrations'\n): DetectedFormat {\n switch (format) {\n case 'name':\n return {\n format: 'name',\n tableName,\n columns: {\n identifier: 'name',\n timestamp: 'applied_at',\n timestampType: 'timestamp',\n },\n };\n case 'hash':\n return {\n format: 'hash',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'timestamp',\n },\n };\n case 'drizzle-kit':\n return {\n format: 'drizzle-kit',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n };\n }\n}\n","import { Pool } from 'pg';\nimport type { Config } from '../types.js';\nimport type { DetectedFormat } from './table-format.js';\n\nconst DEFAULT_MIGRATIONS_TABLE = '__drizzle_migrations';\n\n/**\n * Options for creating a tenant schema\n */\nexport interface CreateSchemaOptions {\n /** Whether to also run migrations after creating (handled by Migrator) */\n migrate?: boolean;\n}\n\n/**\n * Options for dropping a tenant schema\n */\nexport interface DropSchemaOptions {\n /** Use CASCADE to drop all objects in schema */\n cascade?: boolean;\n /** Force drop without confirmation (used by CLI) */\n force?: boolean;\n}\n\n/**\n * Manages PostgreSQL schema lifecycle for multi-tenant applications.\n *\n * Extracted from Migrator to follow Single Responsibility Principle.\n * Handles schema creation, deletion, existence checks, and migrations table management.\n *\n * @example\n * ```typescript\n * const schemaManager = new SchemaManager(config);\n *\n * // Create a new tenant schema\n * await schemaManager.createSchema('tenant-123');\n *\n * // Check if schema exists\n * const exists = await schemaManager.schemaExists('tenant-123');\n *\n * // Drop a tenant schema\n * await schemaManager.dropSchema('tenant-123', { cascade: true });\n * ```\n */\nexport class SchemaManager<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly migrationsTable: string;\n\n constructor(\n private readonly config: Config<TTenantSchema, TSharedSchema>,\n migrationsTable?: string\n ) {\n this.migrationsTable = migrationsTable ?? DEFAULT_MIGRATIONS_TABLE;\n }\n\n /**\n * Get the schema name for a tenant ID using the configured template\n *\n * @param tenantId - The tenant identifier\n * @returns The PostgreSQL schema name\n *\n * @example\n * ```typescript\n * const schemaName = schemaManager.getSchemaName('tenant-123');\n * // Returns: 'tenant_tenant-123' (depends on schemaNameTemplate)\n * ```\n */\n getSchemaName(tenantId: string): string {\n return this.config.isolation.schemaNameTemplate(tenantId);\n }\n\n /**\n * Create a PostgreSQL pool for a specific schema\n *\n * The pool is configured with `search_path` set to the schema,\n * allowing queries to run in tenant isolation.\n *\n * @param schemaName - The PostgreSQL schema name\n * @returns A configured Pool instance\n *\n * @example\n * ```typescript\n * const pool = await schemaManager.createPool('tenant_123');\n * try {\n * await pool.query('SELECT * FROM users'); // Queries tenant_123.users\n * } finally {\n * await pool.end();\n * }\n * ```\n */\n async createPool(schemaName: string): Promise<Pool> {\n return new Pool({\n connectionString: this.config.connection.url,\n ...this.config.connection.poolConfig,\n options: `-c search_path=\"${schemaName}\",public`,\n });\n }\n\n /**\n * Create a PostgreSQL pool without schema-specific search_path\n *\n * Used for operations that need to work across schemas or\n * before a schema exists (like creating the schema itself).\n *\n * @returns A Pool instance connected to the database\n */\n async createRootPool(): Promise<Pool> {\n return new Pool({\n connectionString: this.config.connection.url,\n ...this.config.connection.poolConfig,\n });\n }\n\n /**\n * Create a new tenant schema in the database\n *\n * @param tenantId - The tenant identifier\n * @returns Promise that resolves when schema is created\n *\n * @example\n * ```typescript\n * await schemaManager.createSchema('new-tenant');\n * ```\n */\n async createSchema(tenantId: string): Promise<void> {\n const schemaName = this.getSchemaName(tenantId);\n const pool = await this.createRootPool();\n\n try {\n await pool.query(`CREATE SCHEMA IF NOT EXISTS \"${schemaName}\"`);\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Drop a tenant schema from the database\n *\n * @param tenantId - The tenant identifier\n * @param options - Drop options (cascade, force)\n * @returns Promise that resolves when schema is dropped\n *\n * @example\n * ```typescript\n * // Drop with CASCADE (removes all objects)\n * await schemaManager.dropSchema('old-tenant', { cascade: true });\n *\n * // Drop with RESTRICT (fails if objects exist)\n * await schemaManager.dropSchema('old-tenant', { cascade: false });\n * ```\n */\n async dropSchema(tenantId: string, options: DropSchemaOptions = {}): Promise<void> {\n const { cascade = true } = options;\n const schemaName = this.getSchemaName(tenantId);\n const pool = await this.createRootPool();\n\n try {\n const cascadeSql = cascade ? 'CASCADE' : 'RESTRICT';\n await pool.query(`DROP SCHEMA IF EXISTS \"${schemaName}\" ${cascadeSql}`);\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Check if a tenant schema exists in the database\n *\n * @param tenantId - The tenant identifier\n * @returns True if schema exists, false otherwise\n *\n * @example\n * ```typescript\n * if (await schemaManager.schemaExists('tenant-123')) {\n * console.log('Tenant schema exists');\n * }\n * ```\n */\n async schemaExists(tenantId: string): Promise<boolean> {\n const schemaName = this.getSchemaName(tenantId);\n const pool = await this.createRootPool();\n\n try {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.schemata WHERE schema_name = $1`,\n [schemaName]\n );\n return result.rowCount !== null && result.rowCount > 0;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * List all schemas matching a pattern\n *\n * @param pattern - SQL LIKE pattern to filter schemas (optional)\n * @returns Array of schema names\n *\n * @example\n * ```typescript\n * // List all tenant schemas\n * const schemas = await schemaManager.listSchemas('tenant_%');\n * ```\n */\n async listSchemas(pattern?: string): Promise<string[]> {\n const pool = await this.createRootPool();\n\n try {\n const query = pattern\n ? `SELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE $1 ORDER BY schema_name`\n : `SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast') ORDER BY schema_name`;\n\n const result = await pool.query<{ schema_name: string }>(\n query,\n pattern ? [pattern] : []\n );\n\n return result.rows.map((row) => row.schema_name);\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Ensure the migrations table exists with the correct format\n *\n * Creates the migrations tracking table if it doesn't exist,\n * using the appropriate column types based on the format.\n *\n * @param pool - Database pool to use\n * @param schemaName - The schema to create the table in\n * @param format - The detected/configured table format\n *\n * @example\n * ```typescript\n * const pool = await schemaManager.createPool('tenant_123');\n * await schemaManager.ensureMigrationsTable(pool, 'tenant_123', format);\n * ```\n */\n async ensureMigrationsTable(\n pool: Pool,\n schemaName: string,\n format: DetectedFormat\n ): Promise<void> {\n const { identifier, timestamp, timestampType } = format.columns;\n\n // Build column definitions based on format\n const identifierCol = identifier === 'name'\n ? 'name VARCHAR(255) NOT NULL UNIQUE'\n : 'hash TEXT NOT NULL';\n\n const timestampCol = timestampType === 'bigint'\n ? `${timestamp} BIGINT NOT NULL`\n : `${timestamp} TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP`;\n\n await pool.query(`\n CREATE TABLE IF NOT EXISTS \"${schemaName}\".\"${format.tableName}\" (\n id SERIAL PRIMARY KEY,\n ${identifierCol},\n ${timestampCol}\n )\n `);\n }\n\n /**\n * Check if the migrations table exists in a schema\n *\n * @param pool - Database pool to use\n * @param schemaName - The schema to check\n * @returns True if migrations table exists\n *\n * @example\n * ```typescript\n * const pool = await schemaManager.createPool('tenant_123');\n * if (await schemaManager.migrationsTableExists(pool, 'tenant_123')) {\n * console.log('Migrations table exists');\n * }\n * ```\n */\n async migrationsTableExists(pool: Pool, schemaName: string): Promise<boolean> {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.tables\n WHERE table_schema = $1 AND table_name = $2`,\n [schemaName, this.migrationsTable]\n );\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Get the configured migrations table name\n *\n * @returns The migrations table name\n */\n getMigrationsTableName(): string {\n return this.migrationsTable;\n }\n}\n\n/**\n * Factory function to create a SchemaManager instance\n *\n * @param config - The tenant configuration\n * @param migrationsTable - Optional custom migrations table name\n * @returns A new SchemaManager instance\n *\n * @example\n * ```typescript\n * const schemaManager = createSchemaManager(config);\n * await schemaManager.createSchema('tenant-123');\n * ```\n */\nexport function createSchemaManager<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n config: Config<TTenantSchema, TSharedSchema>,\n migrationsTable?: string\n): SchemaManager<TTenantSchema, TSharedSchema> {\n return new SchemaManager(config, migrationsTable);\n}\n","/**\n * Column Analyzer\n *\n * Analyzes and compares column structures between schemas.\n * Detects missing columns, extra columns, type mismatches, nullable changes, and default value changes.\n *\n * @module drift/column-analyzer\n */\n\nimport type { Pool } from 'pg';\nimport type { ColumnInfo, ColumnDrift } from './types.js';\n\n/**\n * Introspects columns for a specific table in a schema.\n *\n * Retrieves detailed column metadata including data types, nullability,\n * defaults, and precision information.\n *\n * @param pool - Database connection pool\n * @param schemaName - PostgreSQL schema name\n * @param tableName - Table name to introspect\n * @returns Array of column information\n *\n * @example\n * ```typescript\n * const columns = await introspectColumns(pool, 'tenant_123', 'users');\n * for (const col of columns) {\n * console.log(`${col.name}: ${col.dataType} ${col.isNullable ? 'NULL' : 'NOT NULL'}`);\n * }\n * ```\n */\nexport async function introspectColumns(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<ColumnInfo[]> {\n const result = await pool.query<{\n column_name: string;\n data_type: string;\n udt_name: string;\n is_nullable: string;\n column_default: string | null;\n character_maximum_length: number | null;\n numeric_precision: number | null;\n numeric_scale: number | null;\n ordinal_position: number;\n }>(\n `SELECT\n column_name,\n data_type,\n udt_name,\n is_nullable,\n column_default,\n character_maximum_length,\n numeric_precision,\n numeric_scale,\n ordinal_position\n FROM information_schema.columns\n WHERE table_schema = $1 AND table_name = $2\n ORDER BY ordinal_position`,\n [schemaName, tableName]\n );\n\n return result.rows.map((row) => ({\n name: row.column_name,\n dataType: row.data_type,\n udtName: row.udt_name,\n isNullable: row.is_nullable === 'YES',\n columnDefault: row.column_default,\n characterMaximumLength: row.character_maximum_length,\n numericPrecision: row.numeric_precision,\n numericScale: row.numeric_scale,\n ordinalPosition: row.ordinal_position,\n }));\n}\n\n/**\n * Normalizes a default value for comparison.\n *\n * Removes type casts and schema qualifiers to enable accurate comparison\n * between schemas that may have different representations of the same default.\n *\n * @param value - The default value expression from the database\n * @returns Normalized value string or null\n *\n * @example\n * ```typescript\n * normalizeDefault(\"'123'::integer\") // Returns: '123'\n * normalizeDefault(\"CURRENT_TIMESTAMP\") // Returns: 'CURRENT_TIMESTAMP'\n * normalizeDefault(null) // Returns: null\n * ```\n */\nexport function normalizeDefault(value: string | null): string | null {\n if (value === null) return null;\n return value\n .replace(/^'(.+)'::.+$/, '$1') // '123'::integer -> 123\n .replace(/^(.+)::.+$/, '$1') // value::type -> value\n .trim();\n}\n\n/**\n * Compares columns between a reference and target schema.\n *\n * Detects the following types of drift:\n * - Missing columns: Present in reference but absent in target\n * - Extra columns: Present in target but absent in reference\n * - Type mismatches: Different data types\n * - Nullable mismatches: Different NULL/NOT NULL constraints\n * - Default mismatches: Different default values\n *\n * @param reference - Columns from the reference (expected) schema\n * @param target - Columns from the target (actual) schema\n * @returns Array of column drift details\n *\n * @example\n * ```typescript\n * const refColumns = await introspectColumns(pool, 'tenant_ref', 'users');\n * const targetColumns = await introspectColumns(pool, 'tenant_123', 'users');\n * const drifts = compareColumns(refColumns, targetColumns);\n *\n * for (const drift of drifts) {\n * console.log(`${drift.column}: ${drift.description}`);\n * }\n * ```\n */\nexport function compareColumns(\n reference: ColumnInfo[],\n target: ColumnInfo[]\n): ColumnDrift[] {\n const drifts: ColumnDrift[] = [];\n const refColMap = new Map(reference.map((c) => [c.name, c]));\n const targetColMap = new Map(target.map((c) => [c.name, c]));\n\n // Check for missing and drifted columns\n for (const refCol of reference) {\n const targetCol = targetColMap.get(refCol.name);\n\n if (!targetCol) {\n drifts.push({\n column: refCol.name,\n type: 'missing',\n expected: refCol.dataType,\n description: `Column \"${refCol.name}\" (${refCol.dataType}) is missing`,\n });\n continue;\n }\n\n // Compare data types (normalize by comparing udt_name)\n if (refCol.udtName !== targetCol.udtName) {\n drifts.push({\n column: refCol.name,\n type: 'type_mismatch',\n expected: refCol.udtName,\n actual: targetCol.udtName,\n description: `Column \"${refCol.name}\" type mismatch: expected \"${refCol.udtName}\", got \"${targetCol.udtName}\"`,\n });\n }\n\n // Compare nullable\n if (refCol.isNullable !== targetCol.isNullable) {\n drifts.push({\n column: refCol.name,\n type: 'nullable_mismatch',\n expected: refCol.isNullable,\n actual: targetCol.isNullable,\n description: `Column \"${refCol.name}\" nullable mismatch: expected ${refCol.isNullable ? 'NULL' : 'NOT NULL'}, got ${targetCol.isNullable ? 'NULL' : 'NOT NULL'}`,\n });\n }\n\n // Compare defaults (normalize by removing schema qualifiers)\n const normalizedRefDefault = normalizeDefault(refCol.columnDefault);\n const normalizedTargetDefault = normalizeDefault(targetCol.columnDefault);\n if (normalizedRefDefault !== normalizedTargetDefault) {\n drifts.push({\n column: refCol.name,\n type: 'default_mismatch',\n expected: refCol.columnDefault,\n actual: targetCol.columnDefault,\n description: `Column \"${refCol.name}\" default mismatch: expected \"${refCol.columnDefault ?? 'none'}\", got \"${targetCol.columnDefault ?? 'none'}\"`,\n });\n }\n }\n\n // Check for extra columns\n for (const targetCol of target) {\n if (!refColMap.has(targetCol.name)) {\n drifts.push({\n column: targetCol.name,\n type: 'extra',\n actual: targetCol.dataType,\n description: `Extra column \"${targetCol.name}\" (${targetCol.dataType}) not in reference`,\n });\n }\n }\n\n return drifts;\n}\n","/**\n * Index Analyzer\n *\n * Analyzes and compares index structures between schemas.\n * Detects missing indexes, extra indexes, and definition mismatches.\n *\n * @module drift/index-analyzer\n */\n\nimport type { Pool } from 'pg';\nimport type { IndexInfo, IndexDrift } from './types.js';\n\n/**\n * Introspects indexes for a specific table in a schema.\n *\n * Retrieves detailed index metadata including columns, uniqueness,\n * and full index definition.\n *\n * @param pool - Database connection pool\n * @param schemaName - PostgreSQL schema name\n * @param tableName - Table name to introspect\n * @returns Array of index information\n *\n * @example\n * ```typescript\n * const indexes = await introspectIndexes(pool, 'tenant_123', 'users');\n * for (const idx of indexes) {\n * console.log(`${idx.name}: ${idx.columns.join(', ')} ${idx.isUnique ? 'UNIQUE' : ''}`);\n * }\n * ```\n */\nexport async function introspectIndexes(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<IndexInfo[]> {\n // Get index definitions\n const indexResult = await pool.query<{\n indexname: string;\n indexdef: string;\n }>(\n `SELECT indexname, indexdef\n FROM pg_indexes\n WHERE schemaname = $1 AND tablename = $2\n ORDER BY indexname`,\n [schemaName, tableName]\n );\n\n // Get index columns and properties from pg_index\n const indexDetails = await pool.query<{\n indexname: string;\n column_name: string;\n is_unique: boolean;\n is_primary: boolean;\n }>(\n `SELECT\n i.relname as indexname,\n a.attname as column_name,\n ix.indisunique as is_unique,\n ix.indisprimary as is_primary\n FROM pg_class t\n JOIN pg_index ix ON t.oid = ix.indrelid\n JOIN pg_class i ON i.oid = ix.indexrelid\n JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n JOIN pg_namespace n ON n.oid = t.relnamespace\n WHERE n.nspname = $1 AND t.relname = $2\n ORDER BY i.relname, a.attnum`,\n [schemaName, tableName]\n );\n\n // Group columns by index\n const indexColumnsMap = new Map<\n string,\n { columns: string[]; isUnique: boolean; isPrimary: boolean }\n >();\n\n for (const row of indexDetails.rows) {\n const existing = indexColumnsMap.get(row.indexname);\n if (existing) {\n existing.columns.push(row.column_name);\n } else {\n indexColumnsMap.set(row.indexname, {\n columns: [row.column_name],\n isUnique: row.is_unique,\n isPrimary: row.is_primary,\n });\n }\n }\n\n return indexResult.rows.map((row) => {\n const details = indexColumnsMap.get(row.indexname);\n return {\n name: row.indexname,\n columns: details?.columns ?? [],\n isUnique: details?.isUnique ?? false,\n isPrimary: details?.isPrimary ?? false,\n definition: row.indexdef,\n };\n });\n}\n\n/**\n * Compares indexes between a reference and target schema.\n *\n * Detects the following types of drift:\n * - Missing indexes: Present in reference but absent in target\n * - Extra indexes: Present in target but absent in reference\n * - Definition mismatches: Different columns or uniqueness settings\n *\n * @param reference - Indexes from the reference (expected) schema\n * @param target - Indexes from the target (actual) schema\n * @returns Array of index drift details\n *\n * @example\n * ```typescript\n * const refIndexes = await introspectIndexes(pool, 'tenant_ref', 'users');\n * const targetIndexes = await introspectIndexes(pool, 'tenant_123', 'users');\n * const drifts = compareIndexes(refIndexes, targetIndexes);\n *\n * for (const drift of drifts) {\n * console.log(`${drift.index}: ${drift.description}`);\n * }\n * ```\n */\nexport function compareIndexes(\n reference: IndexInfo[],\n target: IndexInfo[]\n): IndexDrift[] {\n const drifts: IndexDrift[] = [];\n const refIndexMap = new Map(reference.map((i) => [i.name, i]));\n const targetIndexMap = new Map(target.map((i) => [i.name, i]));\n\n // Check for missing indexes\n for (const refIndex of reference) {\n const targetIndex = targetIndexMap.get(refIndex.name);\n\n if (!targetIndex) {\n drifts.push({\n index: refIndex.name,\n type: 'missing',\n expected: refIndex.definition,\n description: `Index \"${refIndex.name}\" is missing`,\n });\n continue;\n }\n\n // Compare columns and uniqueness\n const refCols = refIndex.columns.sort().join(',');\n const targetCols = targetIndex.columns.sort().join(',');\n if (refCols !== targetCols || refIndex.isUnique !== targetIndex.isUnique) {\n drifts.push({\n index: refIndex.name,\n type: 'definition_mismatch',\n expected: refIndex.definition,\n actual: targetIndex.definition,\n description: `Index \"${refIndex.name}\" definition differs`,\n });\n }\n }\n\n // Check for extra indexes\n for (const targetIndex of target) {\n if (!refIndexMap.has(targetIndex.name)) {\n drifts.push({\n index: targetIndex.name,\n type: 'extra',\n actual: targetIndex.definition,\n description: `Extra index \"${targetIndex.name}\" not in reference`,\n });\n }\n }\n\n return drifts;\n}\n","/**\n * Constraint Analyzer\n *\n * Analyzes and compares constraint structures between schemas.\n * Detects missing constraints, extra constraints, and definition mismatches.\n *\n * @module drift/constraint-analyzer\n */\n\nimport type { Pool } from 'pg';\nimport type { ConstraintInfo, ConstraintDrift } from './types.js';\n\n/**\n * Introspects constraints for a specific table in a schema.\n *\n * Retrieves detailed constraint metadata including type, columns,\n * foreign key references, and check expressions.\n *\n * @param pool - Database connection pool\n * @param schemaName - PostgreSQL schema name\n * @param tableName - Table name to introspect\n * @returns Array of constraint information\n *\n * @example\n * ```typescript\n * const constraints = await introspectConstraints(pool, 'tenant_123', 'orders');\n * for (const con of constraints) {\n * console.log(`${con.name}: ${con.type} on (${con.columns.join(', ')})`);\n * }\n * ```\n */\nexport async function introspectConstraints(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<ConstraintInfo[]> {\n const result = await pool.query<{\n constraint_name: string;\n constraint_type: string;\n column_name: string;\n foreign_table_schema: string | null;\n foreign_table_name: string | null;\n foreign_column_name: string | null;\n check_clause: string | null;\n }>(\n `SELECT\n tc.constraint_name,\n tc.constraint_type,\n kcu.column_name,\n ccu.table_schema as foreign_table_schema,\n ccu.table_name as foreign_table_name,\n ccu.column_name as foreign_column_name,\n cc.check_clause\n FROM information_schema.table_constraints tc\n LEFT JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n LEFT JOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.constraint_type = 'FOREIGN KEY'\n LEFT JOIN information_schema.check_constraints cc\n ON tc.constraint_name = cc.constraint_name\n AND tc.constraint_type = 'CHECK'\n WHERE tc.table_schema = $1 AND tc.table_name = $2\n ORDER BY tc.constraint_name, kcu.ordinal_position`,\n [schemaName, tableName]\n );\n\n // Group by constraint name since multi-column constraints return multiple rows\n const constraintMap = new Map<string, ConstraintInfo>();\n\n for (const row of result.rows) {\n const existing = constraintMap.get(row.constraint_name);\n if (existing) {\n // Add column if not already present\n if (row.column_name && !existing.columns.includes(row.column_name)) {\n existing.columns.push(row.column_name);\n }\n // Add foreign column if not already present\n if (\n row.foreign_column_name &&\n existing.foreignColumns &&\n !existing.foreignColumns.includes(row.foreign_column_name)\n ) {\n existing.foreignColumns.push(row.foreign_column_name);\n }\n } else {\n const constraint: ConstraintInfo = {\n name: row.constraint_name,\n type: row.constraint_type as ConstraintInfo['type'],\n columns: row.column_name ? [row.column_name] : [],\n };\n if (row.foreign_table_name) {\n constraint.foreignTable = row.foreign_table_name;\n }\n if (row.foreign_column_name) {\n constraint.foreignColumns = [row.foreign_column_name];\n }\n if (row.check_clause) {\n constraint.checkExpression = row.check_clause;\n }\n constraintMap.set(row.constraint_name, constraint);\n }\n }\n\n return Array.from(constraintMap.values());\n}\n\n/**\n * Compares constraints between a reference and target schema.\n *\n * Detects the following types of drift:\n * - Missing constraints: Present in reference but absent in target\n * - Extra constraints: Present in target but absent in reference\n * - Definition mismatches: Different type or columns\n *\n * @param reference - Constraints from the reference (expected) schema\n * @param target - Constraints from the target (actual) schema\n * @returns Array of constraint drift details\n *\n * @example\n * ```typescript\n * const refConstraints = await introspectConstraints(pool, 'tenant_ref', 'orders');\n * const targetConstraints = await introspectConstraints(pool, 'tenant_123', 'orders');\n * const drifts = compareConstraints(refConstraints, targetConstraints);\n *\n * for (const drift of drifts) {\n * console.log(`${drift.constraint}: ${drift.description}`);\n * }\n * ```\n */\nexport function compareConstraints(\n reference: ConstraintInfo[],\n target: ConstraintInfo[]\n): ConstraintDrift[] {\n const drifts: ConstraintDrift[] = [];\n const refConstraintMap = new Map(reference.map((c) => [c.name, c]));\n const targetConstraintMap = new Map(target.map((c) => [c.name, c]));\n\n // Check for missing constraints\n for (const refConstraint of reference) {\n const targetConstraint = targetConstraintMap.get(refConstraint.name);\n\n if (!targetConstraint) {\n drifts.push({\n constraint: refConstraint.name,\n type: 'missing',\n expected: `${refConstraint.type} on (${refConstraint.columns.join(', ')})`,\n description: `Constraint \"${refConstraint.name}\" (${refConstraint.type}) is missing`,\n });\n continue;\n }\n\n // Compare constraint details\n const refCols = refConstraint.columns.sort().join(',');\n const targetCols = targetConstraint.columns.sort().join(',');\n if (refConstraint.type !== targetConstraint.type || refCols !== targetCols) {\n drifts.push({\n constraint: refConstraint.name,\n type: 'definition_mismatch',\n expected: `${refConstraint.type} on (${refConstraint.columns.join(', ')})`,\n actual: `${targetConstraint.type} on (${targetConstraint.columns.join(', ')})`,\n description: `Constraint \"${refConstraint.name}\" definition differs`,\n });\n }\n }\n\n // Check for extra constraints\n for (const targetConstraint of target) {\n if (!refConstraintMap.has(targetConstraint.name)) {\n drifts.push({\n constraint: targetConstraint.name,\n type: 'extra',\n actual: `${targetConstraint.type} on (${targetConstraint.columns.join(', ')})`,\n description: `Extra constraint \"${targetConstraint.name}\" (${targetConstraint.type}) not in reference`,\n });\n }\n }\n\n return drifts;\n}\n","/**\n * Drift Detector\n *\n * Detects schema drift between tenant databases by comparing their structures.\n * Identifies differences in tables, columns, indexes, and constraints.\n *\n * Extracted from Migrator to follow Single Responsibility Principle.\n *\n * @module drift/drift-detector\n */\n\nimport type { Pool } from 'pg';\nimport type { Config } from '../../types.js';\nimport type { SchemaManager } from '../schema-manager.js';\nimport type {\n TenantSchema,\n TableSchema,\n TenantSchemaDrift,\n SchemaDriftStatus,\n SchemaDriftOptions,\n TableDrift,\n IntrospectOptions,\n} from './types.js';\nimport { introspectColumns, compareColumns } from './column-analyzer.js';\nimport { introspectIndexes, compareIndexes } from './index-analyzer.js';\nimport { introspectConstraints, compareConstraints } from './constraint-analyzer.js';\n\nconst DEFAULT_MIGRATIONS_TABLE = '__drizzle_migrations';\n\n/**\n * Configuration options for DriftDetector\n */\nexport interface DriftDetectorConfig {\n /** Migrations table name to exclude from comparisons */\n migrationsTable?: string;\n /** Function to discover tenant IDs */\n tenantDiscovery: () => Promise<string[]>;\n}\n\n/**\n * Detects schema drift between tenant databases.\n *\n * Schema drift occurs when tenant databases have structural differences\n * that shouldn't exist if all migrations were applied consistently.\n * This class helps identify such inconsistencies by comparing schemas.\n *\n * @example\n * ```typescript\n * const detector = new DriftDetector(config, schemaManager, {\n * migrationsTable: '__drizzle_migrations',\n * tenantDiscovery: async () => ['tenant-1', 'tenant-2', 'tenant-3'],\n * });\n *\n * // Detect drift across all tenants\n * const status = await detector.detectDrift();\n * if (status.withDrift > 0) {\n * console.log('Schema drift detected!');\n * for (const tenant of status.details) {\n * if (tenant.hasDrift) {\n * console.log(`Tenant ${tenant.tenantId}:`);\n * for (const table of tenant.tables) {\n * console.log(` Table ${table.table}: ${table.status}`);\n * }\n * }\n * }\n * }\n * ```\n */\nexport class DriftDetector<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly migrationsTable: string;\n\n constructor(\n private readonly tenantConfig: Config<TTenantSchema, TSharedSchema>,\n private readonly schemaManager: SchemaManager<TTenantSchema, TSharedSchema>,\n private readonly driftConfig: DriftDetectorConfig\n ) {\n this.migrationsTable = driftConfig.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE;\n }\n\n /**\n * Get the schema name for a tenant ID\n */\n private getSchemaName(tenantId: string): string {\n return this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n }\n\n /**\n * Create a pool for a schema\n */\n private async createPool(schemaName: string): Promise<Pool> {\n return this.schemaManager.createPool(schemaName);\n }\n\n /**\n * Detect schema drift across all tenants.\n *\n * Compares each tenant's schema against a reference tenant (first tenant by default).\n * Returns a comprehensive report of all differences found.\n *\n * @param options - Detection options\n * @returns Schema drift status with details for each tenant\n *\n * @example\n * ```typescript\n * // Basic usage - compare all tenants against the first one\n * const status = await detector.detectDrift();\n *\n * // Use a specific tenant as reference\n * const status = await detector.detectDrift({\n * referenceTenant: 'golden-tenant',\n * });\n *\n * // Check specific tenants only\n * const status = await detector.detectDrift({\n * tenantIds: ['tenant-1', 'tenant-2'],\n * });\n *\n * // Skip index and constraint comparison for faster checks\n * const status = await detector.detectDrift({\n * includeIndexes: false,\n * includeConstraints: false,\n * });\n * ```\n */\n async detectDrift(options: SchemaDriftOptions = {}): Promise<SchemaDriftStatus> {\n const startTime = Date.now();\n const {\n concurrency = 10,\n includeIndexes = true,\n includeConstraints = true,\n excludeTables = [this.migrationsTable],\n onProgress,\n } = options;\n\n // Get tenant IDs to check\n const tenantIds = options.tenantIds ?? (await this.driftConfig.tenantDiscovery());\n\n if (tenantIds.length === 0) {\n return {\n referenceTenant: '',\n total: 0,\n noDrift: 0,\n withDrift: 0,\n error: 0,\n details: [],\n timestamp: new Date().toISOString(),\n durationMs: Date.now() - startTime,\n };\n }\n\n // Determine reference tenant\n const referenceTenant = options.referenceTenant ?? tenantIds[0]!;\n\n // Get reference schema\n onProgress?.(referenceTenant, 'starting');\n onProgress?.(referenceTenant, 'introspecting');\n\n const referenceSchema = await this.introspectSchema(referenceTenant, {\n includeIndexes,\n includeConstraints,\n excludeTables,\n });\n\n if (!referenceSchema) {\n return {\n referenceTenant,\n total: tenantIds.length,\n noDrift: 0,\n withDrift: 0,\n error: tenantIds.length,\n details: tenantIds.map((id) => ({\n tenantId: id,\n schemaName: this.getSchemaName(id),\n hasDrift: false,\n tables: [],\n issueCount: 0,\n error:\n id === referenceTenant\n ? 'Failed to introspect reference tenant'\n : 'Reference tenant introspection failed',\n })),\n timestamp: new Date().toISOString(),\n durationMs: Date.now() - startTime,\n };\n }\n\n onProgress?.(referenceTenant, 'completed');\n\n // Filter out reference tenant from comparison\n const tenantsToCheck = tenantIds.filter((id) => id !== referenceTenant);\n\n // Compare each tenant against reference\n const results: TenantSchemaDrift[] = [];\n\n // Add reference tenant as \"no drift\" (it's the baseline)\n results.push({\n tenantId: referenceTenant,\n schemaName: referenceSchema.schemaName,\n hasDrift: false,\n tables: [],\n issueCount: 0,\n });\n\n // Process tenants in batches\n for (let i = 0; i < tenantsToCheck.length; i += concurrency) {\n const batch = tenantsToCheck.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n try {\n onProgress?.(tenantId, 'starting');\n onProgress?.(tenantId, 'introspecting');\n\n const tenantSchema = await this.introspectSchema(tenantId, {\n includeIndexes,\n includeConstraints,\n excludeTables,\n });\n\n if (!tenantSchema) {\n onProgress?.(tenantId, 'failed');\n return {\n tenantId,\n schemaName: this.getSchemaName(tenantId),\n hasDrift: false,\n tables: [],\n issueCount: 0,\n error: 'Failed to introspect schema',\n };\n }\n\n onProgress?.(tenantId, 'comparing');\n\n const drift = this.compareSchemas(referenceSchema, tenantSchema, {\n includeIndexes,\n includeConstraints,\n });\n\n onProgress?.(tenantId, 'completed');\n\n return drift;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n return {\n tenantId,\n schemaName: this.getSchemaName(tenantId),\n hasDrift: false,\n tables: [],\n issueCount: 0,\n error: (error as Error).message,\n };\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return {\n referenceTenant,\n total: results.length,\n noDrift: results.filter((r) => !r.hasDrift && !r.error).length,\n withDrift: results.filter((r) => r.hasDrift && !r.error).length,\n error: results.filter((r) => !!r.error).length,\n details: results,\n timestamp: new Date().toISOString(),\n durationMs: Date.now() - startTime,\n };\n }\n\n /**\n * Compare a specific tenant against a reference tenant.\n *\n * @param tenantId - Tenant to check\n * @param referenceTenantId - Tenant to use as reference\n * @param options - Introspection options\n * @returns Drift details for the tenant\n *\n * @example\n * ```typescript\n * const drift = await detector.compareTenant('tenant-123', 'golden-tenant');\n * if (drift.hasDrift) {\n * console.log(`Found ${drift.issueCount} issues`);\n * }\n * ```\n */\n async compareTenant(\n tenantId: string,\n referenceTenantId: string,\n options: IntrospectOptions = {}\n ): Promise<TenantSchemaDrift> {\n const {\n includeIndexes = true,\n includeConstraints = true,\n excludeTables = [this.migrationsTable],\n } = options;\n\n const referenceSchema = await this.introspectSchema(referenceTenantId, {\n includeIndexes,\n includeConstraints,\n excludeTables,\n });\n\n if (!referenceSchema) {\n return {\n tenantId,\n schemaName: this.getSchemaName(tenantId),\n hasDrift: false,\n tables: [],\n issueCount: 0,\n error: 'Failed to introspect reference tenant',\n };\n }\n\n const tenantSchema = await this.introspectSchema(tenantId, {\n includeIndexes,\n includeConstraints,\n excludeTables,\n });\n\n if (!tenantSchema) {\n return {\n tenantId,\n schemaName: this.getSchemaName(tenantId),\n hasDrift: false,\n tables: [],\n issueCount: 0,\n error: 'Failed to introspect tenant schema',\n };\n }\n\n return this.compareSchemas(referenceSchema, tenantSchema, {\n includeIndexes,\n includeConstraints,\n });\n }\n\n /**\n * Introspect a tenant's schema structure.\n *\n * Retrieves all tables, columns, indexes, and constraints\n * for a tenant's schema.\n *\n * @param tenantId - Tenant to introspect\n * @param options - Introspection options\n * @returns Schema structure or null if introspection fails\n *\n * @example\n * ```typescript\n * const schema = await detector.introspectSchema('tenant-123');\n * if (schema) {\n * console.log(`Found ${schema.tables.length} tables`);\n * for (const table of schema.tables) {\n * console.log(` ${table.name}: ${table.columns.length} columns`);\n * }\n * }\n * ```\n */\n async introspectSchema(\n tenantId: string,\n options: IntrospectOptions = {}\n ): Promise<TenantSchema | null> {\n const schemaName = this.getSchemaName(tenantId);\n const pool = await this.createPool(schemaName);\n\n try {\n const tables = await this.introspectTables(pool, schemaName, options);\n\n return {\n tenantId,\n schemaName,\n tables,\n introspectedAt: new Date(),\n };\n } catch {\n return null;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Compare two schema snapshots.\n *\n * This method compares pre-introspected schema snapshots,\n * useful when you already have the schema data available.\n *\n * @param reference - Reference (expected) schema\n * @param target - Target (actual) schema\n * @param options - Comparison options\n * @returns Drift details\n *\n * @example\n * ```typescript\n * const refSchema = await detector.introspectSchema('golden-tenant');\n * const targetSchema = await detector.introspectSchema('tenant-123');\n *\n * if (refSchema && targetSchema) {\n * const drift = detector.compareSchemas(refSchema, targetSchema);\n * console.log(`Drift detected: ${drift.hasDrift}`);\n * }\n * ```\n */\n compareSchemas(\n reference: TenantSchema,\n target: TenantSchema,\n options: Pick<IntrospectOptions, 'includeIndexes' | 'includeConstraints'> = {}\n ): TenantSchemaDrift {\n const { includeIndexes = true, includeConstraints = true } = options;\n const tableDrifts: TableDrift[] = [];\n let totalIssues = 0;\n\n const refTableMap = new Map(reference.tables.map((t) => [t.name, t]));\n const targetTableMap = new Map(target.tables.map((t) => [t.name, t]));\n\n // Check for missing and drifted tables\n for (const refTable of reference.tables) {\n const targetTable = targetTableMap.get(refTable.name);\n\n if (!targetTable) {\n // Table is missing in target\n tableDrifts.push({\n table: refTable.name,\n status: 'missing',\n columns: refTable.columns.map((c) => ({\n column: c.name,\n type: 'missing',\n expected: c.dataType,\n description: `Column \"${c.name}\" (${c.dataType}) is missing`,\n })),\n indexes: [],\n constraints: [],\n });\n totalIssues += refTable.columns.length;\n continue;\n }\n\n // Compare table structure\n const columnDrifts = compareColumns(refTable.columns, targetTable.columns);\n const indexDrifts = includeIndexes\n ? compareIndexes(refTable.indexes, targetTable.indexes)\n : [];\n const constraintDrifts = includeConstraints\n ? compareConstraints(refTable.constraints, targetTable.constraints)\n : [];\n\n const issues = columnDrifts.length + indexDrifts.length + constraintDrifts.length;\n totalIssues += issues;\n\n if (issues > 0) {\n tableDrifts.push({\n table: refTable.name,\n status: 'drifted',\n columns: columnDrifts,\n indexes: indexDrifts,\n constraints: constraintDrifts,\n });\n }\n }\n\n // Check for extra tables in target\n for (const targetTable of target.tables) {\n if (!refTableMap.has(targetTable.name)) {\n tableDrifts.push({\n table: targetTable.name,\n status: 'extra',\n columns: targetTable.columns.map((c) => ({\n column: c.name,\n type: 'extra',\n actual: c.dataType,\n description: `Extra column \"${c.name}\" (${c.dataType}) not in reference`,\n })),\n indexes: [],\n constraints: [],\n });\n totalIssues += targetTable.columns.length;\n }\n }\n\n return {\n tenantId: target.tenantId,\n schemaName: target.schemaName,\n hasDrift: totalIssues > 0,\n tables: tableDrifts,\n issueCount: totalIssues,\n };\n }\n\n /**\n * Introspect all tables in a schema\n */\n private async introspectTables(\n pool: Pool,\n schemaName: string,\n options: IntrospectOptions\n ): Promise<TableSchema[]> {\n const { includeIndexes = true, includeConstraints = true, excludeTables = [] } = options;\n\n // Get all tables in schema\n const tablesResult = await pool.query<{ table_name: string }>(\n `SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = $1\n AND table_type = 'BASE TABLE'\n ORDER BY table_name`,\n [schemaName]\n );\n\n const tables: TableSchema[] = [];\n\n for (const row of tablesResult.rows) {\n if (excludeTables.includes(row.table_name)) {\n continue;\n }\n\n const columns = await introspectColumns(pool, schemaName, row.table_name);\n const indexes = includeIndexes\n ? await introspectIndexes(pool, schemaName, row.table_name)\n : [];\n const constraints = includeConstraints\n ? await introspectConstraints(pool, schemaName, row.table_name)\n : [];\n\n tables.push({\n name: row.table_name,\n columns,\n indexes,\n constraints,\n });\n }\n\n return tables;\n }\n}\n\n/**\n * Factory function to create a DriftDetector instance.\n *\n * @param config - Tenant configuration\n * @param schemaManager - Schema manager instance\n * @param driftConfig - Drift detector configuration\n * @returns A new DriftDetector instance\n *\n * @example\n * ```typescript\n * const detector = createDriftDetector(config, schemaManager, {\n * migrationsTable: '__drizzle_migrations',\n * tenantDiscovery: async () => db.select().from(tenants).then(t => t.map(x => x.id)),\n * });\n * ```\n */\nexport function createDriftDetector<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n config: Config<TTenantSchema, TSharedSchema>,\n schemaManager: SchemaManager<TTenantSchema, TSharedSchema>,\n driftConfig: DriftDetectorConfig\n): DriftDetector<TTenantSchema, TSharedSchema> {\n return new DriftDetector(config, schemaManager, driftConfig);\n}\n","import { drizzle } from 'drizzle-orm/node-postgres';\nimport type {\n SeedFunction,\n SeedOptions,\n TenantSeedResult,\n SeedResults,\n} from '../types.js';\nimport type { ISeeder } from '../interfaces.js';\nimport type { SeederConfig, SeederDependencies } from './types.js';\n\n/**\n * Responsible for seeding tenant databases with initial data.\n *\n * Extracted from Migrator to follow Single Responsibility Principle.\n * Handles seeding individual tenants and batch seeding operations.\n *\n * @example\n * ```typescript\n * const seeder = new Seeder(config, dependencies);\n *\n * // Seed a single tenant\n * const result = await seeder.seedTenant('tenant-123', async (db, tenantId) => {\n * await db.insert(roles).values([\n * { name: 'admin', permissions: ['*'] },\n * { name: 'user', permissions: ['read'] },\n * ]);\n * });\n *\n * // Seed all tenants\n * const results = await seeder.seedAll(seedFn, { concurrency: 10 });\n * ```\n */\nexport class Seeder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n> implements ISeeder<TTenantSchema>\n{\n constructor(\n private readonly config: SeederConfig,\n private readonly deps: SeederDependencies<TTenantSchema>\n ) {}\n\n /**\n * Seed a single tenant with initial data\n *\n * Creates a database connection for the tenant, executes the seed function,\n * and properly cleans up the connection afterward.\n *\n * @param tenantId - The tenant identifier\n * @param seedFn - Function that seeds the database\n * @returns Result of the seeding operation\n *\n * @example\n * ```typescript\n * const result = await seeder.seedTenant('tenant-123', async (db, tenantId) => {\n * await db.insert(users).values([\n * { name: 'Admin', email: `admin@${tenantId}.com` },\n * ]);\n * });\n *\n * if (result.success) {\n * console.log(`Seeded ${result.tenantId} in ${result.durationMs}ms`);\n * }\n * ```\n */\n async seedTenant(\n tenantId: string,\n seedFn: SeedFunction<TTenantSchema>\n ): Promise<TenantSeedResult> {\n const startTime = Date.now();\n const schemaName = this.deps.schemaNameTemplate(tenantId);\n\n const pool = await this.deps.createPool(schemaName);\n\n try {\n const db = drizzle(pool, {\n schema: this.deps.tenantSchema as TTenantSchema,\n });\n\n await seedFn(db as any, tenantId);\n\n return {\n tenantId,\n schemaName,\n success: true,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n success: false,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Seed all tenants with initial data in parallel\n *\n * Discovers all tenants and seeds them in batches with configurable concurrency.\n * Supports progress callbacks and abort-on-error behavior.\n *\n * @param seedFn - Function that seeds each database\n * @param options - Seeding options\n * @returns Aggregate results of all seeding operations\n *\n * @example\n * ```typescript\n * const results = await seeder.seedAll(\n * async (db, tenantId) => {\n * await db.insert(settings).values({ key: 'initialized', value: 'true' });\n * },\n * {\n * concurrency: 5,\n * onProgress: (id, status) => console.log(`${id}: ${status}`),\n * }\n * );\n *\n * console.log(`Succeeded: ${results.succeeded}/${results.total}`);\n * ```\n */\n async seedAll(\n seedFn: SeedFunction<TTenantSchema>,\n options: SeedOptions = {}\n ): Promise<SeedResults> {\n const { concurrency = 10, onProgress, onError } = options;\n\n const tenantIds = await this.config.tenantDiscovery();\n const results: TenantSeedResult[] = [];\n let aborted = false;\n\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n onProgress?.(tenantId, 'seeding');\n const result = await this.seedTenant(tenantId, seedFn);\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n // Mark remaining tenants as skipped if aborted\n if (aborted) {\n const remaining = tenantIds.slice(results.length);\n for (const tenantId of remaining) {\n results.push(this.createSkippedResult(tenantId));\n }\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Seed specific tenants with initial data\n *\n * Seeds only the specified tenants in batches with configurable concurrency.\n *\n * @param tenantIds - List of tenant IDs to seed\n * @param seedFn - Function that seeds each database\n * @param options - Seeding options\n * @returns Aggregate results of seeding operations\n *\n * @example\n * ```typescript\n * const results = await seeder.seedTenants(\n * ['tenant-1', 'tenant-2', 'tenant-3'],\n * async (db) => {\n * await db.insert(config).values({ setup: true });\n * },\n * { concurrency: 2 }\n * );\n * ```\n */\n async seedTenants(\n tenantIds: string[],\n seedFn: SeedFunction<TTenantSchema>,\n options: SeedOptions = {}\n ): Promise<SeedResults> {\n const { concurrency = 10, onProgress, onError } = options;\n\n const results: TenantSeedResult[] = [];\n\n for (let i = 0; i < tenantIds.length; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n try {\n onProgress?.(tenantId, 'starting');\n onProgress?.(tenantId, 'seeding');\n const result = await this.seedTenant(tenantId, seedFn);\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n onError?.(tenantId, error as Error);\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Create a skipped result for aborted seeding\n */\n private createSkippedResult(tenantId: string): TenantSeedResult {\n return {\n tenantId,\n schemaName: this.deps.schemaNameTemplate(tenantId),\n success: false,\n error: 'Skipped due to abort',\n durationMs: 0,\n };\n }\n\n /**\n * Create an error result for failed seeding\n */\n private createErrorResult(tenantId: string, error: Error): TenantSeedResult {\n return {\n tenantId,\n schemaName: this.deps.schemaNameTemplate(tenantId),\n success: false,\n error: error.message,\n durationMs: 0,\n };\n }\n\n /**\n * Aggregate individual results into a summary\n */\n private aggregateResults(results: TenantSeedResult[]): SeedResults {\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter(\n (r) => !r.success && r.error !== 'Skipped due to abort'\n ).length,\n skipped: results.filter((r) => r.error === 'Skipped due to abort').length,\n details: results,\n };\n }\n}\n\n/**\n * Factory function to create a Seeder instance\n *\n * @param config - Seeder configuration\n * @param dependencies - Required dependencies\n * @returns A configured Seeder instance\n *\n * @example\n * ```typescript\n * const seeder = createSeeder(\n * { tenantDiscovery: async () => ['t1', 't2'] },\n * {\n * createPool: schemaManager.createPool.bind(schemaManager),\n * schemaNameTemplate: (id) => `tenant_${id}`,\n * tenantSchema: schema,\n * }\n * );\n * ```\n */\nexport function createSeeder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n>(\n config: SeederConfig,\n dependencies: SeederDependencies<TTenantSchema>\n): Seeder<TTenantSchema> {\n return new Seeder(config, dependencies);\n}\n","import type { Pool } from 'pg';\nimport type {\n MigrationFile,\n TenantSyncStatus,\n SyncStatus,\n TenantSyncResult,\n SyncResults,\n SyncOptions,\n} from '../types.js';\nimport type { ISyncManager } from '../interfaces.js';\nimport type { SyncManagerConfig, SyncManagerDependencies, AppliedMigrationRecord } from './types.js';\nimport type { DetectedFormat } from '../table-format.js';\n\n/**\n * Responsible for synchronizing migration state between disk and database.\n *\n * Extracted from Migrator to follow Single Responsibility Principle.\n * Handles detection of divergences and reconciliation operations.\n *\n * @example\n * ```typescript\n * const syncManager = new SyncManager(config, dependencies);\n *\n * // Check sync status\n * const status = await syncManager.getSyncStatus();\n * if (status.outOfSync > 0) {\n * console.log(`${status.outOfSync} tenants out of sync`);\n * }\n *\n * // Mark missing migrations as applied\n * await syncManager.markAllMissing({ concurrency: 10 });\n *\n * // Clean orphan records\n * await syncManager.cleanAllOrphans({ concurrency: 10 });\n * ```\n */\nexport class SyncManager implements ISyncManager {\n constructor(\n private readonly config: SyncManagerConfig,\n private readonly deps: SyncManagerDependencies\n ) {}\n\n /**\n * Get sync status for all tenants\n *\n * Detects divergences between migrations on disk and tracking in database.\n * A tenant is \"in sync\" when all disk migrations are tracked and no orphan records exist.\n *\n * @returns Aggregate sync status for all tenants\n *\n * @example\n * ```typescript\n * const status = await syncManager.getSyncStatus();\n * console.log(`Total: ${status.total}, In sync: ${status.inSync}, Out of sync: ${status.outOfSync}`);\n *\n * for (const tenant of status.details.filter(d => !d.inSync)) {\n * console.log(`${tenant.tenantId}: missing=${tenant.missing.length}, orphans=${tenant.orphans.length}`);\n * }\n * ```\n */\n async getSyncStatus(): Promise<SyncStatus> {\n const tenantIds = await this.config.tenantDiscovery();\n const migrations = await this.deps.loadMigrations();\n const statuses: TenantSyncStatus[] = [];\n\n for (const tenantId of tenantIds) {\n statuses.push(await this.getTenantSyncStatus(tenantId, migrations));\n }\n\n return {\n total: statuses.length,\n inSync: statuses.filter((s) => s.inSync && !s.error).length,\n outOfSync: statuses.filter((s) => !s.inSync && !s.error).length,\n error: statuses.filter((s) => !!s.error).length,\n details: statuses,\n };\n }\n\n /**\n * Get sync status for a specific tenant\n *\n * Compares migrations on disk with records in the database.\n * Identifies missing migrations (on disk but not tracked) and\n * orphan records (tracked but not on disk).\n *\n * @param tenantId - The tenant identifier\n * @param migrations - Optional pre-loaded migrations (avoids reloading from disk)\n * @returns Sync status for the tenant\n *\n * @example\n * ```typescript\n * const status = await syncManager.getTenantSyncStatus('tenant-123');\n * if (status.missing.length > 0) {\n * console.log(`Missing: ${status.missing.join(', ')}`);\n * }\n * if (status.orphans.length > 0) {\n * console.log(`Orphans: ${status.orphans.join(', ')}`);\n * }\n * ```\n */\n async getTenantSyncStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantSyncStatus> {\n const schemaName = this.deps.schemaNameTemplate(tenantId);\n const pool = await this.deps.createPool(schemaName);\n\n try {\n const allMigrations = migrations ?? await this.deps.loadMigrations();\n const migrationNames = new Set(allMigrations.map((m) => m.name));\n const migrationHashes = new Set(allMigrations.map((m) => m.hash));\n\n // Check if migrations table exists\n const tableExists = await this.deps.migrationsTableExists(pool, schemaName);\n if (!tableExists) {\n return {\n tenantId,\n schemaName,\n missing: allMigrations.map((m) => m.name),\n orphans: [],\n inSync: allMigrations.length === 0,\n format: null,\n };\n }\n\n // Detect the table format\n const format = await this.deps.getOrDetectFormat(pool, schemaName);\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n\n // Find missing migrations (in disk but not in database)\n const appliedIdentifiers = new Set(applied.map((m) => m.identifier));\n const missing = allMigrations\n .filter((m) => !this.isMigrationApplied(m, appliedIdentifiers, format))\n .map((m) => m.name);\n\n // Find orphan records (in database but not in disk)\n const orphans = applied\n .filter((m) => {\n if (format.columns.identifier === 'name') {\n return !migrationNames.has(m.identifier);\n }\n // For hash-based formats, check both hash and name\n return !migrationHashes.has(m.identifier) && !migrationNames.has(m.identifier);\n })\n .map((m) => m.identifier);\n\n return {\n tenantId,\n schemaName,\n missing,\n orphans,\n inSync: missing.length === 0 && orphans.length === 0,\n format: format.format,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n missing: [],\n orphans: [],\n inSync: false,\n format: null,\n error: (error as Error).message,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Mark missing migrations as applied for a tenant\n *\n * Records migrations that exist on disk but are not tracked in the database.\n * Useful for syncing tracking state with already-applied migrations.\n *\n * @param tenantId - The tenant identifier\n * @returns Result of the mark operation\n *\n * @example\n * ```typescript\n * const result = await syncManager.markMissing('tenant-123');\n * if (result.success) {\n * console.log(`Marked ${result.markedMigrations.length} migrations as applied`);\n * }\n * ```\n */\n async markMissing(tenantId: string): Promise<TenantSyncResult> {\n const startTime = Date.now();\n const schemaName = this.deps.schemaNameTemplate(tenantId);\n const markedMigrations: string[] = [];\n\n const pool = await this.deps.createPool(schemaName);\n\n try {\n const syncStatus = await this.getTenantSyncStatus(tenantId);\n\n if (syncStatus.error) {\n return {\n tenantId,\n schemaName,\n success: false,\n markedMigrations: [],\n removedOrphans: [],\n error: syncStatus.error,\n durationMs: Date.now() - startTime,\n };\n }\n\n if (syncStatus.missing.length === 0) {\n return {\n tenantId,\n schemaName,\n success: true,\n markedMigrations: [],\n removedOrphans: [],\n durationMs: Date.now() - startTime,\n };\n }\n\n const format = await this.deps.getOrDetectFormat(pool, schemaName);\n await this.deps.ensureMigrationsTable(pool, schemaName, format);\n\n const allMigrations = await this.deps.loadMigrations();\n const missingSet = new Set(syncStatus.missing);\n\n for (const migration of allMigrations) {\n if (missingSet.has(migration.name)) {\n await this.recordMigration(pool, schemaName, migration, format);\n markedMigrations.push(migration.name);\n }\n }\n\n return {\n tenantId,\n schemaName,\n success: true,\n markedMigrations,\n removedOrphans: [],\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n success: false,\n markedMigrations,\n removedOrphans: [],\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Mark missing migrations as applied for all tenants\n *\n * Processes all tenants in parallel with configurable concurrency.\n * Supports progress callbacks and abort-on-error behavior.\n *\n * @param options - Sync options\n * @returns Aggregate results of all mark operations\n *\n * @example\n * ```typescript\n * const results = await syncManager.markAllMissing({\n * concurrency: 10,\n * onProgress: (id, status) => console.log(`${id}: ${status}`),\n * });\n * console.log(`Succeeded: ${results.succeeded}/${results.total}`);\n * ```\n */\n async markAllMissing(options: SyncOptions = {}): Promise<SyncResults> {\n const { concurrency = 10, onProgress, onError } = options;\n\n const tenantIds = await this.config.tenantDiscovery();\n const results: TenantSyncResult[] = [];\n let aborted = false;\n\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedSyncResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.markMissing(tenantId);\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorSyncResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateSyncResults(results);\n }\n\n /**\n * Remove orphan migration records for a tenant\n *\n * Deletes records from the migrations table that don't have\n * corresponding files on disk.\n *\n * @param tenantId - The tenant identifier\n * @returns Result of the clean operation\n *\n * @example\n * ```typescript\n * const result = await syncManager.cleanOrphans('tenant-123');\n * if (result.success) {\n * console.log(`Removed ${result.removedOrphans.length} orphan records`);\n * }\n * ```\n */\n async cleanOrphans(tenantId: string): Promise<TenantSyncResult> {\n const startTime = Date.now();\n const schemaName = this.deps.schemaNameTemplate(tenantId);\n const removedOrphans: string[] = [];\n\n const pool = await this.deps.createPool(schemaName);\n\n try {\n const syncStatus = await this.getTenantSyncStatus(tenantId);\n\n if (syncStatus.error) {\n return {\n tenantId,\n schemaName,\n success: false,\n markedMigrations: [],\n removedOrphans: [],\n error: syncStatus.error,\n durationMs: Date.now() - startTime,\n };\n }\n\n if (syncStatus.orphans.length === 0) {\n return {\n tenantId,\n schemaName,\n success: true,\n markedMigrations: [],\n removedOrphans: [],\n durationMs: Date.now() - startTime,\n };\n }\n\n const format = await this.deps.getOrDetectFormat(pool, schemaName);\n const identifierColumn = format.columns.identifier;\n\n for (const orphan of syncStatus.orphans) {\n await pool.query(\n `DELETE FROM \"${schemaName}\".\"${format.tableName}\" WHERE \"${identifierColumn}\" = $1`,\n [orphan]\n );\n removedOrphans.push(orphan);\n }\n\n return {\n tenantId,\n schemaName,\n success: true,\n markedMigrations: [],\n removedOrphans,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n success: false,\n markedMigrations: [],\n removedOrphans,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Remove orphan migration records for all tenants\n *\n * Processes all tenants in parallel with configurable concurrency.\n * Supports progress callbacks and abort-on-error behavior.\n *\n * @param options - Sync options\n * @returns Aggregate results of all clean operations\n *\n * @example\n * ```typescript\n * const results = await syncManager.cleanAllOrphans({\n * concurrency: 10,\n * onProgress: (id, status) => console.log(`${id}: ${status}`),\n * });\n * console.log(`Succeeded: ${results.succeeded}/${results.total}`);\n * ```\n */\n async cleanAllOrphans(options: SyncOptions = {}): Promise<SyncResults> {\n const { concurrency = 10, onProgress, onError } = options;\n\n const tenantIds = await this.config.tenantDiscovery();\n const results: TenantSyncResult[] = [];\n let aborted = false;\n\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedSyncResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.cleanOrphans(tenantId);\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorSyncResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateSyncResults(results);\n }\n\n // ============================================================================\n // Private Helper Methods\n // ============================================================================\n\n /**\n * Get applied migrations for a schema\n */\n private async getAppliedMigrations(\n pool: Pool,\n schemaName: string,\n format: DetectedFormat\n ): Promise<Array<{ identifier: string; appliedAt: Date }>> {\n const identifierColumn = format.columns.identifier;\n const timestampColumn = format.columns.timestamp;\n\n const result = await pool.query<AppliedMigrationRecord>(\n `SELECT id, \"${identifierColumn}\" as identifier, \"${timestampColumn}\" as applied_at\n FROM \"${schemaName}\".\"${format.tableName}\"\n ORDER BY id`\n );\n\n return result.rows.map((row) => {\n const appliedAt = format.columns.timestampType === 'bigint'\n ? new Date(Number(row.applied_at))\n : new Date(row.applied_at);\n\n return {\n identifier: row.identifier,\n appliedAt,\n };\n });\n }\n\n /**\n * Check if a migration has been applied\n */\n private isMigrationApplied(\n migration: MigrationFile,\n appliedIdentifiers: Set<string>,\n format: DetectedFormat\n ): boolean {\n if (format.columns.identifier === 'name') {\n return appliedIdentifiers.has(migration.name);\n }\n\n // Hash-based: check both hash AND name for backwards compatibility\n return appliedIdentifiers.has(migration.hash) || appliedIdentifiers.has(migration.name);\n }\n\n /**\n * Record a migration as applied (without executing SQL)\n */\n private async recordMigration(\n pool: Pool,\n schemaName: string,\n migration: MigrationFile,\n format: DetectedFormat\n ): Promise<void> {\n const { identifier, timestamp, timestampType } = format.columns;\n const identifierValue = identifier === 'name' ? migration.name : migration.hash;\n const timestampValue = timestampType === 'bigint' ? Date.now() : new Date();\n\n await pool.query(\n `INSERT INTO \"${schemaName}\".\"${format.tableName}\" (\"${identifier}\", \"${timestamp}\") VALUES ($1, $2)`,\n [identifierValue, timestampValue]\n );\n }\n\n /**\n * Create a skipped sync result for aborted operations\n */\n private createSkippedSyncResult(tenantId: string): TenantSyncResult {\n return {\n tenantId,\n schemaName: this.deps.schemaNameTemplate(tenantId),\n success: false,\n markedMigrations: [],\n removedOrphans: [],\n error: 'Skipped due to abort',\n durationMs: 0,\n };\n }\n\n /**\n * Create an error sync result for failed operations\n */\n private createErrorSyncResult(tenantId: string, error: Error): TenantSyncResult {\n return {\n tenantId,\n schemaName: this.deps.schemaNameTemplate(tenantId),\n success: false,\n markedMigrations: [],\n removedOrphans: [],\n error: error.message,\n durationMs: 0,\n };\n }\n\n /**\n * Aggregate individual sync results into a summary\n */\n private aggregateSyncResults(results: TenantSyncResult[]): SyncResults {\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success).length,\n details: results,\n };\n }\n}\n\n/**\n * Factory function to create a SyncManager instance\n *\n * @param config - SyncManager configuration\n * @param dependencies - Required dependencies\n * @returns A configured SyncManager instance\n *\n * @example\n * ```typescript\n * const syncManager = createSyncManager(\n * {\n * tenantDiscovery: async () => ['t1', 't2'],\n * migrationsFolder: './migrations',\n * migrationsTable: '__drizzle_migrations',\n * },\n * {\n * createPool: schemaManager.createPool.bind(schemaManager),\n * schemaNameTemplate: (id) => `tenant_${id}`,\n * migrationsTableExists: schemaManager.migrationsTableExists.bind(schemaManager),\n * ensureMigrationsTable: schemaManager.ensureMigrationsTable.bind(schemaManager),\n * getOrDetectFormat: migrator.getOrDetectFormat.bind(migrator),\n * loadMigrations: migrator.loadMigrations.bind(migrator),\n * }\n * );\n * ```\n */\nexport function createSyncManager(\n config: SyncManagerConfig,\n dependencies: SyncManagerDependencies\n): SyncManager {\n return new SyncManager(config, dependencies);\n}\n","import type { Pool } from 'pg';\nimport type {\n MigrationFile,\n TenantMigrationResult,\n TenantMigrationStatus,\n} from '../types.js';\nimport type { IMigrationExecutor } from '../interfaces.js';\nimport type {\n MigrationExecutorConfig,\n MigrationExecutorDependencies,\n MigrateTenantOptions,\n AppliedMigration,\n AppliedMigrationRecord,\n} from './types.js';\nimport type { DetectedFormat } from '../table-format.js';\n\n/**\n * Responsible for executing migrations on individual tenants.\n *\n * Extracted from Migrator to follow Single Responsibility Principle.\n * Handles single-tenant migration operations including:\n * - Executing migrations with SQL\n * - Marking migrations as applied (without SQL)\n * - Checking migration status\n * - Getting applied/pending migrations\n *\n * @example\n * ```typescript\n * const executor = new MigrationExecutor(config, dependencies);\n *\n * // Migrate a single tenant\n * const result = await executor.migrateTenant('tenant-123');\n *\n * // Mark migrations as applied without executing SQL\n * const markResult = await executor.markAsApplied('tenant-123');\n *\n * // Get tenant status\n * const status = await executor.getTenantStatus('tenant-123');\n * ```\n */\nexport class MigrationExecutor implements IMigrationExecutor {\n constructor(\n private readonly config: MigrationExecutorConfig,\n private readonly deps: MigrationExecutorDependencies\n ) {}\n\n /**\n * Migrate a single tenant\n *\n * Applies all pending migrations to the tenant's schema.\n * Creates the migrations table if it doesn't exist.\n *\n * @param tenantId - The tenant identifier\n * @param migrations - Optional pre-loaded migrations (avoids reloading from disk)\n * @param options - Migration options (dryRun, onProgress)\n * @returns Migration result with applied migrations and duration\n *\n * @example\n * ```typescript\n * const result = await executor.migrateTenant('tenant-123', undefined, {\n * dryRun: false,\n * onProgress: (id, status, name) => console.log(`${id}: ${status} ${name}`),\n * });\n *\n * if (result.success) {\n * console.log(`Applied ${result.appliedMigrations.length} migrations`);\n * }\n * ```\n */\n async migrateTenant(\n tenantId: string,\n migrations?: MigrationFile[],\n options: MigrateTenantOptions = {}\n ): Promise<TenantMigrationResult> {\n const startTime = Date.now();\n const schemaName = this.deps.schemaNameTemplate(tenantId);\n const appliedMigrations: string[] = [];\n\n const pool = await this.deps.createPool(schemaName);\n\n try {\n await this.config.hooks?.beforeTenant?.(tenantId);\n\n // Detect or determine the format before creating table\n const format = await this.deps.getOrDetectFormat(pool, schemaName);\n\n // Ensure migrations table exists with correct format\n await this.deps.ensureMigrationsTable(pool, schemaName, format);\n\n // Load migrations if not provided\n const allMigrations = migrations ?? await this.deps.loadMigrations();\n\n // Get applied migrations using format-aware query\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n // Filter pending migrations using format-aware comparison\n const pending = allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n\n if (options.dryRun) {\n return {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations: pending.map((m) => m.name),\n durationMs: Date.now() - startTime,\n format: format.format,\n };\n }\n\n // Apply pending migrations\n for (const migration of pending) {\n const migrationStart = Date.now();\n options.onProgress?.(tenantId, 'migrating', migration.name);\n\n await this.config.hooks?.beforeMigration?.(tenantId, migration.name);\n await this.applyMigration(pool, schemaName, migration, format);\n await this.config.hooks?.afterMigration?.(\n tenantId,\n migration.name,\n Date.now() - migrationStart\n );\n\n appliedMigrations.push(migration.name);\n }\n\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations,\n durationMs: Date.now() - startTime,\n format: format.format,\n };\n\n await this.config.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } catch (error) {\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: false,\n appliedMigrations,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n\n await this.config.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Mark migrations as applied without executing SQL\n *\n * Useful for syncing tracking state with already-applied migrations\n * or when migrations were applied manually.\n *\n * @param tenantId - The tenant identifier\n * @param options - Options with progress callback\n * @returns Result with list of marked migrations\n *\n * @example\n * ```typescript\n * const result = await executor.markAsApplied('tenant-123', {\n * onProgress: (id, status, name) => console.log(`${id}: marking ${name}`),\n * });\n *\n * console.log(`Marked ${result.appliedMigrations.length} migrations`);\n * ```\n */\n async markAsApplied(\n tenantId: string,\n options: { onProgress?: MigrateTenantOptions['onProgress'] } = {}\n ): Promise<TenantMigrationResult> {\n const startTime = Date.now();\n const schemaName = this.deps.schemaNameTemplate(tenantId);\n const markedMigrations: string[] = [];\n\n const pool = await this.deps.createPool(schemaName);\n\n try {\n await this.config.hooks?.beforeTenant?.(tenantId);\n\n // Detect or determine the format before creating table\n const format = await this.deps.getOrDetectFormat(pool, schemaName);\n\n // Ensure migrations table exists with correct format\n await this.deps.ensureMigrationsTable(pool, schemaName, format);\n\n // Load all migrations\n const allMigrations = await this.deps.loadMigrations();\n\n // Get applied migrations\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n // Filter pending migrations\n const pending = allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n\n // Mark each pending migration as applied (without executing SQL)\n for (const migration of pending) {\n const migrationStart = Date.now();\n options.onProgress?.(tenantId, 'migrating', migration.name);\n\n await this.config.hooks?.beforeMigration?.(tenantId, migration.name);\n await this.recordMigration(pool, schemaName, migration, format);\n await this.config.hooks?.afterMigration?.(\n tenantId,\n migration.name,\n Date.now() - migrationStart\n );\n\n markedMigrations.push(migration.name);\n }\n\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations: markedMigrations,\n durationMs: Date.now() - startTime,\n format: format.format,\n };\n\n await this.config.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } catch (error) {\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: false,\n appliedMigrations: markedMigrations,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n\n await this.config.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Get migration status for a specific tenant\n *\n * Returns information about applied and pending migrations.\n *\n * @param tenantId - The tenant identifier\n * @param migrations - Optional pre-loaded migrations\n * @returns Migration status with counts and pending list\n *\n * @example\n * ```typescript\n * const status = await executor.getTenantStatus('tenant-123');\n * if (status.status === 'behind') {\n * console.log(`Pending: ${status.pendingMigrations.join(', ')}`);\n * }\n * ```\n */\n async getTenantStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantMigrationStatus> {\n const schemaName = this.deps.schemaNameTemplate(tenantId);\n const pool = await this.deps.createPool(schemaName);\n\n try {\n const allMigrations = migrations ?? await this.deps.loadMigrations();\n\n // Check if migrations table exists\n const tableExists = await this.deps.migrationsTableExists(pool, schemaName);\n if (!tableExists) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: allMigrations.length,\n pendingMigrations: allMigrations.map((m) => m.name),\n status: allMigrations.length > 0 ? 'behind' : 'ok',\n format: null,\n };\n }\n\n // Detect the table format\n const format = await this.deps.getOrDetectFormat(pool, schemaName);\n\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n // Use format-aware comparison\n const pending = allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n\n return {\n tenantId,\n schemaName,\n appliedCount: applied.length,\n pendingCount: pending.length,\n pendingMigrations: pending.map((m) => m.name),\n status: pending.length > 0 ? 'behind' : 'ok',\n format: format.format,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: 0,\n pendingMigrations: [],\n status: 'error',\n error: (error as Error).message,\n format: null,\n };\n } finally {\n await pool.end();\n }\n }\n\n // ============================================================================\n // IMigrationExecutor Interface Methods\n // ============================================================================\n\n /**\n * Execute a single migration on a schema\n */\n async executeMigration(\n pool: Pool,\n schemaName: string,\n migration: MigrationFile,\n format: DetectedFormat,\n options?: { markOnly?: boolean; onProgress?: (status: 'applying' | 'recording') => void }\n ): Promise<void> {\n if (options?.markOnly) {\n options.onProgress?.('recording');\n await this.recordMigration(pool, schemaName, migration, format);\n } else {\n options?.onProgress?.('applying');\n await this.applyMigration(pool, schemaName, migration, format);\n }\n }\n\n /**\n * Execute multiple migrations on a schema\n */\n async executeMigrations(\n pool: Pool,\n schemaName: string,\n migrations: MigrationFile[],\n format: DetectedFormat,\n options?: { markOnly?: boolean; onProgress?: (status: 'applying' | 'recording') => void }\n ): Promise<string[]> {\n const appliedNames: string[] = [];\n\n for (const migration of migrations) {\n await this.executeMigration(pool, schemaName, migration, format, options);\n appliedNames.push(migration.name);\n }\n\n return appliedNames;\n }\n\n /**\n * Record a migration as applied without executing SQL\n */\n async recordMigration(\n pool: Pool,\n schemaName: string,\n migration: MigrationFile,\n format: DetectedFormat\n ): Promise<void> {\n const { identifier, timestamp, timestampType } = format.columns;\n const identifierValue = identifier === 'name' ? migration.name : migration.hash;\n const timestampValue = timestampType === 'bigint' ? Date.now() : new Date();\n\n await pool.query(\n `INSERT INTO \"${schemaName}\".\"${format.tableName}\" (\"${identifier}\", \"${timestamp}\") VALUES ($1, $2)`,\n [identifierValue, timestampValue]\n );\n }\n\n /**\n * Get list of applied migrations for a tenant\n */\n async getAppliedMigrations(\n pool: Pool,\n schemaName: string,\n format: DetectedFormat\n ): Promise<AppliedMigration[]> {\n const identifierColumn = format.columns.identifier;\n const timestampColumn = format.columns.timestamp;\n\n const result = await pool.query<AppliedMigrationRecord>(\n `SELECT id, \"${identifierColumn}\" as identifier, \"${timestampColumn}\" as applied_at\n FROM \"${schemaName}\".\"${format.tableName}\"\n ORDER BY id`\n );\n\n return result.rows.map((row) => {\n // Convert timestamp based on format\n const appliedAt = format.columns.timestampType === 'bigint'\n ? new Date(Number(row.applied_at))\n : new Date(row.applied_at);\n\n return {\n identifier: row.identifier,\n // Set name or hash based on format\n ...(format.columns.identifier === 'name'\n ? { name: row.identifier }\n : { hash: row.identifier }),\n appliedAt,\n };\n });\n }\n\n /**\n * Get pending migrations (not yet applied)\n */\n async getPendingMigrations(\n pool: Pool,\n schemaName: string,\n allMigrations: MigrationFile[],\n format: DetectedFormat\n ): Promise<MigrationFile[]> {\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n return allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n }\n\n // ============================================================================\n // Private Helper Methods\n // ============================================================================\n\n /**\n * Check if a migration has been applied\n */\n private isMigrationApplied(\n migration: MigrationFile,\n appliedIdentifiers: Set<string>,\n format: DetectedFormat\n ): boolean {\n if (format.columns.identifier === 'name') {\n return appliedIdentifiers.has(migration.name);\n }\n\n // Hash-based: check both hash AND name for backwards compatibility\n // This allows migration from name-based to hash-based tracking\n return appliedIdentifiers.has(migration.hash) || appliedIdentifiers.has(migration.name);\n }\n\n /**\n * Apply a migration to a schema (execute SQL + record)\n */\n private async applyMigration(\n pool: Pool,\n schemaName: string,\n migration: MigrationFile,\n format: DetectedFormat\n ): Promise<void> {\n const client = await pool.connect();\n\n try {\n await client.query('BEGIN');\n\n // Execute migration SQL\n await client.query(migration.sql);\n\n // Record migration using format-aware insert\n const { identifier, timestamp, timestampType } = format.columns;\n const identifierValue = identifier === 'name' ? migration.name : migration.hash;\n const timestampValue = timestampType === 'bigint' ? Date.now() : new Date();\n\n await client.query(\n `INSERT INTO \"${schemaName}\".\"${format.tableName}\" (\"${identifier}\", \"${timestamp}\") VALUES ($1, $2)`,\n [identifierValue, timestampValue]\n );\n\n await client.query('COMMIT');\n } catch (error) {\n await client.query('ROLLBACK');\n throw error;\n } finally {\n client.release();\n }\n }\n}\n\n/**\n * Factory function to create a MigrationExecutor instance\n *\n * @param config - Executor configuration (hooks)\n * @param dependencies - Required dependencies\n * @returns A configured MigrationExecutor instance\n *\n * @example\n * ```typescript\n * const executor = createMigrationExecutor(\n * { hooks: { beforeTenant: async (id) => console.log(`Starting ${id}`) } },\n * {\n * createPool: schemaManager.createPool.bind(schemaManager),\n * schemaNameTemplate: (id) => `tenant_${id}`,\n * migrationsTableExists: schemaManager.migrationsTableExists.bind(schemaManager),\n * ensureMigrationsTable: schemaManager.ensureMigrationsTable.bind(schemaManager),\n * getOrDetectFormat: async (pool, schema) => getFormatConfig('name', table),\n * loadMigrations: async () => loadMigrationsFromDisk(),\n * }\n * );\n * ```\n */\nexport function createMigrationExecutor(\n config: MigrationExecutorConfig,\n dependencies: MigrationExecutorDependencies\n): MigrationExecutor {\n return new MigrationExecutor(config, dependencies);\n}\n","import type {\n MigrationFile,\n TenantMigrationResult,\n MigrationResults,\n TenantMigrationStatus,\n} from '../types.js';\nimport type { IBatchExecutor } from '../interfaces.js';\nimport type { MigrationExecutor } from './migration-executor.js';\nimport type { BatchExecutorConfig, BatchMigrateOptions } from './types.js';\n\n/**\n * Responsible for batch migration operations across multiple tenants.\n *\n * Extracted from Migrator to follow Single Responsibility Principle.\n * Handles parallel migration operations including:\n * - Migrating all tenants with configurable concurrency\n * - Migrating specific tenants\n * - Marking all migrations as applied\n * - Progress tracking and error handling\n *\n * @example\n * ```typescript\n * const batchExecutor = new BatchExecutor(config, migrationExecutor, loadMigrations);\n *\n * // Migrate all tenants with concurrency 10\n * const results = await batchExecutor.migrateAll({ concurrency: 10 });\n *\n * // Migrate specific tenants\n * const specificResults = await batchExecutor.migrateTenants(['t1', 't2'], {\n * onProgress: (id, status) => console.log(`${id}: ${status}`),\n * });\n * ```\n */\nexport class BatchExecutor implements IBatchExecutor {\n constructor(\n private readonly config: BatchExecutorConfig,\n private readonly executor: MigrationExecutor,\n private readonly loadMigrations: () => Promise<MigrationFile[]>\n ) {}\n\n /**\n * Migrate all tenants in parallel\n *\n * Processes tenants in batches with configurable concurrency.\n * Supports progress callbacks, error handling, and abort behavior.\n *\n * @param options - Migration options (concurrency, dryRun, callbacks)\n * @returns Aggregate results for all tenants\n *\n * @example\n * ```typescript\n * const results = await batchExecutor.migrateAll({\n * concurrency: 10,\n * dryRun: false,\n * onProgress: (id, status) => console.log(`${id}: ${status}`),\n * onError: (id, error) => {\n * console.error(`${id} failed: ${error.message}`);\n * return 'continue'; // or 'abort' to stop all\n * },\n * });\n *\n * console.log(`Succeeded: ${results.succeeded}/${results.total}`);\n * ```\n */\n async migrateAll(options: BatchMigrateOptions = {}): Promise<MigrationResults> {\n const {\n concurrency = 10,\n onProgress,\n onError,\n dryRun = false,\n } = options;\n\n const tenantIds = await this.config.tenantDiscovery();\n const migrations = await this.loadMigrations();\n\n const results: TenantMigrationResult[] = [];\n let aborted = false;\n\n // Process tenants in batches\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.executor.migrateTenant(tenantId, migrations, { dryRun, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n // Mark remaining tenants as skipped if aborted\n if (aborted) {\n const remaining = tenantIds.slice(results.length);\n for (const tenantId of remaining) {\n results.push(this.createSkippedResult(tenantId));\n }\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Migrate specific tenants in parallel\n *\n * Same as migrateAll but for a subset of tenants.\n *\n * @param tenantIds - List of tenant IDs to migrate\n * @param options - Migration options\n * @returns Aggregate results for specified tenants\n *\n * @example\n * ```typescript\n * const results = await batchExecutor.migrateTenants(\n * ['tenant-1', 'tenant-2', 'tenant-3'],\n * { concurrency: 5 }\n * );\n * ```\n */\n async migrateTenants(tenantIds: string[], options: BatchMigrateOptions = {}): Promise<MigrationResults> {\n const migrations = await this.loadMigrations();\n const results: TenantMigrationResult[] = [];\n\n const { concurrency = 10, onProgress, onError, dryRun = false } = options;\n\n for (let i = 0; i < tenantIds.length; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.executor.migrateTenant(tenantId, migrations, { dryRun, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n onError?.(tenantId, error as Error);\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Mark all tenants as applied without executing SQL\n *\n * Useful for syncing tracking state with already-applied migrations.\n * Processes tenants in parallel with configurable concurrency.\n *\n * @param options - Migration options\n * @returns Aggregate results for all tenants\n *\n * @example\n * ```typescript\n * const results = await batchExecutor.markAllAsApplied({\n * concurrency: 10,\n * onProgress: (id, status) => console.log(`${id}: ${status}`),\n * });\n * ```\n */\n async markAllAsApplied(options: BatchMigrateOptions = {}): Promise<MigrationResults> {\n const {\n concurrency = 10,\n onProgress,\n onError,\n } = options;\n\n const tenantIds = await this.config.tenantDiscovery();\n const results: TenantMigrationResult[] = [];\n let aborted = false;\n\n // Process tenants in batches\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.executor.markAsApplied(tenantId, { onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n // Mark remaining tenants as skipped if aborted\n if (aborted) {\n const remaining = tenantIds.slice(results.length);\n for (const tenantId of remaining) {\n results.push(this.createSkippedResult(tenantId));\n }\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Get migration status for all tenants\n *\n * Queries each tenant's migration status sequentially.\n *\n * @returns List of migration status for all tenants\n *\n * @example\n * ```typescript\n * const statuses = await batchExecutor.getStatus();\n * const behind = statuses.filter(s => s.status === 'behind');\n * console.log(`${behind.length} tenants need migrations`);\n * ```\n */\n async getStatus(): Promise<TenantMigrationStatus[]> {\n const tenantIds = await this.config.tenantDiscovery();\n const migrations = await this.loadMigrations();\n const statuses: TenantMigrationStatus[] = [];\n\n for (const tenantId of tenantIds) {\n statuses.push(await this.executor.getTenantStatus(tenantId, migrations));\n }\n\n return statuses;\n }\n\n // ============================================================================\n // Private Helper Methods\n // ============================================================================\n\n /**\n * Create a skipped result for aborted operations\n */\n private createSkippedResult(tenantId: string): TenantMigrationResult {\n return {\n tenantId,\n schemaName: '', // Schema name not available in batch context\n success: false,\n appliedMigrations: [],\n error: 'Skipped due to abort',\n durationMs: 0,\n };\n }\n\n /**\n * Create an error result for failed operations\n */\n private createErrorResult(tenantId: string, error: Error): TenantMigrationResult {\n return {\n tenantId,\n schemaName: '', // Schema name not available in batch context\n success: false,\n appliedMigrations: [],\n error: error.message,\n durationMs: 0,\n };\n }\n\n /**\n * Aggregate individual migration results into a summary\n */\n private aggregateResults(results: TenantMigrationResult[]): MigrationResults {\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success && r.error !== 'Skipped due to abort').length,\n skipped: results.filter((r) => r.error === 'Skipped due to abort').length,\n details: results,\n };\n }\n}\n\n/**\n * Factory function to create a BatchExecutor instance\n *\n * @param config - Batch configuration (tenantDiscovery)\n * @param executor - MigrationExecutor instance\n * @param loadMigrations - Function to load migrations from disk\n * @returns A configured BatchExecutor instance\n *\n * @example\n * ```typescript\n * const batchExecutor = createBatchExecutor(\n * { tenantDiscovery: async () => ['t1', 't2', 't3'] },\n * migrationExecutor,\n * async () => loadMigrationsFromDisk('./migrations')\n * );\n * ```\n */\nexport function createBatchExecutor(\n config: BatchExecutorConfig,\n executor: MigrationExecutor,\n loadMigrations: () => Promise<MigrationFile[]>\n): BatchExecutor {\n return new BatchExecutor(config, executor, loadMigrations);\n}\n","/**\n * DDL Generator\n *\n * Generates DDL (CREATE TABLE, indexes, constraints) from introspection.\n * Uses information_schema and pg_catalog to reconstruct structure.\n *\n * @module clone/ddl-generator\n */\n\nimport type { Pool } from 'pg';\nimport type { TableCloneInfo, ColumnInfo } from './types.js';\n\n/**\n * List all tables in a schema\n */\nexport async function listTables(\n pool: Pool,\n schemaName: string,\n excludeTables: string[] = []\n): Promise<string[]> {\n // Build placeholders for excluded tables\n const excludePlaceholders =\n excludeTables.length > 0\n ? excludeTables.map((_, i) => `$${i + 2}`).join(', ')\n : \"''::text\";\n\n const result = await pool.query<{ table_name: string }>(\n `SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = $1\n AND table_type = 'BASE TABLE'\n AND table_name NOT IN (${excludePlaceholders})\n ORDER BY table_name`,\n [schemaName, ...excludeTables]\n );\n return result.rows.map((r) => r.table_name);\n}\n\n/**\n * Get column information for a table\n */\nexport async function getColumns(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<ColumnInfo[]> {\n const result = await pool.query<{\n column_name: string;\n data_type: string;\n udt_name: string;\n is_nullable: string;\n column_default: string | null;\n character_maximum_length: number | null;\n numeric_precision: number | null;\n numeric_scale: number | null;\n }>(\n `SELECT\n column_name,\n data_type,\n udt_name,\n is_nullable,\n column_default,\n character_maximum_length,\n numeric_precision,\n numeric_scale\n FROM information_schema.columns\n WHERE table_schema = $1 AND table_name = $2\n ORDER BY ordinal_position`,\n [schemaName, tableName]\n );\n\n return result.rows.map((row) => ({\n columnName: row.column_name,\n dataType: row.data_type,\n udtName: row.udt_name,\n isNullable: row.is_nullable === 'YES',\n columnDefault: row.column_default,\n characterMaximumLength: row.character_maximum_length,\n numericPrecision: row.numeric_precision,\n numericScale: row.numeric_scale,\n }));\n}\n\n/**\n * Generate CREATE TABLE DDL for a table\n */\nexport async function generateTableDdl(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<string> {\n const columns = await getColumns(pool, schemaName, tableName);\n\n const columnDefs = columns.map((col) => {\n let type = col.udtName;\n\n // Handle special types\n if (col.dataType === 'character varying' && col.characterMaximumLength) {\n type = `varchar(${col.characterMaximumLength})`;\n } else if (col.dataType === 'character' && col.characterMaximumLength) {\n type = `char(${col.characterMaximumLength})`;\n } else if (col.dataType === 'numeric' && col.numericPrecision) {\n type = `numeric(${col.numericPrecision}${col.numericScale ? `, ${col.numericScale}` : ''})`;\n } else if (col.dataType === 'ARRAY') {\n // Array types are stored as _typename in udt_name\n type = col.udtName.replace(/^_/, '') + '[]';\n }\n\n // Build column definition\n let definition = `\"${col.columnName}\" ${type}`;\n\n if (!col.isNullable) {\n definition += ' NOT NULL';\n }\n\n if (col.columnDefault) {\n // Replace old schema reference in default values\n const defaultValue = col.columnDefault.replace(\n new RegExp(`\"?${schemaName}\"?\\\\.`, 'g'),\n ''\n );\n definition += ` DEFAULT ${defaultValue}`;\n }\n\n return definition;\n });\n\n return `CREATE TABLE IF NOT EXISTS \"${tableName}\" (\\n ${columnDefs.join(',\\n ')}\\n)`;\n}\n\n/**\n * Generate index DDLs for a table\n */\nexport async function generateIndexDdls(\n pool: Pool,\n sourceSchema: string,\n targetSchema: string,\n tableName: string\n): Promise<string[]> {\n const result = await pool.query<{ indexdef: string; indexname: string }>(\n `SELECT indexname, indexdef\n FROM pg_indexes\n WHERE schemaname = $1 AND tablename = $2\n AND indexname NOT LIKE '%_pkey'`,\n [sourceSchema, tableName]\n );\n\n return result.rows.map((row) =>\n // Replace source schema with target schema\n row.indexdef\n .replace(new RegExp(`ON \"${sourceSchema}\"\\\\.\"`, 'g'), `ON \"${targetSchema}\".\"`)\n .replace(new RegExp(`\"${sourceSchema}\"\\\\.\"`, 'g'), `\"${targetSchema}\".\"`),\n );\n}\n\n/**\n * Generate primary key DDL for a table\n */\nexport async function generatePrimaryKeyDdl(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<string | null> {\n const result = await pool.query<{\n constraint_name: string;\n column_name: string;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'PRIMARY KEY'\n ORDER BY kcu.ordinal_position`,\n [schemaName, tableName]\n );\n\n if (result.rows.length === 0) return null;\n\n const columns = result.rows.map((r) => `\"${r.column_name}\"`).join(', ');\n const constraintName = result.rows[0]!.constraint_name;\n\n return `ALTER TABLE \"${tableName}\" ADD CONSTRAINT \"${constraintName}\" PRIMARY KEY (${columns})`;\n}\n\n/**\n * Generate foreign key DDLs for a table\n */\nexport async function generateForeignKeyDdls(\n pool: Pool,\n sourceSchema: string,\n targetSchema: string,\n tableName: string\n): Promise<string[]> {\n const result = await pool.query<{\n constraint_name: string;\n column_name: string;\n foreign_table_name: string;\n foreign_column_name: string;\n update_rule: string;\n delete_rule: string;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name,\n ccu.table_name as foreign_table_name,\n ccu.column_name as foreign_column_name,\n rc.update_rule,\n rc.delete_rule\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n JOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.table_schema = ccu.table_schema\n JOIN information_schema.referential_constraints rc\n ON tc.constraint_name = rc.constraint_name\n AND tc.table_schema = rc.constraint_schema\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'FOREIGN KEY'\n ORDER BY tc.constraint_name, kcu.ordinal_position`,\n [sourceSchema, tableName]\n );\n\n // Group by constraint name\n const fkMap = new Map<\n string,\n {\n columns: string[];\n foreignTable: string;\n foreignColumns: string[];\n updateRule: string;\n deleteRule: string;\n }\n >();\n\n for (const row of result.rows) {\n const existing = fkMap.get(row.constraint_name);\n if (existing) {\n existing.columns.push(row.column_name);\n existing.foreignColumns.push(row.foreign_column_name);\n } else {\n fkMap.set(row.constraint_name, {\n columns: [row.column_name],\n foreignTable: row.foreign_table_name,\n foreignColumns: [row.foreign_column_name],\n updateRule: row.update_rule,\n deleteRule: row.delete_rule,\n });\n }\n }\n\n return Array.from(fkMap.entries()).map(([name, fk]) => {\n const columns = fk.columns.map((c) => `\"${c}\"`).join(', ');\n const foreignColumns = fk.foreignColumns.map((c) => `\"${c}\"`).join(', ');\n\n let ddl = `ALTER TABLE \"${targetSchema}\".\"${tableName}\" `;\n ddl += `ADD CONSTRAINT \"${name}\" FOREIGN KEY (${columns}) `;\n ddl += `REFERENCES \"${targetSchema}\".\"${fk.foreignTable}\" (${foreignColumns})`;\n\n if (fk.updateRule !== 'NO ACTION') {\n ddl += ` ON UPDATE ${fk.updateRule}`;\n }\n if (fk.deleteRule !== 'NO ACTION') {\n ddl += ` ON DELETE ${fk.deleteRule}`;\n }\n\n return ddl;\n });\n}\n\n/**\n * Generate unique constraint DDLs\n */\nexport async function generateUniqueDdls(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<string[]> {\n const result = await pool.query<{\n constraint_name: string;\n column_name: string;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'UNIQUE'\n ORDER BY tc.constraint_name, kcu.ordinal_position`,\n [schemaName, tableName]\n );\n\n const uniqueMap = new Map<string, string[]>();\n for (const row of result.rows) {\n const existing = uniqueMap.get(row.constraint_name);\n if (existing) {\n existing.push(row.column_name);\n } else {\n uniqueMap.set(row.constraint_name, [row.column_name]);\n }\n }\n\n return Array.from(uniqueMap.entries()).map(([name, columns]) => {\n const cols = columns.map((c) => `\"${c}\"`).join(', ');\n return `ALTER TABLE \"${tableName}\" ADD CONSTRAINT \"${name}\" UNIQUE (${cols})`;\n });\n}\n\n/**\n * Generate check constraint DDLs\n */\nexport async function generateCheckDdls(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<string[]> {\n const result = await pool.query<{\n constraint_name: string;\n check_clause: string;\n }>(\n `SELECT\n tc.constraint_name,\n cc.check_clause\n FROM information_schema.table_constraints tc\n JOIN information_schema.check_constraints cc\n ON tc.constraint_name = cc.constraint_name\n AND tc.constraint_schema = cc.constraint_schema\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'CHECK'\n AND tc.constraint_name NOT LIKE '%_not_null'`,\n [schemaName, tableName]\n );\n\n return result.rows.map(\n (row) => `ALTER TABLE \"${tableName}\" ADD CONSTRAINT \"${row.constraint_name}\" CHECK (${row.check_clause})`,\n );\n}\n\n/**\n * Get row count for a table\n */\nexport async function getRowCount(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<number> {\n const result = await pool.query<{ count: string }>(\n `SELECT count(*) FROM \"${schemaName}\".\"${tableName}\"`,\n );\n return parseInt(result.rows[0]!.count, 10);\n}\n\n/**\n * Generate complete clone information for a table\n */\nexport async function generateTableCloneInfo(\n pool: Pool,\n sourceSchema: string,\n targetSchema: string,\n tableName: string\n): Promise<TableCloneInfo> {\n const [createDdl, indexDdls, pkDdl, uniqueDdls, checkDdls, fkDdls, rowCount] = await Promise.all([\n generateTableDdl(pool, sourceSchema, tableName),\n generateIndexDdls(pool, sourceSchema, targetSchema, tableName),\n generatePrimaryKeyDdl(pool, sourceSchema, tableName),\n generateUniqueDdls(pool, sourceSchema, tableName),\n generateCheckDdls(pool, sourceSchema, tableName),\n generateForeignKeyDdls(pool, sourceSchema, targetSchema, tableName),\n getRowCount(pool, sourceSchema, tableName),\n ]);\n\n return {\n name: tableName,\n createDdl,\n indexDdls,\n constraintDdls: [\n ...(pkDdl ? [pkDdl] : []),\n ...uniqueDdls,\n ...checkDdls,\n ...fkDdls,\n ],\n rowCount,\n };\n}\n","/**\n * Data Copier\n *\n * Copies data between schemas using INSERT...SELECT.\n * Supports anonymization of sensitive columns.\n *\n * @module clone/data-copier\n */\n\nimport type { Pool } from 'pg';\nimport type { AnonymizeRules, CloneProgressCallback } from './types.js';\n\n/**\n * Get column names for a table\n */\nexport async function getTableColumns(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<string[]> {\n const result = await pool.query<{ column_name: string }>(\n `SELECT column_name\n FROM information_schema.columns\n WHERE table_schema = $1 AND table_name = $2\n ORDER BY ordinal_position`,\n [schemaName, tableName]\n );\n return result.rows.map((r) => r.column_name);\n}\n\n/**\n * Format anonymize value for SQL\n */\nfunction formatAnonymizeValue(value: null | string | number | boolean): string {\n if (value === null) {\n return 'NULL';\n }\n if (typeof value === 'string') {\n // Escape single quotes\n return `'${value.replace(/'/g, \"''\")}'`;\n }\n if (typeof value === 'boolean') {\n return value ? 'TRUE' : 'FALSE';\n }\n return String(value);\n}\n\n/**\n * Copy data from one table to another\n *\n * @returns Number of rows copied\n */\nexport async function copyTableData(\n pool: Pool,\n sourceSchema: string,\n targetSchema: string,\n tableName: string,\n anonymizeRules?: AnonymizeRules\n): Promise<number> {\n const columns = await getTableColumns(pool, sourceSchema, tableName);\n\n if (columns.length === 0) {\n return 0;\n }\n\n // Build SELECT with anonymization\n const tableRules = anonymizeRules?.[tableName] ?? {};\n const selectColumns = columns.map((col) => {\n if (col in tableRules) {\n const value = tableRules[col];\n return `${formatAnonymizeValue(value)} as \"${col}\"`;\n }\n return `\"${col}\"`;\n });\n\n const insertColumns = columns.map((c) => `\"${c}\"`).join(', ');\n const selectExpr = selectColumns.join(', ');\n\n const result = await pool.query(\n `INSERT INTO \"${targetSchema}\".\"${tableName}\" (${insertColumns})\n SELECT ${selectExpr}\n FROM \"${sourceSchema}\".\"${tableName}\"`\n );\n\n return result.rowCount ?? 0;\n}\n\n/**\n * Get tables in dependency order for data copy\n *\n * Tables with foreign keys should be copied after their referenced tables.\n * This uses a topological sort based on foreign key relationships.\n */\nexport async function getTablesInDependencyOrder(\n pool: Pool,\n schemaName: string,\n tables: string[]\n): Promise<string[]> {\n // Get all foreign key relationships\n const result = await pool.query<{\n table_name: string;\n foreign_table_name: string;\n }>(\n `SELECT DISTINCT\n tc.table_name,\n ccu.table_name as foreign_table_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.table_schema = ccu.table_schema\n WHERE tc.table_schema = $1\n AND tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_name != ccu.table_name`,\n [schemaName]\n );\n\n // Build dependency graph\n const dependencies = new Map<string, Set<string>>();\n const tableSet = new Set(tables);\n\n for (const table of tables) {\n dependencies.set(table, new Set());\n }\n\n for (const row of result.rows) {\n if (tableSet.has(row.table_name) && tableSet.has(row.foreign_table_name)) {\n dependencies.get(row.table_name)!.add(row.foreign_table_name);\n }\n }\n\n // Topological sort (Kahn's algorithm)\n const sorted: string[] = [];\n const inDegree = new Map<string, number>();\n const queue: string[] = [];\n\n // Calculate in-degrees\n for (const table of tables) {\n inDegree.set(table, 0);\n }\n for (const [table, deps] of dependencies) {\n for (const dep of deps) {\n inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);\n }\n }\n\n // Find nodes with no incoming edges\n for (const [table, degree] of inDegree) {\n if (degree === 0) {\n queue.push(table);\n }\n }\n\n // Process queue\n while (queue.length > 0) {\n const table = queue.shift()!;\n sorted.push(table);\n\n // Remove edges from this node\n for (const [otherTable, deps] of dependencies) {\n if (deps.has(table)) {\n deps.delete(table);\n const newDegree = (inDegree.get(otherTable) ?? 0) - 1;\n inDegree.set(otherTable, newDegree);\n if (newDegree === 0) {\n queue.push(otherTable);\n }\n }\n }\n }\n\n // If there's a cycle, just use original order for remaining tables\n const remaining = tables.filter((t) => !sorted.includes(t));\n return [...sorted, ...remaining];\n}\n\n/**\n * Copy data from all tables\n *\n * @returns Total number of rows copied\n */\nexport async function copyAllData(\n pool: Pool,\n sourceSchema: string,\n targetSchema: string,\n tables: string[],\n anonymizeRules?: AnonymizeRules,\n onProgress?: CloneProgressCallback\n): Promise<number> {\n let totalRows = 0;\n\n // Get tables in dependency order\n const orderedTables = await getTablesInDependencyOrder(pool, sourceSchema, tables);\n\n // Disable triggers temporarily for faster insert and to avoid constraint issues\n await pool.query('SET session_replication_role = replica');\n\n try {\n for (let i = 0; i < orderedTables.length; i++) {\n const table = orderedTables[i]!;\n\n onProgress?.('copying_data', {\n table,\n progress: i + 1,\n total: orderedTables.length,\n });\n\n const rows = await copyTableData(pool, sourceSchema, targetSchema, table, anonymizeRules);\n\n totalRows += rows;\n }\n } finally {\n // Re-enable triggers\n await pool.query('SET session_replication_role = DEFAULT');\n }\n\n return totalRows;\n}\n","/**\n * Cloner\n *\n * Clones a tenant to another, including structure and optionally data.\n *\n * @module clone/cloner\n */\n\nimport type { Pool } from 'pg';\nimport type {\n ClonerConfig,\n ClonerDependencies,\n CloneTenantOptions,\n CloneTenantResult,\n} from './types.js';\nimport { listTables, generateTableCloneInfo } from './ddl-generator.js';\nimport { copyAllData } from './data-copier.js';\n\nconst DEFAULT_MIGRATIONS_TABLE = '__drizzle_migrations';\n\n/**\n * Clones tenants with support for introspection + DDL\n *\n * @example\n * ```typescript\n * const cloner = createCloner(config, dependencies);\n *\n * // Schema-only clone\n * await cloner.cloneTenant('source', 'target');\n *\n * // Clone with data\n * await cloner.cloneTenant('source', 'target', { includeData: true });\n *\n * // Clone with anonymization\n * await cloner.cloneTenant('source', 'target', {\n * includeData: true,\n * anonymize: {\n * enabled: true,\n * rules: { users: { email: null, phone: null } },\n * },\n * });\n * ```\n */\nexport class Cloner {\n private readonly migrationsTable: string;\n\n constructor(\n config: ClonerConfig,\n private readonly deps: ClonerDependencies\n ) {\n this.migrationsTable = config.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE;\n }\n\n /**\n * Clone a tenant to another\n *\n * @param sourceTenantId - Source tenant ID\n * @param targetTenantId - Target tenant ID\n * @param options - Clone options\n * @returns Clone result\n */\n async cloneTenant(\n sourceTenantId: string,\n targetTenantId: string,\n options: CloneTenantOptions = {}\n ): Promise<CloneTenantResult> {\n const startTime = Date.now();\n const {\n includeData = false,\n anonymize,\n excludeTables = [],\n onProgress,\n } = options;\n\n const sourceSchema = this.deps.schemaNameTemplate(sourceTenantId);\n const targetSchema = this.deps.schemaNameTemplate(targetTenantId);\n\n // Tables to exclude: migrations + custom\n const allExcludes = [this.migrationsTable, ...excludeTables];\n\n let sourcePool: Pool | null = null;\n let rootPool: Pool | null = null;\n\n try {\n onProgress?.('starting');\n\n // Check if source exists\n const sourceExists = await this.deps.schemaExists(sourceTenantId);\n if (!sourceExists) {\n return this.createErrorResult(\n sourceTenantId,\n targetTenantId,\n targetSchema,\n `Source tenant \"${sourceTenantId}\" does not exist`,\n startTime\n );\n }\n\n // Check if target already exists\n const targetExists = await this.deps.schemaExists(targetTenantId);\n if (targetExists) {\n return this.createErrorResult(\n sourceTenantId,\n targetTenantId,\n targetSchema,\n `Target tenant \"${targetTenantId}\" already exists`,\n startTime\n );\n }\n\n // Introspect source schema\n onProgress?.('introspecting');\n sourcePool = await this.deps.createPool(sourceSchema);\n\n const tables = await listTables(sourcePool, sourceSchema, allExcludes);\n\n if (tables.length === 0) {\n // Source has no tables, just create empty schema\n onProgress?.('creating_schema');\n await this.deps.createSchema(targetTenantId);\n\n onProgress?.('completed');\n return {\n sourceTenant: sourceTenantId,\n targetTenant: targetTenantId,\n targetSchema,\n success: true,\n tables: [],\n durationMs: Date.now() - startTime,\n };\n }\n\n const tableInfos = await Promise.all(\n tables.map((t) => generateTableCloneInfo(sourcePool!, sourceSchema, targetSchema, t))\n );\n\n // Close source pool after introspection\n await sourcePool.end();\n sourcePool = null;\n\n // Create target schema\n onProgress?.('creating_schema');\n await this.deps.createSchema(targetTenantId);\n\n // Execute DDLs on target\n rootPool = await this.deps.createRootPool();\n\n // Create tables\n onProgress?.('creating_tables');\n for (const info of tableInfos) {\n await rootPool.query(`SET search_path TO \"${targetSchema}\"; ${info.createDdl}`);\n }\n\n // Create PKs and Unique constraints (before FK)\n onProgress?.('creating_constraints');\n for (const info of tableInfos) {\n for (const constraint of info.constraintDdls.filter((c) => !c.includes('FOREIGN KEY'))) {\n try {\n await rootPool.query(`SET search_path TO \"${targetSchema}\"; ${constraint}`);\n } catch (error) {\n // Constraint might already exist due to table definition\n // This can happen with some PostgreSQL versions\n }\n }\n }\n\n // Create indexes\n onProgress?.('creating_indexes');\n for (const info of tableInfos) {\n for (const index of info.indexDdls) {\n try {\n await rootPool.query(index);\n } catch (error) {\n // Index might already exist\n }\n }\n }\n\n // Copy data if requested\n let rowsCopied = 0;\n if (includeData) {\n onProgress?.('copying_data');\n rowsCopied = await copyAllData(\n rootPool,\n sourceSchema,\n targetSchema,\n tables,\n anonymize?.enabled ? anonymize.rules : undefined,\n onProgress\n );\n }\n\n // Create FKs (after data)\n for (const info of tableInfos) {\n for (const fk of info.constraintDdls.filter((c) => c.includes('FOREIGN KEY'))) {\n try {\n await rootPool.query(fk);\n } catch (error) {\n // FK might fail if referencing tables outside the tenant schema\n // Log but don't fail the entire operation\n }\n }\n }\n\n onProgress?.('completed');\n\n const result: CloneTenantResult = {\n sourceTenant: sourceTenantId,\n targetTenant: targetTenantId,\n targetSchema,\n success: true,\n tables,\n durationMs: Date.now() - startTime,\n };\n\n if (includeData) {\n result.rowsCopied = rowsCopied;\n }\n\n return result;\n } catch (error) {\n options.onError?.(error as Error);\n onProgress?.('failed');\n\n return this.createErrorResult(\n sourceTenantId,\n targetTenantId,\n targetSchema,\n (error as Error).message,\n startTime\n );\n } finally {\n // Cleanup pools\n if (sourcePool) {\n await sourcePool.end().catch(() => {});\n }\n if (rootPool) {\n await rootPool.end().catch(() => {});\n }\n }\n }\n\n private createErrorResult(\n source: string,\n target: string,\n schema: string,\n error: string,\n startTime: number\n ): CloneTenantResult {\n return {\n sourceTenant: source,\n targetTenant: target,\n targetSchema: schema,\n success: false,\n error,\n tables: [],\n durationMs: Date.now() - startTime,\n };\n }\n}\n\n/**\n * Factory function for Cloner\n *\n * @param config - Cloner configuration\n * @param dependencies - Cloner dependencies\n * @returns Cloner instance\n */\nexport function createCloner(config: ClonerConfig, dependencies: ClonerDependencies): Cloner {\n return new Cloner(config, dependencies);\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { Pool } from 'pg';\nimport type { Config } from '../types.js';\nimport type {\n MigratorConfig,\n MigrationFile,\n MigrateOptions,\n TenantMigrationResult,\n MigrationResults,\n TenantMigrationStatus,\n CreateTenantOptions,\n DropTenantOptions,\n TenantSyncStatus,\n SyncStatus,\n TenantSyncResult,\n SyncResults,\n SyncOptions,\n SeedFunction,\n SeedOptions,\n TenantSeedResult,\n SeedResults,\n // Schema drift detection types (delegated to DriftDetector)\n TenantSchema,\n TenantSchemaDrift,\n SchemaDriftStatus,\n SchemaDriftOptions,\n} from './types.js';\nimport { detectTableFormat, getFormatConfig, type DetectedFormat, type TableFormat } from './table-format.js';\nimport { SchemaManager } from './schema-manager.js';\nimport { DriftDetector } from './drift/drift-detector.js';\nimport { Seeder } from './seed/seeder.js';\nimport { SyncManager } from './sync/sync-manager.js';\nimport { MigrationExecutor } from './executor/migration-executor.js';\nimport { BatchExecutor } from './executor/batch-executor.js';\nimport { Cloner } from './clone/cloner.js';\nimport type { CloneTenantOptions, CloneTenantResult } from './clone/types.js';\n\nconst DEFAULT_MIGRATIONS_TABLE = '__drizzle_migrations';\n\n/**\n * Parallel migration engine for multi-tenant applications\n */\nexport class Migrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly migrationsTable: string;\n private readonly schemaManager: SchemaManager<TTenantSchema, TSharedSchema>;\n private readonly driftDetector: DriftDetector<TTenantSchema, TSharedSchema>;\n private readonly seeder: Seeder<TTenantSchema>;\n private readonly syncManager: SyncManager;\n private readonly migrationExecutor: MigrationExecutor;\n private readonly batchExecutor: BatchExecutor;\n private readonly cloner: Cloner;\n\n constructor(\n tenantConfig: Config<TTenantSchema, TSharedSchema>,\n private readonly migratorConfig: MigratorConfig\n ) {\n this.migrationsTable = migratorConfig.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE;\n this.schemaManager = new SchemaManager(tenantConfig, this.migrationsTable);\n this.driftDetector = new DriftDetector(tenantConfig, this.schemaManager, {\n migrationsTable: this.migrationsTable,\n tenantDiscovery: migratorConfig.tenantDiscovery,\n });\n this.seeder = new Seeder(\n { tenantDiscovery: migratorConfig.tenantDiscovery },\n {\n createPool: this.schemaManager.createPool.bind(this.schemaManager),\n schemaNameTemplate: tenantConfig.isolation.schemaNameTemplate,\n tenantSchema: tenantConfig.schemas.tenant as TTenantSchema,\n }\n );\n this.syncManager = new SyncManager(\n {\n tenantDiscovery: migratorConfig.tenantDiscovery,\n migrationsFolder: migratorConfig.migrationsFolder,\n migrationsTable: this.migrationsTable,\n },\n {\n createPool: this.schemaManager.createPool.bind(this.schemaManager),\n schemaNameTemplate: tenantConfig.isolation.schemaNameTemplate,\n migrationsTableExists: this.schemaManager.migrationsTableExists.bind(this.schemaManager),\n ensureMigrationsTable: this.schemaManager.ensureMigrationsTable.bind(this.schemaManager),\n getOrDetectFormat: this.getOrDetectFormat.bind(this),\n loadMigrations: this.loadMigrations.bind(this),\n }\n );\n\n // Initialize MigrationExecutor (single tenant operations)\n this.migrationExecutor = new MigrationExecutor(\n { hooks: migratorConfig.hooks },\n {\n createPool: this.schemaManager.createPool.bind(this.schemaManager),\n schemaNameTemplate: tenantConfig.isolation.schemaNameTemplate,\n migrationsTableExists: this.schemaManager.migrationsTableExists.bind(this.schemaManager),\n ensureMigrationsTable: this.schemaManager.ensureMigrationsTable.bind(this.schemaManager),\n getOrDetectFormat: this.getOrDetectFormat.bind(this),\n loadMigrations: this.loadMigrations.bind(this),\n }\n );\n\n // Initialize BatchExecutor (multi-tenant operations)\n this.batchExecutor = new BatchExecutor(\n { tenantDiscovery: migratorConfig.tenantDiscovery },\n this.migrationExecutor,\n this.loadMigrations.bind(this)\n );\n\n // Initialize Cloner (tenant cloning operations)\n this.cloner = new Cloner(\n { migrationsTable: this.migrationsTable },\n {\n createPool: this.schemaManager.createPool.bind(this.schemaManager),\n createRootPool: this.schemaManager.createRootPool.bind(this.schemaManager),\n schemaNameTemplate: tenantConfig.isolation.schemaNameTemplate,\n schemaExists: this.schemaManager.schemaExists.bind(this.schemaManager),\n createSchema: this.schemaManager.createSchema.bind(this.schemaManager),\n }\n );\n }\n\n /**\n * Migrate all tenants in parallel\n *\n * Delegates to BatchExecutor for parallel migration operations.\n */\n async migrateAll(options: MigrateOptions = {}): Promise<MigrationResults> {\n return this.batchExecutor.migrateAll(options);\n }\n\n /**\n * Migrate a single tenant\n *\n * Delegates to MigrationExecutor for single tenant operations.\n */\n async migrateTenant(\n tenantId: string,\n migrations?: MigrationFile[],\n options: { dryRun?: boolean; onProgress?: MigrateOptions['onProgress'] } = {}\n ): Promise<TenantMigrationResult> {\n return this.migrationExecutor.migrateTenant(tenantId, migrations, options);\n }\n\n /**\n * Migrate specific tenants\n *\n * Delegates to BatchExecutor for parallel migration operations.\n */\n async migrateTenants(tenantIds: string[], options: MigrateOptions = {}): Promise<MigrationResults> {\n return this.batchExecutor.migrateTenants(tenantIds, options);\n }\n\n /**\n * Get migration status for all tenants\n *\n * Delegates to BatchExecutor for status operations.\n */\n async getStatus(): Promise<TenantMigrationStatus[]> {\n return this.batchExecutor.getStatus();\n }\n\n /**\n * Get migration status for a specific tenant\n *\n * Delegates to MigrationExecutor for single tenant operations.\n */\n async getTenantStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantMigrationStatus> {\n return this.migrationExecutor.getTenantStatus(tenantId, migrations);\n }\n\n /**\n * Create a new tenant schema and optionally apply migrations\n */\n async createTenant(tenantId: string, options: CreateTenantOptions = {}): Promise<void> {\n const { migrate = true } = options;\n\n // Delegate schema creation to SchemaManager\n await this.schemaManager.createSchema(tenantId);\n\n if (migrate) {\n // Apply all migrations\n await this.migrateTenant(tenantId);\n }\n }\n\n /**\n * Drop a tenant schema\n */\n async dropTenant(tenantId: string, options: DropTenantOptions = {}): Promise<void> {\n // Delegate to SchemaManager\n await this.schemaManager.dropSchema(tenantId, options);\n }\n\n /**\n * Check if a tenant schema exists\n */\n async tenantExists(tenantId: string): Promise<boolean> {\n // Delegate to SchemaManager\n return this.schemaManager.schemaExists(tenantId);\n }\n\n /**\n * Clone a tenant to a new tenant\n *\n * By default, clones only schema structure. Use includeData to copy data.\n *\n * @example\n * ```typescript\n * // Schema-only clone\n * await migrator.cloneTenant('production', 'dev');\n *\n * // Clone with data\n * await migrator.cloneTenant('production', 'dev', { includeData: true });\n *\n * // Clone with anonymization\n * await migrator.cloneTenant('production', 'dev', {\n * includeData: true,\n * anonymize: {\n * enabled: true,\n * rules: {\n * users: { email: null, phone: null },\n * },\n * },\n * });\n * ```\n */\n async cloneTenant(\n sourceTenantId: string,\n targetTenantId: string,\n options: CloneTenantOptions = {}\n ): Promise<CloneTenantResult> {\n return this.cloner.cloneTenant(sourceTenantId, targetTenantId, options);\n }\n\n /**\n * Mark migrations as applied without executing SQL\n * Useful for syncing tracking state with already-applied migrations\n *\n * Delegates to MigrationExecutor for single tenant operations.\n */\n async markAsApplied(\n tenantId: string,\n options: { onProgress?: MigrateOptions['onProgress'] } = {}\n ): Promise<TenantMigrationResult> {\n return this.migrationExecutor.markAsApplied(tenantId, options);\n }\n\n /**\n * Mark migrations as applied for all tenants without executing SQL\n * Useful for syncing tracking state with already-applied migrations\n *\n * Delegates to BatchExecutor for parallel operations.\n */\n async markAllAsApplied(options: MigrateOptions = {}): Promise<MigrationResults> {\n return this.batchExecutor.markAllAsApplied(options);\n }\n\n // ============================================================================\n // Sync Methods (delegated to SyncManager)\n // ============================================================================\n\n /**\n * Get sync status for all tenants\n * Detects divergences between migrations on disk and tracking in database\n */\n async getSyncStatus(): Promise<SyncStatus> {\n return this.syncManager.getSyncStatus();\n }\n\n /**\n * Get sync status for a specific tenant\n */\n async getTenantSyncStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantSyncStatus> {\n return this.syncManager.getTenantSyncStatus(tenantId, migrations);\n }\n\n /**\n * Mark missing migrations as applied for a tenant\n */\n async markMissing(tenantId: string): Promise<TenantSyncResult> {\n return this.syncManager.markMissing(tenantId);\n }\n\n /**\n * Mark missing migrations as applied for all tenants\n */\n async markAllMissing(options: SyncOptions = {}): Promise<SyncResults> {\n return this.syncManager.markAllMissing(options);\n }\n\n /**\n * Remove orphan migration records for a tenant\n */\n async cleanOrphans(tenantId: string): Promise<TenantSyncResult> {\n return this.syncManager.cleanOrphans(tenantId);\n }\n\n /**\n * Remove orphan migration records for all tenants\n */\n async cleanAllOrphans(options: SyncOptions = {}): Promise<SyncResults> {\n return this.syncManager.cleanAllOrphans(options);\n }\n\n // ============================================================================\n // Seeding Methods (delegated to Seeder)\n // ============================================================================\n\n /**\n * Seed a single tenant with initial data\n *\n * @example\n * ```typescript\n * const seed: SeedFunction = async (db, tenantId) => {\n * await db.insert(roles).values([\n * { name: 'admin', permissions: ['*'] },\n * { name: 'user', permissions: ['read'] },\n * ]);\n * };\n *\n * await migrator.seedTenant('tenant-123', seed);\n * ```\n */\n async seedTenant(\n tenantId: string,\n seedFn: SeedFunction<TTenantSchema>\n ): Promise<TenantSeedResult> {\n return this.seeder.seedTenant(tenantId, seedFn);\n }\n\n /**\n * Seed all tenants with initial data in parallel\n *\n * @example\n * ```typescript\n * const seed: SeedFunction = async (db, tenantId) => {\n * await db.insert(roles).values([\n * { name: 'admin', permissions: ['*'] },\n * ]);\n * };\n *\n * await migrator.seedAll(seed, { concurrency: 10 });\n * ```\n */\n async seedAll(\n seedFn: SeedFunction<TTenantSchema>,\n options: SeedOptions = {}\n ): Promise<SeedResults> {\n return this.seeder.seedAll(seedFn, options);\n }\n\n /**\n * Seed specific tenants with initial data\n */\n async seedTenants(\n tenantIds: string[],\n seedFn: SeedFunction<TTenantSchema>,\n options: SeedOptions = {}\n ): Promise<SeedResults> {\n return this.seeder.seedTenants(tenantIds, seedFn, options);\n }\n\n /**\n * Load migration files from the migrations folder\n */\n private async loadMigrations(): Promise<MigrationFile[]> {\n const files = await readdir(this.migratorConfig.migrationsFolder);\n\n const migrations: MigrationFile[] = [];\n\n for (const file of files) {\n if (!file.endsWith('.sql')) continue;\n\n const filePath = join(this.migratorConfig.migrationsFolder, file);\n const content = await readFile(filePath, 'utf-8');\n\n // Extract timestamp from filename (e.g., 0001_migration_name.sql)\n const match = file.match(/^(\\d+)_/);\n const timestamp = match?.[1] ? parseInt(match[1], 10) : 0;\n\n // Compute SHA-256 hash for drizzle-kit compatibility\n const hash = createHash('sha256').update(content).digest('hex');\n\n migrations.push({\n name: basename(file, '.sql'),\n path: filePath,\n sql: content,\n timestamp,\n hash,\n });\n }\n\n // Sort by timestamp\n return migrations.sort((a, b) => a.timestamp - b.timestamp);\n }\n\n /**\n * Get or detect the format for a schema\n * Returns the configured format or auto-detects from existing table\n *\n * Note: This method is shared with SyncManager and MigrationExecutor via dependency injection.\n */\n private async getOrDetectFormat(\n pool: Pool,\n schemaName: string\n ): Promise<DetectedFormat> {\n const configuredFormat = this.migratorConfig.tableFormat ?? 'auto';\n\n // If not auto, return the configured format\n if (configuredFormat !== 'auto') {\n return getFormatConfig(configuredFormat, this.migrationsTable);\n }\n\n // Auto-detect from existing table\n const detected = await detectTableFormat(pool, schemaName, this.migrationsTable);\n\n if (detected) {\n return detected;\n }\n\n // No table exists, use default format\n const defaultFormat: TableFormat = this.migratorConfig.defaultFormat ?? 'name';\n return getFormatConfig(defaultFormat, this.migrationsTable);\n }\n\n // ============================================================================\n // Schema Drift Detection Methods (delegated to DriftDetector)\n // ============================================================================\n\n /**\n * Detect schema drift across all tenants\n * Compares each tenant's schema against a reference tenant (first tenant by default)\n *\n * @example\n * ```typescript\n * const drift = await migrator.getSchemaDrift();\n * if (drift.withDrift > 0) {\n * console.log('Schema drift detected!');\n * for (const tenant of drift.details) {\n * if (tenant.hasDrift) {\n * console.log(`Tenant ${tenant.tenantId} has drift:`);\n * for (const table of tenant.tables) {\n * for (const col of table.columns) {\n * console.log(` - ${table.table}.${col.column}: ${col.description}`);\n * }\n * }\n * }\n * }\n * }\n * ```\n */\n async getSchemaDrift(options: SchemaDriftOptions = {}): Promise<SchemaDriftStatus> {\n return this.driftDetector.detectDrift(options);\n }\n\n /**\n * Get schema drift for a specific tenant compared to a reference\n */\n async getTenantSchemaDrift(\n tenantId: string,\n referenceTenantId: string,\n options: Pick<SchemaDriftOptions, 'includeIndexes' | 'includeConstraints' | 'excludeTables'> = {}\n ): Promise<TenantSchemaDrift> {\n return this.driftDetector.compareTenant(tenantId, referenceTenantId, options);\n }\n\n /**\n * Introspect the schema of a tenant\n */\n async introspectTenantSchema(\n tenantId: string,\n options: { includeIndexes?: boolean; includeConstraints?: boolean; excludeTables?: string[] } = {}\n ): Promise<TenantSchema | null> {\n return this.driftDetector.introspectSchema(tenantId, options);\n }\n}\n\n/**\n * Create a migrator instance\n */\nexport function createMigrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n tenantConfig: Config<TTenantSchema, TSharedSchema>,\n migratorConfig: MigratorConfig\n): Migrator<TTenantSchema, TSharedSchema> {\n return new Migrator(tenantConfig, migratorConfig);\n}\n","import { sql, getTableName } from 'drizzle-orm';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport type { SQL, Table, Column } from 'drizzle-orm';\nimport type {\n CrossSchemaContext,\n SchemaSource,\n JoinType,\n JoinCondition,\n SharedLookupConfig,\n CrossSchemaRawOptions,\n} from './types.js';\n\n/**\n * Cross-schema query builder for joining tenant and shared data\n *\n * @example\n * ```typescript\n * const query = createCrossSchemaQuery({\n * tenantDb: tenants.getDb('tenant-uuid'),\n * sharedDb: tenants.getSharedDb(),\n * });\n *\n * const results = await query\n * .from('tenant', orders)\n * .leftJoin('shared', subscriptionPlans, eq(orders.planId, subscriptionPlans.id))\n * .select({\n * orderId: orders.id,\n * planName: subscriptionPlans.name,\n * })\n * .execute();\n * ```\n */\nexport class CrossSchemaQueryBuilder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n private fromTable: { table: Table; source: SchemaSource; schemaName: string } | null = null;\n private joins: Array<{\n table: Table;\n source: SchemaSource;\n schemaName: string;\n condition: JoinCondition;\n type: JoinType;\n }> = [];\n private selectFields: Record<string, Column> = {};\n private whereCondition: SQL<unknown> | null = null;\n private orderByFields: SQL<unknown>[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n\n constructor(private readonly context: CrossSchemaContext<TTenantSchema, TSharedSchema>) {}\n\n /**\n * Set the main table to query from\n */\n from<T extends Table>(source: SchemaSource, table: T): this {\n const schemaName = this.getSchemaName(source);\n this.fromTable = { table, source, schemaName };\n return this;\n }\n\n /**\n * Add an inner join\n */\n innerJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'inner');\n }\n\n /**\n * Add a left join\n */\n leftJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'left');\n }\n\n /**\n * Add a right join\n */\n rightJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'right');\n }\n\n /**\n * Add a full outer join\n */\n fullJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'full');\n }\n\n /**\n * Select specific fields\n */\n select<T extends Record<string, Column>>(fields: T): this {\n this.selectFields = fields;\n return this;\n }\n\n /**\n * Add a where condition\n */\n where(condition: SQL<unknown>): this {\n this.whereCondition = condition;\n return this;\n }\n\n /**\n * Add order by\n */\n orderBy(...fields: SQL<unknown>[]): this {\n this.orderByFields = fields;\n return this;\n }\n\n /**\n * Set limit\n */\n limit(value: number): this {\n this.limitValue = value;\n return this;\n }\n\n /**\n * Set offset\n */\n offset(value: number): this {\n this.offsetValue = value;\n return this;\n }\n\n /**\n * Execute the query and return typed results\n */\n async execute<TResult = Record<string, unknown>>(): Promise<TResult[]> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified. Use .from() first.');\n }\n\n const sqlQuery = this.buildSql();\n\n // Use the tenant db to execute (it has access to both schemas via search_path)\n const result = await this.context.tenantDb.execute(sqlQuery);\n\n return result.rows as TResult[];\n }\n\n /**\n * Build the SQL query\n */\n private buildSql(): SQL<unknown> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified');\n }\n\n const parts: SQL<unknown>[] = [];\n\n // SELECT clause\n const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {\n const columnName = column.name;\n return sql`${sql.raw(`\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n });\n\n if (selectParts.length === 0) {\n parts.push(sql`SELECT *`);\n } else {\n parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);\n }\n\n // FROM clause\n const fromTableRef = this.getFullTableName(this.fromTable.schemaName, this.fromTable.table);\n parts.push(sql` FROM ${sql.raw(fromTableRef)}`);\n\n // JOIN clauses\n for (const join of this.joins) {\n const joinTableRef = this.getFullTableName(join.schemaName, join.table);\n const joinType = this.getJoinKeyword(join.type);\n parts.push(sql` ${sql.raw(joinType)} ${sql.raw(joinTableRef)} ON ${join.condition}`);\n }\n\n // WHERE clause\n if (this.whereCondition) {\n parts.push(sql` WHERE ${this.whereCondition}`);\n }\n\n // ORDER BY clause\n if (this.orderByFields.length > 0) {\n parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);\n }\n\n // LIMIT clause\n if (this.limitValue !== null) {\n parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);\n }\n\n // OFFSET clause\n if (this.offsetValue !== null) {\n parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);\n }\n\n return sql.join(parts, sql``);\n }\n\n /**\n * Add a join to the query\n */\n private addJoin<T extends Table>(\n source: SchemaSource,\n table: T,\n condition: JoinCondition,\n type: JoinType\n ): this {\n const schemaName = this.getSchemaName(source);\n this.joins.push({ table, source, schemaName, condition, type });\n return this;\n }\n\n /**\n * Get schema name for a source\n */\n private getSchemaName(source: SchemaSource): string {\n if (source === 'tenant') {\n return this.context.tenantSchema ?? 'tenant';\n }\n return this.context.sharedSchema ?? 'public';\n }\n\n /**\n * Get fully qualified table name\n */\n private getFullTableName(schemaName: string, table: Table): string {\n const tableName = getTableName(table);\n return `\"${schemaName}\".\"${tableName}\"`;\n }\n\n /**\n * Get SQL keyword for join type\n */\n private getJoinKeyword(type: JoinType): string {\n switch (type) {\n case 'inner':\n return 'INNER JOIN';\n case 'left':\n return 'LEFT JOIN';\n case 'right':\n return 'RIGHT JOIN';\n case 'full':\n return 'FULL OUTER JOIN';\n }\n }\n}\n\n/**\n * Create a cross-schema query builder\n */\nexport function createCrossSchemaQuery<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(\n context: CrossSchemaContext<TTenantSchema, TSharedSchema>\n): CrossSchemaQueryBuilder<TTenantSchema, TSharedSchema> {\n return new CrossSchemaQueryBuilder(context);\n}\n\n/**\n * Helper for common pattern: tenant table with shared lookup\n *\n * @example\n * ```typescript\n * const ordersWithPlans = await withSharedLookup({\n * tenantDb,\n * sharedDb,\n * tenantTable: orders,\n * sharedTable: subscriptionPlans,\n * foreignKey: 'planId',\n * sharedFields: ['name', 'features', 'price'],\n * });\n * ```\n */\nexport async function withSharedLookup<\n TTenantTable extends Table,\n TSharedTable extends Table,\n TSharedFields extends keyof TSharedTable['_']['columns'],\n>(config: SharedLookupConfig<TTenantTable, TSharedTable, TSharedFields>): Promise<Array<Record<string, unknown>>> {\n const {\n tenantDb,\n tenantTable,\n sharedTable,\n foreignKey,\n sharedKey = 'id' as keyof TSharedTable['_']['columns'],\n sharedFields,\n where: whereCondition,\n } = config;\n\n // Get table names using Drizzle's utility\n const tenantTableName = getTableName(tenantTable);\n const sharedTableName = getTableName(sharedTable);\n\n // Build field list for shared table\n const sharedFieldList = sharedFields\n .map((field) => `s.\"${String(field)}\"`)\n .join(', ');\n\n // Build the query\n const queryParts = [\n `SELECT t.*, ${sharedFieldList}`,\n `FROM \"${tenantTableName}\" t`,\n `LEFT JOIN \"public\".\"${sharedTableName}\" s ON t.\"${String(foreignKey)}\" = s.\"${String(sharedKey)}\"`,\n ];\n\n if (whereCondition) {\n queryParts.push('WHERE');\n // We'll need to use raw SQL for the where condition\n }\n\n const sqlQuery = sql.raw(queryParts.join(' '));\n\n const result = await tenantDb.execute(sqlQuery);\n\n return result.rows as Array<Record<string, unknown>>;\n}\n\n/**\n * Execute raw cross-schema SQL with type safety\n *\n * @example\n * ```typescript\n * const result = await crossSchemaRaw<{ userName: string; planName: string }>({\n * tenantSchema: 'tenant_abc123',\n * sharedSchema: 'public',\n * sql: `\n * SELECT u.name as \"userName\", p.name as \"planName\"\n * FROM $tenant.users u\n * JOIN $shared.plans p ON u.plan_id = p.id\n * `,\n * });\n * ```\n */\nexport async function crossSchemaRaw<TResult = Record<string, unknown>>(\n db: NodePgDatabase<Record<string, unknown>>,\n options: CrossSchemaRawOptions\n): Promise<TResult[]> {\n const { tenantSchema, sharedSchema, sql: rawSql } = options;\n\n // Replace $tenant and $shared placeholders\n const processedSql = rawSql\n .replace(/\\$tenant\\./g, `\"${tenantSchema}\".`)\n .replace(/\\$shared\\./g, `\"${sharedSchema}\".`);\n\n const query = sql.raw(processedSql);\n\n const result = await db.execute(query);\n\n return result.rows as TResult[];\n}\n\n/**\n * Create a typed cross-schema query using SQL template\n *\n * @example\n * ```typescript\n * const users = await crossSchemaSelect(tenantDb, {\n * tenantSchema: 'tenant_abc',\n * sharedSchema: 'public',\n * select: {\n * id: users.id,\n * name: users.name,\n * planName: plans.name,\n * },\n * from: { table: users, schema: 'tenant' },\n * joins: [\n * { table: plans, schema: 'shared', on: eq(users.planId, plans.id), type: 'left' },\n * ],\n * });\n * ```\n */\nexport function buildCrossSchemaSelect<T extends Record<string, Column>>(\n fields: T,\n tenantSchema: string,\n _sharedSchema: string\n): { columns: string[]; getSchema: () => string } {\n const columns = Object.entries(fields).map(([alias, column]) => {\n const columnName = column.name;\n return `\"${columnName}\" as \"${alias}\"`;\n });\n\n const getSchema = (): string => {\n // This would need more context to determine which schema a column belongs to\n // For now, return tenant schema as default\n return tenantSchema;\n };\n\n return { columns, getSchema };\n}\n","import { sql, getTableName } from 'drizzle-orm';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport type { SQL, Column, Table } from 'drizzle-orm';\nimport type {\n JoinCondition,\n JoinType,\n WithSharedConfig,\n WithSharedOptions,\n InferSelectResult,\n} from './types.js';\n\n/**\n * Extract tables from a Drizzle schema object\n */\nfunction extractTablesFromSchema(schema: Record<string, unknown>): Set<Table> {\n const tables = new Set<Table>();\n\n for (const value of Object.values(schema)) {\n if (value && typeof value === 'object' && '_' in value) {\n const branded = value as { _?: { brand?: string } };\n if (branded._?.brand === 'Table') {\n tables.add(value as Table);\n }\n }\n }\n\n return tables;\n}\n\n/**\n * Check if a table belongs to the shared schema\n */\nfunction isSharedTable(table: Table, sharedTables: Set<Table>): boolean {\n return sharedTables.has(table);\n}\n\n/**\n * Simplified cross-schema query builder with automatic schema detection\n *\n * @example\n * ```typescript\n * const result = await withShared(tenantDb, sharedDb, { tenant: tenantSchema, shared: sharedSchema })\n * .from(pedidos)\n * .leftJoin(workflowSteps, eq(pedidos.workflowStepId, workflowSteps.id))\n * .select({ pedidoId: pedidos.id, workflowNome: workflowSteps.nome })\n * .execute();\n * ```\n */\nexport class WithSharedQueryBuilder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n private fromTable: {\n table: Table;\n isShared: boolean;\n schemaName: string;\n } | null = null;\n\n private joins: Array<{\n table: Table;\n isShared: boolean;\n schemaName: string;\n condition: JoinCondition;\n type: JoinType;\n }> = [];\n\n private selectFields: Record<string, Column> = {};\n private whereCondition: SQL<unknown> | null = null;\n private orderByFields: SQL<unknown>[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n\n constructor(\n private readonly tenantDb: NodePgDatabase<TTenantSchema>,\n private readonly sharedTables: Set<Table>,\n private readonly tenantSchemaName: string,\n private readonly sharedSchemaName: string = 'public'\n ) {}\n\n /**\n * Set the main table to query from\n * Automatically detects if it's a tenant or shared table\n */\n from<T extends Table>(table: T): this {\n const isShared = isSharedTable(table, this.sharedTables);\n this.fromTable = {\n table,\n isShared,\n schemaName: isShared ? this.sharedSchemaName : this.tenantSchemaName,\n };\n return this;\n }\n\n /**\n * Add a left join with automatic schema detection\n */\n leftJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'left');\n }\n\n /**\n * Add an inner join with automatic schema detection\n */\n innerJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'inner');\n }\n\n /**\n * Add a right join with automatic schema detection\n */\n rightJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'right');\n }\n\n /**\n * Add a full outer join with automatic schema detection\n */\n fullJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'full');\n }\n\n /**\n * Select specific fields\n */\n select<T extends Record<string, Column>>(fields: T): this {\n this.selectFields = fields;\n return this;\n }\n\n /**\n * Add a WHERE condition\n */\n where(condition: SQL<unknown>): this {\n this.whereCondition = condition;\n return this;\n }\n\n /**\n * Add ORDER BY\n */\n orderBy(...fields: SQL<unknown>[]): this {\n this.orderByFields = fields;\n return this;\n }\n\n /**\n * Set LIMIT\n */\n limit(value: number): this {\n this.limitValue = value;\n return this;\n }\n\n /**\n * Set OFFSET\n */\n offset(value: number): this {\n this.offsetValue = value;\n return this;\n }\n\n /**\n * Execute the query and return typed results\n */\n async execute<TResult extends Record<string, unknown> = InferSelectResult<typeof this.selectFields>>(): Promise<TResult[]> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified. Use .from() first.');\n }\n\n const sqlQuery = this.buildSql();\n const result = await this.tenantDb.execute(sqlQuery);\n\n return result.rows as TResult[];\n }\n\n /**\n * Add a join to the query\n */\n private addJoin<T extends Table>(\n table: T,\n condition: JoinCondition,\n type: JoinType\n ): this {\n const isShared = isSharedTable(table, this.sharedTables);\n this.joins.push({\n table,\n isShared,\n schemaName: isShared ? this.sharedSchemaName : this.tenantSchemaName,\n condition,\n type,\n });\n return this;\n }\n\n /**\n * Build the SQL query\n */\n private buildSql(): SQL<unknown> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified');\n }\n\n const parts: SQL<unknown>[] = [];\n\n // SELECT clause\n const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {\n const columnName = column.name;\n // Try to get table name from column\n const tableName = this.getTableAliasForColumn(column);\n if (tableName) {\n return sql`${sql.raw(`\"${tableName}\".\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n }\n return sql`${sql.raw(`\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n });\n\n if (selectParts.length === 0) {\n parts.push(sql`SELECT *`);\n } else {\n parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);\n }\n\n // FROM clause with alias\n const fromTableName = getTableName(this.fromTable.table);\n const fromTableRef = `\"${this.fromTable.schemaName}\".\"${fromTableName}\"`;\n parts.push(sql` FROM ${sql.raw(fromTableRef)} \"${sql.raw(fromTableName)}\"`);\n\n // JOIN clauses with aliases\n for (const join of this.joins) {\n const joinTableName = getTableName(join.table);\n const joinTableRef = `\"${join.schemaName}\".\"${joinTableName}\"`;\n const joinKeyword = this.getJoinKeyword(join.type);\n parts.push(\n sql` ${sql.raw(joinKeyword)} ${sql.raw(joinTableRef)} \"${sql.raw(joinTableName)}\" ON ${join.condition}`\n );\n }\n\n // WHERE clause\n if (this.whereCondition) {\n parts.push(sql` WHERE ${this.whereCondition}`);\n }\n\n // ORDER BY clause\n if (this.orderByFields.length > 0) {\n parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);\n }\n\n // LIMIT clause\n if (this.limitValue !== null) {\n parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);\n }\n\n // OFFSET clause\n if (this.offsetValue !== null) {\n parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);\n }\n\n return sql.join(parts, sql``);\n }\n\n /**\n * Get table alias for a column (used in SELECT)\n */\n private getTableAliasForColumn(column: Column): string | null {\n // Drizzle columns have a reference to their table\n const columnTable = (column as unknown as { table?: Table }).table;\n if (columnTable) {\n return getTableName(columnTable);\n }\n return null;\n }\n\n /**\n * Get SQL keyword for join type\n */\n private getJoinKeyword(type: JoinType): string {\n switch (type) {\n case 'inner':\n return 'INNER JOIN';\n case 'left':\n return 'LEFT JOIN';\n case 'right':\n return 'RIGHT JOIN';\n case 'full':\n return 'FULL OUTER JOIN';\n }\n }\n}\n\n/**\n * Create a simplified cross-schema query builder with automatic schema detection\n *\n * This helper automatically detects whether a table belongs to the tenant schema\n * or the shared schema based on the schema configuration provided.\n *\n * @param tenantDb - The tenant database instance\n * @param sharedDb - The shared database instance (unused but kept for API symmetry)\n * @param schemas - Object containing tenant and shared schema definitions\n * @param options - Optional configuration for schema names\n * @returns A query builder with automatic schema detection\n *\n * @example\n * ```typescript\n * // Define your schemas\n * const tenantSchema = { pedidos, clientes };\n * const sharedSchema = { workflowSteps, plans };\n *\n * // Use withShared for cross-schema queries\n * const result = await withShared(\n * tenantDb,\n * sharedDb,\n * { tenant: tenantSchema, shared: sharedSchema }\n * )\n * .from(pedidos) // Auto-detected as tenant table\n * .leftJoin(workflowSteps, // Auto-detected as shared table\n * eq(pedidos.workflowStepId, workflowSteps.id)\n * )\n * .select({\n * pedidoId: pedidos.id,\n * workflowNome: workflowSteps.nome,\n * })\n * .where(eq(pedidos.status, 'active'))\n * .orderBy(desc(pedidos.createdAt))\n * .limit(10)\n * .execute();\n * ```\n */\nexport function withShared<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n tenantDb: NodePgDatabase<TTenantSchema>,\n _sharedDb: NodePgDatabase<TSharedSchema>,\n schemas: WithSharedConfig<TTenantSchema, TSharedSchema>,\n options?: WithSharedOptions\n): WithSharedQueryBuilder<TTenantSchema, TSharedSchema> {\n const sharedTables = extractTablesFromSchema(schemas.shared);\n\n return new WithSharedQueryBuilder(\n tenantDb,\n sharedTables,\n options?.tenantSchema ?? 'tenant',\n options?.sharedSchema ?? 'public'\n );\n}\n","import type { RetryConfig } from './types.js';\nimport { DEFAULT_CONFIG } from './types.js';\n\n/**\n * Default function to determine if an error is retryable\n * Focuses on transient connection errors\n */\nexport function isRetryableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n\n // Connection errors\n if (\n message.includes('econnrefused') ||\n message.includes('econnreset') ||\n message.includes('etimedout') ||\n message.includes('enotfound') ||\n message.includes('connection refused') ||\n message.includes('connection reset') ||\n message.includes('connection terminated') ||\n message.includes('connection timed out') ||\n message.includes('timeout expired') ||\n message.includes('socket hang up')\n ) {\n return true;\n }\n\n // PostgreSQL specific transient errors\n if (\n message.includes('too many connections') ||\n message.includes('sorry, too many clients') ||\n message.includes('the database system is starting up') ||\n message.includes('the database system is shutting down') ||\n message.includes('server closed the connection unexpectedly') ||\n message.includes('could not connect to server')\n ) {\n return true;\n }\n\n // SSL/TLS errors that might be transient\n if (\n message.includes('ssl connection') ||\n message.includes('ssl handshake')\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Calculate delay with exponential backoff and optional jitter\n */\nexport function calculateDelay(\n attempt: number,\n config: Required<Pick<RetryConfig, 'initialDelayMs' | 'maxDelayMs' | 'backoffMultiplier' | 'jitter'>>\n): number {\n // Exponential backoff: initialDelay * (multiplier ^ attempt)\n const exponentialDelay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt);\n\n // Cap at maxDelay\n const cappedDelay = Math.min(exponentialDelay, config.maxDelayMs);\n\n // Add jitter to avoid thundering herd\n if (config.jitter) {\n // Random jitter between 0% and 25% of the delay\n const jitterFactor = 1 + Math.random() * 0.25;\n return Math.floor(cappedDelay * jitterFactor);\n }\n\n return Math.floor(cappedDelay);\n}\n\n/**\n * Sleep for a given number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retry result with metadata\n */\nexport interface RetryResult<T> {\n /** The result value if successful */\n result: T;\n /** Number of attempts made (1 = first try succeeded) */\n attempts: number;\n /** Total time spent including retries in ms */\n totalTimeMs: number;\n}\n\n/**\n * Retry an async operation with exponential backoff\n *\n * @example\n * ```typescript\n * const result = await withRetry(\n * () => pool.connect(),\n * {\n * maxAttempts: 3,\n * initialDelayMs: 100,\n * maxDelayMs: 5000,\n * backoffMultiplier: 2,\n * onRetry: (attempt, error, delay) => {\n * console.log(`Retry ${attempt} after ${delay}ms: ${error.message}`);\n * },\n * }\n * );\n * ```\n */\nexport async function withRetry<T>(\n operation: () => Promise<T>,\n config?: RetryConfig\n): Promise<RetryResult<T>> {\n const retryConfig = {\n maxAttempts: config?.maxAttempts ?? DEFAULT_CONFIG.retry.maxAttempts,\n initialDelayMs: config?.initialDelayMs ?? DEFAULT_CONFIG.retry.initialDelayMs,\n maxDelayMs: config?.maxDelayMs ?? DEFAULT_CONFIG.retry.maxDelayMs,\n backoffMultiplier: config?.backoffMultiplier ?? DEFAULT_CONFIG.retry.backoffMultiplier,\n jitter: config?.jitter ?? DEFAULT_CONFIG.retry.jitter,\n isRetryable: config?.isRetryable ?? isRetryableError,\n onRetry: config?.onRetry,\n };\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < retryConfig.maxAttempts; attempt++) {\n try {\n const result = await operation();\n return {\n result,\n attempts: attempt + 1,\n totalTimeMs: Date.now() - startTime,\n };\n } catch (error) {\n lastError = error as Error;\n\n // Check if this is the last attempt\n const isLastAttempt = attempt >= retryConfig.maxAttempts - 1;\n\n // Check if error is retryable\n if (isLastAttempt || !retryConfig.isRetryable(lastError)) {\n throw lastError;\n }\n\n // Calculate delay for this attempt\n const delay = calculateDelay(attempt, retryConfig);\n\n // Call onRetry hook\n retryConfig.onRetry?.(attempt + 1, lastError, delay);\n\n // Wait before next attempt\n await sleep(delay);\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError ?? new Error('Retry failed with no error');\n}\n\n/**\n * Create a retry wrapper with pre-configured options\n *\n * @example\n * ```typescript\n * const retrier = createRetrier({\n * maxAttempts: 5,\n * initialDelayMs: 200,\n * });\n *\n * // Use the same config for multiple operations\n * const result1 = await retrier(() => connectToDb());\n * const result2 = await retrier(() => fetchData());\n * ```\n */\nexport function createRetrier(config: RetryConfig) {\n return <T>(operation: () => Promise<T>): Promise<RetryResult<T>> => {\n return withRetry(operation, config);\n };\n}\n"]}