// ============================================================ // Database Entity Types // ============================================================ export interface Provider { id: number; name: string; display_name: string; api_base_url: string | null; last_sync_at: string | null; // ISO 8601 datetime sync_status: 'pending' | 'syncing' | 'success' | 'error'; sync_error: string | null; created_at: string; updated_at: string; } export interface Region { id: number; provider_id: number; region_code: string; region_name: string; country_code: string | null; // ISO 3166-1 alpha-2 latitude: number | null; longitude: number | null; available: number; // SQLite boolean (0/1) created_at: string; updated_at: string; } export type InstanceFamily = 'general' | 'compute' | 'memory' | 'storage' | 'gpu'; export interface InstanceType { id: number; provider_id: number; instance_id: string; instance_name: string; vcpu: number; memory_mb: number; storage_gb: number; transfer_tb: number | null; network_speed_gbps: number | null; gpu_count: number; gpu_type: string | null; instance_family: InstanceFamily | null; metadata: string | null; // JSON string created_at: string; updated_at: string; } export interface Pricing { id: number; instance_type_id: number; region_id: number; hourly_price: number; monthly_price: number; currency: string; available: number; // SQLite boolean (0/1) created_at: string; updated_at: string; } export interface PriceHistory { id: number; pricing_id: number; hourly_price: number; monthly_price: number; recorded_at: string; } export interface GpuInstance { id: number; provider_id: number; instance_id: string; instance_name: string; vcpu: number; memory_mb: number; storage_gb: number; transfer_tb: number | null; network_speed_gbps: number | null; gpu_count: number; gpu_type: string; gpu_memory_gb: number | null; metadata: string | null; // JSON string created_at: string; updated_at: string; } export interface GpuPricing { id: number; gpu_instance_id: number; region_id: number; hourly_price: number; monthly_price: number; currency: string; available: number; // SQLite boolean (0/1) created_at: string; updated_at: string; } export interface G8Instance { id: number; provider_id: number; instance_id: string; instance_name: string; vcpu: number; memory_mb: number; storage_gb: number; transfer_tb: number | null; network_speed_gbps: number | null; metadata: string | null; // JSON string created_at: string; updated_at: string; } export interface G8Pricing { id: number; g8_instance_id: number; region_id: number; hourly_price: number; monthly_price: number; currency: string; available: number; // SQLite boolean (0/1) created_at: string; updated_at: string; } export interface VpuInstance { id: number; provider_id: number; instance_id: string; instance_name: string; vcpu: number; memory_mb: number; storage_gb: number; transfer_tb: number | null; network_speed_gbps: number | null; vpu_type: string; metadata: string | null; // JSON string created_at: string; updated_at: string; } export interface VpuPricing { id: number; vpu_instance_id: number; region_id: number; hourly_price: number; monthly_price: number; currency: string; available: number; // SQLite boolean (0/1) created_at: string; updated_at: string; } // ============================================================ // Repository Input Types (for create/update operations) // ============================================================ export type ProviderInput = Omit; export type RegionInput = Omit; export type InstanceTypeInput = Omit; export type PricingInput = Omit; export type GpuInstanceInput = Omit; export type GpuPricingInput = Omit; export type G8InstanceInput = Omit; export type G8PricingInput = Omit; export type VpuInstanceInput = Omit; export type VpuPricingInput = Omit; // ============================================================ // Error Types // ============================================================ export class RepositoryError extends Error { constructor( message: string, public readonly code: string, public readonly cause?: unknown ) { super(message); this.name = 'RepositoryError'; } } // Common error codes export const ErrorCodes = { NOT_FOUND: 'NOT_FOUND', DUPLICATE: 'DUPLICATE', CONSTRAINT_VIOLATION: 'CONSTRAINT_VIOLATION', DATABASE_ERROR: 'DATABASE_ERROR', TRANSACTION_FAILED: 'TRANSACTION_FAILED', INVALID_INPUT: 'INVALID_INPUT', VALIDATION_ERROR: 'VALIDATION_ERROR', } as const; // ============================================================ // Pagination Types // ============================================================ export interface PaginationOptions { limit?: number; offset?: number; } export interface PaginatedResult { data: T[]; total: number; limit: number; offset: number; hasMore: boolean; } // ============================================================ // API Query and Response Types // ============================================================ /** * Query parameters for instance search and filtering */ export interface InstanceQueryParams { /** Provider filter (provider ID or name) */ provider?: string; /** Region code filter */ region_code?: string; /** Instance family filter */ family?: InstanceFamily; /** Minimum vCPU count */ min_vcpu?: number; /** Maximum vCPU count */ max_vcpu?: number; /** Minimum memory in MB */ min_memory?: number; /** Maximum memory in MB */ max_memory?: number; /** Minimum hourly price */ min_price?: number; /** Maximum hourly price */ max_price?: number; /** Filter for GPU instances */ has_gpu?: boolean; /** CPU architecture filter */ architecture?: string; /** Sort field (e.g., 'hourly_price', 'vcpu', 'memory_mb') */ sort_by?: string; /** Sort order ('asc' or 'desc') */ sort_order?: 'asc' | 'desc'; /** Page number for pagination (1-indexed) */ page?: number; /** Number of results per page */ limit?: number; /** Force total count calculation (performance optimization: only runs on first page by default) */ include_count?: boolean; } /** * Combined instance data with pricing and relationships */ export interface InstanceData extends InstanceType { /** Provider information */ provider: Provider; /** Region information (nullable if no pricing data) */ region: Region | null; /** Current pricing information (nullable if no pricing data) */ pricing: Pricing | null; } /** * Paginated API response for instance queries */ export interface InstanceResponse { /** Array of instance data */ data: InstanceData[]; /** Pagination metadata */ pagination: { /** Current page number (1-indexed) */ current_page: number; /** Total number of pages */ total_pages: number; /** Number of results per page */ per_page: number; /** Total number of results */ total_results: number; /** Whether there is a next page */ has_next: boolean; /** Whether there is a previous page */ has_previous: boolean; }; /** Query execution metadata */ meta: { /** Query execution time in milliseconds */ query_time_ms: number; /** Applied filters summary */ filters_applied: Partial; }; } // ============================================================ // Sync Report Types // ============================================================ /** * Synchronization report for a single provider */ export interface ProviderSyncResult { /** Provider identifier */ provider: string; /** Synchronization success status */ success: boolean; /** Number of regions synced */ regions_synced: number; /** Number of instances synced */ instances_synced: number; /** Number of pricing records synced */ pricing_synced: number; /** Sync duration in milliseconds */ duration_ms: number; /** Error message if sync failed */ error?: string; /** Detailed error information */ error_details?: Record; } /** * Complete synchronization report for all providers */ export interface SyncReport { /** Overall sync success status */ success: boolean; /** Sync start timestamp (ISO 8601) */ started_at: string; /** Sync completion timestamp (ISO 8601) */ completed_at: string; /** Total sync duration in milliseconds */ total_duration_ms: number; /** Results for each provider */ providers: ProviderSyncResult[]; /** Summary statistics */ summary: { /** Total number of providers synced */ total_providers: number; /** Number of successful provider syncs */ successful_providers: number; /** Number of failed provider syncs */ failed_providers: number; /** Total regions synced across all providers */ total_regions: number; /** Total instances synced across all providers */ total_instances: number; /** Total pricing records synced across all providers */ total_pricing: number; }; } // ============================================================ // Health Check Types // ============================================================ /** * Health check response */ export interface HealthResponse { /** Service health status */ status: 'healthy' | 'degraded' | 'unhealthy'; /** Service version */ version: string; /** Response timestamp (ISO 8601) */ timestamp: string; /** Database connection status */ database: { /** Database connection status */ connected: boolean; /** Database response time in milliseconds */ latency_ms?: number; }; /** Uptime in seconds */ uptime_seconds: number; /** Additional health metrics */ metrics?: { /** Total number of instances in database */ total_instances?: number; /** Total number of providers */ total_providers?: number; /** Last successful sync timestamp (ISO 8601) */ last_sync_at?: string; }; } // ============================================================ // Cloudflare Worker Environment Types // ============================================================ /** * Cloudflare Worker environment bindings and variables */ export interface Env { /** D1 Database binding */ DB: D1Database; /** KV namespace for rate limiting */ RATE_LIMIT_KV: KVNamespace; /** API key for request authentication */ API_KEY: string; /** Provider API credentials (from Wrangler secrets) */ LINODE_API_TOKEN?: string; VULTR_API_KEY?: string; AWS_ACCESS_KEY_ID?: string; AWS_SECRET_ACCESS_KEY?: string; /** Batch size for synchronization operations */ SYNC_BATCH_SIZE?: string; /** Cache TTL in seconds */ CACHE_TTL_SECONDS?: string; /** Log level (debug, info, warn, error, none) - Controls logging verbosity */ LOG_LEVEL?: string; /** CORS origin for Access-Control-Allow-Origin header */ CORS_ORIGIN?: string; /** Environment (development|production) - Controls development-specific features */ ENVIRONMENT?: string; } /** * Hono context variables * Shared across all request contexts */ export interface HonoVariables { /** Unique request ID for tracing */ requestId: string; /** Authentication status (set by auth middleware) */ authenticated?: boolean; } // ============================================================ // Synchronization Types // ============================================================ /** * Synchronization stage enumeration */ export enum SyncStage { /** Initial stage before sync starts */ IDLE = 'idle', /** Initialization stage */ INIT = 'init', /** Fetching regions from provider API */ FETCH_REGIONS = 'fetch_regions', /** Fetching instance types from provider API */ FETCH_INSTANCES = 'fetch_instances', /** Fetching pricing data from provider API */ FETCH_PRICING = 'fetch_pricing', /** Normalizing and transforming data */ NORMALIZE = 'normalize', /** Legacy alias for NORMALIZE */ NORMALIZE_DATA = 'normalize_data', /** Storing data in database */ PERSIST = 'persist', /** Legacy alias for PERSIST */ STORE_DATA = 'store_data', /** Validation stage */ VALIDATE = 'validate', /** Synchronizing Anvil pricing from source provider */ SYNC_ANVIL_PRICING = 'sync_anvil_pricing', /** Sync completed successfully */ COMPLETE = 'complete', /** Legacy alias for COMPLETE */ COMPLETED = 'completed', /** Sync failed with error */ FAILED = 'failed', } /** * Normalized data structure for batch database operations */ export interface NormalizedData { /** Normalized region data ready for insertion */ regions: RegionInput[]; /** Normalized instance type data ready for insertion */ instances: InstanceTypeInput[]; /** Normalized pricing data ready for insertion */ pricing: PricingInput[]; } // ============================================================ // Additional Utility Types // ============================================================ /** * Generic API error response */ export interface ApiError { /** Error status code */ status: number; /** Error type identifier */ error: string; /** Human-readable error message */ message: string; /** Additional error details */ details?: Record; /** Request timestamp (ISO 8601) */ timestamp: string; /** Request path that caused the error */ path?: string; } // ============================================================ // Anvil Product Types // ============================================================ /** * Anvil Region - Anvil-branded regional datacenters */ export interface AnvilRegion { id: number; name: string; // "anvil-tyo1", "anvil-sel1" display_name: string; // "Tokyo 1", "Seoul 1" country_code: string; // "JP", "KR" source_provider: string; // "linode", "vultr" source_region_code: string; // "jp-tyo-3", "nrt" source_region_id: number; // FK to regions.id active: number; // SQLite boolean (0/1) created_at: string; updated_at: string; } /** * Anvil Instance - Anvil-branded instance specifications */ export interface AnvilInstance { id: number; name: string; // "anvil-1g-1c" display_name: string; // "Basic 1GB" category: 'vm' | 'gpu' | 'g8' | 'vpu'; vcpus: number; memory_gb: number; disk_gb: number; transfer_tb: number | null; network_gbps: number | null; gpu_model: string | null; // GPU-specific gpu_vram_gb: number | null; // GPU-specific active: number; // SQLite boolean (0/1) created_at: string; updated_at: string; } /** * Anvil Pricing - Anvil retail pricing (USD only) */ export interface AnvilPricing { id: number; anvil_instance_id: number; anvil_region_id: number; hourly_price: number; // Retail price (USD) monthly_price: number; // Retail price (USD) source_instance_id: number | null; // FK to source tables created_at: string; updated_at: string; } /** * Anvil Transfer Pricing - Data transfer pricing per region (USD only) */ export interface AnvilTransferPricing { id: number; anvil_region_id: number; price_per_gb: number; // USD/GB created_at: string; updated_at: string; } // ============================================================ // Anvil Input Types (auto-derived, excluding id and timestamps) // ============================================================ export type AnvilRegionInput = Omit; export type AnvilInstanceInput = Omit; export type AnvilPricingInput = Omit; export type AnvilTransferPricingInput = Omit;