Merge branch 'fix/perf-q10' into fix/perf-omo-in-tree
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
import { afterEach, describe, expect, mock, spyOn, test } from "bun:test"
|
||||||
|
import * as fs from "node:fs"
|
||||||
|
import { join } from "node:path"
|
||||||
|
|
||||||
|
describe("detectPluginConfigFile memoization", () => {
|
||||||
|
const testDir = join(__dirname, ".test-detect-plugin-memoization")
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
mock.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns cached result on repeated calls for the same directory", async () => {
|
||||||
|
// given
|
||||||
|
const existsSync = spyOn(fs, "existsSync").mockImplementation((filePath: fs.PathLike) => {
|
||||||
|
return String(filePath).endsWith("oh-my-openagent.jsonc")
|
||||||
|
})
|
||||||
|
const readdirSync = spyOn(fs, "readdirSync").mockImplementation(() => [])
|
||||||
|
spyOn(fs, "readFileSync").mockImplementation(() => "")
|
||||||
|
|
||||||
|
const parserModule = await import(`./jsonc-parser?memoization=${Date.now()}-${Math.random()}`)
|
||||||
|
|
||||||
|
// when
|
||||||
|
const firstResult = parserModule.detectPluginConfigFile(testDir)
|
||||||
|
const callsAfterFirstResult = existsSync.mock.calls.length
|
||||||
|
const secondResult = parserModule.detectPluginConfigFile(testDir)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(firstResult).toEqual(secondResult)
|
||||||
|
expect(existsSync.mock.calls.length).toBe(callsAfterFirstResult)
|
||||||
|
expect(readdirSync).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("clears cached result when requested", async () => {
|
||||||
|
// given
|
||||||
|
const existsSync = spyOn(fs, "existsSync").mockImplementation((filePath: fs.PathLike) => {
|
||||||
|
return String(filePath).endsWith("oh-my-openagent.jsonc")
|
||||||
|
})
|
||||||
|
const readdirSync = spyOn(fs, "readdirSync").mockImplementation(() => [])
|
||||||
|
spyOn(fs, "readFileSync").mockImplementation(() => "")
|
||||||
|
|
||||||
|
const parserModule = await import(`./jsonc-parser?memoization=${Date.now()}-${Math.random()}`)
|
||||||
|
|
||||||
|
parserModule.detectPluginConfigFile(testDir)
|
||||||
|
parserModule.clearPluginConfigFileDetectionCache()
|
||||||
|
const callsAfterClear = existsSync.mock.calls.length
|
||||||
|
|
||||||
|
// when
|
||||||
|
parserModule.detectPluginConfigFile(testDir)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(existsSync.mock.calls.length).toBeGreaterThan(callsAfterClear)
|
||||||
|
expect(readdirSync).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
||||||
import { detectConfigFile, detectPluginConfigFile, parseJsonc, parseJsoncSafe, readJsoncFile } from "./jsonc-parser"
|
import { clearPluginConfigFileDetectionCache, detectConfigFile, detectPluginConfigFile, parseJsonc, parseJsoncSafe, readJsoncFile } from "./jsonc-parser"
|
||||||
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"
|
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"
|
||||||
import { join } from "node:path"
|
import { join } from "node:path"
|
||||||
|
|
||||||
@@ -330,6 +330,14 @@ describe("detectConfigFile", () => {
|
|||||||
describe("detectPluginConfigFile", () => {
|
describe("detectPluginConfigFile", () => {
|
||||||
const testDir = join(__dirname, ".test-detect-plugin")
|
const testDir = join(__dirname, ".test-detect-plugin")
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
clearPluginConfigFileDetectionCache()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
clearPluginConfigFileDetectionCache()
|
||||||
|
})
|
||||||
|
|
||||||
test("prefers oh-my-openagent over oh-my-opencode when both jsonc files exist", () => {
|
test("prefers oh-my-openagent over oh-my-opencode when both jsonc files exist", () => {
|
||||||
// given
|
// given
|
||||||
if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true })
|
if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true })
|
||||||
|
|||||||
+28
-10
@@ -9,6 +9,14 @@ export interface JsoncParseResult<T> {
|
|||||||
errors: Array<{ message: string; offset: number; length: number }>
|
errors: Array<{ message: string; offset: number; length: number }>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DetectPluginConfigResult = {
|
||||||
|
format: "json" | "jsonc" | "none"
|
||||||
|
path: string
|
||||||
|
legacyPath?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const pluginConfigFileDetectionCache = new Map<string, DetectPluginConfigResult>()
|
||||||
|
|
||||||
function stripBom(content: string): string {
|
function stripBom(content: string): string {
|
||||||
return content.charCodeAt(0) === 0xfeff ? content.slice(1) : content
|
return content.charCodeAt(0) === 0xfeff ? content.slice(1) : content
|
||||||
}
|
}
|
||||||
@@ -75,24 +83,34 @@ export function detectConfigFile(basePath: string): {
|
|||||||
return { format: "none", path: jsonPath }
|
return { format: "none", path: jsonPath }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function detectPluginConfigFile(dir: string): {
|
export function clearPluginConfigFileDetectionCache(): void {
|
||||||
format: "json" | "jsonc" | "none"
|
pluginConfigFileDetectionCache.clear()
|
||||||
path: string
|
}
|
||||||
legacyPath?: string
|
|
||||||
} {
|
export function detectPluginConfigFile(dir: string): DetectPluginConfigResult {
|
||||||
|
const cachedResult = pluginConfigFileDetectionCache.get(dir)
|
||||||
|
|
||||||
|
if (cachedResult !== undefined) {
|
||||||
|
return cachedResult
|
||||||
|
}
|
||||||
|
|
||||||
const canonicalResult = detectConfigFile(join(dir, CONFIG_BASENAME))
|
const canonicalResult = detectConfigFile(join(dir, CONFIG_BASENAME))
|
||||||
const legacyResult = detectConfigFile(join(dir, LEGACY_CONFIG_BASENAME))
|
const legacyResult = detectConfigFile(join(dir, LEGACY_CONFIG_BASENAME))
|
||||||
|
|
||||||
|
let detectionResult: DetectPluginConfigResult
|
||||||
|
|
||||||
if (canonicalResult.format !== "none") {
|
if (canonicalResult.format !== "none") {
|
||||||
return {
|
detectionResult = {
|
||||||
...canonicalResult,
|
...canonicalResult,
|
||||||
legacyPath: legacyResult.format !== "none" ? legacyResult.path : undefined,
|
legacyPath: legacyResult.format !== "none" ? legacyResult.path : undefined,
|
||||||
}
|
}
|
||||||
|
} else if (legacyResult.format !== "none") {
|
||||||
|
detectionResult = legacyResult
|
||||||
|
} else {
|
||||||
|
detectionResult = { format: "none", path: join(dir, `${CONFIG_BASENAME}.json`) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (legacyResult.format !== "none") {
|
pluginConfigFileDetectionCache.set(dir, detectionResult)
|
||||||
return legacyResult
|
|
||||||
}
|
|
||||||
|
|
||||||
return { format: "none", path: join(dir, `${CONFIG_BASENAME}.json`) }
|
return detectionResult
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user