Skip to content

Commit 02a9495

Browse files
authored
Remove use of Bun.file (anomalyco#14215)
1 parent 0fcba68 commit 02a9495

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+634
-473
lines changed

.opencode/skill/bun-file-io/SKILL.md

Lines changed: 0 additions & 42 deletions
This file was deleted.

packages/opencode/src/cli/cmd/tui/component/prompt/frecency.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import path from "path"
22
import { Global } from "@/global"
3+
import { Filesystem } from "@/util/filesystem"
34
import { onMount } from "solid-js"
45
import { createStore } from "solid-js/store"
56
import { createSimpleContext } from "../../context/helper"
6-
import { appendFile } from "fs/promises"
7+
import { appendFile, writeFile } from "fs/promises"
78

89
function calculateFrecency(entry?: { frequency: number; lastOpen: number }): number {
910
if (!entry) return 0
@@ -17,9 +18,9 @@ const MAX_FRECENCY_ENTRIES = 1000
1718
export const { use: useFrecency, provider: FrecencyProvider } = createSimpleContext({
1819
name: "Frecency",
1920
init: () => {
20-
const frecencyFile = Bun.file(path.join(Global.Path.state, "frecency.jsonl"))
21+
const frecencyPath = path.join(Global.Path.state, "frecency.jsonl")
2122
onMount(async () => {
22-
const text = await frecencyFile.text().catch(() => "")
23+
const text = await Filesystem.readText(frecencyPath).catch(() => "")
2324
const lines = text
2425
.split("\n")
2526
.filter(Boolean)
@@ -53,7 +54,7 @@ export const { use: useFrecency, provider: FrecencyProvider } = createSimpleCont
5354

5455
if (sorted.length > 0) {
5556
const content = sorted.map((entry) => JSON.stringify(entry)).join("\n") + "\n"
56-
Bun.write(frecencyFile, content).catch(() => {})
57+
writeFile(frecencyPath, content).catch(() => {})
5758
}
5859
})
5960

@@ -68,15 +69,15 @@ export const { use: useFrecency, provider: FrecencyProvider } = createSimpleCont
6869
lastOpen: Date.now(),
6970
}
7071
setStore("data", absolutePath, newEntry)
71-
appendFile(frecencyFile.name!, JSON.stringify({ path: absolutePath, ...newEntry }) + "\n").catch(() => {})
72+
appendFile(frecencyPath, JSON.stringify({ path: absolutePath, ...newEntry }) + "\n").catch(() => {})
7273

7374
if (Object.keys(store.data).length > MAX_FRECENCY_ENTRIES) {
7475
const sorted = Object.entries(store.data)
7576
.sort(([, a], [, b]) => b.lastOpen - a.lastOpen)
7677
.slice(0, MAX_FRECENCY_ENTRIES)
7778
setStore("data", Object.fromEntries(sorted))
7879
const content = sorted.map(([path, entry]) => JSON.stringify({ path, ...entry })).join("\n") + "\n"
79-
Bun.write(frecencyFile, content).catch(() => {})
80+
writeFile(frecencyPath, content).catch(() => {})
8081
}
8182
}
8283

packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import path from "path"
22
import { Global } from "@/global"
3+
import { Filesystem } from "@/util/filesystem"
34
import { onMount } from "solid-js"
45
import { createStore, produce } from "solid-js/store"
56
import { clone } from "remeda"
@@ -30,9 +31,9 @@ const MAX_HISTORY_ENTRIES = 50
3031
export const { use: usePromptHistory, provider: PromptHistoryProvider } = createSimpleContext({
3132
name: "PromptHistory",
3233
init: () => {
33-
const historyFile = Bun.file(path.join(Global.Path.state, "prompt-history.jsonl"))
34+
const historyPath = path.join(Global.Path.state, "prompt-history.jsonl")
3435
onMount(async () => {
35-
const text = await historyFile.text().catch(() => "")
36+
const text = await Filesystem.readText(historyPath).catch(() => "")
3637
const lines = text
3738
.split("\n")
3839
.filter(Boolean)
@@ -51,7 +52,7 @@ export const { use: usePromptHistory, provider: PromptHistoryProvider } = create
5152
// Rewrite file with only valid entries to self-heal corruption
5253
if (lines.length > 0) {
5354
const content = lines.map((line) => JSON.stringify(line)).join("\n") + "\n"
54-
writeFile(historyFile.name!, content).catch(() => {})
55+
writeFile(historyPath, content).catch(() => {})
5556
}
5657
})
5758

@@ -97,11 +98,11 @@ export const { use: usePromptHistory, provider: PromptHistoryProvider } = create
9798

9899
if (trimmed) {
99100
const content = store.history.map((line) => JSON.stringify(line)).join("\n") + "\n"
100-
writeFile(historyFile.name!, content).catch(() => {})
101+
writeFile(historyPath, content).catch(() => {})
101102
return
102103
}
103104

104-
appendFile(historyFile.name!, JSON.stringify(entry) + "\n").catch(() => {})
105+
appendFile(historyPath, JSON.stringify(entry) + "\n").catch(() => {})
105106
},
106107
}
107108
},

packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { BoxRenderable, TextareaRenderable, MouseEvent, PasteEvent, t, dim, fg } from "@opentui/core"
22
import { createEffect, createMemo, type JSX, onMount, createSignal, onCleanup, on, Show, Switch, Match } from "solid-js"
33
import "opentui-spinner/solid"
4+
import path from "path"
5+
import { Filesystem } from "@/util/filesystem"
46
import { useLocal } from "@tui/context/local"
57
import { useTheme } from "@tui/context/theme"
68
import { EmptyBorder } from "@tui/component/border"
@@ -931,26 +933,26 @@ export function Prompt(props: PromptProps) {
931933
const isUrl = /^(https?):\/\//.test(filepath)
932934
if (!isUrl) {
933935
try {
934-
const file = Bun.file(filepath)
936+
const mime = Filesystem.mimeType(filepath)
937+
const filename = path.basename(filepath)
935938
// Handle SVG as raw text content, not as base64 image
936-
if (file.type === "image/svg+xml") {
939+
if (mime === "image/svg+xml") {
937940
event.preventDefault()
938-
const content = await file.text().catch(() => {})
941+
const content = await Filesystem.readText(filepath).catch(() => {})
939942
if (content) {
940-
pasteText(content, `[SVG: ${file.name ?? "image"}]`)
943+
pasteText(content, `[SVG: ${filename ?? "image"}]`)
941944
return
942945
}
943946
}
944-
if (file.type.startsWith("image/")) {
947+
if (mime.startsWith("image/")) {
945948
event.preventDefault()
946-
const content = await file
947-
.arrayBuffer()
949+
const content = await Filesystem.readArrayBuffer(filepath)
948950
.then((buffer) => Buffer.from(buffer).toString("base64"))
949951
.catch(() => {})
950952
if (content) {
951953
await pasteImage({
952-
filename: file.name,
953-
mime: file.type,
954+
filename,
955+
mime,
954956
content,
955957
})
956958
return

packages/opencode/src/cli/cmd/tui/component/prompt/stash.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import path from "path"
22
import { Global } from "@/global"
3+
import { Filesystem } from "@/util/filesystem"
34
import { onMount } from "solid-js"
45
import { createStore, produce } from "solid-js/store"
56
import { clone } from "remeda"
@@ -18,9 +19,9 @@ const MAX_STASH_ENTRIES = 50
1819
export const { use: usePromptStash, provider: PromptStashProvider } = createSimpleContext({
1920
name: "PromptStash",
2021
init: () => {
21-
const stashFile = Bun.file(path.join(Global.Path.state, "prompt-stash.jsonl"))
22+
const stashPath = path.join(Global.Path.state, "prompt-stash.jsonl")
2223
onMount(async () => {
23-
const text = await stashFile.text().catch(() => "")
24+
const text = await Filesystem.readText(stashPath).catch(() => "")
2425
const lines = text
2526
.split("\n")
2627
.filter(Boolean)
@@ -39,7 +40,7 @@ export const { use: usePromptStash, provider: PromptStashProvider } = createSimp
3940
// Rewrite file with only valid entries to self-heal corruption
4041
if (lines.length > 0) {
4142
const content = lines.map((line) => JSON.stringify(line)).join("\n") + "\n"
42-
writeFile(stashFile.name!, content).catch(() => {})
43+
writeFile(stashPath, content).catch(() => {})
4344
}
4445
})
4546

@@ -66,11 +67,11 @@ export const { use: usePromptStash, provider: PromptStashProvider } = createSimp
6667

6768
if (trimmed) {
6869
const content = store.entries.map((line) => JSON.stringify(line)).join("\n") + "\n"
69-
writeFile(stashFile.name!, content).catch(() => {})
70+
writeFile(stashPath, content).catch(() => {})
7071
return
7172
}
7273

73-
appendFile(stashFile.name!, JSON.stringify(stash) + "\n").catch(() => {})
74+
appendFile(stashPath, JSON.stringify(stash) + "\n").catch(() => {})
7475
},
7576
pop() {
7677
if (store.entries.length === 0) return undefined
@@ -82,7 +83,7 @@ export const { use: usePromptStash, provider: PromptStashProvider } = createSimp
8283
)
8384
const content =
8485
store.entries.length > 0 ? store.entries.map((line) => JSON.stringify(line)).join("\n") + "\n" : ""
85-
writeFile(stashFile.name!, content).catch(() => {})
86+
writeFile(stashPath, content).catch(() => {})
8687
return entry
8788
},
8889
remove(index: number) {
@@ -94,7 +95,7 @@ export const { use: usePromptStash, provider: PromptStashProvider } = createSimp
9495
)
9596
const content =
9697
store.entries.length > 0 ? store.entries.map((line) => JSON.stringify(line)).join("\n") + "\n" : ""
97-
writeFile(stashFile.name!, content).catch(() => {})
98+
writeFile(stashPath, content).catch(() => {})
9899
},
99100
}
100101
},

packages/opencode/src/cli/cmd/tui/context/kv.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Global } from "@/global"
2+
import { Filesystem } from "@/util/filesystem"
23
import { createSignal, type Setter } from "solid-js"
34
import { createStore } from "solid-js/store"
45
import { createSimpleContext } from "./helper"
@@ -9,10 +10,9 @@ export const { use: useKV, provider: KVProvider } = createSimpleContext({
910
init: () => {
1011
const [ready, setReady] = createSignal(false)
1112
const [store, setStore] = createStore<Record<string, any>>()
12-
const file = Bun.file(path.join(Global.Path.state, "kv.json"))
13+
const filePath = path.join(Global.Path.state, "kv.json")
1314

14-
file
15-
.json()
15+
Filesystem.readJson(filePath)
1616
.then((x) => {
1717
setStore(x)
1818
})
@@ -44,7 +44,7 @@ export const { use: useKV, provider: KVProvider } = createSimpleContext({
4444
},
4545
set(key: string, value: any) {
4646
setStore(key, value)
47-
Bun.write(file, JSON.stringify(store, null, 2))
47+
Filesystem.writeJson(filePath, store)
4848
},
4949
}
5050
return result

packages/opencode/src/cli/cmd/tui/context/local.tsx

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Provider } from "@/provider/provider"
1212
import { useArgs } from "./args"
1313
import { useSDK } from "./sdk"
1414
import { RGBA } from "@opentui/core"
15+
import { Filesystem } from "@/util/filesystem"
1516

1617
export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
1718
name: "Local",
@@ -119,7 +120,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
119120
variant: {},
120121
})
121122

122-
const file = Bun.file(path.join(Global.Path.state, "model.json"))
123+
const filePath = path.join(Global.Path.state, "model.json")
123124
const state = {
124125
pending: false,
125126
}
@@ -130,19 +131,15 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
130131
return
131132
}
132133
state.pending = false
133-
Bun.write(
134-
file,
135-
JSON.stringify({
136-
recent: modelStore.recent,
137-
favorite: modelStore.favorite,
138-
variant: modelStore.variant,
139-
}),
140-
)
134+
Filesystem.writeJson(filePath, {
135+
recent: modelStore.recent,
136+
favorite: modelStore.favorite,
137+
variant: modelStore.variant,
138+
})
141139
}
142140

143-
file
144-
.json()
145-
.then((x) => {
141+
Filesystem.readJson(filePath)
142+
.then((x: any) => {
146143
if (Array.isArray(x.recent)) setModelStore("recent", x.recent)
147144
if (Array.isArray(x.favorite)) setModelStore("favorite", x.favorite)
148145
if (typeof x.variant === "object" && x.variant !== null) setModelStore("variant", x.variant)

packages/opencode/src/cli/cmd/tui/context/theme.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ async function getCustomThemes() {
412412
cwd: dir,
413413
})) {
414414
const name = path.basename(item, ".json")
415-
result[name] = await Bun.file(item).json()
415+
result[name] = await Filesystem.readJson(item)
416416
}
417417
}
418418
return result

packages/opencode/src/cli/cmd/tui/thread.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { tui } from "./app"
33
import { Rpc } from "@/util/rpc"
44
import { type rpc } from "./worker"
55
import path from "path"
6+
import { fileURLToPath } from "url"
67
import { UI } from "@/cli/ui"
78
import { iife } from "@/util/iife"
89
import { Log } from "@/util/log"
910
import { withNetworkOptions, resolveNetworkOptions } from "@/cli/network"
11+
import { Filesystem } from "@/util/filesystem"
1012
import type { Event } from "@opencode-ai/sdk/v2"
1113
import type { EventSource } from "./context/sdk"
1214
import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32"
@@ -99,7 +101,7 @@ export const TuiThreadCommand = cmd({
99101
const distWorker = new URL("./cli/cmd/tui/worker.js", import.meta.url)
100102
const workerPath = await iife(async () => {
101103
if (typeof OPENCODE_WORKER_PATH !== "undefined") return OPENCODE_WORKER_PATH
102-
if (await Bun.file(distWorker).exists()) return distWorker
104+
if (await Filesystem.exists(fileURLToPath(distWorker))) return distWorker
103105
return localWorker
104106
})
105107
try {

packages/opencode/src/lsp/client.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,7 @@ export namespace LSPClient {
147147
notify: {
148148
async open(input: { path: string }) {
149149
input.path = path.isAbsolute(input.path) ? input.path : path.resolve(Instance.directory, input.path)
150-
const file = Bun.file(input.path)
151-
const text = await file.text()
150+
const text = await Filesystem.readText(input.path)
152151
const extension = path.extname(input.path)
153152
const languageId = LANGUAGE_EXTENSIONS[extension] ?? "plaintext"
154153

0 commit comments

Comments
 (0)