From fb3ceb0da4e2cd636013c2c36a9c0016c01aa47f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 18 Aug 2025 16:29:45 -0600 Subject: Read and write files through Zed (#6169) Co-authored-by: Agus Zubiaga --- .../core/src/services/fileSystemService.test.ts | 59 ++++++++++++++++++++++ packages/core/src/services/fileSystemService.ts | 41 +++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 packages/core/src/services/fileSystemService.test.ts create mode 100644 packages/core/src/services/fileSystemService.ts (limited to 'packages/core/src/services') diff --git a/packages/core/src/services/fileSystemService.test.ts b/packages/core/src/services/fileSystemService.test.ts new file mode 100644 index 00000000..c61ec066 --- /dev/null +++ b/packages/core/src/services/fileSystemService.test.ts @@ -0,0 +1,59 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import fs from 'fs/promises'; +import { StandardFileSystemService } from './fileSystemService.js'; + +vi.mock('fs/promises'); + +describe('StandardFileSystemService', () => { + let fileSystem: StandardFileSystemService; + + beforeEach(() => { + vi.resetAllMocks(); + fileSystem = new StandardFileSystemService(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + describe('readTextFile', () => { + it('should read file content using fs', async () => { + const testContent = 'Hello, World!'; + vi.mocked(fs.readFile).mockResolvedValue(testContent); + + const result = await fileSystem.readTextFile('/test/file.txt'); + + expect(fs.readFile).toHaveBeenCalledWith('/test/file.txt', 'utf-8'); + expect(result).toBe(testContent); + }); + + it('should propagate fs.readFile errors', async () => { + const error = new Error('ENOENT: File not found'); + vi.mocked(fs.readFile).mockRejectedValue(error); + + await expect(fileSystem.readTextFile('/test/file.txt')).rejects.toThrow( + 'ENOENT: File not found', + ); + }); + }); + + describe('writeTextFile', () => { + it('should write file content using fs', async () => { + vi.mocked(fs.writeFile).mockResolvedValue(); + + await fileSystem.writeTextFile('/test/file.txt', 'Hello, World!'); + + expect(fs.writeFile).toHaveBeenCalledWith( + '/test/file.txt', + 'Hello, World!', + 'utf-8', + ); + }); + }); +}); diff --git a/packages/core/src/services/fileSystemService.ts b/packages/core/src/services/fileSystemService.ts new file mode 100644 index 00000000..e2f30cf4 --- /dev/null +++ b/packages/core/src/services/fileSystemService.ts @@ -0,0 +1,41 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import fs from 'fs/promises'; + +/** + * Interface for file system operations that may be delegated to different implementations + */ +export interface FileSystemService { + /** + * Read text content from a file + * + * @param filePath - The path to the file to read + * @returns The file content as a string + */ + readTextFile(filePath: string): Promise; + + /** + * Write text content to a file + * + * @param filePath - The path to the file to write + * @param content - The content to write + */ + writeTextFile(filePath: string, content: string): Promise; +} + +/** + * Standard file system implementation + */ +export class StandardFileSystemService implements FileSystemService { + async readTextFile(filePath: string): Promise { + return fs.readFile(filePath, 'utf-8'); + } + + async writeTextFile(filePath: string, content: string): Promise { + await fs.writeFile(filePath, content, 'utf-8'); + } +} -- cgit v1.2.3