Persist remaining client state in disk cache files
Release rolling / release (push) Has been cancelled
Release rolling / release (push) Has been cancelled
Move templates, notifications, backups, table columns, peer envs, and sidebar/first-connect prefs onto ~/.config/peardock/cache (settings.json or dedicated JSON files) with legacy localStorage migration.
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* File-backed JSON cache under ~/.config/peardock/cache/
|
||||
*/
|
||||
import test from 'brittle'
|
||||
import fs from 'fs'
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
import {
|
||||
loadJsonCache,
|
||||
saveJsonCache,
|
||||
clearJsonCache,
|
||||
getCacheFilePath,
|
||||
parseCachePayload,
|
||||
buildCachePayload,
|
||||
JSON_CACHE_VERSION,
|
||||
} from '../client/jsonCache.js'
|
||||
|
||||
function installLocalStorage() {
|
||||
/** @type {Map<string, string>} */
|
||||
const map = new Map()
|
||||
globalThis.localStorage = {
|
||||
get length() {
|
||||
return map.size
|
||||
},
|
||||
key(i) {
|
||||
return [...map.keys()][i] ?? null
|
||||
},
|
||||
getItem(k) {
|
||||
return map.has(k) ? map.get(k) : null
|
||||
},
|
||||
setItem(k, v) {
|
||||
map.set(String(k), String(v))
|
||||
},
|
||||
removeItem(k) {
|
||||
map.delete(k)
|
||||
},
|
||||
clear() {
|
||||
map.clear()
|
||||
},
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
function withTempHome(t) {
|
||||
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'peardock-json-cache-'))
|
||||
const prev = process.env.PEARDOCK_HOME
|
||||
process.env.PEARDOCK_HOME = tmp
|
||||
t.teardown(() => {
|
||||
if (prev === undefined) delete process.env.PEARDOCK_HOME
|
||||
else process.env.PEARDOCK_HOME = prev
|
||||
try {
|
||||
fs.rmSync(tmp, { recursive: true, force: true })
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
})
|
||||
return tmp
|
||||
}
|
||||
|
||||
test('build/parse cache envelope', (t) => {
|
||||
const env = buildCachePayload({ a: 1 })
|
||||
t.is(env.version, JSON_CACHE_VERSION)
|
||||
t.ok(env.updatedAt)
|
||||
t.alike(env.data, { a: 1 })
|
||||
t.alike(parseCachePayload(JSON.stringify(env)), { a: 1 })
|
||||
t.alike(parseCachePayload({ flat: true }), { flat: true })
|
||||
t.alike(parseCachePayload([1, 2]), [1, 2])
|
||||
})
|
||||
|
||||
test('save and load json cache file', (t) => {
|
||||
withTempHome(t)
|
||||
installLocalStorage()
|
||||
|
||||
const r = saveJsonCache('templates', { web: { image: 'nginx' } })
|
||||
t.ok(r.ok)
|
||||
t.ok(fs.existsSync(getCacheFilePath('templates')))
|
||||
|
||||
const loaded = loadJsonCache('templates', { fallback: {} })
|
||||
t.alike(loaded, { web: { image: 'nginx' } })
|
||||
})
|
||||
|
||||
test('migrates legacy localStorage key into cache file', (t) => {
|
||||
withTempHome(t)
|
||||
const ls = installLocalStorage()
|
||||
ls.set('peardock_templates', JSON.stringify({ old: { image: 'busybox' } }))
|
||||
|
||||
const loaded = loadJsonCache('templates', {
|
||||
fallback: {},
|
||||
legacyLocalStorageKey: 'peardock_templates',
|
||||
})
|
||||
t.alike(loaded, { old: { image: 'busybox' } })
|
||||
t.ok(fs.existsSync(getCacheFilePath('templates')))
|
||||
})
|
||||
|
||||
test('clearJsonCache removes file', (t) => {
|
||||
withTempHome(t)
|
||||
installLocalStorage()
|
||||
saveJsonCache('notifications', [{ id: '1' }])
|
||||
t.ok(fs.existsSync(getCacheFilePath('notifications')))
|
||||
clearJsonCache('notifications', { legacyLocalStorageKey: 'peardock_notifications' })
|
||||
t.absent(fs.existsSync(getCacheFilePath('notifications')))
|
||||
})
|
||||
Reference in New Issue
Block a user