Files
openchamber/packages/ui/src/sync/persist-cache.ts
T
00821700de chore: remove dead code (59 unused files + ~125 unused exports) (#1835)
* chore: remove dead/unreferenced files across ui, vscode

Remove 59 unused source files (components, hooks, lib utils, stores,
barrels, and orphaned vscode github modules) that are not imported by
any entry-reachable code. Also drop a stale test mock for the removed
execCommands module.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* refactor: remove unused exported symbols (types, functions, consts, hooks)

Remove exported symbols whose identifier is referenced nowhere in the
repository (verified via repo-wide search), across ui types/contracts,
lib utilities, sync layer, stores, and components. Also drop the few
imports/private helpers orphaned by these removals.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* refactor: remove more unused exports (desktop, shortcuts, worktree, vscode)

Continue removing repo-wide unreferenced exported functions, consts and
types across lib/desktop, shortcuts, worktreeSessionCreator, sync, and
vscode gitService, with cascading orphaned helpers/imports cleaned up.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* chore: add dead-code cleanup tooling

* refactor: checkpoint dead-code cleanup

* refactor: remove dead-code suppressions

---------

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-26 19:27:53 +03:00

119 lines
3.8 KiB
TypeScript

/**
* Persisted child-store metadata caches.
*
* VCS info, project metadata, and icons are cached to localStorage
* per directory so they survive page reloads.
* Only metadata is persisted — session/message/part data is always fresh
* from the server via SSE bootstrap.
*/
import type { Session, VcsInfo } from "@opencode-ai/sdk/v2/client"
import type { ProjectMeta } from "./types"
/** Cap persisted session lists so localStorage stays bounded per directory. */
const PERSISTED_SESSION_LIMIT = 50
// ---------------------------------------------------------------------------
// Storage key generation
// ---------------------------------------------------------------------------
function hashCode(str: string): string {
let hash = 0
for (let i = 0; i < str.length; i++) {
const chr = str.charCodeAt(i)
hash = ((hash << 5) - hash) + chr
hash |= 0
}
return Math.abs(hash).toString(36)
}
function storagePrefix(directory: string): string {
const head = directory.slice(0, 12).replace(/[^a-zA-Z0-9]/g, "_")
return `oc.dir.${head}.${hashCode(directory)}`
}
// ---------------------------------------------------------------------------
// Typed cache helpers
// ---------------------------------------------------------------------------
type CacheKey = "vcs" | "projectMeta" | "icon" | "sessions"
function cacheKey(directory: string, key: CacheKey): string {
return `${storagePrefix(directory)}.${key}`
}
function readCache<T>(directory: string, key: CacheKey): T | undefined {
try {
const raw = localStorage.getItem(cacheKey(directory, key))
if (!raw) return undefined
return JSON.parse(raw) as T
} catch {
return undefined
}
}
function writeCache<T>(directory: string, key: CacheKey, value: T | undefined): void {
try {
const k = cacheKey(directory, key)
if (value === undefined) {
localStorage.removeItem(k)
} else {
localStorage.setItem(k, JSON.stringify(value))
}
} catch {
// localStorage quota exceeded — ignore
}
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
export type PersistedDirCache = {
vcs: VcsInfo | undefined
projectMeta: ProjectMeta | undefined
icon: string | undefined
sessions: Session[] | undefined
}
/** Read all cached metadata for a directory */
export function readDirCache(directory: string): PersistedDirCache {
return {
vcs: readCache<VcsInfo>(directory, "vcs"),
projectMeta: readCache<ProjectMeta>(directory, "projectMeta"),
icon: readCache<string>(directory, "icon"),
sessions: readCache<Session[]>(directory, "sessions"),
}
}
/**
* Write a capped slice of the directory session list to cache so the sidebar
* can paint chats instantly on cold start. Refreshed by bootstrap loadSessions.
*/
export function persistSessions(directory: string, sessions: Session[] | undefined): void {
if (!sessions || sessions.length === 0) {
writeCache(directory, "sessions", undefined)
return
}
// Keep the most recent N by id (ids are time-ordered hex) to bound storage.
const capped = sessions.length > PERSISTED_SESSION_LIMIT
? [...sessions].sort((a, b) => (a.id < b.id ? 1 : a.id > b.id ? -1 : 0)).slice(0, PERSISTED_SESSION_LIMIT)
: sessions
writeCache(directory, "sessions", capped)
}
/** Write vcs info to cache */
export function persistVcs(directory: string, vcs: VcsInfo | undefined): void {
writeCache(directory, "vcs", vcs)
}
/** Write project metadata to cache */
export function persistProjectMeta(directory: string, meta: ProjectMeta | undefined): void {
writeCache(directory, "projectMeta", meta)
}
/** Write icon to cache */
export function persistIcon(directory: string, icon: string | undefined): void {
writeCache(directory, "icon", icon)
}