From 25d81f42380b5a6362593d56ceeb045069474346 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 10:43:56 -0700 Subject: [PATCH 1/8] remove dead findByMonitorIdAndDateRange method --- .../geo-checks/geo-check.repository.mongo.ts | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/server/src/domain/geo-checks/geo-check.repository.mongo.ts b/server/src/domain/geo-checks/geo-check.repository.mongo.ts index d1c56eb1c..5f4067ec7 100644 --- a/server/src/domain/geo-checks/geo-check.repository.mongo.ts +++ b/server/src/domain/geo-checks/geo-check.repository.mongo.ts @@ -187,30 +187,6 @@ class MongoGeoChecksRepository implements IGeoChecksRepository { } }; - findByMonitorIdAndDateRange = async (monitorId: string, startDate: Date, endDate: Date): Promise => { - try { - const docs = await GeoCheckModel.find({ - "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), - createdAt: { - $gte: startDate, - $lte: endDate, - }, - }).sort({ createdAt: -1 }); - return docs.map(this.toEntity); - } catch (error: unknown) { - this.logger.error({ - message: - error instanceof Error - ? `Error finding geo checks by monitor ID and date range: ${error.message}` - : "Error finding geo checks by monitor ID and date range", - service: SERVICE_NAME, - method: "findByMonitorIdAndDateRange", - stack: error instanceof Error ? error.stack : undefined, - }); - throw error; - } - }; - findGroupedByMonitorIdAndDateRange = async (monitorId: string, dateRange: DateRange, continents?: GeoContinent[]): Promise => { const start = getDateForRange(dateRange); const dateString = getDateFormat(dateRange); From 86eeda3f0efa2de62a71f2454dacadd03ef41534 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 10:49:39 -0700 Subject: [PATCH 2/8] replace error instances with AppError --- server/src/domain/checks/check.repository.mongo.ts | 8 +++++++- .../domain/geo-checks/geo-check.repository.interface.ts | 1 - server/src/domain/users/user.repository.mongo.ts | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/server/src/domain/checks/check.repository.mongo.ts b/server/src/domain/checks/check.repository.mongo.ts index 4bfb65dd4..f07f7b3ee 100644 --- a/server/src/domain/checks/check.repository.mongo.ts +++ b/server/src/domain/checks/check.repository.mongo.ts @@ -21,6 +21,7 @@ import { toStringId, toDateString } from "@/utils/mongoMappers.js"; import { getHardwareUpChecks, getHardwareStats, getHardwareTotalChecks } from "@/domain/checks/check.hardware.aggregations.js"; import { DateRange } from "@/types/query.js"; +import { AppError } from "@/utils/AppError.js"; const SERVICE_NAME = "StatusService"; @@ -181,7 +182,12 @@ class MongoChecksRepository implements IChecksRepository { // Map id to _id for MongoDB storage const { id, metadata, ...rest } = check; if (!metadata || !metadata.monitorId || !metadata.teamId) { - throw new Error(`Check must have valid metadata with monitorId and teamId. Got: ${JSON.stringify({ id, metadata })}`); + throw new AppError({ + message: `Check must have valid metadata with monitorId and teamId. Got: ${JSON.stringify({ id, metadata })}`, + status: 500, + service: SERVICE_NAME, + method: "toDocument", + }); } return { _id: id ? new mongoose.Types.ObjectId(id) : new mongoose.Types.ObjectId(), diff --git a/server/src/domain/geo-checks/geo-check.repository.interface.ts b/server/src/domain/geo-checks/geo-check.repository.interface.ts index a2cb7f84e..a9a81f57c 100644 --- a/server/src/domain/geo-checks/geo-check.repository.interface.ts +++ b/server/src/domain/geo-checks/geo-check.repository.interface.ts @@ -22,7 +22,6 @@ export interface IGeoChecksRepository { rowsPerPage: number, continents?: GeoContinent[] ): Promise; - findByMonitorIdAndDateRange(monitorId: string, startDate: Date, endDate: Date): Promise; findGroupedByMonitorIdAndDateRange(monitorId: string, DateRange: DateRange, continents?: GeoContinent[]): Promise; deleteByMonitorId(monitorId: string): Promise; deleteByTeamId(teamId: string): Promise; diff --git a/server/src/domain/users/user.repository.mongo.ts b/server/src/domain/users/user.repository.mongo.ts index af4b78b26..927df23ed 100644 --- a/server/src/domain/users/user.repository.mongo.ts +++ b/server/src/domain/users/user.repository.mongo.ts @@ -71,7 +71,7 @@ class MongoUsersRepository implements IUsersRepository { findById = async (id: string) => { const user = await UserModel.findById(id).select("-password").select("-profileImage"); if (!user) { - throw new Error("User not found"); + throw new AppError({ message: "User not found", service: SERVICE_NAME, status: 404 }); } return this.toEntity(user); From c021d04f5372ffa754c425cab7a7e6753d0fd6e5 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 11:09:53 -0700 Subject: [PATCH 3/8] extract swtich --- .../checks/check.repository.interface.ts | 10 +-- .../domain/checks/check.repository.mongo.ts | 77 ++++++------------- server/src/domain/checks/check.service.ts | 16 ++-- server/src/service/network/DNSProvider.ts | 3 +- server/src/service/network/DockerProvider.ts | 4 +- server/src/service/network/GameProvider.ts | 2 +- server/src/service/network/HttpProvider.ts | 3 +- server/src/service/network/PortProvider.ts | 3 +- .../src/service/network/WebSocketProvider.ts | 3 +- server/src/service/network/utils.ts | 3 - server/src/service/networkService.ts | 2 +- server/src/types/network.ts | 2 + .../test/unit/services/checkService.test.ts | 8 +- 13 files changed, 56 insertions(+), 80 deletions(-) diff --git a/server/src/domain/checks/check.repository.interface.ts b/server/src/domain/checks/check.repository.interface.ts index 8c921c843..2db5df712 100644 --- a/server/src/domain/checks/check.repository.interface.ts +++ b/server/src/domain/checks/check.repository.interface.ts @@ -8,7 +8,7 @@ import type { } from "@/domain/checks/check.type.js"; import type { MonitorType } from "@/domain/monitors/monitor.types.js"; import type { LatestChecksMap } from "@/domain/checks/check.repository.mongo.js"; -import { DateRange } from "@/types/query.js"; +import { CheckFilter, DateRange } from "@/types/query.js"; export interface IChecksRepository { // create @@ -21,18 +21,18 @@ export interface IChecksRepository { monitorId: string, sortOrder: string, dateRange: DateRange, - filter: string | undefined, page: number, rowsPerPage: number, - status: boolean | undefined + status: boolean | undefined, + filter?: CheckFilter ): Promise; findByTeamId( sortOrder: string, dateRange: DateRange, - filter: string | undefined, page: number, rowsPerPage: number, - teamId: string + teamId: string, + filter?: CheckFilter ): Promise; findLatestByMonitorIds(monitorIds: string[], options?: { limitPerMonitor?: number }): Promise; findByDateRangeAndMonitorId( diff --git a/server/src/domain/checks/check.repository.mongo.ts b/server/src/domain/checks/check.repository.mongo.ts index f07f7b3ee..4687f8ffc 100644 --- a/server/src/domain/checks/check.repository.mongo.ts +++ b/server/src/domain/checks/check.repository.mongo.ts @@ -20,8 +20,9 @@ import { ILogger } from "@/utils/logger.js"; import { toStringId, toDateString } from "@/utils/mongoMappers.js"; import { getHardwareUpChecks, getHardwareStats, getHardwareTotalChecks } from "@/domain/checks/check.hardware.aggregations.js"; -import { DateRange } from "@/types/query.js"; +import { CheckFilter, DateRange } from "@/types/query.js"; import { AppError } from "@/utils/AppError.js"; +import { NETWORK_ERROR } from "@/types/network.js"; const SERVICE_NAME = "StatusService"; @@ -211,46 +212,41 @@ class MongoChecksRepository implements IChecksRepository { return this.mapDocuments(inserted as unknown as CheckDocument[]); }; + private filterToMatch = (filter: CheckFilter | undefined): Record => { + switch (filter) { + case "up": + return { status: true }; + case "down": + return { status: false }; + case "resolve": + return { status: false, statusCode: NETWORK_ERROR }; + default: + this.logger.warn({ + message: "invalid filter", + service: SERVICE_NAME, + method: "filterToMatch", + }); + return {}; + } + }; + findByMonitorId = async ( monitorId: string, sortOrder: string, dateRange: DateRange, - filter: string | undefined, page: number, rowsPerPage: number, - status: boolean | undefined + status: boolean | undefined, + filter?: CheckFilter ) => { // Match const matchStage: Record = { "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), ...(typeof status !== "undefined" && { status }), createdAt: { $gte: getDateForRange(dateRange) }, + ...this.filterToMatch(filter), }; - if (filter !== undefined) { - switch (filter) { - case "all": - break; - case "up": - matchStage.status = true; - break; - case "down": - matchStage.status = false; - break; - case "resolve": - matchStage.status = false; - matchStage.statusCode = 5000; - break; - default: - this.logger.warn({ - message: "invalid filter", - service: SERVICE_NAME, - method: "getChecks", - }); - break; - } - } - //Sort const convertedSortOrder = sortOrder === "asc" ? 1 : -1; @@ -268,35 +264,12 @@ class MongoChecksRepository implements IChecksRepository { return { checksCount, checks: this.mapDocuments(checks) }; }; - findByTeamId = async (sortOrder: string, dateRange: DateRange, filter: string, page: number, rowsPerPage: number, teamId: string) => { + findByTeamId = async (sortOrder: string, dateRange: DateRange, page: number, rowsPerPage: number, teamId: string, filter?: CheckFilter) => { const matchStage: Record = { "metadata.teamId": new mongoose.Types.ObjectId(teamId), createdAt: { $gte: getDateForRange(dateRange) }, + ...this.filterToMatch(filter), }; - // Add filter to match stage - if (filter !== undefined) { - switch (filter) { - case "all": - break; - case "up": - matchStage.status = true; - break; - case "down": - matchStage.status = false; - break; - case "resolve": - matchStage.status = false; - matchStage.statusCode = 5000; - break; - default: - this.logger.warn({ - message: "invalid filter", - service: SERVICE_NAME, - method: "getChecksByTeam", - }); - break; - } - } const parsedSortOrder = sortOrder === "asc" ? 1 : -1; diff --git a/server/src/domain/checks/check.service.ts b/server/src/domain/checks/check.service.ts index b577658bd..40dd88f80 100644 --- a/server/src/domain/checks/check.service.ts +++ b/server/src/domain/checks/check.service.ts @@ -6,7 +6,7 @@ import type { MonitorPayloadMap, MonitorStatusResponse } from "@/types/network.j import type { HardwareStatusPayload, PageSpeedStatusPayload } from "@/types/network.js"; import { AppError } from "@/utils/AppError.js"; import { ILogger } from "@/utils/logger.js"; -import { DateRange } from "@/types/query.js"; +import { CheckFilter, DateRange } from "@/types/query.js"; const SERVICE_NAME = "checkService"; @@ -22,7 +22,7 @@ export interface ICheckService { dateRange: DateRange; page: number; rowsPerPage: number; - filter?: string; + filter?: CheckFilter; status?: boolean; }): Promise; getChecksByTeam(params: { @@ -31,7 +31,7 @@ export interface ICheckService { dateRange: DateRange; page: number; rowsPerPage: number; - filter?: string; + filter?: CheckFilter; }): Promise; getChecksSummaryByTeamId(params: { teamId: string; dateRange: DateRange }): Promise; deleteChecks(params: { monitorId: string; teamId: string }): Promise; @@ -169,7 +169,7 @@ export class CheckService implements ICheckService { page: number; rowsPerPage: number; status?: boolean; - filter?: string; + filter: CheckFilter; }) => { if (!monitorId) { throw new AppError({ message: "No monitor ID in request", service: SERVICE_NAME, method: "getChecksByMonitor", status: 400 }); @@ -184,7 +184,7 @@ export class CheckService implements ICheckService { const parsedPage = page ?? 0; const parsedRowsPerPage = rowsPerPage ?? 5; - const result = await this.checksRepository.findByMonitorId(monitorId, sortOrder, dateRange, filter, parsedPage, parsedRowsPerPage, status); + const result = await this.checksRepository.findByMonitorId(monitorId, sortOrder, dateRange, parsedPage, parsedRowsPerPage, status, filter); return result; }; @@ -193,21 +193,21 @@ export class CheckService implements ICheckService { teamId, sortOrder, dateRange, - filter, page, rowsPerPage, + filter, }: { teamId: string; sortOrder: string; dateRange: DateRange; page: number; rowsPerPage: number; - filter?: string; + filter?: CheckFilter; }) => { const parsedPage = page ?? 0; const parsedRowsPerPage = rowsPerPage ?? 5; - const checkData = await this.checksRepository.findByTeamId(sortOrder, dateRange, filter, parsedPage, parsedRowsPerPage, teamId); + const checkData = await this.checksRepository.findByTeamId(sortOrder, dateRange, parsedPage, parsedRowsPerPage, teamId, filter); return checkData; }; diff --git a/server/src/service/network/DNSProvider.ts b/server/src/service/network/DNSProvider.ts index 1aeff7e14..ff136db0e 100644 --- a/server/src/service/network/DNSProvider.ts +++ b/server/src/service/network/DNSProvider.ts @@ -3,7 +3,8 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import type { Resolver } from "dns/promises"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR, timeRequest } from "@/service/network/utils.js"; +import { timeRequest } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; const SERVICE_NAME = "DNSProvider"; diff --git a/server/src/service/network/DockerProvider.ts b/server/src/service/network/DockerProvider.ts index 0cfb133af..5e5d7b630 100644 --- a/server/src/service/network/DockerProvider.ts +++ b/server/src/service/network/DockerProvider.ts @@ -4,8 +4,8 @@ import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { ILogger } from "@/utils/logger.js"; import { AppError } from "@/utils/AppError.js"; import Dockerode from "dockerode"; -import { NETWORK_ERROR, timeRequest } from "@/service/network/utils.js"; - +import { timeRequest } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; type DockerodeType = typeof Dockerode; const SERVICE_NAME = "DockerProvider"; diff --git a/server/src/service/network/GameProvider.ts b/server/src/service/network/GameProvider.ts index 4e063396d..1a07de791 100644 --- a/server/src/service/network/GameProvider.ts +++ b/server/src/service/network/GameProvider.ts @@ -3,7 +3,7 @@ import { GameStatusPayload, MonitorStatusResponse } from "@/types/network.js"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { GameDig } from "gamedig"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import { ILogger } from "@/utils/logger.js"; type GameDigType = typeof GameDig; diff --git a/server/src/service/network/HttpProvider.ts b/server/src/service/network/HttpProvider.ts index 2f08dab00..fb974cac1 100644 --- a/server/src/service/network/HttpProvider.ts +++ b/server/src/service/network/HttpProvider.ts @@ -6,7 +6,8 @@ import { MonitorStatusResponse } from "@/types/network.js"; import { Agent as HttpsAgent } from "https"; import { Agent as HttpAgent } from "http"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; -import { NETWORK_ERROR, isStatusUp } from "@/service/network/utils.js"; +import { isStatusUp } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import CacheableLookup from "cacheable-lookup"; export class HttpProvider implements IStatusProvider { diff --git a/server/src/service/network/PortProvider.ts b/server/src/service/network/PortProvider.ts index debcd8509..b59eb5907 100644 --- a/server/src/service/network/PortProvider.ts +++ b/server/src/service/network/PortProvider.ts @@ -2,7 +2,8 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { PortStatusPayload, MonitorStatusResponse } from "@/types/network.js"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR, timeRequest } from "@/service/network/utils.js"; +import { timeRequest } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import * as net from "net"; type NetType = typeof net; diff --git a/server/src/service/network/WebSocketProvider.ts b/server/src/service/network/WebSocketProvider.ts index fef5f76b1..b599e6fab 100644 --- a/server/src/service/network/WebSocketProvider.ts +++ b/server/src/service/network/WebSocketProvider.ts @@ -2,7 +2,8 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { WebSocketStatusPayload, MonitorStatusResponse } from "@/types/network.js"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR, timeRequest } from "@/service/network/utils.js"; +import { timeRequest } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import type WebSocket from "ws"; type WebSocketConstructor = typeof WebSocket; diff --git a/server/src/service/network/utils.ts b/server/src/service/network/utils.ts index 8bcbc4335..5a23a9412 100644 --- a/server/src/service/network/utils.ts +++ b/server/src/service/network/utils.ts @@ -12,9 +12,6 @@ export const timeRequest = async (operation: () => Promise): Promise<{ res } }; -export const NETWORK_ERROR = 5000; -export const PING_ERROR = 5001; - export const isStatusUp = (statusCode: number | undefined, customUpCodes: HttpStatusCode[] = []): boolean => { if (statusCode === undefined) return false; return (statusCode >= 200 && statusCode < 300) || customUpCodes.includes(statusCode); diff --git a/server/src/service/networkService.ts b/server/src/service/networkService.ts index 632a03141..ec54b8e49 100644 --- a/server/src/service/networkService.ts +++ b/server/src/service/networkService.ts @@ -2,7 +2,7 @@ import type { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import type { MonitorPayloadMap, MonitorStatusResponse } from "@/types/network.js"; import type { AxiosStatic } from "axios"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import { ILogger } from "@/utils/logger.js"; import { IStatusProvider } from "./network/IStatusProvider.js"; const SERVICE_NAME = "NetworkService"; diff --git a/server/src/types/network.ts b/server/src/types/network.ts index fe85221f2..b5dc1d949 100644 --- a/server/src/types/network.ts +++ b/server/src/types/network.ts @@ -13,6 +13,8 @@ import type { DnsRecordType, Monitor, MonitorMatchMethod, MonitorStatus, Monitor import type { QueryResult } from "gamedig"; +export const NETWORK_ERROR = 5000; + export interface MonitorStatusResponse< T = | HttpStatusPayload diff --git a/server/test/unit/services/checkService.test.ts b/server/test/unit/services/checkService.test.ts index 587731951..8c58259e3 100644 --- a/server/test/unit/services/checkService.test.ts +++ b/server/test/unit/services/checkService.test.ts @@ -375,7 +375,7 @@ describe("CheckService", () => { rowsPerPage: null as any, }); - expect(checksRepository.findByMonitorId).toHaveBeenCalledWith("mon-1", "desc", "day", undefined, 0, 5, undefined); + expect(checksRepository.findByMonitorId).toHaveBeenCalledWith("mon-1", "desc", "day", 0, 5, undefined, undefined); }); it("passes filter and status parameters", async () => { @@ -388,11 +388,11 @@ describe("CheckService", () => { dateRange: "week", page: 2, rowsPerPage: 20, - filter: "error", + filter: "resolve", status: false, }); - expect(checksRepository.findByMonitorId).toHaveBeenCalledWith("mon-1", "asc", "week", "error", 2, 20, false); + expect(checksRepository.findByMonitorId).toHaveBeenCalledWith("mon-1", "asc", "week", 2, 20, false, "resolve"); }); it("throws when monitorId is missing", async () => { @@ -443,7 +443,7 @@ describe("CheckService", () => { await service.getChecksByTeam({ teamId: "team-1", sortOrder: "desc", dateRange: "day", page: null as any, rowsPerPage: null as any }); - expect(checksRepository.findByTeamId).toHaveBeenCalledWith("desc", "day", undefined, 0, 5, "team-1"); + expect(checksRepository.findByTeamId).toHaveBeenCalledWith("desc", "day", 0, 5, "team-1", undefined); }); }); From ed36db172a1e7c5793770529e99245f1ccdaf4f2 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 11:32:00 -0700 Subject: [PATCH 4/8] dedupe hardware stat definitions, fix tests, remove misleading null return types --- server/src/api/controllers/controllerUtils.ts | 2 +- server/src/api/validation/checkValidation.ts | 2 +- .../src/api/validation/monitorValidation.ts | 2 +- .../checks/check.hardware.aggregations.ts | 17 +++- server/src/domain/checks/check.model.ts | 2 +- .../checks/check.repository.interface.ts | 2 +- .../domain/checks/check.repository.mongo.ts | 59 +++++++------ server/src/domain/checks/check.type.ts | 85 ++++++++++--------- .../src/domain/geo-checks/geo-check.model.ts | 2 +- .../domain/geo-checks/geo-check.service.ts | 2 +- .../src/domain/geo-checks/geo-check.type.ts | 2 +- .../src/domain/incidents/incident.service.ts | 2 +- server/src/domain/monitors/monitor.model.ts | 4 +- .../monitors/monitor.repository.interface.ts | 8 +- .../monitors/monitor.repository.mongo.ts | 6 +- server/src/domain/monitors/monitor.service.ts | 13 ++- .../{monitor.types.ts => monitor.type.ts} | 43 +--------- .../notification.message-builder.ts | 2 +- .../notifications/notification.service.ts | 2 +- .../status-pages/status-page.service.ts | 2 +- .../domain/status-pages/status-page.type.ts | 2 +- server/src/service/globalPingService.ts | 4 +- server/src/service/network/AdvancedMatcher.ts | 2 +- server/src/service/network/DNSProvider.ts | 2 +- server/src/service/network/DockerProvider.ts | 2 +- server/src/service/network/GameProvider.ts | 2 +- server/src/service/network/GrpcProvider.ts | 2 +- .../src/service/network/HardwareProvider.ts | 2 +- server/src/service/network/HttpProvider.ts | 2 +- server/src/service/network/IStatusProvider.ts | 2 +- .../src/service/network/PageSpeedProvider.ts | 2 +- server/src/service/network/PingProvider.ts | 2 +- server/src/service/network/PortProvider.ts | 2 +- .../src/service/network/WebSocketProvider.ts | 2 +- server/src/service/network/utils.ts | 2 +- server/src/service/networkService.ts | 2 +- server/src/service/statusService.ts | 4 +- server/src/types/network.ts | 2 +- server/src/worker/worker.check-evaluator.ts | 2 +- server/src/worker/worker.check-pipeline.ts | 4 +- server/src/worker/worker.check-producer.ts | 2 +- server/src/worker/worker.interface.ts | 2 +- server/src/worker/worker.job-scheduler.ts | 4 +- 43 files changed, 148 insertions(+), 165 deletions(-) rename server/src/domain/monitors/{monitor.types.ts => monitor.type.ts} (87%) diff --git a/server/src/api/controllers/controllerUtils.ts b/server/src/api/controllers/controllerUtils.ts index be3f46533..1980ec0b4 100755 --- a/server/src/api/controllers/controllerUtils.ts +++ b/server/src/api/controllers/controllerUtils.ts @@ -1,5 +1,5 @@ import { AppError } from "@/utils/AppError.js"; -import { Monitor, MonitorTypes, type MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorTypes, type MonitorType } from "@/domain/monitors/monitor.type.js"; import { UserRole } from "@/domain/users/user.type.js"; import sslChecker, { SSLDetails } from "ssl-checker"; type SSLCheckerType = typeof sslChecker; diff --git a/server/src/api/validation/checkValidation.ts b/server/src/api/validation/checkValidation.ts index d041c9e8f..e40d11024 100644 --- a/server/src/api/validation/checkValidation.ts +++ b/server/src/api/validation/checkValidation.ts @@ -1,7 +1,7 @@ import { z } from "zod"; import { booleanCoercion } from "./shared.js"; import { GeoContinents } from "@/domain/geo-checks/geo-check.type.js"; -import { MonitorTypes } from "@/domain/monitors/monitor.types.js"; +import { MonitorTypes } from "@/domain/monitors/monitor.type.js"; import { CheckFilters, DateRanges, SortOrders } from "@/types/query.js"; //**************************************** diff --git a/server/src/api/validation/monitorValidation.ts b/server/src/api/validation/monitorValidation.ts index 1ed9dca84..37a31fc6a 100644 --- a/server/src/api/validation/monitorValidation.ts +++ b/server/src/api/validation/monitorValidation.ts @@ -10,7 +10,7 @@ import { MonitorStatuses, MonitorTypes, PageSpeedStrategies, -} from "@/domain/monitors/monitor.types.js"; +} from "@/domain/monitors/monitor.type.js"; import { DateRanges, SortOrders } from "@/types/query.js"; const httpStatusCode = z.number().refine((code) => HttpStatusCodeSet.has(code), { message: "Must be a valid HTTP status code" }); diff --git a/server/src/domain/checks/check.hardware.aggregations.ts b/server/src/domain/checks/check.hardware.aggregations.ts index 176817315..6c672b630 100644 --- a/server/src/domain/checks/check.hardware.aggregations.ts +++ b/server/src/domain/checks/check.hardware.aggregations.ts @@ -1,9 +1,22 @@ import { CheckModel } from "@/domain/checks/check.model.js"; import mongoose from "mongoose"; +import type { HardwareDiskStats, HardwareNetStats } from "@/domain/checks/check.type.js"; type DateRange = { start: Date; end: Date }; type HardwareUpChecks = { totalChecks: number }; +// $avg yields null when no values are present, so metrics are nullable until the repository applies fallbacks +type NullableValues = { [K in keyof T]: T[K] | null }; + +export type HardwareStatsBucket = { + _id: string; + avgCpuUsage: number | null; + avgMemoryUsage: number | null; + avgTemperature: number[]; + disks: NullableValues[]; + net: NullableValues[]; +}; + const NET_RATE_FIELDS = [ ["bytesSentPerSecond", "bytes_sent"], ["deltaBytesRecv", "bytes_recv"], @@ -70,13 +83,13 @@ export const getHardwareUpChecks = async (monitorId: string, dates: DateRange): return { totalChecks: count }; }; -export const getHardwareStats = async (monitorId: string, dates: DateRange, dateString: string) => { +export const getHardwareStats = async (monitorId: string, dates: DateRange, dateString: string): Promise => { const netProjection = { name: { $arrayElemAt: ["$sampleDoc.net.name", "$$nIdx"] }, ...Object.fromEntries(NET_RATE_FIELDS.map(([outputKey, sourceField]) => [outputKey, netRatePerSecond(sourceField)])), }; - return await CheckModel.aggregate([ + return await CheckModel.aggregate([ { $match: { "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), diff --git a/server/src/domain/checks/check.model.ts b/server/src/domain/checks/check.model.ts index c3fbc23ff..9f3c2fbc1 100644 --- a/server/src/domain/checks/check.model.ts +++ b/server/src/domain/checks/check.model.ts @@ -1,5 +1,5 @@ import { Schema, model, Types } from "mongoose"; -import { MonitorTypes, type MonitorType } from "@/domain/monitors/monitor.types.js"; +import { MonitorTypes, type MonitorType } from "@/domain/monitors/monitor.type.js"; import type { Check, CheckAudits, diff --git a/server/src/domain/checks/check.repository.interface.ts b/server/src/domain/checks/check.repository.interface.ts index 2db5df712..e6b7c6368 100644 --- a/server/src/domain/checks/check.repository.interface.ts +++ b/server/src/domain/checks/check.repository.interface.ts @@ -6,7 +6,7 @@ import type { PageSpeedChecksResult, UptimeChecksResult, } from "@/domain/checks/check.type.js"; -import type { MonitorType } from "@/domain/monitors/monitor.types.js"; +import type { MonitorType } from "@/domain/monitors/monitor.type.js"; import type { LatestChecksMap } from "@/domain/checks/check.repository.mongo.js"; import { CheckFilter, DateRange } from "@/types/query.js"; diff --git a/server/src/domain/checks/check.repository.mongo.ts b/server/src/domain/checks/check.repository.mongo.ts index 4687f8ffc..9767947d9 100644 --- a/server/src/domain/checks/check.repository.mongo.ts +++ b/server/src/domain/checks/check.repository.mongo.ts @@ -11,8 +11,9 @@ import type { CheckMetadata, CheckNetworkInterfaceInfo, GotTimings, + HardwareCheckStats, } from "@/domain/checks/check.type.js"; -import type { MonitorType } from "@/domain/monitors/monitor.types.js"; +import type { MonitorType } from "@/domain/monitors/monitor.type.js"; import { CheckModel, type CheckDocument } from "@/domain/checks/check.model.js"; import mongoose from "mongoose"; import { getDateFormat, getDateForRange } from "@/utils/dataUtils.js"; @@ -512,33 +513,35 @@ class MongoChecksRepository implements IChecksRepository { totalChecks: upChecksDoc?.totalChecks ?? 0, }; - const checks = (hardwareMetrics ?? []).map((metric) => ({ - bucketDate: metric._id, - avgCpuUsage: metric.avgCpuUsage ?? 0, - avgMemoryUsage: metric.avgMemoryUsage ?? 0, - avgTemperature: metric.avgTemperature ?? [], - disks: (metric.disks ?? []).map((disk: { [key: string]: number | string | undefined }) => ({ - name: disk?.name ?? "", - readSpeed: disk?.readSpeed ?? 0, - writeSpeed: disk?.writeSpeed ?? 0, - totalBytes: disk?.totalBytes ?? 0, - freeBytes: disk?.freeBytes ?? 0, - usagePercent: disk?.usagePercent ?? 0, - })), - net: (metric.net ?? []).map((iface: { [key: string]: number | string | undefined }) => ({ - name: iface?.name ?? "", - bytesSentPerSecond: iface?.bytesSentPerSecond ?? 0, - deltaBytesRecv: iface?.deltaBytesRecv ?? 0, - deltaPacketsSent: iface?.deltaPacketsSent ?? 0, - deltaPacketsRecv: iface?.deltaPacketsRecv ?? 0, - deltaErrIn: iface?.deltaErrIn ?? 0, - deltaErrOut: iface?.deltaErrOut ?? 0, - deltaDropIn: iface?.deltaDropIn ?? 0, - deltaDropOut: iface?.deltaDropOut ?? 0, - deltaFifoIn: iface?.deltaFifoIn ?? 0, - deltaFifoOut: iface?.deltaFifoOut ?? 0, - })), - })); + const checks = (hardwareMetrics ?? []).map( + (metric): HardwareCheckStats => ({ + bucketDate: metric._id, + avgCpuUsage: metric.avgCpuUsage ?? 0, + avgMemoryUsage: metric.avgMemoryUsage ?? 0, + avgTemperature: metric.avgTemperature ?? [], + disks: (metric.disks ?? []).map((disk) => ({ + name: disk?.name ?? "", + readSpeed: disk?.readSpeed ?? 0, + writeSpeed: disk?.writeSpeed ?? 0, + totalBytes: disk?.totalBytes ?? 0, + freeBytes: disk?.freeBytes ?? 0, + usagePercent: disk?.usagePercent ?? 0, + })), + net: (metric.net ?? []).map((iface) => ({ + name: iface?.name ?? "", + bytesSentPerSecond: iface?.bytesSentPerSecond ?? 0, + deltaBytesRecv: iface?.deltaBytesRecv ?? 0, + deltaPacketsSent: iface?.deltaPacketsSent ?? 0, + deltaPacketsRecv: iface?.deltaPacketsRecv ?? 0, + deltaErrIn: iface?.deltaErrIn ?? 0, + deltaErrOut: iface?.deltaErrOut ?? 0, + deltaDropIn: iface?.deltaDropIn ?? 0, + deltaDropOut: iface?.deltaDropOut ?? 0, + deltaFifoIn: iface?.deltaFifoIn ?? 0, + deltaFifoOut: iface?.deltaFifoOut ?? 0, + })), + }) + ); return { monitorType: "hardware" as const, diff --git a/server/src/domain/checks/check.type.ts b/server/src/domain/checks/check.type.ts index fe733e4e9..faac84cef 100644 --- a/server/src/domain/checks/check.type.ts +++ b/server/src/domain/checks/check.type.ts @@ -1,4 +1,4 @@ -import type { MonitorType } from "@/domain/monitors/monitor.types.js"; +import type { MonitorType } from "@/domain/monitors/monitor.type.js"; import type { Response } from "got"; export const CHECK_TTL_SENTINEL = 366; @@ -126,43 +126,6 @@ export interface PageSpeedChecksResult { groupedChecks: PageSpeedGroupedCheck[]; } -export interface HardwareChecksResult { - monitorType: "hardware"; - aggregateData: { - totalChecks: number; - }; - upChecks: { - totalChecks: number; - }; - checks: Array<{ - bucketDate: string; - avgCpuUsage: number; - avgMemoryUsage: number; - avgTemperature: number[]; - disks: Array<{ - name: string; - readSpeed: number; - writeSpeed: number; - totalBytes: number; - freeBytes: number; - usagePercent: number; - }>; - net: Array<{ - name: string; - bytesSentPerSecond: number; - deltaBytesRecv: number; - deltaPacketsSent: number; - deltaPacketsRecv: number; - deltaErrIn: number; - deltaErrOut: number; - deltaDropIn: number; - deltaDropOut: number; - deltaFifoIn: number; - deltaFifoOut: number; - }>; - }>; -} - export interface GroupedCheck { bucketDate: string; avgResponseTime: number; @@ -205,3 +168,49 @@ export type NormalizedUptimeCheck = T & { }; export type CheckSnapshot = Omit; + +export interface HardwareDiskStats { + name: string; + readSpeed: number; + writeSpeed: number; + totalBytes: number; + freeBytes: number; + usagePercent: number; +} + +export interface HardwareNetStats { + name: string; + bytesSentPerSecond: number; + deltaBytesRecv: number; + deltaPacketsSent: number; + deltaPacketsRecv: number; + deltaErrIn: number; + deltaErrOut: number; + deltaDropIn: number; + deltaDropOut: number; + deltaFifoIn: number; + deltaFifoOut: number; +} + +export interface HardwareCheckStats { + bucketDate: string; + avgCpuUsage: number; + avgMemoryUsage: number; + avgTemperature: number[]; + disks: HardwareDiskStats[]; + net: HardwareNetStats[]; +} + +export interface HardwareStats { + aggregateData: { + totalChecks: number; + }; + upChecks: { + totalChecks: number; + }; + checks: HardwareCheckStats[]; +} + +export interface HardwareChecksResult extends HardwareStats { + monitorType: "hardware"; +} diff --git a/server/src/domain/geo-checks/geo-check.model.ts b/server/src/domain/geo-checks/geo-check.model.ts index 0db895d0a..512979ea5 100644 --- a/server/src/domain/geo-checks/geo-check.model.ts +++ b/server/src/domain/geo-checks/geo-check.model.ts @@ -1,5 +1,5 @@ import { Schema, model, Types } from "mongoose"; -import { MonitorTypes, type MonitorType } from "@/domain/monitors/monitor.types.js"; +import { MonitorTypes, type MonitorType } from "@/domain/monitors/monitor.type.js"; import type { GeoCheck, GeoCheckLocation, GeoCheckMetadata, GeoCheckResult, GeoCheckTimings } from "@/domain/geo-checks/geo-check.type.js"; type GeoCheckMetadataDocument = Omit & { diff --git a/server/src/domain/geo-checks/geo-check.service.ts b/server/src/domain/geo-checks/geo-check.service.ts index 26d347228..3b9f19b4d 100644 --- a/server/src/domain/geo-checks/geo-check.service.ts +++ b/server/src/domain/geo-checks/geo-check.service.ts @@ -1,5 +1,5 @@ import type { GeoCheck } from "@/domain/geo-checks/geo-check.type.js"; -import type { Monitor } from "@/domain/monitors/monitor.types.js"; +import type { Monitor } from "@/domain/monitors/monitor.type.js"; import type { GeoCheckResult, GeoContinent } from "@/domain/geo-checks/geo-check.type.js"; import { Types } from "mongoose"; import type { FlatGeoChecksQueryResult, IGeoChecksRepository } from "@/domain/geo-checks/geo-check.repository.interface.js"; diff --git a/server/src/domain/geo-checks/geo-check.type.ts b/server/src/domain/geo-checks/geo-check.type.ts index 044bec3b0..e2eea9f25 100644 --- a/server/src/domain/geo-checks/geo-check.type.ts +++ b/server/src/domain/geo-checks/geo-check.type.ts @@ -1,4 +1,4 @@ -import type { MonitorType } from "@/domain/monitors/monitor.types.js"; +import type { MonitorType } from "@/domain/monitors/monitor.type.js"; export const GeoContinents = ["EU", "NA", "AS", "SA", "AF", "OC"] as const; export type GeoContinent = (typeof GeoContinents)[number]; diff --git a/server/src/domain/incidents/incident.service.ts b/server/src/domain/incidents/incident.service.ts index 9b8fbf25e..a9851d85e 100644 --- a/server/src/domain/incidents/incident.service.ts +++ b/server/src/domain/incidents/incident.service.ts @@ -1,5 +1,5 @@ const SERVICE_NAME = "incidentService"; -import type { Monitor } from "@/domain/monitors/monitor.types.js"; +import type { Monitor } from "@/domain/monitors/monitor.type.js"; import type { MonitorStatusResponse } from "@/types/network.js"; import { AppError } from "@/utils/AppError.js"; import { getDateForRange } from "@/utils/dataUtils.js"; diff --git a/server/src/domain/monitors/monitor.model.ts b/server/src/domain/monitors/monitor.model.ts index 47aa70b5e..446631f45 100644 --- a/server/src/domain/monitors/monitor.model.ts +++ b/server/src/domain/monitors/monitor.model.ts @@ -1,6 +1,6 @@ import { Schema, model, Types } from "mongoose"; -import type { Monitor, MonitorMatchMethod, CheckSnapshot } from "@/domain/monitors/monitor.types.js"; -import { DnsRecordTypes, MonitorTypes, MonitorStatuses, PageSpeedStrategies, HttpMethods } from "@/domain/monitors/monitor.types.js"; +import type { Monitor, MonitorMatchMethod, CheckSnapshot } from "@/domain/monitors/monitor.type.js"; +import { DnsRecordTypes, MonitorTypes, MonitorStatuses, PageSpeedStrategies, HttpMethods } from "@/domain/monitors/monitor.type.js"; import type { CheckAudits, CheckCaptureInfo, diff --git a/server/src/domain/monitors/monitor.repository.interface.ts b/server/src/domain/monitors/monitor.repository.interface.ts index a710e366f..d3dc0597e 100644 --- a/server/src/domain/monitors/monitor.repository.interface.ts +++ b/server/src/domain/monitors/monitor.repository.interface.ts @@ -1,4 +1,4 @@ -import type { MonitorType, Monitor, MonitorStatus, MonitorsSummary, CheckSnapshot } from "@/domain/monitors/monitor.types.js"; +import type { MonitorType, Monitor, MonitorStatus, MonitorsSummary, CheckSnapshot } from "@/domain/monitors/monitor.type.js"; export interface TeamQueryConfig { limit?: number; @@ -26,9 +26,9 @@ export interface IMonitorsRepository { findByIdLean(monitorId: string): Promise; // collection fetch - findAll(): Promise; - findByTeamId(teamId: string, config: TeamQueryConfig): Promise; - findByTeamIdWithStats(teamId: string, config: TeamQueryConfig): Promise; + findAll(): Promise; + findByTeamId(teamId: string, config: TeamQueryConfig): Promise; + findByTeamIdWithStats(teamId: string, config: TeamQueryConfig): Promise; findByIds(monitorIds: string[]): Promise; findByIdsWithChecks(monitorIds: string[], checksCount?: number): Promise; diff --git a/server/src/domain/monitors/monitor.repository.mongo.ts b/server/src/domain/monitors/monitor.repository.mongo.ts index d9e35855c..b96ec3907 100644 --- a/server/src/domain/monitors/monitor.repository.mongo.ts +++ b/server/src/domain/monitors/monitor.repository.mongo.ts @@ -1,7 +1,7 @@ import { MonitorModel } from "@/domain/monitors/monitor.model.js"; import type { MonitorDocument, CheckSnapshotDocument } from "@/domain/monitors/monitor.model.js"; import type { CheckSnapshot } from "@/domain/checks/check.type.js"; -import type { Monitor, MonitorStatus, MonitorsSummary } from "@/domain/monitors/monitor.types.js"; +import type { Monitor, MonitorStatus, MonitorsSummary } from "@/domain/monitors/monitor.type.js"; import mongoose, { type FilterQuery, type PipelineStage } from "mongoose"; import { MongoBulkWriteError } from "mongodb"; import { AppError } from "@/utils/AppError.js"; @@ -96,14 +96,14 @@ class MongoMonitorsRepository implements IMonitorsRepository { return { sort: { [field]: order === "asc" ? 1 : -1 } as const, skip: Math.max(page, 0) * rowsPerPage, limit: rowsPerPage }; }; - findByTeamId = async (teamId: string, config: TeamQueryConfig): Promise => { + findByTeamId = async (teamId: string, config: TeamQueryConfig): Promise => { const query = this.queryBuilder(config, teamId); const { sort, skip, limit } = this.pageOptions(config); const documents = await MonitorModel.find(query).sort(sort).skip(skip).limit(limit); return this.mapDocuments(documents); }; - findByTeamIdWithStats = async (teamId: string, config: TeamQueryConfig): Promise => { + findByTeamIdWithStats = async (teamId: string, config: TeamQueryConfig): Promise => { const { sort, skip, limit } = this.pageOptions(config); const query = this.queryBuilder(config, teamId); diff --git a/server/src/domain/monitors/monitor.service.ts b/server/src/domain/monitors/monitor.service.ts index 711fc9b9b..178da5225 100644 --- a/server/src/domain/monitors/monitor.service.ts +++ b/server/src/domain/monitors/monitor.service.ts @@ -1,5 +1,5 @@ import { NormalizeData, NormalizeDataUptimeDetails } from "@/utils/dataUtils.js"; -import { type Monitor } from "@/domain/monitors/monitor.types.js"; +import { type Monitor } from "@/domain/monitors/monitor.type.js"; import type { MonitorType, MonitorsWithChecksByTeamIdResult, @@ -8,8 +8,8 @@ import type { PageSpeedDetailsResult, GamesMap, GroupedGeoCheckResult, -} from "@/domain/monitors/monitor.types.js"; -import { supportsGeoCheck, supportsUptimeDetails } from "@/domain/monitors/monitor.types.js"; +} from "@/domain/monitors/monitor.type.js"; +import { supportsGeoCheck, supportsUptimeDetails } from "@/domain/monitors/monitor.type.js"; import type { UptimeChecksResult, HardwareChecksResult, PageSpeedChecksResult } from "@/domain/checks/check.type.js"; import type { GeoContinent } from "@/domain/geo-checks/geo-check.type.js"; import type { IChecksRepository } from "@/domain/checks/check.repository.interface.js"; @@ -318,7 +318,7 @@ export class MonitorService implements IMonitorService { type?: MonitorType | MonitorType[]; tags?: string | string[]; filter?: string; - }): Promise => { + }): Promise => { return await this.monitorsRepository.findByTeamId(teamId, { type, tags, filter }); }; @@ -356,13 +356,12 @@ export class MonitorService implements IMonitorService { order, }); - const monitorsList = (monitors ?? []) as Monitor[]; const snapshotTypes: MonitorType[] = ["hardware"]; const requestedTypes = Array.isArray(type) ? type : type ? [type] : []; const snapshotOnlyRequest = requestedTypes.length > 0 && requestedTypes.every((requestedType) => snapshotTypes.includes(requestedType as MonitorType)); - const monitorsWithChecks = monitorsList.map((monitor: Monitor) => { + const monitorsWithChecks = monitors.map((monitor: Monitor) => { const rawChecks = monitor.recentChecks ?? []; const isSnapshotType = snapshotOnlyRequest || snapshotTypes.includes(monitor.type); const checks = isSnapshotType ? rawChecks.slice(0, 1) : NormalizeData(rawChecks, 10, 100); @@ -523,7 +522,7 @@ export class MonitorService implements IMonitorService { exportMonitorsToJSON = async ({ teamId }: { teamId: string }): Promise => { const monitors = await this.monitorsRepository.findByTeamId(teamId, {}); - if (!monitors || monitors.length === 0) { + if (monitors.length === 0) { throw new AppError({ message: "No monitors found to export.", service: SERVICE_NAME, method: "exportMonitorsToJSON", status: 400 }); } diff --git a/server/src/domain/monitors/monitor.types.ts b/server/src/domain/monitors/monitor.type.ts similarity index 87% rename from server/src/domain/monitors/monitor.types.ts rename to server/src/domain/monitors/monitor.type.ts index 22090f68c..865bafd76 100644 --- a/server/src/domain/monitors/monitor.types.ts +++ b/server/src/domain/monitors/monitor.type.ts @@ -3,6 +3,7 @@ export type { CheckSnapshot } from "@/domain/checks/check.type.js"; import type { GeoContinent, GroupedGeoCheck } from "@/domain/geo-checks/geo-check.type.js"; export type { GeoContinent } from "@/domain/geo-checks/geo-check.type.js"; import http from "node:http"; +import { HardwareStats } from "@/domain/checks/check.type.js"; export const HttpStatusCodes = [ ...Object.keys(http.STATUS_CODES).map(Number), @@ -149,48 +150,6 @@ export interface UptimeDetailsResult { monitorStats: import("../monitor-stats/monitor-stats.type.js").MonitorStats | null; } -export interface HardwareDiskStats { - name: string; - readSpeed: number; - writeSpeed: number; - totalBytes: number; - freeBytes: number; - usagePercent: number; -} - -export interface HardwareNetStats { - name: string; - bytesSentPerSecond: number; - deltaBytesRecv: number; - deltaPacketsSent: number; - deltaPacketsRecv: number; - deltaErrIn: number; - deltaErrOut: number; - deltaDropIn: number; - deltaDropOut: number; - deltaFifoIn: number; - deltaFifoOut: number; -} - -export interface HardwareCheckStats { - bucketDate: string; - avgCpuUsage: number; - avgMemoryUsage: number; - avgTemperature: number[]; - disks: HardwareDiskStats[]; - net: HardwareNetStats[]; -} - -export interface HardwareStats { - aggregateData: { - totalChecks: number; - }; - upChecks: { - totalChecks: number; - }; - checks: HardwareCheckStats[]; -} - export interface HardwareDetailsResult { monitor: Monitor; stats: HardwareStats; diff --git a/server/src/domain/notifications/notification.message-builder.ts b/server/src/domain/notifications/notification.message-builder.ts index b11d99a94..76e9f6447 100644 --- a/server/src/domain/notifications/notification.message-builder.ts +++ b/server/src/domain/notifications/notification.message-builder.ts @@ -1,4 +1,4 @@ -import type { Monitor } from "@/domain/monitors/monitor.types.js"; +import type { Monitor } from "@/domain/monitors/monitor.type.js"; import type { HardwareStatusPayload, MonitorStatusResponse } from "@/types/network.js"; import type { MonitorActionDecision } from "@/worker/worker.helper.js"; import type { diff --git a/server/src/domain/notifications/notification.service.ts b/server/src/domain/notifications/notification.service.ts index 30141c3ea..61d8d09e3 100644 --- a/server/src/domain/notifications/notification.service.ts +++ b/server/src/domain/notifications/notification.service.ts @@ -1,4 +1,4 @@ -import type { Monitor } from "@/domain/monitors/monitor.types.js"; +import type { Monitor } from "@/domain/monitors/monitor.type.js"; import type { Notification } from "@/domain/notifications/notification.type.js"; import type { MonitorStatusResponse } from "@/types/network.js"; import type { NotificationMessage } from "@/domain/notifications/notification.type.js"; diff --git a/server/src/domain/status-pages/status-page.service.ts b/server/src/domain/status-pages/status-page.service.ts index f7827041a..834f87384 100644 --- a/server/src/domain/status-pages/status-page.service.ts +++ b/server/src/domain/status-pages/status-page.service.ts @@ -9,7 +9,7 @@ import { } from "@/domain/status-pages/status-page.type.js"; import { AppError } from "@/utils/AppError.js"; import { normalizeStatusPageDomain } from "@/utils/statusPageDomain.js"; -import { Monitor } from "@/domain/monitors/monitor.types.js"; +import { Monitor } from "@/domain/monitors/monitor.type.js"; import { NormalizeData } from "@/utils/dataUtils.js"; export interface IStatusPageService { diff --git a/server/src/domain/status-pages/status-page.type.ts b/server/src/domain/status-pages/status-page.type.ts index d4642af17..65f331ad9 100644 --- a/server/src/domain/status-pages/status-page.type.ts +++ b/server/src/domain/status-pages/status-page.type.ts @@ -1,4 +1,4 @@ -import type { Monitor } from "@/domain/monitors/monitor.types.js"; +import type { Monitor } from "@/domain/monitors/monitor.type.js"; import type { NormalizedCheck, CheckSnapshot } from "@/domain/checks/check.type.js"; export const StatusPageTypes = ["uptime", "infrastructure"] as const; export type StatusPageType = (typeof StatusPageTypes)[number]; diff --git a/server/src/service/globalPingService.ts b/server/src/service/globalPingService.ts index 4b0257df4..5a175485f 100644 --- a/server/src/service/globalPingService.ts +++ b/server/src/service/globalPingService.ts @@ -1,6 +1,6 @@ import type { GeoContinent, GeoCheckResult, GeoCheckTimings, GeoCheckLocation } from "@/domain/geo-checks/geo-check.type.js"; -import { supportsGeoCheck, type HttpStatusCode } from "@/domain/monitors/monitor.types.js"; -import { MonitorType } from "@/domain/monitors/monitor.types.js"; +import { supportsGeoCheck, type HttpStatusCode } from "@/domain/monitors/monitor.type.js"; +import { MonitorType } from "@/domain/monitors/monitor.type.js"; import type { ILogger } from "@/utils/logger.js"; import got from "got"; import { isStatusUp } from "@/service/network/utils.js"; diff --git a/server/src/service/network/AdvancedMatcher.ts b/server/src/service/network/AdvancedMatcher.ts index 8e77ef3ec..af0195061 100644 --- a/server/src/service/network/AdvancedMatcher.ts +++ b/server/src/service/network/AdvancedMatcher.ts @@ -1,4 +1,4 @@ -import { Monitor } from "@/domain/monitors/monitor.types.js"; +import { Monitor } from "@/domain/monitors/monitor.type.js"; import jmespath from "jmespath"; import RE2 from "re2"; type JmesPath = typeof jmespath; diff --git a/server/src/service/network/DNSProvider.ts b/server/src/service/network/DNSProvider.ts index ff136db0e..10eff8d74 100644 --- a/server/src/service/network/DNSProvider.ts +++ b/server/src/service/network/DNSProvider.ts @@ -1,7 +1,7 @@ import { DNSStatusPayload, MonitorStatusResponse } from "@/types/network.js"; import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import type { Resolver } from "dns/promises"; -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { AppError } from "@/utils/AppError.js"; import { timeRequest } from "@/service/network/utils.js"; import { NETWORK_ERROR } from "@/types/network.js"; diff --git a/server/src/service/network/DockerProvider.ts b/server/src/service/network/DockerProvider.ts index 5e5d7b630..9f2a99de7 100644 --- a/server/src/service/network/DockerProvider.ts +++ b/server/src/service/network/DockerProvider.ts @@ -1,6 +1,6 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { DockerStatusPayload, MonitorStatusResponse } from "@/types/network.js"; -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { ILogger } from "@/utils/logger.js"; import { AppError } from "@/utils/AppError.js"; import Dockerode from "dockerode"; diff --git a/server/src/service/network/GameProvider.ts b/server/src/service/network/GameProvider.ts index 1a07de791..5ccfaee6e 100644 --- a/server/src/service/network/GameProvider.ts +++ b/server/src/service/network/GameProvider.ts @@ -1,6 +1,6 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { GameStatusPayload, MonitorStatusResponse } from "@/types/network.js"; -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { GameDig } from "gamedig"; import { AppError } from "@/utils/AppError.js"; import { NETWORK_ERROR } from "@/types/network.js"; diff --git a/server/src/service/network/GrpcProvider.ts b/server/src/service/network/GrpcProvider.ts index 4e79cef7f..340fdc01a 100644 --- a/server/src/service/network/GrpcProvider.ts +++ b/server/src/service/network/GrpcProvider.ts @@ -1,6 +1,6 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { GrpcStatusPayload, MonitorStatusResponse } from "@/types/network.js"; -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { AppError } from "@/utils/AppError.js"; import { timeRequest } from "@/service/network/utils.js"; import * as grpc from "@grpc/grpc-js"; diff --git a/server/src/service/network/HardwareProvider.ts b/server/src/service/network/HardwareProvider.ts index c612bdbad..840dbc2e8 100644 --- a/server/src/service/network/HardwareProvider.ts +++ b/server/src/service/network/HardwareProvider.ts @@ -1,6 +1,6 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { HardwareStatusPayload, MonitorStatusResponse } from "@/types/network.js"; -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { HttpProvider } from "@/service/network/HttpProvider.js"; import { AppError } from "@/utils/AppError.js"; diff --git a/server/src/service/network/HttpProvider.ts b/server/src/service/network/HttpProvider.ts index fb974cac1..b1debd969 100644 --- a/server/src/service/network/HttpProvider.ts +++ b/server/src/service/network/HttpProvider.ts @@ -5,7 +5,7 @@ import { HttpStatusPayload } from "@/types/network.js"; import { MonitorStatusResponse } from "@/types/network.js"; import { Agent as HttpsAgent } from "https"; import { Agent as HttpAgent } from "http"; -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { isStatusUp } from "@/service/network/utils.js"; import { NETWORK_ERROR } from "@/types/network.js"; import CacheableLookup from "cacheable-lookup"; diff --git a/server/src/service/network/IStatusProvider.ts b/server/src/service/network/IStatusProvider.ts index f077ff9b5..6da91b30f 100644 --- a/server/src/service/network/IStatusProvider.ts +++ b/server/src/service/network/IStatusProvider.ts @@ -1,4 +1,4 @@ -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { MonitorStatusResponse } from "@/types/network.js"; export interface IStatusProvider { diff --git a/server/src/service/network/PageSpeedProvider.ts b/server/src/service/network/PageSpeedProvider.ts index a609ca80b..dfa29a5c9 100644 --- a/server/src/service/network/PageSpeedProvider.ts +++ b/server/src/service/network/PageSpeedProvider.ts @@ -1,6 +1,6 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { MonitorStatusResponse, PageSpeedStatusPayload } from "@/types/network.js"; -import { Monitor, MonitorType, DefaultPageSpeedStrategy } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType, DefaultPageSpeedStrategy } from "@/domain/monitors/monitor.type.js"; import { HttpProvider } from "@/service/network/HttpProvider.js"; import { ISettingsService } from "@/domain/app-settings/app-settings.service.js"; import { ILogger } from "@/utils/logger.js"; diff --git a/server/src/service/network/PingProvider.ts b/server/src/service/network/PingProvider.ts index ee66046f9..53f6aad0d 100644 --- a/server/src/service/network/PingProvider.ts +++ b/server/src/service/network/PingProvider.ts @@ -1,6 +1,6 @@ import { PingStatusPayload } from "@/types/network.js"; import { IStatusProvider } from "./IStatusProvider.js"; -import { MonitorType, Monitor } from "@/domain/monitors/monitor.types.js"; +import { MonitorType, Monitor } from "@/domain/monitors/monitor.type.js"; import { MonitorStatusResponse } from "@/types/network.js"; import { AppError } from "@/utils/AppError.js"; import ping from "ping"; diff --git a/server/src/service/network/PortProvider.ts b/server/src/service/network/PortProvider.ts index b59eb5907..692ca40af 100644 --- a/server/src/service/network/PortProvider.ts +++ b/server/src/service/network/PortProvider.ts @@ -1,6 +1,6 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { PortStatusPayload, MonitorStatusResponse } from "@/types/network.js"; -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { AppError } from "@/utils/AppError.js"; import { timeRequest } from "@/service/network/utils.js"; import { NETWORK_ERROR } from "@/types/network.js"; diff --git a/server/src/service/network/WebSocketProvider.ts b/server/src/service/network/WebSocketProvider.ts index b599e6fab..d27106989 100644 --- a/server/src/service/network/WebSocketProvider.ts +++ b/server/src/service/network/WebSocketProvider.ts @@ -1,6 +1,6 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { WebSocketStatusPayload, MonitorStatusResponse } from "@/types/network.js"; -import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import { AppError } from "@/utils/AppError.js"; import { timeRequest } from "@/service/network/utils.js"; import { NETWORK_ERROR } from "@/types/network.js"; diff --git a/server/src/service/network/utils.ts b/server/src/service/network/utils.ts index 5a23a9412..1a0e157ea 100644 --- a/server/src/service/network/utils.ts +++ b/server/src/service/network/utils.ts @@ -1,4 +1,4 @@ -import type { HttpStatusCode } from "@/domain/monitors/monitor.types.js"; +import type { HttpStatusCode } from "@/domain/monitors/monitor.type.js"; export const timeRequest = async (operation: () => Promise): Promise<{ response: T | null; responseTime: number; error: unknown }> => { const start = process.hrtime.bigint(); diff --git a/server/src/service/networkService.ts b/server/src/service/networkService.ts index ec54b8e49..75ff66bda 100644 --- a/server/src/service/networkService.ts +++ b/server/src/service/networkService.ts @@ -1,4 +1,4 @@ -import type { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; +import type { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js"; import type { MonitorPayloadMap, MonitorStatusResponse } from "@/types/network.js"; import type { AxiosStatic } from "axios"; import { AppError } from "@/utils/AppError.js"; diff --git a/server/src/service/statusService.ts b/server/src/service/statusService.ts index 6435958cb..748960a37 100755 --- a/server/src/service/statusService.ts +++ b/server/src/service/statusService.ts @@ -1,7 +1,7 @@ import { IMonitorStatsRepository } from "@/domain/monitor-stats/monitor-stats.repository.interface.js"; import { IMonitorsRepository } from "@/domain/monitors/monitor.repository.interface.js"; import type { Check, CheckDiskInfo, CheckSnapshot } from "@/domain/checks/check.type.js"; -import type { Monitor, MonitorStatus } from "@/domain/monitors/monitor.types.js"; +import type { Monitor, MonitorStatus } from "@/domain/monitors/monitor.type.js"; import type { DockerStatusPayload, GameStatusPayload, @@ -17,7 +17,7 @@ import type { import { AppError } from "@/utils/AppError.js"; import { ILogger } from "@/utils/logger.js"; import type { HardwareStatusMetrics } from "@/types/network.js"; -import { MAX_RECENT_CHECKS } from "@/domain/monitors/monitor.types.js"; +import { MAX_RECENT_CHECKS } from "@/domain/monitors/monitor.type.js"; const SERVICE_NAME = "StatusService"; const HARDWARE_ALERT_COUNTER_START = 5; diff --git a/server/src/types/network.ts b/server/src/types/network.ts index b5dc1d949..2839ed95f 100644 --- a/server/src/types/network.ts +++ b/server/src/types/network.ts @@ -9,7 +9,7 @@ import type { GotTimings, ILighthouseAudit, } from "@/domain/checks/check.type.js"; -import type { DnsRecordType, Monitor, MonitorMatchMethod, MonitorStatus, MonitorType } from "@/domain/monitors/monitor.types.js"; +import type { DnsRecordType, Monitor, MonitorMatchMethod, MonitorStatus, MonitorType } from "@/domain/monitors/monitor.type.js"; import type { QueryResult } from "gamedig"; diff --git a/server/src/worker/worker.check-evaluator.ts b/server/src/worker/worker.check-evaluator.ts index 34c444271..da7e13dbe 100644 --- a/server/src/worker/worker.check-evaluator.ts +++ b/server/src/worker/worker.check-evaluator.ts @@ -1,7 +1,7 @@ import { MonitorStatusResponse } from "@/types/network.js"; import { MonitorEvaluation } from "@/worker/worker.interface.js"; import { Check } from "@/domain/checks/check.type.js"; -import { Monitor } from "@/domain/monitors/monitor.types.js"; +import { Monitor } from "@/domain/monitors/monitor.type.js"; import { IMonitorStatusPolicy } from "@/worker/worker.monitor-status-policy.js"; import { IStatusService } from "@/service/statusService.js"; diff --git a/server/src/worker/worker.check-pipeline.ts b/server/src/worker/worker.check-pipeline.ts index 045cea1ad..9b97de354 100644 --- a/server/src/worker/worker.check-pipeline.ts +++ b/server/src/worker/worker.check-pipeline.ts @@ -1,11 +1,11 @@ -import { Monitor } from "@/domain/monitors/monitor.types.js"; +import { Monitor } from "@/domain/monitors/monitor.type.js"; import { MonitorEvaluation } from "@/worker/worker.interface.js"; import { IMaintenanceWindowsRepository } from "@/domain/maintenance-windows/maintenance-window.repository.interface.js"; import { isWindowActive } from "@/utils/maintenanceWindow.js"; import { ILogger } from "@/utils/logger.js"; import { IBufferService } from "@/service/bufferService.js"; import { AppError } from "@/utils/AppError.js"; -import { supportsGeoCheck } from "@/domain/monitors/monitor.types.js"; +import { supportsGeoCheck } from "@/domain/monitors/monitor.type.js"; import { IGeoChecksService } from "@/domain/geo-checks/geo-check.service.js"; const SERVICE_NAME = "CheckPipeline"; diff --git a/server/src/worker/worker.check-producer.ts b/server/src/worker/worker.check-producer.ts index 3365ea93b..b73e2c6de 100644 --- a/server/src/worker/worker.check-producer.ts +++ b/server/src/worker/worker.check-producer.ts @@ -1,4 +1,4 @@ -import { Monitor } from "@/domain/monitors/monitor.types.js"; +import { Monitor } from "@/domain/monitors/monitor.type.js"; import { Check } from "@/domain/checks/check.type.js"; import { MonitorStatusResponse } from "@/types/network.js"; import { AppError } from "@/utils/AppError.js"; diff --git a/server/src/worker/worker.interface.ts b/server/src/worker/worker.interface.ts index e70af5f35..bb6cb0c53 100644 --- a/server/src/worker/worker.interface.ts +++ b/server/src/worker/worker.interface.ts @@ -1,4 +1,4 @@ -import { Monitor } from "@/domain/monitors/monitor.types.js"; +import { Monitor } from "@/domain/monitors/monitor.type.js"; import { Check } from "@/domain/checks/check.type.js"; import { JobType } from "@/domain/jobs/job.type.js"; import { MonitorPayloadMap, MonitorStatusResponse, StatusChangeResult } from "@/types/network.js"; diff --git a/server/src/worker/worker.job-scheduler.ts b/server/src/worker/worker.job-scheduler.ts index 433e69955..8d103e87f 100644 --- a/server/src/worker/worker.job-scheduler.ts +++ b/server/src/worker/worker.job-scheduler.ts @@ -1,7 +1,7 @@ import { IJobScheduler } from "@/worker/worker.interface.js"; import { IJobsRepository } from "@/domain/jobs/job.repository.interface.js"; import { IMonitorsRepository } from "@/domain/monitors/monitor.repository.interface.js"; -import { Monitor, supportsGeoCheck } from "@/domain/monitors/monitor.types.js"; +import { Monitor, supportsGeoCheck } from "@/domain/monitors/monitor.type.js"; import { type Job, type JobSeed, type JobType, jobId } from "@/domain/jobs/job.type.js"; import { IQueueWorkersRepository } from "@/domain/queue-workers/queue-worker.repository.interface.js"; import { WorkerJobsPagination, WorkerJobSummary, WorkerMetrics } from "@/worker/worker.interface.js"; @@ -187,7 +187,7 @@ export class JobScheduler implements IJobScheduler { // Seed queue protected reconcile = async () => { const now = Date.now(); - const monitors = (await this.monitorsRepository.findAll()) ?? []; + const monitors = await this.monitorsRepository.findAll(); for (const monitor of monitors) { await this.jobsRepository.upsertJob(this.toCheckJob(monitor, now)); if (supportsGeoCheck(monitor.type) && monitor.geoCheckEnabled) { From c28be97fb0fa0dd0d522d307541cd81585da718e Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 11:32:18 -0700 Subject: [PATCH 5/8] update tests --- server/test/unit/services/monitorService.test.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/server/test/unit/services/monitorService.test.ts b/server/test/unit/services/monitorService.test.ts index 085b3322f..69edbba9c 100644 --- a/server/test/unit/services/monitorService.test.ts +++ b/server/test/unit/services/monitorService.test.ts @@ -574,7 +574,7 @@ describe("MonitorService", () => { const monitorsRepository = createMonitorsRepositoryMock(); (monitorsRepository.findMonitorsSummaryByTeamId as jest.Mock).mockResolvedValue(null); (monitorsRepository.findMonitorCountByTeamIdAndType as jest.Mock).mockResolvedValue(0); - (monitorsRepository.findByTeamIdWithStats as jest.Mock).mockResolvedValue(null); + (monitorsRepository.findByTeamIdWithStats as jest.Mock).mockResolvedValue([]); const { service } = createService({ monitorsRepository }); const result = await service.getMonitorsWithChecksByTeamId({ teamId: TEAM_ID }); @@ -1576,14 +1576,6 @@ describe("MonitorService", () => { expect(result).toEqual(monitors); }); - it("throws when no monitors found (null)", async () => { - const monitorsRepository = createMonitorsRepositoryMock(); - (monitorsRepository.findByTeamId as jest.Mock).mockResolvedValue(null); - const { service } = createService({ monitorsRepository }); - - await expect(service.exportMonitorsToJSON({ teamId: TEAM_ID })).rejects.toThrow("No monitors found to export."); - }); - it("throws when monitors array is empty", async () => { const monitorsRepository = createMonitorsRepositoryMock(); (monitorsRepository.findByTeamId as jest.Mock).mockResolvedValue([]); From 49e8d26bfcb1f6f13611ee3af0283e3374bfe26d Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 11:34:54 -0700 Subject: [PATCH 6/8] remove legacy try/catch blocks --- .../geo-checks/geo-check.repository.mongo.ts | 400 ++++++++---------- 1 file changed, 170 insertions(+), 230 deletions(-) diff --git a/server/src/domain/geo-checks/geo-check.repository.mongo.ts b/server/src/domain/geo-checks/geo-check.repository.mongo.ts index 5f4067ec7..0d1183720 100644 --- a/server/src/domain/geo-checks/geo-check.repository.mongo.ts +++ b/server/src/domain/geo-checks/geo-check.repository.mongo.ts @@ -64,28 +64,18 @@ class MongoGeoChecksRepository implements IGeoChecksRepository { }; createGeoChecks = async (geoChecks: Omit[]): Promise => { - try { - const docs = await GeoCheckModel.insertMany( - geoChecks.map((geoCheck) => ({ - metadata: { - monitorId: new mongoose.Types.ObjectId(geoCheck.metadata.monitorId), - teamId: new mongoose.Types.ObjectId(geoCheck.metadata.teamId), - type: geoCheck.metadata.type, - }, - results: geoCheck.results, - expiry: new Date(geoCheck.expiry), - })) - ); - return docs.map((doc) => this.toEntity(doc)); - } catch (error: unknown) { - this.logger.error({ - message: error instanceof Error ? `Failed to createGeoChecks: ${error.message}` : "Failed to createGeoChecks", - service: SERVICE_NAME, - method: "createGeoChecks", - stack: error instanceof Error ? error.stack : undefined, - }); - throw error; - } + const docs = await GeoCheckModel.insertMany( + geoChecks.map((geoCheck) => ({ + metadata: { + monitorId: new mongoose.Types.ObjectId(geoCheck.metadata.monitorId), + teamId: new mongoose.Types.ObjectId(geoCheck.metadata.teamId), + type: geoCheck.metadata.type, + }, + results: geoCheck.results, + expiry: new Date(geoCheck.expiry), + })) + ); + return docs.map((doc) => this.toEntity(doc)); }; findByMonitorId = async ( @@ -96,95 +86,85 @@ class MongoGeoChecksRepository implements IGeoChecksRepository { rowsPerPage: number, continents?: GeoContinent[] ): Promise => { - try { - const matchStage: Record = { - "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), - createdAt: { $gte: getDateForRange(dateRange) }, - }; + const matchStage: Record = { + "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), + createdAt: { $gte: getDateForRange(dateRange) }, + }; - const convertedSortOrder = sortOrder === "asc" ? 1 : -1; + const convertedSortOrder = sortOrder === "asc" ? 1 : -1; - let skip = 0; - if (page && rowsPerPage) { - skip = page * rowsPerPage; - } - - // Common pipeline stages for both paths - const pipeline: PipelineStage[] = [ - { $match: matchStage }, - { $unwind: "$results" }, - // Filter by continent if specified - ...(continents && continents.length > 0 - ? [ - { - $match: { - "results.location.continent": { $in: continents }, - }, - }, - ] - : []), - // Project to flat structure - { - $project: { - _id: 0, - monitorId: "$metadata.monitorId", - teamId: "$metadata.teamId", - type: "$metadata.type", - location: "$results.location", - status: "$results.status", - statusCode: "$results.statusCode", - timings: "$results.timings", - createdAt: 1, - updatedAt: 1, - }, - }, - { $sort: { createdAt: convertedSortOrder } }, - { $skip: skip }, - { $limit: rowsPerPage }, - ]; - - // Count pipeline - const countPipeline: PipelineStage[] = [ - { $match: matchStage }, - { $unwind: "$results" }, - ...(continents && continents.length > 0 - ? [ - { - $match: { - "results.location.continent": { $in: continents }, - }, - }, - ] - : []), - { $count: "count" }, - ]; - - const [countResult, dataResults] = await Promise.all([GeoCheckModel.aggregate(countPipeline), GeoCheckModel.aggregate(pipeline)]); - - const geoChecksCount = countResult[0]?.count || 0; - const geoChecks: FlatGeoCheck[] = dataResults.map((doc) => ({ - id: `${doc.monitorId.toString()}-${new Date(doc.createdAt).getTime()}-${doc.location.continent}-${doc.location.city}-${Math.random().toString(36).substring(2, 15)}`, - monitorId: doc.monitorId.toString(), - teamId: doc.teamId.toString(), - type: doc.type, - location: doc.location, - status: doc.status, - statusCode: doc.statusCode, - timings: doc.timings, - createdAt: new Date(doc.createdAt).toISOString(), - updatedAt: new Date(doc.updatedAt).toISOString(), - })); - - return { geoChecksCount, geoChecks }; - } catch (error: unknown) { - this.logger.error({ - message: error instanceof Error ? `Error finding geo checks by monitor ID: ${error.message}` : "Error finding geo checks by monitor ID", - service: SERVICE_NAME, - method: "findByMonitorId", - stack: error instanceof Error ? error.stack : undefined, - }); - throw error; + let skip = 0; + if (page && rowsPerPage) { + skip = page * rowsPerPage; } + + // Common pipeline stages for both paths + const pipeline: PipelineStage[] = [ + { $match: matchStage }, + { $unwind: "$results" }, + // Filter by continent if specified + ...(continents && continents.length > 0 + ? [ + { + $match: { + "results.location.continent": { $in: continents }, + }, + }, + ] + : []), + // Project to flat structure + { + $project: { + _id: 0, + monitorId: "$metadata.monitorId", + teamId: "$metadata.teamId", + type: "$metadata.type", + location: "$results.location", + status: "$results.status", + statusCode: "$results.statusCode", + timings: "$results.timings", + createdAt: 1, + updatedAt: 1, + }, + }, + { $sort: { createdAt: convertedSortOrder } }, + { $skip: skip }, + { $limit: rowsPerPage }, + ]; + + // Count pipeline + const countPipeline: PipelineStage[] = [ + { $match: matchStage }, + { $unwind: "$results" }, + ...(continents && continents.length > 0 + ? [ + { + $match: { + "results.location.continent": { $in: continents }, + }, + }, + ] + : []), + { $count: "count" }, + ]; + + const [countResult, dataResults] = await Promise.all([GeoCheckModel.aggregate(countPipeline), GeoCheckModel.aggregate(pipeline)]); + + const geoChecksCount = countResult[0]?.count || 0; + const geoChecks: FlatGeoCheck[] = dataResults.map((doc) => ({ + id: `${doc.monitorId.toString()}-${new Date(doc.createdAt).getTime()}-${doc.location.continent}-${doc.location.city}-${Math.random().toString(36).substring(2, 15)}`, + monitorId: doc.monitorId.toString(), + teamId: doc.teamId.toString(), + type: doc.type, + location: doc.location, + status: doc.status, + statusCode: doc.statusCode, + timings: doc.timings, + createdAt: new Date(doc.createdAt).toISOString(), + updatedAt: new Date(doc.updatedAt).toISOString(), + })); + + return { geoChecksCount, geoChecks }; }; findGroupedByMonitorIdAndDateRange = async (monitorId: string, dateRange: DateRange, continents?: GeoContinent[]): Promise => { @@ -192,146 +172,106 @@ class MongoGeoChecksRepository implements IGeoChecksRepository { const dateString = getDateFormat(dateRange); const end = new Date(); - try { - const pipeline: PipelineStage[] = [ - // Match geo checks for this monitor in date range - { - $match: { - "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), - createdAt: { - $gte: start, - $lte: end, + const pipeline: PipelineStage[] = [ + // Match geo checks for this monitor in date range + { + $match: { + "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), + createdAt: { + $gte: start, + $lte: end, + }, + }, + }, + // Unwind the results array to process each location separately + { + $unwind: "$results", + }, + // Filter by continent if specified + ...(continents && continents.length > 0 + ? [ + { + $match: { + "results.location.continent": { $in: continents }, + }, + }, + ] + : []), + // Group by date bucket and continent + { + $group: { + _id: { + bucketDate: { + $dateToString: { + format: dateString, + date: "$createdAt", + }, + }, + continent: "$results.location.continent", + }, + avgResponseTime: { $avg: "$results.timings.total" }, + totalChecks: { $sum: 1 }, + upChecks: { + $sum: { + $cond: ["$results.status", 1, 0], }, }, }, - // Unwind the results array to process each location separately - { - $unwind: "$results", - }, - // Filter by continent if specified - ...(continents && continents.length > 0 - ? [ + }, + // Calculate uptime percentage + { + $project: { + _id: 0, + bucketDate: "$_id.bucketDate", + continent: "$_id.continent", + avgResponseTime: { $round: ["$avgResponseTime", 2] }, + totalChecks: 1, + uptimePercentage: { + $round: [ { - $match: { - "results.location.continent": { $in: continents }, - }, + $multiply: [ + { + $divide: ["$upChecks", "$totalChecks"], + }, + 100, + ], }, - ] - : []), - // Group by date bucket and continent - { - $group: { - _id: { - bucketDate: { - $dateToString: { - format: dateString, - date: "$createdAt", - }, - }, - continent: "$results.location.continent", - }, - avgResponseTime: { $avg: "$results.timings.total" }, - totalChecks: { $sum: 1 }, - upChecks: { - $sum: { - $cond: ["$results.status", 1, 0], - }, - }, + 2, + ], }, }, - // Calculate uptime percentage - { - $project: { - _id: 0, - bucketDate: "$_id.bucketDate", - continent: "$_id.continent", - avgResponseTime: { $round: ["$avgResponseTime", 2] }, - totalChecks: 1, - uptimePercentage: { - $round: [ - { - $multiply: [ - { - $divide: ["$upChecks", "$totalChecks"], - }, - 100, - ], - }, - 2, - ], - }, - }, + }, + // Sort by date and continent + { + $sort: { + bucketDate: 1, + continent: 1, }, - // Sort by date and continent - { - $sort: { - bucketDate: 1, - continent: 1, - }, - }, - ]; + }, + ]; - const results = await GeoCheckModel.aggregate(pipeline); - return results as GroupedGeoCheck[]; - } catch (error: unknown) { - this.logger.error({ - message: error instanceof Error ? `Error finding grouped geo checks: ${error.message}` : "Error finding grouped geo checks", - service: SERVICE_NAME, - method: "findGroupedByMonitorIdAndDateRange", - stack: error instanceof Error ? error.stack : undefined, - }); - throw error; - } + const results = await GeoCheckModel.aggregate(pipeline); + return results as GroupedGeoCheck[]; }; deleteByMonitorId = async (monitorId: string): Promise => { - try { - const result = await GeoCheckModel.deleteMany({ - "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), - }); - return result.deletedCount || 0; - } catch (error: unknown) { - this.logger.error({ - message: error instanceof Error ? `Error deleting geo checks by monitor ID: ${error.message}` : "Error deleting geo checks by monitor ID", - service: SERVICE_NAME, - method: "deleteByMonitorId", - stack: error instanceof Error ? error.stack : undefined, - }); - throw error; - } + const result = await GeoCheckModel.deleteMany({ + "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), + }); + return result.deletedCount || 0; }; deleteByTeamId = async (teamId: string): Promise => { - try { - const result = await GeoCheckModel.deleteMany({ - "metadata.teamId": new mongoose.Types.ObjectId(teamId), - }); - return result.deletedCount || 0; - } catch (error: unknown) { - this.logger.error({ - message: error instanceof Error ? `Error deleting geo checks by team ID: ${error.message}` : "Error deleting geo checks by team ID", - service: SERVICE_NAME, - method: "deleteByTeamId", - stack: error instanceof Error ? error.stack : undefined, - }); - throw error; - } + const result = await GeoCheckModel.deleteMany({ + "metadata.teamId": new mongoose.Types.ObjectId(teamId), + }); + return result.deletedCount || 0; }; deleteByMonitorIdsNotIn = async (monitorIds: string[]): Promise => { - try { - const objectIds = monitorIds.map((id) => new mongoose.Types.ObjectId(id)); - const result = await GeoCheckModel.deleteMany({ "metadata.monitorId": { $nin: objectIds } }); - return result.deletedCount || 0; - } catch (error: unknown) { - this.logger.error({ - message: error instanceof Error ? `Error deleting orphaned geo checks: ${error.message}` : "Error deleting orphaned geo checks", - service: SERVICE_NAME, - method: "deleteByMonitorIdsNotIn", - stack: error instanceof Error ? error.stack : undefined, - }); - throw error; - } + const objectIds = monitorIds.map((id) => new mongoose.Types.ObjectId(id)); + const result = await GeoCheckModel.deleteMany({ "metadata.monitorId": { $nin: objectIds } }); + return result.deletedCount || 0; }; } From 8369db5ca2d54baab8ba90864f543a883792e6bf Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 11:38:08 -0700 Subject: [PATCH 7/8] remove logger --- server/src/config/services.shared.ts | 2 +- server/src/domain/geo-checks/geo-check.repository.mongo.ts | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/server/src/config/services.shared.ts b/server/src/config/services.shared.ts index 72fe3fcf4..0f7813d8a 100644 --- a/server/src/config/services.shared.ts +++ b/server/src/config/services.shared.ts @@ -126,7 +126,7 @@ export const buildShared = async ({ const checksRepository = new MongoChecksRepository(logger); const incidentsRepository = new MongoIncidentsRepository(); const usersRepository = new MongoUsersRepository(); - const geoChecksRepository = new MongoGeoChecksRepository(logger); + const geoChecksRepository = new MongoGeoChecksRepository(); const notificationsRepository = new MongoNotificationsRepository(); const jobsRepository = new MongoJobsRepository(workerId); const queueWorkersRepository = new MongoQueueWorkersRepository(); diff --git a/server/src/domain/geo-checks/geo-check.repository.mongo.ts b/server/src/domain/geo-checks/geo-check.repository.mongo.ts index 0d1183720..a56699750 100644 --- a/server/src/domain/geo-checks/geo-check.repository.mongo.ts +++ b/server/src/domain/geo-checks/geo-check.repository.mongo.ts @@ -4,7 +4,6 @@ import type { FlatGeoChecksQueryResult } from "./geo-check.repository.interface. import { GeoCheckMetadataDocument, GeoCheckModel, type GeoCheckDocument } from "@/domain/geo-checks/geo-check.model.js"; import mongoose, { PipelineStage } from "mongoose"; import { getDateForRange, getDateFormat } from "@/utils/dataUtils.js"; -import { ILogger } from "@/utils/logger.js"; import { toStringId, toDateString } from "@/utils/mongoMappers.js"; import { DateRange } from "@/types/query.js"; @@ -13,11 +12,6 @@ const SERVICE_NAME = "GeoChecksRepository"; class MongoGeoChecksRepository implements IGeoChecksRepository { static SERVICE_NAME = SERVICE_NAME; - private logger: ILogger; - constructor(logger: ILogger) { - this.logger = logger; - } - private toEntity = (doc: GeoCheckDocument): GeoCheck => { const mapMetadata = (metadata: GeoCheckMetadataDocument): GeoCheckMetadata => ({ monitorId: toStringId(metadata.monitorId), From e0228918fb85a943d1c78bfe52cc4e4d77248419 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 12:28:45 -0700 Subject: [PATCH 8/8] fix tests --- server/test/helpers/InMemoryMonitorsRepository.ts | 2 +- server/test/helpers/heartbeatTestHarness.ts | 2 +- server/test/helpers/statusProviderContract.ts | 2 +- server/test/integration/incidentLifecycle.test.ts | 2 +- server/test/unit/providers/network/advancedMatcher.test.ts | 2 +- server/test/unit/providers/network/dnsProvider.test.ts | 4 ++-- server/test/unit/providers/network/dockerProvider.test.ts | 4 ++-- server/test/unit/providers/network/gameProvider.test.ts | 4 ++-- server/test/unit/providers/network/grpcProvider.test.ts | 2 +- .../test/unit/providers/network/hardwareProvider.test.ts | 2 +- server/test/unit/providers/network/httpProvider.test.ts | 4 ++-- .../test/unit/providers/network/pageSpeedProvider.test.ts | 2 +- server/test/unit/providers/network/pingProvider.test.ts | 2 +- server/test/unit/providers/network/portProvider.test.ts | 4 ++-- server/test/unit/providers/network/utils.test.ts | 7 ++----- .../test/unit/providers/network/webSocketProvider.test.ts | 4 ++-- server/test/unit/services/checkEvaluator.test.ts | 2 +- server/test/unit/services/checkPipeline.test.ts | 2 +- server/test/unit/services/checkProducer.test.ts | 2 +- server/test/unit/services/checkService.test.ts | 2 +- server/test/unit/services/dbQueueWorker.test.ts | 2 +- server/test/unit/services/geoChecksService.test.ts | 2 +- server/test/unit/services/incidentService.test.ts | 2 +- server/test/unit/services/jobScheduler.test.ts | 2 +- server/test/unit/services/networkService.test.ts | 4 ++-- .../test/unit/services/notificationMessageBuilder.test.ts | 2 +- server/test/unit/services/notificationsService.test.ts | 2 +- server/test/unit/services/statusPageService.test.ts | 2 +- server/test/unit/services/statusService.test.ts | 4 ++-- 29 files changed, 38 insertions(+), 41 deletions(-) diff --git a/server/test/helpers/InMemoryMonitorsRepository.ts b/server/test/helpers/InMemoryMonitorsRepository.ts index 09162cfd2..1ff0b0383 100644 --- a/server/test/helpers/InMemoryMonitorsRepository.ts +++ b/server/test/helpers/InMemoryMonitorsRepository.ts @@ -1,6 +1,6 @@ import type { IMonitorsRepository, TeamQueryConfig, SummaryConfig } from "../../src/domain/monitors/monitor.repository.interface.ts"; import type { CheckSnapshot } from "../../src/domain/checks/check.type.ts"; -import type { Monitor, MonitorsSummary } from "../../src/domain/monitors/monitor.types.ts"; +import type { Monitor, MonitorsSummary } from "../../src/domain/monitors/monitor.type.ts"; export class InMemoryMonitorsRepository implements IMonitorsRepository { private monitors: Monitor[] = []; diff --git a/server/test/helpers/heartbeatTestHarness.ts b/server/test/helpers/heartbeatTestHarness.ts index 5711f5aa9..898c3c91e 100644 --- a/server/test/helpers/heartbeatTestHarness.ts +++ b/server/test/helpers/heartbeatTestHarness.ts @@ -10,7 +10,7 @@ import { IncidentService } from "../../src/domain/incidents/incident.service.ts" import { InMemoryMonitorsRepository } from "./InMemoryMonitorsRepository.ts"; import { InMemoryIncidentsRepository } from "./InMemoryIncidentsRepository.ts"; import { createMockLogger } from "./createMockLogger.ts"; -import type { Monitor } from "../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../src/domain/monitors/monitor.type.ts"; import type { MonitorStatusResponse } from "../../src/types/network.ts"; import type { Check } from "../../src/domain/checks/check.type.ts"; import type { MaintenanceWindow } from "../../src/domain/maintenance-windows/maintenance-window.type.ts"; diff --git a/server/test/helpers/statusProviderContract.ts b/server/test/helpers/statusProviderContract.ts index af625f64d..707d8b3c3 100644 --- a/server/test/helpers/statusProviderContract.ts +++ b/server/test/helpers/statusProviderContract.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "@jest/globals"; import type { IStatusProvider } from "../../src/service/network/IStatusProvider.ts"; -import type { Monitor } from "../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../src/domain/monitors/monitor.type.ts"; /** * Shared contract tests for all IStatusProvider implementations. diff --git a/server/test/integration/incidentLifecycle.test.ts b/server/test/integration/incidentLifecycle.test.ts index 73b25d893..6f7d8bc9a 100644 --- a/server/test/integration/incidentLifecycle.test.ts +++ b/server/test/integration/incidentLifecycle.test.ts @@ -5,7 +5,7 @@ import { createMockLogger } from "../helpers/createMockLogger.ts"; import type { IMonitorsRepository } from "../../src/domain/monitors/monitor.repository.interface.ts"; import type { IUsersRepository } from "../../src/domain/users/user.repository.interface.ts"; import type { INotificationMessageBuilder } from "../../src/domain/notifications/notification.message-builder.ts"; -import type { Monitor } from "../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../src/domain/monitors/monitor.type.ts"; import type { MonitorActionDecision } from "../../src/worker/worker.helper.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/advancedMatcher.test.ts b/server/test/unit/providers/network/advancedMatcher.test.ts index 063591e4f..b66d5ed56 100644 --- a/server/test/unit/providers/network/advancedMatcher.test.ts +++ b/server/test/unit/providers/network/advancedMatcher.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, jest } from "@jest/globals"; import { AdvancedMatcher } from "../../../../src/service/network/AdvancedMatcher.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/dnsProvider.test.ts b/server/test/unit/providers/network/dnsProvider.test.ts index 1c31b3b1d..d485ca599 100644 --- a/server/test/unit/providers/network/dnsProvider.test.ts +++ b/server/test/unit/providers/network/dnsProvider.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it, jest } from "@jest/globals"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; -import { NETWORK_ERROR } from "../../../../src/service/network/utils.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import { NETWORK_ERROR } from "../../../../src/types/network.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; import { DNSProvider } from "../../../../src/service/network/DNSProvider.ts"; // ── Mocks ──────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/dockerProvider.test.ts b/server/test/unit/providers/network/dockerProvider.test.ts index f0b743f16..6d16b3e5c 100644 --- a/server/test/unit/providers/network/dockerProvider.test.ts +++ b/server/test/unit/providers/network/dockerProvider.test.ts @@ -2,8 +2,8 @@ import { describe, expect, it, jest } from "@jest/globals"; import { DockerProvider } from "../../../../src/service/network/DockerProvider.ts"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; import { createMockLogger } from "../../../helpers/createMockLogger.ts"; -import { NETWORK_ERROR } from "../../../../src/service/network/utils.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import { NETWORK_ERROR } from "../../../../src/types/network.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/gameProvider.test.ts b/server/test/unit/providers/network/gameProvider.test.ts index d166c30f3..eac775b3b 100644 --- a/server/test/unit/providers/network/gameProvider.test.ts +++ b/server/test/unit/providers/network/gameProvider.test.ts @@ -2,8 +2,8 @@ import { describe, expect, it, jest } from "@jest/globals"; import { GameProvider } from "../../../../src/service/network/GameProvider.ts"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; import { createMockLogger } from "../../../helpers/createMockLogger.ts"; -import { NETWORK_ERROR } from "../../../../src/service/network/utils.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import { NETWORK_ERROR } from "../../../../src/types/network.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/grpcProvider.test.ts b/server/test/unit/providers/network/grpcProvider.test.ts index bb1c78aac..63e8859f2 100644 --- a/server/test/unit/providers/network/grpcProvider.test.ts +++ b/server/test/unit/providers/network/grpcProvider.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, jest } from "@jest/globals"; import { GrpcProvider } from "../../../../src/service/network/GrpcProvider.ts"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/hardwareProvider.test.ts b/server/test/unit/providers/network/hardwareProvider.test.ts index 2b4583af9..b8bb66531 100644 --- a/server/test/unit/providers/network/hardwareProvider.test.ts +++ b/server/test/unit/providers/network/hardwareProvider.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, jest } from "@jest/globals"; import { HardwareProvider } from "../../../../src/service/network/HardwareProvider.ts"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; import type { HttpProvider } from "../../../../src/service/network/HttpProvider.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/httpProvider.test.ts b/server/test/unit/providers/network/httpProvider.test.ts index 7556f7595..88897aca3 100644 --- a/server/test/unit/providers/network/httpProvider.test.ts +++ b/server/test/unit/providers/network/httpProvider.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, jest } from "@jest/globals"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; -import { NETWORK_ERROR } from "../../../../src/service/network/utils.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import { NETWORK_ERROR } from "../../../../src/types/network.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Mocks ──────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/pageSpeedProvider.test.ts b/server/test/unit/providers/network/pageSpeedProvider.test.ts index df5beb0be..2767e8e56 100644 --- a/server/test/unit/providers/network/pageSpeedProvider.test.ts +++ b/server/test/unit/providers/network/pageSpeedProvider.test.ts @@ -4,7 +4,7 @@ import { testStatusProviderContract } from "../../../helpers/statusProviderContr import { createMockLogger } from "../../../helpers/createMockLogger.ts"; import type { HttpProvider } from "../../../../src/service/network/HttpProvider.ts"; import type { ISettingsService } from "../../../../src/domain/app-settings/app-settings.service.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/pingProvider.test.ts b/server/test/unit/providers/network/pingProvider.test.ts index 8f006a470..04e4ad74e 100644 --- a/server/test/unit/providers/network/pingProvider.test.ts +++ b/server/test/unit/providers/network/pingProvider.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, jest } from "@jest/globals"; import { PingProvider } from "../../../../src/service/network/PingProvider.ts"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/portProvider.test.ts b/server/test/unit/providers/network/portProvider.test.ts index 8a7d55c4c..fbbfb5767 100644 --- a/server/test/unit/providers/network/portProvider.test.ts +++ b/server/test/unit/providers/network/portProvider.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it, jest } from "@jest/globals"; import { PortProvider } from "../../../../src/service/network/PortProvider.ts"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; -import { NETWORK_ERROR } from "../../../../src/service/network/utils.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import { NETWORK_ERROR } from "../../../../src/types/network.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/providers/network/utils.test.ts b/server/test/unit/providers/network/utils.test.ts index b37a5597c..a83e14cff 100644 --- a/server/test/unit/providers/network/utils.test.ts +++ b/server/test/unit/providers/network/utils.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "@jest/globals"; -import { timeRequest, NETWORK_ERROR, PING_ERROR, isStatusUp } from "../../../../src/service/network/utils.ts"; +import { timeRequest, isStatusUp } from "../../../../src/service/network/utils.ts"; +import { NETWORK_ERROR } from "../../../../src/types/network.ts"; describe("network utils", () => { describe("timeRequest", () => { @@ -36,10 +37,6 @@ describe("network utils", () => { it("NETWORK_ERROR is 5000", () => { expect(NETWORK_ERROR).toBe(5000); }); - - it("PING_ERROR is 5001", () => { - expect(PING_ERROR).toBe(5001); - }); }); describe("isStatusUp", () => { diff --git a/server/test/unit/providers/network/webSocketProvider.test.ts b/server/test/unit/providers/network/webSocketProvider.test.ts index 12ff32d63..b765b2f74 100644 --- a/server/test/unit/providers/network/webSocketProvider.test.ts +++ b/server/test/unit/providers/network/webSocketProvider.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it, jest, beforeEach, afterEach } from "@jest/globals"; import { WebSocketProvider } from "../../../../src/service/network/WebSocketProvider.ts"; import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts"; -import { NETWORK_ERROR } from "../../../../src/service/network/utils.ts"; -import type { Monitor } from "../../../../src/domain/monitors/monitor.types.ts"; +import { NETWORK_ERROR } from "../../../../src/types/network.ts"; +import type { Monitor } from "../../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/services/checkEvaluator.test.ts b/server/test/unit/services/checkEvaluator.test.ts index a22ceb1c7..22919495a 100644 --- a/server/test/unit/services/checkEvaluator.test.ts +++ b/server/test/unit/services/checkEvaluator.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, jest } from "@jest/globals"; import { CheckEvaluator } from "../../../src/worker/worker.check-evaluator.ts"; import { MonitorStatusPolicy } from "../../../src/worker/worker.monitor-status-policy.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; const makeMonitor = (overrides?: Partial): Monitor => ({ diff --git a/server/test/unit/services/checkPipeline.test.ts b/server/test/unit/services/checkPipeline.test.ts index 008e879fa..2e7026f4d 100644 --- a/server/test/unit/services/checkPipeline.test.ts +++ b/server/test/unit/services/checkPipeline.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, jest } from "@jest/globals"; import { GeoChecksPipeline } from "../../../src/worker/worker.check-pipeline.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import { createMockLogger } from "../../helpers/createMockLogger.ts"; const makeMonitor = (overrides?: Partial): Monitor => diff --git a/server/test/unit/services/checkProducer.test.ts b/server/test/unit/services/checkProducer.test.ts index 4edd12bb5..dacff3d9b 100644 --- a/server/test/unit/services/checkProducer.test.ts +++ b/server/test/unit/services/checkProducer.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, jest } from "@jest/globals"; import { CheckProducer } from "../../../src/worker/worker.check-producer.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import { createMockLogger } from "../../helpers/createMockLogger.ts"; const makeMonitor = (overrides?: Partial): Monitor => diff --git a/server/test/unit/services/checkService.test.ts b/server/test/unit/services/checkService.test.ts index 8c58259e3..80b941b6f 100644 --- a/server/test/unit/services/checkService.test.ts +++ b/server/test/unit/services/checkService.test.ts @@ -5,7 +5,7 @@ import type { IChecksRepository } from "../../../src/domain/checks/check.reposit import type { IMonitorsRepository } from "../../../src/domain/monitors/monitor.repository.interface.ts"; import type { MonitorStatusResponse, HardwareStatusPayload, PageSpeedStatusPayload } from "../../../src/types/network.ts"; import { NotificationMessageBuilder } from "../../../src/domain/notifications/notification.message-builder.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/services/dbQueueWorker.test.ts b/server/test/unit/services/dbQueueWorker.test.ts index 4956e474c..d903ae887 100644 --- a/server/test/unit/services/dbQueueWorker.test.ts +++ b/server/test/unit/services/dbQueueWorker.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, jest, beforeEach, afterEach } from "@jest/globals import { DBQueueWorker } from "../../../src/worker/worker.db-queue.ts"; import { LOCK_MS } from "../../../src/domain/jobs/job.type.ts"; import type { Job } from "../../../src/domain/jobs/job.type.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import type { QueueMode } from "../../../src/domain/app-settings/app-settings.type.ts"; import { createMockLogger } from "../../helpers/createMockLogger.ts"; diff --git a/server/test/unit/services/geoChecksService.test.ts b/server/test/unit/services/geoChecksService.test.ts index 69bfff730..a7b1a5db4 100644 --- a/server/test/unit/services/geoChecksService.test.ts +++ b/server/test/unit/services/geoChecksService.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, jest } from "@jest/globals"; import { GeoChecksService } from "../../../src/domain/geo-checks/geo-check.service.ts"; import { createMockLogger } from "../../helpers/createMockLogger.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import type { GeoCheckResult } from "../../../src/domain/geo-checks/geo-check.type.ts"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/services/incidentService.test.ts b/server/test/unit/services/incidentService.test.ts index 27b2736df..af73623df 100644 --- a/server/test/unit/services/incidentService.test.ts +++ b/server/test/unit/services/incidentService.test.ts @@ -5,7 +5,7 @@ import type { IIncidentsRepository } from "../../../src/domain/incidents/inciden import type { IMonitorsRepository } from "../../../src/domain/monitors/monitor.repository.interface.ts"; import type { IUsersRepository } from "../../../src/domain/users/user.repository.interface.ts"; import type { INotificationMessageBuilder } from "../../../src/domain/notifications/notification.message-builder.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import type { Incident } from "../../../src/domain/incidents/incident.type.ts"; import type { MonitorActionDecision } from "../../../src/worker/worker.helper.ts"; diff --git a/server/test/unit/services/jobScheduler.test.ts b/server/test/unit/services/jobScheduler.test.ts index 1528c06a6..098cef245 100644 --- a/server/test/unit/services/jobScheduler.test.ts +++ b/server/test/unit/services/jobScheduler.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, jest, beforeEach, afterEach } from "@jest/globals"; import { JobScheduler } from "../../../src/worker/worker.job-scheduler.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import type { QueueMode } from "../../../src/domain/app-settings/app-settings.type.ts"; import { createMockLogger } from "../../helpers/createMockLogger.ts"; diff --git a/server/test/unit/services/networkService.test.ts b/server/test/unit/services/networkService.test.ts index 0943b1f22..2e6627452 100644 --- a/server/test/unit/services/networkService.test.ts +++ b/server/test/unit/services/networkService.test.ts @@ -1,9 +1,9 @@ import { describe, expect, it, jest } from "@jest/globals"; import { NetworkService } from "../../../src/service/networkService.ts"; import { createMockLogger } from "../../helpers/createMockLogger.ts"; -import { NETWORK_ERROR } from "../../../src/service/network/utils.ts"; +import { NETWORK_ERROR } from "../../../src/types/network.ts"; import type { IStatusProvider } from "../../../src/service/network/IStatusProvider.ts"; -import type { Monitor, MonitorType } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor, MonitorType } from "../../../src/domain/monitors/monitor.type.ts"; import type { AxiosStatic } from "axios"; // ── Helpers ────────────────────────────────────────────────────────────────── diff --git a/server/test/unit/services/notificationMessageBuilder.test.ts b/server/test/unit/services/notificationMessageBuilder.test.ts index 6e1c4f4dc..1b9e42772 100644 --- a/server/test/unit/services/notificationMessageBuilder.test.ts +++ b/server/test/unit/services/notificationMessageBuilder.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, beforeEach } from "@jest/globals"; import { NotificationMessageBuilder } from "../../../src/domain/notifications/notification.message-builder.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import type { MonitorStatusResponse, HardwareStatusPayload } from "../../../src/types/network.ts"; import type { MonitorActionDecision } from "../../../src/worker/worker.helper.ts"; diff --git a/server/test/unit/services/notificationsService.test.ts b/server/test/unit/services/notificationsService.test.ts index 6fbbfa4a1..8e1633803 100644 --- a/server/test/unit/services/notificationsService.test.ts +++ b/server/test/unit/services/notificationsService.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, jest, beforeEach } from "@jest/globals"; import { NotificationsService } from "../../../src/domain/notifications/notification.service.ts"; import { createMockLogger } from "../../helpers/createMockLogger.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import type { Notification } from "../../../src/domain/notifications/notification.type.ts"; import type { MonitorStatusResponse } from "../../../src/types/network.ts"; import type { MonitorActionDecision } from "../../../src/worker/worker.helper.ts"; diff --git a/server/test/unit/services/statusPageService.test.ts b/server/test/unit/services/statusPageService.test.ts index 7ab2da69d..e0115ab99 100644 --- a/server/test/unit/services/statusPageService.test.ts +++ b/server/test/unit/services/statusPageService.test.ts @@ -3,7 +3,7 @@ import { StatusPageService } from "../../../src/domain/status-pages/status-page. import type { IStatusPagesRepository } from "../../../src/domain/status-pages/status-page-repository.interface.ts"; import type { ISettingsService } from "../../../src/domain/app-settings/app-settings.service.ts"; import type { IMonitorsRepository } from "../../../src/domain/monitors/monitor.repository.interface.ts"; -import type { Monitor } from "../../../src/domain/monitors/monitor.types.ts"; +import type { Monitor } from "../../../src/domain/monitors/monitor.type.ts"; import type { StatusPage } from "../../../src/domain/status-pages/status-page.type.ts"; import { DEFAULT_STATUS_PAGE_THEME, DEFAULT_STATUS_PAGE_THEME_MODE } from "../../../src/domain/status-pages/status-page.type.ts"; diff --git a/server/test/unit/services/statusService.test.ts b/server/test/unit/services/statusService.test.ts index 4f4c0264a..9e66ddbec 100644 --- a/server/test/unit/services/statusService.test.ts +++ b/server/test/unit/services/statusService.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it, jest, beforeEach } from "@jest/globals"; import { StatusService } from "../../../src/service/statusService.ts"; import { createMockLogger } from "../../helpers/createMockLogger.ts"; -import { MAX_RECENT_CHECKS } from "../../../src/domain/monitors/monitor.types.ts"; -import type { Monitor, MonitorStatus } from "../../../src/domain/monitors/monitor.types.ts"; +import { MAX_RECENT_CHECKS } from "../../../src/domain/monitors/monitor.type.ts"; +import type { Monitor, MonitorStatus } from "../../../src/domain/monitors/monitor.type.ts"; import type { Check } from "../../../src/domain/checks/check.type.ts"; import type { MonitorStatusResponse, HardwareStatusPayload } from "../../../src/types/network.ts"; import type { IMonitorsRepository } from "../../../src/domain/monitors/monitor.repository.interface.ts";