import * as Lark from "@larksuiteoapi/node-sdk"; import type { FeishuDomain, ResolvedFeishuAccount } from "./types.js"; // Multi-account client cache const clientCache = new Map< string, { client: Lark.Client; config: { appId: string; appSecret: string; domain?: FeishuDomain }; } >(); function resolveDomain(domain: FeishuDomain | undefined): Lark.Domain | string { if (domain === "lark") { return Lark.Domain.Lark; } if (domain === "feishu" || !domain) { return Lark.Domain.Feishu; } return domain.replace(/\/+$/, ""); // Custom URL for private deployment } /** * Credentials needed to create a Feishu client. * Both FeishuConfig and ResolvedFeishuAccount satisfy this interface. */ export type FeishuClientCredentials = { accountId?: string; appId?: string; appSecret?: string; domain?: FeishuDomain; }; /** * Create or get a cached Feishu client for an account. * Accepts any object with appId, appSecret, and optional domain/accountId. */ export function createFeishuClient(creds: FeishuClientCredentials): Lark.Client { const { accountId = "default", appId, appSecret, domain } = creds; if (!appId || !appSecret) { throw new Error(`Feishu credentials not configured for account "${accountId}"`); } // Check cache const cached = clientCache.get(accountId); if ( cached && cached.config.appId === appId && cached.config.appSecret === appSecret && cached.config.domain === domain ) { return cached.client; } // Create new client const client = new Lark.Client({ appId, appSecret, appType: Lark.AppType.SelfBuild, domain: resolveDomain(domain), }); // Cache it clientCache.set(accountId, { client, config: { appId, appSecret, domain }, }); return client; } /** * Create a Feishu WebSocket client for an account. * Note: WSClient is not cached since each call creates a new connection. */ export function createFeishuWSClient(account: ResolvedFeishuAccount): Lark.WSClient { const { accountId, appId, appSecret, domain } = account; if (!appId || !appSecret) { throw new Error(`Feishu credentials not configured for account "${accountId}"`); } return new Lark.WSClient({ appId, appSecret, domain: resolveDomain(domain), loggerLevel: Lark.LoggerLevel.info, }); } /** * Create an event dispatcher for an account. */ export function createEventDispatcher(account: ResolvedFeishuAccount): Lark.EventDispatcher { return new Lark.EventDispatcher({ encryptKey: account.encryptKey, verificationToken: account.verificationToken, }); } /** * Get a cached client for an account (if exists). */ export function getFeishuClient(accountId: string): Lark.Client | null { return clientCache.get(accountId)?.client ?? null; } /** * Clear client cache for a specific account or all accounts. */ export function clearClientCache(accountId?: string): void { if (accountId) { clientCache.delete(accountId); } else { clientCache.clear(); } }