From 570fd76062dee6213f216a46bbb2133001095457 Mon Sep 17 00:00:00 2001 From: Dustin Do Date: Fri, 7 Jun 2024 05:21:27 +0700 Subject: [PATCH] feat(api): add wallet API routes (#16) Closes #7 --- apps/api/v1/index.ts | 2 + apps/api/v1/routes/wallets.ts | 111 ++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 apps/api/v1/routes/wallets.ts diff --git a/apps/api/v1/index.ts b/apps/api/v1/index.ts index fcf514eb..7d295ab3 100644 --- a/apps/api/v1/index.ts +++ b/apps/api/v1/index.ts @@ -2,6 +2,7 @@ import { Hono } from 'hono' import { authMiddleware } from './middlewares/auth' import authApp from './routes/auth' import usersApp from './routes/users' +import walletsApp from './routes/wallets' export const hono = new Hono() @@ -9,3 +10,4 @@ hono.use('*', authMiddleware) hono.route('/auth', authApp) hono.route('/users', usersApp) +hono.route('/wallets', walletsApp) diff --git a/apps/api/v1/routes/wallets.ts b/apps/api/v1/routes/wallets.ts new file mode 100644 index 00000000..53ba7851 --- /dev/null +++ b/apps/api/v1/routes/wallets.ts @@ -0,0 +1,111 @@ +import { zValidator } from '@hono/zod-validator' +import { Hono } from 'hono' +import { object, string } from 'zod' +import { getAuthUserStrict } from '../middlewares/auth' +import { + canUserCreateWallet, + canUserDeleteWallet, + canUserUpdateWallet, + createWallet, + deleteWallet, + findUserWallet, + findUserWallets, + getWalletBalance, + updateWallet, + walletWithBalance, +} from '../services/wallet.service' +import { zCreateWallet, zUpdateWallet } from '../validation' + +const router = new Hono() + +router.get('/wallets', async (c) => { + const user = getAuthUserStrict(c) + + const wallets = (await findUserWallets({ user })).map(walletWithBalance) + + return c.json(wallets, 200) +}) + +router.post('/wallets', zValidator('json', zCreateWallet), async (c) => { + const user = getAuthUserStrict(c) + + if (!(await canUserCreateWallet({ user }))) { + return c.json({ message: 'forbidden' }, 403) + } + + const data = c.req.valid('json') + + const wallet = await createWallet({ user, data }) + + return c.json(walletWithBalance(wallet), 201) +}) + +router.put( + '/wallets/:walletId', + zValidator('param', object({ walletId: string() })), + zValidator('json', zUpdateWallet), + async (c) => { + const user = getAuthUserStrict(c) + const { walletId } = c.req.valid('param') + + const wallet = await findUserWallet({ user, walletId }) + + if (!wallet) { + return c.json({ message: 'wallet not found' }, 404) + } + + if (!(await canUserUpdateWallet({ user, walletId }))) { + return c.json({ message: 'forbidden' }, 403) + } + + const data = c.req.valid('json') + + const updatedWallet = await updateWallet({ walletId, data }) + + return c.json(walletWithBalance(updatedWallet), 200) + }, +) + +router.delete( + '/wallets/:walletId', + zValidator('param', object({ walletId: string() })), + async (c) => { + const user = getAuthUserStrict(c) + const { walletId } = c.req.valid('param') + + const wallet = await findUserWallet({ user, walletId }) + + if (!wallet) { + return c.json({ message: 'wallet not found' }, 404) + } + + if (!(await canUserDeleteWallet({ user, walletId }))) { + return c.json({ message: 'forbidden' }, 403) + } + + await deleteWallet({ walletId }) + + return c.json(wallet, 200) + }, +) + +router.get( + '/wallets/:walletId/balance', + zValidator('param', object({ walletId: string() })), + async (c) => { + const user = getAuthUserStrict(c) + const { walletId } = c.req.valid('param') + + const wallet = await findUserWallet({ user, walletId }) + + if (!wallet) { + return c.json({ message: 'wallet not found' }, 404) + } + + const balance = await getWalletBalance({ wallet }) + + return c.json({ wallet, balance }, 200) + }, +) + +export default router