docs: add openapi for global and website
This commit is contained in:
parent
243b1dad81
commit
594f3124ef
@ -47,6 +47,7 @@ app.use('/telemetry', telemetryRouter);
|
||||
|
||||
if (env.allowOpenapi) {
|
||||
app.use('/open/_ui', swaggerUI.serve, swaggerUI.setup(trpcOpenapiDocument));
|
||||
app.use('/open/_document', (req, res) => res.send(trpcOpenapiDocument));
|
||||
app.use('/open', trpcOpenapiHttpHandler);
|
||||
}
|
||||
app.use('/trpc', trpcExpressMiddleware);
|
||||
|
@ -21,3 +21,16 @@ export const userInfoSchema = z.object({
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
export const websiteInfoSchema = z.object({
|
||||
id: z.string(),
|
||||
workspaceId: z.string(),
|
||||
name: z.string(),
|
||||
domain: z.string().nullable(),
|
||||
shareId: z.string().nullable(),
|
||||
resetAt: z.date().nullable(),
|
||||
monitorId: z.string().nullable(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
deletedAt: z.date().nullable(),
|
||||
});
|
||||
|
@ -273,7 +273,7 @@ export async function getWebsiteOnlineUserCount(
|
||||
Ret[]
|
||||
>`SELECT count(distinct "sessionId") x FROM "WebsiteEvent" where "websiteId" = ${websiteId} AND "createdAt" >= ${startAt}`;
|
||||
|
||||
return res?.[0].x ?? 0;
|
||||
return Number(res?.[0].x ?? 0);
|
||||
}
|
||||
|
||||
export async function getSessionMetrics(
|
||||
|
@ -19,9 +19,13 @@ export const trpcOpenapiHttpHandler = createOpenApiHttpHandler({
|
||||
createContext,
|
||||
});
|
||||
|
||||
const description = `
|
||||
<h3>Insight into everything</h3>
|
||||
<p>Github: <a href="https://github.com/msgbyte/tianji" target="_blank">https://github.com/msgbyte/tianji</a></p>
|
||||
`.trim();
|
||||
export const trpcOpenapiDocument = generateOpenApiDocument(appRouter, {
|
||||
title: 'Tianji OpenAPI',
|
||||
description: 'Insight into everything',
|
||||
description,
|
||||
version: '1.0.0',
|
||||
baseUrl: '/open',
|
||||
});
|
||||
|
@ -1,12 +1,29 @@
|
||||
import { z } from 'zod';
|
||||
import { publicProcedure, router } from '../trpc';
|
||||
import { OPENAPI_TAG } from '../../utils/const';
|
||||
|
||||
export const globalRouter = router({
|
||||
config: publicProcedure.query(async ({ input }) => {
|
||||
return {
|
||||
allowRegister: checkEnvTrusty(process.env.ALLOW_REGISTER),
|
||||
websiteId: process.env.WEBSITE_ID,
|
||||
};
|
||||
}),
|
||||
config: publicProcedure
|
||||
.meta({
|
||||
openapi: {
|
||||
method: 'GET',
|
||||
path: '/global/config',
|
||||
tags: [OPENAPI_TAG.GLOBAL],
|
||||
},
|
||||
})
|
||||
.input(z.void())
|
||||
.output(
|
||||
z.object({
|
||||
allowRegister: z.boolean(),
|
||||
websiteId: z.string().optional(),
|
||||
})
|
||||
)
|
||||
.query(async ({ input }) => {
|
||||
return {
|
||||
allowRegister: checkEnvTrusty(process.env.ALLOW_REGISTER),
|
||||
websiteId: process.env.WEBSITE_ID,
|
||||
};
|
||||
}),
|
||||
});
|
||||
|
||||
function checkEnvTrusty(env: string | undefined): boolean {
|
||||
|
@ -1,23 +1,38 @@
|
||||
import { router, workspaceOwnerProcedure, workspaceProcedure } from '../trpc';
|
||||
import {
|
||||
OpenApiMetaInfo,
|
||||
router,
|
||||
workspaceOwnerProcedure,
|
||||
workspaceProcedure,
|
||||
} from '../trpc';
|
||||
import { z } from 'zod';
|
||||
import { getWebsiteOnlineUserCount } from '../../model/website';
|
||||
import { prisma } from '../../model/_client';
|
||||
import {
|
||||
EVENT_COLUMNS,
|
||||
FILTER_COLUMNS,
|
||||
OPENAPI_TAG,
|
||||
SESSION_COLUMNS,
|
||||
hostnameRegex,
|
||||
} from '../../utils/const';
|
||||
import { parseDateRange } from '../../utils/common';
|
||||
import { getSessionMetrics, getPageviewMetrics } from '../../model/website';
|
||||
import { websiteInfoSchema } from '../../model/_schema';
|
||||
import { OpenApiMeta } from 'trpc-openapi';
|
||||
|
||||
export const websiteRouter = router({
|
||||
onlineCount: workspaceProcedure
|
||||
.meta(
|
||||
buildWebsiteOpenapi({
|
||||
method: 'GET',
|
||||
path: '/onlineCount',
|
||||
})
|
||||
)
|
||||
.input(
|
||||
z.object({
|
||||
websiteId: z.string(),
|
||||
})
|
||||
)
|
||||
.output(z.number())
|
||||
.query(async ({ input }) => {
|
||||
const websiteId = input.websiteId;
|
||||
|
||||
@ -26,11 +41,18 @@ export const websiteRouter = router({
|
||||
return count;
|
||||
}),
|
||||
info: workspaceProcedure
|
||||
.meta(
|
||||
buildWebsiteOpenapi({
|
||||
method: 'GET',
|
||||
path: '/info',
|
||||
})
|
||||
)
|
||||
.input(
|
||||
z.object({
|
||||
websiteId: z.string(),
|
||||
})
|
||||
)
|
||||
.output(websiteInfoSchema.nullable())
|
||||
.query(async ({ input }) => {
|
||||
const { workspaceId, websiteId } = input;
|
||||
|
||||
@ -44,6 +66,12 @@ export const websiteRouter = router({
|
||||
return website;
|
||||
}),
|
||||
metrics: workspaceProcedure
|
||||
.meta(
|
||||
buildWebsiteOpenapi({
|
||||
method: 'GET',
|
||||
path: '/metrics',
|
||||
})
|
||||
)
|
||||
.input(
|
||||
z.object({
|
||||
websiteId: z.string(),
|
||||
@ -157,6 +185,12 @@ export const websiteRouter = router({
|
||||
return [];
|
||||
}),
|
||||
updateInfo: workspaceOwnerProcedure
|
||||
.meta(
|
||||
buildWebsiteOpenapi({
|
||||
method: 'PUT',
|
||||
path: '/update',
|
||||
})
|
||||
)
|
||||
.input(
|
||||
z.object({
|
||||
websiteId: z.string().cuid2(),
|
||||
@ -168,6 +202,7 @@ export const websiteRouter = router({
|
||||
monitorId: z.string().cuid2().nullish(),
|
||||
})
|
||||
)
|
||||
.output(websiteInfoSchema)
|
||||
.mutation(async ({ input }) => {
|
||||
const { workspaceId, websiteId, name, domain, monitorId } = input;
|
||||
|
||||
@ -186,3 +221,14 @@ export const websiteRouter = router({
|
||||
return websiteInfo;
|
||||
}),
|
||||
});
|
||||
|
||||
function buildWebsiteOpenapi(meta: OpenApiMetaInfo): OpenApiMeta {
|
||||
return {
|
||||
openapi: {
|
||||
tags: [OPENAPI_TAG.WEBSITE],
|
||||
protect: true,
|
||||
...meta,
|
||||
path: `/workspace/{workspaceId}/website/{websiteId}${meta.path}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ export function createContext({ req }: { req: IncomingMessage }) {
|
||||
type Context = inferAsyncReturnType<typeof createContext>;
|
||||
const t = initTRPC.context<Context>().meta<OpenApiMeta>().create();
|
||||
|
||||
export type OpenApiMetaInfo = NonNullable<OpenApiMeta['openapi']>;
|
||||
|
||||
export const middleware = t.middleware;
|
||||
export const router = t.router;
|
||||
export const publicProcedure = t.procedure;
|
||||
|
@ -115,7 +115,9 @@ export const FILTER_COLUMNS = {
|
||||
export const DEFAULT_RESET_DATE = '2000-01-01';
|
||||
|
||||
export enum OPENAPI_TAG {
|
||||
GLOBAL = 'Global',
|
||||
USER = 'User',
|
||||
WEBSITE = 'Website',
|
||||
}
|
||||
|
||||
export const hostnameRegex =
|
||||
|
@ -1,5 +1,3 @@
|
||||
export * from './server';
|
||||
export * from './monitor';
|
||||
export * from './utils';
|
||||
|
||||
export type { MaybePromise } from '@trpc/server';
|
||||
|
@ -2,3 +2,5 @@ export type ExactType<T, U extends Partial<T>> = Omit<T, keyof U> & U;
|
||||
|
||||
export type PickRequired<T, U extends keyof T> = Omit<T, keyof U> &
|
||||
Required<Pick<T, U>>;
|
||||
|
||||
export type { MaybePromise } from '@trpc/server';
|
||||
|
Loading…
Reference in New Issue
Block a user