add checks endpoint

This commit is contained in:
Alex Holliday
2025-10-08 13:45:07 -07:00
parent 86bb28e239
commit aae1fefb31
5 changed files with 103 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
{
"ignore": ["src/locales/*", "*.log", "node_modules/*"],
"watch": ["src/**/*.js", "*.json"],
"ext": "js,json"
"watch": ["src/**/*.ts", "src/**/*.js", "*.json"],
"ext": "ts,js,json"
}

View File

@@ -74,7 +74,7 @@ export const initializeControllers = (services) => {
controllers.authControllerV2 = new AuthControllerV2(services.authServiceV2, services.inviteServiceV2);
controllers.inviteControllerV2 = new InviteControllerV2(services.inviteServiceV2);
controllers.maintenanceControllerV2 = new MaintenanceControllerV2(services.maintenanceServiceV2);
controllers.monitorControllerV2 = new MonitorControllerV2(services.monitorServiceV2);
controllers.monitorControllerV2 = new MonitorControllerV2(services.monitorServiceV2, services.checkServiceV2);
controllers.notificationChannelControllerV2 = new NotificationChannelControllerV2(services.notificationChannelServiceV2);
controllers.queueControllerV2 = new QueueControllerV2(services.jobQueueV2);

View File

@@ -2,10 +2,13 @@ import { Request, Response, NextFunction } from "express";
import ApiError from "../../utils/ApiError.js";
import MonitorService from "../../service/v2/business/MonitorService.js";
import { MonitorType } from "../../db/v2/models/monitors/Monitor.js";
import CheckService from "../../service/v2/business/CheckService.js";
class MonitorController {
private monitorService: MonitorService;
constructor(monitorService: MonitorService) {
private checkService: CheckService;
constructor(monitorService: MonitorService, checkService: CheckService) {
this.monitorService = monitorService;
this.checkService = checkService;
}
create = async (req: Request, res: Response, next: NextFunction) => {
@@ -25,6 +28,86 @@ class MonitorController {
}
};
getAll = async (req: Request, res: Response, next: NextFunction) => {
try {
const tokenizedUser = req.user;
if (!tokenizedUser) {
return res.status(401).json({ message: "Unauthorized" });
}
let monitors;
if (req.query.embedChecks === "true") {
const page = Math.max(1, Number(req.query.page) || 1);
const limit = Math.max(1, Number(req.query.limit) || 10);
const type: MonitorType[] = req.query.type as MonitorType[];
monitors = await this.monitorService.getAllEmbedChecks(page, limit, type);
} else {
monitors = await this.monitorService.getAll();
}
res.status(200).json({
message: "Monitors retrieved successfully",
data: monitors,
});
} catch (error) {
next(error);
}
};
getChecks = async (req: Request, res: Response, next: NextFunction) => {
try {
const tokenizedUser = req.user;
if (!tokenizedUser) {
return res.status(401).json({ message: "Unauthorized" });
}
const id = req.params.id;
if (!id) {
throw new ApiError("Monitor ID is required", 400);
}
const page = Number(req.query.page);
const rowsPerPage = Number(req.query.rowsPerPage);
if (isNaN(page)) throw new ApiError("Page query parameter must be a number", 400);
if (isNaN(rowsPerPage)) throw new ApiError("rowsPerPage query parameter must be a number", 400);
if (page < 0) throw new ApiError("Page must be greater than 0", 400);
if (rowsPerPage < 0) throw new ApiError("rowsPerPage must be greater than 0", 400);
const { count, checks } = await this.checkService.getChecks(id, page, rowsPerPage);
res.status(200).json({
message: "Checks retrieved successfully",
data: { count, checks },
});
} catch (error) {
next(error);
}
};
toggleActive = async (req: Request, res: Response, next: NextFunction) => {
try {
const tokenizedUser = req.user;
if (!tokenizedUser) {
return res.status(401).json({ message: "Unauthorized" });
}
const id = req.params.id;
if (!id) {
throw new ApiError("Monitor ID is required", 400);
}
const monitor = await this.monitorService.toggleActive(id, tokenizedUser);
res.status(200).json({
message: "Monitor paused/unpaused successfully",
data: monitor,
});
} catch (error) {
next(error);
}
};
get = async (req: Request, res: Response, next: NextFunction) => {
try {
const tokenizedUser = req.user;
@@ -62,55 +145,6 @@ class MonitorController {
}
};
getAll = async (req: Request, res: Response, next: NextFunction) => {
try {
const tokenizedUser = req.user;
if (!tokenizedUser) {
return res.status(401).json({ message: "Unauthorized" });
}
let monitors;
if (req.query.embedChecks === "true") {
const page = Math.max(1, Number(req.query.page) || 1);
const limit = Math.max(1, Number(req.query.limit) || 10);
const type: MonitorType[] = req.query.type as MonitorType[];
monitors = await this.monitorService.getAllEmbedChecks(page, limit, type);
} else {
monitors = await this.monitorService.getAll();
}
res.status(200).json({
message: "Monitors retrieved successfully",
data: monitors,
});
} catch (error) {
next(error);
}
};
toggleActive = async (req: Request, res: Response, next: NextFunction) => {
try {
const tokenizedUser = req.user;
if (!tokenizedUser) {
return res.status(401).json({ message: "Unauthorized" });
}
const id = req.params.id;
if (!id) {
throw new ApiError("Monitor ID is required", 400);
}
const monitor = await this.monitorService.toggleActive(id, tokenizedUser);
res.status(200).json({
message: "Monitor paused/unpaused successfully",
data: monitor,
});
} catch (error) {
next(error);
}
};
update = async (req: Request, res: Response, next: NextFunction) => {
try {
const tokenizedUser = req.user;

View File

@@ -17,12 +17,14 @@ class MonitorRoutes {
this.router.get("/", verifyToken, verifyPermission(["monitors.view"]), this.controller.getAll);
this.router.get("/:id/checks", verifyToken, verifyPermission(["monitors.view"]), this.controller.getChecks);
this.router.patch("/:id/active", verifyToken, verifyPermission(["monitors.update"]), this.controller.toggleActive);
this.router.patch("/:id", verifyToken, verifyPermission(["monitors.update"]), this.controller.update);
this.router.get("/:id", verifyToken, verifyPermission(["monitors.view"]), this.controller.get);
this.router.patch("/:id", verifyToken, verifyPermission(["monitors.update"]), this.controller.update);
this.router.delete("/:id", verifyToken, verifyPermission(["monitors.delete"]), this.controller.delete);
};

View File

@@ -5,6 +5,7 @@ import { MonitorType } from "../../../db/v2/models/monitors/Monitor.js";
import { StatusResponse } from "../infrastructure/NetworkService.js";
import type { ICapturePayload, ILighthousePayload } from "../infrastructure/NetworkService.js";
import mongoose from "mongoose";
import { stat } from "fs";
const SERVICE_NAME = "CheckServiceV2";
export interface ICheckService {
@@ -60,6 +61,7 @@ class CheckService implements ICheckService {
monitorId: monitorId,
type: statusResponse?.type,
status: statusResponse?.status,
httpStatusCode: statusResponse?.code,
message: statusResponse?.message,
responseTime: statusResponse?.responseTime,
timings: statusResponse?.timings,
@@ -130,6 +132,16 @@ class CheckService implements ICheckService {
return false;
}
};
getChecks = async (monitorId: string, page: number, rowsPerPage: number) => {
const count = await Check.countDocuments({ monitorId: new mongoose.Types.ObjectId(monitorId) });
const checks = await Check.find({ monitorId: new mongoose.Types.ObjectId(monitorId) })
.sort({ createdAt: -1 })
.skip(page * rowsPerPage)
.limit(rowsPerPage)
.exec();
return { checks, count };
};
}
export default CheckService;