import type { FastifyInstance } from "fastify" import { secrets } from "../../utils/secrets" import { sendMail } from "../../utils/mailer" import { CollaborationService } from "./service" import { FederationService } from "./federation" import { encrypt, decrypt } from "../../utils/crypt" import { collaborationConfig } from "./config" import { CollaborationNotifications } from "./notifications" export function collaborationRuntime(server: FastifyInstance) { const { apiUrl, publicUrl, enabled, disabledReason } = collaborationConfig({ ...process.env, API_BASE_URL: secrets.API_BASE_URL, ENCRYPTION_KEY: secrets.ENCRYPTION_KEY, }) const service = new CollaborationService(server.db, { publicUrl, guestPepper: () => secrets.ENCRYPTION_KEY || "", sendMail, }) const federation = new FederationService(service, { apiUrl, enabled, disabledReason, seal: encrypt, unseal: decrypt }) const notifications = new CollaborationNotifications(server, service, federation) service.options.notifications = notifications service.options.changed = (roomId, db) => federation.changed(roomId, db) service.options.invited = (ctx, roomId, target, invitationId, db) => federation.invite(ctx, roomId, target, invitationId, db) let timer: ReturnType server.addHook("onReady", async () => { if (federation.options.enabled) await federation.keys() timer = setInterval(() => { void federation.tick().catch(error => server.log.error({ err: error }, "Collaboration worker failed")) void notifications.tick().catch(error => server.log.error({ err: error }, "Collaboration notification worker failed")) }, 5000) timer.unref() }) server.addHook("onClose", async () => { clearInterval(timer) }) return { service, federation, apiUrl } }