73 lines
1.5 KiB
TypeScript
73 lines
1.5 KiB
TypeScript
import type { IKey } from '../types'
|
|
import hash from '../lib/hash'
|
|
export interface ICacheItem<Data> {
|
|
data: Data,
|
|
createdAt: number,
|
|
expiresAt: number
|
|
}
|
|
|
|
function serializeKeyDefault (key: IKey): string {
|
|
if (typeof key === 'function') {
|
|
try {
|
|
key = key()
|
|
} catch (err) {
|
|
// dependencies not ready
|
|
key = ''
|
|
}
|
|
}
|
|
|
|
if (Array.isArray(key)) {
|
|
key = hash(key)
|
|
} else {
|
|
// convert null to ''
|
|
key = String(key || '')
|
|
}
|
|
|
|
return key
|
|
}
|
|
|
|
export default class SWRVCache<CacheData> {
|
|
protected ttl: number
|
|
private items?: Map<string, ICacheItem<CacheData>>
|
|
|
|
constructor (ttl = 0) {
|
|
this.items = new Map()
|
|
this.ttl = ttl
|
|
}
|
|
|
|
serializeKey (key: IKey): string {
|
|
return serializeKeyDefault(key)
|
|
}
|
|
|
|
get (k: string): ICacheItem<CacheData> {
|
|
const _key = this.serializeKey(k)
|
|
return this.items!.get(_key)!
|
|
}
|
|
|
|
set (k: string, v: any, ttl: number) {
|
|
const _key = this.serializeKey(k)
|
|
const timeToLive = ttl || this.ttl
|
|
const now = Date.now()
|
|
const item = {
|
|
data: v,
|
|
createdAt: now,
|
|
expiresAt: timeToLive ? now + timeToLive : Infinity
|
|
}
|
|
|
|
this.dispatchExpire(timeToLive, item, _key)
|
|
this.items!.set(_key, item)
|
|
}
|
|
|
|
dispatchExpire (ttl: number, item: any, serializedKey: string) {
|
|
ttl && setTimeout(() => {
|
|
const current = Date.now()
|
|
const hasExpired = current >= item.expiresAt
|
|
if (hasExpired) this.delete(serializedKey)
|
|
}, ttl)
|
|
}
|
|
|
|
delete (serializedKey: string) {
|
|
this.items!.delete(serializedKey)
|
|
}
|
|
}
|