import { Cache } from './Cache' import { Collection } from '../collection/Collection' import {Awaitable, Maybe} from '../support/types' import {ErrorWithContext} from '../error/ErrorWithContext' /** * Base interface for an item stored in a memory cache. */ export interface InMemCacheItem { key: string, item: string, } /** * A cache implementation stored in memory. * @extends Cache */ export class InMemCache extends Cache { /** * The stored cache items. * @type Collection */ protected items: Collection = new Collection() public async fetch(key: string): Promise { const item = this.items.firstWhere('key', '=', key) if ( item ) { return item.item } } public async put(key: string, item: string): Promise { const existing = this.items.firstWhere('key', '=', key) if ( existing ) { existing.item = item } else { this.items.push({ key, item }) } } public async has(key: string): Promise { return this.items.where('key', '=', key).length > 0 } public async drop(key: string): Promise { this.items = this.items.whereNot('key', '=', key) } public pop(key: string): Awaitable> { const existing = this.items.firstWhere('key', '=', key) this.items = this.items.where('key', '!=', key) return existing?.item } public async increment(key: string, amount?: number): Promise { const next = parseInt((await this.fetch(key)) ?? '0', 10) + (amount ?? 1) await this.put(key, String(next)) return next } public async decrement(key: string, amount?: number): Promise { const next = parseInt((await this.fetch(key)) ?? '0', 10) - (amount ?? 1) await this.put(key, String(next)) return next } public arrayPush(key: string, value: string): Awaitable { const existing = this.items.where('key', '=', key).first() const arr = JSON.parse(existing?.item ?? '[]') if ( !Array.isArray(arr) ) { throw new ErrorWithContext('Unable to arrayPush: key is not an array', { key, value, }) } arr.push(value) if ( existing ) { existing.item = JSON.stringify(arr) } else { this.items.push({ key, item: JSON.stringify(arr), }) } } public arrayPop(key: string): Awaitable> { const existing = this.items.where('key', '=', key).first() const arr = JSON.parse(existing?.item ?? '[]') const value = arr.pop() if ( existing ) { existing.item = JSON.stringify(arr) } else { this.items.push({ key, item: JSON.stringify(arr), }) } return value } }