/**
 * Datastore just in memory with no on disk persistence.
 */ import { AbstractDatastore , AbstractPrefsProvider , Datastore , DatastoreCapabilities , DatastoreOverview , DefaultWriteFileOpts , DeleteResult , DocMetaSnapshotEventListener , ErrorListener , FileMeta , PrefsProvider , SnapshotResult , WriteFileOpts , WriteOpts } from './Datastore' ; import { isPresent , Preconditions } from 'polar-shared/src/Preconditions' ; import { DocMetaFileRef , DocMetaRef } from './DocMetaRef' ; import { Logger } from 'polar-shared/src/logger/Logger' ; import { FileHandle , Files } from 'polar-shared/src/util/Files' ; import { Backend } from 'polar-shared/src/datastore/Backend' ; import { DocFileMeta } from 'polar-shared/src/datastore/DocFileMeta' ; import { Optional } from 'polar-shared/src/util/ts/Optional' ; import { DefaultDatastoreMutation } from './DatastoreMutation' ; import { Datastores } from './Datastores' ; import { NULL_FUNCTION } from 'polar-shared/src/util/Functions' ; import { DiskInitResult } from './DiskDatastore' ; import { ISODateTimeString , ISODateTimeStrings } from 'polar-shared/src/metadata/ISODateTimeStrings' ; import { NonPersistentPrefs , IPersistentPrefs } from '../util/prefs/Prefs' ; import { IDocInfo } from "polar-shared/src/metadata/IDocInfo" ; import { FileRef } from "polar-shared/src/datastore/FileRef" ; import { NetworkLayer } from "polar-shared/src/datastore/IDatastore" ; const log = Logger . create ( ) ; export class MemoryDatastore extends AbstractDatastore implements Datastore { public readonly id = 'memory' ; private readonly created : ISODateTimeString ; protected readonly docMetas : { [ fingerprint ] : string ; } = { } ; protected readonly files : { [ key ] : FileData ; } = { } ; private readonly prefs = new NonPersistentPrefs ( ) ; constructor ( ) { super ( ) ; this . docMetas = { } ; this . created = ISODateTimeStrings . create ( ) ; } public async init ( errorListener = NULL_FUNCTION ) { return { } ; } public async stop ( ) { } public async contains ( fingerprint ) { return fingerprint in this . docMetas ; } public async delete ( docMetaFileRef ) { const result = { docMetaFile : { path : `/${ docMetaFileRef . fingerprint }.json` , deleted : false } , dataFile : { path : '/' + Optional . of ( docMetaFileRef . docFile ) . map ( current => current . name ) . getOrUndefined ( ) , deleted : false } } ; if ( await this . contains ( docMetaFileRef . fingerprint ) ) { result . docMetaFile . deleted = true ; result . dataFile . deleted = true ; } return result ; } public async writeFile ( backend , ref , data , opts = new DefaultWriteFileOpts ( ) ) { const key = MemoryDatastore . toFileRefKey ( backend , ref ) ; let buff ; if ( typeof data === 'string' ) { buff = Buffer . from ( data ) ; } else if ( data instanceof Buffer ) { buff = data ; } else { buff = await Files . readFileAsync ( data . path ) ; } const meta = opts . meta || { } ; this . files [ key ] = { buffer : buff ! , meta } ; return { backend , ref , url : 'NOT_IMPLEMENTED:none' } ; } public getFile ( backend , ref ) { const key = MemoryDatastore . toFileRefKey ( backend , ref ) ; if ( ! key ) { throw new Error ( `No file for ${ backend } at ${ ref . name }` ) ; } const fileData = this . files [ key ] ; return { backend , ref , url : 'NOT_IMPLEMENTED:none' } ; } public async containsFile ( backend , ref ) { const key = MemoryDatastore . toFileRefKey ( backend , ref ) ; return isPresent ( this . files [ key ] ) ; } public async deleteFile ( backend , ref ) { const key = MemoryDatastore . toFileRefKey ( backend , ref ) ; delete this . files [ key ] ; } /**
     */ public async getDocMeta ( fingerprint ) { const nrDocs = Object . keys ( this . docMetas ) . length ; log . info ( `Fetching document from datastore with fingerprint ${ fingerprint } of ${ nrDocs } docs.` ) ; return this . docMetas [ fingerprint ] ; } /**
     * Write the datastore to disk.
     */ public async write ( fingerprint , data , docInfo , opts = { } ) { const datastoreMutation = opts . datastoreMutation || new DefaultDatastoreMutation ( ) ; Preconditions . assertTypeOf ( data , "string" , "data" ) ; this . docMetas [ fingerprint ] = data ; datastoreMutation . written . resolve ( true ) ; datastoreMutation . committed . resolve ( true ) ; } public async getDocMetaRefs ( ) { return Object . keys ( this . docMetas ) . map ( fingerprint => < DocMetaRef > { fingerprint } ) ; } public async snapshot ( listener ) { return Datastores . createCommittedSnapshot ( this , listener ) ; } public addDocMetaSnapshotEventListener ( docMetaSnapshotEventListener ) { } public async overview ( ) { const docMetaRefs = await this . getDocMetaRefs ( ) ; return { nrDocs : docMetaRefs . length , created : this . created } ; } public capabilities ( ) { const networkLayers = new Set < NetworkLayer > ( [ 'local' ] ) ; return { networkLayers , permission : { mode : 'rw' } } ; } private static toFileRefKey ( backend , fileRef ) { return `${ backend }:${ fileRef . name }` ; } public getPrefs ( ) { class PrefsProviderImpl extends AbstractPrefsProvider { constructor ( private readonly prefs ) { super ( ) ; } public get ( ) { return this . prefs ; } } return new PrefsProviderImpl ( this . prefs ) ; } } interface FileData { buffer : Buffer ; meta : FileMeta ; }