Merge pull request #3406 from bluewave-labs/fix/incident-controller-typing
fix: Incident Controller/Service typing
This commit is contained in:
4 files changed
+65
-52
No files matched your search
@@ -1,35 +1,30 @@
|
||||
import { AppError } from "@/utils/AppError.js";
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { requireTeamId, requireUserId, requireUserEmail } from "./controllerUtils.js";
|
||||
import { IIncidentService } from "@/service/index.js";
|
||||
import { getIncidentsByTeamQueryValidation, getIncidentSummaryQueryValidation } from "@/validation/incidentValidation.js";
|
||||
|
||||
const SERVICE_NAME = "incidentController";
|
||||
|
||||
const SERVICE_NAME = "IncidentController";
|
||||
class IncidentController {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private incidentService: any;
|
||||
constructor(incidentService: any) {
|
||||
private incidentService: IIncidentService;
|
||||
constructor(incidentService: IIncidentService) {
|
||||
this.incidentService = incidentService;
|
||||
}
|
||||
|
||||
get serviceName() {
|
||||
return IncidentController.SERVICE_NAME;
|
||||
}
|
||||
|
||||
getIncidentsByTeam = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const { sortOrder, dateRange, page, rowsPerPage, status, monitorId, resolutionType } = req.query || {};
|
||||
const validatedQuery = getIncidentsByTeamQueryValidation.parse(req.query);
|
||||
|
||||
const teamId = requireTeamId(req.user?.teamId);
|
||||
const result = await this.incidentService.getIncidentsByTeam(
|
||||
teamId,
|
||||
sortOrder,
|
||||
dateRange,
|
||||
page,
|
||||
rowsPerPage,
|
||||
status,
|
||||
monitorId,
|
||||
resolutionType
|
||||
validatedQuery.sortOrder,
|
||||
validatedQuery.dateRange,
|
||||
validatedQuery.page,
|
||||
validatedQuery.rowsPerPage,
|
||||
validatedQuery.status,
|
||||
validatedQuery.monitorId,
|
||||
validatedQuery.resolutionType
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
@@ -45,10 +40,9 @@ class IncidentController {
|
||||
getIncidentSummary = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const teamId = requireTeamId(req.user?.teamId);
|
||||
const validatedQuery = getIncidentSummaryQueryValidation.parse(req.query);
|
||||
|
||||
const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 10;
|
||||
|
||||
const summary = await this.incidentService.getIncidentSummary(teamId, limit);
|
||||
const summary = await this.incidentService.getIncidentSummary(teamId, validatedQuery.limit);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: "Incident summary retrieved successfully",
|
||||
|
||||
@@ -2,7 +2,6 @@ const SERVICE_NAME = "incidentService";
|
||||
import type { Monitor } from "@/types/monitor.js";
|
||||
import type { MonitorStatusResponse } from "@/types/network.js";
|
||||
import { AppError } from "@/utils/AppError.js";
|
||||
import { ParseBoolean } from "@/utils/utils.js";
|
||||
import { getDateForRange } from "@/utils/dataUtils.js";
|
||||
import type { IIncidentsRepository, IMonitorsRepository, IUsersRepository } from "@/repositories/index.js";
|
||||
import type { Incident, IncidentSummary, User } from "@/types/index.js";
|
||||
@@ -22,13 +21,13 @@ export interface IIncidentService {
|
||||
teamId: string,
|
||||
sortOrder: string,
|
||||
dateRange: string,
|
||||
page: string,
|
||||
rowsPerPage: string,
|
||||
status: string,
|
||||
monitorId: string,
|
||||
resolutionType: string
|
||||
page: number,
|
||||
rowsPerPage: number,
|
||||
status: boolean | undefined,
|
||||
monitorId: string | undefined,
|
||||
resolutionType: string | undefined
|
||||
): Promise<{ incidents: Incident[]; count: number }>;
|
||||
getIncidentSummary(teamId: string, limit?: string): Promise<IncidentSummary>;
|
||||
getIncidentSummary(teamId: string, limit?: number): Promise<IncidentSummary>;
|
||||
getIncidentById(incidentId: string, teamId: string): Promise<{ incident: Incident; monitor: Monitor; user: User | null }>;
|
||||
}
|
||||
|
||||
@@ -164,13 +163,13 @@ export class IncidentService implements IIncidentService {
|
||||
});
|
||||
|
||||
return resolvedIncident;
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
this.logger.error({
|
||||
service: SERVICE_NAME,
|
||||
method: "resolveIncident",
|
||||
message: error.message,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
details: { id: incidentId },
|
||||
stack: error.stack,
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@@ -180,11 +179,11 @@ export class IncidentService implements IIncidentService {
|
||||
teamId: string,
|
||||
sortOrder: string,
|
||||
dateRange: string,
|
||||
page: string,
|
||||
rowsPerPage: string,
|
||||
status: string,
|
||||
monitorId: string,
|
||||
resolutionType: string
|
||||
page: number,
|
||||
rowsPerPage: number,
|
||||
status: boolean | undefined,
|
||||
monitorId: string | undefined,
|
||||
resolutionType: string | undefined
|
||||
) => {
|
||||
try {
|
||||
if (!teamId) {
|
||||
@@ -193,9 +192,8 @@ export class IncidentService implements IIncidentService {
|
||||
|
||||
const startDate = getDateForRange(dateRange);
|
||||
|
||||
const parsedPage = Number.isFinite(parseInt(page)) ? parseInt(page) : 0;
|
||||
const parsedRowsPerPage = Number.isFinite(parseInt(rowsPerPage)) ? parseInt(rowsPerPage) : 20;
|
||||
const parsedStatus = typeof status === "undefined" ? undefined : ParseBoolean(status);
|
||||
const parsedPage = page ?? 0;
|
||||
const parsedRowsPerPage = rowsPerPage ?? 20;
|
||||
|
||||
const incidents = await this.incidentsRepository.findByTeamId(
|
||||
teamId,
|
||||
@@ -203,43 +201,43 @@ export class IncidentService implements IIncidentService {
|
||||
parsedPage,
|
||||
parsedRowsPerPage,
|
||||
sortOrder,
|
||||
parsedStatus,
|
||||
status,
|
||||
monitorId,
|
||||
resolutionType
|
||||
);
|
||||
|
||||
const count = await this.incidentsRepository.countByTeamId(teamId, startDate, parsedStatus, monitorId, resolutionType);
|
||||
const count = await this.incidentsRepository.countByTeamId(teamId, startDate, status, monitorId, resolutionType);
|
||||
|
||||
return { incidents, count };
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
this.logger.error({
|
||||
service: SERVICE_NAME,
|
||||
method: "getIncidentsByTeam",
|
||||
message: error.message,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
details: { teamId },
|
||||
stack: error.stack,
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
getIncidentSummary = async (teamId: string, limit?: string) => {
|
||||
getIncidentSummary = async (teamId: string, limit?: number) => {
|
||||
try {
|
||||
if (!teamId) {
|
||||
throw new AppError({ message: "No team ID in request", service: SERVICE_NAME, method: "getIncidentSummary", status: 400 });
|
||||
}
|
||||
|
||||
const parsedLimit = limit && Number.isFinite(parseInt(limit, 10)) ? parseInt(limit, 10) : 10;
|
||||
const parsedLimit = limit ?? 10;
|
||||
const summary = await this.incidentsRepository.findSummaryByTeamId(teamId, parsedLimit);
|
||||
|
||||
return summary;
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
this.logger.error({
|
||||
service: SERVICE_NAME,
|
||||
method: "getIncidentSummary",
|
||||
message: error.message,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
details: { teamId },
|
||||
stack: error.stack,
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@@ -254,13 +252,13 @@ export class IncidentService implements IIncidentService {
|
||||
user = await this.usersRepository.findById(incident.resolvedBy);
|
||||
}
|
||||
return { incident, monitor, user };
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
this.logger.error({
|
||||
service: SERVICE_NAME,
|
||||
method: "getIncidentById",
|
||||
message: error.message,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
details: { incidentId },
|
||||
stack: error.stack,
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { z } from "zod";
|
||||
import { booleanCoercion } from "./shared.js";
|
||||
|
||||
//****************************************
|
||||
// Incident Validations
|
||||
//****************************************
|
||||
|
||||
export const getIncidentsByTeamQueryValidation = z.object({
|
||||
sortOrder: z.enum(["asc", "desc"]),
|
||||
dateRange: z.enum(["recent", "hour", "day", "week", "month", "all"]),
|
||||
page: z.coerce.number().int().min(0),
|
||||
rowsPerPage: z.coerce.number().int().min(1),
|
||||
status: booleanCoercion.optional(),
|
||||
monitorId: z.string().optional(),
|
||||
resolutionType: z.enum(["manual", "automatic"]).optional(),
|
||||
});
|
||||
|
||||
export const getIncidentSummaryQueryValidation = z.object({
|
||||
limit: z.coerce.number().int().min(1).optional(),
|
||||
});
|
||||
@@ -20,3 +20,4 @@ export * from "./settingsValidation.js";
|
||||
export * from "./statusPageValidation.js";
|
||||
export * from "./notificationValidation.js";
|
||||
export * from "./userValidation.js";
|
||||
export * from "./incidentValidation.js";
|
||||
Reference in new issue
Block a user