UNPKG

sjursen-digital-watchtower

Version:

A TypeScript Node.js SDK for Watchtower, an Intelligence as a Service (IaaS) platform that uses Google's Gemini AI model to transform traditional logging into an active intelligence system with predictive analytics and automated decision-making capabiliti

971 lines (743 loc) 21.9 kB
# Watchtower Node.js SDK Documentation ## Introduction The Watchtower Node.js SDK provides a convenient way to interact with the Watchtower API for logging, metrics, analysis, and more. This SDK is designed to be used in Node.js environments. ## Installation To install the SDK, run the following command in your project directory: ```bash npm install sjursen-digital-watchtower ``` ## Initialization Import and initialize the SDK with your API base URL: ```typescript import { WatchtowerSDK } from 'sjursen-digital-watchtower'; const sdk = new WatchtowerSDK('YOUR_API_BASE_URL'); ``` Replace `YOUR_API_BASE_URL` with the actual base URL of the Watchtower API. ## Endpoints The SDK organizes API endpoints into logical categories: ### 1. Health Endpoint Check the health of the API. #### `health.check()` `GET /api/health` Checks if the API is reachable and operational. ```typescript async check(): Promise<any> ``` **Example:** ```typescript try { const healthStatus = await sdk.health.check(); console.log('API Health Status:', healthStatus); } catch (error) { console.error('Failed to check API health:', error); } ``` ### 2. API Key Endpoints Manage API keys for organizations, apps, and tenants. #### `apikey.createOrganization(data)` `POST /api/apikey/org` Creates a new organization and returns the API key. ```typescript async createOrganization(data: CreateOrganizationRequest): Promise<APIKey> ``` **Request Interface (`CreateOrganizationRequest`):** ```typescript interface CreateOrganizationRequest { // ... organization details ... } ``` **Response Interface (`APIKey`):** ```typescript interface APIKey { organization_apikey: string; } ``` **Example:** ```typescript try { const apiKey = await sdk.apikey.createOrganization({ // organization details }); console.log('New Organization API Key:', apiKey.organization_apikey); } catch (error) { console.error('Failed to create organization:', error); } ``` #### `apikey.createApp(data)` `POST /api/apikey/app` Creates a new app and returns the app API key. ```typescript async createApp(data: CreateAppRequest): Promise<AppAPIKey> ``` **Request Interface (`CreateAppRequest`):** ```typescript interface CreateAppRequest { organization_apikey: string; // ... app details ... } ``` **Response Interface (`AppAPIKey`):** ```typescript interface AppAPIKey { app_apikey: string; } ``` **Example:** ```typescript try { const appApiKey = await sdk.apikey.createApp({ organization_apikey: 'YOUR_ORG_API_KEY', // app details }); console.log('New App API Key:', appApiKey.app_apikey); } catch (error) { console.error('Failed to create app:', error); } ``` #### `apikey.createTenant(data)` `POST /api/apikey/tenant` Creates a new tenant and returns the tenant API key. ```typescript async createTenant(data: CreateTenantRequest): Promise<TenantAPIKey> ``` **Request Interface (`CreateTenantRequest`):** ```typescript interface CreateTenantRequest { organization_apikey: string; app_apikey: string; // ... tenant details ... } ``` **Response Interface (`TenantAPIKey`):** ```typescript interface TenantAPIKey { tenant_apikey: string; } ``` **Example:** ```typescript try { const tenantApiKey = await sdk.apikey.createTenant({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', // tenant details }); console.log('New Tenant API Key:', tenantApiKey.tenant_apikey); } catch (error) { console.error('Failed to create tenant:', error); } ``` #### `apikey.rollAPIKey(data)` `POST /api/apikey/roll` Rolls (rotates) an existing API key. ```typescript async rollAPIKey(data: RollAPIKeyRequest): Promise<RolledAPIKey> ``` **Request Interface (`RollAPIKeyRequest`):** ```typescript interface RollAPIKeyRequest { organization_apikey: string; // ... key details to roll ... } ``` **Response Interface (`RolledAPIKey`):** ```typescript interface RolledAPIKey { // ... new key details ... } ``` **Example:** ```typescript try { const rolledKey = await sdk.apikey.rollAPIKey({ organization_apikey: 'YOUR_ORG_API_KEY', // key details to roll }); console.log('Rolled API Key:', rolledKey); } catch (error) { console.error('Failed to roll API key:', error); } ``` ### JWT-based API Key Endpoints These endpoints allow you to create API keys using a Supabase JWT token for authentication. Use these if you want to manage API keys with user-level permissions and JWT-based auth. #### `apikey.createOrgKey(organizationId, jwtToken)` `POST /api/apikey/org/jwt` Creates a new API key for an existing organization using a Supabase JWT token. ```typescript async createOrgKey(organizationId: string, jwtToken: string): Promise<APIKeyResponse> ``` **Parameters:** - `organizationId` (string): The ID of the existing organization - `jwtToken` (string): A valid Supabase JWT token (must be included in the Authorization header) **Returns:** - `Promise<APIKeyResponse>` **Example:** ```typescript const apiKey = await sdk.apikey.createOrgKey('org_123', 'your_jwt_token'); console.log('New Org API Key:', apiKey.key); ``` #### `apikey.createAppKey(appName, tenancyModel, jwtToken)` `POST /api/apikey/app/jwt` Creates a new API key for an app in the user's organization using a Supabase JWT token. ```typescript async createAppKey(appName: string, tenancyModel: 'single' | 'multi', jwtToken: string): Promise<APIKeyResponse> ``` **Parameters:** - `appName` (string): Name of the app - `tenancyModel` ('single' | 'multi'): App's tenancy model - `jwtToken` (string): A valid Supabase JWT token (must be included in the Authorization header) **Returns:** - `Promise<APIKeyResponse>` **Example:** ```typescript const apiKey = await sdk.apikey.createAppKey('My App', 'multi', 'your_jwt_token'); console.log('New App API Key:', apiKey.key); ``` **Notes:** - JWT tokens must be obtained from Supabase Auth and included as `Bearer <token>` in the Authorization header. - These endpoints require the user to have appropriate permissions (e.g., 'admin' or 'owner' role). - API keys are only returned once upon creation. Store them securely. - All timestamps are in UTC (ISO 8601 format). **Error Handling:** - `400 Bad Request`: Missing required fields or invalid request - `401 Unauthorized`: Missing or invalid JWT token - `403 Forbidden`: Insufficient permissions - `404 Not Found`: Organization not found - `500 Internal Server Error`: Server/database error ### 3. Logs Endpoints Manage log entries. #### `logs.createLog(data)` `POST /api/logs` Creates a new log entry. ```typescript async createLog(data: CreateLogRequest): Promise<void> ``` **Request Interface (`CreateLogRequest`):** ```typescript interface CreateLogRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; item_id: string; timestamp: string; // ISO 8601 level: string; message: string; context?: Record<string, any>; metadata?: Record<string, any>; } ``` **Example:** ```typescript try { await sdk.logs.createLog({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', item_id: 'item123', timestamp: new Date().toISOString(), level: 'info', message: 'User logged in', context: { userId: 'user456' }, }); console.log('Log created successfully'); } catch (error) { console.error('Failed to create log:', error); } ``` #### `logs.getLogs(data)` `GET /api/logs` Retrieves log entries with filtering options. ```typescript async getLogs(data: GetLogsRequest): Promise<GetLogsResponse> ``` **Request Interface (`GetLogsRequest`):** ```typescript interface GetLogsRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; item_id?: string; level?: string; after?: string; // ISO 8601 before?: string; // ISO 8601 limit?: number; offset?: number; } ``` **Response Interface (`GetLogsResponse`):** ```typescript interface GetLogsResponse { logs: Array<{ // log entry details }>; } ``` **Example:** ```typescript try { const logs = await sdk.logs.getLogs({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', item_id: 'item123', level: 'error', after: '2023-10-26T10:00:00Z', }); console.log('Retrieved Logs:', logs); } catch (error) { console.error('Failed to get logs:', error); } ``` ### 4. Metrics Endpoints Retrieve metadata for apps and tenants. #### `metrics.getAppMetadata(data)` `GET /api/metrics/app` Gets metadata for a specific app. ```typescript async getAppMetadata(data: GetAppMetadataRequest): Promise<GetAppMetadataResponse> ``` **Request Interface (`GetAppMetadataRequest`):** ```typescript interface GetAppMetadataRequest { organization_apikey: string; app_apikey: string; } ``` **Response Interface (`GetAppMetadataResponse`):** ```typescript interface GetAppMetadataResponse { id: string; app_id: string; tenant_count: number; created_at: string; updated_at: string; } ``` **Example:** ```typescript try { const appMetadata = await sdk.metrics.getAppMetadata({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', }); console.log('App Metadata:', appMetadata); } catch (error) { console.error('Failed to get app metadata:', error); } ``` #### `metrics.getTenantMetadata(data)` `GET /api/metrics/tenant` Gets metadata for a specific tenant. ```typescript async getTenantMetadata(data: GetTenantMetadataRequest): Promise<GetTenantMetadataResponse> ``` **Request Interface (`GetTenantMetadataRequest`):** ```typescript interface GetTenantMetadataRequest { organization_apikey: string; app_apikey: string; tenant_apikey: string; } ``` **Response Interface (`GetTenantMetadataResponse`):** ```typescript interface GetTenantMetadataResponse { id: string; app_id: string; tenant_id: string; log_count: number; created_at: string; updated_at: string; } ``` **Example:** ```typescript try { const tenantMetadata = await sdk.metrics.getTenantMetadata({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', tenant_apikey: 'YOUR_TENANT_API_KEY', }); console.log('Tenant Metadata:', tenantMetadata); } catch (error) { console.error('Failed to get tenant metadata:', error); } ``` ### 5. Items Endpoints List items associated with an app or tenant. #### `items.listItems(data)` `GET /api/items` Lists items for a given app or tenant. ```typescript async listItems(data: ListItemsRequest): Promise<ListItemsResponse> ``` **Request Interface (`ListItemsRequest`):** ```typescript interface ListItemsRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; } ``` **Response Interface (`ListItemsResponse`):** ```typescript interface ListItemsResponse { items: Array<{ item_id: string; friendly_name?: string; last_seen: string; // ISO 8601 }>; } ``` **Example:** ```typescript try { const items = await sdk.items.listItems({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', tenant_apikey: 'YOUR_TENANT_API_KEY', // Optional }); console.log('Items:', items.items); } catch (error) { console.error('Failed to list items:', error); } ``` ### 6. Intelligence Endpoints Get predictions and decisions based on data. #### `intelligence.getPredictConfig()` `GET /api/intelligence/predict/config` Gets the configuration for predictions, including available types and timeframes. ```typescript async getPredictConfig(): Promise<PredictConfigResponse> ``` **Response Interface (`PredictConfigResponse`):** ```typescript interface PredictConfigResponse { prediction_types: Array<{ type: string; description: string; use_cases: string[]; example: string }>; timeframes: Array<{ value: string; description: string; use_cases: string }>; example_request: PredictRequest; example_response: PredictResponse; } ``` **Example:** ```typescript try { const config = await sdk.intelligence.getPredictConfig(); console.log('Prediction Config:', config); } catch (error) { console.error('Failed to get prediction config:', error); } ``` #### `intelligence.predict(data)` `POST /api/intelligence/predict` Gets a prediction for a specific item based on the provided parameters. ```typescript async predict(data: PredictRequest): Promise<PredictResponse> ``` **Request Interface (`PredictRequest`):** ```typescript interface PredictRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; item_id: string; prediction_type: 'trend' | 'anomaly' | 'failure'; timeframe: '1h' | '24h' | '7d' | '30d'; } ``` **Response Interface (`PredictResponse`):** ```typescript interface PredictResponse { timestamp: string; // ISO 8601 item_id: string; prediction: string; confidence: number; explanation: string; timeframe: string; recommendations: string[]; } ``` **Example:** ```typescript try { const prediction = await sdk.intelligence.predict({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', item_id: 'item123', prediction_type: 'anomaly', timeframe: '24h', }); console.log('Prediction Result:', prediction); } catch (error) { console.error('Failed to get prediction:', error); } ``` #### `intelligence.decide(data)` `POST /api/intelligence/decide` Gets a decision based on log data. ```typescript async decide(data: DecideRequest): Promise<DecideResponse> ``` **Request Interface (`DecideRequest`):** ```typescript interface DecideRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; log_data: { metrics: Array<{ name: string; friendly_name?: string; value: any; unit?: string }>; context: string; item_name: string; }; allowed_actions: Record<string, string>; } ``` **Response Interface (`DecideResponse`):** ```typescript interface DecideResponse { timestamp: string; // ISO 8601 decision: string; reason: string; confidence: number; message?: string; } ``` **Example:** ```typescript try { const decision = await sdk.intelligence.decide({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', log_data: { metrics: [{ name: 'cpu_usage', value: 90 }], context: 'high_load', item_name: 'server1', }, allowed_actions: { restart: 'Restart the server' }, }); console.log('Decision Result:', decision); } catch (error) { console.error('Failed to get decision:', error); } ``` ### 7. Analyze Endpoints Perform analysis on logs and get current status. #### `analyze.getLatest(data)` `GET /api/analyze/latest` Gets the latest analysis for a specific item. ```typescript async getLatest(data: GetLatestRequest): Promise<AnalysisResult> ``` **Request Interface (`GetLatestRequest`):** ```typescript interface GetLatestRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; item_id: string; } ``` **Response Interface (`AnalysisResult`):** ```typescript interface AnalysisResult { summary: { /* ... */ }; metrics: Record<string, { /* ... */ }>; time_series: Array<{ /* ... */ }>; ai_analysis?: { /* ... */ }; } ``` *(See `src/endpoints/analyze/types.ts` for full `AnalysisResult` interface details)* **Example:** ```typescript try { const latestAnalysis = await sdk.analyze.getLatest({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', item_id: 'item123', }); console.log('Latest Analysis:', latestAnalysis); } catch (error) { console.error('Failed to get latest analysis:', error); } ``` #### `analyze.analyzeLogs(data)` `GET /api/analyze` Analyzes logs for an item within a specified time range. ```typescript async analyzeLogs(data: AnalyzeLogsRequest): Promise<AnalysisResult> ``` **Request Interface (`AnalyzeLogsRequest`):** ```typescript interface AnalyzeLogsRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; item_id: string; after?: string; // ISO 8601 before?: string; // ISO 8601 } ``` **Response Interface (`AnalysisResult`):** ```typescript interface AnalysisResult { summary: { /* ... */ }; metrics: Record<string, { /* ... */ }>; time_series: Array<{ /* ... */ }>; ai_analysis?: { /* ... */ }; } ``` *(See `src/endpoints/analyze/types.ts` for full `AnalysisResult` interface details)* **Example:** ```typescript try { const analysis = await sdk.analyze.analyzeLogs({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', item_id: 'item123', after: '2023-10-01T00:00:00Z', before: '2023-10-31T23:59:59Z', }); console.log('Log Analysis:', analysis); } catch (error) { console.error('Failed to analyze logs:', error); } ``` #### `analyze.analyzeCurrent(data)` `GET /api/analyze/current` Gets the current analysis status for a specific item. ```typescript async analyzeCurrent(data: AnalyzeCurrentRequest): Promise<AnalyzeCurrentResponse> ``` **Request Interface (`AnalyzeCurrentRequest`):** ```typescript interface AnalyzeCurrentRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; item_id: string; } ``` **Response Interface (`AnalyzeCurrentResponse`):** ```typescript interface AnalyzeCurrentResponse { timestamp: string; // ISO 8601 overview: string; status: 'normal' | 'warning' | 'critical'; description: string; metrics: Record<string, { /* ... */ }>; recommendations: Array<{ /* ... */ }>; } ``` **Example:** ```typescript try { const currentAnalysis = await sdk.analyze.analyzeCurrent({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', item_id: 'item123', }); console.log('Current Analysis:', currentAnalysis); } catch (error) { console.error('Failed to get current analysis:', error); } ``` ### 8. App Endpoints Manage and retrieve the status of an app. #### `app.updateStatus(data)` `POST /api/app/status` Updates the status of an app. ```typescript async updateStatus(data: AppStatusRequest): Promise<AppStatusOverview> ``` **Request Interface (`AppStatusRequest`):** ```typescript interface AppStatusRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; // ... status details ... } ``` **Response Interface (`AppStatusOverview`):** ```typescript interface AppStatusOverview { timestamp: string; // ISO 8601 overview: string; status: 'normal' | 'warning' | 'critical'; item_statuses: Array<{ /* ... */ }>; recommendations: Array<{ /* ... */ }>; } ``` **Example:** ```typescript try { const updatedStatus = await sdk.app.updateStatus({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', // status details }); console.log('Updated App Status:', updatedStatus); } catch (error) { console.error('Failed to update app status:', error); } ``` #### `app.getLatestStatus(data)` `GET /api/app/status/latest` Gets the latest status overview for an app. ```typescript async getLatestStatus(data: GetLatestAppStatusRequest): Promise<AppStatusOverview> ``` **Request Interface (`GetLatestAppStatusRequest`):** ```typescript interface GetLatestAppStatusRequest { organization_apikey: string; app_apikey: string; tenant_apikey?: string; } ``` **Response Interface (`AppStatusOverview`):** ```typescript interface AppStatusOverview { timestamp: string; // ISO 8601 overview: string; status: 'normal' | 'warning' | 'critical'; item_statuses: Array<{ /* ... */ }>; recommendations: Array<{ /* ... */ }>; } ``` **Example:** ```typescript try { const latestStatus = await sdk.app.getLatestStatus({ organization_apikey: 'YOUR_ORG_API_KEY', app_apikey: 'YOUR_APP_API_KEY', }); console.log('Latest App Status:', latestStatus); } catch (error) { console.error('Failed to get latest app status:', error); } ``` ## Error Handling The SDK throws custom error types for different API responses: - `InvalidRequestError`: For missing or invalid request parameters (status 400). - `AuthenticationError`: For invalid API keys (status 401). - `ServerError`: For internal server errors (status 500). You can catch these errors to handle specific API responses: ```typescript import { InvalidRequestError, AuthenticationError, ServerError } from 'sjursen-digital-watchtower/errors'; try { // SDK call } catch (error) { if (error instanceof InvalidRequestError) { console.error('Invalid Request:', error.message); } else if (error instanceof AuthenticationError) { console.error('Authentication Failed:', error.message); } else if (error instanceof ServerError) { console.error('Server Error:', error.message); } else { console.error('An unexpected error occurred:', error); } } ``` ## Contributing [Add contributing guidelines here] ## License [Add license information here]