fs-browser-side
v2.0.1
Published
NodeJS-like FileSystem API for the browser, built on the File System Access API
Maintainers
Readme
Fs Browser Side
Overview
Fs Browser Side is a TypeScript library that brings Node.js FileSystem (fs) capabilities into the client-side environment, built on top of the File System Access API. It provides a clean, promise-based interface for managing files and directories within the browser.
Features
- Promise-first API — All methods return
Promiseby default, with optional error-first callbacks. - Stateless path resolution — No mutable internal state; concurrent operations are safe.
- Robust path handling — Proper normalization with
.,.., and//support. - Idiomatic errors —
FsErrorextendsErrorwith typed error codes. - AsyncGenerator for recursive reads —
readdirRecursiveyields entries lazily viafor await...of. - Two access modes — User-picked directory (
showDirectoryPicker) or OPFS (navigator.storage).
Installation
pnpm add fs-browser-sideQuick Start
import { FsBrowserSide } from 'fs-browser-side';
const fs = new FsBrowserSide();
// Request access to a user-selected directory
if (await fs.getAccess()) {
// Create nested directories
await fs.mkdir('/project/src', { recursive: true });
// Write a text file
await fs.writeFileText('/project/src/index.ts', 'console.log("hello");');
// Read it back
const content = await fs.readFileText('/project/src/index.ts');
console.log(content); // 'console.log("hello");'
// List directory contents
const entries = await fs.readdir('/project/src');
console.log(entries);
// [{ name: 'index.ts', type: 'file', path: '/project/src/index.ts' }]
}OPFS Mode (Origin Private File System)
const fs = new FsBrowserSide({ navigatorMode: true });
await fs.getAccess(); // No user prompt neededAPI Reference
new FsBrowserSide(options?)
| Option | Type | Default | Description |
|---|---|---|---|
| navigatorMode | boolean | false | Use OPFS instead of showDirectoryPicker |
getAccess(): Promise<boolean>
Request file system access. Returns true on success.
readFile(path): Promise<ArrayBuffer>
Read a file as an ArrayBuffer.
readFileText(path): Promise<string>
Read a file as a UTF-8 string.
writeFile(path, data, options?): Promise<void>
Write binary data to a file. Creates the file and parent directories if needed.
| Option | Type | Default | Description |
|---|---|---|---|
| append | boolean | false | Append to existing content |
writeFileText(path, data, options?): Promise<void>
Write a string to a file. Same options as writeFile.
exists(path): Promise<boolean>
Check if a file or directory exists at the given path.
mkdir(path, options?): Promise<void>
Create a directory.
| Option | Type | Default | Description |
|---|---|---|---|
| recursive | boolean | false | Create parent directories as needed |
rmdir(path, options?): Promise<void>
Remove a directory. Fails if non-empty unless recursive is true.
| Option | Type | Default | Description |
|---|---|---|---|
| recursive | boolean | false | Remove contents recursively |
rm(path, options?): Promise<void>
Remove a file or directory entry.
| Option | Type | Default | Description |
|---|---|---|---|
| recursive | boolean | false | Remove directory contents recursively |
copyFile(src, dest): Promise<void>
Copy a file from src to dest.
rename(src, dest): Promise<void>
Move/rename a file (copy + remove).
readdir(path): Promise<DirEntry[]>
List entries in a directory. Each DirEntry has name, type ('file' | 'directory'), and path.
readdirRecursive(path): AsyncGenerator<DirEntry>
Recursively yield all entries under a directory:
for await (const entry of fs.readdirRecursive('/')) {
console.log(entry.type, entry.path);
}Callback Style
Every method also accepts an error-first callback as last argument:
fs.readFileText('/file.txt', (err, content) => {
if (err) {
console.error(err.code, err.path);
return;
}
console.log(content);
});Error Handling
All errors are instances of FsError with a typed code:
import { FsError } from 'fs-browser-side';
try {
await fs.readFile('/missing.txt');
} catch (err) {
if (err instanceof FsError) {
console.log(err.code); // 'NOT_FOUND'
console.log(err.path); // '/missing.txt'
}
}| Code | Description |
|---|---|
| NO_ACCESS | File system access not granted |
| NOT_FOUND | Path does not exist |
| ALREADY_EXISTS | Path already exists |
| PERMISSION_DENIED | Insufficient permissions |
| INVALID_PATH | Invalid path (e.g. resolves above root) |
| NOT_A_DIRECTORY | Expected a directory |
| NOT_A_FILE | Expected a file |
| UNKNOWN | Unexpected error |
Path Utilities
import { PathUtils } from 'fs-browser-side';
PathUtils.normalize('//a/./b/../c'); // '/a/c'
PathUtils.dirname('/a/b/c'); // '/a/b'
PathUtils.basename('/a/b/c'); // 'c'
PathUtils.join('/a', 'b', '../c'); // '/a/c'
PathUtils.segments('/a/b/c'); // ['a', 'b', 'c']Compatibility
The library requires browser support for the File System Access API. OPFS mode (navigatorMode: true) has broader compatibility than showDirectoryPicker.
Use Cases
- Browser-Based IDE — Read and write project files directly. Sample
- Custom CMS — Manage content files without a server.
- Offline-first apps — Persistent storage via OPFS.
- Client-side scraping — Save processed data to local files.
- Photo/file organizer — Manage user files in the browser.
License
MIT
