Merge pull request #3424 from bluewave-labs/feat/status-page-infra-section-be
feat: status-page infrastructure section BE
This commit is contained in:
6 files changed
+61
-6
No files matched your search
@@ -0,0 +1,45 @@
|
||||
import mongoose from "mongoose";
|
||||
import { logger } from "@/utils/logger.js";
|
||||
import StatusPageModel from "../models/StatusPage.js";
|
||||
|
||||
export async function migrateStatusPageTypeToArray(): Promise<void> {
|
||||
const SERVICE_NAME = "Migration:MigrateStatusPageTypeToArray";
|
||||
|
||||
try {
|
||||
logger.info({ service: SERVICE_NAME, message: "Starting migration of StatusPage type field from string to array" });
|
||||
|
||||
const db = mongoose.connection.db;
|
||||
if (!db) {
|
||||
throw new Error("Database connection is not initialized");
|
||||
}
|
||||
|
||||
const result = await StatusPageModel.updateMany(
|
||||
{
|
||||
$expr: {
|
||||
$eq: [{ $type: "$type" }, "string"], // only scalar string, not existing array
|
||||
},
|
||||
},
|
||||
[
|
||||
{
|
||||
$set: {
|
||||
type: ["$type"],
|
||||
},
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
if (result.modifiedCount === 0) {
|
||||
logger.info({ service: SERVICE_NAME, message: "No StatusPage documents needed migration" });
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info({
|
||||
service: SERVICE_NAME,
|
||||
message: `Migration complete. Converted ${result.modifiedCount} StatusPage document(s) from string type to array type`,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
logger.error({ service: SERVICE_NAME, message: `Error during StatusPage type migration: ${errorMessage}` });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { convertChecksToTimeSeries } from "./0002_convertChecksToTimeSeries.js";
|
||||
import { cleanupDuplicateMonitorStats } from "./0003_cleanupDuplicateMonitorStats.js";
|
||||
import { fixInfrastructureThresholds } from "./0004_fixInfrastructureThresholds.js";
|
||||
import MigrationModel from "../models/Migration.js";
|
||||
import { migrateStatusPageTypeToArray } from "./0005_migrateStatusPageTypeToArray.js";
|
||||
|
||||
type MigrationEntry = {
|
||||
name: string;
|
||||
@@ -14,6 +15,7 @@ const migrations: MigrationEntry[] = [
|
||||
{ name: "0002_convertChecksToTimeSeries", execute: convertChecksToTimeSeries },
|
||||
{ name: "0003_cleanupDuplicateMonitorStats", execute: cleanupDuplicateMonitorStats },
|
||||
{ name: "0004_fixInfrastructureThresholds", execute: fixInfrastructureThresholds },
|
||||
{ name: "0005_migrateStatusPageTypeToArray", execute: migrateStatusPageTypeToArray },
|
||||
];
|
||||
|
||||
const runMigrations = async (logger?: { info: Function; error: Function }) => {
|
||||
|
||||
@@ -43,9 +43,9 @@ const StatusPageSchema = new Schema<StatusPageDocument>(
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
type: [String],
|
||||
required: true,
|
||||
default: "uptime",
|
||||
default: ["uptime"],
|
||||
enum: StatusPageTypes,
|
||||
},
|
||||
companyName: {
|
||||
@@ -100,6 +100,10 @@ const StatusPageSchema = new Schema<StatusPageDocument>(
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showInfrastructure: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
customCSS: {
|
||||
type: String,
|
||||
default: "",
|
||||
|
||||
@@ -57,6 +57,7 @@ class MongoStatusPagesRepository implements IStatusPagesRepository {
|
||||
showCharts: doc.showCharts,
|
||||
showUptimePercentage: doc.showUptimePercentage,
|
||||
showAdminLoginLink: doc.showAdminLoginLink,
|
||||
showInfrastructure: doc.showInfrastructure,
|
||||
customCSS: doc.customCSS,
|
||||
createdAt: this.toDateString(doc.createdAt),
|
||||
updatedAt: this.toDateString(doc.updatedAt),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const StatusPageTypes = ["uptime"] as const;
|
||||
export const StatusPageTypes = ["uptime", "infrastructure"] as const;
|
||||
export type StatusPageType = (typeof StatusPageTypes)[number];
|
||||
|
||||
export interface StatusPageLogo {
|
||||
@@ -15,7 +15,7 @@ export interface StatusPage {
|
||||
id: string;
|
||||
userId: string;
|
||||
teamId: string;
|
||||
type: StatusPageType;
|
||||
type: StatusPageType[];
|
||||
companyName: string;
|
||||
url: string;
|
||||
timezone?: string;
|
||||
@@ -28,6 +28,7 @@ export interface StatusPage {
|
||||
showCharts: boolean;
|
||||
showUptimePercentage: boolean;
|
||||
showAdminLoginLink: boolean;
|
||||
showInfrastructure: boolean;
|
||||
customCSS: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { z } from "zod";
|
||||
import { booleanCoercion } from "./shared.js";
|
||||
import { StatusPageTypes } from "@/types/statusPage.js";
|
||||
|
||||
//****************************************
|
||||
// Status Page Validations
|
||||
@@ -10,13 +11,13 @@ export const getStatusPageParamValidation = z.object({
|
||||
});
|
||||
|
||||
export const getStatusPageQueryValidation = z.object({
|
||||
type: z.literal("uptime"),
|
||||
type: z.union([z.enum(StatusPageTypes), z.array(z.enum(StatusPageTypes))]).transform((val) => (Array.isArray(val) ? val : [val])),
|
||||
timeFrame: z.coerce.number().optional(),
|
||||
});
|
||||
|
||||
export const createStatusPageBodyValidation = z
|
||||
.object({
|
||||
type: z.literal("uptime"),
|
||||
type: z.union([z.enum(StatusPageTypes), z.array(z.enum(StatusPageTypes))]).transform((val) => (Array.isArray(val) ? val : [val])),
|
||||
companyName: z.string().min(1, "Company name is required"),
|
||||
url: z.string().regex(/^[a-zA-Z0-9_-]+$/, {
|
||||
message: "URL can only contain letters, numbers, underscores, and hyphens",
|
||||
@@ -30,6 +31,7 @@ export const createStatusPageBodyValidation = z
|
||||
showCharts: booleanCoercion.optional(),
|
||||
showUptimePercentage: booleanCoercion,
|
||||
showAdminLoginLink: booleanCoercion.optional(),
|
||||
showInfrastructure: booleanCoercion.optional(),
|
||||
removeLogo: z.union([z.literal("true"), z.literal("false")]).optional(),
|
||||
})
|
||||
.strip();
|
||||
|
||||
Reference in new issue
Block a user