86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import { afterEach, expect, test } from "bun:test"
|
|
import { Hono } from "hono"
|
|
import { existsSync } from "node:fs"
|
|
import path from "node:path"
|
|
import { pathToFileURL } from "node:url"
|
|
import { bootstrap as cliBootstrap } from "../../src/cli/bootstrap"
|
|
import { Instance } from "../../src/project/instance"
|
|
import { WithInstance } from "../../src/project/with-instance"
|
|
import { InstanceRuntime } from "../../src/project/instance-runtime"
|
|
import { InstanceMiddleware } from "../../src/server/routes/instance/middleware"
|
|
import { disposeAllInstances, tmpdir } from "../fixture/fixture"
|
|
|
|
// These regressions cover the legacy instance-loading paths fixed by PRs
|
|
// #25389 and #25449. The plugin config hook writes a marker file, and the test
|
|
// bodies deliberately avoid touching Plugin or config directly. The marker only
|
|
// exists if InstanceBootstrap ran at the instance boundary.
|
|
|
|
afterEach(async () => {
|
|
await disposeAllInstances()
|
|
})
|
|
|
|
async function bootstrapFixture() {
|
|
return tmpdir({
|
|
init: async (dir) => {
|
|
const marker = path.join(dir, "config-hook-fired")
|
|
const pluginFile = path.join(dir, "plugin.ts")
|
|
await Bun.write(
|
|
pluginFile,
|
|
[
|
|
`const MARKER = ${JSON.stringify(marker)}`,
|
|
"export default async () => ({",
|
|
" config: async () => {",
|
|
' await Bun.write(MARKER, "ran")',
|
|
" },",
|
|
"})",
|
|
"",
|
|
].join("\n"),
|
|
)
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
plugin: [pathToFileURL(pluginFile).href],
|
|
}),
|
|
)
|
|
return marker
|
|
},
|
|
})
|
|
}
|
|
|
|
test("Instance.provide runs InstanceBootstrap before fn (boundary invariant)", async () => {
|
|
await using tmp = await bootstrapFixture()
|
|
|
|
await WithInstance.provide({
|
|
directory: tmp.path,
|
|
fn: async () => "ok",
|
|
})
|
|
|
|
expect(existsSync(tmp.extra)).toBe(true)
|
|
})
|
|
|
|
test("CLI bootstrap runs InstanceBootstrap before callback", async () => {
|
|
await using tmp = await bootstrapFixture()
|
|
|
|
await cliBootstrap(tmp.path, async () => "ok")
|
|
|
|
expect(existsSync(tmp.extra)).toBe(true)
|
|
})
|
|
|
|
test("legacy Hono instance middleware runs InstanceBootstrap before next handler", async () => {
|
|
await using tmp = await bootstrapFixture()
|
|
const app = new Hono().use(InstanceMiddleware()).get("/probe", (c) => c.text("ok"))
|
|
|
|
const response = await app.request("/probe", { headers: { "x-opencode-directory": tmp.path } })
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(existsSync(tmp.extra)).toBe(true)
|
|
})
|
|
|
|
test("InstanceRuntime.reloadInstance runs InstanceBootstrap", async () => {
|
|
await using tmp = await bootstrapFixture()
|
|
|
|
await InstanceRuntime.reloadInstance({ directory: tmp.path })
|
|
|
|
expect(existsSync(tmp.extra)).toBe(true)
|
|
})
|