Skip to content

SDK Integration Examples

This guide provides comprehensive, real-world examples of integrating the Altus 4 TypeScript SDK into various application types and frameworks. Each example includes complete code, error handling, and best practices.

React Application

Complete React application with authentication, search functionality, and analytics dashboard.

Setup and Configuration

typescript
// src/lib/altus4.ts
import { Altus4SDK } from '@altus4/sdk';

export const altus4 = new Altus4SDK({
  baseURL: process.env.REACT_APP_API_URL || 'http://localhost:3000/api/v1',
  timeout: 30000,
  debug: process.env.NODE_ENV === 'development',
});

Authentication Context

typescript
// src/contexts/AuthContext.tsx
import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { altus4 } from '../lib/altus4';
import type { User } from '@altus4/sdk';

interface AuthContextType {
  user: User | null;
  loading: boolean;
  login: (email: string, password: string) => Promise<{ success: boolean; error?: string }>;
  register: (name: string, email: string, password: string) => Promise<{ success: boolean; error?: string }>;
  logout: () => Promise<void>;
  isAuthenticated: boolean;
}

const AuthContext = createContext<AuthContextType | null>(null);

interface AuthProviderProps {
  children: ReactNode;
}

export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    initializeAuth();
  }, []);

  const initializeAuth = async () => {
    try {
      setLoading(true);

      // Try to restore session from cookies
      const restored = await altus4.auth.restoreSession();

      if (restored && altus4.isAuthenticated()) {
        // Fetch user profile
        const userResult = await altus4.getCurrentUser();
        if (userResult.success) {
          setUser(userResult.data || null);
        }
      }
    } catch (error) {
      console.error('Auth initialization failed:', error);
    } finally {
      setLoading(false);
    }
  };

  const login = async (email: string, password: string) => {
    try {
      const result = await altus4.login(email, password);

      if (result.success) {
        setUser(result.user || null);
        return { success: true };
      }

      return {
        success: false,
        error: result.error?.message || 'Login failed',
      };
    } catch (error) {
      console.error('Login error:', error);
      return {
        success: false,
        error: 'Network error. Please try again.',
      };
    }
  };

  const register = async (name: string, email: string, password: string) => {
    try {
      const result = await altus4.register(name, email, password);

      if (result.success) {
        setUser(result.user || null);
        return { success: true };
      }

      return {
        success: false,
        error: result.error?.message || 'Registration failed',
      };
    } catch (error) {
      console.error('Registration error:', error);
      return {
        success: false,
        error: 'Network error. Please try again.',
      };
    }
  };

  const logout = async () => {
    try {
      await altus4.logout();
    } catch (error) {
      console.error('Logout error:', error);
    } finally {
      setUser(null);
    }
  };

  return (
    <AuthContext.Provider
      value={{
        user,
        loading,
        login,
        register,
        logout,
        isAuthenticated: !!user,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within AuthProvider');
  }
  return context;
};

Login Component

typescript
// src/components/Login.tsx
import React, { useState } from 'react';
import { useAuth } from '../contexts/AuthContext';
import { useNavigate } from 'react-router-dom';

export const Login: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const { login } = useAuth();
  const navigate = useNavigate();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError('');
    setLoading(true);

    try {
      const result = await login(email, password);

      if (result.success) {
        navigate('/dashboard');
      } else {
        setError(result.error || 'Login failed');
      }
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="login-container">
      <form onSubmit={handleSubmit} className="login-form">
        <h2>Login to Altus 4</h2>

        {error && (
          <div className="error-message">
            {error}
          </div>
        )}

        <div className="form-group">
          <label htmlFor="email">Email:</label>
          <input
            id="email"
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            required
            disabled={loading}
          />
        </div>

        <div className="form-group">
          <label htmlFor="password">Password:</label>
          <input
            id="password"
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            required
            disabled={loading}
          />
        </div>

        <button type="submit" disabled={loading}>
          {loading ? 'Logging in...' : 'Login'}
        </button>
      </form>
    </div>
  );
};

Dashboard Component

typescript
// src/components/Dashboard.tsx
import React, { useEffect, useState } from 'react';
import { altus4 } from '../lib/altus4';
import { useAuth } from '../contexts/AuthContext';
import type { DashboardAnalytics, DatabaseConnection } from '@altus4/sdk';

export const Dashboard: React.FC = () => {
  const { user, logout } = useAuth();
  const [analytics, setAnalytics] = useState<DashboardAnalytics | null>(null);
  const [databases, setDatabases] = useState<DatabaseConnection[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  useEffect(() => {
    loadDashboardData();
  }, []);

  const loadDashboardData = async () => {
    try {
      setLoading(true);
      setError('');

      // Load analytics and databases in parallel
      const [analyticsResult, databasesResult] = await Promise.all([
        altus4.analytics.getDashboardAnalytics({ period: 'week' }),
        altus4.database.listDatabaseConnections(),
      ]);

      if (analyticsResult.success) {
        setAnalytics(analyticsResult.data || null);
      } else {
        console.error('Failed to load analytics:', analyticsResult.error);
      }

      if (databasesResult.success) {
        setDatabases(databasesResult.data || []);
      } else {
        console.error('Failed to load databases:', databasesResult.error);
      }
    } catch (error) {
      console.error('Dashboard load error:', error);
      setError('Failed to load dashboard data');
    } finally {
      setLoading(false);
    }
  };

  const handleLogout = async () => {
    await logout();
  };

  if (loading) {
    return <div className="loading">Loading dashboard...</div>;
  }

  return (
    <div className="dashboard">
      <header className="dashboard-header">
        <h1>Welcome back, {user?.name}</h1>
        <button onClick={handleLogout} className="logout-button">
          Logout
        </button>
      </header>

      {error && (
        <div className="error-message">{error}</div>
      )}

      <div className="dashboard-content">
        {/* Analytics Overview */}
        {analytics && (
          <div className="analytics-section">
            <h2>Analytics Overview</h2>
            <div className="metrics-grid">
              <div className="metric-card">
                <h3>Total Searches</h3>
                <p className="metric-value">{analytics.totalSearches.toLocaleString()}</p>
              </div>
              <div className="metric-card">
                <h3>Connected Databases</h3>
                <p className="metric-value">{analytics.totalDatabases}</p>
              </div>
              <div className="metric-card">
                <h3>Active Users</h3>
                <p className="metric-value">{analytics.totalUsers}</p>
              </div>
              <div className="metric-card">
                <h3>Avg Response Time</h3>
                <p className="metric-value">{analytics.averageResponseTime}ms</p>
              </div>
            </div>
          </div>
        )}

        {/* Database Connections */}
        <div className="databases-section">
          <h2>Database Connections</h2>
          {databases.length === 0 ? (
            <p>No database connections configured.</p>
          ) : (
            <div className="databases-list">
              {databases.map((db) => (
                <div key={db.id} className="database-card">
                  <h3>{db.name}</h3>
                  <p>{db.host}:{db.port}/{db.database}</p>
                  <span className={`status ${db.status}`}>
                    {db.status}
                  </span>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

Search Component

typescript
// src/components/Search.tsx
import React, { useState } from 'react';
import { altus4 } from '../lib/altus4';

interface SearchResult {
  id: string;
  title: string;
  content: string;
  score: number;
  database: string;
  table: string;
}

export const Search: React.FC = () => {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState<SearchResult[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const handleSearch = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!query.trim()) return;

    try {
      setLoading(true);
      setError('');

      const searchResult = await altus4.database.searchDatabase({
        query: query.trim(),
        mode: 'semantic', // Use AI-enhanced semantic search
        limit: 20,
      });

      if (searchResult.success) {
        setResults(searchResult.data?.results || []);
      } else {
        setError(searchResult.error?.message || 'Search failed');
      }
    } catch (error) {
      console.error('Search error:', error);
      setError('Network error. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="search-container">
      <form onSubmit={handleSearch} className="search-form">
        <div className="search-input-group">
          <input
            type="text"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Search across your databases..."
            disabled={loading}
            className="search-input"
          />
          <button type="submit" disabled={loading || !query.trim()}>
            {loading ? 'Searching...' : 'Search'}
          </button>
        </div>
      </form>

      {error && (
        <div className="error-message">{error}</div>
      )}

      <div className="search-results">
        {results.length === 0 && !loading && (
          <p>No results found. Try a different search term.</p>
        )}

        {results.map((result) => (
          <div key={result.id} className="search-result">
            <h3>{result.title}</h3>
            <p className="result-content">{result.content}</p>
            <div className="result-meta">
              <span className="result-source">
                {result.database}.{result.table}
              </span>
              <span className="result-score">
                Score: {result.score.toFixed(2)}
              </span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

Vue.js Application

Complete Vue 3 application with Composition API.

Setup and Composables

typescript
// src/composables/useAuth.ts
import { ref, computed } from 'vue';
import { altus4 } from '../lib/altus4';
import type { User } from '@altus4/sdk';

const user = ref<User | null>(null);
const loading = ref(false);

export const useAuth = () => {
  const isAuthenticated = computed(() => !!user.value);

  const initializeAuth = async () => {
    loading.value = true;

    try {
      const restored = await altus4.auth.restoreSession();

      if (restored && altus4.isAuthenticated()) {
        const userResult = await altus4.getCurrentUser();
        if (userResult.success) {
          user.value = userResult.data || null;
        }
      }
    } catch (error) {
      console.error('Auth initialization failed:', error);
    } finally {
      loading.value = false;
    }
  };

  const login = async (email: string, password: string) => {
    loading.value = true;

    try {
      const result = await altus4.login(email, password);

      if (result.success) {
        user.value = result.user || null;
        return { success: true };
      }

      return {
        success: false,
        error: result.error?.message || 'Login failed',
      };
    } catch (error) {
      return {
        success: false,
        error: 'Network error. Please try again.',
      };
    } finally {
      loading.value = false;
    }
  };

  const logout = async () => {
    try {
      await altus4.logout();
    } finally {
      user.value = null;
    }
  };

  return {
    user: computed(() => user.value),
    loading: computed(() => loading.value),
    isAuthenticated,
    initializeAuth,
    login,
    logout,
  };
};

Vue Dashboard Component

vue
<!-- src/components/Dashboard.vue -->
<template>
  <div class="dashboard">
    <header class="dashboard-header">
      <h1>Welcome back, {{ user?.name }}</h1>
      <button @click="handleLogout" class="logout-button">
        Logout
      </button>
    </header>

    <div v-if="loading" class="loading">
      Loading dashboard...
    </div>

    <div v-else-if="error" class="error-message">
      {{ error }}
    </div>

    <div v-else class="dashboard-content">
      <!-- Analytics Overview -->
      <section v-if="analytics" class="analytics-section">
        <h2>Analytics Overview</h2>
        <div class="metrics-grid">
          <div class="metric-card">
            <h3>Total Searches</h3>
            <p class="metric-value">{{ analytics.totalSearches.toLocaleString() }}</p>
          </div>
          <div class="metric-card">
            <h3>Connected Databases</h3>
            <p class="metric-value">{{ analytics.totalDatabases }}</p>
          </div>
          <div class="metric-card">
            <h3>Active Users</h3>
            <p class="metric-value">{{ analytics.totalUsers }}</p>
          </div>
          <div class="metric-card">
            <h3>Avg Response Time</h3>
            <p class="metric-value">{{ analytics.averageResponseTime }}ms</p>
          </div>
        </div>
      </section>

      <!-- Database Connections -->
      <section class="databases-section">
        <h2>Database Connections</h2>
        <div v-if="databases.length === 0">
          <p>No database connections configured.</p>
        </div>
        <div v-else class="databases-list">
          <div v-for="db in databases" :key="db.id" class="database-card">
            <h3>{{ db.name }}</h3>
            <p>{{ db.host }}:{{ db.port }}/{{ db.database }}</p>
            <span :class="`status ${db.status}`">
              {{ db.status }}
            </span>
          </div>
        </div>
      </section>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { useAuth } from '../composables/useAuth';
import { altus4 } from '../lib/altus4';
import type { DashboardAnalytics, DatabaseConnection } from '@altus4/sdk';

const router = useRouter();
const { user, logout } = useAuth();

const analytics = ref<DashboardAnalytics | null>(null);
const databases = ref<DatabaseConnection[]>([]);
const loading = ref(true);
const error = ref('');

onMounted(() => {
  loadDashboardData();
});

const loadDashboardData = async () => {
  try {
    loading.value = true;
    error.value = '';

    const [analyticsResult, databasesResult] = await Promise.all([
      altus4.analytics.getDashboardAnalytics({ period: 'week' }),
      altus4.database.listDatabaseConnections(),
    ]);

    if (analyticsResult.success) {
      analytics.value = analyticsResult.data || null;
    }

    if (databasesResult.success) {
      databases.value = databasesResult.data || [];
    }
  } catch (err) {
    console.error('Dashboard load error:', err);
    error.value = 'Failed to load dashboard data';
  } finally {
    loading.value = false;
  }
};

const handleLogout = async () => {
  await logout();
  router.push('/login');
};
</script>

Node.js Express Server

Complete Express.js server with API key authentication and error handling.

Server Setup

typescript
// src/server.ts
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import { Altus4SDK } from '@altus4/sdk';

const app = express();

// Security middleware
app.use(helmet());
app.use(cors({
  origin: process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'],
  credentials: true,
}));

// Rate limiting
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 1000, // Limit each IP to 1000 requests per windowMs
});
app.use('/api', limiter);

app.use(express.json());

// Initialize Altus 4 SDK
const altus4 = new Altus4SDK({
  baseURL: process.env.ALTUS4_API_URL || 'http://localhost:3000/api/v1',
  apiKey: process.env.ALTUS4_API_KEY,
  timeout: 30000,
});

// Middleware to add SDK to request
app.use((req, res, next) => {
  req.altus4 = altus4;
  next();
});

// Health check
app.get('/health', async (req, res) => {
  try {
    const health = await altus4.management.getSystemHealth();
    res.json({ status: 'healthy', altus4: health.success });
  } catch (error) {
    res.status(503).json({ status: 'unhealthy', error: error.message });
  }
});

export default app;

// Type augmentation
declare global {
  namespace Express {
    interface Request {
      altus4: Altus4SDK;
    }
  }
}

Search Routes

typescript
// src/routes/search.ts
import { Router } from 'express';
import { body, query, validationResult } from 'express-validator';

const router = Router();

// Search endpoint with validation
router.post('/search',
  [
    body('query').isString().isLength({ min: 1, max: 500 }),
    body('databases').optional().isArray(),
    body('mode').optional().isIn(['natural', 'boolean', 'semantic']),
    body('limit').optional().isInt({ min: 1, max: 100 }),
  ],
  async (req, res) => {
    try {
      // Check validation errors
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          error: 'Validation failed',
          details: errors.array(),
        });
      }

      const { query, databases, mode = 'semantic', limit = 20 } = req.body;

      const searchResult = await req.altus4.database.searchDatabase({
        query,
        databases,
        mode,
        limit,
      });

      if (searchResult.success) {
        res.json({
          success: true,
          results: searchResult.data?.results || [],
          totalCount: searchResult.data?.totalCount || 0,
          searchTime: searchResult.data?.searchTime || 0,
        });
      } else {
        res.status(400).json({
          success: false,
          error: searchResult.error?.message || 'Search failed',
        });
      }
    } catch (error) {
      console.error('Search error:', error);
      res.status(500).json({
        success: false,
        error: 'Internal server error',
      });
    }
  }
);

// Search suggestions endpoint
router.get('/suggestions',
  [
    query('q').isString().isLength({ min: 1, max: 100 }),
    query('limit').optional().isInt({ min: 1, max: 20 }),
  ],
  async (req, res) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          error: 'Validation failed',
          details: errors.array(),
        });
      }

      const { q: query, limit = 10 } = req.query;

      const suggestionsResult = await req.altus4.database.getSearchSuggestions({
        partial: query as string,
        limit: parseInt(limit as string),
      });

      if (suggestionsResult.success) {
        res.json({
          success: true,
          suggestions: suggestionsResult.data?.suggestions || [],
        });
      } else {
        res.status(400).json({
          success: false,
          error: suggestionsResult.error?.message || 'Failed to get suggestions',
        });
      }
    } catch (error) {
      console.error('Suggestions error:', error);
      res.status(500).json({
        success: false,
        error: 'Internal server error',
      });
    }
  }
);

export default router;

Analytics Routes

typescript
// src/routes/analytics.ts
import { Router } from 'express';
import { query, validationResult } from 'express-validator';

const router = Router();

// Dashboard analytics
router.get('/dashboard',
  [
    query('period').optional().isIn(['day', 'week', 'month', 'year']),
    query('startDate').optional().isISO8601(),
    query('endDate').optional().isISO8601(),
  ],
  async (req, res) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          error: 'Validation failed',
          details: errors.array(),
        });
      }

      const { period = 'week', startDate, endDate } = req.query;

      const analyticsResult = await req.altus4.analytics.getDashboardAnalytics({
        period: period as any,
        startDate: startDate as string,
        endDate: endDate as string,
      });

      if (analyticsResult.success) {
        res.json({
          success: true,
          data: analyticsResult.data,
        });
      } else {
        res.status(400).json({
          success: false,
          error: analyticsResult.error?.message || 'Failed to get analytics',
        });
      }
    } catch (error) {
      console.error('Analytics error:', error);
      res.status(500).json({
        success: false,
        error: 'Internal server error',
      });
    }
  }
);

// Search trends
router.get('/trends',
  [
    query('period').optional().isIn(['day', 'week', 'month', 'year']),
  ],
  async (req, res) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          error: 'Validation failed',
          details: errors.array(),
        });
      }

      const { period = 'week' } = req.query;

      const trendsResult = await req.altus4.analytics.getSearchTrends({
        period: period as any,
      });

      if (trendsResult.success) {
        res.json({
          success: true,
          trends: trendsResult.data || [],
        });
      } else {
        res.status(400).json({
          success: false,
          error: trendsResult.error?.message || 'Failed to get trends',
        });
      }
    } catch (error) {
      console.error('Trends error:', error);
      res.status(500).json({
        success: false,
        error: 'Internal server error',
      });
    }
  }
);

export default router;

Next.js Full-Stack App

Complete Next.js application with API routes and client-side components.

API Route Example

typescript
// pages/api/search.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { Altus4SDK } from '@altus4/sdk';

const altus4 = new Altus4SDK({
  baseURL: process.env.ALTUS4_API_URL!,
  apiKey: process.env.ALTUS4_API_KEY!,
});

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const { query, databases, mode = 'semantic', limit = 20 } = req.body;

    // Validate input
    if (!query || typeof query !== 'string') {
      return res.status(400).json({ error: 'Query is required' });
    }

    const searchResult = await altus4.database.searchDatabase({
      query,
      databases,
      mode,
      limit,
    });

    if (searchResult.success) {
      res.json({
        success: true,
        results: searchResult.data?.results || [],
        totalCount: searchResult.data?.totalCount || 0,
      });
    } else {
      res.status(400).json({
        success: false,
        error: searchResult.error?.message || 'Search failed',
      });
    }
  } catch (error) {
    console.error('API search error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error',
    });
  }
}

Custom Hook for API Calls

typescript
// hooks/useSearch.ts
import { useState, useCallback } from 'react';

interface SearchOptions {
  query: string;
  databases?: string[];
  mode?: 'natural' | 'boolean' | 'semantic';
  limit?: number;
}

export const useSearch = () => {
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const search = useCallback(async (options: SearchOptions) => {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch('/api/search', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(options),
      });

      const data = await response.json();

      if (data.success) {
        setResults(data.results);
      } else {
        setError(data.error || 'Search failed');
      }
    } catch (err) {
      setError('Network error. Please try again.');
    } finally {
      setLoading(false);
    }
  }, []);

  return { results, loading, error, search };
};

Microservices Architecture

Example microservice using the Altus 4 SDK with proper error handling and monitoring.

Search Microservice

typescript
// services/search-service.ts
import { Altus4SDK } from '@altus4/sdk';
import { Logger } from 'winston';

export class SearchMicroservice {
  private altus4: Altus4SDK;
  private logger: Logger;

  constructor(logger: Logger) {
    this.logger = logger;
    this.altus4 = new Altus4SDK({
      baseURL: process.env.ALTUS4_API_URL!,
      apiKey: process.env.ALTUS4_SEARCH_API_KEY!,
      timeout: 10000,
    });
  }

  async performSearch(options: {
    query: string;
    databases?: string[];
    mode?: string;
    limit?: number;
  }): Promise<SearchResult> {
    const startTime = Date.now();

    try {
      this.logger.info('Starting search operation', {
        query: options.query,
        databases: options.databases,
        mode: options.mode,
      });

      const result = await this.altus4.database.searchDatabase(options);

      const duration = Date.now() - startTime;

      if (result.success) {
        this.logger.info('Search completed successfully', {
          duration,
          resultCount: result.data?.results?.length || 0,
        });

        return {
          success: true,
          results: result.data?.results || [],
          totalCount: result.data?.totalCount || 0,
          searchTime: duration,
        };
      } else {
        this.logger.error('Search failed', {
          error: result.error?.message,
          code: result.error?.code,
          duration,
        });

        return {
          success: false,
          error: result.error?.message || 'Search failed',
        };
      }
    } catch (error) {
      const duration = Date.now() - startTime;

      this.logger.error('Search operation failed', {
        error: error.message,
        stack: error.stack,
        duration,
      });

      return {
        success: false,
        error: 'Internal search service error',
      };
    }
  }

  async getHealthStatus(): Promise<{ healthy: boolean; details: any }> {
    try {
      const testResult = await this.altus4.management.testConnection();

      return {
        healthy: testResult.success,
        details: {
          altus4Connection: testResult.success,
          timestamp: new Date().toISOString(),
        },
      };
    } catch (error) {
      return {
        healthy: false,
        details: {
          error: error.message,
          timestamp: new Date().toISOString(),
        },
      };
    }
  }
}

interface SearchResult {
  success: boolean;
  results?: any[];
  totalCount?: number;
  searchTime?: number;
  error?: string;
}

Testing Examples

Comprehensive testing examples for SDK integration.

Unit Tests

typescript
// __tests__/auth.test.ts
import { Altus4SDK } from '@altus4/sdk';

// Mock the SDK
jest.mock('@altus4/sdk');

describe('Authentication', () => {
  let altus4: jest.Mocked<Altus4SDK>;

  beforeEach(() => {
    altus4 = new Altus4SDK() as jest.Mocked<Altus4SDK>;
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should login successfully', async () => {
    const mockUser = {
      id: '1',
      name: 'Test User',
      email: 'test@example.com',
      role: 'user' as const,
      connectedDatabases: [],
      createdAt: new Date(),
      lastActive: new Date(),
    };

    altus4.login.mockResolvedValue({
      success: true,
      user: mockUser,
      token: 'mock-token',
      expiresIn: 3600,
    });

    const result = await altus4.login('test@example.com', 'password');

    expect(result.success).toBe(true);
    expect(result.user).toEqual(mockUser);
    expect(altus4.login).toHaveBeenCalledWith('test@example.com', 'password');
  });

  it('should handle login failure', async () => {
    altus4.login.mockResolvedValue({
      success: false,
      error: {
        code: 'AUTHENTICATION_FAILED',
        message: 'Invalid credentials',
      },
    });

    const result = await altus4.login('test@example.com', 'wrongpassword');

    expect(result.success).toBe(false);
    expect(result.error?.code).toBe('AUTHENTICATION_FAILED');
  });
});

Integration Tests

typescript
// __tests__/search.integration.test.ts
import { Altus4SDK } from '@altus4/sdk';

describe('Search Integration', () => {
  let altus4: Altus4SDK;

  beforeAll(() => {
    altus4 = new Altus4SDK({
      baseURL: process.env.TEST_API_URL,
      apiKey: process.env.TEST_API_KEY,
    });
  });

  it('should perform search with real API', async () => {
    const searchResult = await altus4.database.searchDatabase({
      query: 'test query',
      mode: 'semantic',
      limit: 10,
    });

    expect(searchResult.success).toBe(true);

    if (searchResult.success) {
      expect(Array.isArray(searchResult.data?.results)).toBe(true);
      expect(typeof searchResult.data?.totalCount).toBe('number');
    }
  }, 10000); // 10 second timeout

  it('should handle invalid query gracefully', async () => {
    const searchResult = await altus4.database.searchDatabase({
      query: '', // Invalid empty query
      limit: 10,
    });

    expect(searchResult.success).toBe(false);
    expect(searchResult.error?.code).toBe('VALIDATION_ERROR');
  });
});

React Testing Library Examples

typescript
// __tests__/components/Dashboard.test.tsx
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { Dashboard } from '../src/components/Dashboard';
import { AuthProvider } from '../src/contexts/AuthContext';

// Mock the SDK
jest.mock('../src/lib/altus4');

const renderWithAuth = (component: React.ReactElement) => {
  return render(
    <AuthProvider>
      {component}
    </AuthProvider>
  );
};

describe('Dashboard Component', () => {
  it('should render dashboard with analytics', async () => {
    const mockAnalytics = {
      totalSearches: 1000,
      totalUsers: 50,
      totalDatabases: 5,
      averageResponseTime: 150,
    };

    // Mock SDK responses
    require('../src/lib/altus4').altus4.analytics.getDashboardAnalytics.mockResolvedValue({
      success: true,
      data: mockAnalytics,
    });

    require('../src/lib/altus4').altus4.database.listDatabaseConnections.mockResolvedValue({
      success: true,
      data: [],
    });

    renderWithAuth(<Dashboard />);

    await waitFor(() => {
      expect(screen.getByText('1,000')).toBeInTheDocument(); // Total searches
      expect(screen.getByText('50')).toBeInTheDocument(); // Total users
      expect(screen.getByText('5')).toBeInTheDocument(); // Total databases
      expect(screen.getByText('150ms')).toBeInTheDocument(); // Response time
    });
  });

  it('should handle loading state', () => {
    renderWithAuth(<Dashboard />);

    expect(screen.getByText('Loading dashboard...')).toBeInTheDocument();
  });
});

These examples demonstrate real-world integration patterns for the Altus 4 TypeScript SDK across different frameworks and application types. Each example includes proper error handling, type safety, and best practices for production applications.