import { getContainer } from '@bytelyst/cosmos'; import { config } from '../config/index.js'; import logger from '../utils/logger.js'; export interface DynamicConfigEntry { key: string; value: string; description?: string; updated_at?: string; } interface DynamicConfigDocument extends DynamicConfigEntry { id: string; productId: string; updatedAt: string; } const CONTAINER_NAME = 'dynamic_config'; function isCosmosConfigured(): boolean { return Boolean(config.COSMOS_ENDPOINT && config.COSMOS_KEY); } function normalizeEntry(entry: Partial | null | undefined): DynamicConfigEntry | null { const key = String(entry?.key || '').trim(); if (!key) return null; return { key, value: String(entry?.value ?? ''), description: entry?.description ? String(entry.description) : '', updated_at: entry?.updated_at ? String(entry.updated_at) : undefined, }; } async function listFromCosmos(): Promise { if (!isCosmosConfigured()) return []; const container = getContainer(CONTAINER_NAME); const { resources } = await container.items .query({ query: 'SELECT * FROM c WHERE c.productId = @productId ORDER BY c.key', parameters: [{ name: '@productId', value: config.PRODUCT_ID }], }) .fetchAll(); return resources .map((resource) => normalizeEntry({ key: resource.key, value: resource.value, description: resource.description, updated_at: resource.updatedAt, })) .filter((entry): entry is DynamicConfigEntry => Boolean(entry)); } export async function listDynamicConfigEntries(): Promise { if (!isCosmosConfigured()) { logger.warn('[DynamicConfig] Cosmos is not configured; dynamic config overrides are unavailable in this environment.'); return []; } try { return await listFromCosmos(); } catch (error) { logger.warn(`[DynamicConfig] Cosmos read failed: ${error instanceof Error ? error.message : 'unknown error'}`); return []; } } export async function upsertDynamicConfigEntries(entries: DynamicConfigEntry[]): Promise { const normalized = entries .map((entry) => normalizeEntry(entry)) .filter((entry): entry is DynamicConfigEntry => Boolean(entry)); if (normalized.length === 0) { return; } const now = new Date().toISOString(); if (!isCosmosConfigured()) { logger.warn('[DynamicConfig] Cosmos is not configured; skipping dynamic config upsert.'); return; } try { const container = getContainer(CONTAINER_NAME); await Promise.all(normalized.map((entry) => container.items.upsert({ id: entry.key, productId: config.PRODUCT_ID, key: entry.key, value: entry.value, description: entry.description || '', updated_at: entry.updated_at || now, updatedAt: entry.updated_at || now, }))); } catch (error) { logger.warn(`[DynamicConfig] Cosmos upsert failed: ${error instanceof Error ? error.message : 'unknown error'}`); } }