diff --git a/server/src/config/services.ts b/server/src/config/services.ts index 6fb27feb7..3535f44d7 100644 --- a/server/src/config/services.ts +++ b/server/src/config/services.ts @@ -43,7 +43,6 @@ import { games, GameDig } from "gamedig"; import jmespath from "jmespath"; // DB Modules -import { NormalizeData } from "../utils/dataUtils.js"; import { GenerateAvatarImage } from "../utils/imageProcessing.js"; import { ParseBoolean } from "../utils/utils.js"; @@ -51,16 +50,13 @@ import { ParseBoolean } from "../utils/utils.js"; import Monitor from "../db/models/Monitor.js"; import User from "../db/models/User.js"; import InviteToken from "../db/models/Invite.js"; -import StatusPage from "../db/models/StatusPage.js"; import Team from "../db/models/Team.js"; import MaintenanceWindow from "../db/models/MaintenanceWindow.js"; import MonitorStats from "../db/models/MonitorStats.js"; import NotificationModel from "../db/models/Notification.js"; import RecoveryToken from "../db/models/RecoveryToken.js"; -import AppSettings from "../db/models/AppSettings.js"; import Incident from "../db/models/Incident.js"; -import StatusPageModule from "../db/modules/statusPageModule.js"; import IncidentModule from "../db/modules/incidentModule.js"; // repositories @@ -139,13 +135,11 @@ export const initializeServices = async ({ settingsRepository: ISettingsRepository; }): Promise => { // Create DB - const statusPageModule = new StatusPageModule({ StatusPage, NormalizeData, AppSettings }); const incidentModule = new IncidentModule({ logger, Incident, Monitor, User }); const db = new MongoDB({ logger, envSettings, - statusPageModule, incidentModule, }); diff --git a/server/src/db/MongoDB.js b/server/src/db/MongoDB.js index 07d3d31c8..f149fbd6d 100755 --- a/server/src/db/MongoDB.js +++ b/server/src/db/MongoDB.js @@ -4,10 +4,9 @@ import { runMigrations } from "./migration/index.js"; class MongoDB { static SERVICE_NAME = "MongoDB"; - constructor({ logger, envSettings, statusPageModule, incidentModule }) { + constructor({ logger, envSettings, incidentModule }) { this.logger = logger; this.envSettings = envSettings; - this.statusPageModule = statusPageModule; this.incidentModule = incidentModule; } diff --git a/server/src/db/modules/statusPageModule.js b/server/src/db/modules/statusPageModule.js deleted file mode 100755 index 78a632cb8..000000000 --- a/server/src/db/modules/statusPageModule.js +++ /dev/null @@ -1,299 +0,0 @@ -const SERVICE_NAME = "statusPageModule"; - -class StatusPageModule { - constructor({ StatusPage, NormalizeData, AppSettings }) { - this.StatusPage = StatusPage; - this.NormalizeData = NormalizeData; - this.AppSettings = AppSettings; - } - - createStatusPage = async ({ statusPageData, image, userId, teamId }) => { - try { - const statusPage = new this.StatusPage({ - ...statusPageData, - userId, - teamId, - }); - if (image) { - statusPage.logo = { - data: image.buffer, - contentType: image.mimetype, - }; - } - await statusPage.save(); - return statusPage; - } catch (error) { - if (error?.code === 11000) { - // Handle duplicate URL errors - error.status = 400; - error.message = "Status page URL must be unique"; - } - error.service = SERVICE_NAME; - error.method = "createStatusPage"; - throw error; - } - }; - - updateStatusPage = async (statusPageData, image) => { - try { - if (image) { - statusPageData.logo = { - data: image.buffer, - contentType: image.mimetype, - }; - } else { - statusPageData.logo = null; - } - - if (statusPageData.deleteSubmonitors === "true") { - statusPageData.subMonitors = []; - } - const statusPage = await this.StatusPage.findOneAndUpdate({ url: statusPageData.url }, statusPageData, { - new: true, - }); - - return statusPage; - } catch (error) { - error.service = SERVICE_NAME; - error.method = "updateStatusPage"; - throw error; - } - }; - - getStatusPageByUrl = async (url) => { - // TODO This is deprecated, can remove and have controller call getStatusPage - try { - return this.getStatusPage(url); - } catch (error) { - error.service = SERVICE_NAME; - error.method = "getStatusPageByUrl"; - throw error; - } - }; - - getStatusPagesByTeamId = async (teamId) => { - try { - const statusPages = await this.StatusPage.find({ teamId }); - return statusPages; - } catch (error) { - error.service = SERVICE_NAME; - error.method = "getStatusPagesByTeamId"; - throw error; - } - }; - - getStatusPage = async (url) => { - try { - const preliminaryStatusPage = await this.StatusPage.findOne({ url }); - if (!preliminaryStatusPage) { - const error = new Error("Status page not found"); - error.status = 404; - throw error; - } - - if (!preliminaryStatusPage.monitors || preliminaryStatusPage.monitors.length === 0) { - const { _id, color, companyName, isPublished, logo, originalMonitors, showCharts, showUptimePercentage, timezone, showAdminLoginLink, url } = - preliminaryStatusPage; - return { - statusPage: { - _id, - color, - companyName, - isPublished, - logo, - originalMonitors, - showCharts, - showUptimePercentage, - timezone, - showAdminLoginLink, - url, - }, - monitors: [], - }; - } - - const statusPageQuery = await this.StatusPage.aggregate([ - { $match: { url: url } }, - { - $set: { - originalMonitors: "$monitors", - }, - }, - { - $lookup: { - from: "monitors", - localField: "monitors", - foreignField: "_id", - as: "monitors", - }, - }, - { - $unwind: { - path: "$monitors", - preserveNullAndEmptyArrays: true, - }, - }, - { - $lookup: { - from: "maintenancewindows", - let: { monitorId: "$monitors._id" }, - pipeline: [{ $match: { $expr: { $eq: ["$monitorId", "$$monitorId"] } } }], - as: "monitors.maintenanceWindows", - }, - }, - { - $lookup: { - from: "checks", - let: { monitorId: "$monitors._id" }, - pipeline: [ - { - $match: { - $expr: { $eq: ["$metadata.monitorId", "$$monitorId"] }, - }, - }, - { $sort: { createdAt: -1 } }, - { $limit: 25 }, - ], - as: "monitors.checks", - }, - }, - { - $lookup: { - from: "monitorstats", - localField: "monitors._id", - foreignField: "monitorId", - as: "monitors.stats", - }, - }, - { - $addFields: { - "monitors.orderIndex": { - $indexOfArray: ["$originalMonitors", "$monitors._id"], - }, - "monitors.isMaintenance": { - $reduce: { - input: "$monitors.maintenanceWindows", - initialValue: false, - in: { - $or: [ - "$$value", - { - $and: [{ $eq: ["$$this.active", true] }, { $lte: ["$$this.start", "$$NOW"] }, { $gte: ["$$this.end", "$$NOW"] }], - }, - ], - }, - }, - }, - "monitors.uptimePercentage": { - $arrayElemAt: ["$monitors.stats.uptimePercentage", 0], - }, - }, - }, - { $match: { "monitors.orderIndex": { $ne: -1 } } }, - { $sort: { "monitors.orderIndex": 1 } }, - - { - $group: { - _id: "$_id", - statusPage: { $first: "$$ROOT" }, - monitors: { $push: "$monitors" }, - }, - }, - { - $project: { - statusPage: { - _id: 1, - color: 1, - companyName: 1, - isPublished: 1, - logo: 1, - originalMonitors: 1, - showCharts: 1, - showUptimePercentage: 1, - timezone: 1, - showAdminLoginLink: 1, - url: 1, - }, - monitors: { - _id: 1, - userId: 1, - teamId: 1, - name: 1, - description: 1, - status: 1, - type: 1, - ignoreTlsErrors: 1, - jsonPath: 1, - expectedValue: 1, - matchMethod: 1, - url: 1, - port: 1, - isActive: 1, - interval: 1, - uptimePercentage: 1, - notifications: 1, - secret: 1, - thresholds: 1, - alertThreshold: 1, - cpuAlertThreshold: 1, - memoryAlertThreshold: 1, - diskAlertThreshold: 1, - tempAlertThreshold: 1, - checks: 1, - isMaintenance: 1, - createdAt: 1, - updatedAt: 1, - }, - }, - }, - ]); - if (!statusPageQuery.length) { - const error = new Error("Status page not found"); - error.status = 404; - throw error; - } - - const { statusPage, monitors } = statusPageQuery[0]; - - const appSettings = await this.AppSettings.findOne({ singleton: true }).lean(); - const showURL = appSettings?.showURL === true; - - const normalizedMonitors = monitors.map((monitor) => { - const normalizedChecks = this.NormalizeData(monitor.checks, 10, 100); - if (!showURL) { - const { url, port, secret, notifications, ...rest } = monitor; - return { ...rest, checks: normalizedChecks }; - } - return { ...monitor, checks: normalizedChecks }; - }); - - return { statusPage, monitors: normalizedMonitors }; - } catch (error) { - error.service = SERVICE_NAME; - error.method = "getStatusPageByUrl"; - throw error; - } - }; - - deleteStatusPage = async (url) => { - try { - await this.StatusPage.deleteOne({ url }); - } catch (error) { - error.service = SERVICE_NAME; - error.method = "deleteStatusPage"; - throw error; - } - }; - deleteStatusPagesByMonitorId = async (monitorId) => { - try { - await this.StatusPage.deleteMany({ monitors: { $in: [monitorId] } }); - await this.StatusPage.deleteMany({ subMonitors: { $in: [monitorId] } }); - } catch (error) { - error.service = SERVICE_NAME; - error.method = "deleteStatusPageByMonitorId"; - throw error; - } - }; -} - -export default StatusPageModule; diff --git a/server/src/shutdown.js b/server/src/shutdown.ts similarity index 74% rename from server/src/shutdown.js rename to server/src/shutdown.ts index 27eb0f21d..2287a6a4a 100644 --- a/server/src/shutdown.js +++ b/server/src/shutdown.ts @@ -1,6 +1,7 @@ +import { InitializedServices } from "./config/services.js"; import { logger } from "./utils/logger.js"; -export const initShutdownListener = (server, services) => { +export const initShutdownListener = (server: any, services: InitializedServices) => { const SERVICE_NAME = "Server"; let isShuttingDown = false; @@ -19,11 +20,12 @@ export const initShutdownListener = (server, services) => { logger.info({ message: "Graceful shutdown complete" }); process.exit(0); } catch (error) { + const err = error as Error; logger.error({ - message: error.message, + message: err.message, service: SERVICE_NAME, method: "shutdown", - stack: error.stack, + stack: err.stack, }); process.exit(1); }