UNPKG

expo-file-system

Version:

Provides access to the local file system on the device.

213 lines (188 loc) 7.13 kB
import ExpoFileSystem from './ExpoFileSystem'; import type { DownloadOptions, PathInfo } from './ExpoFileSystem.types'; import { PathUtilities } from './pathUtilities'; import { FileSystemReadableStreamSource, FileSystemWritableSink } from './streams'; export class Paths extends PathUtilities { /** * A property containing the cache directory – a place to store files that can be deleted by the system when the device runs low on storage. */ static get cache() { return new Directory(ExpoFileSystem.cacheDirectory); } /** * A property containing the bundle directory – the directory where assets bundled with the application are stored. */ static get bundle() { return new Directory(ExpoFileSystem.bundleDirectory); } /** * A property containing the document directory – a place to store files that are safe from being deleted by the system. */ static get document() { return new Directory(ExpoFileSystem.documentDirectory); } static get appleSharedContainers() { const containers: Record<string, string> = ExpoFileSystem.appleSharedContainers ?? {}; const result: Record<string, Directory> = {}; for (const appGroupId in containers) { if (containers[appGroupId]) { result[appGroupId] = new Directory(containers[appGroupId]); } } return result; } /** * A property that represents the total space on device's internal storage, represented in bytes. */ static get totalDiskSpace() { return ExpoFileSystem.totalDiskSpace; } /** * A property that represents the available space on device's internal storage, represented in bytes. */ static get availableDiskSpace() { return ExpoFileSystem.availableDiskSpace; } /** * Returns an object that indicates if the specified path represents a directory. */ static info(...uris: string[]): PathInfo { return ExpoFileSystem.info(uris.join('/')); } } /** * Represents a file on the filesystem. * * A `File` instance can be created for any path, and does not need to exist on the filesystem during creation. * * The constructor accepts an array of strings that are joined to create the file URI. The first argument can also be a `Directory` instance (like `Paths.cache`) or a `File` instance (which creates a new reference to the same file). * @example * ```ts * const file = new File(File.cache, "subdirName", "file.txt"); * ``` */ export class File extends ExpoFileSystem.FileSystemFile implements Blob { /** * Creates an instance of a file. It can be created for any path, and does not need to exist on the filesystem during creation. * * The constructor accepts an array of strings that are joined to create the file URI. The first argument can also be a `Directory` instance (like `Paths.cache`) or a `File` instance (which creates a new reference to the same file). * @param uris An array of: `file:///` string URIs, `File` instances, and `Directory` instances representing an arbitrary location on the file system. * @example * ```ts * const file = new File(File.cache, "subdirName", "file.txt"); * ``` */ constructor(...uris: (string | File | Directory)[]) { super(Paths.join(...uris)); this.validatePath(); } /* * Directory containing the file. */ get parentDirectory() { return new Directory(Paths.dirname(this.uri)); } /** * File extension. * @example '.png' */ get extension() { return Paths.extname(this.uri); } /** * File name. Includes the extension. */ get name() { return Paths.basename(this.uri); } readableStream() { return new ReadableStream(new FileSystemReadableStreamSource(super.open())); } writableStream() { return new WritableStream<Uint8Array>(new FileSystemWritableSink(super.open())); } async arrayBuffer(): Promise<ArrayBuffer> { const bytes = await this.bytes(); return bytes.buffer as ArrayBuffer; } stream(): ReadableStream<Uint8Array<ArrayBuffer>> { return this.readableStream(); } slice(start?: number, end?: number, contentType?: string): Blob { return new Blob([this.bytesSync().slice(start, end)], { type: contentType }); } } // Cannot use `static` keyword in class declaration because of a runtime error. File.downloadFileAsync = async function downloadFileAsync( url: string, to: File | Directory, options?: DownloadOptions ) { const outputURI = await ExpoFileSystem.downloadFileAsync(url, to, options); return new File(outputURI); }; File.pickFileAsync = async function (initialUri?: string, mimeType?: string) { const file = (await ExpoFileSystem.pickFileAsync(initialUri, mimeType)).uri; return new File(file); }; /** * Represents a directory on the filesystem. * * A `Directory` instance can be created for any path, and does not need to exist on the filesystem during creation. * * The constructor accepts an array of strings that are joined to create the directory URI. The first argument can also be a `Directory` instance (like `Paths.cache`). * @example * ```ts * const directory = new Directory(File.cache, "subdirName"); * ``` */ export class Directory extends ExpoFileSystem.FileSystemDirectory { /** * Creates an instance of a directory. It can be created for any path, and does not need to exist on the filesystem during creation. * * The constructor accepts an array of strings that are joined to create the directory URI. The first argument can also be a `Directory` instance (like `Paths.cache`). * @param uris An array of: `file:///` string URIs, `File` instances, and `Directory` instances representing an arbitrary location on the file system. * @example * ```ts * const directory = new Directory(File.cache, "subdirName"); * ``` */ constructor(...uris: (string | File | Directory)[]) { super(Paths.join(...uris)); this.validatePath(); } /* * Directory containing the file. */ get parentDirectory() { return new Directory(Paths.join(this.uri, '..')); } /** * Lists the contents of a directory. * Calling this method if the parent directory does not exist will throw an error. * @returns An array of `Directory` and `File` instances. */ override list(): (Directory | File)[] { // We need to wrap it in the JS File/Directory classes, and returning SharedObjects in lists is not supported yet on Android. return super .listAsRecords() .map(({ isDirectory, uri }) => (isDirectory ? new Directory(uri) : new File(uri))); } /** * Directory name. */ get name() { return Paths.basename(this.uri); } createFile(name: string, mimeType: string | null): File { // Wrapping with the JS child class for additional, JS-only methods. return new File(super.createFile(name, mimeType).uri); } createDirectory(name: string): Directory { return new Directory(super.createDirectory(name).uri); } } Directory.pickDirectoryAsync = async function (initialUri?: string) { const directory = (await ExpoFileSystem.pickDirectoryAsync(initialUri)).uri; return new Directory(directory); };