import buildDebug from 'debug' ; import { fs } from 'memfs' ; import { VerdaccioError , errorUtils } from '@verdaccio/core' ; import { ReadTarball , UploadTarball } from '@verdaccio/streams' ; import { CallbackAction , IPackageStorageManager , IReadTarball , IUploadTarball , Logger , Package , PackageTransformer , ReadPackageCallback , StorageUpdateCallback , StorageWriteCallback , } from '@verdaccio/types' ; import { parsePackage , stringifyPackage } from './utils' ; const debug = buildDebug ( 'verdaccio:plugin:storage:memory-storage' ) ; export type DataHandler = { [ key ] : string ; } ; class MemoryHandler implements IPackageStorageManager { private data : DataHandler ; private name : string ; private path : string ; public logger : Logger ; public constructor ( packageName , data , logger ) { this . data = data ; this . name = packageName ; this . logger = logger ; this . path = '/' ; debug ( 'initialized' ) ; } public updatePackage ( pkgFileName , updateHandler , onWrite , transformPackage , onEnd ) { const json = this . _getStorage ( pkgFileName ) ; let pkg ; try { pkg = parsePackage ( json ) as Package ; } catch ( err ) { return onEnd ( err ) ; } updateHandler ( pkg , ( err ) => { if ( err ) { return onEnd ( err ) ; } try { onWrite ( pkgFileName , transformPackage ( pkg ) , onEnd ) ; } catch ( err ) { return onEnd ( errorUtils . getInternalError ( 'error on parse the metadata' ) ) ; } } ) ; } public deletePackage ( pkgName ) { delete this . data [ pkgName ] ; return Promise . resolve ( ) ; } public removePackage ( ) { return Promise . resolve ( ) ; } public createPackage ( name , value , cb ) { debug ( 'create package %o' , name ) ; this . savePackage ( name , value , cb ) ; } public savePackage ( name , value , cb ) { try { debug ( 'save package %o' , name ) ; this . data [ name ] = stringifyPackage ( value ) ; return cb ( null ) ; } catch ( err ) { return cb ( errorUtils . getInternalError ( err . message ) ) ; } } public async readPackageNext ( name ) { const json = this . _getStorage ( name ) ; try { return typeof json === 'undefined' ? errorUtils . getNotFound ( ) : null , parsePackage ( json ) ; } catch ( err ) { throw errorUtils . getNotFound ( ) ; } } public readPackage ( name , cb ) { debug ( 'read package %o' , name ) ; const json = this . _getStorage ( name ) ; const isJson = typeof json === 'undefined' ; try { return cb ( isJson ? errorUtils . getNotFound ( ) : null , parsePackage ( json ) ) ; } catch ( err ) { return cb ( errorUtils . getNotFound ( ) ) ; } } public writeTarball ( name ) { debug ( 'write tarball %o' , name ) ; const uploadStream = new UploadTarball ( { } ) ; const temporalName = `/${ name }` ; process . nextTick ( function ( ) { fs . stat ( temporalName , function ( fileError , stats ) { if ( ! fileError && stats ) { return uploadStream . emit ( 'error' , errorUtils . getConflict ( ) ) ; } try { const file = fs . createWriteStream ( temporalName ) ; uploadStream . pipe ( file ) ; uploadStream . done = function ( ) : void { const onEnd = function ( ) : void { uploadStream . emit ( 'success' ) ; } ; uploadStream . on ( 'end' , onEnd ) ; } ; uploadStream . abort = function ( ) : void { uploadStream . emit ( 'error' , errorUtils . getBadRequest ( 'transmision aborted' ) ) ; file . end ( ) ; } ; uploadStream . emit ( 'open' ) ; return ; } catch ( err ) { uploadStream . emit ( 'error' , err ) ; return ; } } ) ; } ) ; return uploadStream ; } public readTarball ( name ) { const pathName = `/${ name }` ; debug ( 'read tarball %o' , name ) ; const readTarballStream = new ReadTarball ( { } ) ; process . nextTick ( function ( ) { fs . stat ( pathName , function ( error , stats ) { if ( error && ! stats ) { return readTarballStream . emit ( 'error' , errorUtils . getNotFound ( ) ) ; } try { const readStream = fs . createReadStream ( pathName ) ; readTarballStream . emit ( 'content-length' , stats ?. size ) ; readTarballStream . emit ( 'open' ) ; readStream . pipe ( readTarballStream ) ; readStream . on ( 'error' , ( error ) => { readTarballStream . emit ( 'error' , error ) ; } ) ; readTarballStream . abort = function ( ) : void { readStream . destroy ( errorUtils . getBadRequest ( 'read has been aborted' ) ) ; } ; return ; } catch ( err ) { readTarballStream . emit ( 'error' , err ) ; return ; } } ) ; } ) ; return readTarballStream ; } private _getStorage ( name = '' ) { debug ( 'get storage %o' , name ) ; return this . data [ name ] ; } } export default MemoryHandler ;