UNPKG

opfs-worker

Version:

A robust TypeScript library for working with Origin Private File System (OPFS) through Web Workers

487 lines 18.9 kB
import type { DirentData, Encoding, FileStat, OPFSOptions, RenameOptions, WatchOptions } from './types'; import type { BufferEncoding } from 'typescript'; /** * OPFS (Origin Private File System) File System implementation * * This class provides a high-level interface for working with the browser's * Origin Private File System API, offering file and directory operations * similar to Node.js fs module. * * @example * ```typescript * const fs = new OPFSFileSystem(); * await fs.init('/my-app'); * await fs.writeFile('/data/config.json', JSON.stringify({ theme: 'dark' })); * const config = await fs.readFile('/data/config.json'); * ``` */ export declare class OPFSWorker { /** Root directory handle for the file system */ private root; /** Map of watched paths and options */ private watchers; /** Promise to prevent concurrent mount operations */ private mountingPromise; /** BroadcastChannel instance for sending events */ private broadcastChannel; /** Configuration options */ private options; /** * Notify about internal changes to the file system * * This method is called by internal operations to notify clients about * changes, even when no specific paths are being watched. * * @param path - The path that was changed * @param type - The type of change (create, change, delete) */ private notifyChange; /** * Creates a new OPFSFileSystem instance * * @param options - Optional configuration options * @param options.root - Root path for the file system (default: '/') * @param options.watchInterval - Polling interval in milliseconds for file watching * @param options.hashAlgorithm - Hash algorithm for file hashing * @param options.maxFileSize - Maximum file size for hashing in bytes (default: 50MB) * @throws {OPFSError} If OPFS is not supported in the current browser */ constructor(options?: OPFSOptions); /** * Initialize the file system within a given directory * * This method sets up the root directory for all subsequent operations. * If no root is specified, it will use the OPFS root directory. * * @param root - The root path for the file system (default: '/') * @returns Promise that resolves to true if initialization was successful * @throws {OPFSError} If initialization fails * * @example * ```typescript * const fs = new OPFSFileSystem(); * * // Use OPFS root (default) * await fs.mount(); * * // Use custom directory * await fs.mount('/my-app'); * ``` */ private mount; /** * Update configuration options * * @param options - Configuration options to update * @param options.root - Root path for the file system * @param options.watchInterval - Polling interval in milliseconds for file watching * @param options.hashAlgorithm - Hash algorithm for file hashing * @param options.maxFileSize - Maximum file size for hashing in bytes * @param options.broadcastChannel - Custom name for the broadcast channel */ setOptions(options: OPFSOptions): Promise<void>; /** * Get a directory handle from a path * * Navigates through the directory structure to find or create a directory * at the specified path. * * @param path - The path to the directory (string or array of segments) * @param create - Whether to create the directory if it doesn't exist (default: false) * @param from - The directory to start from (default: root directory) * @returns Promise that resolves to the directory handle * @throws {OPFSError} If the directory cannot be accessed or created * * @example * ```typescript * const docsDir = await fs.getDirectoryHandle('/users/john/documents', true); * const docsDir2 = await fs.getDirectoryHandle(['users', 'john', 'documents'], true); * ``` */ private getDirectoryHandle; /** * Get a file handle from a path * * Navigates to the parent directory and retrieves or creates a file handle * for the specified file path. * * @param path - The path to the file (string or array of segments) * @param create - Whether to create the file if it doesn't exist (default: false) * @param from - The directory to start from (default: root directory) * @returns Promise that resolves to the file handle * @throws {PathError} If the path is empty * @throws {OPFSError} If the file cannot be accessed or created * * @example * ```typescript * const fileHandle = await fs.getFileHandle('/config/settings.json', true); * const fileHandle2 = await fs.getFileHandle(['config', 'settings.json'], true); * ``` */ private getFileHandle; /** * Get a complete index of all files and directories in the file system * * This method recursively traverses the entire file system and returns * a Map containing FileStat objects for every file and directory. * * @returns Promise that resolves to a Map of paths to FileStat objects * @throws {OPFSError} If the file system is not mounted * * @example * ```typescript * const index = await fs.index(); * const fileStats = index.get('/data/config.json'); * if (fileStats) { * console.log(`File size: ${fileStats.size} bytes`); * if (fileStats.hash) console.log(`Hash: ${fileStats.hash}`); * } * ``` */ index(): Promise<Map<string, FileStat>>; /** * Read a file from the file system * * Reads the contents of a file and returns it as a string or binary data * depending on the specified encoding. * * @param path - The path to the file to read * @param encoding - The encoding to use for reading the file * @returns Promise that resolves to the file contents * @throws {FileNotFoundError} If the file does not exist * @throws {OPFSError} If reading the file fails * * @example * ```typescript * // Read as text * const content = await fs.readFile('/config/settings.json'); * * // Read as binary * const binaryData = await fs.readFile('/images/logo.png', 'binary'); * * // Read with specific encoding * const utf8Content = await fs.readFile('/data/utf8.txt', 'utf-8'); * ``` */ readFile(path: string, encoding: 'binary'): Promise<Uint8Array>; readFile(path: string, encoding: Encoding): Promise<string>; readFile(path: string, encoding: Encoding | 'binary'): Promise<string | Uint8Array>; /** * Write data to a file * * Creates or overwrites a file with the specified data. If the file already * exists, it will be truncated before writing. * * @param path - The path to the file to write * @param data - The data to write to the file (string, Uint8Array, or ArrayBuffer) * @param encoding - The encoding to use when writing string data (default: 'utf-8') * @returns Promise that resolves when the write operation is complete * @throws {OPFSError} If writing the file fails * * @example * ```typescript * // Write text data * await fs.writeFile('/config/settings.json', JSON.stringify({ theme: 'dark' })); * * // Write binary data * const binaryData = new Uint8Array([1, 2, 3, 4, 5]); * await fs.writeFile('/data/binary.dat', binaryData); * * // Write with specific encoding * await fs.writeFile('/data/utf16.txt', 'Hello World', 'utf-16le'); * ``` */ writeFile(path: string, data: string | Uint8Array | ArrayBuffer, encoding?: BufferEncoding): Promise<void>; /** * Append data to a file * * Adds data to the end of an existing file. If the file doesn't exist, * it will be created. * * @param path - The path to the file to append to * @param data - The data to append to the file (string, Uint8Array, or ArrayBuffer) * @param encoding - The encoding to use when appending string data (default: 'utf-8') * @returns Promise that resolves when the append operation is complete * @throws {OPFSError} If appending to the file fails * * @example * ```typescript * // Append text to a log file * await fs.appendFile('/logs/app.log', `[${new Date().toISOString()}] User logged in\n`); * * // Append binary data * const additionalData = new Uint8Array([6, 7, 8]); * await fs.appendFile('/data/binary.dat', additionalData); * ``` */ appendFile(path: string, data: string | Uint8Array | ArrayBuffer, encoding?: BufferEncoding): Promise<void>; /** * Create a directory * * Creates a new directory at the specified path. If the recursive option * is enabled, parent directories will be created as needed. * * @param path - The path where the directory should be created * @param options - Options for directory creation * @param options.recursive - Whether to create parent directories if they don't exist (default: false) * @returns Promise that resolves when the directory is created * @throws {OPFSError} If the directory cannot be created * * @example * ```typescript * // Create a single directory * await fs.mkdir('/users/john'); * * // Create nested directories * await fs.mkdir('/users/john/documents/projects', { recursive: true }); * ``` */ mkdir(path: string, options?: { recursive?: boolean; }): Promise<void>; /** * Get file or directory statistics * * Returns detailed information about a file or directory, including * size, modification time, and optionally a hash of the file content. * * @param path - The path to the file or directory * @returns Promise that resolves to FileStat object * @throws {OPFSError} If the path does not exist or cannot be accessed * * @example * ```typescript * const stats = await fs.stat('/data/config.json'); * console.log(`File size: ${stats.size} bytes`); * console.log(`Last modified: ${stats.mtime}`); * * // If hashing is enabled, hash will be included * if (stats.hash) { * console.log(`Hash: ${stats.hash}`); * } * ``` */ stat(path: string): Promise<FileStat>; /** * Read a directory's contents * * Lists all files and subdirectories within the specified directory. * * @param path - The path to the directory to read * @returns Promise that resolves to an array of detailed file/directory information * @throws {OPFSError} If the directory does not exist or cannot be accessed * * @example * ```typescript * // Get detailed information about files and directories * const detailed = await fs.readDir('/users/john/documents'); * detailed.forEach(item => { * console.log(`${item.name} - ${item.isFile ? 'file' : 'directory'}`); * }); * ``` */ readDir(path: string): Promise<DirentData[]>; /** * Check if a file or directory exists * * Verifies if a file or directory exists at the specified path. * * @param path - The path to check * @returns Promise that resolves to true if the file or directory exists, false otherwise * * @example * ```typescript * const exists = await fs.exists('/config/settings.json'); * console.log(`File exists: ${exists}`); * ``` */ exists(path: string): Promise<boolean>; /** * Clear all contents of a directory without removing the directory itself * * Removes all files and subdirectories within the specified directory, * but keeps the directory itself. * * @param path - The path to the directory to clear (default: '/') * @returns Promise that resolves when all contents are removed * @throws {OPFSError} If the operation fails * * @example * ```typescript * // Clear root directory contents * await fs.clear('/'); * * // Clear specific directory contents * await fs.clear('/data'); * ``` */ clear(path?: string): Promise<void>; /** * Remove files and directories * * Removes files and directories. Similar to Node.js fs.rm(). * * @param path - The path to remove * @param options - Options for removal * @param options.recursive - Whether to remove directories and their contents recursively (default: false) * @param options.force - Whether to ignore errors if the path doesn't exist (default: false) * @returns Promise that resolves when the removal is complete * @throws {OPFSError} If the removal fails * * @example * ```typescript * // Remove a file * await fs.rm('/path/to/file.txt'); * * // Remove a directory and all its contents * await fs.rm('/path/to/directory', { recursive: true }); * * // Remove with force (ignore if doesn't exist) * await fs.rm('/maybe/exists', { force: true }); * ``` */ remove(path: string, options?: { recursive?: boolean; force?: boolean; }): Promise<void>; /** * Resolve a path to an absolute path * * Resolves relative paths and normalizes path segments (like '..' and '.'). * Similar to Node.js fs.realpath() but without symlink resolution since OPFS doesn't support symlinks. * * @param path - The path to resolve * @returns Promise that resolves to the absolute normalized path * @throws {FileNotFoundError} If the path does not exist * @throws {OPFSError} If path resolution fails * * @example * ```typescript * // Resolve relative path * const absolute = await fs.realpath('./config/../data/file.txt'); * console.log(absolute); // '/data/file.txt' * ``` */ realpath(path: string): Promise<string>; /** * Rename a file or directory * * Changes the name of a file or directory. If the target path already exists, * it will be replaced only if overwrite option is enabled. * * @param oldPath - The current path of the file or directory * @param newPath - The new path for the file or directory * @param options - Options for renaming * @param options.overwrite - Whether to overwrite existing files (default: false) * @returns Promise that resolves when the rename operation is complete * @throws {OPFSError} If the rename operation fails * * @example * ```typescript * // Basic rename (fails if target exists) * await fs.rename('/old/path/file.txt', '/new/path/renamed.txt'); * * // Rename with overwrite * await fs.rename('/old/path/file.txt', '/new/path/renamed.txt', { overwrite: true }); * ``` */ rename(oldPath: string, newPath: string, options?: RenameOptions): Promise<void>; /** * Copy files and directories * * Copies files and directories. Similar to Node.js fs.cp(). * * @param source - The source path to copy from * @param destination - The destination path to copy to * @param options - Options for copying * @param options.recursive - Whether to copy directories recursively (default: false) * @param options.overwrite - Whether to overwrite existing files (default: true) * @returns Promise that resolves when the copy operation is complete * @throws {OPFSError} If the copy operation fails * * @example * ```typescript * // Copy a file * await fs.copy('/source/file.txt', '/dest/file.txt'); * * // Copy a directory and all its contents * await fs.copy('/source/dir', '/dest/dir', { recursive: true }); * * // Copy without overwriting existing files * await fs.copy('/source', '/dest', { recursive: true, overwrite: false }); * ``` */ copy(source: string, destination: string, options?: { recursive?: boolean; overwrite?: boolean; }): Promise<void>; /** * Start watching a file or directory for changes * * @param path - The path to watch (minimatch syntax allowed) * @param options - Watch options * @param options.recursive - Whether to watch recursively (default: true) * @param options.exclude - Glob pattern(s) to exclude (minimatch). * @returns Promise that resolves when watching starts * * @example * ```typescript * // Watch entire directory tree recursively (default) * await fs.watch('/data'); * * // Watch only immediate children (shallow) * await fs.watch('/data', { recursive: false }); * * // Watch a single file * await fs.watch('/config.json', { recursive: false }); * * // Watch all json files but not in dist directory * await fs.watch('/**\/*.json', { recursive: false, exclude: ['dist/**'] }); * * ``` */ watch(path: string, options?: WatchOptions): Promise<void>; /** * Stop watching a previously watched path */ unwatch(path: string): void; /** * Dispose of resources and clean up the file system instance * * This method should be called when the file system instance is no longer needed * to properly clean up resources like the broadcast channel and watch timers. */ dispose(): void; /** * Synchronize the file system with external data * * Syncs the file system with an array of entries containing paths and data. * This is useful for importing data from external sources or syncing with remote data. * * @param entries - Array of [path, data] tuples to sync * @param options - Options for synchronization * @param options.cleanBefore - Whether to clear the file system before syncing (default: false) * @returns Promise that resolves when synchronization is complete * @throws {OPFSError} If the synchronization fails * * @example * ```typescript * // Sync with external data * const entries: [string, string | Uint8Array | Blob][] = [ * ['/config.json', JSON.stringify({ theme: 'dark' })], * ['/data/binary.dat', new Uint8Array([1, 2, 3, 4])], * ['/upload.txt', new Blob(['file content'], { type: 'text/plain' })] * ]; * * // Sync without clearing existing files * await fs.sync(entries); * * // Clean file system and then sync * await fs.sync(entries, { cleanBefore: true }); * ``` */ sync(entries: [string, string | Uint8Array | Blob][], options?: { cleanBefore?: boolean; }): Promise<void>; } //# sourceMappingURL=worker.d.ts.map