import type { Redis } from "ioredis"; import { z } from "zod"; export const ProviderConfigSchema = z.object({ clientId: z.string(), clientSecret: z.string(), redirectUri: z.url().optional(), authUrl: z.url(), tokenUrl: z.url(), scope: z.string(), }); export type ProviderConfig = z.infer; export class ConfigManager { constructor(private redis: Redis) {} async setProviderConfig(provider: string, config: ProviderConfig): Promise { const validatedConfig = ProviderConfigSchema.parse(config); await this.redis.set(`config:${provider}`, JSON.stringify(validatedConfig)); } async getProviderConfig(provider: string): Promise { const data = await this.redis.get(`config:${provider}`); if (!data) return null; return ProviderConfigSchema.parse(JSON.parse(data)); } async getAllProviders(): Promise> { const keys = await this.redis.keys("config:*"); const result: Record = {}; for (const key of keys) { const provider = key.replace("config:", ""); const config = await this.getProviderConfig(provider); if (config) { result[provider] = config; } } return result; } async deleteProviderConfig(provider: string): Promise { await this.redis.del(`config:${provider}`); // Also clean up tokens across all tenants const tokenKeys = await this.redis.keys(`tenant:*:provider:${provider}:*`); if (tokenKeys.length > 0) { await this.redis.del(...tokenKeys); } } }