UNPKG

@dwn-protocol/id-sdk

Version:

SDK for accessing the features and capabilities

82 lines (64 loc) 2.2 kB
import type { DidResolutionResult, DidResolverCache } from './types.js'; import ms from 'ms'; import { Level } from 'level'; export type DidResolverCacheOptions = { location?: string; ttl?: string; } type CacheWrapper = { ttlMillis: number; value: DidResolutionResult; } /** * Naive level-based cache for did resolution results. It just so happens that level aggressively keeps as much as it * can in memory when possible while also writing to the filesystem (in node runtime) and indexedDB (in browser runtime). * the persistent aspect is especially useful across page refreshes. */ export class DidResolverCacheLevel implements DidResolverCache { private cache: Level<string, string>; private ttl: number; private static defaultOptions: Required<DidResolverCacheOptions> = { location : 'data/AGENT/DID_RESOLVERCACHE', ttl : '15m' }; constructor(options: DidResolverCacheOptions = {}) { let { location, ttl } = options; location ??= DidResolverCacheLevel.defaultOptions.location; ttl ??= DidResolverCacheLevel.defaultOptions.ttl; this.cache = new Level(location); this.ttl = ms(ttl); } async get(did: string): Promise<DidResolutionResult | void> { try { const str = await this.cache.get(did); const cacheWrapper: CacheWrapper = JSON.parse(str); if (Date.now() >= cacheWrapper.ttlMillis) { // defer deletion to be called in the next tick of the js event loop this.cache.nextTick(() => this.cache.del(did)); return; } else { return cacheWrapper.value; } } catch(error: any) { // Don't throw when a key wasn't found. if (error.code === 'LEVEL_NOT_FOUND') { return; } throw error; } } set(did: string, value: DidResolutionResult): Promise<void> { const cacheWrapper: CacheWrapper = { ttlMillis: Date.now() + this.ttl, value }; const str = JSON.stringify(cacheWrapper); return this.cache.put(did, str); } delete(did: string): Promise<void> { return this.cache.del(did); } clear(): Promise<void> { return this.cache.clear(); } close(): Promise<void> { return this.cache.close(); } }