Dax Raad 2 месяцев назад
Родитель
Сommit
ecd7f43bd2
1 измененных файлов с 0 добавлено и 331 удалено
  1. 0 331
      packages/opencode/MIGRATION.md

+ 0 - 331
packages/opencode/MIGRATION.md

@@ -1,331 +0,0 @@
-# Migration Guide: Replacing Bun.file with Node.js APIs
-
-**Goal**: Replace all `Bun.file()` and `Bun.write()` calls in the opencode codebase with the `Filesystem` utility module from `src/util/filesystem.ts`. This utility provides Node.js `fs/promises` equivalents optimized for performance.
-
-**What to do**: Pick one unchecked file from the checklist below, migrate it using the Filesystem module, ensure tests pass, open a PR, and check off the file once merged. Repeat until all files are done.
-
-## Migration Process
-
-Each file should be migrated **one at a time** with a separate PR opened for each file. This approach ensures:
-
-- Easier code review and debugging
-- Isolated changes that can be rolled back independently
-- Clear tracking of which files have been migrated
-- Reduced risk of introducing multiple bugs at once
-
-**Workflow:**
-
-1. Pick one unchecked file from the checklist below
-2. Create a new branch for that file
-3. Migrate all `Bun.file()` and related APIs to Node.js equivalents using the Filesystem module
-4. Run tests for the specific file and ensure they pass before pushing
-5. Open a PR specifically for that single file
-6. Once merged, check off the file in the checklist below
-
-## Using the Filesystem Module
-
-Use the `Filesystem` module from `src/util/filesystem.ts` for all file operations:
-
-```typescript
-import { Filesystem } from "./util/filesystem"
-
-// Before: Bun.file().exists()
-const exists = await Bun.file(path).exists()
-// After: Filesystem.exists()
-const exists = await Filesystem.exists(path)
-
-// Before: Bun.file().text()
-const content = await Bun.file(path).text()
-// After: Filesystem.readText()
-const content = await Filesystem.readText(path)
-
-// Before: Bun.file().json()
-const data = await Bun.file(path).json()
-// After: Filesystem.readJson()
-const data = await Filesystem.readJson<Config>(path)
-
-// Before: Bun.file().bytes()
-const bytes = await Bun.file(path).bytes()
-// After: Filesystem.readBytes()
-const buffer = await Filesystem.readBytes(path)
-
-// Before: Bun.file().stat()
-const stats = await Bun.file(path).stat()
-// After: Filesystem.isDir() and size
-const isDir = await Filesystem.isDir(path)
-const size = await Filesystem.size(path)
-
-// Before: Bun.file().size
-const size = Bun.file(path).size
-// After: Filesystem.size()
-const size = await Filesystem.size(path)
-
-// Before: Bun.write()
-await Bun.write(path, content)
-// After: Filesystem.write()
-await Filesystem.write(path, content)
-
-// Before: Bun.write() with JSON
-await Bun.write(path, JSON.stringify(data, null, 2))
-// After: Filesystem.writeJson()
-await Filesystem.writeJson(path, data)
-
-// Before: Bun.file().type
-const mime = Bun.file(path).type
-// After: Filesystem.mimeType()
-const mime = Filesystem.mimeType(path)
-```
-
-## Files Requiring Updates
-
-### Core Utilities
-
-- [ ] `src/util/filesystem.ts` - `exists()` and `isDir()` functions use `Bun.file().stat()`
-- [x] `src/util/log.ts` - Uses `Bun.file()` for log file access
-
-### Tool Implementations
-
-- [x] `src/tool/read.ts` - Uses `Bun.file()` for file type, stat, and bytes
-- [x] `src/tool/write.ts` - Uses `Bun.file().exists()` and `Bun.file().text()`
-- [x] `src/tool/edit.ts` - Uses `Bun.file().exists()`
-- [x] `src/tool/grep.ts` - Uses `Bun.file()`
-- [x] `src/tool/glob.ts` - Uses `Bun.file()` for stats
-- [x] `src/tool/lsp.ts` - Uses `Bun.file().exists()`
-- [x] `src/tool/truncation.ts` - Uses `Bun.write()`
-
-### Storage & Data
-
-- [x] `src/storage/storage.ts` - Multiple uses of `Bun.file().json()` and `Bun.write()`
-- [x] `src/storage/json-migration.ts` - Uses `Bun.file().json()`
-- [x] `src/storage/db.ts` - Uses `Bun.file().size`
-- [x] `src/mcp/auth.ts` - Uses `Bun.file().json()` and `Bun.write()`
-
-### Project Management
-
-- [x] `src/project/project.ts` - Uses `Bun.file().text()` and `Bun.file().stat()`
-
-### Session & Prompts
-
-- [x] `src/session/prompt.ts` - Uses `Bun.file().stat()`, `Bun.file().exists()`, and `Bun.file().text()`
-- [x] `src/session/instruction.ts` - Uses `Bun.file().exists()` and `Bun.file().text()`
-
-### Provider & Models
-
-- [x] `src/provider/models.ts` - Uses `Bun.file()` and `Bun.write()`
-- [x] `src/provider/provider.ts` - Uses `Bun.file().text()`
-
-### Skill Discovery
-
-- [x] `src/skill/discovery.ts` - Uses `Bun.file().exists()` and `Bun.write()`
-
-### LSP
-
-- [x] `src/lsp/client.ts` - Uses `Bun.file()`
-- [x] `src/lsp/server.ts` - Uses `Bun.file().exists()` and `Bun.file().write()`
-
-### Shell & CLI
-
-- [x] `src/shell/shell.ts` - Uses `Bun.file().size`
-- [x] `src/cli/cmd/tui/thread.ts` - Uses `Bun.file().exists()`
-
-### Additional Files Migrated
-
-- [x] `src/acp/agent.ts` - Uses `Bun.file().exists()` and `Bun.file().text()`
-- [x] `src/auth/index.ts` - Uses `Bun.file().json()` and `Bun.write()`
-- [x] `src/bun/index.ts` - Uses `Bun.file().json()` and `Bun.write()`
-- [x] `src/cli/cmd/agent.ts` - Uses `Bun.file().exists()` and `Bun.write()`
-- [x] `src/cli/cmd/github.ts` - Uses `Bun.write()`
-- [x] `src/cli/cmd/import.ts` - Uses `Bun.file().json()`
-- [x] `src/cli/cmd/mcp.ts` - Uses `Bun.file()` and `Bun.write()`
-- [x] `src/cli/cmd/run.ts` - Uses `Bun.file()`
-- [x] `src/cli/cmd/session.ts` - Uses `Bun.file().size`
-- [x] `src/cli/cmd/uninstall.ts` - Uses `Bun.file().text()` and `Bun.write()`
-- [x] `src/cli/cmd/tui/util/clipboard.ts` - Uses `Bun.file().arrayBuffer()`
-- [x] `src/cli/cmd/tui/util/editor.ts` - Uses `Bun.write()` and `Bun.file().text()`
-- [x] `src/config/markdown.ts` - Uses `Bun.file().text()`
-- [x] `src/file/index.ts` - Uses `Bun.file()` for text, exists, arrayBuffer, and mime type
-- [x] `src/file/time.ts` - Uses `Bun.file().stat()`
-- [x] `src/format/formatter.ts` - Uses `Bun.file().json()` and `Bun.file().text()`
-- [x] `src/global/index.ts` - Uses `Bun.file().text()` and `Bun.file().write()`
-
-## Centralized File API Module
-
-The `src/util/filesystem.ts` module provides optimized Node.js equivalents for all Bun.file operations:
-
-```typescript
-import { Filesystem } from "./util/filesystem"
-
-// Migration examples:
-
-// Before: Bun.file().exists()
-const exists = await Bun.file(path).exists()
-// After: Filesystem.exists() (uses fast existsSync internally)
-const exists = await Filesystem.exists(path)
-
-// Before: Bun.file().text()
-const content = await Bun.file(path).text()
-// After: Filesystem.readText()
-const content = await Filesystem.readText(path)
-
-// Before: Bun.file().json()
-const data = await Bun.file(path).json()
-// After: Filesystem.readJson()
-const data = await Filesystem.readJson<Config>(path)
-
-// Before: Bun.file().bytes()
-const bytes = await Bun.file(path).bytes()
-// After: Filesystem.readBytes()
-const buffer = await Filesystem.readBytes(path)
-
-// Before: Bun.file().stat()
-const stats = await Bun.file(path).stat()
-// After: Filesystem.isDir() and size (uses fast statSync)
-const isDir = await Filesystem.isDir(path)
-const size = await Filesystem.size(path)
-
-// Before: Bun.file().size
-const size = Bun.file(path).size
-// After: Filesystem.size() (8x faster than async stat)
-const size = await Filesystem.size(path)
-
-// Before: Bun.write()
-await Bun.write(path, content)
-// After: Filesystem.write() (auto-creates directories)
-await Filesystem.write(path, content)
-
-// Before: Bun.write() with JSON
-await Bun.write(path, JSON.stringify(data, null, 2))
-// After: Filesystem.writeJson()
-await Filesystem.writeJson(path, data)
-
-// Before: Bun.file().type
-const mime = Bun.file(path).type
-// After: Filesystem.mimeType()
-const mime = Filesystem.mimeType(path)
-```
-
-### API Reference
-
-| Bun API                | Filesystem Equivalent                       | Implementation                |
-| ---------------------- | ------------------------------------------- | ----------------------------- |
-| `Bun.file(p).exists()` | `Filesystem.exists(p)`                      | `existsSync()` (15x faster)   |
-| `Bun.file(p).stat()`   | `Filesystem.isDir(p)`, `Filesystem.size(p)` | `statSync()` (8x faster)      |
-| `Bun.file(p).text()`   | `Filesystem.readText(p)`                    | `readFile()`                  |
-| `Bun.file(p).json()`   | `Filesystem.readJson<T>(p)`                 | `readFile()` + `JSON.parse()` |
-| `Bun.file(p).bytes()`  | `Filesystem.readBytes(p)`                   | `readFile()` (returns Buffer) |
-| `Bun.file(p).size`     | `Filesystem.size(p)`                        | `statSync().size` (8x faster) |
-| `Bun.file(p).type`     | `Filesystem.mimeType(p)`                    | `mime-types` library          |
-| `Bun.write(p, data)`   | `Filesystem.write(p, data, mode?)`          | `writeFile()` + lazy `mkdir`  |
-| -                      | `Filesystem.writeJson(p, data, mode?)`      | `write()` with JSON.stringify |
-
-### Performance Notes
-
-The `Filesystem` module uses optimized implementations:
-
-- **Metadata operations** (`exists`, `isDir`, `size`): Use sync APIs (`existsSync`, `statSync`) for 8-15x speedup
-- **Content operations** (`readText`, `write`): Use async APIs to avoid blocking thread during I/O
-- **Directory creation**: Lazy - only creates directories when write fails with ENOENT
-- **MIME type detection**: Uses `mime-types` library for broader format support than Bun
-
-## Testing
-
-Always run tests before pushing changes:
-
-```bash
-cd packages/opencode
-bun test
-```
-
-## Quick Reference for LLM Agents
-
-**What you're doing**: Migrating one file at a time from Bun-specific file APIs to the Filesystem module.
-
-**Commands to run**:
-
-1. `cd packages/opencode` - Always work from the package directory
-2. After migration: `bun test` - Ensure tests pass before pushing
-
-**What to migrate**:
-
-- `Bun.file(path).exists()` → `Filesystem.exists(path)`
-- `Bun.file(path).text()` → `Filesystem.readText(path)`
-- `Bun.file(path).json()` → `Filesystem.readJson(path)`
-- `Bun.file(path).bytes()` → `Filesystem.readBytes(path)`
-- `Bun.file(path).stat()` → `Filesystem.isDir(path)` or `Filesystem.size(path)`
-- `Bun.file(path).size` → `Filesystem.size(path)`
-- `Bun.file(path).type` → `Filesystem.mimeType(path)`
-- `Bun.write(path, content)` → `Filesystem.write(path, content)`
-- `Bun.write(path, JSON.stringify(data))` → `Filesystem.writeJson(path, data)`
-
-**Do NOT migrate** (leave as-is):
-
-- `Bun.hash.xxHash32` - Keep using Bun's hash
-- `Bun.stdin` - Keep using Bun's stdin
-
-**After merging your PR**: Return to this file and check off the file you just migrated from the checklist.
-
-## Migration Checklist
-
-### Phase 1: Centralize File Operations (DONE ✅)
-
-- [x] Create `src/util/filesystem.ts` with all file operations
-- [x] Implement optimized sync variants for metadata (exists, isDir, size)
-- [x] Implement async variants for content operations (read, write)
-- [x] Add lazy directory creation for write operations
-- [x] Add comprehensive test coverage (31 tests)
-
-### Phase 2: Migrate Source Files
-
-For each file using Bun.file APIs, replace with `Filesystem` equivalents:
-
-**Pattern:**
-
-```typescript
-// Remove Bun imports
-import { Bun } from "bun" // ❌ Remove this
-
-// Add Filesystem import
-import { Filesystem } from "./util/filesystem" // ✅ Add this
-
-// Replace all Bun.file() calls
-const exists = await Bun.file(path).exists() // ❌
-const exists = await Filesystem.exists(path) // ✅
-
-const content = await Bun.file(path).text() // ❌
-const content = await Filesystem.readText(path) // ✅
-
-await Bun.write(path, content) // ❌
-await Filesystem.write(path, content) // ✅
-```
-
-**Files to migrate:**
-
-- [ ] `src/tool/read.ts` - `stat()`, `type`, `bytes()`, `text()`
-- [ ] `src/tool/write.ts` - `exists()`, `text()`, `Bun.write()`
-- [ ] `src/tool/edit.ts` - `exists()`, `stat()`, `text()`, `write()`
-- [ ] `src/file/time.ts` - `stat()`
-- [ ] `src/file/index.ts` - `text()`, `bytes()`, `exists()`, `type`
-- [ ] `src/mcp/auth.ts` - `json()`, `Bun.write()`
-- [ ] `src/storage/storage.ts` - `json()`, `Bun.write()`
-- [ ] `src/lsp/server.ts` - `exists()`, `write()`, `text()`
-- [ ] ... (see full list above)
-
-### Phase 3: Handle Special Cases
-
-- [ ] Install `@types/mime-types` (already done)
-- [ ] Run all tests to verify functionality
-- [ ] Update `package.json` to remove Bun-only dependencies if any
-
-### Migration Priority
-
-1. **High**: Files with >5 Bun.file usages or critical paths
-2. **Medium**: Files with 2-5 usages
-3. **Low**: Files with 1-2 usages or covered by other tests
-
-## Notes
-
-- Bun APIs return `null` on some errors where Node.js throws; ensure `.catch(() => ...)` is used appropriately
-- File permissions: Bun defaults may differ from Node.js defaults; explicitly pass `mode: 0o600` where needed
-- Performance: Node.js `fs/promises` is generally comparable to Bun.file for most read operations (within 2x)
-- Metadata operations (exists, size) will be ~10x slower after migration
-- Streaming: Both support similar streaming APIs via `createReadStream` and `createWriteStream`