mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-27 06:45:24 +00:00
92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
import { app } from "electron"
|
|
import log from "electron-log/main.js"
|
|
import { existsSync, readdirSync, readFileSync } from "node:fs"
|
|
import { homedir } from "node:os"
|
|
import { join } from "node:path"
|
|
import { CHANNEL } from "./constants"
|
|
import { getStore } from "./store"
|
|
|
|
const TAURI_MIGRATED_KEY = "tauriMigrated"
|
|
|
|
// Resolve the directory where Tauri stored its .dat files for the given app identifier.
|
|
// Mirrors Tauri's AppLocalData / AppData resolution per OS.
|
|
function tauriDir(id: string) {
|
|
switch (process.platform) {
|
|
case "darwin":
|
|
return join(homedir(), "Library", "Application Support", id)
|
|
case "win32":
|
|
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), id)
|
|
default:
|
|
return join(process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), id)
|
|
}
|
|
}
|
|
|
|
// The Tauri app identifier changes between dev/beta/prod builds.
|
|
const TAURI_APP_IDS: Record<string, string> = {
|
|
dev: "ai.opencode.desktop.dev",
|
|
beta: "ai.opencode.desktop.beta",
|
|
prod: "ai.opencode.desktop",
|
|
}
|
|
function tauriAppId() {
|
|
return app.isPackaged ? TAURI_APP_IDS[CHANNEL] : "ai.opencode.desktop.dev"
|
|
}
|
|
|
|
// Migrate a single Tauri .dat file into the corresponding electron-store.
|
|
// `opencode.settings.dat` is special: it maps to the `opencode.settings` store
|
|
// (the electron-store name without the `.dat` extension). All other .dat files
|
|
// keep their full filename as the electron-store name so they match what the
|
|
// renderer already passes via IPC (e.g. `"default.dat"`, `"opencode.global.dat"`).
|
|
function migrateFile(datPath: string, filename: string) {
|
|
let data: Record<string, unknown>
|
|
try {
|
|
data = JSON.parse(readFileSync(datPath, "utf-8"))
|
|
} catch (err) {
|
|
log.warn("tauri migration: failed to parse", filename, err)
|
|
return
|
|
}
|
|
|
|
// opencode.settings.dat → the electron settings store ("opencode.settings").
|
|
// All other .dat files keep their full filename as the store name so they match
|
|
// what the renderer passes via IPC (e.g. "default.dat", "opencode.global.dat").
|
|
const storeName = filename === "opencode.settings.dat" ? "opencode.settings" : filename
|
|
const target = getStore(storeName)
|
|
const migrated: string[] = []
|
|
const skipped: string[] = []
|
|
|
|
for (const [key, value] of Object.entries(data)) {
|
|
// Don't overwrite values the user has already set in the Electron app.
|
|
if (target.has(key)) {
|
|
skipped.push(key)
|
|
continue
|
|
}
|
|
target.set(key, value)
|
|
migrated.push(key)
|
|
}
|
|
|
|
log.log("tauri migration: migrated", filename, "→", storeName, { migrated, skipped })
|
|
}
|
|
|
|
export function migrate() {
|
|
if (getStore().get(TAURI_MIGRATED_KEY)) {
|
|
log.log("tauri migration: already done, skipping")
|
|
return
|
|
}
|
|
|
|
const dir = tauriDir(tauriAppId())
|
|
log.log("tauri migration: starting", { dir })
|
|
|
|
if (!existsSync(dir)) {
|
|
log.log("tauri migration: no tauri data directory found, nothing to migrate")
|
|
getStore().set(TAURI_MIGRATED_KEY, true)
|
|
return
|
|
}
|
|
|
|
for (const filename of readdirSync(dir)) {
|
|
if (!filename.endsWith(".dat")) continue
|
|
migrateFile(join(dir, filename), filename)
|
|
}
|
|
|
|
log.log("tauri migration: complete")
|
|
getStore().set(TAURI_MIGRATED_KEY, true)
|
|
}
|