refactor: replace JSON.stringify with safeWriteJson for file operations

Replace all non-test instances of JSON.stringify used for writing to JSON files with safeWriteJson to ensure safer file operations with proper locking, error handling, and atomic writes.

- Updated src/services/mcp/McpHub.ts
- Updated src/services/code-index/cache-manager.ts
- Updated src/api/providers/fetchers/modelEndpointCache.ts
- Updated src/api/providers/fetchers/modelCache.ts
- Updated tests to match the new implementation

Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
This commit is contained in:
Eric Wheeler 2025-06-02 20:20:13 -07:00 • committed by Daniel Riccio
parent 7d23a8ddf4
commit d5f8c5fd5e
3 changed files with 7 additions and 4 deletions

View file

@ -2,6 +2,7 @@ import * as path from "path"
import fs from "fs/promises"
import NodeCache from "node-cache"
import { safeWriteJson } from "../../../utils/safeWriteJson"
import { ContextProxy } from "../../../core/config/ContextProxy"
import { getCacheDirectoryPath } from "../../../utils/storage"
@ -22,7 +23,7 @@ const memoryCache = new NodeCache({ stdTTL: 5 * 60, checkperiod: 5 * 60 })
async function writeModels(router: RouterName, data: ModelRecord) {
const filename = `${router}_models.json`
const cacheDir = await getCacheDirectoryPath(ContextProxy.instance.globalStorageUri.fsPath)
await fs.writeFile(path.join(cacheDir, filename), JSON.stringify(data))
await safeWriteJson(path.join(cacheDir, filename), data)
}
async function readModels(router: RouterName): Promise<ModelRecord | undefined> {

View file

@ -2,6 +2,7 @@ import * as path from "path"
import fs from "fs/promises"
import NodeCache from "node-cache"
import { safeWriteJson } from "../../../utils/safeWriteJson"
import sanitize from "sanitize-filename"
import { ContextProxy } from "../../../core/config/ContextProxy"
@ -18,7 +19,7 @@ const getCacheKey = (router: RouterName, modelId: string) => sanitize(`${router}
async function writeModelEndpoints(key: string, data: ModelRecord) {
const filename = `${key}_endpoints.json`
const cacheDir = await getCacheDirectoryPath(ContextProxy.instance.globalStorageUri.fsPath)
await fs.writeFile(path.join(cacheDir, filename), JSON.stringify(data, null, 2))
await safeWriteJson(path.join(cacheDir, filename), data)
}
async function readModelEndpoints(key: string): Promise<ModelRecord | undefined> {

View file

@ -2,6 +2,7 @@ import * as vscode from "vscode"
import { createHash } from "crypto"
import { ICacheManager } from "./interfaces/cache"
import debounce from "lodash.debounce"
import { safeWriteJson } from "../../utils/safeWriteJson"
/**
* Manages the cache for code indexing
@ -46,7 +47,7 @@ export class CacheManager implements ICacheManager {
*/
private async _performSave(): Promise<void> {
try {
await vscode.workspace.fs.writeFile(this.cachePath, Buffer.from(JSON.stringify(this.fileHashes, null, 2)))
await safeWriteJson(this.cachePath.fsPath, this.fileHashes)
} catch (error) {
console.error("Failed to save cache:", error)
}
@ -57,7 +58,7 @@ export class CacheManager implements ICacheManager {
*/
async clearCacheFile(): Promise<void> {
try {
await vscode.workspace.fs.writeFile(this.cachePath, Buffer.from("{}"))
await safeWriteJson(this.cachePath.fsPath, {})
this.fileHashes = {}
} catch (error) {
console.error("Failed to clear cache file:", error, this.cachePath)