Skip to content

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.

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'
});
interface OstrichDBConfig {
baseUrl?: string; // Server URL (default: 'http://localhost:8042')
apiKey?: string; // JWT authentication token
timeout?: number; // Request timeout in milliseconds (default: 30000)
}

OstrichDB uses JWT (JSON Web Token) authentication for API access:

const db = new OstrichDB({
baseUrl: 'https://your-ostrichdb-server.com',
apiKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
});

Update the authentication token after client initialization:

// Initial setup without token
const 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 refreshed
function onTokenRefresh(newToken: string) {
db.setAuthToken(newToken);
}
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;
}
}
development.config.ts
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.config.ts
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
});

Create environment-specific configuration files:

.env.development:

Terminal window
OSTRICHDB_URL=http://localhost:8042
OSTRICHDB_TOKEN=dev-jwt-token-here
OSTRICHDB_TIMEOUT=30000
NODE_ENV=development

.env.production:

Terminal window
OSTRICHDB_URL=https://api.your-domain.com
OSTRICHDB_TOKEN=prod-jwt-token-here
OSTRICHDB_TIMEOUT=10000
NODE_ENV=production

Configuration factory:

config/database.ts
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
});
}

The SDK automatically handles connection pooling, but you can optimize for your use case:

// Single global instance for connection reuse
let 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 application
const db = getDatabase();

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);
}
}
}
config/database.ts
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 connection
export function requireDatabase(req: any, res: any, next: any) {
if (!db.apiKey) {
return res.status(500).json({ error: 'Database not configured' });
}
req.db = db;
next();
}

For App Router:

lib/database.ts
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:

app/api/posts/route.ts
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);
}
hooks/useOstrichDB.ts
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;
}

Configure timeouts based on your application needs:

// Quick operations - short timeout
const quickClient = new OstrichDB({
baseUrl: 'http://localhost:8042',
apiKey: 'your-token',
timeout: 5000 // 5 seconds
});
// Bulk operations - longer timeout
const bulkClient = new OstrichDB({
baseUrl: 'http://localhost:8042',
apiKey: 'your-token',
timeout: 60000 // 60 seconds
});
// Dynamic timeout based on operation
async 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;
}
}

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());
}
}

Never hardcode tokens in client-side code:

// ❌ Bad - token exposed in client bundle
const db = new OstrichDB({
baseUrl: 'https://api.example.com',
apiKey: 'hardcoded-token-here' // Never do this!
});
// ✅ Good - token from secure storage or API
const db = new OstrichDB({
baseUrl: 'https://api.example.com',
apiKey: await getTokenFromSecureStorage()
});

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
});
config/test.ts
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 data
export async function cleanupTestData(db: OstrichDB, projectName: string) {
try {
await db.delete_project(projectName);
} catch (error) {
// Ignore if project doesn't exist
}
}
jest.setup.ts
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;
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);
}
  1. Environment Variables: Use environment variables for sensitive configuration
  2. Validation: Always validate configuration at startup
  3. Defaults: Provide sensible defaults for optional settings
  4. Type Safety: Use TypeScript interfaces for configuration objects
  5. Documentation: Document all configuration options clearly
  1. Never commit tokens: Use environment variables or secure vaults
  2. Use HTTPS: Always use HTTPS in production environments
  3. Token rotation: Implement automatic token refresh mechanisms
  4. Minimal permissions: Use tokens with minimal required permissions
  5. Error handling: Don’t expose sensitive information in error messages
  1. Connection reuse: Use a single client instance across your application
  2. Appropriate timeouts: Set timeouts based on operation complexity
  3. Retry logic: Implement retry mechanisms for transient failures
  4. Health checks: Monitor database connection health
  5. Resource cleanup: Properly clean up resources in tests and shutdown handlers

Now that you understand configuration:

  1. Explore the API Reference - Learn all available methods
  2. Master the Builder Pattern - Use the intuitive chainable API
  3. Framework Integration - See specific framework examples
  4. 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.