Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111// stack/refresh.mjs — keep stack knowledge current. Read-only against DO + npm.//// node --env-file=<vault>/devcontainer.env stack/refresh.mjs// npm run stack:refresh (wires the env file)//// Pulls real DigitalOcean spend + inventory and the outdated-dependency set for// the deployed projects, writes a dated snapshot, and prints DELTAS vs the last// run — the actual nightly signal (spend moved, a droplet appeared, a new major// bump landed). Does NOT touch git or the poster; the poster is a curated// artifact you rebuild when folding fresh numbers in. Never prints secrets.
import { readFileSync, writeFileSync, readdirSync, mkdirSync, existsSync } from "fs";import { execFileSync } from "child_process";import { join, dirname } from "path";import { fileURLToPath } from "url";
const HERE = dirname(fileURLToPath(import.meta.url));const SNAPDIR = join(HERE, "snapshots");const ROOT = join(HERE, "..");if (!existsSync(SNAPDIR)) mkdirSync(SNAPDIR, { recursive: true });
const token = process.env.DIGITALOCEAN_ACCESS_TOKEN || process.env.DO_TOKEN;if (!token) { console.error("no DO token in env — run via `npm run stack:refresh` or --env-file the vault"); process.exit(2); }
const doApi = async (p) => { const r = await fetch(`https://api.digitalocean.com/v2${p}`, { headers: { Authorization: `Bearer ${token}` } }); return r.ok ? r.json() : { __err: `${r.status}` };};
// ---- DigitalOcean ----const bal = await doApi("/customers/my/balance");const dro = await doApi("/droplets?per_page=100");const dbs = await doApi("/databases");
const droplets = (dro.droplets || []).map((d) => ({ name: d.name, size: d.size_slug, price: d.size?.price_monthly, region: d.region?.slug,})).sort((a, b) => b.price - a.price);const dropletTotal = droplets.reduce((s, d) => s + (d.price || 0), 0);const databases = (dbs.databases || []).map((d) => ({ name: d.name, engine: `${d.engine}/${d.version}`, size: d.size, nodes: d.num_nodes }));
// ---- outdated deps (network; the deployed node projects) ----const ncu = (dir) => { try { const out = execFileSync("npx", ["--yes", "npm-check-updates", "--jsonUpgraded", "--packageFile", join(ROOT, dir, "package.json")], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 120000 }); return JSON.parse(out || "{}"); } catch { return { __err: "ncu failed" }; }};const outdated = { system: ncu("system"), "session-server": ncu("session-server") };
// ---- assemble snapshot ----const now = new Date();const stamp = now.toISOString();const day = stamp.slice(0, 10);const snap = { stamp, do: { monthToDate: bal.month_to_date_usage ?? null, balance: bal.account_balance ?? null, dropletTotalMonthly: dropletTotal, droplets, databases, }, outdated: { system: Object.keys(outdated.system).filter((k) => k !== "__err"), "session-server": Object.keys(outdated["session-server"]).filter((k) => k !== "__err"), },};
// ---- delta vs previous snapshot ----const prev = readdirSync(SNAPDIR).filter((f) => f.endsWith(".json")).sort().pop();const before = prev ? JSON.parse(readFileSync(join(SNAPDIR, prev), "utf8")) : null;const deltas = [];if (before) { const dSpend = (snap.do.dropletTotalMonthly - before.do.dropletTotalMonthly); if (dSpend) deltas.push(`droplet run-rate ${dSpend > 0 ? "+" : ""}$${dSpend}/mo (now $${dropletTotal}/mo)`); const names = (x) => new Set(x.do.droplets.map((d) => d.name)); const nowN = names(snap), oldN = names(before); for (const n of nowN) if (!oldN.has(n)) deltas.push(`NEW droplet: ${n}`); for (const n of oldN) if (!nowN.has(n)) deltas.push(`REMOVED droplet: ${n}`); for (const proj of ["system", "session-server"]) { const nw = new Set(snap.outdated[proj]), od = new Set(before.outdated[proj] || []); for (const p of nw) if (!od.has(p)) deltas.push(`${proj}: newly outdated — ${p}`); }}
writeFileSync(join(SNAPDIR, `${day}.json`), JSON.stringify(snap, null, 2));
// ---- human-readable latest ----const md = `# Stack refresh — ${day}
_Auto-generated by stack/refresh.mjs. Read-only pull of DigitalOcean spend + npm outdated._
## DigitalOcean spend- month-to-date: **$${snap.do.monthToDate}** · droplet run-rate: **$${dropletTotal}/mo** · balance: $${snap.do.balance}- droplets (${droplets.length}):${droplets.map((d) => ` - ${d.name} — ${d.size} — $${d.price}/mo (${d.region})`).join("\n")}- managed dbs: ${databases.map((d) => `${d.name} (${d.engine}, ${d.size}×${d.nodes})`).join("; ") || "none"}
## Outdated (majors+ available)- system: ${snap.outdated.system.length} packages- session-server: ${snap.outdated["session-server"].length} packages
## Changes since last run${before ? ` (${prev.replace(".json", "")})` : ""}${deltas.length ? deltas.map((d) => `- ${d}`).join("\n") : (before ? "- no changes" : "- (first snapshot — no prior to compare)")}`;writeFileSync(join(HERE, "refresh-latest.md"), md);
console.log(md);console.log(`\nsnapshot: stack/snapshots/${day}.json`);if (deltas.length) console.log(`\n⚠️ ${deltas.length} change(s) since last run — see above`);