import { Readable } from 'stream' ; import { Config , generateToken } from '@foal/core' ; import { Disk , FileDoesNotExist } from '@foal/storage' ; import * as S3 from 'aws-sdk/clients/s3' ; export class extends Disk export class S3Disk extends Disk { private s3 : S3 ; async write ( dirname , content , options = { } ) { let name = this . hasName ( options ) ? options . name : await generateToken ( ) ; if ( this . hasExtension ( options ) ) { name = `${ name }.${ options . extension }` ; } const path = `${ dirname }/${ name }` ; await this . getS3 ( ) . upload ( { Body : content , Bucket : this . getBucket ( ) , Key : path , } ) . promise ( ) ; return { path } ; } async read < C extends 'buffer' | 'stream' > ( path , content ) { try { if ( content === 'buffer' ) { const { Body , ContentLength } = await this . getS3 ( ) . getObject ( { Bucket : this . getBucket ( ) , Key : path , } ) . promise ( ) ; return { file : Body as any , size : ContentLength as number } ; } const { ContentLength } = await this . getS3 ( ) . headObject ( { Bucket : this . getBucket ( ) , Key : path , } ) . promise ( ) ; const stream = this . getS3 ( ) . getObject ( { Bucket : this . getBucket ( ) , Key : path , } ) . createReadStream ( ) . on ( 'error' , ( ) => { } ) ; return { file : stream as any , size : ContentLength as number } ; } catch ( error ) { if ( error . code === 'NoSuchKey' || error . code === 'NotFound' ) { throw new FileDoesNotExist ( path ) ; } throw error ; } } async readSize ( path ) { try { const { ContentLength } = await this . getS3 ( ) . headObject ( { Bucket : this . getBucket ( ) , Key : path , } ) . promise ( ) ; return ContentLength as number ; } catch ( error ) { if ( error . code === 'NotFound' ) { throw new FileDoesNotExist ( path ) ; } throw error ; } } async delete ( path ) { await this . getS3 ( ) . deleteObject ( { Bucket : this . getBucket ( ) , Key : path } ) . promise ( ) ; } private getBucket ( ) { return Config . getOrThrow ( 'settings.disk.s3.bucket' , 'string' , 'You must provide a bucket name when using AWS S3 file storage (S3Disk).' ) ; } private getS3 ( ) { if ( ! this . s3 ) { this . s3 = new S3 ( { accessKeyId : Config . get ( 'settings.aws.accessKeyId' , 'string' ) , apiVersion : '2006-03-01' , endpoint : Config . get ( 'settings.aws.endpoint' , 'string' ) , secretAccessKey : Config . get ( 'settings.aws.secretAccessKey' , 'string' ) , } ) ; } return this . s3 ; } }