Skip to main content
Glama
auth.example.ts8.23 kB
// Database configuration template with environment variable support // // IMPORTANT: Copy this file to auth.ts and customize the database connection // // Steps: // 1. Copy this file: cp src/auth.example.ts src/auth.ts // 2. Update the connectionString below with your PostgreSQL credentials // 3. Adjust connection pool settings if needed // 4. The auth.ts file is already in .gitignore to protect your credentials // 5. You can also use environment variables to override any setting import { DatabaseConfig } from './types.js'; import { ValidationError } from './error-handler.js'; // Environment variable configuration const getEnvVar = (key: string, defaultValue?: string): string => { const value = process.env[key]; if (value === undefined) { if (defaultValue !== undefined) { return defaultValue; } throw new Error(`Required environment variable ${key} is not set`); } return value; }; const getEnvNumber = (key: string, defaultValue: number): number => { const value = process.env[key]; if (value === undefined) { return defaultValue; } const num = Number(value); if (isNaN(num)) { throw new Error(`Environment variable ${key} must be a number`); } return num; }; const getEnvBoolean = (key: string, defaultValue: boolean): boolean => { const value = process.env[key]; if (value === undefined) { return defaultValue; } return value.toLowerCase() === 'true'; }; // Connection string validation export function validateConnectionString(connectionString: string): void { if (!connectionString || typeof connectionString !== 'string') { throw new ValidationError('Connection string must be a non-empty string'); } // Check for basic PostgreSQL connection string format const postgresRegex = /^postgres(ql)?:\/\/([^:]+):([^@]+)@([^:]+):(\d+)\/(.+)$/; if (!postgresRegex.test(connectionString)) { throw new ValidationError( 'Invalid PostgreSQL connection string format. Expected: postgresql://username:password@host:port/database' ); } // Parse and validate components try { const url = new URL(connectionString); // Validate protocol if (!url.protocol.startsWith('postgres')) { throw new ValidationError( 'Connection string must use postgresql:// protocol' ); } // Validate required components if (!url.hostname) { throw new ValidationError('Connection string must include hostname'); } if (!url.port) { throw new ValidationError('Connection string must include port'); } const port = parseInt(url.port, 10); if (isNaN(port) || port < 1 || port > 65535) { throw new ValidationError( 'Port must be a valid number between 1 and 65535' ); } if (!url.pathname || url.pathname === '/') { throw new ValidationError('Connection string must include database name'); } if (!url.username) { throw new ValidationError('Connection string must include username'); } if (!url.password) { throw new ValidationError('Connection string must include password'); } // Validate hostname format const hostnameRegex = /^[a-zA-Z0-9.-]+$/; if (!hostnameRegex.test(url.hostname)) { throw new ValidationError('Invalid hostname format'); } // Validate database name format const dbName = url.pathname.substring(1); // Remove leading slash const dbNameRegex = /^[a-zA-Z0-9_-]+$/; if (!dbNameRegex.test(dbName)) { throw new ValidationError( 'Database name can only contain letters, numbers, underscores, and hyphens' ); } // Validate username format const usernameRegex = /^[a-zA-Z0-9_-]+$/; if (!usernameRegex.test(url.username)) { throw new ValidationError( 'Username can only contain letters, numbers, underscores, and hyphens' ); } } catch (error) { if (error instanceof ValidationError) { throw error; } throw new ValidationError( `Invalid connection string: ${error instanceof Error ? error.message : 'Unknown error'}` ); } } // Validate database configuration export function validateDatabaseConfig(config: DatabaseConfig): void { // Validate connection string validateConnectionString(config.connectionString); // Validate pool settings if (config.max !== undefined) { if (typeof config.max !== 'number' || config.max < 1 || config.max > 100) { throw new ValidationError( 'Pool max connections must be a number between 1 and 100' ); } } if (config.idleTimeoutMillis !== undefined) { if ( typeof config.idleTimeoutMillis !== 'number' || config.idleTimeoutMillis < 1000 ) { throw new ValidationError('Idle timeout must be at least 1000ms'); } } if (config.connectionTimeoutMillis !== undefined) { if ( typeof config.connectionTimeoutMillis !== 'number' || config.connectionTimeoutMillis < 1000 ) { throw new ValidationError('Connection timeout must be at least 1000ms'); } } // Validate SSL configuration if (config.ssl !== undefined) { if (typeof config.ssl !== 'object' || config.ssl === null) { throw new ValidationError('SSL configuration must be an object'); } if ( config.ssl.rejectUnauthorized !== undefined && typeof config.ssl.rejectUnauthorized !== 'boolean' ) { throw new ValidationError('SSL rejectUnauthorized must be a boolean'); } } } // Database configuration with environment variable support const dbConfig: DatabaseConfig = { // PostgreSQL connection string // Can be overridden with DB_CONNECTION_STRING environment variable connectionString: getEnvVar( 'DB_CONNECTION_STRING', 'postgresql://username:password@localhost:5432/database' ), // Connection pool settings max: getEnvNumber('DB_POOL_MAX', 20), // Maximum number of clients in the pool idleTimeoutMillis: getEnvNumber('DB_IDLE_TIMEOUT', 30000), // Close idle clients after 30 seconds connectionTimeoutMillis: getEnvNumber('DB_CONNECTION_TIMEOUT', 2000), // Return an error after 2 seconds if connection could not be established // SSL configuration ssl: process.env.DB_SSL_ENABLED === 'true' ? { rejectUnauthorized: getEnvBoolean( 'DB_SSL_REJECT_UNAUTHORIZED', false ), } : undefined, }; // Validate the database configuration try { validateDatabaseConfig(dbConfig); } catch (error) { console.error('❌ Database configuration validation failed:', error); throw error; } export const DB_CONFIG = dbConfig; // Optional: Provider-specific settings with environment variable support export const PROVIDER_CONFIG = { // Default behavior when no provider is specified defaultBehavior: getEnvVar('DEFAULT_PROVIDER_BEHAVIOR', 'ALL'), // Query all providers by default // Available providers (will be auto-detected from database) availableProviders: [], // Populated at runtime // Provider display names displayNames: { 'deutsche-bank': getEnvVar( 'PROVIDER_DISPLAY_DEUTSCHE_BANK', 'Deutsche Bank' ), tink: getEnvVar('PROVIDER_DISPLAY_TINK', 'Tink'), truelayer: getEnvVar('PROVIDER_DISPLAY_TRUELAYER', 'TrueLayer'), gocardless: getEnvVar('PROVIDER_DISPLAY_GOCARDLESS', 'GoCardless'), }, }; // Application configuration with environment variable support export const APP_CONFIG = { // Server settings port: getEnvNumber('APP_PORT', 3000), host: getEnvVar('APP_HOST', 'localhost'), environment: getEnvVar('NODE_ENV', 'development'), // Logging settings logLevel: getEnvVar('LOG_LEVEL', 'info'), // debug, info, warn, error enableStructuredLogging: getEnvBoolean('ENABLE_STRUCTURED_LOGGING', false), enableQueryLogging: getEnvBoolean('ENABLE_QUERY_LOGGING', false), // Performance settings enableCaching: getEnvBoolean('ENABLE_CACHING', false), enablePerformanceMonitoring: getEnvBoolean( 'ENABLE_PERFORMANCE_MONITORING', true ), // Health check settings healthCheckInterval: getEnvNumber('HEALTH_CHECK_INTERVAL', 30000), // 30 seconds // Security settings enableInputSanitization: getEnvBoolean('ENABLE_INPUT_SANITIZATION', true), };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/radup/mcp-sigmund'

If you have feedback or need assistance with the MCP directory API, please join our Discord server