export interface TelemetryConfig { /** Base URL of the telemetry server (e.g., "https://tel.mosaicstack.dev") */ serverUrl: string; /** API key for authentication (64-char hex string) */ apiKey: string; /** Instance UUID for this client */ instanceId: string; /** Whether telemetry collection is enabled. Default: true */ enabled?: boolean; /** Interval between automatic batch submissions in ms. Default: 300_000 (5 min) */ submitIntervalMs?: number; /** Maximum number of events held in queue. Default: 1000 */ maxQueueSize?: number; /** Maximum events per batch submission. Default: 100 */ batchSize?: number; /** HTTP request timeout in ms. Default: 10_000 */ requestTimeoutMs?: number; /** TTL for cached predictions in ms. Default: 21_600_000 (6 hours) */ predictionCacheTtlMs?: number; /** If true, log events instead of sending them. Default: false */ dryRun?: boolean; /** Maximum number of retries on failure. Default: 3 */ maxRetries?: number; /** Optional callback invoked on errors */ onError?: (error: Error) => void; } export interface ResolvedConfig { serverUrl: string; apiKey: string; instanceId: string; enabled: boolean; submitIntervalMs: number; maxQueueSize: number; batchSize: number; requestTimeoutMs: number; predictionCacheTtlMs: number; dryRun: boolean; maxRetries: number; onError: (error: Error) => void; } const DEFAULT_ON_ERROR = (_error: Error): void => { // Silent by default }; export function resolveConfig(config: TelemetryConfig): ResolvedConfig { return { serverUrl: config.serverUrl.replace(/\/+$/, ""), apiKey: config.apiKey, instanceId: config.instanceId, enabled: config.enabled ?? true, submitIntervalMs: config.submitIntervalMs ?? 300_000, maxQueueSize: config.maxQueueSize ?? 1000, batchSize: config.batchSize ?? 100, requestTimeoutMs: config.requestTimeoutMs ?? 10_000, predictionCacheTtlMs: config.predictionCacheTtlMs ?? 21_600_000, dryRun: config.dryRun ?? false, maxRetries: config.maxRetries ?? 3, onError: config.onError ?? DEFAULT_ON_ERROR, }; }