Openstatus
www.openstatus.dev
1import { createInsertSchema, createSelectSchema } from "drizzle-zod";
2import * as z from "zod";
3
4import { notificationProvider } from "./constants";
5import { notification } from "./notification";
6
7export const notificationProviderSchema = z.enum(notificationProvider);
8
9export const selectNotificationSchema = createSelectSchema(notification).extend(
10 {
11 data: z
12 .preprocess((val) => {
13 return String(val);
14 }, z.string())
15 .prefault("{}"),
16 },
17);
18
19// we need to extend, otherwise data can be `null` or `undefined` - default is not
20export const insertNotificationSchema = createInsertSchema(notification).extend(
21 {
22 data: z.string().prefault("{}"),
23 monitors: z.array(z.number()).optional().prefault([]),
24 },
25);
26
27export type InsertNotification = z.infer<typeof insertNotificationSchema>;
28export type Notification = z.infer<typeof selectNotificationSchema>;
29export type NotificationProvider = z.infer<typeof notificationProviderSchema>;
30
31const phoneRegex = new RegExp(
32 /^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)])?([-]?[\s]?[0-9])+$/,
33);
34
35export const phoneSchema = z.string().regex(phoneRegex, "Invalid Number!");
36export const emailSchema = z.email();
37export const urlSchema = z.url();
38
39export const ntfyDataSchema = z.object({
40 ntfy: z.object({
41 topic: z.string().prefault(""),
42 serverUrl: z.string().prefault("https://ntfy.sh"),
43 token: z.string().optional(),
44 }),
45});
46export const webhookDataSchema = z.object({
47 webhook: z.object({
48 endpoint: z.url(),
49 headers: z
50 .array(z.object({ key: z.string(), value: z.string() }))
51 .optional(),
52 }),
53});
54export const emailDataSchema = z.object({ email: emailSchema });
55export const phoneDataSchema = z.object({ sms: phoneSchema });
56export const slackDataSchema = z.object({ slack: urlSchema });
57export const discordDataSchema = z.object({ discord: urlSchema });
58export const googleChatDataSchema = z.object({ "google-chat": urlSchema });
59export const pagerdutyDataSchema = z.object({ pagerduty: z.string() });
60export const opsgenieDataSchema = z.object({
61 opsgenie: z.object({
62 apiKey: z.string(),
63 region: z.enum(["us", "eu"]),
64 }),
65});
66export const telegramDataSchema = z.object({
67 telegram: z.object({ chatId: z.string() }),
68});
69
70export const whatsappDataSchema = z.object({
71 whatsapp: phoneSchema,
72});
73
74export const NotificationDataSchema = z.union([
75 discordDataSchema,
76 emailDataSchema,
77 ntfyDataSchema,
78 opsgenieDataSchema,
79 pagerdutyDataSchema,
80 phoneDataSchema,
81 telegramDataSchema,
82 slackDataSchema,
83 webhookDataSchema,
84 whatsappDataSchema,
85 googleChatDataSchema,
86]);
87
88export const InsertNotificationWithDataSchema = z.discriminatedUnion(
89 "provider",
90 [
91 insertNotificationSchema.extend(
92 z.object({
93 provider: z.literal("discord"),
94 data: discordDataSchema,
95 }).shape,
96 ),
97 insertNotificationSchema.extend(
98 z.object({
99 provider: z.literal("email"),
100 data: emailDataSchema,
101 }).shape,
102 ),
103 insertNotificationSchema.extend(
104 z.object({
105 provider: z.literal("google-chat"),
106 data: googleChatDataSchema,
107 }).shape,
108 ),
109 insertNotificationSchema.extend(
110 z.object({
111 provider: z.literal("ntfy"),
112 data: ntfyDataSchema,
113 }).shape,
114 ),
115 insertNotificationSchema.extend(
116 z.object({
117 provider: z.literal("pagerduty"),
118 data: pagerdutyDataSchema,
119 }).shape,
120 ),
121 insertNotificationSchema.extend(
122 z.object({
123 provider: z.literal("opsgenie"),
124 data: opsgenieDataSchema,
125 }).shape,
126 ),
127 insertNotificationSchema.extend(
128 z.object({
129 provider: z.literal("sms"),
130 data: phoneDataSchema,
131 }).shape,
132 ),
133 insertNotificationSchema.extend(
134 z.object({
135 provider: z.literal("slack"),
136 data: slackDataSchema,
137 }).shape,
138 ),
139 insertNotificationSchema.extend(
140 z.object({
141 provider: z.literal("webhook"),
142 data: webhookDataSchema,
143 }).shape,
144 ),
145 insertNotificationSchema.merge(
146 z.object({
147 provider: z.literal("whatsapp"),
148 data: whatsappDataSchema,
149 }),
150 ),
151 ],
152);
153
154export type InsertNotificationWithData = z.infer<
155 typeof InsertNotificationWithDataSchema
156>;