import * as fs from 'fs' ; import pathModule from 'path' ; import globby from 'globby' ; import { PathAbs , Storage , StorageOptions } from './Storage' ; import { FilesTransform } from './utils' ; import { Readable } from 'stream' ; import { ListResult } from './Files' ; export interface LocalStorageOptions extends StorageOptions { path : string ; } export class LocalStorage extends Storage < LocalStorageOptions > { constructor ( options ) { super ( options ) ; this . initialize ( ) ; } async initialize ( ) { const [ , folder ] = await Promise . all ( [ fs . promises . access ( this . options . path , fs . constants . F_OK | fs . constants . R_OK | fs . constants . W_OK ) , fs . promises . lstat ( this . options . path ) ] ) ; if ( ! folder . isDirectory ( ) ) throw new Error ( 'Path is not a directory' ) ; } async terminate ( ) { } @ PathAbs ( ) async getTopLevel ( path ? ) { const fullPath = this . fullPath ( path ) ; const files = await globby ( `${ fullPath }/*` , { onlyFiles : false , onlyDirectories : false , objectMode : true } ) ; const rootPath = pathModule . resolve ( this . fullPath ( ) ) ; const formatPath = ( path ) => pathModule . resolve ( path ) . replace ( `${ rootPath }/` , '' ) ; return files . map ( f => ( { path : formatPath ( f . path ) , name : pathModule . basename ( f . path ) , raw : f , isFile : f . dirent . isFile ( ) } ) ) ; } @ PathAbs ( ) getFilesStream ( path ? ) { const fullPath = this . fullPath ( path ) ; const rootPath = pathModule . resolve ( this . fullPath ( ) ) ; const formatPath = ( path ) => pathModule . resolve ( path ) . replace ( `${ rootPath }/` , '' ) ; const trans = new FilesTransform ( ( f ) => ( { name : pathModule . basename ( f . path ) , path : formatPath ( f . path ) , size : f . stats . size , raw : f } ) ) ; return globby . stream ( `${ fullPath }/**/*` , { objectMode : true , onlyFiles : true , stats : true } ) . pipe ( trans ) ; } @ PathAbs ( ) async getFileSize ( filePath ) { const stat = await fs . promises . stat ( this . fullPath ( filePath ) ) ; return stat . size ; } @ PathAbs ( ) async readFile ( filePath ) { const fullPath = this . fullPath ( filePath ) ; return fs . promises . readFile ( fullPath ) ; } @ PathAbs ( ) async writeFile ( filePath , data ) { await this . makeDir ( filePath ) ; const fullPath = this . fullPath ( filePath ) ; await fs . promises . writeFile ( fullPath , data ) ; } @ PathAbs ( ) async deleteFile ( filePath ) { await fs . promises . unlink ( this . fullPath ( filePath ) ) ; } @ PathAbs ( ) async makeDir ( path ) { const dir = pathModule . dirname ( path ) ; await fs . promises . mkdir ( this . fullPath ( dir ) , { recursive : true } ) ; } @ PathAbs ( ) async createWriteStream ( path ) { await this . makeDir ( path ) ; return fs . createWriteStream ( this . fullPath ( path ) ) ; } @ PathAbs ( ) async createReadStream ( path , options ? ) { return fs . createReadStream ( this . fullPath ( path ) , options ) ; } @ PathAbs ( ) fullPath ( path ? ) { return path ? pathModule . join ( this . options . path , path ) : this . options . path ; } }