import { createGunzip } from 'zlib' ; import { createReadStream } from 'fs' ; import { PassThrough , Writable } from 'stream' ; import { Arguments , Capabilities , CodedError , Util } from '@kui-shell/core' ; import { VFS , mount } from '.' ; import { kuiglob , KuiGlobOptions } from '../lib/glob' ; import { fstat , FStat } from '../lib/fstat' ; import { _fwrite } from '../lib/fwrite' ; class LocalVFS implements VFS { public readonly mountPath = '/' ; public readonly isLocal = true ; public readonly isVirtual = false ; public async ls ( opts , filepaths ) { return kuiglob ( this , { tab : opts . tab , argvNoOptions : [ 'kuiglob' , ... filepaths ] , parsedOptions : opts . parsedOptions } ) ; } /** Insert filepath into directory */ public async cp ( opts ) { return opts . REPL . qexec ( `sendtopty ${ opts . command . replace ( /^vfs/ , '' ) }` , undefined , undefined , Object . assign ( opts . execOptions , { quiet : opts . parsedOptions . i ? false : opts . execOptions . quiet } ) ) ; } /** Remove filepath */ public async rm ( opts ) { await opts . REPL . qexec ( `sendtopty ${ opts . command . replace ( /^vfs/ , '' ) }` , undefined , undefined , Object . assign ( opts . execOptions , { quiet : false } ) ) ; return true ; } /** Fetch contents */ public async fstat ( opts , filepath , withData , enoentOk ) { return fstat ( { argvNoOptions : [ 'fstat' , filepath ] , parsedOptions : { 'with-data' : withData , 'enoent-ok' : enoentOk } } ) ; } /** Write data to a files */ public async fwrite ( opts , filepath , data , options = { } ) { return _fwrite ( filepath , data , options ) ; } /** Pipe a content slice to the given `stream` */ public pipe ( filepath , offset , _length , stream ) { const fullpath = Util . expandHomeDir ( filepath ) ; return new Promise ( ( resolve , reject ) => { if ( filepath . endsWith ( '.gz' ) ) { createReadStream ( fullpath , { start : offset , end : _length ? offset + _length - 1 : Infinity } ) . pipe ( createGunzip ( ) ) . pipe ( stream ) . on ( 'error' , ( err ) => { if ( err . code === 'Z_BUF_ERROR' ) { resolve ( ) ; } else { reject ( err ) ; } } ) . on ( 'end' , ( ) => resolve ( ) ) ; } else { createReadStream ( fullpath , { start : offset , end : _length ? offset + _length - 1 : Infinity } ) . pipe ( stream ) . on ( 'error' , reject ) . on ( 'end' , resolve ) ; } } ) ; } /** Fetch content slice */ public async fslice ( filepath , offset , length ) { return new Promise ( async ( resolve , reject ) => { let data = '' ; const passthrough = new PassThrough ( ) ; passthrough . on ( 'error' , reject ) ; passthrough . on ( 'data' , d => ( data += d . toString ( ) ) ) ; try { await this . pipe ( filepath , offset , length , passthrough ) ; resolve ( data ) ; } catch ( err ) { reject ( err ) ; } } ) ; } /** Create a directory/bucket */ public async mkdir ( opts ) { await opts . REPL . qexec ( `sendtopty ${ opts . command . replace ( /^vfs/ , '' ) }` , undefined , undefined , Object . assign ( opts . execOptions , { quiet : false } ) ) ; } /** Remove a directory/bucket */ public async rmdir ( opts ) { await opts . REPL . qexec ( `sendtopty ${ opts . command . replace ( /^vfs/ , '' ) }` , undefined , undefined , Object . assign ( opts . execOptions , { quiet : false } ) ) ; } } export default async ( ) => { if ( ! Capabilities . inBrowser ( ) || Capabilities . hasProxy ( ) ) { mount ( new LocalVFS ( ) ) ; } } ;