From 669b2ed8b83268a4176ee146f5169343605113cd Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Wed, 13 Dec 2023 18:21:04 +0800 Subject: [PATCH] feat: add monitor status page api --- prisma/schema.prisma | 27 ++++++++-- prisma/zod/index.ts | 1 + prisma/zod/monitor.ts | 1 + prisma/zod/monitordata.ts | 1 + prisma/zod/monitorevent.ts | 1 + prisma/zod/monitorstatus.ts | 1 + prisma/zod/monitorstatuspage.ts | 36 +++++++++++++ prisma/zod/notification.ts | 1 + prisma/zod/schemas/index.ts | 7 +++ prisma/zod/telemetryevent.ts | 1 + prisma/zod/telemetrysession.ts | 1 + prisma/zod/user.ts | 1 + prisma/zod/website.ts | 1 + prisma/zod/websiteevent.ts | 1 + prisma/zod/websiteeventdata.ts | 1 + prisma/zod/websitesession.ts | 1 + prisma/zod/websitesessiondata.ts | 1 + prisma/zod/workspace.ts | 5 +- prisma/zod/workspacesonusers.ts | 1 + src/server/trpc/routers/monitor.ts | 86 ++++++++++++++++++++++++++++++ src/types/index.ts | 3 ++ 21 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 prisma/zod/monitorstatuspage.ts create mode 100644 prisma/zod/schemas/index.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a4469a9..f118a4a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -14,6 +14,7 @@ generator json { generator zod { provider = "zod-prisma" modelSuffix = "ModelSchema" + imports = "./zod/schemas" } model User { @@ -40,10 +41,11 @@ model Workspace { createdAt DateTime @default(now()) @db.Timestamptz(6) updatedAt DateTime @updatedAt @db.Timestamptz(6) - users WorkspacesOnUsers[] - websites Website[] - notifications Notification[] - monitors Monitor[] + users WorkspacesOnUsers[] + websites Website[] + notifications Notification[] + monitors Monitor[] + monitorStatusPages MonitorStatusPage[] // for user currentWorkspace selectedUsers User[] @@ -303,3 +305,20 @@ model MonitorStatus { @@id([monitorId, statusName]) } + +model MonitorStatusPage { + id String @id @default(cuid()) @db.VarChar(30) + workspaceId String @db.VarChar(30) + slug String @unique // url slug + title String @db.VarChar(100) + description String @default("") @db.VarChar(1000) + /// [MonitorStatusPageList] + /// @zod.custom(imports.MonitorStatusPageListSchema) + monitorList Json @default("[]") // monitor list + createdAt DateTime @default(now()) @db.Timestamptz(6) + updatedAt DateTime @updatedAt @db.Timestamptz(6) + + workspace Workspace @relation(fields: [workspaceId], references: [id]) + + @@index([slug]) +} diff --git a/prisma/zod/index.ts b/prisma/zod/index.ts index aeac455..298109b 100644 --- a/prisma/zod/index.ts +++ b/prisma/zod/index.ts @@ -13,3 +13,4 @@ export * from "./monitor" export * from "./monitorevent" export * from "./monitordata" export * from "./monitorstatus" +export * from "./monitorstatuspage" diff --git a/prisma/zod/monitor.ts b/prisma/zod/monitor.ts index 1f70f60..ae80008 100644 --- a/prisma/zod/monitor.ts +++ b/prisma/zod/monitor.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteWorkspace, RelatedWorkspaceModelSchema, CompleteWebsite, RelatedWebsiteModelSchema, CompleteNotification, RelatedNotificationModelSchema, CompleteMonitorEvent, RelatedMonitorEventModelSchema, CompleteMonitorData, RelatedMonitorDataModelSchema, CompleteMonitorStatus, RelatedMonitorStatusModelSchema } from "./index" // Helper schema for JSON fields diff --git a/prisma/zod/monitordata.ts b/prisma/zod/monitordata.ts index d72374a..30dc5ab 100644 --- a/prisma/zod/monitordata.ts +++ b/prisma/zod/monitordata.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteMonitor, RelatedMonitorModelSchema } from "./index" export const MonitorDataModelSchema = z.object({ diff --git a/prisma/zod/monitorevent.ts b/prisma/zod/monitorevent.ts index d0f6550..0b78182 100644 --- a/prisma/zod/monitorevent.ts +++ b/prisma/zod/monitorevent.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteMonitor, RelatedMonitorModelSchema } from "./index" export const MonitorEventModelSchema = z.object({ diff --git a/prisma/zod/monitorstatus.ts b/prisma/zod/monitorstatus.ts index c6b6e22..c5d9171 100644 --- a/prisma/zod/monitorstatus.ts +++ b/prisma/zod/monitorstatus.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteMonitor, RelatedMonitorModelSchema } from "./index" // Helper schema for JSON fields diff --git a/prisma/zod/monitorstatuspage.ts b/prisma/zod/monitorstatuspage.ts new file mode 100644 index 0000000..696ece9 --- /dev/null +++ b/prisma/zod/monitorstatuspage.ts @@ -0,0 +1,36 @@ +import * as z from "zod" +import * as imports from "./schemas" +import { CompleteWorkspace, RelatedWorkspaceModelSchema } from "./index" + +// Helper schema for JSON fields +type Literal = boolean | number | string +type Json = Literal | { [key: string]: Json } | Json[] +const literalSchema = z.union([z.string(), z.number(), z.boolean()]) +const jsonSchema: z.ZodSchema = z.lazy(() => z.union([literalSchema, z.array(jsonSchema), z.record(jsonSchema)])) + +export const MonitorStatusPageModelSchema = z.object({ + id: z.string(), + workspaceId: z.string(), + slug: z.string(), + title: z.string(), + description: z.string(), + /** + * [MonitorStatusPageList] + */ + monitorList: imports.MonitorStatusPageListSchema, + createdAt: z.date(), + updatedAt: z.date(), +}) + +export interface CompleteMonitorStatusPage extends z.infer { + workspace: CompleteWorkspace +} + +/** + * RelatedMonitorStatusPageModelSchema contains all relations on your model in addition to the scalars + * + * NOTE: Lazy required in case of potential circular dependencies within schema + */ +export const RelatedMonitorStatusPageModelSchema: z.ZodSchema = z.lazy(() => MonitorStatusPageModelSchema.extend({ + workspace: RelatedWorkspaceModelSchema, +})) diff --git a/prisma/zod/notification.ts b/prisma/zod/notification.ts index 553e61a..6eadbbf 100644 --- a/prisma/zod/notification.ts +++ b/prisma/zod/notification.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteWorkspace, RelatedWorkspaceModelSchema, CompleteMonitor, RelatedMonitorModelSchema } from "./index" // Helper schema for JSON fields diff --git a/prisma/zod/schemas/index.ts b/prisma/zod/schemas/index.ts new file mode 100644 index 0000000..cc452cc --- /dev/null +++ b/prisma/zod/schemas/index.ts @@ -0,0 +1,7 @@ +import { z } from 'zod'; + +export const MonitorStatusPageListSchema = z.array( + z.object({ + id: z.string(), + }) +); diff --git a/prisma/zod/telemetryevent.ts b/prisma/zod/telemetryevent.ts index fb2de7f..1dfadf0 100644 --- a/prisma/zod/telemetryevent.ts +++ b/prisma/zod/telemetryevent.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteTelemetrySession, RelatedTelemetrySessionModelSchema } from "./index" // Helper schema for JSON fields diff --git a/prisma/zod/telemetrysession.ts b/prisma/zod/telemetrysession.ts index cd1b251..48ea5fd 100644 --- a/prisma/zod/telemetrysession.ts +++ b/prisma/zod/telemetrysession.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteTelemetryEvent, RelatedTelemetryEventModelSchema } from "./index" export const TelemetrySessionModelSchema = z.object({ diff --git a/prisma/zod/user.ts b/prisma/zod/user.ts index 8cfde42..ec682b4 100644 --- a/prisma/zod/user.ts +++ b/prisma/zod/user.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteWorkspace, RelatedWorkspaceModelSchema, CompleteWorkspacesOnUsers, RelatedWorkspacesOnUsersModelSchema } from "./index" export const UserModelSchema = z.object({ diff --git a/prisma/zod/website.ts b/prisma/zod/website.ts index 1264adf..b80bafa 100644 --- a/prisma/zod/website.ts +++ b/prisma/zod/website.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteWorkspace, RelatedWorkspaceModelSchema, CompleteMonitor, RelatedMonitorModelSchema, CompleteWebsiteSession, RelatedWebsiteSessionModelSchema, CompleteWebsiteEventData, RelatedWebsiteEventDataModelSchema, CompleteWebsiteSessionData, RelatedWebsiteSessionDataModelSchema } from "./index" export const WebsiteModelSchema = z.object({ diff --git a/prisma/zod/websiteevent.ts b/prisma/zod/websiteevent.ts index 65c507e..1420498 100644 --- a/prisma/zod/websiteevent.ts +++ b/prisma/zod/websiteevent.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteWebsiteEventData, RelatedWebsiteEventDataModelSchema, CompleteWebsiteSession, RelatedWebsiteSessionModelSchema } from "./index" export const WebsiteEventModelSchema = z.object({ diff --git a/prisma/zod/websiteeventdata.ts b/prisma/zod/websiteeventdata.ts index a7050f9..ed6bd66 100644 --- a/prisma/zod/websiteeventdata.ts +++ b/prisma/zod/websiteeventdata.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteWebsite, RelatedWebsiteModelSchema, CompleteWebsiteEvent, RelatedWebsiteEventModelSchema } from "./index" export const WebsiteEventDataModelSchema = z.object({ diff --git a/prisma/zod/websitesession.ts b/prisma/zod/websitesession.ts index 1f668cf..1214ed0 100644 --- a/prisma/zod/websitesession.ts +++ b/prisma/zod/websitesession.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteWebsite, RelatedWebsiteModelSchema, CompleteWebsiteEvent, RelatedWebsiteEventModelSchema, CompleteWebsiteSessionData, RelatedWebsiteSessionDataModelSchema } from "./index" export const WebsiteSessionModelSchema = z.object({ diff --git a/prisma/zod/websitesessiondata.ts b/prisma/zod/websitesessiondata.ts index 25d06f0..845de6b 100644 --- a/prisma/zod/websitesessiondata.ts +++ b/prisma/zod/websitesessiondata.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteWebsite, RelatedWebsiteModelSchema, CompleteWebsiteSession, RelatedWebsiteSessionModelSchema } from "./index" export const WebsiteSessionDataModelSchema = z.object({ diff --git a/prisma/zod/workspace.ts b/prisma/zod/workspace.ts index 97d4254..b74df8a 100644 --- a/prisma/zod/workspace.ts +++ b/prisma/zod/workspace.ts @@ -1,5 +1,6 @@ import * as z from "zod" -import { CompleteWorkspacesOnUsers, RelatedWorkspacesOnUsersModelSchema, CompleteWebsite, RelatedWebsiteModelSchema, CompleteNotification, RelatedNotificationModelSchema, CompleteMonitor, RelatedMonitorModelSchema, CompleteUser, RelatedUserModelSchema } from "./index" +import * as imports from "./schemas" +import { CompleteWorkspacesOnUsers, RelatedWorkspacesOnUsersModelSchema, CompleteWebsite, RelatedWebsiteModelSchema, CompleteNotification, RelatedNotificationModelSchema, CompleteMonitor, RelatedMonitorModelSchema, CompleteMonitorStatusPage, RelatedMonitorStatusPageModelSchema, CompleteUser, RelatedUserModelSchema } from "./index" // Helper schema for JSON fields type Literal = boolean | number | string @@ -24,6 +25,7 @@ export interface CompleteWorkspace extends z.infer websites: CompleteWebsite[] notifications: CompleteNotification[] monitors: CompleteMonitor[] + monitorStatusPages: CompleteMonitorStatusPage[] selectedUsers: CompleteUser[] } @@ -37,5 +39,6 @@ export const RelatedWorkspaceModelSchema: z.ZodSchema = z.laz websites: RelatedWebsiteModelSchema.array(), notifications: RelatedNotificationModelSchema.array(), monitors: RelatedMonitorModelSchema.array(), + monitorStatusPages: RelatedMonitorStatusPageModelSchema.array(), selectedUsers: RelatedUserModelSchema.array(), })) diff --git a/prisma/zod/workspacesonusers.ts b/prisma/zod/workspacesonusers.ts index 090a1b0..0e4701a 100644 --- a/prisma/zod/workspacesonusers.ts +++ b/prisma/zod/workspacesonusers.ts @@ -1,4 +1,5 @@ import * as z from "zod" +import * as imports from "./schemas" import { CompleteUser, RelatedUserModelSchema, CompleteWorkspace, RelatedWorkspaceModelSchema } from "./index" export const WorkspacesOnUsersModelSchema = z.object({ diff --git a/src/server/trpc/routers/monitor.ts b/src/server/trpc/routers/monitor.ts index cf1dd9d..d85b444 100644 --- a/src/server/trpc/routers/monitor.ts +++ b/src/server/trpc/routers/monitor.ts @@ -17,6 +17,7 @@ import { } from '../../model/_schema'; import { OPENAPI_TAG } from '../../utils/const'; import { OpenApiMeta } from 'trpc-openapi'; +import { MonitorStatusPageModelSchema } from '../../../../prisma/zod'; export const monitorRouter = router({ all: workspaceProcedure @@ -417,6 +418,91 @@ export const monitorRouter = router({ }, }); }), + createPage: workspaceOwnerProcedure + .meta( + buildMonitorOpenapi({ + method: 'POST', + path: '/createStatusPage', + }) + ) + .input( + z.object({ + slug: z.string(), + title: z.string(), + }) + ) + .output(MonitorStatusPageModelSchema) + .mutation(async ({ input }) => { + const { workspaceId, slug, title } = input; + + const existSlugCount = await prisma.monitorStatusPage.count({ + where: { + slug, + }, + }); + + if (existSlugCount > 0) { + throw new Error('This slug has been existed'); + } + + const res = await prisma.monitorStatusPage.create({ + data: { + workspaceId, + slug, + title, + }, + }); + + return res; + }), + editPage: workspaceOwnerProcedure + .meta( + buildMonitorOpenapi({ + method: 'PATCH', + path: '/updateStatusPage', + }) + ) + .input( + MonitorStatusPageModelSchema.pick({ + id: true, + }).merge( + MonitorStatusPageModelSchema.pick({ + slug: true, + title: true, + description: true, + monitorList: true, + }).partial() + ) + ) + .output(MonitorStatusPageModelSchema) + .mutation(async ({ input }) => { + const { id, workspaceId, slug, title, description, monitorList } = input; + + if (slug) { + const existSlugCount = await prisma.monitorStatusPage.count({ + where: { + slug, + }, + }); + + if (existSlugCount > 0) { + throw new Error('This slug has been existed'); + } + } + + return prisma.monitorStatusPage.update({ + where: { + id, + workspaceId, + }, + data: { + slug, + title, + description, + monitorList, + }, + }); + }), }); function buildMonitorOpenapi(meta: OpenApiMetaInfo): OpenApiMeta { diff --git a/src/types/index.ts b/src/types/index.ts index 786049c..eeddbda 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -10,5 +10,8 @@ declare global { layouts: Record; items: any[]; } | null; + type MonitorStatusPageList = { + id: string; + }[]; } }