Merge pull request #3801 from bluewave-labs/chore/cleanup
chore: cleanup
This commit is contained in:
78 files changed
+420
-557
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
//****************************************
|
||||
|
||||
@@ -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" });
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<T> = { [K in keyof T]: T[K] | null };
|
||||
|
||||
export type HardwareStatsBucket = {
|
||||
_id: string;
|
||||
avgCpuUsage: number | null;
|
||||
avgMemoryUsage: number | null;
|
||||
avgTemperature: number[];
|
||||
disks: NullableValues<HardwareDiskStats>[];
|
||||
net: NullableValues<HardwareNetStats>[];
|
||||
};
|
||||
|
||||
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<HardwareStatsBucket[]> => {
|
||||
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<HardwareStatsBucket>([
|
||||
{
|
||||
$match: {
|
||||
"metadata.monitorId": new mongoose.Types.ObjectId(monitorId),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -6,9 +6,9 @@ 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 { 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<ChecksQueryResult>;
|
||||
findByTeamId(
|
||||
sortOrder: string,
|
||||
dateRange: DateRange,
|
||||
filter: string | undefined,
|
||||
page: number,
|
||||
rowsPerPage: number,
|
||||
teamId: string
|
||||
teamId: string,
|
||||
filter?: CheckFilter
|
||||
): Promise<ChecksQueryResult>;
|
||||
findLatestByMonitorIds(monitorIds: string[], options?: { limitPerMonitor?: number }): Promise<LatestChecksMap>;
|
||||
findByDateRangeAndMonitorId(
|
||||
|
||||
@@ -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";
|
||||
@@ -20,7 +21,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";
|
||||
|
||||
@@ -181,7 +184,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(),
|
||||
@@ -205,46 +213,41 @@ class MongoChecksRepository implements IChecksRepository {
|
||||
return this.mapDocuments(inserted as unknown as CheckDocument[]);
|
||||
};
|
||||
|
||||
private filterToMatch = (filter: CheckFilter | undefined): Record<string, unknown> => {
|
||||
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<string, unknown> = {
|
||||
"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;
|
||||
|
||||
@@ -262,35 +265,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<string, unknown> = {
|
||||
"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;
|
||||
|
||||
@@ -533,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,
|
||||
|
||||
@@ -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<ChecksQueryResult>;
|
||||
getChecksByTeam(params: {
|
||||
@@ -31,7 +31,7 @@ export interface ICheckService {
|
||||
dateRange: DateRange;
|
||||
page: number;
|
||||
rowsPerPage: number;
|
||||
filter?: string;
|
||||
filter?: CheckFilter;
|
||||
}): Promise<ChecksQueryResult>;
|
||||
getChecksSummaryByTeamId(params: { teamId: string; dateRange: DateRange }): Promise<ChecksSummary>;
|
||||
deleteChecks(params: { monitorId: string; teamId: string }): Promise<number>;
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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 extends GroupedCheck = GroupedCheck> = T & {
|
||||
};
|
||||
|
||||
export type CheckSnapshot = Omit<Check, "metadata" | "updatedAt">;
|
||||
|
||||
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";
|
||||
}
|
||||
@@ -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<GeoCheckMetadata, "monitorId" | "teamId"> & {
|
||||
|
||||
@@ -22,7 +22,6 @@ export interface IGeoChecksRepository {
|
||||
rowsPerPage: number,
|
||||
continents?: GeoContinent[]
|
||||
): Promise<FlatGeoChecksQueryResult>;
|
||||
findByMonitorIdAndDateRange(monitorId: string, startDate: Date, endDate: Date): Promise<GeoCheck[]>;
|
||||
findGroupedByMonitorIdAndDateRange(monitorId: string, DateRange: DateRange, continents?: GeoContinent[]): Promise<GroupedGeoCheck[]>;
|
||||
deleteByMonitorId(monitorId: string): Promise<number>;
|
||||
deleteByTeamId(teamId: string): Promise<number>;
|
||||
|
||||
@@ -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),
|
||||
@@ -64,28 +58,18 @@ class MongoGeoChecksRepository implements IGeoChecksRepository {
|
||||
};
|
||||
|
||||
createGeoChecks = async (geoChecks: Omit<GeoCheck, "id" | "__v" | "createdAt" | "updatedAt">[]): Promise<GeoCheck[]> => {
|
||||
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,119 +80,85 @@ class MongoGeoChecksRepository implements IGeoChecksRepository {
|
||||
rowsPerPage: number,
|
||||
continents?: GeoContinent[]
|
||||
): Promise<FlatGeoChecksQueryResult> => {
|
||||
try {
|
||||
const matchStage: Record<string, unknown> = {
|
||||
"metadata.monitorId": new mongoose.Types.ObjectId(monitorId),
|
||||
createdAt: { $gte: getDateForRange(dateRange) },
|
||||
};
|
||||
const matchStage: Record<string, unknown> = {
|
||||
"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;
|
||||
}
|
||||
};
|
||||
|
||||
findByMonitorIdAndDateRange = async (monitorId: string, startDate: Date, endDate: Date): Promise<GeoCheck[]> => {
|
||||
try {
|
||||
const docs = await GeoCheckModel.find({
|
||||
"metadata.monitorId": new mongoose.Types.ObjectId(monitorId),
|
||||
createdAt: {
|
||||
$gte: startDate,
|
||||
$lte: endDate,
|
||||
// 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: -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;
|
||||
}
|
||||
},
|
||||
{ $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<GroupedGeoCheck[]> => {
|
||||
@@ -216,146 +166,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<number> => {
|
||||
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<number> => {
|
||||
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<number> => {
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<Monitor | null>;
|
||||
|
||||
// collection fetch
|
||||
findAll(): Promise<Monitor[] | null>;
|
||||
findByTeamId(teamId: string, config: TeamQueryConfig): Promise<Monitor[] | null>;
|
||||
findByTeamIdWithStats(teamId: string, config: TeamQueryConfig): Promise<Monitor[] | null>;
|
||||
findAll(): Promise<Monitor[]>;
|
||||
findByTeamId(teamId: string, config: TeamQueryConfig): Promise<Monitor[]>;
|
||||
findByTeamIdWithStats(teamId: string, config: TeamQueryConfig): Promise<Monitor[]>;
|
||||
findByIds(monitorIds: string[]): Promise<Monitor[]>;
|
||||
findByIdsWithChecks(monitorIds: string[], checksCount?: number): Promise<Monitor[]>;
|
||||
|
||||
|
||||
@@ -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<Monitor[] | null> => {
|
||||
findByTeamId = async (teamId: string, config: TeamQueryConfig): Promise<Monitor[]> => {
|
||||
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<Monitor[] | null> => {
|
||||
findByTeamIdWithStats = async (teamId: string, config: TeamQueryConfig): Promise<Monitor[]> => {
|
||||
const { sort, skip, limit } = this.pageOptions(config);
|
||||
const query = this.queryBuilder(config, teamId);
|
||||
|
||||
|
||||
@@ -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<Monitor[] | null> => {
|
||||
}): Promise<Monitor[]> => {
|
||||
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<Monitor[]> => {
|
||||
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 });
|
||||
}
|
||||
|
||||
|
||||
+1
-42
@@ -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;
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
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 { 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";
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
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";
|
||||
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";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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 "@/service/network/utils.js";
|
||||
import { NETWORK_ERROR } from "@/types/network.js";
|
||||
import { ILogger } from "@/utils/logger.js";
|
||||
|
||||
type GameDigType = typeof GameDig;
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ 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 { NETWORK_ERROR, isStatusUp } from "@/service/network/utils.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";
|
||||
|
||||
export class HttpProvider implements IStatusProvider<HttpStatusPayload> {
|
||||
|
||||
@@ -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<T> {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
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 { 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;
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
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 { 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;
|
||||
|
||||
@@ -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 <T>(operation: () => Promise<T>): Promise<{ response: T | null; responseTime: number; error: unknown }> => {
|
||||
const start = process.hrtime.bigint();
|
||||
@@ -12,9 +12,6 @@ export const timeRequest = async <T>(operation: () => Promise<T>): 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);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
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";
|
||||
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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -9,10 +9,12 @@ 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";
|
||||
|
||||
export const NETWORK_ERROR = 5000;
|
||||
|
||||
export interface MonitorStatusResponse<
|
||||
T =
|
||||
| HttpStatusPayload
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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[] = [];
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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 ────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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 ────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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", () => {
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -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>): Monitor =>
|
||||
({
|
||||
|
||||
@@ -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>): Monitor =>
|
||||
|
||||
@@ -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>): Monitor =>
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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([]);
|
||||
|
||||
@@ -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 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in new issue
Block a user