From b462ba756272fbab3364fdf67c32d24db283b2c5 Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Thu, 7 May 2026 12:38:54 -0400 Subject: [PATCH] refactor(maintenance): centralize DurationUnit + sync OpenAPI spec Convention pass per docs/coding-conventions.md (rules 5/8/10/11): - Promote DurationUnit from a raw union type to a const tuple + derived type. - Mongoose schema enum imports DurationUnits instead of inlining the values. - Both validators import DurationUnits instead of inlining z.enum twice. - Drop stale 'expiry' entries from openapi.json (spec is now strict-mode-correct). --- server/openapi.json | 10 ---------- server/src/db/models/MaintenanceWindow.ts | 4 ++-- server/src/types/maintenanceWindow.ts | 3 ++- server/src/validation/maintenanceWindowValidation.ts | 5 +++-- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/server/openapi.json b/server/openapi.json index f62062332..058e934b7 100644 --- a/server/openapi.json +++ b/server/openapi.json @@ -4657,11 +4657,6 @@ "repeat": { "type": "number", "minimum": 0 - }, - "expiry": { - "type": "string", - "nullable": true, - "format": "date-time" } }, "required": ["monitors", "name", "duration", "durationUnit", "start", "end", "repeat"] @@ -5190,11 +5185,6 @@ "nullable": true, "format": "date-time" }, - "expiry": { - "type": "string", - "nullable": true, - "format": "date-time" - }, "monitors": { "type": "array", "items": { diff --git a/server/src/db/models/MaintenanceWindow.ts b/server/src/db/models/MaintenanceWindow.ts index e3287ce7c..1fc9b5f4a 100644 --- a/server/src/db/models/MaintenanceWindow.ts +++ b/server/src/db/models/MaintenanceWindow.ts @@ -1,5 +1,5 @@ import { Schema, model, type Types } from "mongoose"; -import type { MaintenanceWindow } from "@/types/maintenanceWindow.js"; +import { DurationUnits, type MaintenanceWindow } from "@/types/maintenanceWindow.js"; type MaintenanceWindowDocumentBase = Omit & { monitorId: Types.ObjectId; @@ -38,7 +38,7 @@ const MaintenanceWindowSchema = new Schema( }, durationUnit: { type: String, - enum: ["seconds", "minutes", "hours", "days"], + enum: DurationUnits, }, repeat: { type: Number, diff --git a/server/src/types/maintenanceWindow.ts b/server/src/types/maintenanceWindow.ts index bcbd075a1..950dc1713 100644 --- a/server/src/types/maintenanceWindow.ts +++ b/server/src/types/maintenanceWindow.ts @@ -1,4 +1,5 @@ -export type DurationUnit = "seconds" | "minutes" | "hours" | "days"; +export const DurationUnits = ["seconds", "minutes", "hours", "days"] as const; +export type DurationUnit = (typeof DurationUnits)[number]; export interface MaintenanceWindow { id: string; diff --git a/server/src/validation/maintenanceWindowValidation.ts b/server/src/validation/maintenanceWindowValidation.ts index 9bf775596..bdd11df5f 100644 --- a/server/src/validation/maintenanceWindowValidation.ts +++ b/server/src/validation/maintenanceWindowValidation.ts @@ -1,5 +1,6 @@ import { z } from "zod"; import { booleanCoercion } from "./shared.js"; +import { DurationUnits } from "@/types/maintenanceWindow.js"; const dateToString = z.coerce.date().transform((d) => d.toISOString()); @@ -13,7 +14,7 @@ export const createMaintenanceWindowBodyValidation = z name: z.string().min(1, "Name is required"), active: z.boolean().optional(), duration: z.number().min(1, "Duration is required"), - durationUnit: z.enum(["seconds", "minutes", "hours", "days"]), + durationUnit: z.enum(DurationUnits), start: dateToString, end: dateToString, repeat: z.number().min(0, "Repeat must be a non-negative number"), @@ -71,7 +72,7 @@ export const editMaintenanceByIdWindowBodyValidation = z end: dateToString.optional(), monitors: z.array(z.string()).optional(), duration: z.number().optional(), - durationUnit: z.enum(["seconds", "minutes", "hours", "days"]).optional(), + durationUnit: z.enum(DurationUnits).optional(), }) .strict() .superRefine((data, ctx) => {