Files
Checkmate/server/src/service/infrastructure/network/PingProvider.ts
T
2026-03-06 09:37:45 -08:00

67 lines
1.8 KiB
TypeScript

import { PingStatusPayload } from "@/types/network.js";
import { IStatusProvider } from "./IStatusProvider.js";
import { MonitorType, Monitor } from "@/types/monitor.js";
import { MonitorStatusResponse } from "@/types/network.js";
import { AppError } from "@/utils/AppError.js";
import ping from "ping";
import { timeRequest } from "@/service/infrastructure/network/utils.js";
const SERVICE_NAME = "PingProvider";
type Ping = typeof ping;
export class PingProvider implements IStatusProvider<PingStatusPayload> {
readonly type = "ping";
constructor(private ping: Ping) {}
supports(type: MonitorType): boolean {
return type === "ping";
}
private sanitizeHost(url: string): string {
return url
.replace(/^https?:\/\//, "")
.replace(/\/.*$/, "")
.replace(/:.*/, "");
}
async handle(monitor: Monitor): Promise<MonitorStatusResponse<PingStatusPayload>> {
try {
if (!monitor.url) {
throw new Error("URL is required for ping monitor");
}
const sanitizedHost = this.sanitizeHost(monitor.url);
const { response, error } = await timeRequest<PingStatusPayload>(() => this.ping.promise.probe(sanitizedHost));
if (error) {
throw error;
}
if (!response) {
throw new Error(`No response from ping for host: ${sanitizedHost}`);
}
const responseTime = typeof response.time === "number" ? response.time : parseFloat(String(response.time)) || 0;
return {
monitorId: monitor.id,
teamId: monitor.teamId,
type: monitor.type,
status: response.alive ?? false,
code: response.alive ? 200 : 5000,
message: response.alive ? "Success" : "Ping failed",
responseTime,
payload: response,
};
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
throw new AppError({
message,
service: SERVICE_NAME,
method: "handle",
});
}
}
}