import { FabCache , FabCacheValue } from '@fab/core' ; import NodeCache from 'node-cache' ; import Stream from 'stream' ; import { HybridReadableStream as _HRS } from '@fab/sandbox-node-vm' ; const HybridReadableStream = _HRS ; export class Cache implements FabCache { private cache : NodeCache ; constructor ( ) { this . cache = new NodeCache ( ) ; } async set ( key , value , ttl_seconds ? ) { this . cache . set ( key , await this . readAllIfStream ( value ) , ttl_seconds || 0 ) ; } async setJSON ( key , value , ttl_seconds ? ) { await this . set ( key , JSON . stringify ( value ) , ttl_seconds ) ; } async get ( key ) { return this . cache . get < string > ( key ) ; } async getJSON ( key ) { const val = await this . get ( key ) ; return val && JSON . parse ( val ) ; } async getArrayBuffer ( key ) { return this . cache . get < ArrayBuffer > ( key ) ; } async getNumber ( key ) { return this . cache . get < number > ( key ) ; } async getStream ( key ) { const buffer = this . cache . get < Buffer > ( key ) ; if ( ! buffer ) return undefined ; return new HybridReadableStream ( { async pull ( controller ) { controller . enqueue ( buffer ) ; controller . close ( ) ; } , } ) ; } private async readAllIfStream ( value ) { if ( typeof ( value as ReadableStream ) . getReader === 'function' ) { const reader = ( value as ReadableStream < string > ) . getReader ( ) ; let chunk = await reader . read ( ) ; let buffer = Buffer . from ( [ ] ) ; const enc = new TextEncoder ( ) ; while ( ! chunk . done ) { buffer = Buffer . concat ( [ buffer , enc . encode ( chunk . value ) ] ) ; chunk = await reader . read ( ) ; } return buffer ; } else if ( value instanceof Stream ) { const chunks = [ ] ; return await new Promise ( ( resolve , reject ) => { value . on ( 'data' , ( chunk ) => chunks . push ( chunk ) ) ; value . on ( 'error' , reject ) ; value . on ( 'end' , ( ) => resolve ( Buffer . concat ( chunks ) ) ) ; } ) ; } return value ; } }