Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193#!/usr/bin/env bun
import path from "node:path"
const args = process.argv.slice(2)const usage = "Usage: bun run script/upgrade-opentui.ts [--snapshot] <version>"
if (args.includes("--help") || args.includes("-h")) { console.log(usage) process.exit(0)}
const snapshotArg = args.find((arg) => arg.startsWith("--snapshot="))const snapshot = args.includes("--snapshot") || snapshotArg !== undefinedconst unknown = args.find((arg) => arg.startsWith("-") && arg !== "--snapshot" && !arg.startsWith("--snapshot="))if (unknown) { console.error(`Unknown option: ${unknown}`) console.error(usage) process.exit(1)}
const positional = args.filter((arg) => arg !== "--snapshot" && !arg.startsWith("--snapshot="))const raw = snapshotArg?.slice("--snapshot=".length) || positional[0]if (!raw || positional.length > (snapshotArg ? 0 : 1)) { console.error(usage) process.exit(1)}
if (snapshotArg === "--snapshot=") { console.error("Missing snapshot version") console.error(usage) process.exit(1)}
const ver = raw.replace(/^v/, "")const root = path.resolve(import.meta.dir, "..")const lockfile = path.join(root, "bun.lock")const skip = new Set([".git", ".opencode", ".turbo", "dist", "node_modules"])const keys = ["@opentui/core", "@opentui/keymap", "@opentui/solid"] as const
const files = (await Array.fromAsync(new Bun.Glob("**/package.json").scan({ cwd: root }))).filter( (file) => !file.split("/").some((part) => skip.has(part)),)
const setVersion = (cur: string, kind: "dep" | "peer") => { if (cur === "catalog:" || cur.startsWith("workspace:")) return cur if (snapshot) return ver if (kind === "peer") return `>=${ver}` if (cur.startsWith(">=")) return `>=${ver}` if (cur.startsWith("^")) return `^${ver}` if (cur.startsWith("~")) return `~${ver}` return ver}
const editDeps = (obj: unknown, kind: "dep" | "peer") => { if (!obj || typeof obj !== "object") return false const map = obj as Record<string, unknown> return keys .map((key) => { const cur = map[key] if (typeof cur !== "string") return false const next = setVersion(cur, kind) if (next === cur) return false map[key] = next return true }) .some(Boolean)}
const editCatalog = (obj: unknown) => { if (!obj || typeof obj !== "object") return false const map = obj as Record<string, unknown> return keys .map((key) => { const cur = map[key] if (typeof cur !== "string" || cur === ver) return false map[key] = ver return true }) .some(Boolean)}
const editOverrides = (obj: unknown) => { if (!obj || typeof obj !== "object") return false const map = obj as Record<string, unknown> return keys .map((key) => { const cur = map[key] if (typeof cur !== "string") return false const next = snapshot ? ver : "catalog:" if (next === cur) return false map[key] = next return true }) .some(Boolean)}
const out = ( await Promise.all( files.map(async (rel) => { const file = path.join(root, rel) const txt = await Bun.file(file).text() const json = JSON.parse(txt) const hit = [ editCatalog(json.workspaces?.catalog), editOverrides(json.overrides), editDeps(json.dependencies, "dep"), editDeps(json.devDependencies, "dep"), editDeps(json.peerDependencies, "peer"), ].some(Boolean) if (!hit) return null await Bun.write(file, `${JSON.stringify(json, null, 2)}\n`) return rel }), )).filter((item): item is string => item !== null)
if (out.length === 0) { console.log(`No opentui manifest updates needed for ${ver}`)}
if (out.length > 0) { console.log(`Updated opentui${snapshot ? " snapshot" : ""} to ${ver} in:`) for (const file of out) { console.log(`- ${file}`) }}
console.log("Running bun install to update bun.lock...")const install = Bun.spawn([process.execPath, "install"], { cwd: root, stdout: "inherit", stderr: "inherit",})const installCode = await install.exitedif (installCode !== 0) process.exit(installCode)
const fixed = await fixKnownLockfileIssues()if (fixed.length > 0) { console.log("Removed stale opentui-spinner peer lockfile entries:") for (const item of fixed) { console.log(`- ${item}`) }}
const stale = await findStaleLockfileEntries()if (stale.length > 0) { console.error(`bun.lock still contains stale opentui versions after upgrading to ${ver}:`) for (const item of stale) { console.error(`- ${item.entry}: ${item.pkg}@${item.version}`) } process.exit(1)}
console.log("bun.lock opentui versions are consistent")
async function fixKnownLockfileIssues() { const txt = await Bun.file(lockfile).text() const stale = findStaleLockfileEntriesInText(txt) if (stale.length === 0) return [] if (stale.some((item) => !item.entry.startsWith("opentui-spinner/@opentui/"))) return []
const removed = txt .split("\n") .map((line) => line.match(/^ "(opentui-spinner\/@opentui\/[^\"]+)": /)?.[1]) .filter((item): item is string => item !== undefined)
if (removed.length === 0) return []
await Bun.write( lockfile, txt .split("\n") .filter((line) => !line.match(/^ "opentui-spinner\/@opentui\//)) .join("\n"), ) return removed}
async function findStaleLockfileEntries() { return findStaleLockfileEntriesInText(await Bun.file(lockfile).text())}
function findStaleLockfileEntriesInText(txt: string) { return Array.from(txt.matchAll(/^ "([^"]+)": \["(@opentui\/(?:core(?:-[^@"]+)?|keymap|solid))@([^"]+)"/gm)) .map((match) => ({ entry: match[1]!, pkg: match[2]!, version: match[3]!, })) .filter((item) => item.version !== ver)}