"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.listmonkClient = void 0; const env_1 = require("../config/env"); const logger_1 = require("../utils/logger"); // --- Client --- class ListmonkClient { get baseUrl() { return env_1.env.LISTMONK_URL; } get authHeader() { return 'Basic ' + Buffer.from(`${env_1.env.LISTMONK_ADMIN_USER}:${env_1.env.LISTMONK_ADMIN_PASSWORD}`).toString('base64'); } get enabled() { return env_1.env.LISTMONK_SYNC_ENABLED === 'true'; } assertEnabled() { if (!this.enabled) { throw new Error('Listmonk sync is disabled. Set LISTMONK_SYNC_ENABLED=true to enable.'); } } async request(method, path, body) { const url = `${this.baseUrl}${path}`; const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 5000); try { const res = await fetch(url, { method, headers: { 'Authorization': this.authHeader, 'Content-Type': 'application/json', }, body: body ? JSON.stringify(body) : undefined, signal: controller.signal, }); if (!res.ok) { const text = await res.text().catch(() => ''); throw new Error(`Listmonk API ${method} ${path} returned ${res.status}: ${text}`); } return await res.json(); } finally { clearTimeout(timeout); } } async checkHealth() { try { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 5000); try { const res = await fetch(`${this.baseUrl}/api/health`, { headers: { 'Authorization': this.authHeader }, signal: controller.signal, }); return res.ok; } finally { clearTimeout(timeout); } } catch (err) { logger_1.logger.warn('Listmonk health check failed:', err instanceof Error ? err.message : err); return false; } } async getLists() { this.assertEnabled(); try { const res = await this.request('GET', '/api/lists?per_page=all'); return res.data.results || []; } catch (err) { logger_1.logger.warn('Failed to fetch Listmonk lists:', err instanceof Error ? err.message : err); throw err; } } async createList(name, type, tags) { this.assertEnabled(); try { const res = await this.request('POST', '/api/lists', { name, type, optin: 'single', tags, }); return res.data; } catch (err) { logger_1.logger.warn(`Failed to create Listmonk list "${name}":`, err instanceof Error ? err.message : err); throw err; } } async findSubscriberByEmail(email) { this.assertEnabled(); try { const query = encodeURIComponent(`subscribers.email='${email}'`); const res = await this.request('GET', `/api/subscribers?query=${query}&per_page=1`); const results = res.data.results; return results && results.length > 0 ? results[0] : null; } catch (err) { logger_1.logger.warn(`Failed to find subscriber ${email}:`, err instanceof Error ? err.message : err); return null; } } async createSubscriber(email, name, listIds, attribs) { this.assertEnabled(); const res = await this.request('POST', '/api/subscribers', { email, name, status: 'enabled', lists: listIds, attribs, }); return res.data; } async updateSubscriber(id, data) { this.assertEnabled(); const res = await this.request('PUT', `/api/subscribers/${id}`, data); return res.data; } async upsertSubscriber(email, name, listIds, attribs) { this.assertEnabled(); const existing = await this.findSubscriberByEmail(email); if (existing) { // Merge lists: combine existing + new, deduplicate const existingListIds = existing.lists.map(l => l.id); const mergedListIds = [...new Set([...existingListIds, ...listIds])]; // Merge attribs const mergedAttribs = { ...existing.attribs, ...attribs }; return this.updateSubscriber(existing.id, { email, name: name || existing.name, lists: mergedListIds, attribs: mergedAttribs, }); } return this.createSubscriber(email, name, listIds, attribs); } } exports.listmonkClient = new ListmonkClient(); //# sourceMappingURL=listmonk.client.js.map