Skip to content
← Public packages

@kentcdodds/audible

Personal Audible library app — browser re-auth, library, wishlist, NAS archive stub.

src/nas-status-cache.ts

75 lines · 2.0 KB · TypeScript
/**
 * SWR-style packageStorage cache for Library On-NAS / Save-to-NAS mapping.
 *
 * Soft TTL (~60s): serve cache without home MCP.
 * Max age (~30d): past soft TTL still serve stale immediately; refresh on
 * forceRefresh / ?refresh=1 / client soft-reload after paint / next explicit revalidate.
 * Write-through on successful archive-to-nas (including already_exists skip).
 */
import { packageStorage } from 'kody:runtime'
import {
	NAS_MAX_AGE_MS,
	NAS_SOFT_TTL_MS,
	coerceNasStatusCacheStore,
	emptyNasStatusCacheStore,
	putNasStatusCacheEntry,
	type NasStatusCacheStore,
} from './nas-status-cache-policy.ts'

export {
	NAS_MAX_AGE_MS,
	NAS_SOFT_TTL_MS,
	classifyCacheAge,
	lookupNasStatusCache,
	putNasStatusCacheEntry,
	titleCacheKey,
	type NasCacheLookup,
	type NasStatusCacheEntry,
	type NasStatusCacheStore,
} from './nas-status-cache-policy.ts'

export const NAS_STATUS_CACHE_KEY = 'library-nas-status-v1'

export async function loadNasStatusCache(): Promise<NasStatusCacheStore> {
	try {
		const raw = await packageStorage().get(NAS_STATUS_CACHE_KEY)
		if (raw == null) return emptyNasStatusCacheStore()
		if (typeof raw === 'string') {
			try {
				return coerceNasStatusCacheStore(JSON.parse(raw))
			} catch {
				return emptyNasStatusCacheStore()
			}
		}
		return coerceNasStatusCacheStore(raw)
	} catch {
		return emptyNasStatusCacheStore()
	}
}

export async function saveNasStatusCache(
	store: NasStatusCacheStore,
): Promise<void> {
	await packageStorage().set(NAS_STATUS_CACHE_KEY, store)
}

/** Write-through after Save / Re-save / already_exists skip. */
export async function writeThroughNasStatus(input: {
	title: string
	asin?: string
	filename: string
	onNas?: boolean
}): Promise<void> {
	const title = input.title?.trim()
	const filename = input.filename?.trim()
	if (!title || !filename) return
	const store = await loadNasStatusCache()
	putNasStatusCacheEntry(store, {
		title,
		asin: input.asin,
		nasFilename: filename,
		onNas: input.onNas !== false,
		checkedAt: Date.now(),
	})
	await saveNasStatusCache(store)
}