opfs-worker
Version:
A robust TypeScript library for working with Origin Private File System (OPFS) through Web Workers
487 lines • 18.9 kB
TypeScript
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