feat(backend): GET/PUT /api/state mit Dokument-Persistenz

This commit is contained in:
Kenearos 2026-07-07 15:46:48 +02:00
parent 9714d845bb
commit 45503f03ee
2 changed files with 67 additions and 0 deletions

View file

@ -1,11 +1,36 @@
const path = require('path');
const express = require('express');
const { getDoc, putDoc } = require('./db');
const app = express();
app.use(express.json({ limit: '5mb' }));
const KEYS = ['employees', 'duties', 'vacation'];
const EMPTY = { employees: [], duties: {}, vacation: {} };
app.get('/api/health', (req, res) => res.json({ status: 'ok' }));
app.get('/api/state', (req, res) => {
const state = { ...EMPTY, updatedAt: null };
for (const key of KEYS) {
const doc = getDoc(key);
if (doc) {
state[key] = doc.value;
if (!state.updatedAt || doc.updatedAt > state.updatedAt) state.updatedAt = doc.updatedAt;
}
}
res.json(state);
});
app.put('/api/state', (req, res) => {
const body = req.body || {};
const now = new Date().toISOString();
for (const key of KEYS) {
if (body[key] !== undefined) putDoc(key, body[key], now);
}
res.json({ status: 'ok', updatedAt: now });
});
// Statisches Frontend (Repo-Root). Dotfiles werden per Default nicht ausgeliefert.
app.use(express.static(path.join(__dirname, '..')));

42
server/state.test.js Normal file
View file

@ -0,0 +1,42 @@
const { test } = require('node:test');
const assert = require('node:assert');
const fs = require('fs');
const os = require('os');
const path = require('path');
process.env.DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'dp-state-'));
const app = require('./index');
async function req(port, method, body) {
const opts = { method, headers: { 'Content-Type': 'application/json' } };
if (body) opts.body = JSON.stringify(body);
const res = await fetch(`http://127.0.0.1:${port}/api/state`, opts);
return { status: res.status, body: await res.json() };
}
test('leerer Server liefert leeren State', async () => {
const server = app.listen(0);
const { port } = server.address();
try {
const { status, body } = await req(port, 'GET');
assert.strictEqual(status, 200);
assert.deepStrictEqual(body.employees, []);
assert.deepStrictEqual(body.duties, {});
assert.deepStrictEqual(body.vacation, {});
assert.strictEqual(body.updatedAt, null);
} finally { server.close(); }
});
test('PUT dann GET Roundtrip', async () => {
const server = app.listen(0);
const { port } = server.address();
try {
const put = await req(port, 'PUT', { employees: ['Max'], duties: { Max: { '2026-07': [] } } });
assert.strictEqual(put.status, 200);
assert.strictEqual(put.body.status, 'ok');
const get = await req(port, 'GET');
assert.deepStrictEqual(get.body.employees, ['Max']);
assert.deepStrictEqual(get.body.duties, { Max: { '2026-07': [] } });
assert.strictEqual(typeof get.body.updatedAt, 'string');
} finally { server.close(); }
});