← back to Secrets Manager
update-viewer/server.mjs
32 lines
#!/usr/bin/env node
// Credentials & Tokens Update Tracker — local web viewer. Zero deps.
// node server.mjs → http://localhost:9778
// Reads update-items.json; lets Steve toggle status (persisted). No secret VALUES.
import http from 'node:http';
import fs from 'node:fs';
import path from 'node:path';
const DIR = path.dirname(new URL(import.meta.url).pathname);
const DATA = path.join(DIR, 'update-items.json');
const PORT = process.env.PORT || 9778;
const send = (res, code, type, body) => { res.writeHead(code, { 'Content-Type': type, 'Cache-Control': 'no-store' }); res.end(body); };
http.createServer((req, res) => {
const u = new URL(req.url, 'http://localhost');
if (u.pathname === '/') return send(res, 200, 'text/html; charset=utf-8', fs.readFileSync(path.join(DIR, 'index.html')));
if (u.pathname === '/api/items') return send(res, 200, 'application/json', fs.readFileSync(DATA));
if (u.pathname === '/api/toggle' && req.method === 'POST') {
let b = ''; req.on('data', c => b += c); req.on('end', () => {
try {
const { id, status } = JSON.parse(b);
const d = JSON.parse(fs.readFileSync(DATA, 'utf8'));
const it = d.items.find(x => x.id === id);
if (it) { it.status = status; fs.writeFileSync(DATA, JSON.stringify(d, null, 2) + '\n'); }
send(res, 200, 'application/json', JSON.stringify({ ok: !!it }));
} catch (e) { send(res, 400, 'application/json', JSON.stringify({ ok: false, error: e.message })); }
});
return;
}
send(res, 404, 'text/plain', 'not found');
}).listen(PORT, () => console.log(`Credentials Update Tracker → http://localhost:${PORT}`));