/opt/canhelp/apps/api/src/routes
Edit: /opt/canhelp/apps/api/src/routes/uploads.ts (1526B)
import { Hono } from 'hono'
import { serveStatic } from '@hono/node-server/serve-static'
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import { requireAuth, type AuthVariables } from '../middleware/auth.js'
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml']
const MAX_SIZE = (Number(process.env.MAX_FILE_SIZE_MB) || 5) * 1024 * 1024
const _dir = path.dirname(fileURLToPath(import.meta.url))
const UPLOAD_DIR = process.env.UPLOAD_DIR
? path.resolve(process.env.UPLOAD_DIR)
: path.resolve(_dir, '../../uploads')
if (!fs.existsSync(UPLOAD_DIR)) {
fs.mkdirSync(UPLOAD_DIR, { recursive: true })
}
const app = new Hono<{ Variables: AuthVariables }>()
// POST /uploads
app.post('/', requireAuth, async (c) => {
const formData = await c.req.formData()
const file = formData.get('file') as File | null
if (!file) return c.json({ error: 'No file provided' }, 400)
if (!ALLOWED_TYPES.includes(file.type)) {
return c.json({ error: 'Only JPEG, PNG, GIF, WebP and SVG images are allowed' }, 400)
}
if (file.size > MAX_SIZE) {
return c.json({ error: `File too large (max ${MAX_SIZE / 1024 / 1024}MB)` }, 400)
}
const ext = file.name.split('.').pop() || 'jpg'
const filename = `${crypto.randomUUID()}.${ext}`
const dest = path.join(UPLOAD_DIR, filename)
const buffer = Buffer.from(await file.arrayBuffer())
fs.writeFileSync(dest, buffer)
return c.json({ url: `/api/uploads/${filename}` }, 201)
})
export default app