1import { EventEmitter, UnavailabilityError } from 'expo-modules-core'; 2import { Platform } from 'react-native'; 3import { v4 as uuidv4 } from 'uuid'; 4import ExponentFileSystem from './ExponentFileSystem'; 5import { EncodingType, FileSystemSessionType, FileSystemUploadType, } from './FileSystem.types'; 6if (!ExponentFileSystem) { 7 console.warn("No native ExponentFileSystem module found, are you sure the expo-file-system's module is linked properly?"); 8} 9// Prevent webpack from pruning this. 10const _unused = new EventEmitter(ExponentFileSystem); // eslint-disable-line 11export { EncodingType, FileSystemSessionType, FileSystemUploadType, }; 12function normalizeEndingSlash(p) { 13 if (p != null) { 14 return p.replace(/\/*$/, '') + '/'; 15 } 16 return null; 17} 18export const documentDirectory = normalizeEndingSlash(ExponentFileSystem.documentDirectory); 19export const cacheDirectory = normalizeEndingSlash(ExponentFileSystem.cacheDirectory); 20export const { bundledAssets, bundleDirectory } = ExponentFileSystem; 21export async function getInfoAsync(fileUri, options = {}) { 22 if (!ExponentFileSystem.getInfoAsync) { 23 throw new UnavailabilityError('expo-file-system', 'getInfoAsync'); 24 } 25 return await ExponentFileSystem.getInfoAsync(fileUri, options); 26} 27export async function readAsStringAsync(fileUri, options) { 28 if (!ExponentFileSystem.readAsStringAsync) { 29 throw new UnavailabilityError('expo-file-system', 'readAsStringAsync'); 30 } 31 return await ExponentFileSystem.readAsStringAsync(fileUri, options || {}); 32} 33export async function getContentUriAsync(fileUri) { 34 if (Platform.OS === 'android') { 35 if (!ExponentFileSystem.getContentUriAsync) { 36 throw new UnavailabilityError('expo-file-system', 'getContentUriAsync'); 37 } 38 return await ExponentFileSystem.getContentUriAsync(fileUri); 39 } 40 else { 41 return new Promise(function (resolve, reject) { 42 resolve(fileUri); 43 }); 44 } 45} 46export async function writeAsStringAsync(fileUri, contents, options = {}) { 47 if (!ExponentFileSystem.writeAsStringAsync) { 48 throw new UnavailabilityError('expo-file-system', 'writeAsStringAsync'); 49 } 50 return await ExponentFileSystem.writeAsStringAsync(fileUri, contents, options); 51} 52export async function deleteAsync(fileUri, options = {}) { 53 if (!ExponentFileSystem.deleteAsync) { 54 throw new UnavailabilityError('expo-file-system', 'deleteAsync'); 55 } 56 return await ExponentFileSystem.deleteAsync(fileUri, options); 57} 58export async function deleteLegacyDocumentDirectoryAndroid() { 59 if (Platform.OS !== 'android' || documentDirectory == null) { 60 return; 61 } 62 const legacyDocumentDirectory = `${documentDirectory}ExperienceData/`; 63 return await deleteAsync(legacyDocumentDirectory, { idempotent: true }); 64} 65export async function moveAsync(options) { 66 if (!ExponentFileSystem.moveAsync) { 67 throw new UnavailabilityError('expo-file-system', 'moveAsync'); 68 } 69 return await ExponentFileSystem.moveAsync(options); 70} 71export async function copyAsync(options) { 72 if (!ExponentFileSystem.copyAsync) { 73 throw new UnavailabilityError('expo-file-system', 'copyAsync'); 74 } 75 return await ExponentFileSystem.copyAsync(options); 76} 77export async function makeDirectoryAsync(fileUri, options = {}) { 78 if (!ExponentFileSystem.makeDirectoryAsync) { 79 throw new UnavailabilityError('expo-file-system', 'makeDirectoryAsync'); 80 } 81 return await ExponentFileSystem.makeDirectoryAsync(fileUri, options); 82} 83export async function readDirectoryAsync(fileUri) { 84 if (!ExponentFileSystem.readDirectoryAsync) { 85 throw new UnavailabilityError('expo-file-system', 'readDirectoryAsync'); 86 } 87 return await ExponentFileSystem.readDirectoryAsync(fileUri, {}); 88} 89export async function getFreeDiskStorageAsync() { 90 if (!ExponentFileSystem.getFreeDiskStorageAsync) { 91 throw new UnavailabilityError('expo-file-system', 'getFreeDiskStorageAsync'); 92 } 93 return await ExponentFileSystem.getFreeDiskStorageAsync(); 94} 95export async function getTotalDiskCapacityAsync() { 96 if (!ExponentFileSystem.getTotalDiskCapacityAsync) { 97 throw new UnavailabilityError('expo-file-system', 'getTotalDiskCapacityAsync'); 98 } 99 return await ExponentFileSystem.getTotalDiskCapacityAsync(); 100} 101export async function downloadAsync(uri, fileUri, options = {}) { 102 if (!ExponentFileSystem.downloadAsync) { 103 throw new UnavailabilityError('expo-file-system', 'downloadAsync'); 104 } 105 return await ExponentFileSystem.downloadAsync(uri, fileUri, { 106 sessionType: FileSystemSessionType.BACKGROUND, 107 ...options, 108 }); 109} 110export async function uploadAsync(url, fileUri, options = {}) { 111 if (!ExponentFileSystem.uploadAsync) { 112 throw new UnavailabilityError('expo-file-system', 'uploadAsync'); 113 } 114 return await ExponentFileSystem.uploadAsync(url, fileUri, { 115 sessionType: FileSystemSessionType.BACKGROUND, 116 uploadType: FileSystemUploadType.BINARY_CONTENT, 117 ...options, 118 httpMethod: (options.httpMethod || 'POST').toUpperCase(), 119 }); 120} 121export function createDownloadResumable(uri, fileUri, options, callback, resumeData) { 122 return new DownloadResumable(uri, fileUri, options, callback, resumeData); 123} 124export function createUploadTask(url, fileUri, options, callback) { 125 return new UploadTask(url, fileUri, options, callback); 126} 127export class FileSystemCancellableNetworkTask { 128 _uuid = uuidv4(); 129 taskWasCanceled = false; 130 emitter = new EventEmitter(ExponentFileSystem); 131 subscription; 132 async cancelAsync() { 133 if (!ExponentFileSystem.networkTaskCancelAsync) { 134 throw new UnavailabilityError('expo-file-system', 'networkTaskCancelAsync'); 135 } 136 this.removeSubscription(); 137 this.taskWasCanceled = true; 138 return await ExponentFileSystem.networkTaskCancelAsync(this.uuid); 139 } 140 isTaskCancelled() { 141 if (this.taskWasCanceled) { 142 console.warn('This task was already canceled.'); 143 return true; 144 } 145 return false; 146 } 147 get uuid() { 148 return this._uuid; 149 } 150 addSubscription() { 151 if (this.subscription) { 152 return; 153 } 154 this.subscription = this.emitter.addListener(this.getEventName(), (event) => { 155 if (event.uuid === this.uuid) { 156 const callback = this.getCallback(); 157 if (callback) { 158 callback(event.data); 159 } 160 } 161 }); 162 } 163 removeSubscription() { 164 if (!this.subscription) { 165 return; 166 } 167 this.emitter.removeSubscription(this.subscription); 168 this.subscription = null; 169 } 170} 171export class UploadTask extends FileSystemCancellableNetworkTask { 172 url; 173 fileUri; 174 callback; 175 options; 176 constructor(url, fileUri, options, callback) { 177 super(); 178 this.url = url; 179 this.fileUri = fileUri; 180 this.callback = callback; 181 const httpMethod = (options?.httpMethod?.toUpperCase || 182 'POST'); 183 this.options = { 184 sessionType: FileSystemSessionType.BACKGROUND, 185 uploadType: FileSystemUploadType.BINARY_CONTENT, 186 ...options, 187 httpMethod, 188 }; 189 } 190 getEventName() { 191 return 'expo-file-system.uploadProgress'; 192 } 193 getCallback() { 194 return this.callback; 195 } 196 async uploadAsync() { 197 if (!ExponentFileSystem.uploadTaskStartAsync) { 198 throw new UnavailabilityError('expo-file-system', 'uploadTaskStartAsync'); 199 } 200 if (this.isTaskCancelled()) { 201 return; 202 } 203 this.addSubscription(); 204 const result = await ExponentFileSystem.uploadTaskStartAsync(this.url, this.fileUri, this.uuid, this.options); 205 this.removeSubscription(); 206 return result; 207 } 208} 209export class DownloadResumable extends FileSystemCancellableNetworkTask { 210 url; 211 _fileUri; 212 options; 213 callback; 214 resumeData; 215 constructor(url, _fileUri, options = {}, callback, resumeData) { 216 super(); 217 this.url = url; 218 this._fileUri = _fileUri; 219 this.options = options; 220 this.callback = callback; 221 this.resumeData = resumeData; 222 } 223 get fileUri() { 224 return this._fileUri; 225 } 226 getEventName() { 227 return 'expo-file-system.downloadProgress'; 228 } 229 getCallback() { 230 return this.callback; 231 } 232 async downloadAsync() { 233 if (!ExponentFileSystem.downloadResumableStartAsync) { 234 throw new UnavailabilityError('expo-file-system', 'downloadResumableStartAsync'); 235 } 236 if (this.isTaskCancelled()) { 237 return; 238 } 239 this.addSubscription(); 240 return await ExponentFileSystem.downloadResumableStartAsync(this.url, this._fileUri, this.uuid, this.options, this.resumeData); 241 } 242 async pauseAsync() { 243 if (!ExponentFileSystem.downloadResumablePauseAsync) { 244 throw new UnavailabilityError('expo-file-system', 'downloadResumablePauseAsync'); 245 } 246 if (this.isTaskCancelled()) { 247 return { 248 fileUri: this._fileUri, 249 options: this.options, 250 url: this.url, 251 }; 252 } 253 const pauseResult = await ExponentFileSystem.downloadResumablePauseAsync(this.uuid); 254 this.removeSubscription(); 255 if (pauseResult) { 256 this.resumeData = pauseResult.resumeData; 257 return this.savable(); 258 } 259 else { 260 throw new Error('Unable to generate a savable pause state'); 261 } 262 } 263 async resumeAsync() { 264 if (!ExponentFileSystem.downloadResumableStartAsync) { 265 throw new UnavailabilityError('expo-file-system', 'downloadResumableStartAsync'); 266 } 267 if (this.isTaskCancelled()) { 268 return; 269 } 270 this.addSubscription(); 271 return await ExponentFileSystem.downloadResumableStartAsync(this.url, this.fileUri, this.uuid, this.options, this.resumeData); 272 } 273 savable() { 274 return { 275 url: this.url, 276 fileUri: this.fileUri, 277 options: this.options, 278 resumeData: this.resumeData, 279 }; 280 } 281} 282const baseReadAsStringAsync = readAsStringAsync; 283const baseWriteAsStringAsync = writeAsStringAsync; 284const baseDeleteAsync = deleteAsync; 285const baseMoveAsync = moveAsync; 286const baseCopyAsync = copyAsync; 287/** 288 * Android only 289 */ 290export var StorageAccessFramework; 291(function (StorageAccessFramework) { 292 function getUriForDirectoryInRoot(folderName) { 293 return `content://com.android.externalstorage.documents/tree/primary:${folderName}/document/primary:${folderName}`; 294 } 295 StorageAccessFramework.getUriForDirectoryInRoot = getUriForDirectoryInRoot; 296 async function requestDirectoryPermissionsAsync(initialFileUrl = null) { 297 if (!ExponentFileSystem.requestDirectoryPermissionsAsync) { 298 throw new UnavailabilityError('expo-file-system', 'StorageAccessFramework.requestDirectoryPermissionsAsync'); 299 } 300 return await ExponentFileSystem.requestDirectoryPermissionsAsync(initialFileUrl); 301 } 302 StorageAccessFramework.requestDirectoryPermissionsAsync = requestDirectoryPermissionsAsync; 303 async function readDirectoryAsync(dirUri) { 304 if (!ExponentFileSystem.readSAFDirectoryAsync) { 305 throw new UnavailabilityError('expo-file-system', 'StorageAccessFramework.readDirectoryAsync'); 306 } 307 return await ExponentFileSystem.readSAFDirectoryAsync(dirUri, {}); 308 } 309 StorageAccessFramework.readDirectoryAsync = readDirectoryAsync; 310 async function makeDirectoryAsync(parentUri, dirName) { 311 if (!ExponentFileSystem.makeSAFDirectoryAsync) { 312 throw new UnavailabilityError('expo-file-system', 'StorageAccessFramework.makeDirectoryAsync'); 313 } 314 return await ExponentFileSystem.makeSAFDirectoryAsync(parentUri, dirName); 315 } 316 StorageAccessFramework.makeDirectoryAsync = makeDirectoryAsync; 317 async function createFileAsync(parentUri, fileName, mimeType) { 318 if (!ExponentFileSystem.createSAFFileAsync) { 319 throw new UnavailabilityError('expo-file-system', 'StorageAccessFramework.createFileAsync'); 320 } 321 return await ExponentFileSystem.createSAFFileAsync(parentUri, fileName, mimeType); 322 } 323 StorageAccessFramework.createFileAsync = createFileAsync; 324 StorageAccessFramework.writeAsStringAsync = baseWriteAsStringAsync; 325 StorageAccessFramework.readAsStringAsync = baseReadAsStringAsync; 326 StorageAccessFramework.deleteAsync = baseDeleteAsync; 327 StorageAccessFramework.moveAsync = baseMoveAsync; 328 StorageAccessFramework.copyAsync = baseCopyAsync; 329})(StorageAccessFramework || (StorageAccessFramework = {})); 330//# sourceMappingURL=FileSystem.js.map