#!/usr/bin/env node import fs from "node:fs"; const BASE = process.env.QB_ARGS_BASE || process.argv[2] || "https://graceful-tiger-715.convex.site"; let pkg; try { pkg = JSON.parse(fs.readFileSync("package.json", "utf8")); } catch { console.log("CHECK_UPDATES_NO_PACKAGE_JSON — run this from the app directory (where package.json lives)."); process.exit(2); } const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) }; let reg; try { reg = await (await fetch(BASE + "/components.json")).json(); } catch (e) { console.log("CHECK_UPDATES_REGISTRY_UNREACHABLE " + (e && e.message || e)); process.exit(3); } // Extract the installed ref from a value like // "https://pkg.pr.new/@convex-dev/auth@ed481f5" -> "ed481f5" // "1.2.3" / "^1.2.3" -> "1.2.3" const refOf = (v) => { const s = String(v); const m = s.match(/@([a-f0-9]{7,40})(?:$|[/?#])/) || s.match(/(\d+\.\d+\.\d+[\w.-]*)/); return m ? m[1] : s; }; const stale = []; for (const [name, entry] of Object.entries(reg.components || {})) { if (!(name in deps)) continue; const installed = refOf(deps[name]); if (installed === entry.current) continue; const rel = (entry.releases || []).find((r) => r.from === installed || installed.startsWith(r.from) || r.from.startsWith(installed)) || (entry.releases || [])[0]; if (!rel || rel.to === installed) continue; stale.push({ name, installed, current: entry.current, ref: entry.ref, peers: entry.peers || {}, breaking: rel.breaking, summary: rel.summary, migration: rel.migration }); } if (!stale.length) { console.log("COMPONENTS_UP_TO_DATE"); process.exit(0); } console.log("COMPONENTS_STALE=" + stale.length); console.log(JSON.stringify(stale, null, 2));