77 lines
2.5 KiB
JavaScript
77 lines
2.5 KiB
JavaScript
import express from 'express'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { checkBackendHealth, fetchStoredAppState, persistAppState } from './appwriteBackend.mjs'
|
|
import { triageIdea } from './aiTriage.mjs'
|
|
|
|
const app = express()
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = path.dirname(__filename)
|
|
const distDir = path.resolve(__dirname, '../dist')
|
|
const port = Number(process.env.BUILDPULSE_PORT || process.env.BUILDPULSE_API_PORT || 3034)
|
|
const host = process.env.BUILDPULSE_HOST || '127.0.0.1'
|
|
|
|
app.use(express.json({ limit: '2mb' }))
|
|
|
|
app.get('/api/health', async (_req, res) => {
|
|
try {
|
|
const health = await checkBackendHealth()
|
|
res.json(health)
|
|
} catch (error) {
|
|
res.status(500).json({ ok: false, backend: 'appwrite', error: error?.message || 'Unknown backend error' })
|
|
}
|
|
})
|
|
|
|
app.get('/api/state', async (_req, res) => {
|
|
try {
|
|
const state = await fetchStoredAppState()
|
|
res.json({ ok: true, backend: 'appwrite', state })
|
|
} catch (error) {
|
|
res.status(500).json({ ok: false, backend: 'appwrite', error: error?.message || 'Failed to fetch state' })
|
|
}
|
|
})
|
|
|
|
app.put('/api/state', async (req, res) => {
|
|
const state = req.body?.state
|
|
if (!state || typeof state !== 'object') {
|
|
res.status(400).json({ ok: false, error: 'Request body must include a state object.' })
|
|
return
|
|
}
|
|
|
|
try {
|
|
await persistAppState(state)
|
|
res.json({ ok: true, backend: 'appwrite' })
|
|
} catch (error) {
|
|
res.status(500).json({ ok: false, backend: 'appwrite', error: error?.message || 'Failed to persist state' })
|
|
}
|
|
})
|
|
|
|
app.post('/api/ai/triage-idea', async (req, res) => {
|
|
const rawIdea = req.body?.raw_idea
|
|
if (typeof rawIdea !== 'string' || !rawIdea.trim()) {
|
|
res.status(400).json({ ok: false, error: 'raw_idea is required.' })
|
|
return
|
|
}
|
|
|
|
try {
|
|
const recommendation = await triageIdea({
|
|
rawIdea,
|
|
optionalContext: typeof req.body?.optional_context === 'string' ? req.body.optional_context : '',
|
|
appContext: req.body?.app_context && typeof req.body.app_context === 'object' ? req.body.app_context : {},
|
|
})
|
|
res.json({ ok: true, provider: process.env.BUILDPULSE_AI_PROVIDER || 'gemini', recommendation })
|
|
} catch (error) {
|
|
res.status(502).json({ ok: false, error: error?.message || 'AI triage failed.' })
|
|
}
|
|
})
|
|
|
|
app.use(express.static(distDir))
|
|
|
|
app.get('/{*path}', (_req, res) => {
|
|
res.sendFile(path.join(distDir, 'index.html'))
|
|
})
|
|
|
|
app.listen(port, host, () => {
|
|
console.log(`BuildPulse listening on http://${host}:${port}`)
|
|
})
|