Skip to content

Commit 45f0050

Browse files
committed
core: add db command for database inspection and querying
1 parent b5c8bd3 commit 45f0050

3 files changed

Lines changed: 71 additions & 0 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { Argv } from "yargs"
2+
import { spawn } from "child_process"
3+
import { Database } from "../../storage/db"
4+
import { Database as BunDatabase } from "bun:sqlite"
5+
import { UI } from "../ui"
6+
import { cmd } from "./cmd"
7+
8+
const QueryCommand = cmd({
9+
command: "$0 [query]",
10+
describe: "open an interactive sqlite3 shell or run a query",
11+
builder: (yargs: Argv) => {
12+
return yargs
13+
.positional("query", {
14+
type: "string",
15+
describe: "SQL query to execute",
16+
})
17+
.option("format", {
18+
type: "string",
19+
choices: ["json", "tsv"],
20+
default: "tsv",
21+
describe: "Output format",
22+
})
23+
},
24+
handler: async (args: { query?: string; format: string }) => {
25+
const query = args.query as string | undefined
26+
if (query) {
27+
const db = new BunDatabase(Database.Path, { readonly: true })
28+
try {
29+
const result = db.query(query).all() as Record<string, unknown>[]
30+
if (args.format === "json") {
31+
console.log(JSON.stringify(result, null, 2))
32+
} else if (result.length > 0) {
33+
const keys = Object.keys(result[0])
34+
console.log(keys.join("\t"))
35+
for (const row of result) {
36+
console.log(keys.map((k) => row[k]).join("\t"))
37+
}
38+
}
39+
} catch (err) {
40+
UI.error(err instanceof Error ? err.message : String(err))
41+
process.exit(1)
42+
}
43+
db.close()
44+
return
45+
}
46+
const child = spawn("sqlite3", [Database.Path], {
47+
stdio: "inherit",
48+
})
49+
await new Promise((resolve) => child.on("close", resolve))
50+
},
51+
})
52+
53+
const PathCommand = cmd({
54+
command: "path",
55+
describe: "print the database path",
56+
handler: () => {
57+
console.log(Database.Path)
58+
},
59+
})
60+
61+
export const DbCommand = cmd({
62+
command: "db",
63+
describe: "database tools",
64+
builder: (yargs: Argv) => {
65+
return yargs.command(QueryCommand).command(PathCommand).demandCommand()
66+
},
67+
handler: () => {},
68+
})

packages/opencode/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { EOL } from "os"
2626
import { WebCommand } from "./cli/cmd/web"
2727
import { PrCommand } from "./cli/cmd/pr"
2828
import { SessionCommand } from "./cli/cmd/session"
29+
import { DbCommand } from "./cli/cmd/db"
2930
import path from "path"
3031
import { Global } from "./global"
3132
import { JsonMigration } from "./storage/json-migration"
@@ -138,6 +139,7 @@ const cli = yargs(hideBin(process.argv))
138139
.command(GithubCommand)
139140
.command(PrCommand)
140141
.command(SessionCommand)
142+
.command(DbCommand)
141143
.fail((msg, err) => {
142144
if (
143145
msg?.startsWith("Unknown argument") ||

packages/opencode/src/storage/db.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const NotFoundError = NamedError.create(
2525
const log = Log.create({ service: "db" })
2626

2727
export namespace Database {
28+
export const Path = path.join(Global.Path.data, "opencode.db")
2829
type Schema = typeof schema
2930
export type Transaction = SQLiteTransaction<"sync", void, Schema>
3031

0 commit comments

Comments
 (0)