chore: maintenance — test coverage, route cleanup, README rewrite
All checks were successful
CI / test (pull_request) Successful in 13s
CI / build-dev (pull_request) Has been skipped

- Add fmtHistVal and stateClass helper tests (7 new, 106 total)
- Add import regression test: missing name field returns 400 not 500
- Fix normalise() crash on missing name: body.name.trim() → (body.name ?? '').trim()
- Extract duplicate DB error handler into handleDbError() helper
- Rewrite README from scratch with audit log, export/import, full API docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-28 14:46:48 -04:00
parent f16fb3e088
commit 0ecfa7dbc9
4 changed files with 191 additions and 82 deletions

View File

@@ -28,9 +28,16 @@ function validate(body) {
return errors;
}
function handleDbError(context, e, res) {
if (e.message.includes('UNIQUE')) return res.status(409).json({ error: 'vmid already exists' });
if (e.message.includes('CHECK')) return res.status(400).json({ error: 'invalid field value' });
console.error(context, e);
res.status(500).json({ error: 'internal server error' });
}
function normalise(body) {
const row = {
name: body.name.trim(),
name: (body.name ?? '').trim(),
state: body.state,
stack: body.stack,
vmid: body.vmid,
@@ -84,10 +91,7 @@ router.post('/instances', (req, res) => {
const created = getInstance(data.vmid);
res.status(201).json(created);
} catch (e) {
if (e.message.includes('UNIQUE')) return res.status(409).json({ error: 'vmid already exists' });
if (e.message.includes('CHECK')) return res.status(400).json({ error: 'invalid field value' });
console.error('POST /api/instances', e);
res.status(500).json({ error: 'internal server error' });
handleDbError('POST /api/instances', e, res);
}
});
@@ -105,10 +109,7 @@ router.put('/instances/:vmid', (req, res) => {
updateInstance(vmid, data);
res.json(getInstance(data.vmid));
} catch (e) {
if (e.message.includes('UNIQUE')) return res.status(409).json({ error: 'vmid already exists' });
if (e.message.includes('CHECK')) return res.status(400).json({ error: 'invalid field value' });
console.error('PUT /api/instances/:vmid', e);
res.status(500).json({ error: 'internal server error' });
handleDbError('PUT /api/instances/:vmid', e, res);
}
});
@@ -155,7 +156,6 @@ router.delete('/instances/:vmid', (req, res) => {
deleteInstance(vmid);
res.status(204).end();
} catch (e) {
console.error('DELETE /api/instances/:vmid', e);
res.status(500).json({ error: 'internal server error' });
handleDbError('DELETE /api/instances/:vmid', e, res);
}
});