diff --git a/src/config.ts b/src/config.ts index ceb0116..5a8d4c2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -98,11 +98,16 @@ export function normalizeConfig( export async function loadConfig(options: { explicitPath?: string; cwd?: string; -}): Promise<{ config: McpAuditConfig; path?: string }> { +} = {}): Promise<{ config: McpAuditConfig; path?: string }> { const path = options.explicitPath ?? findConfigFile(options.cwd ?? process.cwd()); if (!path) return { config: DEFAULT_CONFIG }; const raw = await readFile(resolve(path), "utf8"); - const parsed = JSON.parse(raw); + let parsed: unknown; + try { + parsed = JSON.parse(raw); + } catch (err) { + throw new Error(`Failed to parse config file ${path}: ${(err as Error).message}`); + } return { config: normalizeConfig(parsed), path }; } diff --git a/test/config.test.ts b/test/config.test.ts index d7f0877..b1b20a2 100644 --- a/test/config.test.ts +++ b/test/config.test.ts @@ -1,5 +1,8 @@ import { describe, it, expect } from "vitest"; -import { normalizeConfig, DEFAULT_CONFIG } from "../src/config.js"; +import { normalizeConfig, loadConfig, DEFAULT_CONFIG } from "../src/config.js"; +import { writeFile, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { tmpdir } from "node:os"; describe("normalizeConfig", () => { it("returns defaults for an empty object", () => { @@ -40,3 +43,18 @@ describe("normalizeConfig", () => { expect(overlaid.failOn).toBe("medium"); }); }); + +describe("loadConfig", () => { + it("wraps JSON syntax errors with the file path", async () => { + const tmpFile = join(tmpdir(), `mcp-audit-test-${Math.random()}.json`); + await writeFile(tmpFile, "{ invalid json ", "utf8"); + try { + await loadConfig({ explicitPath: tmpFile }); + expect.fail("Should have thrown"); + } catch (err) { + expect((err as Error).message).toContain(tmpFile); + } finally { + await rm(tmpFile, { force: true }); + } + }); +});