Remove anytype cast from config loader

This commit is contained in:
Lumeille 2024-03-10 16:38:34 +11:00
parent 168b07b4ff
commit f083b02491
5 changed files with 60 additions and 40 deletions

11
package-lock.json generated
View File

@ -12,7 +12,8 @@
"@network-utils/tcp-ping": "^1.2.3", "@network-utils/tcp-ping": "^1.2.3",
"discord-webhook-node": "^1.1.8", "discord-webhook-node": "^1.1.8",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"ping": "^0.4.4" "ping": "^0.4.4",
"zod": "^3.22.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.10.5", "@types/node": "^20.10.5",
@ -183,6 +184,14 @@
"tr46": "~0.0.3", "tr46": "~0.0.3",
"webidl-conversions": "^3.0.0" "webidl-conversions": "^3.0.0"
} }
},
"node_modules/zod": {
"version": "3.22.4",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz",
"integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
} }
} }
} }

View File

@ -19,6 +19,7 @@
"@network-utils/tcp-ping": "^1.2.3", "@network-utils/tcp-ping": "^1.2.3",
"discord-webhook-node": "^1.1.8", "discord-webhook-node": "^1.1.8",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"ping": "^0.4.4" "ping": "^0.4.4",
"zod": "^3.22.4"
} }
} }

View File

@ -1,40 +1,50 @@
import { readFileSync } from "fs" import { readFileSync } from "fs"
import { z } from "zod"
export const defaultInterval = 60 export const defaultInterval = 60
export const defaultNotifyInterval = 300 export const defaultNotifyInterval = 300
export type Config = { const configSchema = z.object({
alertEndpoints: ({ alertEndpoints: z.array(z.object({
enabled: boolean enabled: z.boolean(),
name: string name: z.string()
} & ({ }).and(z.union([
type: "discord-webhook" z.object({
webhookUrl: string type: z.literal("discord-webhook"),
} | { webhookUrl: z.string()
type: "telegram" }),
token: string z.object({
chatIds: string[] type: z.literal("telegram"),
} | { token: z.string(),
type: "pushover" chatIds: z.array(z.string())
token: string }),
destinationIds: string[] z.object({
}))[], type: z.literal("pushover"),
pollEndpoints: ({ token: z.string(),
name: string destinationIds: z.array(z.string())
interval?: number })
notifyInterval?: number ]))),
alertEndpoints: string[] pollEndpoints: z.array(z.object({
} & ({ name: z.string(),
type: "fetch" interval: z.number().default(60),
url: string notifyInterval: z.number().default(300),
} | { alertEndpoints: z.array(z.string())
type: "ping" }).and(z.union([
address: string z.object({
} | { type: z.literal("fetch"),
type: "tcp-ping" url: z.string()
address: string }),
port?: number z.object({
}))[] type: z.literal("ping"),
} address: z.string()
}),
z.object({
type: z.literal("tcp-ping"),
address: z.string(),
port: z.number().default(80)
})
])))
})
export const config = JSON.parse(readFileSync("./config.json").toString()) as Config export type Config = z.infer<typeof configSchema>
export const config = configSchema.parse(JSON.parse(readFileSync("./config.json").toString()))

View File

@ -10,7 +10,7 @@ export const handleDown = (endpointState: EndpointState, curTime: number, endpoi
endpointState.isDown = true endpointState.isDown = true
if (!prevDown) endpointState.downStart = curTime if (!prevDown) endpointState.downStart = curTime
if (curTime - endpointState.lastDownAlert < (endpoint.notifyInterval ?? defaultNotifyInterval) * 1000) return if (curTime - endpointState.lastDownAlert < (endpoint.notifyInterval) * 1000) return
const message = prevDown ? const message = prevDown ?
`[${formatTS(curTime)}] ${endpoint.name} is still down and initially went down at ${formatTS(endpointState.downStart)}` : `[${formatTS(curTime)}] ${endpoint.name} is still down and initially went down at ${formatTS(endpointState.downStart)}` :
`[${formatTS(curTime)}] ${endpoint.name} went down` `[${formatTS(curTime)}] ${endpoint.name} went down`

View File

@ -19,7 +19,7 @@ const isEndpointUp = async (endpoint: Config["pollEndpoints"][number]) => {
return r.ok return r.ok
} }
else if (endpoint.type === "tcp-ping" ) { else if (endpoint.type === "tcp-ping" ) {
const r = await ping({address: endpoint.address, port:endpoint.port ?? 80}) const r = await ping({address: endpoint.address, port:endpoint.port})
return r.errors.length === 0 return r.errors.length === 0
} }
else if (endpoint.type === "ping") { else if (endpoint.type === "ping") {
@ -34,7 +34,7 @@ const executor = async () => {
config.pollEndpoints.map(async endpoint => { config.pollEndpoints.map(async endpoint => {
const endpointState = state.get(endpoint.name) const endpointState = state.get(endpoint.name)
if (endpointState === undefined) console.log(`Could not find endpoint for ${endpoint.name}`) if (endpointState === undefined) console.log(`Could not find endpoint for ${endpoint.name}`)
else if (curTime - endpointState.lastExec > ((endpoint.interval ?? defaultInterval) * 1000)) { else if (curTime - endpointState.lastExec > ((endpoint.interval) * 1000)) {
console.log(`Time to poll ${endpoint.name}`) console.log(`Time to poll ${endpoint.name}`)
endpointState.lastExec = curTime endpointState.lastExec = curTime
if (await isEndpointUp(endpoint)) handleUp(endpointState, curTime, endpoint) if (await isEndpointUp(endpoint)) handleUp(endpointState, curTime, endpoint)