mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-29 21:52:08 +00:00
124 lines
5.4 KiB
TypeScript
124 lines
5.4 KiB
TypeScript
import { NodeServices } from "@effect/platform-node"
|
|
import { Global } from "@opencode-ai/util/global"
|
|
import { expect, test } from "bun:test"
|
|
import { Effect, Exit, FileSystem } from "effect"
|
|
import { Command } from "effect/unstable/cli"
|
|
import path from "node:path"
|
|
import { Commands } from "../src/commands/commands"
|
|
import { ServiceConfig } from "../src/services/service-config"
|
|
import { it } from "../../core/test/lib/effect"
|
|
|
|
it.live("service CORS config persists multiple origins and preserves other settings on set and unset", () =>
|
|
Effect.gen(function* () {
|
|
const fs = yield* FileSystem.FileSystem
|
|
const root = yield* fs.makeTempDirectoryScoped({ prefix: "opencode-cors-" })
|
|
const config = path.join(root, "config")
|
|
const state = path.join(root, "state")
|
|
const file = path.join(config, ServiceConfig.filename())
|
|
const existing = { hostname: "127.0.0.1", port: 4321, password: "test-secret", env: { TEST: "value" } }
|
|
yield* fs.makeDirectory(config)
|
|
yield* fs.makeDirectory(state)
|
|
yield* fs.writeFileString(file, JSON.stringify(existing))
|
|
yield* Effect.gen(function* () {
|
|
expect(yield* ServiceConfig.get("cors")).toBe("[]")
|
|
yield* ServiceConfig.set("cors", " http://192.0.2.10:3001, https://app.example.com ")
|
|
const cors = ["http://192.0.2.10:3001", "https://app.example.com"]
|
|
expect(yield* ServiceConfig.read()).toEqual({ ...existing, cors })
|
|
expect(yield* ServiceConfig.get("cors")).toBe(JSON.stringify(cors, null, 2))
|
|
expect(JSON.parse(yield* ServiceConfig.get())).toEqual({
|
|
hostname: existing.hostname,
|
|
port: existing.port,
|
|
env: existing.env,
|
|
cors,
|
|
})
|
|
expect(JSON.parse(yield* fs.readFileString(file))).toEqual({ ...existing, cors })
|
|
yield* ServiceConfig.set("cors", "https://replacement.example.com")
|
|
expect((yield* ServiceConfig.read()).cors).toEqual(["https://replacement.example.com"])
|
|
yield* ServiceConfig.unset("cors")
|
|
expect(yield* ServiceConfig.get("cors")).toBe("[]")
|
|
expect(JSON.parse(yield* fs.readFileString(file))).toEqual(existing)
|
|
}).pipe(Effect.provideService(Global.Service, Global.make({ config, state })))
|
|
}).pipe(Effect.provide(NodeServices.layer)),
|
|
)
|
|
|
|
it.live("service CORS config rejects empty lists, invalid origins, and extra arguments without changing config", () =>
|
|
Effect.gen(function* () {
|
|
const fs = yield* FileSystem.FileSystem
|
|
const root = yield* fs.makeTempDirectoryScoped({ prefix: "opencode-cors-invalid-" })
|
|
const config = path.join(root, "config")
|
|
const state = path.join(root, "state")
|
|
const file = path.join(config, ServiceConfig.filename())
|
|
const existing = { port: 4321, cors: ["https://app.example.com"] }
|
|
yield* fs.makeDirectory(config)
|
|
yield* fs.makeDirectory(state)
|
|
yield* fs.writeFileString(file, JSON.stringify(existing))
|
|
yield* Effect.gen(function* () {
|
|
yield* Effect.forEach(
|
|
[
|
|
"",
|
|
" ",
|
|
",",
|
|
"https://app.example.com,",
|
|
",https://app.example.com",
|
|
"https://app.example.com,,https://other.example.com",
|
|
"not-a-url",
|
|
"*",
|
|
"null",
|
|
"ftp://app.example.com",
|
|
"https://app.example.com/",
|
|
"https://app.example.com/path",
|
|
"https://app.example.com?query=1",
|
|
"https://app.example.com#fragment",
|
|
"https://user:password@app.example.com",
|
|
],
|
|
(value) =>
|
|
Effect.gen(function* () {
|
|
expect(Exit.isFailure(yield* ServiceConfig.set("cors", value).pipe(Effect.exit))).toBe(true)
|
|
expect(yield* ServiceConfig.read()).toEqual(existing)
|
|
}),
|
|
)
|
|
yield* Effect.forEach(
|
|
[
|
|
ServiceConfig.get("cors", "extra"),
|
|
ServiceConfig.set("cors", "https://app.example.com", "extra"),
|
|
ServiceConfig.unset("cors", "extra"),
|
|
],
|
|
(operation) =>
|
|
Effect.gen(function* () {
|
|
expect(Exit.isFailure(yield* operation.pipe(Effect.exit))).toBe(true)
|
|
}),
|
|
)
|
|
expect(JSON.parse(yield* fs.readFileString(file))).toEqual(existing)
|
|
}).pipe(Effect.provideService(Global.Service, Global.make({ config, state })))
|
|
}).pipe(Effect.provide(NodeServices.layer)),
|
|
)
|
|
|
|
test.each([
|
|
{ args: [], cors: [] },
|
|
{ args: ["--cors", "https://app.example.com"], cors: ["https://app.example.com"] },
|
|
{
|
|
args: ["--service", "--cors", "http://192.0.2.10:3001", "--cors", "https://app.example.com"],
|
|
cors: ["http://192.0.2.10:3001", "https://app.example.com"],
|
|
},
|
|
])("serve parses CORS flags: $args", async ({ args, cors }) => {
|
|
const received: (readonly string[])[] = []
|
|
const command = Commands.commands.serve.spec.pipe(
|
|
Command.withHandler((input) => Effect.sync(() => void received.push(input.cors))),
|
|
)
|
|
await Effect.runPromise(Command.runWith(command, { version: "test" })(args).pipe(Effect.provide(NodeServices.layer)))
|
|
expect(received).toEqual([cors])
|
|
})
|
|
|
|
test.each([{ args: ["--cors"] }, { args: ["--cors", ""] }])(
|
|
"serve rejects a missing or empty CORS flag value: $args",
|
|
async ({ args }) => {
|
|
const command = Commands.commands.serve.spec.pipe(Command.withHandler(() => Effect.void))
|
|
const result = await Effect.runPromise(
|
|
Command.runWith(command, { version: "test", renderErrors: false })(args).pipe(
|
|
Effect.exit,
|
|
Effect.provide(NodeServices.layer),
|
|
),
|
|
)
|
|
expect(Exit.isFailure(result)).toBe(true)
|
|
},
|
|
)
|