mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-05-14 13:38:39 -05:00
Merge pull request #3379 from bluewave-labs/fix/network-providers
fix: network providers
This commit is contained in:
@@ -1,31 +1,65 @@
|
||||
import MongoDB from "../db/MongoDB.js";
|
||||
import NetworkService from "../service/infrastructure/networkService.js";
|
||||
import EmailService from "../service/infrastructure/emailService.js";
|
||||
import BufferService from "../service/infrastructure/bufferService.js";
|
||||
import { IDb } from "@/db/IDb.js";
|
||||
import {
|
||||
// Service classes
|
||||
NetworkService,
|
||||
EmailService,
|
||||
BufferService,
|
||||
GlobalPingService,
|
||||
SuperSimpleQueue,
|
||||
SuperSimpleQueueHelper,
|
||||
NotificationsService,
|
||||
StatusService,
|
||||
NotificationMessageBuilder,
|
||||
MonitorService,
|
||||
StatusPageService,
|
||||
UserService,
|
||||
CheckService,
|
||||
GeoChecksService,
|
||||
DiagnosticService,
|
||||
InviteService,
|
||||
MaintenanceWindowService,
|
||||
IncidentService,
|
||||
// Notification providers
|
||||
WebhookProvider,
|
||||
SlackProvider,
|
||||
EmailProvider,
|
||||
DiscordProvider,
|
||||
PagerDutyProvider,
|
||||
MatrixProvider,
|
||||
// Interfaces
|
||||
INetworkService,
|
||||
IEmailService,
|
||||
IBufferService,
|
||||
ISuperSimpleQueue,
|
||||
INotificationsService,
|
||||
IStatusService,
|
||||
IMonitorService,
|
||||
IUserService,
|
||||
ICheckService,
|
||||
IGeoChecksService,
|
||||
IDiagnosticService,
|
||||
IInviteService,
|
||||
IMaintenanceWindowService,
|
||||
IStatusPageService,
|
||||
IIncidentService,
|
||||
INotificationMessageBuilder,
|
||||
ISettingsService,
|
||||
EnvConfig,
|
||||
} from "@/service/index.js";
|
||||
import SuperSimpleQueueHelper from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js";
|
||||
import SuperSimpleQueue from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js";
|
||||
import UserService from "../service/business/userService.js";
|
||||
import CheckService from "../service/business/checkService.js";
|
||||
import GeoChecksService from "../service/business/geoChecksService.js";
|
||||
import GlobalPingService from "../service/infrastructure/globalPingService.js";
|
||||
import DiagnosticService from "../service/business/diagnosticService.js";
|
||||
import InviteService from "../service/business/inviteService.js";
|
||||
import MaintenanceWindowService from "../service/business/maintenanceWindowService.js";
|
||||
import { MonitorService } from "@/service/index.js";
|
||||
import { StatusPageService, IStatusPageService } from "../service/business/statusPageService.js";
|
||||
import IncidentService from "../service/business/incidentService.js";
|
||||
import { NotificationMessageBuilder, INotificationMessageBuilder } from "../service/infrastructure/notificationMessageBuilder.js";
|
||||
|
||||
// Network providers
|
||||
import { PingProvider } from "@/service/infrastructure/network/PingProvider.js";
|
||||
import { HttpProvider } from "@/service/infrastructure/network/HttpProvider.js";
|
||||
import { AdvancedMatcher } from "@/service/infrastructure/network/AdvancedMatcher.js";
|
||||
import { PageSpeedProvider } from "@/service/infrastructure/network/PageSpeedProvider.js";
|
||||
import { HardwareProvider } from "@/service/infrastructure/network/HardwareProvider.js";
|
||||
import { DockerProvider } from "@/service/infrastructure/network/DockerProvider.js";
|
||||
import { PortProvider } from "@/service/infrastructure/network/PortProvider.js";
|
||||
import { GameProvider } from "@/service/infrastructure/network/GameProvider.js";
|
||||
import { GrpcProvider } from "@/service/infrastructure/network/GrpcProvider.js";
|
||||
|
||||
// Third-party
|
||||
import axios from "axios";
|
||||
import got from "got";
|
||||
import ping from "ping";
|
||||
@@ -44,7 +78,7 @@ import jmespath from "jmespath";
|
||||
import * as grpc from "@grpc/grpc-js";
|
||||
import * as protoLoader from "@grpc/proto-loader";
|
||||
|
||||
// repositories
|
||||
// Repositories
|
||||
import {
|
||||
MongoMonitorsRepository,
|
||||
MongoChecksRepository,
|
||||
@@ -73,33 +107,23 @@ import {
|
||||
IMaintenanceWindowsRepository,
|
||||
} from "@/repositories/index.js";
|
||||
import { ILogger } from "@/utils/logger.js";
|
||||
import { EnvConfig } from "@/service/system/settingsService.js";
|
||||
import { PingProvider } from "@/service/infrastructure/network/PingProvider.js";
|
||||
import { HttpProvider } from "@/service/infrastructure/network/HttpProvider.js";
|
||||
import { AdvancedMatcher } from "@/service/infrastructure/network/AdvancedMatcher.js";
|
||||
import { PageSpeedProvider } from "@/service/infrastructure/network/PageSpeedProvider.js";
|
||||
import { HardwareProvider } from "@/service/infrastructure/network/HardwareProvider.js";
|
||||
import { DockerProvider } from "@/service/infrastructure/network/DockerProvider.js";
|
||||
import { PortProvider } from "@/service/infrastructure/network/PortProvider.js";
|
||||
import { GameProvider } from "@/service/infrastructure/network/GameProvider.js";
|
||||
import { GrpcProvider } from "@/service/infrastructure/network/GrpcProvider.js";
|
||||
|
||||
export type InitializedServices = {
|
||||
settingsService: any;
|
||||
db: any;
|
||||
networkService: any;
|
||||
emailService: any;
|
||||
bufferService: any;
|
||||
statusService: any;
|
||||
jobQueue: any;
|
||||
userService: any;
|
||||
checkService: any;
|
||||
geoChecksService: any;
|
||||
diagnosticService: any;
|
||||
inviteService: any;
|
||||
maintenanceWindowService: any;
|
||||
monitorService: any;
|
||||
incidentService: any;
|
||||
settingsService: ISettingsService;
|
||||
db: IDb;
|
||||
networkService: INetworkService;
|
||||
emailService: IEmailService;
|
||||
bufferService: IBufferService;
|
||||
statusService: IStatusService;
|
||||
jobQueue: ISuperSimpleQueue;
|
||||
userService: IUserService;
|
||||
checkService: ICheckService;
|
||||
geoChecksService: IGeoChecksService;
|
||||
diagnosticService: IDiagnosticService;
|
||||
inviteService: IInviteService;
|
||||
maintenanceWindowService: IMaintenanceWindowService;
|
||||
monitorService: IMonitorService;
|
||||
incidentService: IIncidentService;
|
||||
logger: ILogger;
|
||||
notificationsService: INotificationsService;
|
||||
statusPageService: IStatusPageService;
|
||||
@@ -129,7 +153,7 @@ export const initializeServices = async ({
|
||||
}: {
|
||||
logger: ILogger;
|
||||
envSettings: EnvConfig;
|
||||
settingsService: any;
|
||||
settingsService: ISettingsService;
|
||||
settingsRepository: ISettingsRepository;
|
||||
}): Promise<InitializedServices> => {
|
||||
// Create DB
|
||||
@@ -152,8 +176,7 @@ export const initializeServices = async ({
|
||||
const teamsRepository = new MongoTeamsRepository();
|
||||
const maintenanceWindowsRepository = new MongoMaintenanceWindowsRepository();
|
||||
|
||||
// Providers
|
||||
|
||||
// Network providers
|
||||
const pingProvider = new PingProvider(ping);
|
||||
const httpProvider = new HttpProvider(got, new AdvancedMatcher(jmespath));
|
||||
const pageSpeedProvider = new PageSpeedProvider(httpProvider, settingsService, logger);
|
||||
@@ -163,9 +186,7 @@ export const initializeServices = async ({
|
||||
const gameProvider = new GameProvider(logger, GameDig);
|
||||
const grpcProvider = new GrpcProvider(grpc, protoLoader);
|
||||
|
||||
const networkService = new NetworkService(
|
||||
axios,
|
||||
logger,
|
||||
const networkService = new NetworkService(axios, logger, [
|
||||
pingProvider,
|
||||
httpProvider,
|
||||
pageSpeedProvider,
|
||||
@@ -173,8 +194,8 @@ export const initializeServices = async ({
|
||||
dockerProvider,
|
||||
portProvider,
|
||||
gameProvider,
|
||||
grpcProvider
|
||||
);
|
||||
grpcProvider,
|
||||
]);
|
||||
const emailService = new EmailService(settingsService, fs, path, compile, mjml2html, nodemailer, logger);
|
||||
|
||||
const notificationMessageBuilder = new NotificationMessageBuilder();
|
||||
@@ -196,6 +217,7 @@ export const initializeServices = async ({
|
||||
|
||||
const statusService = new StatusService(logger, bufferService, monitorsRepository, monitorStatsRepository, checksRepository);
|
||||
|
||||
// Notification providers
|
||||
const webhookProvider = new WebhookProvider(logger);
|
||||
const slackProvider = new SlackProvider(logger);
|
||||
const emailProvider = new EmailProvider(emailService, logger);
|
||||
@@ -279,7 +301,6 @@ export const initializeServices = async ({
|
||||
const statusPageService = new StatusPageService(statusPagesRepository);
|
||||
|
||||
const services = {
|
||||
//v1
|
||||
settingsService,
|
||||
db,
|
||||
networkService,
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface IDb {
|
||||
connect(): Promise<void>;
|
||||
disconnect(): Promise<void>;
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
import mongoose from "mongoose";
|
||||
import AppSettings from "./models/AppSettings.js";
|
||||
import { runMigrations } from "./migration/index.js";
|
||||
import AppSettings from "@/db/models/AppSettings.js";
|
||||
import { runMigrations } from "@/db/migration/index.js";
|
||||
import { ILogger } from "@/utils/logger.js";
|
||||
import { EnvConfig } from "@/service/system/settingsService.js";
|
||||
const SERVICE_NAME = "MongoDB";
|
||||
class MongoDB {
|
||||
import { IDb } from "@/db/IDb.js";
|
||||
|
||||
class MongoDB implements IDb {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private logger: ILogger;
|
||||
@@ -46,12 +48,12 @@ class MongoDB {
|
||||
});
|
||||
|
||||
await runMigrations();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
this.logger.error({
|
||||
message: error.message,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
service: SERVICE_NAME,
|
||||
method: "connect",
|
||||
stack: error.stack,
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@@ -63,12 +65,12 @@ class MongoDB {
|
||||
await mongoose.disconnect();
|
||||
this.logger.info({ message: "Disconnected from MongoDB", service: SERVICE_NAME, method: "disconnect" });
|
||||
return;
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
this.logger.error({
|
||||
message: error.message,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
service: SERVICE_NAME,
|
||||
method: "disconnect",
|
||||
stack: error.stack,
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import fs from "fs";
|
||||
import { runMigrations } from "./db/migration/index.js";
|
||||
|
||||
import Logger, { ILogger } from "@/utils/logger.js";
|
||||
import SettingsService from "@/service/system/settingsService.js";
|
||||
import { SettingsService } from "@/service/index.js";
|
||||
import { MongoSettingsRepository } from "./repositories/index.js";
|
||||
|
||||
const SERVICE_NAME = "Server";
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface ICheckService {
|
||||
updateChecksTTL(params: { teamId: string; ttl: string }): Promise<void>;
|
||||
}
|
||||
|
||||
class CheckService implements ICheckService {
|
||||
export class CheckService implements ICheckService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private monitorsRepository: IMonitorsRepository;
|
||||
@@ -195,4 +195,3 @@ class CheckService implements ICheckService {
|
||||
};
|
||||
}
|
||||
|
||||
export default CheckService;
|
||||
|
||||
@@ -3,15 +3,19 @@ import os from "os";
|
||||
|
||||
const SERVICE_NAME = "diagnosticService";
|
||||
|
||||
interface MemoryUsageMetrics {
|
||||
rss: number;
|
||||
heapTotal: number;
|
||||
heapUsed: number;
|
||||
external: number;
|
||||
arrayBuffers: number;
|
||||
export interface IDiagnosticService {
|
||||
getCPUUsage(): Promise<{ userUsageMs: number; systemUsageMs: number; usagePercentage: number }>;
|
||||
getSystemStats(): Promise<{
|
||||
osStats: { freeMemoryBytes: number; totalMemoryBytes: number };
|
||||
memoryUsage: Record<keyof NodeJS.MemoryUsage, number>;
|
||||
cpuUsage: { userUsageMs: number; systemUsageMs: number; usagePercentage: number };
|
||||
v8HeapStats: { totalHeapSizeBytes: number; usedHeapSizeBytes: number; heapSizeLimitBytes: number };
|
||||
eventLoopDelayMs: number;
|
||||
uptimeMs: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
class DiagnosticService {
|
||||
export class DiagnosticService implements IDiagnosticService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
constructor() {
|
||||
@@ -104,4 +108,3 @@ class DiagnosticService {
|
||||
};
|
||||
}
|
||||
|
||||
export default DiagnosticService;
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface IGeoChecksService {
|
||||
getGeoChecksByMonitor(args: { monitorId: string; query: any; teamId: string }): Promise<any>;
|
||||
}
|
||||
|
||||
class GeoChecksService implements IGeoChecksService {
|
||||
export class GeoChecksService implements IGeoChecksService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private logger: ILogger;
|
||||
@@ -189,4 +189,3 @@ class GeoChecksService implements IGeoChecksService {
|
||||
};
|
||||
}
|
||||
|
||||
export default GeoChecksService;
|
||||
|
||||
@@ -5,12 +5,34 @@ 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 } from "@/types/index.js";
|
||||
import type { Incident, IncidentSummary, User } from "@/types/index.js";
|
||||
import type { MonitorActionDecision } from "@/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js";
|
||||
import type { INotificationMessageBuilder } from "@/service/infrastructure/notificationMessageBuilder.js";
|
||||
import type { ILogger } from "@/utils/logger.js";
|
||||
|
||||
class IncidentService {
|
||||
export interface IIncidentService {
|
||||
handleIncident(
|
||||
monitor: Monitor,
|
||||
code: number,
|
||||
decision: MonitorActionDecision,
|
||||
monitorStatusResponse?: MonitorStatusResponse
|
||||
): Promise<Incident | null>;
|
||||
resolveIncident(incidentId: string, userId: string, teamId: string, comment?: string, userEmail?: string): Promise<Incident>;
|
||||
getIncidentsByTeam(
|
||||
teamId: string,
|
||||
sortOrder: string,
|
||||
dateRange: string,
|
||||
page: string,
|
||||
rowsPerPage: string,
|
||||
status: string,
|
||||
monitorId: string,
|
||||
resolutionType: string
|
||||
): Promise<{ incidents: Incident[]; count: number }>;
|
||||
getIncidentSummary(teamId: string, limit?: string): Promise<IncidentSummary>;
|
||||
getIncidentById(incidentId: string, teamId: string): Promise<{ incident: Incident; monitor: Monitor; user: User | null }>;
|
||||
}
|
||||
|
||||
export class IncidentService implements IIncidentService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private logger: ILogger;
|
||||
@@ -245,4 +267,3 @@ class IncidentService {
|
||||
};
|
||||
}
|
||||
|
||||
export default IncidentService;
|
||||
|
||||
@@ -5,7 +5,13 @@ import { AppError } from "@/utils/AppError.js";
|
||||
|
||||
const SERVICE_NAME = "inviteService";
|
||||
|
||||
class InviteService {
|
||||
export interface IInviteService {
|
||||
getInviteToken(params: { invite: Partial<Invite>; teamId: string; userRoles: UserRole[] }): Promise<Invite>;
|
||||
sendInviteEmail(params: { invite: Partial<Invite>; firstName: string; userRoles: UserRole[] }): Promise<void>;
|
||||
verifyInviteToken(params: { inviteToken: string }): Promise<Invite>;
|
||||
}
|
||||
|
||||
export class InviteService implements IInviteService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private settingsService: any;
|
||||
@@ -89,4 +95,3 @@ class InviteService {
|
||||
};
|
||||
}
|
||||
|
||||
export default InviteService;
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
import { IMaintenanceWindowsRepository, IMonitorsRepository } from "@/repositories/index.js";
|
||||
import type { MaintenanceWindow } from "@/types/index.js";
|
||||
import { ParseBoolean } from "@/utils/utils.js";
|
||||
import { AppError } from "@/utils/AppError.js";
|
||||
|
||||
const SERVICE_NAME = "maintenanceWindowService";
|
||||
|
||||
class MaintenanceWindowService {
|
||||
export interface IMaintenanceWindowService {
|
||||
createMaintenanceWindow(params: { teamId: string; body: Partial<MaintenanceWindow> & { monitors: string[] } }): Promise<void>;
|
||||
getMaintenanceWindowById(params: { id: string; teamId: string }): Promise<MaintenanceWindow>;
|
||||
getMaintenanceWindowsByTeamId(params: {
|
||||
teamId: string;
|
||||
query: Record<string, string>;
|
||||
}): Promise<{ maintenanceWindows: MaintenanceWindow[]; maintenanceWindowCount: number }>;
|
||||
getMaintenanceWindowsByMonitorId(params: { monitorId: string; teamId: string }): Promise<MaintenanceWindow[]>;
|
||||
deleteMaintenanceWindow(params: { id: string; teamId: string }): Promise<MaintenanceWindow>;
|
||||
editMaintenanceWindow(params: { id: string; teamId: string; body: Partial<MaintenanceWindow> }): Promise<MaintenanceWindow>;
|
||||
}
|
||||
|
||||
export class MaintenanceWindowService implements IMaintenanceWindowService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
private monitorsRepository: IMonitorsRepository;
|
||||
private maintenanceWindowsRepository: IMaintenanceWindowsRepository;
|
||||
@@ -84,4 +97,3 @@ class MaintenanceWindowService {
|
||||
};
|
||||
}
|
||||
|
||||
export default MaintenanceWindowService;
|
||||
|
||||
@@ -11,10 +11,31 @@ import { canManageRole, type UserRole } from "@/types/user.js";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { AppError } from "@/utils/AppError.js";
|
||||
import { ISuperSimpleQueue } from "@/service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js";
|
||||
|
||||
import { IEmailService } from "@/service/infrastructure/emailService.js";
|
||||
import { ISettingsService } from "@/service/system/settingsService.js";
|
||||
import { ILogger } from "@/utils/logger.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
type JwtType = typeof jwt;
|
||||
const SERVICE_NAME = "userService";
|
||||
|
||||
class UserService {
|
||||
export interface IUserService {
|
||||
issueToken(payload: Partial<User>, appSettings: { jwtTTL?: string; jwtSecret?: string }): string;
|
||||
registerUser(user: Partial<User>, inviteToken: string, file: unknown): Promise<{ user: User; token: string }>;
|
||||
createUser(userData: Partial<User>, teamId: string, actorRoles: UserRole[], file: unknown): Promise<User>;
|
||||
loginUser(email: string, password: string): Promise<{ user: User; token: string }>;
|
||||
editUser(updates: Partial<User & { newPassword?: string }>, file: unknown, currentUser: User): Promise<User>;
|
||||
checkSuperadminExists(): Promise<boolean>;
|
||||
requestRecovery(email: string): Promise<string | false | undefined>;
|
||||
validateRecovery(recoveryToken: string): Promise<void>;
|
||||
resetPassword(password: string, recoveryToken: string): Promise<{ user: User; token: string }>;
|
||||
deleteUser(user: User): Promise<void>;
|
||||
getAllUsers(): Promise<User[]>;
|
||||
getUserById(roles: UserRole[], userId: string): Promise<User>;
|
||||
editUserById(userId: string, patch: Partial<User>): Promise<void>;
|
||||
setPasswordByUserId(userId: string, password: string): Promise<User>;
|
||||
}
|
||||
|
||||
export class UserService implements IUserService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private hashPassword = (password: string): string => {
|
||||
@@ -22,10 +43,10 @@ class UserService {
|
||||
return bcrypt.hashSync(password, salt);
|
||||
};
|
||||
|
||||
private emailService: any;
|
||||
private settingsService: any;
|
||||
private logger: any;
|
||||
private jwt: any;
|
||||
private emailService: IEmailService;
|
||||
private settingsService: ISettingsService;
|
||||
private logger: ILogger;
|
||||
private jwt: JwtType;
|
||||
private jobQueue: ISuperSimpleQueue;
|
||||
private crypto: any;
|
||||
private monitorsRepository: IMonitorsRepository;
|
||||
@@ -50,10 +71,10 @@ class UserService {
|
||||
teamsRepository,
|
||||
}: {
|
||||
crypto: any;
|
||||
emailService: any;
|
||||
settingsService: any;
|
||||
logger: any;
|
||||
jwt: any;
|
||||
emailService: IEmailService;
|
||||
settingsService: ISettingsService;
|
||||
logger: ILogger;
|
||||
jwt: JwtType;
|
||||
jobQueue: ISuperSimpleQueue;
|
||||
monitorsRepository: IMonitorsRepository;
|
||||
usersRepository: IUsersRepository;
|
||||
@@ -134,20 +155,23 @@ class UserService {
|
||||
const html = await this.emailService.buildEmail("welcomeEmailTemplate", {
|
||||
name: newUser.firstName,
|
||||
});
|
||||
this.emailService.sendEmail(newUser.email, "Welcome to Uptime Monitor", html).catch((error: any) => {
|
||||
if (!html) {
|
||||
throw new Error("Failed to build welcome email HTML");
|
||||
}
|
||||
this.emailService.sendEmail(newUser.email, "Welcome to Uptime Monitor", html).catch((error: unknown) => {
|
||||
this.logger.warn({
|
||||
message: error.message,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
service: SERVICE_NAME,
|
||||
method: "registerUser",
|
||||
stack: error.stack,
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
this.logger.warn({
|
||||
message: error.message,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
service: SERVICE_NAME,
|
||||
method: "registerUser",
|
||||
stack: error.stack,
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -313,13 +337,13 @@ class UserService {
|
||||
|
||||
if (roles.includes("superadmin")) {
|
||||
// 2. Remove all jobs, delete checks and alerts
|
||||
res &&
|
||||
res?.length > 0 &&
|
||||
(await Promise.all(
|
||||
if (res && res.length > 0) {
|
||||
await Promise.all(
|
||||
res.map(async (monitor) => {
|
||||
await this.jobQueue.deleteJob(monitor.id);
|
||||
})
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
// 6. Delete the user by id
|
||||
await this.usersRepository.deleteById(userId);
|
||||
@@ -348,4 +372,3 @@ class UserService {
|
||||
return updatedUser;
|
||||
};
|
||||
}
|
||||
export default UserService;
|
||||
|
||||
@@ -1,14 +1,33 @@
|
||||
// Business services
|
||||
export * from "@/service/business/checkService.js";
|
||||
export * from "@/service/business/diagnosticService.js";
|
||||
export * from "@/service/business/geoChecksService.js";
|
||||
export * from "@/service/business/incidentService.js";
|
||||
export * from "@/service/business/inviteService.js";
|
||||
export * from "@/service/business/maintenanceWindowService.js";
|
||||
export * from "@/service/business/monitorService.js";
|
||||
export * from "@/service/business/statusPageService.js";
|
||||
export * from "@/service/business/userService.js";
|
||||
|
||||
// Infrastructure services
|
||||
export * from "@/service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js";
|
||||
export * from "@/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js";
|
||||
export * from "@/service/infrastructure/notificationMessageBuilder.js";
|
||||
export * from "@/service/infrastructure/bufferService.js";
|
||||
export * from "@/service/infrastructure/emailService.js";
|
||||
export * from "@/service/infrastructure/globalPingService.js";
|
||||
export * from "@/service/infrastructure/networkService.js";
|
||||
export * from "@/service/infrastructure/notificationsService.js";
|
||||
export * from "@/service/infrastructure/statusService.js";
|
||||
|
||||
// Notification providers
|
||||
export * from "@/service/infrastructure/notificationProviders/discord.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/email.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/INotificationProvider.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/pagerduty.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/matrix.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/pagerduty.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/slack.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/webhook.js";
|
||||
export * from "@/service/infrastructure/notificationsService.js";
|
||||
export * from "@/service/infrastructure/statusService.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/webhook.js";
|
||||
export * from "@/service/infrastructure/notificationProviders/matrix.js";
|
||||
export * from "@/service/business/statusPageService.js";
|
||||
|
||||
// System services
|
||||
export * from "@/service/system/settingsService.js";
|
||||
|
||||
@@ -53,7 +53,7 @@ export interface ISuperSimpleQueue {
|
||||
obliterate(): Promise<void>;
|
||||
}
|
||||
|
||||
class SuperSimpleQueue implements ISuperSimpleQueue {
|
||||
export class SuperSimpleQueue implements ISuperSimpleQueue {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private logger: ILogger;
|
||||
@@ -290,4 +290,3 @@ class SuperSimpleQueue implements ISuperSimpleQueue {
|
||||
};
|
||||
}
|
||||
|
||||
export default SuperSimpleQueue;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
const SERVICE_NAME = "JobQueueHelper";
|
||||
import type { Monitor } from "@/types/monitor.js";
|
||||
import { AppError } from "@/utils/AppError.js";
|
||||
import { INetworkService, INotificationsService, IStatusService } from "@/service/index.js";
|
||||
import { INetworkService, INotificationsService, IStatusService, IncidentService, type IGeoChecksService } from "@/service/index.js";
|
||||
import type { StatusChangeResult } from "@/types/index.js";
|
||||
import IncidentService from "@/service/business/incidentService.js";
|
||||
import type { IGeoChecksService } from "@/service/business/geoChecksService.js";
|
||||
import {
|
||||
IMaintenanceWindowsRepository,
|
||||
IMonitorsRepository,
|
||||
@@ -15,7 +13,7 @@ import {
|
||||
IGeoChecksRepository,
|
||||
} from "@/repositories/index.js";
|
||||
import { ILogger } from "@/utils/logger.js";
|
||||
import { IBufferService } from "../bufferService.js";
|
||||
import { IBufferService } from "@/service/index.js";
|
||||
|
||||
export interface ISuperSimpleQueueHelper {
|
||||
readonly serviceName: string;
|
||||
@@ -39,7 +37,7 @@ export interface MonitorActionDecision {
|
||||
};
|
||||
}
|
||||
|
||||
class SuperSimpleQueueHelper implements ISuperSimpleQueueHelper {
|
||||
export class SuperSimpleQueueHelper implements ISuperSimpleQueueHelper {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private logger: any;
|
||||
@@ -415,4 +413,3 @@ class SuperSimpleQueueHelper implements ISuperSimpleQueueHelper {
|
||||
}
|
||||
}
|
||||
|
||||
export default SuperSimpleQueueHelper;
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface IBufferService {
|
||||
flushGeoBuffer(): Promise<void>;
|
||||
}
|
||||
|
||||
class BufferService implements IBufferService {
|
||||
export class BufferService implements IBufferService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
private BUFFER_TIMEOUT: number;
|
||||
private logger: ILogger;
|
||||
@@ -178,4 +178,3 @@ class BufferService implements IBufferService {
|
||||
}
|
||||
}
|
||||
|
||||
export default BufferService;
|
||||
|
||||
@@ -23,7 +23,7 @@ export interface IEmailService {
|
||||
sendEmail(to: string, subject: string, html: string, transportConfig?: EmailTransportConfig): Promise<string | false | undefined>;
|
||||
}
|
||||
|
||||
class EmailService implements IEmailService {
|
||||
export class EmailService implements IEmailService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private settingsService: ISettingsService;
|
||||
@@ -179,4 +179,3 @@ class EmailService implements IEmailService {
|
||||
};
|
||||
}
|
||||
|
||||
export default EmailService;
|
||||
|
||||
@@ -54,7 +54,7 @@ export interface IGlobalPingService {
|
||||
pollForResults(measurementId: string, timeoutMs?: number): Promise<GeoCheckResult[]>;
|
||||
}
|
||||
|
||||
class GlobalPingService implements IGlobalPingService {
|
||||
export class GlobalPingService implements IGlobalPingService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private logger: ILogger;
|
||||
@@ -207,4 +207,3 @@ class GlobalPingService implements IGlobalPingService {
|
||||
}
|
||||
}
|
||||
|
||||
export default GlobalPingService;
|
||||
|
||||
@@ -51,7 +51,6 @@ export class PortProvider implements IStatusProvider<PortStatusPayload> {
|
||||
});
|
||||
});
|
||||
if (error) {
|
||||
console.log(error);
|
||||
const errorMessage = error instanceof Error ? error.message : "Port check failed";
|
||||
return {
|
||||
monitorId: monitor.id,
|
||||
|
||||
@@ -1,38 +1,14 @@
|
||||
import type {
|
||||
Monitor,
|
||||
MonitorStatusResponse,
|
||||
GrpcStatusPayload,
|
||||
PageSpeedStatusPayload,
|
||||
HttpStatusPayload,
|
||||
HardwareStatusPayload,
|
||||
PingStatusPayload,
|
||||
DockerStatusPayload,
|
||||
PortStatusPayload,
|
||||
GameStatusPayload,
|
||||
} from "@/types/index.js";
|
||||
import type { Monitor, MonitorStatusResponse } from "@/types/index.js";
|
||||
import type { AxiosStatic } from "axios";
|
||||
import { AppError } from "@/utils/AppError.js";
|
||||
|
||||
import { NETWORK_ERROR } from "@/service/infrastructure/network/utils.js";
|
||||
import { ILogger } from "@/utils/logger.js";
|
||||
import { IStatusProvider } from "./network/IStatusProvider.js";
|
||||
const SERVICE_NAME = "NetworkService";
|
||||
|
||||
export interface INetworkService {
|
||||
readonly serviceName: string;
|
||||
requestStatus(
|
||||
monitor: Monitor
|
||||
): Promise<
|
||||
MonitorStatusResponse<
|
||||
| PingStatusPayload
|
||||
| HttpStatusPayload
|
||||
| PageSpeedStatusPayload
|
||||
| HardwareStatusPayload
|
||||
| DockerStatusPayload
|
||||
| PortStatusPayload
|
||||
| GameStatusPayload
|
||||
| GrpcStatusPayload
|
||||
>
|
||||
>;
|
||||
requestStatus(monitor: Monitor): Promise<MonitorStatusResponse<unknown>>;
|
||||
requestWebhook(
|
||||
type: string,
|
||||
url: string,
|
||||
@@ -47,66 +23,19 @@ export interface INetworkService {
|
||||
}>;
|
||||
}
|
||||
|
||||
class NetworkService implements INetworkService {
|
||||
export class NetworkService implements INetworkService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
private TYPE_PING: string;
|
||||
private TYPE_HTTP: string;
|
||||
private TYPE_PAGESPEED: string;
|
||||
private TYPE_HARDWARE: string;
|
||||
private TYPE_DOCKER: string;
|
||||
private TYPE_PORT: string;
|
||||
private TYPE_GAME: string;
|
||||
private TYPE_GRPC: string;
|
||||
private SERVICE_NAME: string;
|
||||
private NETWORK_ERROR: number;
|
||||
private PING_ERROR: number;
|
||||
|
||||
private axios: AxiosStatic;
|
||||
private logger: ILogger;
|
||||
private pingProvider;
|
||||
private httpProvider;
|
||||
private pageSpeedProvider;
|
||||
private hardwareProvider;
|
||||
private dockerProvider;
|
||||
private portProvider;
|
||||
private gameProvider;
|
||||
private grpcProvider;
|
||||
|
||||
constructor(
|
||||
axios: AxiosStatic,
|
||||
logger: ILogger,
|
||||
pingProvider: IStatusProvider<PingStatusPayload>,
|
||||
httpProvider: IStatusProvider<HttpStatusPayload>,
|
||||
pagespeedProvider: IStatusProvider<PageSpeedStatusPayload>,
|
||||
hardwareProvider: IStatusProvider<HardwareStatusPayload>,
|
||||
dockerProvider: IStatusProvider<DockerStatusPayload>,
|
||||
portProvider: IStatusProvider<PortStatusPayload>,
|
||||
gameProvider: IStatusProvider<GameStatusPayload>,
|
||||
grpcProvider: IStatusProvider<GrpcStatusPayload>
|
||||
private providers: IStatusProvider<unknown>[]
|
||||
) {
|
||||
this.TYPE_PING = "ping";
|
||||
this.TYPE_HTTP = "http";
|
||||
this.TYPE_PAGESPEED = "pagespeed";
|
||||
this.TYPE_HARDWARE = "hardware";
|
||||
this.TYPE_DOCKER = "docker";
|
||||
this.TYPE_PORT = "port";
|
||||
this.TYPE_GAME = "game";
|
||||
this.TYPE_GRPC = "grpc";
|
||||
this.SERVICE_NAME = SERVICE_NAME;
|
||||
this.NETWORK_ERROR = 5000;
|
||||
this.PING_ERROR = 5001;
|
||||
this.axios = axios;
|
||||
this.logger = logger;
|
||||
|
||||
this.pingProvider = pingProvider;
|
||||
this.httpProvider = httpProvider;
|
||||
this.pageSpeedProvider = pagespeedProvider;
|
||||
this.hardwareProvider = hardwareProvider;
|
||||
this.dockerProvider = dockerProvider;
|
||||
this.portProvider = portProvider;
|
||||
this.gameProvider = gameProvider;
|
||||
this.grpcProvider = grpcProvider;
|
||||
}
|
||||
|
||||
get serviceName(): string {
|
||||
@@ -114,41 +43,12 @@ class NetworkService implements INetworkService {
|
||||
}
|
||||
|
||||
// Main entry point
|
||||
async requestStatus(
|
||||
monitor: Monitor
|
||||
): Promise<
|
||||
MonitorStatusResponse<
|
||||
| PingStatusPayload
|
||||
| HttpStatusPayload
|
||||
| PageSpeedStatusPayload
|
||||
| HardwareStatusPayload
|
||||
| DockerStatusPayload
|
||||
| PortStatusPayload
|
||||
| GameStatusPayload
|
||||
| GrpcStatusPayload
|
||||
>
|
||||
> {
|
||||
const type = monitor?.type || "unknown";
|
||||
switch (type) {
|
||||
case this.TYPE_PING:
|
||||
return await this.pingProvider.handle(monitor);
|
||||
case this.TYPE_HTTP:
|
||||
return await this.httpProvider.handle(monitor);
|
||||
case this.TYPE_PAGESPEED:
|
||||
return await this.pageSpeedProvider.handle(monitor);
|
||||
case this.TYPE_HARDWARE:
|
||||
return await this.hardwareProvider.handle(monitor);
|
||||
case this.TYPE_DOCKER:
|
||||
return await this.dockerProvider.handle(monitor);
|
||||
case this.TYPE_PORT:
|
||||
return await this.portProvider.handle(monitor);
|
||||
case this.TYPE_GAME:
|
||||
return await this.gameProvider.handle(monitor);
|
||||
case this.TYPE_GRPC:
|
||||
return await this.grpcProvider.handle(monitor);
|
||||
default:
|
||||
return this.handleUnsupportedType(type);
|
||||
async requestStatus(monitor: Monitor) {
|
||||
const provider = this.providers.find((p) => p.supports(monitor.type));
|
||||
if (!provider) {
|
||||
return this.handleUnsupportedType(monitor.type);
|
||||
}
|
||||
return provider.handle(monitor);
|
||||
}
|
||||
|
||||
private async handleUnsupportedType(type: string): Promise<MonitorStatusResponse> {
|
||||
@@ -157,7 +57,7 @@ class NetworkService implements INetworkService {
|
||||
teamId: "unknown",
|
||||
type: "unknown",
|
||||
status: false,
|
||||
code: this.NETWORK_ERROR,
|
||||
code: NETWORK_ERROR,
|
||||
message: `Unsupported type: ${type}`,
|
||||
};
|
||||
}
|
||||
@@ -181,7 +81,7 @@ class NetworkService implements INetworkService {
|
||||
} catch (err: unknown) {
|
||||
this.logger.warn({
|
||||
message: err instanceof Error ? err.message : String(err),
|
||||
service: this.SERVICE_NAME,
|
||||
service: SERVICE_NAME,
|
||||
method: "requestWebhook",
|
||||
});
|
||||
|
||||
@@ -190,7 +90,7 @@ class NetworkService implements INetworkService {
|
||||
return {
|
||||
type: "webhook",
|
||||
status: false,
|
||||
code: axiosError.response?.status ?? this.NETWORK_ERROR,
|
||||
code: axiosError.response?.status ?? NETWORK_ERROR,
|
||||
message: `Failed to send ${type} notification`,
|
||||
payload: axiosError.response?.data,
|
||||
};
|
||||
@@ -199,7 +99,7 @@ class NetworkService implements INetworkService {
|
||||
return {
|
||||
type: "webhook",
|
||||
status: false,
|
||||
code: this.NETWORK_ERROR,
|
||||
code: NETWORK_ERROR,
|
||||
message: `Failed to send ${type} notification`,
|
||||
};
|
||||
}
|
||||
@@ -225,7 +125,7 @@ class NetworkService implements INetworkService {
|
||||
|
||||
throw new AppError({
|
||||
message: originalMessage || "Error sending PagerDuty notification",
|
||||
service: this.SERVICE_NAME,
|
||||
service: SERVICE_NAME,
|
||||
method: "requestPagerDuty",
|
||||
details: {
|
||||
responseData: err && typeof err === "object" && "response" in err ? (err as { response?: { data?: unknown } }).response?.data : undefined,
|
||||
@@ -268,7 +168,7 @@ class NetworkService implements INetworkService {
|
||||
if (err instanceof Error) {
|
||||
this.logger.warn({
|
||||
message: err.message,
|
||||
service: this.SERVICE_NAME,
|
||||
service: SERVICE_NAME,
|
||||
method: "requestMatrix",
|
||||
});
|
||||
|
||||
@@ -276,7 +176,7 @@ class NetworkService implements INetworkService {
|
||||
const axiosError = err as { response?: { status?: number; data?: unknown } };
|
||||
return {
|
||||
status: false,
|
||||
code: axiosError.response?.status || this.NETWORK_ERROR,
|
||||
code: axiosError.response?.status || NETWORK_ERROR,
|
||||
message: "Failed to send Matrix notification",
|
||||
payload: axiosError.response?.data,
|
||||
};
|
||||
@@ -285,17 +185,16 @@ class NetworkService implements INetworkService {
|
||||
|
||||
this.logger.warn({
|
||||
message: String(err),
|
||||
service: this.SERVICE_NAME,
|
||||
service: SERVICE_NAME,
|
||||
method: "requestMatrix",
|
||||
});
|
||||
|
||||
return {
|
||||
status: false,
|
||||
code: this.NETWORK_ERROR,
|
||||
code: NETWORK_ERROR,
|
||||
message: "Failed to send Matrix notification",
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default NetworkService;
|
||||
|
||||
@@ -21,7 +21,7 @@ export interface ISettingsService {
|
||||
getDBSettings(): Promise<Settings>;
|
||||
}
|
||||
|
||||
class SettingsService implements ISettingsService {
|
||||
export class SettingsService implements ISettingsService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
private settings: EnvConfig;
|
||||
private settingsRepository: ISettingsRepository;
|
||||
@@ -75,4 +75,3 @@ class SettingsService implements ISettingsService {
|
||||
};
|
||||
}
|
||||
|
||||
export default SettingsService;
|
||||
|
||||
Reference in New Issue
Block a user