summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax <[email protected]>2026-02-16 14:05:21 -0500
committerGitHub <[email protected]>2026-02-16 19:05:21 +0000
commitfdad823edc13fbc8fbaf4bf54eae53b1286ee2e9 (patch)
tree7d0f4b52a79f935f46080a5b034d4156daa7083d
parent5cc1d6097e02e2f157b7ae68de9e5df06531b53d (diff)
downloadopencode-fdad823edc13fbc8fbaf4bf54eae53b1286ee2e9.tar.gz
opencode-fdad823edc13fbc8fbaf4bf54eae53b1286ee2e9.zip
feat(cli): add db migrate command for JSON to SQLite migration (#13874)
-rw-r--r--packages/opencode/src/cli/cmd/db.ts52
1 files changed, 51 insertions, 1 deletions
diff --git a/packages/opencode/src/cli/cmd/db.ts b/packages/opencode/src/cli/cmd/db.ts
index 0ade4d3c4..8ca4b9a42 100644
--- a/packages/opencode/src/cli/cmd/db.ts
+++ b/packages/opencode/src/cli/cmd/db.ts
@@ -4,6 +4,8 @@ import { Database } from "../../storage/db"
import { Database as BunDatabase } from "bun:sqlite"
import { UI } from "../ui"
import { cmd } from "./cmd"
+import { JsonMigration } from "../../storage/json-migration"
+import { EOL } from "os"
const QueryCommand = cmd({
command: "$0 [query]",
@@ -58,11 +60,59 @@ const PathCommand = cmd({
},
})
+const MigrateCommand = cmd({
+ command: "migrate",
+ describe: "migrate JSON data to SQLite (merges with existing data)",
+ handler: async () => {
+ const sqlite = new BunDatabase(Database.Path)
+ const tty = process.stderr.isTTY
+ const width = 36
+ const orange = "\x1b[38;5;214m"
+ const muted = "\x1b[0;2m"
+ const reset = "\x1b[0m"
+ let last = -1
+ if (tty) process.stderr.write("\x1b[?25l")
+ try {
+ const stats = await JsonMigration.run(sqlite, {
+ progress: (event) => {
+ const percent = Math.floor((event.current / event.total) * 100)
+ if (percent === last) return
+ last = percent
+ if (tty) {
+ const fill = Math.round((percent / 100) * width)
+ const bar = `${"■".repeat(fill)}${"・".repeat(width - fill)}`
+ process.stderr.write(
+ `\r${orange}${bar} ${percent.toString().padStart(3)}%${reset} ${muted}${event.current}/${event.total}${reset} `,
+ )
+ } else {
+ process.stderr.write(`sqlite-migration:${percent}${EOL}`)
+ }
+ },
+ })
+ if (tty) process.stderr.write("\n")
+ if (tty) process.stderr.write("\x1b[?25h")
+ else process.stderr.write(`sqlite-migration:done${EOL}`)
+ UI.println(
+ `Migration complete: ${stats.projects} projects, ${stats.sessions} sessions, ${stats.messages} messages`,
+ )
+ if (stats.errors.length > 0) {
+ UI.println(`${stats.errors.length} errors occurred during migration`)
+ }
+ } catch (err) {
+ if (tty) process.stderr.write("\x1b[?25h")
+ UI.error(`Migration failed: ${err instanceof Error ? err.message : String(err)}`)
+ process.exit(1)
+ } finally {
+ sqlite.close()
+ }
+ },
+})
+
export const DbCommand = cmd({
command: "db",
describe: "database tools",
builder: (yargs: Argv) => {
- return yargs.command(QueryCommand).command(PathCommand).demandCommand()
+ return yargs.command(QueryCommand).command(PathCommand).command(MigrateCommand).demandCommand()
},
handler: () => {},
})