2018-03-09 22:59:12 +02:00
const RNFS = require ( 'react-native-fs' ) ;
const FsDriverBase = require ( 'lib/fs-driver-base' ) ;
2020-01-08 20:57:40 +02:00
const RNFetchBlob = require ( 'rn-fetch-blob' ) . default ;
2017-12-12 01:52:42 +02:00
2018-02-25 23:08:32 +02:00
class FsDriverRN extends FsDriverBase {
2019-09-13 00:16:42 +02:00
appendFileSync ( ) {
2018-03-09 22:59:12 +02:00
throw new Error ( 'Not implemented' ) ;
2017-12-12 01:52:42 +02:00
}
2020-01-08 20:57:40 +02:00
// Encoding can be either "utf8" or "base64"
appendFile ( path , content , encoding = 'base64' ) {
return RNFS . appendFile ( path , content , encoding ) ;
2017-12-12 01:52:42 +02:00
}
2020-01-08 20:57:40 +02:00
// Encoding can be either "utf8" or "base64"
writeFile ( path , content , encoding = 'base64' ) {
// We need to use rn-fetch-blob here due to this bug:
// https://github.com/itinance/react-native-fs/issues/700
return RNFetchBlob . fs . writeFile ( path , content , encoding ) ;
2018-01-17 20:51:15 +02:00
}
2018-01-25 23:15:58 +02:00
// same as rm -rf
async remove ( path ) {
2018-03-18 01:00:01 +02:00
return await this . unlink ( path ) ;
2018-01-25 23:15:58 +02:00
}
2019-09-13 00:16:42 +02:00
writeBinaryFile ( ) {
2018-03-09 22:59:12 +02:00
throw new Error ( 'Not implemented' ) ;
2017-12-12 01:52:42 +02:00
}
2018-01-17 23:01:41 +02:00
// Returns a format compatible with Node.js format
rnfsStatToStd _ ( stat , path ) {
return {
birthtime : stat . ctime ? stat . ctime : stat . mtime , // Confusingly, "ctime" normally means "change time" but here it's used as "creation time". Also sometimes it is null
mtime : stat . mtime ,
isDirectory : ( ) => stat . isDirectory ( ) ,
path : path ,
size : stat . size ,
2019-07-29 15:43:53 +02:00
} ;
2018-01-17 23:01:41 +02:00
}
2018-02-25 23:08:32 +02:00
async readDirStats ( path , options = null ) {
if ( ! options ) options = { } ;
2018-03-09 22:59:12 +02:00
if ( ! ( 'recursive' in options ) ) options . recursive = false ;
2019-07-29 15:43:53 +02:00
2019-12-29 19:58:40 +02:00
let items = [ ] ;
try {
items = await RNFS . readDir ( path ) ;
} catch ( error ) {
throw new Error ( ` Could not read directory: ${ path } : ${ error . message } ` ) ;
}
2018-01-17 23:01:41 +02:00
let output = [ ] ;
for ( let i = 0 ; i < items . length ; i ++ ) {
const item = items [ i ] ;
const relativePath = item . path . substr ( path . length + 1 ) ;
output . push ( this . rnfsStatToStd _ ( item , relativePath ) ) ;
2018-02-25 23:08:32 +02:00
output = await this . readDirStatsHandleRecursion _ ( path , item , output , options ) ;
2018-01-17 23:01:41 +02:00
}
return output ;
}
2017-12-28 21:57:21 +02:00
async move ( source , dest ) {
return RNFS . moveFile ( source , dest ) ;
}
async exists ( path ) {
return RNFS . exists ( path ) ;
2017-12-19 21:01:29 +02:00
}
2018-01-17 20:51:15 +02:00
async mkdir ( path ) {
2018-01-17 23:01:41 +02:00
return RNFS . mkdir ( path ) ;
2018-01-17 20:51:15 +02:00
}
async stat ( path ) {
2018-01-17 23:01:41 +02:00
try {
const r = await RNFS . stat ( path ) ;
return this . rnfsStatToStd _ ( r , path ) ;
} catch ( error ) {
2018-03-09 22:59:12 +02:00
if ( error && ( ( error . message && error . message . indexOf ( 'exist' ) >= 0 ) || error . code === 'ENOENT' ) ) {
2018-01-17 23:01:41 +02:00
// Probably { [Error: File does not exist] framesToPop: 1, code: 'EUNSPECIFIED' }
// which unfortunately does not have a proper error code. Can be ignored.
return null ;
} else {
throw error ;
}
}
2018-01-17 20:51:15 +02:00
}
2018-01-17 23:01:41 +02:00
// NOTE: DOES NOT WORK - no error is thrown and the function is called with the right
// arguments but the function returns `false` and the timestamp is not set.
// Current setTimestamp is not really used so keep it that way, but careful if it
// becomes needed.
2019-09-13 00:16:42 +02:00
async setTimestamp ( ) {
2018-01-17 23:01:41 +02:00
// return RNFS.touch(path, timestampDate, timestampDate);
2018-01-17 20:51:15 +02:00
}
2017-12-12 01:52:42 +02:00
async open ( path , mode ) {
// Note: RNFS.read() doesn't provide any way to know if the end of file has been reached.
// So instead we stat the file here and use stat.size to manually check for end of file.
// Bug: https://github.com/itinance/react-native-fs/issues/342
2018-01-17 20:51:15 +02:00
const stat = await this . stat ( path ) ;
2017-12-12 01:52:42 +02:00
return {
path : path ,
offset : 0 ,
mode : mode ,
stat : stat ,
2019-07-29 15:43:53 +02:00
} ;
2017-12-12 01:52:42 +02:00
}
2019-09-13 00:16:42 +02:00
close ( ) {
2017-12-12 01:52:42 +02:00
return null ;
}
2018-03-09 22:59:12 +02:00
readFile ( path , encoding = 'utf8' ) {
if ( encoding === 'Buffer' ) throw new Error ( 'Raw buffer output not supported for FsDriverRN.readFile' ) ;
2018-01-17 20:51:15 +02:00
return RNFS . readFile ( path , encoding ) ;
}
// Always overwrite destination
async copy ( source , dest ) {
let retry = false ;
try {
await RNFS . copyFile ( source , dest ) ;
} catch ( error ) {
// On iOS it will throw an error if the file already exist
retry = true ;
await this . unlink ( dest ) ;
}
if ( retry ) await RNFS . copyFile ( source , dest ) ;
2017-12-12 01:52:42 +02:00
}
async unlink ( path ) {
try {
await RNFS . unlink ( path ) ;
} catch ( error ) {
2018-03-09 22:59:12 +02:00
if ( error && ( ( error . message && error . message . indexOf ( 'exist' ) >= 0 ) || error . code === 'ENOENT' ) ) {
2017-12-12 01:52:42 +02:00
// Probably { [Error: File does not exist] framesToPop: 1, code: 'EUNSPECIFIED' }
// which unfortunately does not have a proper error code. Can be ignored.
} else {
throw error ;
}
}
}
2018-03-09 22:59:12 +02:00
async readFileChunk ( handle , length , encoding = 'base64' ) {
2017-12-12 01:52:42 +02:00
if ( handle . offset + length > handle . stat . size ) {
length = handle . stat . size - handle . offset ;
}
if ( ! length ) return null ;
2020-03-14 01:46:14 +02:00
const output = await RNFS . read ( handle . path , length , handle . offset , encoding ) ;
2019-07-30 09:35:42 +02:00
// eslint-disable-next-line require-atomic-updates
2017-12-12 01:52:42 +02:00
handle . offset += length ;
return output ? output : null ;
}
}
2019-07-29 15:43:53 +02:00
module . exports . FsDriverRN = FsDriverRN ;