UNPKG

@osiris-ai/postgres-sdk

Version:
1,007 lines (1,004 loc) 33.8 kB
import { Pool, Client } from 'pg'; import { z } from 'zod'; import { SecretSharingAuthenticator } from '@osiris-ai/sdk'; // @osiris-ai/postgres-sdk - PostgreSQL SDK for Authentication and API Clients var PostgresDatabaseAdapter = class { pool; schema; config; initialized = false; constructor(config) { this.config = config; this.schema = config.schema || "public"; console.log("\u{1F527} Initializing PostgreSQL adapter with config:", { host: config.host, database: config.database, schema: this.schema }); } async ensureInitialized() { if (this.initialized && this.pool) return; try { this.pool = new Pool({ connectionString: this.config.connectionString, host: this.config.host, port: this.config.port, database: this.config.database, user: this.config.user, password: this.config.password, ssl: this.config.ssl ? { rejectUnauthorized: false } : void 0 }); await this.initialize(); this.initialized = true; } catch (error) { throw new Error( `Failed to initialize PostgreSQL connection: ${error.message}` ); } } async initialize() { try { await this.pool.query(`CREATE SCHEMA IF NOT EXISTS ${this.schema};`); await this.pool.query(` CREATE TABLE IF NOT EXISTS ${this.schema}.connections ( id UUID PRIMARY KEY, name TEXT NOT NULL, description TEXT, package_id TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('active', 'inactive', 'pending')), services TEXT[] NOT NULL DEFAULT '{}', created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), is_direct_auth BOOLEAN NOT NULL DEFAULT TRUE ); `); await this.pool.query(` CREATE TABLE IF NOT EXISTS ${this.schema}.authentications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), connection_id UUID NOT NULL, user_id TEXT NOT NULL, service TEXT NOT NULL, access_token TEXT NOT NULL, refresh_token TEXT, expires_in INTEGER, scope TEXT, token_type TEXT DEFAULT 'bearer', created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), user_info JSONB, UNIQUE(connection_id, service), FOREIGN KEY (connection_id) REFERENCES ${this.schema}.connections(id) ON DELETE CASCADE ); `); await this.pool.query(` CREATE TABLE IF NOT EXISTS ${this.schema}.sessions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), package_id TEXT NOT NULL, name TEXT NOT NULL, description TEXT, created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), expires_at TIMESTAMP WITH TIME ZONE NOT NULL, connected_services JSONB NOT NULL DEFAULT '{}', is_direct_auth BOOLEAN NOT NULL DEFAULT TRUE, status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'expired', 'completed')) ); `); await this.pool.query(` CREATE TABLE IF NOT EXISTS ${this.schema}.secrets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), connection_id UUID NOT NULL, service TEXT NOT NULL, credentials JSONB NOT NULL, created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), UNIQUE(connection_id, service), FOREIGN KEY (connection_id) REFERENCES ${this.schema}.connections(id) ON DELETE CASCADE ); `); await this.pool.query(` CREATE TABLE IF NOT EXISTS ${this.schema}.tokens ( deployment_id TEXT NOT NULL, service TEXT NOT NULL, user_id TEXT NOT NULL, access_token TEXT NOT NULL, refresh_token TEXT, expires_in INTEGER, scope TEXT, token_type TEXT DEFAULT 'bearer', created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), user_info JSONB, PRIMARY KEY (deployment_id, service) ); `); await this.pool.query(` CREATE INDEX IF NOT EXISTS authentications_service_idx ON ${this.schema}.authentications (service); CREATE INDEX IF NOT EXISTS authentications_connection_id_idx ON ${this.schema}.authentications (connection_id); CREATE INDEX IF NOT EXISTS sessions_package_id_idx ON ${this.schema}.sessions (package_id); CREATE INDEX IF NOT EXISTS sessions_expires_at_idx ON ${this.schema}.sessions (expires_at); CREATE INDEX IF NOT EXISTS connections_package_id_idx ON ${this.schema}.connections (package_id); CREATE INDEX IF NOT EXISTS secrets_connection_id_idx ON ${this.schema}.secrets (connection_id); CREATE INDEX IF NOT EXISTS tokens_deployment_id_idx ON ${this.schema}.tokens (deployment_id); `); } catch (error) { console.log("\u274C Database initialization error:", error); throw new Error(`Failed to initialize database schema: ${error.message}`); } } // Authentication management async storeAuthentication(auth) { await this.ensureInitialized(); try { const result = await this.pool.query(` INSERT INTO ${this.schema}.authentications ( connection_id, service, access_token, refresh_token, expires_in, scope, token_type, user_info, user_id ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (connection_id, service) DO UPDATE SET access_token = $3, refresh_token = $4, expires_in = $5, scope = $6, token_type = $7, user_info = $8, user_id = $9, updated_at = NOW() RETURNING * `, [ auth.connectionId, auth.service, auth.token.access_token, auth.token.refresh_token || null, auth.token.expires_in || null, auth.token.scope || null, auth.token.token_type || "bearer", auth.userInfo, auth.token.user_id ]); const row = result.rows[0]; return { id: row.id, connectionId: row.connection_id, service: row.service, token: { access_token: row.access_token, refresh_token: row.refresh_token, expires_in: row.expires_in, scope: row.scope, token_type: row.token_type, user_id: row.user_id }, userInfo: row.user_info, createdAt: row.created_at, updatedAt: row.updated_at }; } catch (error) { throw new Error(`Failed to store authentication: ${error.message}`); } } async updateAuthentication(connectionId, service, updates) { await this.ensureInitialized(); try { const updateFields = ["updated_at = NOW()"]; const values = []; let paramCount = 1; if (updates.token) { if (updates.token.access_token) { updateFields.push(`access_token = $${paramCount}`); values.push(updates.token.access_token); paramCount++; } if (updates.token.refresh_token !== void 0) { updateFields.push(`refresh_token = $${paramCount}`); values.push(updates.token.refresh_token || null); paramCount++; } if (updates.token.expires_in !== void 0) { updateFields.push(`expires_in = $${paramCount}`); values.push(updates.token.expires_in || null); paramCount++; } if (updates.token.scope !== void 0) { updateFields.push(`scope = $${paramCount}`); values.push(updates.token.scope || null); paramCount++; } if (updates.token.token_type) { updateFields.push(`token_type = $${paramCount}`); values.push(updates.token.token_type); paramCount++; } } if (updates.userInfo) { updateFields.push(`user_info = $${paramCount}`); values.push(updates.userInfo); paramCount++; } values.push(connectionId, service); const result = await this.pool.query(` UPDATE ${this.schema}.authentications SET ${updateFields.join(", ")} WHERE connection_id = $${paramCount} AND service = $${paramCount + 1} RETURNING * `, values); if (result.rows.length === 0) { throw new Error(`Authentication with connection ID ${connectionId} and service ${service} not found`); } const row = result.rows[0]; return { id: row.id, connectionId: row.connection_id, service: row.service, token: { access_token: row.access_token, refresh_token: row.refresh_token, expires_in: row.expires_in, scope: row.scope, token_type: row.token_type, user_id: row.user_id }, userInfo: row.user_info, createdAt: row.created_at, updatedAt: row.updated_at }; } catch (error) { throw new Error(`Failed to update authentication: ${error.message}`); } } async getAuthentication(connectionId, service) { await this.ensureInitialized(); try { const result = await this.pool.query(` SELECT * FROM ${this.schema}.authentications WHERE connection_id = $1 AND service = $2 `, [connectionId, service]); if (result.rows.length === 0) { return null; } const row = result.rows[0]; return { id: row.id, connectionId: row.connection_id, service: row.service, token: { access_token: row.access_token, refresh_token: row.refresh_token, expires_in: row.expires_in, scope: row.scope, token_type: row.token_type, user_id: row.user_id }, userInfo: row.user_info, createdAt: row.created_at, updatedAt: row.updated_at }; } catch (error) { throw new Error(`Failed to get authentication: ${error.message}`); } } async getAuthenticationsForConnection(connectionId) { await this.ensureInitialized(); try { const result = await this.pool.query(` SELECT * FROM ${this.schema}.authentications WHERE connection_id = $1 ORDER BY created_at DESC `, [connectionId]); return result.rows.map((row) => ({ id: row.id, connectionId: row.connection_id, service: row.service, token: { access_token: row.access_token, refresh_token: row.refresh_token, expires_in: row.expires_in, scope: row.scope, token_type: row.token_type, user_id: row.user_id }, userInfo: row.user_info, createdAt: row.created_at, updatedAt: row.updated_at })); } catch (error) { throw new Error(`Failed to get authentications for connection: ${error.message}`); } } async deleteAuthentication(id) { await this.ensureInitialized(); try { const result = await this.pool.query(` DELETE FROM ${this.schema}.authentications WHERE id = $1 `, [id]); return result.rowCount > 0; } catch (error) { throw new Error(`Failed to delete authentication: ${error.message}`); } } async getSessions() { await this.ensureInitialized(); const result = await this.pool.query(`SELECT * FROM ${this.schema}.sessions`); return result.rows.map((row) => ({ id: row.id, packageId: row.package_id, name: row.name, description: row.description, createdAt: row.created_at, expiresAt: row.expires_at, connectedServices: row.connected_services, isDirectAuth: row.is_direct_auth, status: row.status })); } // Session management async storeSession(session) { await this.ensureInitialized(); try { const result = await this.pool.query(` INSERT INTO ${this.schema}.sessions ( package_id, name, description, expires_at, connected_services, is_direct_auth, status ) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING * `, [ session.packageId, session.name, session.description || null, session.expiresAt, JSON.stringify(session.connectedServices), session.isDirectAuth, session.status ]); const row = result.rows[0]; return { id: row.id, packageId: row.package_id, name: row.name, description: row.description, createdAt: row.created_at, expiresAt: row.expires_at, connectedServices: row.connected_services, isDirectAuth: row.is_direct_auth, status: row.status }; } catch (error) { throw new Error(`Failed to store session: ${error.message}`); } } async updateSession(id, updates) { await this.ensureInitialized(); try { const updateFields = []; const values = []; let paramCount = 1; if (updates.connectedServices) { updateFields.push(`connected_services = $${paramCount}`); values.push(JSON.stringify(updates.connectedServices)); paramCount++; } if (updates.status) { updateFields.push(`status = $${paramCount}`); values.push(updates.status); paramCount++; } if (updateFields.length === 0) { return this.getSession(id); } values.push(id); const result = await this.pool.query(` UPDATE ${this.schema}.sessions SET ${updateFields.join(", ")} WHERE id = $${paramCount} RETURNING * `, values); if (result.rows.length === 0) { return null; } const row = result.rows[0]; return { id: row.id, packageId: row.package_id, name: row.name, description: row.description, createdAt: row.created_at, expiresAt: row.expires_at, connectedServices: row.connected_services, isDirectAuth: row.is_direct_auth, status: row.status }; } catch (error) { throw new Error(`Failed to update session: ${error.message}`); } } async getSession(id) { await this.ensureInitialized(); try { const result = await this.pool.query(` SELECT * FROM ${this.schema}.sessions WHERE id = $1 `, [id]); if (result.rows.length === 0) { return null; } const row = result.rows[0]; return { id: row.id, packageId: row.package_id, name: row.name, description: row.description, createdAt: row.created_at, expiresAt: row.expires_at, connectedServices: row.connected_services, isDirectAuth: row.is_direct_auth, status: row.status }; } catch (error) { throw new Error(`Failed to get session: ${error.message}`); } } async deleteSession(id) { await this.ensureInitialized(); try { const result = await this.pool.query(` DELETE FROM ${this.schema}.sessions WHERE id = $1 `, [id]); return result.rowCount > 0; } catch (error) { throw new Error(`Failed to delete session: ${error.message}`); } } async cleanupExpiredSessions() { await this.ensureInitialized(); try { const result = await this.pool.query(` DELETE FROM ${this.schema}.sessions WHERE expires_at < NOW() `); return result.rowCount; } catch (error) { throw new Error(`Failed to cleanup expired sessions: ${error.message}`); } } // Connection management async storeConnection(connection) { await this.ensureInitialized(); try { const result = await this.pool.query(` INSERT INTO ${this.schema}.connections ( id, name, description, package_id, status, services, is_direct_auth ) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING * `, [ connection.id, connection.name, connection.description || null, connection.packageId, connection.status, connection.services, connection.isDirectAuth ]); const row = result.rows[0]; return { id: row.id, userId: connection.userId, name: row.name, description: row.description, packageId: row.package_id, status: row.status, services: row.services, createdAt: row.created_at, updatedAt: row.updated_at, isDirectAuth: row.is_direct_auth }; } catch (error) { throw new Error(`Failed to store connection: ${error.message}`); } } async updateConnection(id, updates) { await this.ensureInitialized(); try { const updateFields = ["updated_at = NOW()"]; const values = []; let paramCount = 1; if (updates.name) { updateFields.push(`name = $${paramCount}`); values.push(updates.name); paramCount++; } if (updates.description !== void 0) { updateFields.push(`description = $${paramCount}`); values.push(updates.description || null); paramCount++; } if (updates.status) { updateFields.push(`status = $${paramCount}`); values.push(updates.status); paramCount++; } if (updates.services) { updateFields.push(`services = $${paramCount}`); values.push(updates.services); paramCount++; } values.push(id); const result = await this.pool.query(` UPDATE ${this.schema}.connections SET ${updateFields.join(", ")} WHERE id = $${paramCount} RETURNING * `, values); if (result.rows.length === 0) { throw new Error(`Connection with id ${id} not found`); } const row = result.rows[0]; return { id: row.id, userId: row.user_id, name: row.name, description: row.description, packageId: row.package_id, status: row.status, services: row.services, createdAt: row.created_at, updatedAt: row.updated_at, isDirectAuth: row.is_direct_auth }; } catch (error) { throw new Error(`Failed to update connection: ${error.message}`); } } async getConnection(id) { await this.ensureInitialized(); try { const result = await this.pool.query(` SELECT * FROM ${this.schema}.connections WHERE id = $1 `, [id]); if (result.rows.length === 0) { return null; } const row = result.rows[0]; return { id: row.id, userId: row.user_id, name: row.name, description: row.description, packageId: row.package_id, status: row.status, services: row.services, createdAt: row.created_at, updatedAt: row.updated_at, isDirectAuth: row.is_direct_auth }; } catch (error) { throw new Error(`Failed to get connection: ${error.message}`); } } async getConnectionsForPackage(packageId) { await this.ensureInitialized(); try { const result = await this.pool.query(` SELECT * FROM ${this.schema}.connections WHERE package_id = $1 ORDER BY created_at DESC `, [packageId]); return result.rows.map((row) => ({ id: row.id, userId: row.user_id, name: row.name, description: row.description, packageId: row.package_id, status: row.status, services: row.services, createdAt: row.created_at, updatedAt: row.updated_at, isDirectAuth: row.is_direct_auth })); } catch (error) { throw new Error(`Failed to get connections for package: ${error.message}`); } } async deleteConnection(id) { await this.ensureInitialized(); try { const result = await this.pool.query(` DELETE FROM ${this.schema}.connections WHERE id = $1 `, [id]); return result.rowCount > 0; } catch (error) { throw new Error(`Failed to delete connection: ${error.message}`); } } // Secret management async storeSecret(secret) { await this.ensureInitialized(); try { const result = await this.pool.query(` INSERT INTO ${this.schema}.secrets ( connection_id, service, credentials ) VALUES ($1, $2, $3) ON CONFLICT (connection_id, service) DO UPDATE SET credentials = $3, updated_at = NOW() RETURNING * `, [ secret.connectionId, secret.service, JSON.stringify(secret.credentials) ]); const row = result.rows[0]; return { id: row.id, connectionId: row.connection_id, service: row.service, credentials: row.credentials, createdAt: row.created_at, updatedAt: row.updated_at }; } catch (error) { throw new Error(`Failed to store secret: ${error.message}`); } } async updateSecret(id, updates) { await this.ensureInitialized(); try { const result = await this.pool.query(` UPDATE ${this.schema}.secrets SET credentials = $1, updated_at = NOW() WHERE id = $2 RETURNING * `, [JSON.stringify(updates.credentials), id]); if (result.rows.length === 0) { return null; } const row = result.rows[0]; return { id: row.id, connectionId: row.connection_id, service: row.service, credentials: row.credentials, createdAt: row.created_at, updatedAt: row.updated_at }; } catch (error) { throw new Error(`Failed to update secret: ${error.message}`); } } async getSecretsForConnection(connectionId) { await this.ensureInitialized(); try { const result = await this.pool.query(` SELECT * FROM ${this.schema}.secrets WHERE connection_id = $1 ORDER BY created_at DESC `, [connectionId]); return result.rows.map((row) => ({ id: row.id, connectionId: row.connection_id, service: row.service, credentials: row.credentials, createdAt: row.created_at, updatedAt: row.updated_at })); } catch (error) { throw new Error(`Failed to get secrets for connection: ${error.message}`); } } async getSecret(connectionId, service) { await this.ensureInitialized(); try { const result = await this.pool.query(` SELECT * FROM ${this.schema}.secrets WHERE connection_id = $1 AND service = $2 `, [connectionId, service]); if (result.rows.length === 0) { return null; } const row = result.rows[0]; return { id: row.id, connectionId: row.connection_id, service: row.service, credentials: row.credentials, createdAt: row.created_at, updatedAt: row.updated_at }; } catch (error) { throw new Error(`Failed to get secret: ${error.message}`); } } async deleteSecret(id) { await this.ensureInitialized(); try { const result = await this.pool.query(` DELETE FROM ${this.schema}.secrets WHERE id = $1 `, [id]); return result.rowCount > 0; } catch (error) { throw new Error(`Failed to delete secret: ${error.message}`); } } // Legacy methods for backward compatibility async storeTokenForService(deploymentId, service, token, userInfo) { await this.ensureInitialized(); try { if (!deploymentId || !service || !token.access_token) { throw new Error("deploymentId, service, and access_token are required"); } await this.pool.query(` INSERT INTO ${this.schema}.tokens ( deployment_id, service, user_id, access_token, refresh_token, expires_in, scope, token_type, user_info ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (deployment_id, service) DO UPDATE SET user_id = $3, access_token = $4, refresh_token = $5, expires_in = $6, scope = $7, token_type = $8, updated_at = NOW(), user_info = $9 `, [ deploymentId, service, token.user_id, token.access_token, token.refresh_token || null, token.expires_in || null, token.scope || null, token.token_type || "bearer", userInfo ]); } catch (error) { throw new Error(`Failed to store token for deployment ${deploymentId}, service ${service}: ${error.message}`); } } async updateTokenForService(deploymentId, service, token, userInfo) { await this.ensureInitialized(); try { if (!deploymentId || !service) { throw new Error("deploymentId and service are required"); } if (!token && !userInfo) { await this.pool.query(` DELETE FROM ${this.schema}.tokens WHERE deployment_id = $1 AND service = $2 `, [deploymentId, service]); return; } const updateFields = ["updated_at = NOW()"]; const values = []; let paramCount = 1; if (token) { if (token.access_token) { updateFields.push(`access_token = $${paramCount}`); values.push(token.access_token); paramCount++; } if (token.refresh_token !== void 0) { updateFields.push(`refresh_token = $${paramCount}`); values.push(token.refresh_token || null); paramCount++; } if (token.expires_in !== void 0) { updateFields.push(`expires_in = $${paramCount}`); values.push(token.expires_in || null); paramCount++; } if (token.scope !== void 0) { updateFields.push(`scope = $${paramCount}`); values.push(token.scope || null); paramCount++; } if (token.token_type) { updateFields.push(`token_type = $${paramCount}`); values.push(token.token_type); paramCount++; } if (token.user_id) { updateFields.push(`user_id = $${paramCount}`); values.push(token.user_id); paramCount++; } } if (userInfo) { updateFields.push(`user_info = $${paramCount}`); values.push(userInfo); paramCount++; } values.push(deploymentId); values.push(service); await this.pool.query(` UPDATE ${this.schema}.tokens SET ${updateFields.join(", ")} WHERE deployment_id = $${paramCount} AND service = $${paramCount + 1} `, values); } catch (error) { throw new Error(`Failed to update token for deployment ${deploymentId}, service ${service}: ${error.message}`); } } async getTokensForDeployment(deploymentId) { await this.ensureInitialized(); try { if (!deploymentId) { throw new Error("deploymentId is required"); } const result = await this.pool.query(` SELECT * FROM ${this.schema}.tokens WHERE deployment_id = $1 `, [deploymentId]); const tokens = /* @__PURE__ */ new Map(); for (const row of result.rows) { tokens.set(row.service, { access_token: row.access_token, refresh_token: row.refresh_token, expires_in: row.expires_in, scope: row.scope, token_type: row.token_type, user_id: row.user_id }); } return tokens; } catch (error) { throw new Error(`Failed to get tokens for deployment ${deploymentId}: ${error.message}`); } } async getTokenForService(deploymentId, service) { await this.ensureInitialized(); try { if (!deploymentId || !service) { throw new Error("deploymentId and service are required"); } const result = await this.pool.query(` SELECT * FROM ${this.schema}.tokens WHERE deployment_id = $1 AND service = $2 `, [deploymentId, service]); if (result.rows.length === 0) { return null; } const row = result.rows[0]; return { access_token: row.access_token, refresh_token: row.refresh_token, expires_in: row.expires_in, scope: row.scope, token_type: row.token_type, user_id: row.user_id }; } catch (error) { throw new Error(`Failed to get token for deployment ${deploymentId}, service ${service}: ${error.message}`); } } async close() { try { if (this.pool) { await this.pool.end(); this.pool = null; this.initialized = false; } } catch (error) { throw new Error(`Failed to close database connection: ${error.message}`); } } }; var PostgresSecretSchema = z.object({ db_url: z.string().url({ message: "Invalid database URL format" }) }); var PostgresSecretSharingAuthenticator = class extends SecretSharingAuthenticator { secrets = null; constructor() { super("postgres", PostgresSecretSchema); } set(secrets) { const result = PostgresSecretSchema.safeParse(secrets); if (!result.success) { return false; } this.secrets = result.data; return true; } getDbUrl() { return this.secrets?.db_url ?? null; } /** * Execute SQL queries against the PostgreSQL database * @param params Action parameters containing SQL query * @param secrets Database connection secrets * @returns Query results or error response */ async action(params, secrets) { if (!params.data) { return { status: 400, statusText: "No data provided", data: null }; } const sql = params.data.sql; const queryParams = params.data.params; if (!sql || !queryParams) { return { status: 400, statusText: "No SQL query provided", data: null }; } const validation = this.validateSql(sql); if (!validation.isValid) { return { status: 400, statusText: validation.error || "Invalid SQL query", data: null }; } if (!this.secrets?.db_url) { return { status: 400, statusText: "No database connection configured", data: null }; } const client = new Client({ connectionString: this.secrets.db_url }); try { await client.connect(); const result = await client.query(sql, queryParams); await client.end(); return { status: 200, statusText: "OK", data: { rows: result.rows, rowCount: result.rowCount, command: result.command }, headers: {} }; } catch (error) { await client.end().catch(() => { }); return { status: 500, statusText: error.message || "Database query failed", data: null }; } } /** * Validate SQL query for safety (basic checks) * @param sql SQL query to validate * @returns true if query appears safe */ validateSql(sql) { const trimmedSql = sql.trim().toLowerCase(); const dangerousPatterns = [ /^\s*drop\s+/, /^\s*delete\s+.*\s+where\s+1\s*=\s*1/, /^\s*truncate\s+/, /^\s*alter\s+/, /;\s*drop\s+/, /;\s*delete\s+/, /;\s*truncate\s+/ ]; for (const pattern of dangerousPatterns) { if (pattern.test(trimmedSql)) { return { isValid: false, error: "SQL query contains potentially dangerous operations" }; } } return { isValid: true }; } }; export { PostgresDatabaseAdapter, PostgresSecretSharingAuthenticator }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map