import { Serializable , AsBytes } from "./encoding" ; import { SimpleContainer } from "./container" ; import { VaultID } from "./vault" ; import { AESKeyParams } from "./crypto" ; import { getCryptoProvider as getProvider } from "./platform" ; import { Err , ErrorCode } from "./error" ; import { RequestProgress } from "./transport" ; function readFile ( blob ) { return new Promise ( ( resolve , reject ) => { const reader = new FileReader ( ) ; reader . onload = ( ) => { const result = new Uint8Array ( reader . result as ArrayBuffer ) ; resolve ( result ) ; } ; reader . onerror = e => { reader . abort ( ) ; reject ( e ) ; } ; reader . readAsArrayBuffer ( blob ) ; } ) ; } function readAsText ( blob ) { return new Promise ( ( resolve , reject ) => { const reader = new FileReader ( ) ; reader . onload = ( ) => { resolve ( reader . result as string ) ; } ; reader . onerror = e => { reader . abort ( ) ; reject ( e ) ; } ; reader . readAsText ( blob ) ; } ) ; } function readFileAsDataURL ( blob ) { return new Promise ( ( resolve , reject ) => { const reader = new FileReader ( ) ; reader . onload = ( ) => { resolve ( reader . result as string ) ; } ; reader . onerror = e => { reader . abort ( ) ; reject ( e ) ; } ; reader . readAsDataURL ( blob ) ; } ) ; } export type AttachmentID = string ; export class AttachmentInfo extends Serializable { constructor ( vals = { } ) { super ( ) ; Object . assign ( this , vals ) ; } id : AttachmentID = "" ; vault : VaultID = "" ; name : string = "" ; size : number = 0 ; type : string = "" ; @ AsBytes ( ) key ! : Uint8Array ; } export class Attachment extends SimpleContainer { id : AttachmentID = "" ; vault : VaultID = "" ; name : string = "" ; size : number = 0 ; type : string = "" ; uploadProgress ? : RequestProgress ; downloadProgress ? : RequestProgress ; constructor ( { key , ... info } = { } ) { super ( ) ; Object . assign ( this , { _key : key , ... info } ) ; } get info ( ) : AttachmentInfo { return new AttachmentInfo ( { id : this . id , vault : this . vault , name : this . name , type : this . type , size : this . size , key : this . _key } ) ; } get loaded ( ) : boolean { return ! ! this . encryptedData ; } async fromFile ( file ) { this . type = file . type ; this . size = file . size ; this . name = file . name ; const data = await readFile ( file ) ; this . _key = await getProvider ( ) . generateKey ( { algorithm : "AES" , keySize : this . encryptionParams . keySize } as AESKeyParams ) ; await this . setData ( data ) ; return this ; } async toFile ( ) { const data = await this . getData ( ) ; return new File ( [ data ] , this . name , { type : this . type } ) ; } async toDataURL ( ) { const file = await this . toFile ( ) ; return readFileAsDataURL ( file ) ; } async toObjectURL ( ) { const file = await this . toFile ( ) ; return URL . createObjectURL ( file ) ; } async toText ( ) { const file = await this . toFile ( ) ; return readAsText ( file ) ; } validate ( ) { return typeof this . id === "string" && typeof this . vault === "string" && typeof this . size === "number" ; } } export interface AttachmentStorage { put ( a ) : Promise < void > ; get ( vault , id ) : Promise < Attachment > ; delete ( vault , id ) : Promise < void > ; deleteAll ( vault ) : Promise < void > ; getUsage ( vault ) : Promise < number > ; } export class MemoryAttachmentStorage implements AttachmentStorage { private _storage = new Map < string , Attachment > ( ) ; async put ( a ) { this . _storage . set ( `${ a . vault }_${ a . id }` , a ) ; } async get ( vault , id ) { const att = this . _storage . get ( `${ vault }_${ id }` ) ; if ( ! att ) { throw new Err ( ErrorCode . NOT_FOUND ) ; } return att ; } async delete ( vault , id ) { this . _storage . delete ( `${ vault }_${ id }` ) ; } async deleteAll ( vault ) { for ( const key of this . _storage . keys ( ) ) { if ( key . startsWith ( vault ) ) { this . _storage . delete ( key ) ; } } } async getUsage ( vault ) { let size = 0 ; for ( const [ key , att ] of this . _storage . entries ( ) ) { if ( key . startsWith ( vault ) ) { size += att . size ; } } return size ; } }