OPFS Project
A Rust library for managing npm-style projects on the Origin Private File System (OPFS) in WebAssembly. Provides lazy tgz extraction via fuse links, a content-addressable store, and zero-copy file reads.
Features
- Struct-based API — all state owned by
OpfsProject(config, caches, store) - Fuse links —
fuse.linkfiles mapnode_modules/<pkg>/to tgz entries in the store, enabling lazy on-demand extraction - Zero-copy reads — decompressed tar kept as a single
Bytesbuffer; individual files served viaBytes::slice()(no per-file allocations) - O(1) lookups —
is_dir,get_file,list_dirall backed byHashMap/HashSet - LRU cache — configurable budget for decompressed tar data with automatic eviction
- In-flight dedup — concurrent reads of the same tgz only decompress once
- Content-addressable store — tgz files stored by integrity hash (SHA-512 / SHA-1)
- Async I/O — all file operations are async via
tokio-fs-ext - Lazy / non-lazy tgz mode — configurable via
Config::lazy_tgz
Architecture
OpfsProject
├── Config — store root, cache budgets, lazy_tgz toggle
├── FuseFs — fuse-link resolution + tar index
│ ├── link_cache — PathBuf → Arc<FuseLink> (LRU)
│ └── tar_index — PathBuf → TgzEntry (LRU, zero-copy Bytes)
└── Store — download, verify (sha512/sha1), save tgz
Read path (lazy_tgz = true, default)
read("node_modules/pkg/index.js")
→ locate_fuse_link_file() zero-alloc path walk
→ read_fuse_link() cache hit: Arc::clone (no IO)
→ extract_file()
1. tar_index.get_file() O(1), Bytes::slice(), zero IO
2. ensure_tgz_cached() decompress tgz on first access
Read path (lazy_tgz = false)
read("node_modules/pkg/index.js")
→ locate_fuse_link_file() zero-alloc path walk
→ read_fuse_link() cache hit: Arc::clone (no IO)
→ tokio_fs_ext::read(dir/relative) plain filesystem read
Usage
use ;
// Lazy mode (default) — reads from in-memory tar index
let project = default;
// Non-lazy mode — extracts tgz to real files during install
let project = new;
// Fuse-aware reads (transparent tgz extraction under node_modules)
let content = project.read.await?;
let entries = project.read_dir.await?;
// Install from package-lock.json
use PackageLock;
let lock = from_json?;
project.install.await?;
Configuration
| Field | Default | Description |
|---|---|---|
store_root |
/stores |
Root directory for tgz store |
tar_cache_max_bytes |
100 MB | In-memory tar index budget |
fuse_cache_max_entries |
10,000 | Fuse-link path cache capacity |
max_concurrent_downloads |
20 | Parallel HTTP downloads |
download_retries |
3 | Retry count for failed downloads |
retry_base_delay_ms |
500 | Exponential backoff base delay |
lazy_tgz |
true |
true: read from in-memory tar index; false: extract to disk during install |
Testing
# native tests
# wasm tests (requires chromedriver)
CHROMEDRIVER=
# interactive wasm tests
License
MIT