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:
@@ -2,12 +2,12 @@ import { describe, expect } from "bun:test"
|
||||
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
||||
import { Effect, Layer } from "effect"
|
||||
import path from "path"
|
||||
import { Server } from "../../src/server/server"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { resetDatabase } from "../fixture/db"
|
||||
import { TestInstance } from "../fixture/fixture"
|
||||
import { markPluginDependenciesReady } from "../fixture/plugin"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { httpApiLayer, request } from "./httpapi-layer"
|
||||
|
||||
void Log.init({ print: false })
|
||||
|
||||
@@ -18,16 +18,12 @@ const testStateLayer = Layer.effectDiscard(
|
||||
),
|
||||
)
|
||||
|
||||
const it = testEffect(Layer.mergeAll(testStateLayer, AppFileSystem.defaultLayer))
|
||||
const it = testEffect(Layer.mergeAll(testStateLayer, AppFileSystem.defaultLayer, httpApiLayer))
|
||||
const projectOptions = { config: { formatter: false, lsp: false } }
|
||||
const providerID = "test-oauth-parity"
|
||||
const oauthURL = "https://example.com/oauth"
|
||||
const oauthInstructions = "Finish OAuth"
|
||||
|
||||
function app() {
|
||||
return Server.Default().app
|
||||
}
|
||||
|
||||
function providerListHasFetch(list: unknown) {
|
||||
if (!Array.isArray(list)) return false
|
||||
return list.some((item: unknown) => {
|
||||
@@ -77,41 +73,34 @@ function hasProviderMutationMarker(input: unknown, key: "all" | "providers", id:
|
||||
}
|
||||
|
||||
function requestAuthorize(input: {
|
||||
app: ReturnType<typeof app>
|
||||
providerID: string
|
||||
method: number
|
||||
headers: HeadersInit
|
||||
inputs?: Record<string, string>
|
||||
}) {
|
||||
return Effect.promise(async () => {
|
||||
const response = await input.app.request(`/provider/${input.providerID}/oauth/authorize`, {
|
||||
return Effect.gen(function* () {
|
||||
const response = yield* request(`/provider/${input.providerID}/oauth/authorize`, {
|
||||
method: "POST",
|
||||
headers: input.headers,
|
||||
body: JSON.stringify({ method: input.method, ...(input.inputs ? { inputs: input.inputs } : {}) }),
|
||||
})
|
||||
return {
|
||||
status: response.status,
|
||||
body: await response.text(),
|
||||
body: yield* response.text,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function requestCallback(input: {
|
||||
app: ReturnType<typeof app>
|
||||
providerID: string
|
||||
method: number
|
||||
headers: HeadersInit
|
||||
code?: string
|
||||
}) {
|
||||
return Effect.promise(async () => {
|
||||
const response = await input.app.request(`/provider/${input.providerID}/oauth/callback`, {
|
||||
function requestCallback(input: { providerID: string; method: number; headers: HeadersInit; code?: string }) {
|
||||
return Effect.gen(function* () {
|
||||
const response = yield* request(`/provider/${input.providerID}/oauth/callback`, {
|
||||
method: "POST",
|
||||
headers: input.headers,
|
||||
body: JSON.stringify({ method: input.method, ...(input.code ? { code: input.code } : {}) }),
|
||||
})
|
||||
return {
|
||||
status: response.status,
|
||||
body: await response.text(),
|
||||
body: yield* response.text,
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -277,15 +266,13 @@ describe("provider HttpApi", () => {
|
||||
it.instance.skip(
|
||||
"returns public v2 provider not found errors",
|
||||
Effect.gen(function* () {
|
||||
const instance = yield* TestInstance
|
||||
const response = yield* Effect.promise(() =>
|
||||
Promise.resolve(
|
||||
app().request("/api/provider/missing", { headers: { "x-opencode-directory": instance.directory } }),
|
||||
),
|
||||
)
|
||||
const directory = (yield* TestInstance).directory
|
||||
const response = yield* request("/api/provider/missing", {
|
||||
headers: { "x-opencode-directory": directory },
|
||||
})
|
||||
|
||||
expect(response.status).toBe(404)
|
||||
expect(yield* Effect.promise(() => response.json())).toEqual({
|
||||
expect(yield* response.json).toEqual({
|
||||
_tag: "ProviderNotFoundError",
|
||||
providerID: "missing",
|
||||
message: "Provider not found: missing",
|
||||
@@ -297,13 +284,9 @@ describe("provider HttpApi", () => {
|
||||
it.instance(
|
||||
"serves OAuth authorize response shapes",
|
||||
Effect.gen(function* () {
|
||||
const instance = yield* TestInstance
|
||||
yield* writeProviderAuthPlugin(instance.directory)
|
||||
const headers = { "x-opencode-directory": instance.directory, "content-type": "application/json" }
|
||||
const server = app()
|
||||
|
||||
const directory = (yield* TestInstance).directory
|
||||
const headers = { "x-opencode-directory": directory, "content-type": "application/json" }
|
||||
const api = yield* requestAuthorize({
|
||||
app: server,
|
||||
providerID,
|
||||
method: 0,
|
||||
headers,
|
||||
@@ -315,7 +298,6 @@ describe("provider HttpApi", () => {
|
||||
expect(api).toEqual({ status: 200, body: "null" })
|
||||
|
||||
const oauth = yield* requestAuthorize({
|
||||
app: server,
|
||||
providerID,
|
||||
method: 1,
|
||||
headers,
|
||||
@@ -326,21 +308,19 @@ describe("provider HttpApi", () => {
|
||||
instructions: oauthInstructions,
|
||||
})
|
||||
}),
|
||||
projectOptions,
|
||||
{ ...projectOptions, init: writeProviderAuthPlugin },
|
||||
30000,
|
||||
)
|
||||
|
||||
it.instance(
|
||||
"returns declared provider auth validation errors",
|
||||
Effect.gen(function* () {
|
||||
const instance = yield* TestInstance
|
||||
yield* writeProviderAuthValidationPlugin(instance.directory)
|
||||
const directory = (yield* TestInstance).directory
|
||||
const response = yield* requestAuthorize({
|
||||
app: app(),
|
||||
providerID: "test-oauth-validation",
|
||||
method: 0,
|
||||
inputs: { token: "nope" },
|
||||
headers: { "x-opencode-directory": instance.directory, "content-type": "application/json" },
|
||||
headers: { "x-opencode-directory": directory, "content-type": "application/json" },
|
||||
})
|
||||
|
||||
expect(response.status).toBe(400)
|
||||
@@ -349,19 +329,18 @@ describe("provider HttpApi", () => {
|
||||
data: { field: "token", message: "Token must be ok" },
|
||||
})
|
||||
}),
|
||||
projectOptions,
|
||||
{ ...projectOptions, init: writeProviderAuthValidationPlugin },
|
||||
30000,
|
||||
)
|
||||
|
||||
it.instance(
|
||||
"returns declared provider auth callback errors",
|
||||
Effect.gen(function* () {
|
||||
const instance = yield* TestInstance
|
||||
const directory = (yield* TestInstance).directory
|
||||
const response = yield* requestCallback({
|
||||
app: app(),
|
||||
providerID,
|
||||
method: 0,
|
||||
headers: { "x-opencode-directory": instance.directory, "content-type": "application/json" },
|
||||
headers: { "x-opencode-directory": directory, "content-type": "application/json" },
|
||||
})
|
||||
|
||||
expect(response.status).toBe(400)
|
||||
@@ -377,54 +356,48 @@ describe("provider HttpApi", () => {
|
||||
it.instance(
|
||||
"serves provider lists when auth loaders add runtime fetch options",
|
||||
Effect.gen(function* () {
|
||||
const instance = yield* TestInstance
|
||||
yield* writeFunctionOptionsPlugin(instance.directory)
|
||||
const directory = (yield* TestInstance).directory
|
||||
yield* setEnvScoped(
|
||||
"OPENCODE_AUTH_CONTENT",
|
||||
JSON.stringify({
|
||||
google: { type: "oauth", refresh: "dummy", access: "dummy", expires: 9999999999999 },
|
||||
}),
|
||||
)
|
||||
const headers = { "x-opencode-directory": instance.directory }
|
||||
const providerResponse = yield* Effect.promise(() => Promise.resolve(app().request("/provider", { headers })))
|
||||
const configResponse = yield* Effect.promise(() =>
|
||||
Promise.resolve(app().request("/config/providers", { headers })),
|
||||
)
|
||||
const headers = { "x-opencode-directory": directory }
|
||||
const providerResponse = yield* request("/provider", { headers })
|
||||
const configResponse = yield* request("/config/providers", { headers })
|
||||
|
||||
expect(providerResponse.status).toBe(200)
|
||||
expect(configResponse.status).toBe(200)
|
||||
|
||||
const providerBody = yield* Effect.promise(() => providerResponse.json())
|
||||
const configBody = yield* Effect.promise(() => configResponse.json())
|
||||
const providerBody = yield* providerResponse.json
|
||||
const configBody = yield* configResponse.json
|
||||
expect(hasProviderWithFetch(providerBody, "all")).toBe(false)
|
||||
expect(hasProviderWithFetch(configBody, "providers")).toBe(false)
|
||||
expect(hasNonZeroModelCost(providerBody, "all", "google")).toBe(true)
|
||||
expect(hasNonZeroModelCost(configBody, "providers", "google")).toBe(true)
|
||||
}),
|
||||
projectOptions,
|
||||
{ ...projectOptions, init: writeFunctionOptionsPlugin },
|
||||
)
|
||||
|
||||
it.instance(
|
||||
"keeps provider.models hook input mutations out of provider state",
|
||||
Effect.gen(function* () {
|
||||
const instance = yield* TestInstance
|
||||
yield* writeProviderModelsMutationPlugin(instance.directory)
|
||||
const directory = (yield* TestInstance).directory
|
||||
|
||||
const headers = { "x-opencode-directory": instance.directory }
|
||||
const providerResponse = yield* Effect.promise(() => Promise.resolve(app().request("/provider", { headers })))
|
||||
const configResponse = yield* Effect.promise(() =>
|
||||
Promise.resolve(app().request("/config/providers", { headers })),
|
||||
)
|
||||
const headers = { "x-opencode-directory": directory }
|
||||
const providerResponse = yield* request("/provider", { headers })
|
||||
const configResponse = yield* request("/config/providers", { headers })
|
||||
|
||||
expect(providerResponse.status).toBe(200)
|
||||
expect(configResponse.status).toBe(200)
|
||||
|
||||
const providerBody = yield* Effect.promise(() => providerResponse.json())
|
||||
const configBody = yield* Effect.promise(() => configResponse.json())
|
||||
const providerBody = yield* providerResponse.json
|
||||
const configBody = yield* configResponse.json
|
||||
expect(hasProviderMutationMarker(providerBody, "all", "google")).toBe(false)
|
||||
expect(hasProviderMutationMarker(configBody, "providers", "google")).toBe(false)
|
||||
expect(hasNonZeroModelCost(providerBody, "all", "google")).toBe(true)
|
||||
}),
|
||||
projectOptions,
|
||||
{ ...projectOptions, init: writeProviderModelsMutationPlugin },
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user