Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248// AC Machines — REST API for machine management// GET /api/machines — list all machines for authenticated user// GET /api/machines?machineId=X — single machine detail// GET /api/machines?machineId=X&logs=true&limit=50 — machine + recent logs// POST /api/machines — update machine label { machineId, label }// DELETE /api/machines?machineId=X — soft-delete (set nuked: true)
import { authorize } from "../../backend/authorization.mjs";import { connect } from "../../backend/database.mjs";import { respond } from "../../backend/http.mjs";
const CORS = { "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",};
const ONLINE_THRESHOLD_MS = 90 * 1000; // 90 seconds
async function ensureIndexes(db) { const machines = db.collection("ac-machines"); const logs = db.collection("ac-machine-logs");
await Promise.all([ machines.createIndex({ user: 1, machineId: 1 }, { unique: true }), machines.createIndex({ user: 1, lastSeen: -1 }), // Log indexes are created in machine-logs.mjs but ensure the one we // need for the crash-count aggregation exists here too. logs.createIndex({ machineId: 1, when: -1 }), ]);}
function computeStatus(machine) { if (!machine.lastSeen) return "offline"; const age = Date.now() - new Date(machine.lastSeen).getTime(); if (age > ONLINE_THRESHOLD_MS) return "offline"; return machine.status || "online";}
export async function handler(event) { // ── Preflight ────────────────────────────────────────────────────── if (event.httpMethod === "OPTIONS") { return respond(204, "", CORS); }
// ── Auth ─────────────────────────────────────────────────────────── const authHeader = event.headers.authorization || event.headers.Authorization; const user = await authorize({ authorization: authHeader }); if (!user || !user.sub) { return respond(401, { success: false, error: "Unauthorized" }, CORS); }
const database = await connect();
try { const db = database.db; const machines = db.collection("ac-machines");
// Ensure indexes (idempotent, fast on subsequent calls) await ensureIndexes(db);
const params = event.queryStringParameters || {};
// ── GET ──────────────────────────────────────────────────────── if (event.httpMethod === "GET") { const { machineId, logs: wantLogs, limit: rawLimit } = params;
// Single machine detail if (machineId) { const machine = await machines.findOne({ user: user.sub, machineId, nuked: { $ne: true }, });
if (!machine) { return respond( 404, { success: false, error: "Machine not found" }, CORS, ); }
machine.status = computeStatus(machine);
let recentLogs = undefined; if (wantLogs === "true") { const logLimit = Math.min( 200, Math.max(1, Number(rawLimit) || 50), ); const logsCol = db.collection("ac-machine-logs"); recentLogs = await logsCol .find({ machineId, user: user.sub }) .sort({ when: -1 }) .limit(logLimit) .toArray(); }
return respond( 200, { success: true, machine, ...(recentLogs ? { logs: recentLogs } : {}) }, CORS, ); }
// List all machines for user const allMachines = await machines .find({ user: user.sub, nuked: { $ne: true } }) .sort({ lastSeen: -1 }) .toArray();
// Compute live status for each machine for (const m of allMachines) { m.status = computeStatus(m); }
// Aggregate recent crash counts (last 24h) per machine const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000); const machineIds = allMachines.map((m) => m.machineId);
let crashCounts = {}; if (machineIds.length > 0) { const logsCol = db.collection("ac-machine-logs"); const crashAgg = await logsCol .aggregate([ { $match: { machineId: { $in: machineIds }, user: user.sub, type: "crash", when: { $gte: twentyFourHoursAgo }, }, }, { $group: { _id: "$machineId", count: { $sum: 1 }, }, }, ]) .toArray();
for (const entry of crashAgg) { crashCounts[entry._id] = entry.count; } }
// Attach crash counts for (const m of allMachines) { m.recentCrashes = crashCounts[m.machineId] || 0; }
return respond(200, { success: true, machines: allMachines }, CORS); }
// ── POST — update machine label ──────────────────────────────── if (event.httpMethod === "POST") { let body; try { body = JSON.parse(event.body || "{}"); } catch { return respond( 400, { success: false, error: "Invalid JSON body" }, CORS, ); }
const { machineId, label } = body || {}; if (!machineId || typeof machineId !== "string") { return respond( 400, { success: false, error: "Missing machineId" }, CORS, ); } if (label !== undefined && typeof label !== "string") { return respond( 400, { success: false, error: "label must be a string" }, CORS, ); }
const now = new Date(); const result = await machines.updateOne( { user: user.sub, machineId, nuked: { $ne: true } }, { $set: { label: label || null, updatedAt: now, }, }, );
if (result.matchedCount === 0) { return respond( 404, { success: false, error: "Machine not found" }, CORS, ); }
return respond(200, { success: true }, CORS); }
// ── DELETE — soft-delete a machine ───────────────────────────── if (event.httpMethod === "DELETE") { const { machineId } = params; if (!machineId) { return respond( 400, { success: false, error: "Missing machineId query parameter" }, CORS, ); }
const now = new Date(); const result = await machines.updateOne( { user: user.sub, machineId, nuked: { $ne: true } }, { $set: { nuked: true, updatedAt: now, }, }, );
if (result.matchedCount === 0) { return respond( 404, { success: false, error: "Machine not found" }, CORS, ); }
return respond(200, { success: true }, CORS); }
// ── Unsupported method ───────────────────────────────────────── return respond(405, { success: false, error: "Method not allowed" }, CORS); } catch (err) { return respond(500, { success: false, error: err.message }, CORS); } finally { await database.disconnect(); }}