Skip to content

WaRtr0/FsBrowserSide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub GitHub top language GitHub repo size GitHub contributors GitHub repo directory count GitHub last commit (branch) GitHub Repo stars GitHub watchers GitHub followers View counter

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 Promise by 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 errorsFsError extends Error with typed error codes.
  • AsyncGenerator for recursive readsreaddirRecursive yields entries lazily via for await...of.
  • Two access modes — User-picked directory (showDirectoryPicker) or OPFS (navigator.storage).

Installation

pnpm add fs-browser-side

Quick 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 needed

API 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. Demo Github
  • 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.

Contributing

You are completely free to contribute to this project! It would be my pleasure to review and accept your Pull Requests or Issues to improve this package.

License

This project is licensed under the MIT License.

Releases

No releases published

Packages

 
 
 

Contributors