toes/src/server/index.tsx

62 lines
2.0 KiB
TypeScript

import { allApps, initApps, TOES_URL } from '$apps'
import appsRouter from './api/apps'
import syncRouter from './api/sync'
import systemRouter from './api/system'
import { Hype } from '@because/hype'
const app = new Hype({ layout: false, logging: !!process.env.DEBUG })
app.route('/api/apps', appsRouter)
app.route('/api/sync', syncRouter)
app.route('/api/system', systemRouter)
// Tool URLs: /tool/code?app=todo&file=README.md -> redirect to tool port
app.get('/tool/:tool', c => {
const toolName = c.req.param('tool')
const tool = allApps().find(a => a.tool && a.name === toolName)
if (!tool || tool.state !== 'running' || !tool.port) {
return c.text(`Tool "${toolName}" not found or not running`, 404)
}
const params = new URLSearchParams(c.req.query()).toString()
const base = new URL(TOES_URL)
base.port = String(tool.port)
const url = params ? `${base.origin}?${params}` : base.origin
return c.redirect(url)
})
// Tool API proxy: /api/tools/:tool/* -> proxy to tool port
app.all('/api/tools/:tool/:path{.+}', async c => {
const toolName = c.req.param('tool')
const tool = allApps().find(a => a.tool && a.name === toolName)
if (!tool || tool.state !== 'running' || !tool.port) {
return c.json({ error: `Tool "${toolName}" not found or not running` }, 404)
}
const subPath = '/' + c.req.param('path')
// Build target URL
const params = new URLSearchParams(c.req.query()).toString()
const targetUrl = params
? `http://localhost:${tool.port}${subPath}?${params}`
: `http://localhost:${tool.port}${subPath}`
// Proxy the request
const response = await fetch(targetUrl, {
method: c.req.method,
headers: c.req.raw.headers,
body: c.req.method !== 'GET' && c.req.method !== 'HEAD' ? c.req.raw.body : undefined,
})
return new Response(response.body, {
status: response.status,
headers: response.headers,
})
})
await initApps()
export default {
...app.defaults,
maxRequestBodySize: 1024 * 1024 * 50, // 50MB
}