Merge pull request #239 from mvanhorn/osc/125-fix-install-config-overwrite
fix(install): merge config instead of overwriting on opencode target
This commit is contained in:
@@ -18,8 +18,8 @@ export async function mergeJsonConfigAtKey(options: {
|
|||||||
const merged = {
|
const merged = {
|
||||||
...existing,
|
...existing,
|
||||||
[key]: {
|
[key]: {
|
||||||
...existingEntries,
|
|
||||||
...incoming,
|
...incoming,
|
||||||
|
...existingEntries, // existing user entries win on conflict
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,12 +58,16 @@ export async function writeOpenCodeBundle(outputRoot: string, bundle: OpenCodeBu
|
|||||||
const openCodePaths = resolveOpenCodePaths(outputRoot)
|
const openCodePaths = resolveOpenCodePaths(outputRoot)
|
||||||
await ensureDir(openCodePaths.root)
|
await ensureDir(openCodePaths.root)
|
||||||
|
|
||||||
|
const hadExistingConfig = await pathExists(openCodePaths.configPath)
|
||||||
const backupPath = await backupFile(openCodePaths.configPath)
|
const backupPath = await backupFile(openCodePaths.configPath)
|
||||||
if (backupPath) {
|
if (backupPath) {
|
||||||
console.log(`Backed up existing config to ${backupPath}`)
|
console.log(`Backed up existing config to ${backupPath}`)
|
||||||
}
|
}
|
||||||
const merged = await mergeOpenCodeConfig(openCodePaths.configPath, bundle.config)
|
const merged = await mergeOpenCodeConfig(openCodePaths.configPath, bundle.config)
|
||||||
await writeJson(openCodePaths.configPath, merged)
|
await writeJson(openCodePaths.configPath, merged)
|
||||||
|
if (hadExistingConfig) {
|
||||||
|
console.log("Merged plugin config into existing opencode.json (user settings preserved)")
|
||||||
|
}
|
||||||
|
|
||||||
const agentsDir = openCodePaths.agentsDir
|
const agentsDir = openCodePaths.agentsDir
|
||||||
for (const agent of bundle.agents) {
|
for (const agent of bundle.agents) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { promises as fs } from "fs"
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import os from "os"
|
import os from "os"
|
||||||
import { writeOpenCodeBundle } from "../src/targets/opencode"
|
import { writeOpenCodeBundle } from "../src/targets/opencode"
|
||||||
|
import { mergeJsonConfigAtKey } from "../src/sync/json-config"
|
||||||
import type { OpenCodeBundle } from "../src/types/opencode"
|
import type { OpenCodeBundle } from "../src/types/opencode"
|
||||||
|
|
||||||
async function exists(filePath: string): Promise<boolean> {
|
async function exists(filePath: string): Promise<boolean> {
|
||||||
@@ -254,3 +255,38 @@ describe("writeOpenCodeBundle", () => {
|
|||||||
expect(backupContent).toBe("old content\n")
|
expect(backupContent).toBe("old content\n")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("mergeJsonConfigAtKey", () => {
|
||||||
|
test("preserves existing user entries on conflict", async () => {
|
||||||
|
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "json-merge-"))
|
||||||
|
const configPath = path.join(tempDir, "opencode.json")
|
||||||
|
|
||||||
|
// User has an existing MCP server config
|
||||||
|
const existingConfig = {
|
||||||
|
model: "my-model",
|
||||||
|
mcp: {
|
||||||
|
"user-server": { type: "local", command: ["uvx", "user-srv"] },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
await fs.writeFile(configPath, JSON.stringify(existingConfig, null, 2))
|
||||||
|
|
||||||
|
// Plugin tries to add its own server and override user-server
|
||||||
|
await mergeJsonConfigAtKey({
|
||||||
|
configPath,
|
||||||
|
key: "mcp",
|
||||||
|
incoming: {
|
||||||
|
"plugin-server": { type: "local", command: ["uvx", "plugin-srv"] },
|
||||||
|
"user-server": { type: "local", command: ["uvx", "plugin-override"] },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const merged = JSON.parse(await fs.readFile(configPath, "utf8"))
|
||||||
|
|
||||||
|
// User's top-level keys preserved
|
||||||
|
expect(merged.model).toBe("my-model")
|
||||||
|
// Plugin server added
|
||||||
|
expect(merged.mcp["plugin-server"]).toBeDefined()
|
||||||
|
// User's server NOT overwritten by plugin
|
||||||
|
expect(merged.mcp["user-server"].command[1]).toBe("user-srv")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user