Buckets:
| 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) | |
| } | |
Xet Storage Details
- Size:
- 3.21 kB
- Xet hash:
- c2def1e64a3f45d5d23d265866a180c1efa60108fb8403d31c55b7b3f574f0ee
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.