refactor(core): move database schema ownership (#29068)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
Dax
2026-05-30 21:08:38 -04:00
committed by GitHub
parent 6bcb9cb9bb
commit 7f571d36ea
390 changed files with 11127 additions and 9164 deletions

View File

@@ -1,41 +1,36 @@
import { afterEach, describe, expect } from "bun:test"
import { Deferred, Effect, Fiber, Layer } from "effect"
import { HttpClient, HttpClientResponse } from "effect/unstable/http"
import { eq } from "drizzle-orm"
import { GlobalBus, type GlobalEvent } from "@/bus/global"
import { Server } from "../../src/server/server"
import { ExperimentalPaths } from "../../src/server/routes/instance/httpapi/groups/experimental"
import { Session } from "@/session/session"
import { SessionTable } from "@/session/session.sql"
import { Database } from "@/storage/db"
import { SessionTable } from "@opencode-ai/core/session/sql"
import { Database } from "@opencode-ai/core/database/database"
import { AccountV2 } from "@opencode-ai/core/account"
import { AccountTable } from "@opencode-ai/core/account/sql"
import * as Log from "@opencode-ai/core/util/log"
import { Worktree } from "../../src/worktree"
import { resetDatabase } from "../fixture/db"
import { disposeAllInstances, TestInstance } from "../fixture/fixture"
import { testEffect } from "../lib/effect"
import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
void Log.init({ print: false })
const it = testEffect(Layer.mergeAll(Session.defaultLayer))
const it = testEffect(Layer.mergeAll(Session.defaultLayer, Database.defaultLayer, httpApiLayer))
const testWorktreeMutations = process.platform === "win32" ? it.instance.skip : it.instance
function app() {
return Server.Default().app
}
function request(path: string, directory: string, init: RequestInit = {}) {
return Effect.promise(() => {
const headers = new Headers(init.headers)
headers.set("x-opencode-directory", directory)
return Promise.resolve(app().request(path, { ...init, headers }))
})
return requestInDirectory(path, directory, init)
}
function createSession(input?: Session.CreateInput) {
return Session.use.create(input)
}
function json<T>(response: Response) {
return Effect.promise(() => response.json() as Promise<T>)
function json<T>(response: HttpClientResponse.HttpClientResponse) {
return response.json.pipe(Effect.map((value) => value as T))
}
function waitReady(input: { directory?: string; name?: string }) {
@@ -62,38 +57,50 @@ function waitReady(input: { directory?: string; name?: string }) {
function insertAccount() {
return Effect.acquireRelease(
Effect.sync(() => {
Database.Client()
.$client.prepare(
"INSERT INTO account (id, email, url, access_token, refresh_token, time_created, time_updated) VALUES (?, ?, ?, ?, ?, ?, ?)",
)
.run(
"account-test",
"test@example.com",
"https://console.example.com",
"access",
"refresh",
Date.now(),
Date.now(),
)
Effect.gen(function* () {
const { db } = yield* Database.Service
yield* db
.insert(AccountTable)
.values({
id: AccountV2.ID.make("account-test"),
email: "test@example.com",
url: "https://console.example.com",
access_token: AccountV2.AccessToken.make("access"),
refresh_token: AccountV2.RefreshToken.make("refresh"),
time_created: Date.now(),
time_updated: Date.now(),
})
.run()
.pipe(Effect.orDie)
return "account-test"
}),
(id) =>
Effect.sync(() => {
Database.Client().$client.prepare("DELETE FROM account WHERE id = ?").run(id)
}),
Database.Service.use(({ db }) =>
db
.delete(AccountTable)
.where(eq(AccountTable.id, AccountV2.ID.make(id)))
.run()
.pipe(Effect.orDie),
),
)
}
function setSessionUpdated(session: Session.Info, updated: number) {
return Effect.sync(() => {
Database.use((db) =>
db.update(SessionTable).set({ time_updated: updated }).where(eq(SessionTable.id, session.id)).run(),
)
return Effect.gen(function* () {
const { db } = yield* Database.Service
yield* db
.update(SessionTable)
.set({ time_updated: updated })
.where(eq(SessionTable.id, session.id))
.run()
.pipe(Effect.orDie)
})
}
function withCreatedWorktree(directory: string, use: (info: Worktree.Info) => Effect.Effect<void, unknown, never>) {
function withCreatedWorktree(
directory: string,
use: (info: Worktree.Info) => Effect.Effect<void, unknown, HttpClient.HttpClient>,
) {
const name = "api-test"
const headers = { "content-type": "application/json" }
return Effect.acquireUseRelease(
@@ -242,7 +249,7 @@ describe("experimental HttpApi", () => {
tmp.directory,
)
expect(page.status).toBe(200)
expect(page.headers.get("x-next-cursor")).toBeTruthy()
expect(page.headers["x-next-cursor"]).toBeTruthy()
const body = yield* json<Session.GlobalInfo[]>(page)
expect(body.map((session) => session.id)).toEqual([second.id])