const { EventEmitter } = require("node:events"); function uniqueStrings(values) { return Array.from( new Set( (Array.isArray(values) ? values : []) .map((value) => (typeof value === "string" ? value.trim() : "")) .filter(Boolean), ), ); } function createAppEventBus() { const emitter = new EventEmitter(); emitter.setMaxListeners(500); let sequence = 0; return { publish(event) { const payload = { id: `${Date.now()}-${++sequence}`, createdAt: new Date().toISOString(), ...event, audienceEmployeeIds: uniqueStrings(event?.audienceEmployeeIds), }; emitter.emit("event", payload); return payload; }, subscribe(handler) { emitter.on("event", handler); return () => emitter.off("event", handler); }, }; } function buildInvoiceUpdatedEvent({ invoiceId, status, updatedAt = null, audienceEmployeeIds = [], }) { return { type: "invoice.updated", invoiceId, status, updatedAt: updatedAt ?? new Date().toISOString(), audienceEmployeeIds: uniqueStrings(audienceEmployeeIds), }; } function publishInvoiceUpdated(fastify, event) { if (!fastify?.appEvents || typeof fastify.appEvents.publish !== "function") { return null; } return fastify.appEvents.publish(buildInvoiceUpdatedEvent(event)); } function canReceiveEvent(employee, event, options = {}) { if (!employee) { return false; } if (event?.type === "invoice.updated" && options.canManageInvoice) { return true; } const audience = uniqueStrings(event?.audienceEmployeeIds); if (!audience.length) { return false; } return audience.includes(employee.id); } function toClientEvent(event) { if (!event) { return null; } if (event.type === "invoice.updated") { return { id: event.id, type: event.type, invoiceId: event.invoiceId, status: event.status ?? null, updatedAt: event.updatedAt ?? event.createdAt ?? null, createdAt: event.createdAt ?? null, }; } return { id: event.id, type: event.type, createdAt: event.createdAt ?? null, }; } module.exports = { buildInvoiceUpdatedEvent, canReceiveEvent, createAppEventBus, publishInvoiceUpdated, toClientEvent, };