Files
Checkmate/server/src/config/services.shared.ts
T

227 lines
10 KiB
TypeScript

import { Mongoose } from "mongoose";
import { hostname } from "node:os";
import { randomUUID } from "node:crypto";
import fs from "fs";
import path from "path";
import nodemailer from "nodemailer";
import pkg from "handlebars";
const { compile } = pkg;
import mjml2html from "mjml";
import MongoDB from "@/db/db.mongo.js";
import { IDb } from "@/db/db.interface.js";
import { ISettingsService, EnvConfig, SettingsService } from "@/domain/app-settings/app-settings.service.js";
import { ICheckService, CheckService } from "@/domain/checks/check.service.js";
import { IGeoChecksService, GeoChecksService } from "@/domain/geo-checks/geo-check.service.js";
import { IIncidentService, IncidentService } from "@/domain/incidents/incident.service.js";
import { INotificationMessageBuilder, NotificationMessageBuilder } from "@/domain/notifications/notification.message-builder.js";
import { INotificationsService, NotificationsService } from "@/domain/notifications/notification.service.js";
import { IEmailService, EmailService } from "@/service/emailService.js";
import { GlobalPingService } from "@/service/globalPingService.js";
import { ILogger } from "@/utils/logger.js";
// Notification providers
import type { NotificationProviderRegistry } from "@/domain/notifications/notification.service.js";
import { WebhookProvider } from "@/domain/notifications/providers/webhook.js";
import { RocketChatProvider } from "@/domain/notifications/providers/rocketChat.js";
import { SlackProvider } from "@/domain/notifications/providers/slack.js";
import { EmailProvider } from "@/domain/notifications/providers/email.js";
import { DiscordProvider } from "@/domain/notifications/providers/discord.js";
import { PagerDutyProvider } from "@/domain/notifications/providers/pagerduty.js";
import { MatrixProvider } from "@/domain/notifications/providers/matrix.js";
import { TeamsProvider } from "@/domain/notifications/providers/teams.js";
import { TelegramProvider } from "@/domain/notifications/providers/telegram.js";
import { PushoverProvider } from "@/domain/notifications/providers/pushover.js";
import { TwilioProvider } from "@/domain/notifications/providers/twilio.js";
import { NtfyProvider } from "@/domain/notifications/providers/ntfy.js";
// Repository interfaces
import { ISettingsRepository } from "@/domain/app-settings/app-settings-repository.interface.js";
import { IChecksRepository } from "@/domain/checks/check.repository.interface.js";
import { IGeoChecksRepository } from "@/domain/geo-checks/geo-check.repository.interface.js";
import { IIncidentsRepository } from "@/domain/incidents/incident.repository.interface.js";
import { IInvitesRepository } from "@/domain/invites/invite.repository.interface.js";
import { IJobsRepository } from "@/domain/jobs/job.repository.interface.js";
import { IMaintenanceWindowsRepository } from "@/domain/maintenance-windows/maintenance-window.repository.interface.js";
import { IMonitorStatsRepository } from "@/domain/monitor-stats/monitor-stats.repository.interface.js";
import { IMonitorsRepository } from "@/domain/monitors/monitor.repository.interface.js";
import { INotificationsRepository } from "@/domain/notifications/notification.repository.interface.js";
import { IQueueWorkersRepository } from "@/domain/queue-workers/queue-worker.repository.interface.js";
import { IRecoveryTokensRepository } from "@/domain/recovery-tokens/recovery-token.repository.interface.js";
import { IStatusPagesRepository } from "@/domain/status-pages/status-page-repository.interface.js";
import { ITagsRepository } from "@/domain/tags/tag.repository.interface.js";
import { ITeamsRepository } from "@/domain/teams/team.repository.interface.js";
import { IUsersRepository } from "@/domain/users/user.repository.interface.js";
// Mongo repository implementations
import MongoSettingsRepository from "@/domain/app-settings/app-settings.repository.mongo.js";
import MongoChecksRepository from "@/domain/checks/check.repository.mongo.js";
import MongoGeoChecksRepository from "@/domain/geo-checks/geo-check.repository.mongo.js";
import MongoIncidentsRepository from "@/domain/incidents/incident.repository.mongo.js";
import MongoInvitesRepository from "@/domain/invites/invite.repository.mongo.js";
import MongoJobsRepository from "@/domain/jobs/job.repository.mongo.js";
import MongoMaintenanceWindowsRepository from "@/domain/maintenance-windows/maintenance-window.repository.mongo.js";
import MongoMonitorStatsRepository from "@/domain/monitor-stats/monitor-stats.repository.mongo.js";
import MongoMonitorsRepository from "@/domain/monitors/monitor.repository.mongo.js";
import MongoNotificationsRepository from "@/domain/notifications/notification.repository.mongo.js";
import MongoQueueWorkersRepository from "@/domain/queue-workers/queue-worker.repository.mongo.js";
import MongoRecoveryTokensRepository from "@/domain/recovery-tokens/recovery-token.repository.mongo.js";
import MongoStatusPagesRepository from "@/domain/status-pages/status-page-repository.mongo.js";
import MongoTagsRepository from "@/domain/tags/tag.repository.mongo.js";
import MongoTeamsRepository from "@/domain/teams/team.repository.model.js";
import MongoUsersRepository from "@/domain/users/user.repository.mongo.js";
// Shared infrastructure + business services that both the API and the worker process construct.
export interface SharedServices {
logger: ILogger;
db: IDb<Mongoose>;
settingsService: ISettingsService;
emailService: IEmailService;
notificationMessageBuilder: INotificationMessageBuilder;
incidentService: IIncidentService;
checkService: ICheckService;
geoChecksService: IGeoChecksService;
notificationsService: INotificationsService;
// Queue identity (one per process; the worker reuses these)
workerId: string;
jobsRepository: IJobsRepository;
queueWorkersRepository: IQueueWorkersRepository;
// Repositories
monitorsRepository: IMonitorsRepository;
checksRepository: IChecksRepository;
geoChecksRepository: IGeoChecksRepository;
monitorStatsRepository: IMonitorStatsRepository;
statusPagesRepository: IStatusPagesRepository;
usersRepository: IUsersRepository;
invitesRepository: IInvitesRepository;
recoveryTokensRepository: IRecoveryTokensRepository;
settingsRepository: ISettingsRepository;
notificationsRepository: INotificationsRepository;
tagsRepository: ITagsRepository;
incidentsRepository: IIncidentsRepository;
teamsRepository: ITeamsRepository;
maintenanceWindowsRepository: IMaintenanceWindowsRepository;
}
export const buildShared = async ({
logger,
envSettings,
settingsService,
}: {
logger: ILogger;
envSettings: EnvConfig;
settingsService: ISettingsService;
}): Promise<SharedServices> => {
// Shared worker ID
const workerId = `${hostname()}:${process.pid}:${randomUUID()}`;
// Create DB
let db: IDb<Mongoose> | null = null;
db = new MongoDB(logger, envSettings);
await db.connect();
// Repositories
const monitorsRepository = new MongoMonitorsRepository();
const checksRepository = new MongoChecksRepository(logger);
const incidentsRepository = new MongoIncidentsRepository();
const usersRepository = new MongoUsersRepository();
const geoChecksRepository = new MongoGeoChecksRepository();
const notificationsRepository = new MongoNotificationsRepository();
const jobsRepository = new MongoJobsRepository(workerId);
const queueWorkersRepository = new MongoQueueWorkersRepository();
const monitorStatsRepository = new MongoMonitorStatsRepository();
const statusPagesRepository = new MongoStatusPagesRepository();
const invitesRepository = new MongoInvitesRepository();
const recoveryTokensRepository = new MongoRecoveryTokensRepository();
const settingsRepository = new MongoSettingsRepository();
const tagsRepository = new MongoTagsRepository();
const teamsRepository = new MongoTeamsRepository();
const maintenanceWindowsRepository = new MongoMaintenanceWindowsRepository();
// Inject settings repository into settings service (now that DB is connected)
(settingsService as SettingsService).setRepository(settingsRepository);
// Services
const notificationMessageBuilder = new NotificationMessageBuilder();
const emailService = new EmailService(settingsService, fs, path, compile, mjml2html, nodemailer, logger);
const incidentService = new IncidentService(logger, incidentsRepository, monitorsRepository, usersRepository, notificationMessageBuilder);
const checkService = new CheckService(monitorsRepository, logger, checksRepository);
const globalPingService = new GlobalPingService(logger);
const geoChecksService = new GeoChecksService({
logger,
geoChecksRepository,
globalPingService,
monitorsRepository,
});
const webhookProvider = new WebhookProvider(logger);
const rocketChatProvider = new RocketChatProvider(logger);
const slackProvider = new SlackProvider(logger);
const emailProvider = new EmailProvider(emailService, logger);
const discordProvider = new DiscordProvider(logger);
const pagerDutyProvider = new PagerDutyProvider(logger);
const matrixProvider = new MatrixProvider(logger);
const teamsProvider = new TeamsProvider(logger);
const telegramProvider = new TelegramProvider(logger);
const pushoverProvider = new PushoverProvider(logger);
const twilioProvider = new TwilioProvider(logger);
const ntfyProvider = new NtfyProvider(logger);
const notificationProviders: NotificationProviderRegistry = {
webhook: webhookProvider,
rocket_chat: rocketChatProvider,
email: emailProvider,
slack: slackProvider,
discord: discordProvider,
pager_duty: pagerDutyProvider,
matrix: matrixProvider,
teams: teamsProvider,
telegram: telegramProvider,
pushover: pushoverProvider,
twilio: twilioProvider,
ntfy: ntfyProvider,
};
const notificationsService = new NotificationsService({
notificationsRepository,
monitorsRepository,
providers: notificationProviders,
settingsService,
logger,
notificationMessageBuilder,
});
const sharedServices: SharedServices = {
logger,
db,
settingsService,
emailService,
notificationMessageBuilder,
incidentService,
checkService,
geoChecksService,
notificationsService,
workerId,
jobsRepository,
monitorsRepository,
queueWorkersRepository,
checksRepository,
geoChecksRepository,
monitorStatsRepository,
statusPagesRepository,
usersRepository,
invitesRepository,
recoveryTokensRepository,
settingsRepository,
notificationsRepository,
tagsRepository,
incidentsRepository,
teamsRepository,
maintenanceWindowsRepository,
};
return sharedServices;
};