refactor(server): add more error utils

This commit is contained in:
RainbowBird
2026-03-28 02:25:44 +08:00
committed by RainbowBird
parent fc51738209
commit d8b3a18d65
5 changed files with 25 additions and 8 deletions
+1 -1
View File
@@ -40,7 +40,7 @@
"injeca": "catalog:",
"pg": "^8.20.0",
"postgres": "^3.4.8",
"stripe": "catalog:",
"stripe": "^20.3.0",
"tsx": "^4.21.0",
"valibot": "catalog:"
},
+5 -5
View File
@@ -8,7 +8,7 @@ import { Hono } from 'hono'
import { integer, minValue, number, object, pipe, safeParse } from 'valibot'
import { authGuard } from '../middlewares/auth'
import { ApiError, createBadRequestError } from '../utils/error'
import { createBadRequestError, createServiceUnavailableError } from '../utils/error'
const CheckoutBodySchema = object({
amount: pipe(number(), integer(), minValue(1)),
@@ -20,7 +20,7 @@ export function createStripeRoutes(fluxService: FluxService, env: Env) {
return new Hono<HonoEnv>()
.post('/checkout', authGuard, async (c) => {
if (!stripe)
throw new ApiError(503, 'STRIPE_NOT_CONFIGURED', 'Stripe is not configured')
throw createServiceUnavailableError('Stripe is not configured', 'STRIPE_NOT_CONFIGURED')
const user = c.get('user')!
const body = await c.req.json()
@@ -58,11 +58,11 @@ export function createStripeRoutes(fluxService: FluxService, env: Env) {
})
.post('/webhook', async (c) => {
if (!stripe || !env.STRIPE_WEBHOOK_SECRET)
throw new ApiError(503, 'STRIPE_NOT_CONFIGURED', 'Stripe is not configured')
throw createServiceUnavailableError('Stripe is not configured', 'STRIPE_NOT_CONFIGURED')
const sig = c.req.header('stripe-signature')
if (!sig)
return c.json({ error: 'No signature' }, 400)
throw createBadRequestError('No signature', 'MISSING_SIGNATURE')
let event: Stripe.Event
try {
@@ -71,7 +71,7 @@ export function createStripeRoutes(fluxService: FluxService, env: Env) {
}
catch (err: unknown) {
const message = err instanceof Error ? err.message : 'Unknown error'
return c.json({ error: `Webhook Error: ${message}` }, 400)
throw createBadRequestError(`Webhook Error: ${message}`, 'WEBHOOK_ERROR')
}
if (event.type === 'checkout.session.completed') {
+2 -1
View File
@@ -7,6 +7,7 @@ import type { HonoEnv } from '../types/hono'
import { Hono } from 'hono'
import { authGuard } from '../middlewares/auth'
import { createPaymentRequiredError } from '../utils/error'
// Only forward these headers from the upstream LLM response
const SAFE_RESPONSE_HEADERS = new Set([
@@ -21,7 +22,7 @@ export function createV1CompletionsRoutes(fluxService: FluxService, env: Env) {
const user = c.get('user')!
const flux = await fluxService.getFlux(user.id)
if (flux.flux <= 0) {
return c.json({ error: 'Insufficient flux' }, 402)
throw createPaymentRequiredError('Insufficient flux')
}
const body = await c.req.json()
+3 -1
View File
@@ -3,6 +3,8 @@ import type { Database } from './db'
import { and, eq, gte, sql } from 'drizzle-orm'
import { createPaymentRequiredError } from '../utils/error'
import * as schema from '../schemas/flux'
export function createFluxService(db: Database<typeof fullSchema>) {
@@ -39,7 +41,7 @@ export function createFluxService(db: Database<typeof fullSchema>) {
.returning()
if (result.length === 0) {
throw new Error('Insufficient flux')
throw createPaymentRequiredError('Insufficient flux')
}
return result[0]
+14
View File
@@ -47,9 +47,23 @@ export function createNotFoundError(message = 'Not Found', details?: unknown) {
return new ApiError(404, 'NOT_FOUND', message, details)
}
/**
* Creates a payment required error (402)
*/
export function createPaymentRequiredError(message: string, details?: unknown) {
return new ApiError(402, 'PAYMENT_REQUIRED', message, details)
}
/**
* Creates a conflict error (409)
*/
export function createConflictError(message: string, details?: unknown) {
return new ApiError(409, 'CONFLICT', message, details)
}
/**
* Creates a service unavailable error (503)
*/
export function createServiceUnavailableError(message = 'Service Unavailable', errorCode = 'SERVICE_UNAVAILABLE', details?: unknown) {
return new ApiError(503, errorCode, message, details)
}