feat: monitor openapi and some type issue

This commit is contained in:
moonrailgun 2023-10-25 00:17:18 +08:00
parent c161219137
commit 111cf2f0eb
6 changed files with 180 additions and 33 deletions

View File

@ -3,9 +3,9 @@ import { DateUnit } from '../../utils/date';
import { queryClient } from '../cache';
import { request } from '../request';
import { getUserTimezone } from './user';
import { Website as WebsiteInfo } from '@prisma/client';
import { AppRouterOutput } from '../trpc';
export type { WebsiteInfo };
export type WebsiteInfo = NonNullable<AppRouterOutput['website']['info']>;
export async function getWorkspaceWebsites(
workspaceId: string

View File

@ -31,7 +31,7 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
isLoading,
} = trpc.monitor.get.useQuery({
workspaceId,
id: monitorId,
monitorId,
});
if (isInitialLoading) {

View File

@ -12,10 +12,10 @@ import { useCurrentWorkspaceId } from '../../store/user';
export const MonitorEdit: React.FC = React.memo(() => {
const { monitorId } = useParams<{ monitorId: string }>();
const currentWorkspaceId = useCurrentWorkspaceId();
const workspaceId = useCurrentWorkspaceId();
const { data: monitor, isLoading } = trpc.monitor.get.useQuery({
id: monitorId!,
workspaceId: currentWorkspaceId,
monitorId: monitorId!,
workspaceId,
});
const mutation = useMonitorUpsert();
const navigate = useNavigate();
@ -40,7 +40,7 @@ export const MonitorEdit: React.FC = React.memo(() => {
onSave={async (value) => {
const monitor = await mutation.mutateAsync({
...value,
workspaceId: currentWorkspaceId,
workspaceId,
});
navigate(`/monitor/${monitor.id}`, { replace: true });
}}

View File

@ -1,5 +1,15 @@
import { z } from 'zod';
// Match prisma `JsonValue`
export const jsonFieldSchema = z.union([
z.null(),
z.record(z.any()),
z.array(z.any()),
z.string(),
z.boolean(),
z.number(),
]);
export const workspaceSchema = z.object({
id: z.string(),
name: z.string(),
@ -34,3 +44,36 @@ export const websiteInfoSchema = z.object({
updatedAt: z.date(),
deletedAt: z.date().nullable(),
});
export const monitorInfoSchema = z.object({
id: z.string(),
workspaceId: z.string(),
name: z.string(),
type: z.string(),
active: z.boolean(),
interval: z.number(),
payload: jsonFieldSchema,
createdAt: z.date(),
});
export const monitorInfoWithNotificationIdSchema = monitorInfoSchema.and(
z.object({
notifications: z.array(z.object({ id: z.string() })),
})
);
export const monitorEventSchema = z.object({
id: z.string(),
message: z.string(),
monitorId: z.string(),
type: z.string(),
createdAt: z.date(),
});
export const monitorStatusSchema = z.object({
monitorId: z.string(),
statusName: z.string(),
payload: jsonFieldSchema,
createdAt: z.date(),
updatedAt: z.date(),
});

View File

@ -1,12 +1,33 @@
import { router, workspaceOwnerProcedure, workspaceProcedure } from '../trpc';
import {
OpenApiMetaInfo,
router,
workspaceOwnerProcedure,
workspaceProcedure,
} from '../trpc';
import { prisma } from '../../model/_client';
import { z } from 'zod';
import { monitorManager } from '../../model/monitor';
import { MonitorInfoWithNotificationIds } from '../../../types';
import dayjs from 'dayjs';
import {
monitorEventSchema,
monitorInfoSchema,
monitorInfoWithNotificationIdSchema,
monitorStatusSchema,
} from '../../model/_schema';
import { OPENAPI_TAG } from '../../utils/const';
import { OpenApiMeta } from 'trpc-openapi';
export const monitorRouter = router({
all: workspaceProcedure.query(async ({ input }) => {
all: workspaceProcedure
.meta(
buildMonitorOpenapi({
method: 'GET',
path: '/all',
})
)
.output(z.array(monitorInfoWithNotificationIdSchema))
.query(async ({ input }) => {
const workspaceId = input.workspaceId;
const monitors = await prisma.monitor.findMany({
where: {
@ -24,16 +45,23 @@ export const monitorRouter = router({
return monitors as MonitorInfoWithNotificationIds[];
}),
get: workspaceProcedure
.input(
z.object({
id: z.string().cuid2(),
.meta(
buildMonitorOpenapi({
method: 'GET',
path: '/{monitorId}',
})
)
.input(
z.object({
monitorId: z.string().cuid2(),
})
)
.output(monitorInfoWithNotificationIdSchema.nullable())
.query(async ({ input }) => {
const { id, workspaceId } = input;
const { monitorId, workspaceId } = input;
const monitor = await prisma.monitor.findUnique({
where: {
id,
id: monitorId,
workspaceId,
},
include: {
@ -45,9 +73,15 @@ export const monitorRouter = router({
},
});
return monitor as MonitorInfoWithNotificationIds;
return monitor;
}),
upsert: workspaceOwnerProcedure
.meta(
buildMonitorOpenapi({
method: 'POST',
path: '/upsert',
})
)
.input(
z.object({
id: z.string().cuid2().optional(),
@ -59,6 +93,7 @@ export const monitorRouter = router({
payload: z.object({}).passthrough(),
})
)
.output(monitorInfoSchema)
.mutation(async ({ input }) => {
const {
id,
@ -85,6 +120,12 @@ export const monitorRouter = router({
return monitor;
}),
data: workspaceProcedure
.meta(
buildMonitorOpenapi({
method: 'GET',
path: '/{monitorId}/data',
})
)
.input(
z.object({
monitorId: z.string().cuid2(),
@ -92,6 +133,14 @@ export const monitorRouter = router({
endAt: z.number(),
})
)
.output(
z.array(
z.object({
value: z.number(),
createdAt: z.date(),
})
)
)
.query(async ({ input }) => {
const { monitorId, workspaceId, startAt, endAt } = input;
@ -113,12 +162,26 @@ export const monitorRouter = router({
});
}),
recentData: workspaceProcedure
.meta(
buildMonitorOpenapi({
method: 'GET',
path: '/{monitorId}/recentData',
})
)
.input(
z.object({
monitorId: z.string().cuid2(),
take: z.number(),
})
)
.output(
z.array(
z.object({
value: z.number(),
createdAt: z.date(),
})
)
)
.query(async ({ input }) => {
const { monitorId, take } = input;
@ -134,11 +197,26 @@ export const monitorRouter = router({
});
}),
dataMetrics: workspaceProcedure
.meta(
buildMonitorOpenapi({
method: 'GET',
path: '/{monitorId}/dataMetrics',
})
)
.input(
z.object({
monitorId: z.string().cuid2(),
})
)
.output(
z.object({
recent1DayAvg: z.number(),
recent1DayOnlineCount: z.number(),
recent1DayOfflineCount: z.number(),
recent30DayOnlineCount: z.number(),
recent30DayOfflineCount: z.number(),
})
)
.query(async ({ input }) => {
const { monitorId } = input;
const now = dayjs();
@ -219,11 +297,18 @@ export const monitorRouter = router({
};
}),
events: workspaceProcedure
.meta(
buildMonitorOpenapi({
method: 'GET',
path: '/events',
})
)
.input(
z.object({
monitorId: z.string().cuid2().optional(),
})
)
.output(z.array(monitorEventSchema))
.query(async ({ input }) => {
const { monitorId } = input;
@ -240,12 +325,19 @@ export const monitorRouter = router({
return list;
}),
getStatus: workspaceProcedure
.meta(
buildMonitorOpenapi({
method: 'GET',
path: '/{monitorId}/status',
})
)
.input(
z.object({
monitorId: z.string().cuid2(),
statusName: z.string(),
})
)
.output(monitorStatusSchema.nullable())
.query(async ({ input }) => {
const { monitorId, statusName } = input;
@ -259,3 +351,14 @@ export const monitorRouter = router({
});
}),
});
function buildMonitorOpenapi(meta: OpenApiMetaInfo): OpenApiMeta {
return {
openapi: {
tags: [OPENAPI_TAG.MONITOR],
protect: true,
...meta,
path: `/workspace/{workspaceId}/monitor${meta.path}`,
},
};
}

View File

@ -118,6 +118,7 @@ export enum OPENAPI_TAG {
GLOBAL = 'Global',
USER = 'User',
WEBSITE = 'Website',
MONITOR = 'Monitor',
}
export const hostnameRegex =