80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import * as fs from "node:fs"
|
|
import * as os from "node:os"
|
|
import * as path from "node:path"
|
|
|
|
import { parseJsoncSafe } from "./jsonc-parser"
|
|
|
|
interface OpencodeConfig {
|
|
plugin?: (string | [string, ...unknown[]])[]
|
|
}
|
|
|
|
const opencodePluginsCache = new Map<string, string[]>()
|
|
|
|
function getWindowsAppdataDir(): string | null {
|
|
return process.env.APPDATA || null
|
|
}
|
|
|
|
function getConfigPaths(directory: string): string[] {
|
|
const crossPlatformDir = path.join(os.homedir(), ".config")
|
|
const paths = [
|
|
path.join(directory, ".opencode", "opencode.json"),
|
|
path.join(directory, ".opencode", "opencode.jsonc"),
|
|
path.join(crossPlatformDir, "opencode", "opencode.json"),
|
|
path.join(crossPlatformDir, "opencode", "opencode.jsonc"),
|
|
]
|
|
|
|
const customConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim()
|
|
if (customConfigDir) {
|
|
const resolvedCustomConfigDir = path.resolve(customConfigDir)
|
|
paths.push(path.join(resolvedCustomConfigDir, "opencode.json"))
|
|
paths.push(path.join(resolvedCustomConfigDir, "opencode.jsonc"))
|
|
}
|
|
|
|
if (process.platform === "win32") {
|
|
const appdataDir = getWindowsAppdataDir()
|
|
if (appdataDir) {
|
|
paths.push(path.join(appdataDir, "opencode", "opencode.json"))
|
|
paths.push(path.join(appdataDir, "opencode", "opencode.jsonc"))
|
|
}
|
|
}
|
|
|
|
return Array.from(new Set(paths))
|
|
}
|
|
|
|
export function loadOpencodePlugins(directory: string): string[] {
|
|
const cachedPluginEntries = opencodePluginsCache.get(directory)
|
|
if (cachedPluginEntries) {
|
|
return cachedPluginEntries
|
|
}
|
|
|
|
const pluginEntries: string[] = []
|
|
const seenPluginEntries = new Set<string>()
|
|
|
|
for (const configPath of getConfigPaths(directory)) {
|
|
try {
|
|
if (!fs.existsSync(configPath)) continue
|
|
|
|
const content = fs.readFileSync(configPath, "utf-8")
|
|
const result = parseJsoncSafe<OpencodeConfig>(content)
|
|
const plugins = result.data?.plugin ?? []
|
|
|
|
for (const plugin of plugins) {
|
|
const entry = typeof plugin === "string" ? plugin : Array.isArray(plugin) ? plugin[0] : null
|
|
if (typeof entry !== "string") continue
|
|
if (seenPluginEntries.has(entry)) continue
|
|
seenPluginEntries.add(entry)
|
|
pluginEntries.push(entry)
|
|
}
|
|
} catch {
|
|
continue
|
|
}
|
|
}
|
|
|
|
opencodePluginsCache.set(directory, pluginEntries)
|
|
return pluginEntries
|
|
}
|
|
|
|
export function clearOpencodePluginsCache(): void {
|
|
opencodePluginsCache.clear()
|
|
}
|