Files
hianime-api/src/app.ts
2026-03-27 00:33:48 +06:00

63 lines
1.5 KiB
TypeScript

import { Hono, Context } from 'hono';
import { cors } from 'hono/cors';
import hiAnimeRoutes from './routes/routes';
import { AppError } from './utils/errors';
import { fail } from './utils/response';
import { logger } from 'hono/logger';
import config from './config/config';
const app = new Hono();
const origins = config.origin.includes(',')
? config.origin.split(',').map(o => o.trim())
: config.origin === '*'
? '*'
: [config.origin];
app.use(
'*',
cors({
origin: origins,
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
exposeHeaders: ['Content-Length', 'X-Request-Id'],
maxAge: 600,
credentials: true,
})
);
if (!config.isProduction || config.enableLogging) {
app.use('/api/v2/*', logger());
}
app.get('/ping', (c: Context) => {
return c.json({
status: 'ok',
timestamp: new Date().toISOString(),
environment: config.isVercel ? 'vercel' : 'self-hosted',
});
});
app.get('/favicon.ico', (c: Context) => {
return c.body(null, 204);
});
app.route('/api/v2', hiAnimeRoutes);
app.onError((err, c) => {
if (err instanceof AppError) {
return fail(c, err.message, err.statusCode, err.details);
}
console.error('Unexpected Error:', err.message);
if (!config.isProduction) {
console.error('Stack:', err.stack);
}
return fail(c, 'Internal server error', 500);
});
app.notFound((c: Context) => {
return fail(c, 'Route not found', 404);
});
export default app;