Openstatus www.openstatus.dev
at main 204 lines 6.7 kB view raw
1import { z } from "zod"; 2 3import { selectIncidentSchema } from "./incidents/validation"; 4import { selectMaintenanceSchema } from "./maintenances"; 5import { selectMonitorGroupSchema } from "./monitor_groups"; 6import { selectMonitorSchema } from "./monitors"; 7import { selectPageComponentGroupSchema } from "./page_component_groups"; 8import { selectPageComponentSchema } from "./page_components"; 9import { selectPageSchema } from "./pages"; 10import { 11 selectStatusReportSchema, 12 selectStatusReportUpdateSchema, 13} from "./status_reports"; 14import { workspacePlanSchema } from "./workspaces"; 15 16// TODO: create a 'public-status' schema with all the different types and validations 17 18// Base schema without transform so it can be extended 19const selectPublicMonitorBaseSchema = selectMonitorSchema.omit({ 20 body: true, 21 headers: true, 22 method: true, 23 otelEndpoint: true, 24 otelHeaders: true, 25}); 26 27export const selectPublicMonitorSchema = 28 selectPublicMonitorBaseSchema.transform((data) => ({ 29 ...data, 30 name: data.externalName || data.name, 31 })); 32 33export const selectStatusReportPageSchema = selectStatusReportSchema.extend({ 34 statusReportUpdates: z.array(selectStatusReportUpdateSchema).prefault([]), 35 statusReportsToPageComponents: z 36 .array( 37 z.object({ 38 pageComponentId: z.number(), 39 statusReportId: z.number(), 40 pageComponent: selectPageComponentSchema, 41 }), 42 ) 43 .prefault([]), 44}); 45 46export const selectMaintenancePageSchema = selectMaintenanceSchema.extend({ 47 maintenancesToPageComponents: z 48 .array( 49 z.object({ 50 pageComponentId: z.number(), 51 maintenanceId: z.number(), 52 pageComponent: selectPageComponentSchema, 53 }), 54 ) 55 .prefault([]), 56}); 57 58export const selectPageSchemaWithRelation = selectPageSchema.extend({ 59 monitors: z.array(selectMonitorSchema), 60 statusReports: z.array(selectStatusReportPageSchema), 61}); 62 63export const legacy_selectPublicPageSchemaWithRelation = selectPageSchema 64 .extend({ 65 monitors: z.array(selectPublicMonitorSchema).prefault([]), 66 statusReports: z.array(selectStatusReportPageSchema).prefault([]), 67 incidents: z.array(selectIncidentSchema).prefault([]), 68 maintenances: z.array(selectMaintenancePageSchema).prefault([]), 69 workspacePlan: workspacePlanSchema 70 .nullable() 71 .prefault("free") 72 .transform((val) => val ?? "free"), 73 }) 74 .omit({ 75 // workspaceId: true, 76 id: true, 77 }); 78 79const selectPublicMonitorWithStatusSchema = selectPublicMonitorBaseSchema 80 .extend({ 81 status: z 82 .enum(["success", "degraded", "error", "info"]) 83 .prefault("success"), 84 monitorGroupId: z.number().nullable().optional(), 85 order: z.number().default(0).optional(), 86 groupOrder: z.number().default(0).nullish(), 87 }) 88 .transform((data) => ({ 89 ...data, 90 name: data.externalName || data.name, 91 })); 92 93export const statusPageEventSchema = z.object({ 94 id: z.number(), 95 name: z.string(), 96 from: z.date(), 97 to: z.date().nullable(), 98 status: z.enum(["success", "degraded", "error", "info"]).prefault("success"), 99 type: z.enum(["maintenance", "incident", "report"]), 100}); 101 102// Page component with status - used for new tracker system 103const selectPublicPageComponentWithStatusSchema = 104 selectPageComponentSchema.extend({ 105 status: z 106 .enum(["success", "degraded", "error", "info"]) 107 .prefault("success"), 108 events: z.array(statusPageEventSchema).prefault([]), 109 // For monitor-type components - omit status since it's now at component level 110 monitor: selectPublicMonitorBaseSchema 111 .extend({ 112 incidents: selectIncidentSchema.array().nullish(), 113 }) 114 .nullish(), 115 }); 116 117const trackersSchema = z 118 .array( 119 z.discriminatedUnion("type", [ 120 z.object({ 121 type: z.literal("component"), 122 component: selectPublicPageComponentWithStatusSchema, 123 order: z.number(), 124 }), 125 z.object({ 126 type: z.literal("group"), 127 groupId: z.number(), 128 groupName: z.string(), 129 components: z.array(selectPublicPageComponentWithStatusSchema), 130 status: z 131 .enum(["success", "degraded", "error", "info"]) 132 .prefault("success"), 133 order: z.number(), 134 }), 135 ]), 136 ) 137 .prefault([]); 138 139export const selectPageComponentWithMonitorRelation = 140 selectPageComponentSchema.extend({ 141 monitor: selectPublicMonitorBaseSchema 142 .extend({ 143 incidents: selectIncidentSchema.array().nullish(), 144 }) 145 .transform((data) => ({ 146 ...data, 147 name: data.externalName || data.name, 148 })) 149 .nullish(), 150 group: selectPageComponentGroupSchema.nullish(), 151 }); 152 153export type PageComponentWithMonitorRelation = z.infer< 154 typeof selectPageComponentWithMonitorRelation 155>; 156 157export const selectPublicPageLightSchemaWithRelation = selectPageSchema 158 .extend({ 159 monitors: z.array(selectPublicMonitorSchema).prefault([]), 160 statusReports: z.array(selectStatusReportPageSchema).prefault([]), 161 incidents: z.array(selectIncidentSchema).prefault([]), 162 maintenances: z.array(selectMaintenancePageSchema).prefault([]), 163 workspacePlan: workspacePlanSchema 164 .nullable() 165 .prefault("free") 166 .transform((val) => val ?? "free"), 167 // NEW: Include pageComponents for modern consumers 168 pageComponents: selectPageComponentWithMonitorRelation.array().prefault([]), 169 pageComponentGroups: selectPageComponentGroupSchema.array().prefault([]), 170 }) 171 .omit({ 172 id: true, 173 }); 174 175export const selectPublicPageSchemaWithRelation = selectPageSchema.extend({ 176 monitorGroups: selectMonitorGroupSchema.array().prefault([]), 177 // TODO: include status of the monitor 178 monitors: selectPublicMonitorWithStatusSchema.array(), 179 pageComponents: selectPageComponentWithMonitorRelation.array().prefault([]), 180 pageComponentGroups: selectPageComponentGroupSchema.array().prefault([]), 181 trackers: trackersSchema, 182 lastEvents: z.array(statusPageEventSchema), 183 openEvents: z.array(statusPageEventSchema), 184 statusReports: z.array(selectStatusReportPageSchema), 185 incidents: z.array(selectIncidentSchema), 186 maintenances: z.array(selectMaintenancePageSchema), 187 status: z.enum(["success", "degraded", "error", "info"]).prefault("success"), 188 workspacePlan: workspacePlanSchema 189 .nullable() 190 .prefault("free") 191 .transform((val) => val ?? "free"), 192 whiteLabel: z.boolean().prefault(false), 193}); 194 195export type StatusReportWithUpdates = z.infer< 196 typeof selectStatusReportPageSchema 197>; 198export type PublicMonitor = z.infer<typeof selectPublicMonitorSchema>; 199export type PublicPage = z.infer< 200 typeof legacy_selectPublicPageSchemaWithRelation 201>; 202export type PublicPageComponentWithStatus = z.infer< 203 typeof selectPublicPageComponentWithStatusSchema 204>;