From 0951d066078d9cad500404fbf8a782cf1e625026 Mon Sep 17 00:00:00 2001 From: Lars Hampe Date: Thu, 24 Oct 2024 22:15:47 +0200 Subject: [PATCH] chore: refactor hono structure --- apps/api/src/page/byId.ts | 12 +++++----- apps/api/src/page/create.ts | 10 ++++---- apps/api/src/page/list.ts | 4 ++-- apps/api/src/page/public.ts | 6 ++--- apps/api/src/page/update.ts | 6 ++--- apps/api/src/user/get.ts | 32 ++++++++++++------------- apps/api/src/user/index.ts | 46 ++++++------------------------------ apps/api/src/user/webhook.ts | 37 ++++++++++++++++------------- 8 files changed, 62 insertions(+), 91 deletions(-) diff --git a/apps/api/src/page/byId.ts b/apps/api/src/page/byId.ts index 241ffdc..b05754a 100644 --- a/apps/api/src/page/byId.ts +++ b/apps/api/src/page/byId.ts @@ -1,16 +1,16 @@ import { db, page } from '@boring.tools/database' +import { PageByIdParams, PageOutput } from '@boring.tools/schema' import { createRoute } from '@hono/zod-openapi' import { and, eq } from 'drizzle-orm' - -import { PageByIdParams, PageOutput } from '@boring.tools/schema' import { HTTPException } from 'hono/http-exception' + import { verifyAuthentication } from '../utils/authentication' import type { pageApi } from './index' -const getRoute = createRoute({ +const route = createRoute({ method: 'get', tags: ['page'], - description: 'Get a page', + description: 'Get a page by id', path: '/:id', request: { params: PageByIdParams, @@ -33,8 +33,8 @@ const getRoute = createRoute({ }, }) -export function registerPageById(api: typeof pageApi) { - return api.openapi(getRoute, async (c) => { +export const registerPageById = (api: typeof pageApi) => { + return api.openapi(route, async (c) => { const userId = verifyAuthentication(c) const { id } = c.req.valid('param') diff --git a/apps/api/src/page/create.ts b/apps/api/src/page/create.ts index de1da13..cba5a3e 100644 --- a/apps/api/src/page/create.ts +++ b/apps/api/src/page/create.ts @@ -1,12 +1,12 @@ import { changelogs_to_pages, db, page } from '@boring.tools/database' -import { createRoute, type z } from '@hono/zod-openapi' - import { PageCreateInput, PageOutput } from '@boring.tools/schema' +import { createRoute, type z } from '@hono/zod-openapi' import { HTTPException } from 'hono/http-exception' + import { verifyAuthentication } from '../utils/authentication' import type { pageApi } from './index' -const getRoute = createRoute({ +const route = createRoute({ method: 'post', tags: ['page'], description: 'Create a page', @@ -36,8 +36,8 @@ const getRoute = createRoute({ }, }) -export function registerPageCreate(api: typeof pageApi) { - return api.openapi(getRoute, async (c) => { +export const registerPageCreate = (api: typeof pageApi) => { + return api.openapi(route, async (c) => { const userId = verifyAuthentication(c) const { changelogIds, ...rest }: z.infer = diff --git a/apps/api/src/page/list.ts b/apps/api/src/page/list.ts index 4230d6f..deb6126 100644 --- a/apps/api/src/page/list.ts +++ b/apps/api/src/page/list.ts @@ -1,5 +1,5 @@ import { db, page } from '@boring.tools/database' -import { createRoute, z } from '@hono/zod-openapi' +import { createRoute } from '@hono/zod-openapi' import { and, eq } from 'drizzle-orm' import { PageListOutput } from '@boring.tools/schema' @@ -30,7 +30,7 @@ const route = createRoute({ }, }) -export function registerPageList(api: typeof pageApi) { +export const registerPageList = (api: typeof pageApi) => { return api.openapi(route, async (c) => { const userId = verifyAuthentication(c) diff --git a/apps/api/src/page/public.ts b/apps/api/src/page/public.ts index a14b03c..acf7a2d 100644 --- a/apps/api/src/page/public.ts +++ b/apps/api/src/page/public.ts @@ -6,7 +6,7 @@ import { PagePublicOutput, PagePublicParams } from '@boring.tools/schema' import { HTTPException } from 'hono/http-exception' import type { pageApi } from './index' -const getRoute = createRoute({ +const route = createRoute({ method: 'get', tags: ['page'], description: 'Get a page', @@ -32,8 +32,8 @@ const getRoute = createRoute({ }, }) -export function registerPagePublic(api: typeof pageApi) { - return api.openapi(getRoute, async (c) => { +export const registerPagePublic = (api: typeof pageApi) => { + return api.openapi(route, async (c) => { const { id } = c.req.valid('param') const result = await db.query.page.findFirst({ diff --git a/apps/api/src/page/update.ts b/apps/api/src/page/update.ts index 81d8126..1e639a9 100644 --- a/apps/api/src/page/update.ts +++ b/apps/api/src/page/update.ts @@ -11,7 +11,7 @@ import { HTTPException } from 'hono/http-exception' import { verifyAuthentication } from '../utils/authentication' import type { pageApi } from './index' -const getRoute = createRoute({ +const route = createRoute({ method: 'put', tags: ['page'], description: 'Update a page', @@ -42,8 +42,8 @@ const getRoute = createRoute({ }, }) -export function registerPageUpdate(api: typeof pageApi) { - return api.openapi(getRoute, async (c) => { +export const registerPageUpdate = (api: typeof pageApi) => { + return api.openapi(route, async (c) => { const userId = verifyAuthentication(c) const { id } = c.req.valid('param') diff --git a/apps/api/src/user/get.ts b/apps/api/src/user/get.ts index ab00dea..52cc980 100644 --- a/apps/api/src/user/get.ts +++ b/apps/api/src/user/get.ts @@ -1,11 +1,13 @@ -import { type UserSelect, db, user as userDb } from '@boring.tools/database' +import { db, user as userDb } from '@boring.tools/database' import { UserOutput } from '@boring.tools/schema' import { createRoute } from '@hono/zod-openapi' import { eq } from 'drizzle-orm' +import type { userApi } from '.' -export const route = createRoute({ +const route = createRoute({ method: 'get', path: '/', + tags: ['user'], responses: { 200: { content: { @@ -22,19 +24,17 @@ export const route = createRoute({ }, }) -export const func = async ({ user }: { user: UserSelect }) => { - const result = await db.query.user.findFirst({ - where: eq(userDb.id, user.id), +export const registerUserGet = (api: typeof userApi) => { + return api.openapi(route, async (c) => { + const user = c.get('user') + const result = await db.query.user.findFirst({ + where: eq(userDb.id, user.id), + }) + + if (!result) { + throw new Error('User not found') + } + + return c.json(result, 200) }) - - if (!result) { - throw new Error('User not found') - } - - return result -} - -export default { - route, - func, } diff --git a/apps/api/src/user/index.ts b/apps/api/src/user/index.ts index fd5d4e6..016e8e8 100644 --- a/apps/api/src/user/index.ts +++ b/apps/api/src/user/index.ts @@ -1,48 +1,16 @@ -import { logger } from '@boring.tools/logger' import { OpenAPIHono } from '@hono/zod-openapi' -import { Webhook } from 'svix' import type { Variables } from '..' -import { type ContextModule, captureSentry } from '../utils/sentry' -import get from './get' -import webhook from './webhook' +import type { ContextModule } from '../utils/sentry' +import { registerUserGet } from './get' +import { registerUserWebhook } from './webhook' -const app = new OpenAPIHono<{ Variables: Variables }>() +export const userApi = new OpenAPIHono<{ Variables: Variables }>() const module: ContextModule = { name: 'user', } -app.openapi(get.route, async (c) => { - const user = c.get('user') - try { - const result = await get.func({ user }) - return c.json(result, 201) - } catch (error) { - return captureSentry({ - c, - error, - module, - user, - }) - } -}) +registerUserGet(userApi) +registerUserWebhook(userApi) -app.openapi(webhook.route, async (c) => { - try { - const wh = new Webhook(import.meta.env.CLERK_WEBHOOK_SECRET as string) - const payload = await c.req.json() - const headers = c.req.header() - const verifiedPayload = wh.verify(JSON.stringify(payload), headers) - const result = await webhook.func({ payload: verifiedPayload }) - logger.info('Clerk Webhook', result) - return c.json(result, 200) - } catch (error) { - return captureSentry({ - c, - error, - module, - }) - } -}) - -export default app +export default userApi diff --git a/apps/api/src/user/webhook.ts b/apps/api/src/user/webhook.ts index 871dce7..7c8243a 100644 --- a/apps/api/src/user/webhook.ts +++ b/apps/api/src/user/webhook.ts @@ -3,10 +3,13 @@ import { logger } from '@boring.tools/logger' import { UserOutput, UserWebhookInput } from '@boring.tools/schema' import { createRoute, type z } from '@hono/zod-openapi' import { HTTPException } from 'hono/http-exception' +import { Webhook } from 'svix' +import type userApi from '.' -export const route = createRoute({ +const route = createRoute({ method: 'post', path: '/webhook', + tags: ['user'], request: { body: { content: { @@ -59,20 +62,20 @@ const userCreate = async ({ } } -export const func = async ({ - payload, -}: { - payload: z.infer -}) => { - switch (payload.type) { - case 'user.created': - return userCreate({ payload }) - default: - throw new HTTPException(404, { message: 'Webhook type not supported' }) - } -} - -export default { - route, - func, +export const registerUserWebhook = (api: typeof userApi) => { + return api.openapi(route, async (c) => { + const wh = new Webhook(import.meta.env.CLERK_WEBHOOK_SECRET as string) + const payload = await c.req.json() + const headers = c.req.header() + const verifiedPayload = wh.verify(JSON.stringify(payload), headers) + switch (verifiedPayload.type) { + case 'user.created': { + const result = await userCreate({ payload: verifiedPayload }) + logger.info('Clerk Webhook', result) + return c.json(result, 200) + } + default: + throw new HTTPException(404, { message: 'Webhook type not supported' }) + } + }) }