← Public packages
@kentcdodds/package-app-kit
Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.
src/server-cache.ts
112 lines · 3.1 KB · TypeScript/**
* @epic-web/cachified factory backed by packageStorage for Worker/package exports.
*/
import { cachified, type Cache, type CacheEntry } from '@epic-web/cachified'
import { packageStorage } from 'kody:runtime'
export type PackageStorageCacheOptions = {
/** Key prefix inside packageStorage (default `cache:`). */
prefix?: string
/** Optional cache name for reporters. */
name?: string
}
/**
* Build a cachified `Cache` backed by this package's `packageStorage()`.
* Use for Worker-side / package-export caching (not browser IndexedDB).
*
* @example
* import { createPackageStorageCache } from 'kody:@kentcdodds/package-app-kit/server-cache'
* const cache = createPackageStorageCache({ prefix: 'status:' })
*/
export function createPackageStorageCache(
options: PackageStorageCacheOptions = {},
): Cache {
const prefix = options.prefix ?? 'cache:'
const name = options.name ?? 'packageStorage'
return {
name,
async get(key) {
const raw = await packageStorage().get(prefix + key)
if (raw == null) return null
if (typeof raw === 'string') {
try {
return JSON.parse(raw) as CacheEntry
} catch {
return null
}
}
if (typeof raw === 'object') return raw as CacheEntry
return null
},
async set(key, value) {
await packageStorage().set(prefix + key, value)
},
async delete(key) {
await packageStorage().delete(prefix + key)
},
}
}
export type CreateServerCachifiedInput<Value> = {
key: string
getFreshValue: () => Promise<Value> | Value
ttl?: number
swr?: number
cache?: Cache
prefix?: string
}
/**
* One-shot cachified call using a packageStorage-backed cache.
* Prefer `createPackageStorageCache` + `cachified` when sharing one cache across keys.
*
* @example
* import { serverCachified } from 'kody:@kentcdodds/package-app-kit/server-cache'
* const status = await serverCachified({
* key: 'court-status',
* ttl: 15_000,
* getFreshValue: async () => ({ ok: true }),
* })
*/
export async function serverCachified<Value>(
input: CreateServerCachifiedInput<Value>,
): Promise<Value> {
const cache = input.cache ?? createPackageStorageCache({ prefix: input.prefix })
return await cachified({
key: input.key,
cache,
ttl: input.ttl ?? 60_000,
swr: input.swr ?? 0,
getFreshValue: input.getFreshValue,
})
}
/**
* Factory that binds a shared packageStorage cache for repeated cachified calls.
*
* @example
* import { createServerCachified } from 'kody:@kentcdodds/package-app-kit/server-cache'
* const cached = createServerCachified({ prefix: 'api:' })
* const value = await cached({ key: 'hello', ttl: 10_000, getFreshValue: async () => 'hi' })
*/
export function createServerCachified(options: PackageStorageCacheOptions = {}) {
const cache = createPackageStorageCache(options)
return async function run<Value>(input: {
key: string
getFreshValue: () => Promise<Value> | Value
ttl?: number
swr?: number
}): Promise<Value> {
return await serverCachified({ ...input, cache })
}
}
/**
* Server-cache helpers overview.
*
*/
/** Primary callable export for this subpath. */
export default serverCachified