rfunds-online/lib/state.ts

77 lines
2.2 KiB
TypeScript

import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from 'lz-string'
import type { FlowNode, SpaceConfig, IntegrationConfig } from './types'
const STORAGE_PREFIX = 'rfunds-space-'
interface SerializableState {
nodes: FlowNode[]
integrations?: IntegrationConfig
}
export function serializeState(nodes: FlowNode[], integrations?: IntegrationConfig): string {
const state: SerializableState = { nodes }
if (integrations) state.integrations = integrations
const json = JSON.stringify(state)
return compressToEncodedURIComponent(json)
}
export function deserializeState(compressed: string): { nodes: FlowNode[]; integrations?: IntegrationConfig } | null {
try {
const json = decompressFromEncodedURIComponent(compressed)
if (!json) return null
const state = JSON.parse(json) as SerializableState
if (!state.nodes || !Array.isArray(state.nodes)) return null
return { nodes: state.nodes, integrations: state.integrations }
} catch {
return null
}
}
export function saveToLocal(name: string, nodes: FlowNode[], integrations?: IntegrationConfig): void {
const config: SpaceConfig = {
name,
nodes,
integrations,
createdAt: Date.now(),
updatedAt: Date.now(),
}
// Check if exists to preserve createdAt
const existing = loadFromLocal(name)
if (existing) {
config.createdAt = existing.createdAt
}
localStorage.setItem(STORAGE_PREFIX + name, JSON.stringify(config))
}
export function loadFromLocal(name: string): SpaceConfig | null {
try {
const raw = localStorage.getItem(STORAGE_PREFIX + name)
if (!raw) return null
return JSON.parse(raw) as SpaceConfig
} catch {
return null
}
}
export function deleteFromLocal(name: string): void {
localStorage.removeItem(STORAGE_PREFIX + name)
}
export function listSavedSpaces(): SpaceConfig[] {
const spaces: SpaceConfig[] = []
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i)
if (key && key.startsWith(STORAGE_PREFIX)) {
try {
const config = JSON.parse(localStorage.getItem(key)!) as SpaceConfig
spaces.push(config)
} catch {
// skip corrupt entries
}
}
}
return spaces.sort((a, b) => b.updatedAt - a.updatedAt)
}