SDK Configuration
SDK Configuration
Section titled “SDK Configuration”The OstrichDB SDK provides flexible configuration options to suit different environments and use cases. This guide covers all configuration options, authentication methods, and environment-specific setups.
Basic Configuration
Section titled “Basic Configuration”Client Initialization
Section titled “Client Initialization”The most basic configuration requires only the server URL and authentication token:
import OstrichDB from 'ostrichdb-js';
const db = new OstrichDB({ baseUrl: 'http://localhost:8042', apiKey: 'your-jwt-token-here'});
Configuration Options
Section titled “Configuration Options”interface OstrichDBConfig { baseUrl?: string; // Server URL (default: 'http://localhost:8042') apiKey?: string; // JWT authentication token timeout?: number; // Request timeout in milliseconds (default: 30000)}
Authentication
Section titled “Authentication”JWT Token Authentication
Section titled “JWT Token Authentication”OstrichDB uses JWT (JSON Web Token) authentication for API access:
const db = new OstrichDB({ baseUrl: 'https://your-ostrichdb-server.com', apiKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'});
Dynamic Token Updates
Section titled “Dynamic Token Updates”Update the authentication token after client initialization:
// Initial setup without tokenconst db = new OstrichDB({ baseUrl: 'https://your-ostrichdb-server.com'});
// Set token later (e.g., after user login)db.setAuthToken('new-jwt-token-here');
// Update token when refreshedfunction onTokenRefresh(newToken: string) { db.setAuthToken(newToken);}
Token Management Example
Section titled “Token Management Example”class TokenManager { private db: OstrichDB; private refreshTimer?: NodeJS.Timeout;
constructor(baseUrl: string) { this.db = new OstrichDB({ baseUrl }); }
async login(username: string, password: string) { // Login via your authentication service const response = await fetch(`${this.db.baseUrl}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) });
const { token, expiresIn } = await response.json();
// Set the token in the SDK this.db.setAuthToken(token);
// Set up automatic refresh this.scheduleTokenRefresh(expiresIn);
return token; }
private scheduleTokenRefresh(expiresIn: number) { // Refresh token 5 minutes before expiry const refreshTime = (expiresIn - 300) * 1000;
this.refreshTimer = setTimeout(async () => { try { const newToken = await this.refreshToken(); this.db.setAuthToken(newToken); } catch (error) { console.error('Token refresh failed:', error); // Handle refresh failure (e.g., redirect to login) } }, refreshTime); }
private async refreshToken(): Promise<string> { // Implement token refresh logic const response = await fetch(`${this.db.baseUrl}/auth/refresh`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.db.apiKey}` } });
const { token, expiresIn } = await response.json(); this.scheduleTokenRefresh(expiresIn);
return token; }
getClient(): OstrichDB { return this.db; }}
Environment Configuration
Section titled “Environment Configuration”Development Environment
Section titled “Development Environment”import OstrichDB from 'ostrichdb-js';
export const createDevClient = () => new OstrichDB({ baseUrl: 'http://localhost:8042', apiKey: process.env.DEV_OSTRICHDB_TOKEN, timeout: 30000 // Longer timeout for debugging});
Production Environment
Section titled “Production Environment”import OstrichDB from 'ostrichdb-js';
export const createProdClient = () => new OstrichDB({ baseUrl: process.env.OSTRICHDB_URL, // HTTPS URL apiKey: process.env.OSTRICHDB_TOKEN, // Production token timeout: 10000 // Shorter timeout for performance});
Environment Variables
Section titled “Environment Variables”Create environment-specific configuration files:
.env.development:
OSTRICHDB_URL=http://localhost:8042OSTRICHDB_TOKEN=dev-jwt-token-hereOSTRICHDB_TIMEOUT=30000NODE_ENV=development
.env.production:
OSTRICHDB_URL=https://api.your-domain.comOSTRICHDB_TOKEN=prod-jwt-token-hereOSTRICHDB_TIMEOUT=10000NODE_ENV=production
Configuration factory:
import OstrichDB from 'ostrichdb-js';
interface ConfigOptions { development: { baseUrl: string; timeout: number; }; production: { baseUrl: string; timeout: number; }; test: { baseUrl: string; timeout: number; };}
const config: ConfigOptions = { development: { baseUrl: 'http://localhost:8042', timeout: 30000 }, production: { baseUrl: process.env.OSTRICHDB_URL!, timeout: 10000 }, test: { baseUrl: 'http://localhost:8043', // Test server timeout: 5000 }};
export function createOstrichDBClient(apiKey?: string): OstrichDB { const env = process.env.NODE_ENV as keyof ConfigOptions || 'development'; const envConfig = config[env];
return new OstrichDB({ baseUrl: envConfig.baseUrl, apiKey: apiKey || process.env.OSTRICHDB_TOKEN, timeout: envConfig.timeout });}
Connection Management
Section titled “Connection Management”Connection Pooling
Section titled “Connection Pooling”The SDK automatically handles connection pooling, but you can optimize for your use case:
// Single global instance for connection reuselet dbInstance: OstrichDB | null = null;
export function getDatabase(): OstrichDB { if (!dbInstance) { dbInstance = new OstrichDB({ baseUrl: process.env.OSTRICHDB_URL, apiKey: process.env.OSTRICHDB_TOKEN, timeout: 15000 }); } return dbInstance;}
// Usage across your applicationconst db = getDatabase();
Health Checks
Section titled “Health Checks”Implement health checks to monitor connection status:
class DatabaseHealth { private db: OstrichDB; private healthCheckInterval?: NodeJS.Timeout;
constructor(db: OstrichDB) { this.db = db; this.startHealthChecks(); }
async checkHealth(): Promise<boolean> { try { await this.db.health_check(); return true; } catch (error) { console.error('Database health check failed:', error); return false; } }
private startHealthChecks() { this.healthCheckInterval = setInterval(async () => { const isHealthy = await this.checkHealth();
if (!isHealthy) { // Handle unhealthy database connection console.warn('Database connection unhealthy'); // Optionally attempt reconnection or alert monitoring systems } }, 60000); // Check every minute }
stopHealthChecks() { if (this.healthCheckInterval) { clearInterval(this.healthCheckInterval); } }}
Framework-Specific Configuration
Section titled “Framework-Specific Configuration”Express.js Configuration
Section titled “Express.js Configuration”import OstrichDB from 'ostrichdb-js';
export const db = new OstrichDB({ baseUrl: process.env.OSTRICHDB_URL || 'http://localhost:8042', apiKey: process.env.OSTRICHDB_TOKEN, timeout: 15000});
// Middleware for database connectionexport function requireDatabase(req: any, res: any, next: any) { if (!db.apiKey) { return res.status(500).json({ error: 'Database not configured' }); } req.db = db; next();}
Next.js Configuration
Section titled “Next.js Configuration”For App Router:
import OstrichDB from 'ostrichdb-js';
class DatabaseManager { private static instance: OstrichDB;
static getInstance(): OstrichDB { if (!DatabaseManager.instance) { DatabaseManager.instance = new OstrichDB({ baseUrl: process.env.OSTRICHDB_URL!, apiKey: process.env.OSTRICHDB_TOKEN!, timeout: 10000 }); } return DatabaseManager.instance; }
static updateToken(token: string) { if (DatabaseManager.instance) { DatabaseManager.instance.setAuthToken(token); } }}
export default DatabaseManager;
Usage in API routes:
import { NextRequest, NextResponse } from 'next/server';import DatabaseManager from '@/lib/database';
export async function GET(request: NextRequest) { const db = DatabaseManager.getInstance();
// Use the database const posts = await db.list_records('blog', 'posts', 'published');
return NextResponse.json(posts);}
React Configuration (Client-Side)
Section titled “React Configuration (Client-Side)”import { useState, useEffect, createContext, useContext } from 'react';import OstrichDB from 'ostrichdb-js';
interface DatabaseContextType { db: OstrichDB | null; isConnected: boolean; error: string | null;}
const DatabaseContext = createContext<DatabaseContextType>({ db: null, isConnected: false, error: null});
export function DatabaseProvider({ children, apiKey }: { children: React.ReactNode, apiKey: string }) { const [db, setDb] = useState<OstrichDB | null>(null); const [isConnected, setIsConnected] = useState(false); const [error, setError] = useState<string | null>(null);
useEffect(() => { const initDatabase = async () => { try { const client = new OstrichDB({ baseUrl: process.env.REACT_APP_OSTRICHDB_URL || 'http://localhost:8042', apiKey: apiKey, timeout: 10000 });
// Test connection await client.health_check();
setDb(client); setIsConnected(true); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Connection failed'); setIsConnected(false); } };
if (apiKey) { initDatabase(); } }, [apiKey]);
return ( <DatabaseContext.Provider value={{ db, isConnected, error }}> {children} </DatabaseContext.Provider> );}
export function useOstrichDB() { const context = useContext(DatabaseContext); if (!context) { throw new Error('useOstrichDB must be used within a DatabaseProvider'); } return context;}
Timeout Configuration
Section titled “Timeout Configuration”Request Timeouts
Section titled “Request Timeouts”Configure timeouts based on your application needs:
// Quick operations - short timeoutconst quickClient = new OstrichDB({ baseUrl: 'http://localhost:8042', apiKey: 'your-token', timeout: 5000 // 5 seconds});
// Bulk operations - longer timeoutconst bulkClient = new OstrichDB({ baseUrl: 'http://localhost:8042', apiKey: 'your-token', timeout: 60000 // 60 seconds});
// Dynamic timeout based on operationasync function performOperation(operationType: 'quick' | 'bulk') { const client = operationType === 'quick' ? quickClient : bulkClient;
try { // Perform database operation const result = await client.list_projects(); return result; } catch (error) { if (error.message.includes('timeout')) { console.warn(`${operationType} operation timed out`); } throw error; }}
Retry Configuration
Section titled “Retry Configuration”Implement retry logic for failed requests:
class RetryableOstrichDB { private client: OstrichDB; private maxRetries: number; private retryDelay: number;
constructor(config: any, maxRetries = 3, retryDelay = 1000) { this.client = new OstrichDB(config); this.maxRetries = maxRetries; this.retryDelay = retryDelay; }
async withRetry<T>(operation: () => Promise<T>): Promise<T> { let lastError: any;
for (let attempt = 1; attempt <= this.maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error;
if (attempt === this.maxRetries) { break; }
// Only retry on network or timeout errors if (this.isRetryableError(error)) { await this.sleep(this.retryDelay * attempt); continue; } else { break; } } }
throw lastError; }
private isRetryableError(error: any): boolean { return error.message?.includes('timeout') || error.message?.includes('network') || error.statusCode >= 500; }
private sleep(ms: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); }
// Wrap common operations with retry logic async create_project(name: string) { return this.withRetry(() => this.client.create_project(name)); }
async list_projects() { return this.withRetry(() => this.client.list_projects()); }}
Security Configuration
Section titled “Security Configuration”Secure Token Storage
Section titled “Secure Token Storage”Never hardcode tokens in client-side code:
// ❌ Bad - token exposed in client bundleconst db = new OstrichDB({ baseUrl: 'https://api.example.com', apiKey: 'hardcoded-token-here' // Never do this!});
// ✅ Good - token from secure storage or APIconst db = new OstrichDB({ baseUrl: 'https://api.example.com', apiKey: await getTokenFromSecureStorage()});
HTTPS Configuration
Section titled “HTTPS Configuration”Always use HTTPS in production:
const isProduction = process.env.NODE_ENV === 'production';
const db = new OstrichDB({ baseUrl: isProduction ? 'https://your-secure-domain.com' // HTTPS for production : 'http://localhost:8042', // HTTP OK for development apiKey: process.env.OSTRICHDB_TOKEN, timeout: 15000});
Testing Configuration
Section titled “Testing Configuration”Test Environment Setup
Section titled “Test Environment Setup”import OstrichDB from 'ostrichdb-js';
export function createTestClient(): OstrichDB { return new OstrichDB({ baseUrl: process.env.TEST_OSTRICHDB_URL || 'http://localhost:8043', apiKey: process.env.TEST_OSTRICHDB_TOKEN || 'test-token', timeout: 5000 // Short timeout for tests });}
// Clean up test dataexport async function cleanupTestData(db: OstrichDB, projectName: string) { try { await db.delete_project(projectName); } catch (error) { // Ignore if project doesn't exist }}
Jest Configuration
Section titled “Jest Configuration”import { createTestClient, cleanupTestData } from './config/test';
let testDb: OstrichDB;
beforeAll(async () => { testDb = createTestClient();
// Wait for database to be ready await testDb.health_check();});
afterEach(async () => { // Clean up after each test const projects = await testDb.list_projects(); for (const project of projects) { if (project.name.startsWith('test-')) { await cleanupTestData(testDb, project.name); } }});
// Make test client available globally(global as any).testDb = testDb;
Configuration Validation
Section titled “Configuration Validation”Runtime Validation
Section titled “Runtime Validation”import OstrichDB from 'ostrichdb-js';
interface ValidatedConfig { baseUrl: string; apiKey: string; timeout: number;}
function validateConfig(config: Partial<ValidatedConfig>): ValidatedConfig { const errors: string[] = [];
if (!config.baseUrl) { errors.push('baseUrl is required'); } else if (!config.baseUrl.match(/^https?:\/\//)) { errors.push('baseUrl must be a valid HTTP/HTTPS URL'); }
if (!config.apiKey) { errors.push('apiKey is required'); } else if (typeof config.apiKey !== 'string' || config.apiKey.length < 10) { errors.push('apiKey must be a valid JWT token'); }
if (config.timeout && typeof config.timeout !== 'number') { errors.push('timeout must be a number'); }
if (errors.length > 0) { throw new Error(`Configuration validation failed: ${errors.join(', ')}`); }
return { baseUrl: config.baseUrl!, apiKey: config.apiKey!, timeout: config.timeout || 30000 };}
export function createValidatedClient(config: Partial<ValidatedConfig>): OstrichDB { const validatedConfig = validateConfig(config); return new OstrichDB(validatedConfig);}
Best Practices
Section titled “Best Practices”Configuration Management
Section titled “Configuration Management”- Environment Variables: Use environment variables for sensitive configuration
- Validation: Always validate configuration at startup
- Defaults: Provide sensible defaults for optional settings
- Type Safety: Use TypeScript interfaces for configuration objects
- Documentation: Document all configuration options clearly
Security Best Practices
Section titled “Security Best Practices”- Never commit tokens: Use environment variables or secure vaults
- Use HTTPS: Always use HTTPS in production environments
- Token rotation: Implement automatic token refresh mechanisms
- Minimal permissions: Use tokens with minimal required permissions
- Error handling: Don’t expose sensitive information in error messages
Performance Optimization
Section titled “Performance Optimization”- Connection reuse: Use a single client instance across your application
- Appropriate timeouts: Set timeouts based on operation complexity
- Retry logic: Implement retry mechanisms for transient failures
- Health checks: Monitor database connection health
- Resource cleanup: Properly clean up resources in tests and shutdown handlers
Next Steps
Section titled “Next Steps”Now that you understand configuration:
- Explore the API Reference - Learn all available methods
- Master the Builder Pattern - Use the intuitive chainable API
- Framework Integration - See specific framework examples
- Error Handling - Implement robust error management
Proper configuration is crucial for reliable, secure, and performant applications. Take time to set up your configuration correctly for each environment.