opfs-worker 1.3.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/README.md +64 -458
  2. package/dist/BaseOPFS-BPw9AIQ-.cjs +4 -0
  3. package/dist/BaseOPFS-BPw9AIQ-.cjs.map +1 -0
  4. package/dist/BaseOPFS-Cylz6ijk.js +2036 -0
  5. package/dist/BaseOPFS-Cylz6ijk.js.map +1 -0
  6. package/dist/OPFSAsync-BKSAJJeh.js +124 -0
  7. package/dist/OPFSAsync-BKSAJJeh.js.map +1 -0
  8. package/dist/OPFSAsync-s2P7y3sw.cjs +2 -0
  9. package/dist/OPFSAsync-s2P7y3sw.cjs.map +1 -0
  10. package/dist/OPFSFacade-DePnNRgt.cjs +2 -0
  11. package/dist/OPFSFacade-DePnNRgt.cjs.map +1 -0
  12. package/dist/OPFSFacade-XohWlHuu.js +281 -0
  13. package/dist/OPFSFacade-XohWlHuu.js.map +1 -0
  14. package/dist/OPFSSync-C7KBepe_.cjs +2 -0
  15. package/dist/OPFSSync-C7KBepe_.cjs.map +1 -0
  16. package/dist/OPFSSync-CsSQkpk5.js +208 -0
  17. package/dist/OPFSSync-CsSQkpk5.js.map +1 -0
  18. package/dist/assets/dedicated.worker-nY3tK4zi.js.map +1 -0
  19. package/dist/{worker.d.ts → core/BaseOPFS.d.ts} +34 -300
  20. package/dist/core/BaseOPFS.d.ts.map +1 -0
  21. package/dist/core/OPFSAsync.d.ts +55 -0
  22. package/dist/core/OPFSAsync.d.ts.map +1 -0
  23. package/dist/core/OPFSSync.d.ts +54 -0
  24. package/dist/core/OPFSSync.d.ts.map +1 -0
  25. package/dist/createOPFSAsync-BwKDmHsy.cjs +2 -0
  26. package/dist/createOPFSAsync-BwKDmHsy.cjs.map +1 -0
  27. package/dist/createOPFSAsync-Y4Mg6qte.js +10 -0
  28. package/dist/createOPFSAsync-Y4Mg6qte.js.map +1 -0
  29. package/dist/createOPFSDedicated-CsnV6MLP.js +2333 -0
  30. package/dist/createOPFSDedicated-CsnV6MLP.js.map +1 -0
  31. package/dist/createOPFSDedicated-pKTRWLdz.cjs +2283 -0
  32. package/dist/createOPFSDedicated-pKTRWLdz.cjs.map +1 -0
  33. package/dist/createOPFSShared-CGdd__PH.js +23 -0
  34. package/dist/createOPFSShared-CGdd__PH.js.map +1 -0
  35. package/dist/createOPFSShared-CskROt7U.cjs +2 -0
  36. package/dist/createOPFSShared-CskROt7U.cjs.map +1 -0
  37. package/dist/dedicated.worker.js +2281 -0
  38. package/dist/dedicated.worker.js.map +1 -0
  39. package/dist/{facade.d.ts → facade/OPFSFacade.d.ts} +35 -10
  40. package/dist/facade/OPFSFacade.d.ts.map +1 -0
  41. package/dist/facade/createOPFSAsync.d.ts +16 -0
  42. package/dist/facade/createOPFSAsync.d.ts.map +1 -0
  43. package/dist/facade/createOPFSDedicated.d.ts +17 -0
  44. package/dist/facade/createOPFSDedicated.d.ts.map +1 -0
  45. package/dist/facade/createOPFSShared.d.ts +24 -0
  46. package/dist/facade/createOPFSShared.d.ts.map +1 -0
  47. package/dist/index.async.cjs +2 -0
  48. package/dist/index.async.cjs.map +1 -0
  49. package/dist/index.async.d.ts +10 -0
  50. package/dist/index.async.d.ts.map +1 -0
  51. package/dist/index.async.js +55 -0
  52. package/dist/index.async.js.map +1 -0
  53. package/dist/index.cjs +1 -2466
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.d.ts +15 -7
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +61 -2799
  58. package/dist/index.js.map +1 -1
  59. package/dist/index.pure.cjs +2 -0
  60. package/dist/index.pure.cjs.map +1 -0
  61. package/dist/index.pure.d.ts +8 -0
  62. package/dist/index.pure.d.ts.map +1 -0
  63. package/dist/index.pure.js +53 -0
  64. package/dist/index.pure.js.map +1 -0
  65. package/dist/index.sharedworker.cjs +2 -0
  66. package/dist/index.sharedworker.cjs.map +1 -0
  67. package/dist/index.sharedworker.d.ts +11 -0
  68. package/dist/index.sharedworker.d.ts.map +1 -0
  69. package/dist/index.sharedworker.js +55 -0
  70. package/dist/index.sharedworker.js.map +1 -0
  71. package/dist/index.sync.cjs +2 -0
  72. package/dist/index.sync.cjs.map +1 -0
  73. package/dist/index.sync.d.ts +11 -0
  74. package/dist/index.sync.d.ts.map +1 -0
  75. package/dist/index.sync.js +55 -0
  76. package/dist/index.sync.js.map +1 -0
  77. package/dist/shared.worker.js +2166 -0
  78. package/dist/shared.worker.js.map +1 -0
  79. package/dist/types.d.ts +9 -4
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/utils/helpers.d.ts +11 -1
  82. package/dist/utils/helpers.d.ts.map +1 -1
  83. package/dist/worker/createDedicatedWorker.d.ts +30 -0
  84. package/dist/worker/createDedicatedWorker.d.ts.map +1 -0
  85. package/dist/worker/createSharedWorker.d.ts +37 -0
  86. package/dist/worker/createSharedWorker.d.ts.map +1 -0
  87. package/dist/worker/dedicated.worker.d.ts +2 -0
  88. package/dist/worker/dedicated.worker.d.ts.map +1 -0
  89. package/dist/worker/shared.worker.d.ts +2 -0
  90. package/dist/worker/shared.worker.d.ts.map +1 -0
  91. package/docs/README.md +30 -0
  92. package/docs/api/backend.md +36 -0
  93. package/docs/api/create.md +82 -0
  94. package/docs/api/facade.md +52 -0
  95. package/docs/choosing-a-mode.md +41 -0
  96. package/docs/file-descriptors.md +695 -0
  97. package/docs/guides/async.md +36 -0
  98. package/docs/guides/dedicated.md +76 -0
  99. package/docs/guides/hashing.md +34 -0
  100. package/docs/guides/pure.md +46 -0
  101. package/docs/guides/sharedworker.md +57 -0
  102. package/docs/guides/streaming.md +51 -0
  103. package/docs/guides/watching.md +35 -0
  104. package/docs/migration.md +41 -0
  105. package/docs/types.md +246 -0
  106. package/package.json +55 -10
  107. package/src/core/BaseOPFS.ts +951 -0
  108. package/src/core/OPFSAsync.ts +248 -0
  109. package/src/core/OPFSSync.ts +460 -0
  110. package/src/facade/OPFSFacade.ts +489 -0
  111. package/src/facade/createOPFSAsync.ts +22 -0
  112. package/src/facade/createOPFSDedicated.ts +23 -0
  113. package/src/facade/createOPFSShared.ts +30 -0
  114. package/src/index.async.ts +11 -0
  115. package/src/index.pure.ts +8 -0
  116. package/src/index.sharedworker.ts +12 -0
  117. package/src/index.sync.ts +12 -0
  118. package/src/index.ts +44 -0
  119. package/src/types.ts +103 -0
  120. package/src/utils/encoder.ts +205 -0
  121. package/src/utils/errors.ts +297 -0
  122. package/src/utils/helpers.ts +465 -0
  123. package/src/worker/createDedicatedWorker.ts +74 -0
  124. package/src/worker/createSharedWorker.ts +67 -0
  125. package/src/worker/dedicated.worker.ts +13 -0
  126. package/src/worker/shared.worker.ts +17 -0
  127. package/dist/assets/worker-1Wh1cr7P.js.map +0 -1
  128. package/dist/assets/worker-BeJaVyBV.js.map +0 -1
  129. package/dist/assets/worker-DYYLzR1Y.js.map +0 -1
  130. package/dist/facade.d.ts.map +0 -1
  131. package/dist/helpers-BuGfPAg0.js +0 -1439
  132. package/dist/helpers-BuGfPAg0.js.map +0 -1
  133. package/dist/helpers-CF7A2WQG.cjs +0 -4
  134. package/dist/helpers-CF7A2WQG.cjs.map +0 -1
  135. package/dist/helpers-CIiblZ8d.cjs +0 -4
  136. package/dist/helpers-CIiblZ8d.cjs.map +0 -1
  137. package/dist/helpers-CKOebsbw.js +0 -1423
  138. package/dist/helpers-CKOebsbw.js.map +0 -1
  139. package/dist/helpers-Ca2c767K.js +0 -1427
  140. package/dist/helpers-Ca2c767K.js.map +0 -1
  141. package/dist/helpers-Dwc92hv9.cjs +0 -4
  142. package/dist/helpers-Dwc92hv9.cjs.map +0 -1
  143. package/dist/raw.cjs +0 -2
  144. package/dist/raw.cjs.map +0 -1
  145. package/dist/raw.d.ts +0 -13
  146. package/dist/raw.d.ts.map +0 -1
  147. package/dist/raw.js +0 -1001
  148. package/dist/raw.js.map +0 -1
  149. package/dist/worker.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,111 +1,23 @@
1
1
  # OPFS Worker
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/opfs-worker)](https://www.npmjs.com/package/opfs-worker)
3
+ [npm](https://www.npmjs.com/package/opfs-worker)
4
+ [demo](https://kachurun.github.io/opfs-worker/)
4
5
 
5
- A robust TypeScript library for working with Origin Private File System (OPFS) through Web Workers, providing a Node.js-like file system API for browser environments.
6
+ ## What is OPFS?
6
7
 
7
- ## Table of Contents
8
+ OPFS ([Origin Private File System](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system)) is a private file store for your origin. No file picker, no permission prompts. It lives under the usual site quota, and clearing site data wipes it.
8
9
 
9
- - [Features](#features)
10
- - [Installation](#installation)
11
- - [Quick Start](#quick-start)
12
- - [Demo](#demo)
13
- - [API Reference](#api-reference)
14
- - [Types](#types)
15
- - [Browser Support](#browser-support)
16
- - [Development](#development)
17
- - [License](#license)
10
+ This library gives you a real filesystem on top of it — read, write, and watch files with a familiar Node-like API.
18
11
 
19
- ## Features
20
-
21
- ### 🚀 **Performance & Architecture**
22
-
23
- - **Web Worker-based**: Runs in a separate thread, keeping your main thread responsive
24
- - **Zero-copy data transfer**: Efficient binary data handling with Comlink transfer
25
- - **Faster than IndexedDB hacks**: Direct OPFS access without the overhead of database abstractions
26
- - **Efficient file watching**: Real-time change detection with minimatch patterns, no polling delays
27
-
28
- ### 🛠️ **Developer Experience**
29
-
30
- - **Better DX vs File System Access API**: Familiar Node.js-like API instead of complex browser APIs
31
- - **Type-safe**: Full TypeScript support with comprehensive type definitions
32
- - **Comlink-powered**: Seamless RPC communication between main thread and worker
33
-
34
- ### 🌐 **Compatibility & Standards**
35
-
36
- - **Cross-browser compatible**: Works in all modern browsers including Safari, Firefox, Chrome, and Edge
37
- - **OPFS-native**: Built directly on Origin Private File System standards
38
- - **No polyfills needed**: Uses native browser capabilities
39
-
40
- ### 📁 **File System Operations**
41
-
42
- - **Complete API**: `readFile`, `writeFile`, `mkdir`, `remove`, `copy`, `rename`, and more
43
- - **Binary file support**: Handle images, documents, and any binary data seamlessly
44
- - **Hash support**: Built-in file hash calculation (SHA-1, SHA-256, SHA-384, SHA-512)
45
- - **File indexing**: Complete file system indexing with metadata and search
46
-
47
- ### 🔄 **Advanced Features**
48
-
49
- - **Sync operations**: Bulk file synchronization from external data sources
50
- - **Event broadcasting**: Real-time file change notifications via BroadcastChannel
51
- - **Include/exclude filters**: Fine-grained control over file watching patterns
52
- - **Comprehensive error handling**: Detailed error types for better debugging
53
-
54
- ## When to Use
55
-
56
- **Use OPFS Worker when you need a persistent file system directly in the browser with an API almost like Node.js `fs`.** It's faster than IndexedDB for file operations and provides better DX than raw File System Access API.
57
-
58
- Here are the key use cases:
59
-
60
- ### 🚀 **Offline-First Applications**
61
-
62
- - **Progressive Web Apps (PWAs)**: Store user data, cached resources, and app state locally
63
- - **Media applications**: Cache images, videos, and audio files for offline playback
64
- - **Data synchronization**: Local-first data with background sync to remote servers
65
-
66
- ### 💾 **Performance & Caching**
67
-
68
- - **Asset caching**: Store and serve static files (CSS, JS, images) from local storage
69
- - **Database caching**: Cache API responses and database queries locally
70
- - **Session persistence**: Maintain user sessions and preferences across browser restarts
71
- - **Resource preloading**: Preload critical resources for instant access
72
-
73
- ### 🎨 **Editor & IDE Features**
74
-
75
- - **Code editors**: File tree navigation, syntax highlighting, and project management
76
- - **Design tools**: Canvas state persistence, project files, and asset management
77
- - **Document editors**: Rich text, markdown, and collaborative editing with local storage
78
- - **Build tools**: Local development servers, build caches, and project configurations
79
-
80
- ### 🔄 **State Management**
81
-
82
- - **Application state**: Persist complex application state and user preferences
83
- - **Form data**: Auto-save forms and restore user input on page refresh
84
- - **Game state**: Save game progress, levels, and user achievements
85
- - **User preferences**: Settings, themes, and personalized configurations
86
-
87
- ### 📱 **Mobile & Cross-Platform**
88
-
89
- - **Mobile web apps**: Native-like file management on mobile devices
90
- - **Cross-tab synchronization**: Share data between multiple browser tabs
91
- - **Worker-based processing**: Offload file operations to background threads
92
- - **Progressive Web Apps**: Full offline capabilities with file system access
93
-
94
- ### ❌ **When NOT to Use**
95
-
96
- - **Server-side storage**: This is a client-side solution, not a replacement for server storage
97
- - **Cross-origin access**: Files are isolated to the specific domain/origin
98
- - **Large datasets**: OPFS has browser-specific storage limitations:
99
- - **Chrome/Edge**: Up to ~50% of free disk space (check via `navigator.storage.estimate()`)
100
- - **Safari**: Usually 1-2 GB, sometimes less
101
- - **Firefox**: Shared limit with IndexedDB, similar to Chromium
102
-
103
- ### ⚡ **Performance Notes**
104
-
105
- - **Faster than IndexedDB**: Direct file system access without database overhead
106
- - **Slower than native FS**: Browser APIs have performance limitations compared to desktop file systems
107
- - **Worker-based**: File operations run in background threads, keeping main thread responsive
108
- - **Memory efficient**: Files are stored in browser's native file system, not in memory
12
+ - **High-level Node-like API.** `readFile`, `writeFile`, `mkdir`, `stat`, `rename`, `copy`, `readDir` — with encodings, auto-detection by extension, and `string | URL` paths. You write `fs` code, not handle plumbing. → [facade API](docs/api/facade.md)
13
+ - **Low-level positional I/O.** `open` / `read` / `write` at an offset, plus `ftruncate` and `fsync` — enough for random-access formats and databases. → [file descriptors](docs/file-descriptors.md)
14
+ - **Sync API by default.** `createOPFS()` runs sync access handles in a dedicated worker: the fastest path OPFS offers, with file descriptors, and it works in every browser that has OPFS — including older Safari. You don't manage `Worker`, Comlink, or handles yourself. → [dedicated](docs/guides/dedicated.md)
15
+ - **Async API for modern browsers / SharedWorkers.** Uses `createWritable()` — runs on the main thread or inside a SharedWorker, no dedicated worker needed. Safari 26+ for writes. → [async](docs/guides/async.md) · [sharedworker](docs/guides/sharedworker.md)
16
+ - **Any way you want to run it.** Inlined dedicated worker, your own worker file, raw classes inside a worker you control, or one SharedWorker for every tab. Same methods in all of them. → [choosing a mode](docs/choosing-a-mode.md)
17
+ - **Memory-friendly for big files.** Streaming support means you can pull in gigabyte-sized files without blowing RAM — `importStream` writes a `ReadableStream`, `Blob`, or `File` chunk by chunk, with optional progress callbacks. → [streaming](docs/guides/streaming.md)
18
+ - **Cross-tab `watch()`.** Changes broadcast over `BroadcastChannel`, so listeners fire in every context that shares the filesystem. [watching](docs/guides/watching.md)
19
+ - **Built-in file hashing.** `stat()` can carry a cheap etag or a real SHA hash, with a size cap so big files don't get hashed by accident — handy for caching and diffing. → [hashing](docs/guides/hashing.md)
20
+ - **Small and typed.** Full TypeScript types, ESM and CJS, two small runtime deps (`comlink`, `minimatch`) — and the async entry pulls in no worker code at all. → [types](docs/types.md)
109
21
 
110
22
  ## Installation
111
23
 
@@ -113,379 +25,73 @@ Here are the key use cases:
113
25
  npm install opfs-worker
114
26
  ```
115
27
 
116
- **Dependencies:**
117
-
118
- - `comlink` - Required for both modes (automatically included with inline mode)
119
- - A bundler with Web Worker support (Vite, Webpack, Rollup, etc.) - Required for manual worker setup
120
-
121
- ## Quick Start
122
-
123
- This library provides two ways to use OPFS with Web Workers:
124
-
125
- ### Inline Worker (Recommended)
126
-
127
- The easiest way to get started - just import and use:
128
-
129
- ```typescript
130
- import { createWorker } from 'opfs-worker';
131
-
132
- async function basicExample() {
133
- // Create a file system instance with default root path '/'
134
- const fs = await createWorker();
135
-
136
- // Write a file
137
- await fs.writeFile('/config.json', JSON.stringify({ theme: 'dark' }));
138
-
139
- // Read the file back
140
- const config = await fs.readFile('/config.json');
141
- console.log(JSON.parse(config));
142
- }
143
-
144
- // Extended example with all options
145
- async function extendedExample() {
146
- const broadcastChannel = new BroadcastChannel('my-app-events');
147
-
148
- const fs = await createWorker({
149
- root: '/my-app',
150
- namespace: 'my-app:fs',
151
- hashAlgorithm: 'SHA-256',
152
- maxFileSize: 100 * 1024 * 1024, // 100MB
153
- broadcastChannel
154
- });
155
-
156
- // Handle binary files
157
- const imageData = new Uint8Array([58, /* binary data */]);
158
- await fs.writeFile('/image.png', imageData);
159
- const binaryData = await fs.readFile('/image.png', 'binary');
160
-
161
- // Text files are automatically handled
162
- await fs.writeFile('/config.txt', 'Hello, World!');
163
- const textContent = await fs.readFile('/config.txt'); // Returns string
164
-
165
- // Use file watching with BroadcastChannel
166
- await fs.watch('/', {
167
- recursive: true,
168
- include: ['*.json'],
169
- exclude: ['dist/**']
170
- });
171
-
172
- broadcastChannel.onmessage = (event) => {
173
- console.log(`File changed: `, event.data);
174
- };
175
-
176
- // Get file statistics with hashing
177
- const stats = await fs.stat('/image.png');
178
-
179
- console.log(
180
- `File size: ${stats.size} bytes`,
181
- `Hash: ${stats.hash}`
182
- );
183
- }
184
- ```
185
-
186
- > **Note:** File change events are sent via BroadcastChannel. Set the `broadcastChannel` option to customize the channel name, or use the default 'opfs-worker' channel. The watch system only sends events for watched paths, making it efficient and focused.
187
-
188
- ### Manual Worker Setup
189
-
190
- For more control over the worker lifecycle, use the worker directly with your bundler:
191
-
192
- ```typescript
193
- import OPFSWorker from 'opfs-worker/raw?worker';
194
- import { wrap } from 'comlink';
195
-
196
- async function basicExample() {
197
- // Create and wrap the worker with default root path '/'
198
- const worker = wrap(new OPFSWorker());
199
-
200
- // Use the file system
201
- await worker.writeFile('/config.json', JSON.stringify({ theme: 'dark' }));
202
- const config = await worker.readFile('/config.json');
203
- console.log(JSON.parse(config));
204
- }
205
-
206
- // Extended example with all options
207
- async function extendedExample() {
208
- // Create with all available options
209
- const worker = wrap(new OPFSWorker({
210
- root: '/my-app',
211
- namespace: 'my-app:fs',
212
- hashAlgorithm: 'SHA-256',
213
- maxFileSize: 100 * 1024 * 1024, // 100MB
214
- broadcastChannel: 'my-app-events' // You can't pass a BroadcastChannel instance to the worker, so you must use a broadcast channel name here
215
- }));
216
-
217
- // Bulk sync from external data
218
- const entries = [
219
- ['/data/config.json', JSON.stringify({ version: '1.0' })],
220
- ['/data/users.json', JSON.stringify([{ id: 1, name: 'John' }])]
221
- ];
222
- await worker.sync(entries, { cleanBefore: true });
223
-
224
- // Create directories
225
- await worker.mkdir('/data/logs', { recursive: true });
226
-
227
- // Append to log files (worker works with bytes)
228
- const logEntry = new TextEncoder().encode(`${new Date().toISOString()}: App started\n`);
229
- await worker.appendFile('/data/logs/app.log', logEntry);
230
-
231
- // Watch for changes
232
- await worker.watch('/data', { recursive: true });
233
-
234
- const channel = new BroadcastChannel('my-app-events');
235
- channel.onmessage = (event) => {
236
- console.log('File changed:', event.data);
237
- };
238
- }
239
- ```
240
-
241
- **Note:** Manual worker setup requires a bundler that supports Web Workers (like Vite, Webpack, Rollup, etc.) and the `comlink` package for communication between the main thread and worker.
242
-
243
- ### Hash Algorithm Configuration
244
-
245
- The file system supports global hash algorithm configuration. Instead of passing hash options to individual methods, you can set the hash algorithm once and it will be used for all file operations that support hashing.
246
-
247
- ```typescript
248
- import { createWorker } from 'opfs-worker';
249
-
250
- async function hashExample() {
251
- const fs = await createWorker();
252
-
253
- // Enable SHA-256 hashing globally
254
- fs.setOptions({ hashAlgorithm: 'SHA-256' });
255
-
256
- // Write a file
257
- await fs.writeFile('/data.txt', 'Hello World');
258
-
259
- // Get stats - hash will be included automatically
260
- const stats = await fs.stat('/data.txt');
261
- console.log(`Hash: ${stats.hash}`); // SHA-256 hash
262
-
263
- // Get file system index - all files will include hashes
264
- const index = await fs.index();
265
- for (const [path, stat] of index) {
266
- if (stat.isFile && stat.hash) {
267
- console.log(`${path}: ${stat.hash}`);
268
- }
269
- }
270
-
271
- // Watch events will also include hash information
272
- const channel = new BroadcastChannel('opfs-worker');
273
- channel.onmessage = (event) => {
274
- if (event.data.hash) {
275
- console.log(`File ${event.data.path} changed, hash: ${event.data.hash}`);
276
- }
277
- };
278
- }
279
-
280
- // Configure maximum file size for hashing
281
- async function maxFileSizeExample() {
282
- const fs = await createWorker();
283
-
284
- // Set custom maximum file size (100MB instead of default 50MB)
285
- fs.setOptions({
286
- hashAlgorithm: 'SHA-256',
287
- maxFileSize: 100 * 1024 * 1024 // 100MB
288
- });
289
-
290
- // Files up to 100MB will be hashed
291
- // Files larger than this will not have hash information
292
- const stats = await fs.stat('/large-file.dat');
293
- if (stats.hash) {
294
- console.log(`Hash: ${stats.hash}`);
295
- } else {
296
- console.log('File too large for hashing');
297
- }
298
- }
299
- ```
300
-
301
- **Supported Hash Algorithms:**
302
-
303
- - `'SHA-1'` - Fastest, good for general use (default)
304
- - `'SHA-256'` - More secure, widely supported
305
- - `'SHA-384'` - Higher security
306
- - `'SHA-512'` - Highest security
307
- - `null` - Disable hashing for maximum performance
308
-
309
- **Note:** When hashing is enabled, it affects all file operations including `stat()`, `index()`, and watch events. Set to `null` when you don't need hash information to improve performance.
310
-
311
- ### Root Path Configuration
312
-
313
- The file system supports configuring the root path through options. The root path determines where in OPFS the file system's root will be created. All file paths passed to the API are relative to this root path.
28
+ ## Quick start
314
29
 
315
30
  ```typescript
316
- import { createWorker } from 'opfs-worker';
31
+ import { createOPFS } from 'opfs-worker';
317
32
 
318
- async function rootPathExample() {
319
- // Use default root path '/'
320
- const fsDefault = await createWorker();
321
- await fsDefault.writeFile('/config.json', '{}');
322
- // This creates /config.json in OPFS root
33
+ const fs = createOPFS({
34
+ root: '/my-app',
35
+ hashAlgorithm: 'SHA-256'
36
+ });
323
37
 
324
- // Use custom root path
325
- const fsCustom = await createWorker({ root: '/my-app' });
326
- await fsCustom.writeFile('/config.json', '{}');
327
- // This creates /my-app/config.json in OPFS root
38
+ await fs.mkdir('/project');
39
+ await fs.writeFile('/project/hello.txt', 'Hello, OPFS!');
40
+ await fs.rename('/project/hello.txt', '/project/readme.txt');
328
41
 
329
- // Change root path dynamically
330
- await fsCustom.setOptions({ root: '/new-app' });
331
- await fsCustom.writeFile('/config.json', '{}');
332
- // This creates /new-app/config.json in OPFS root
333
- }
42
+ const files = await fs.readDir('/project');
43
+ const text = await fs.readFile('/project/readme.txt'); // 'Hello, OPFS!'
334
44
  ```
335
45
 
336
- **Root Path Behavior:**
337
-
338
- - **Default**: Uses `/` (OPFS root directory)
339
- - **Custom**: Creates a subdirectory within OPFS for isolation
340
- - **Dynamic**: Can be changed at runtime via `setOptions()`
341
- - **Auto-mount**: Automatically mounts to the specified root when needed
342
- - **Path Resolution**: All API paths are relative to the configured root
343
-
344
- ## Demo
345
-
346
- Check out the live demo powered by Vite and hosted on GitHub Pages.
347
-
348
- [Live Demo](https://kachurun.github.io/opfs-worker/)
349
-
350
- ## API Reference
351
-
352
- The complete API reference is available in the [docs/api-reference.md](docs/api-reference.md) file.
353
-
354
- **Additional Documentation:**
355
-
356
- - [File Descriptors Guide](docs/file-descriptors.md) - Comprehensive guide to low-level file I/O operations
357
- - [Types Reference](docs/types.md) - Complete TypeScript type definitions
358
-
359
- ### Quick API Overview
360
-
361
- **Entry Points:**
362
-
363
- - `createWorker(options?)` - Create file system instance with inline worker (recommended)
364
- - `OPFSFileSystem` - High-level facade with automatic encoding detection
365
- - `OPFSWorker` - Direct webworker class
366
-
367
- **Core File Operations:**
368
-
369
- - `readFile(path, encoding?)` - Read files as text or binary with auto-detection
370
- - `writeFile(path, data, encoding?)` - Write text or binary data with auto-detection
371
- - `readText(path, encoding?)` - Read files as text with specified encoding
372
- - `writeText(path, text, encoding?)` - Write text with specified encoding
373
- - `appendText(path, text, encoding?)` - Append text with specified encoding
374
-
375
- **Common Operations:**
376
-
377
- - `mkdir(path, options?)` - Create directories
378
- - `readDir(path)` - List directory contents
379
- - `stat(path)` - Get file/directory statistics
380
- - `remove(path, options?)` - Remove files/directories
381
- - `copy(source, destination, options?)` - Copy files/directories
382
- - `rename(oldPath, newPath)` - Rename files/directories
383
-
384
- **File Descriptors (Low-level I/O):**
385
-
386
- - `open(path, options?)` - Open file and return descriptor
387
- - `read(fd, buffer, offset, length, position?)` - Read from descriptor (returns `{bytesRead, buffer}`)
388
- - `write(fd, buffer, offset?, length?, position?)` - Write to descriptor
389
- - `fstat(fd)` - Get stats by descriptor
390
- - `ftruncate(fd, size?)` - Truncate file by descriptor
391
- - `fsync(fd)` - Sync file data to storage
392
- - `close(fd)` - Close file descriptor
393
-
394
- **Note**: The `read()` method uses `Comlink.transfer()` for efficient buffer handling. **From the main window**, you must transfer buffer ownership to the worker, and **from the worker**, the buffer is transferred back to you. See [File Descriptors Guide](docs/file-descriptors.md) for complete usage examples.
395
-
396
- _For detailed file descriptor documentation, see [File Descriptors Guide](docs/file-descriptors.md)_
397
-
398
- **Advanced Features:**
399
-
400
- - `watch(path, options?)` - Watch for file changes with minimatch patterns
401
- - `index()` - Get complete file system index
402
- - `sync(entries, options?)` - Bulk synchronization
403
- - `setOptions(options)` - Update configuration
404
-
405
- **Binary File Support:**
406
-
407
- - Full support for images, documents, and any binary data
408
- - Automatic conversion between Uint8Array, ArrayBuffer, and Blob
409
- - Multiple text encodings (UTF-8, UTF-16, ASCII, Base64, etc.)
410
-
411
- **Utility Functions:**
412
-
413
- - Path manipulation (`basename`, `dirname`, `normalizePath`, etc.)
414
- - Data conversion helpers
415
- - OPFS support detection
416
-
417
- For detailed API documentation with examples, see [docs/api-reference.md](docs/api-reference.md).
418
-
419
- ## Types
420
-
421
- Full TypeScript types are provided — see [docs/types.md](docs/types.md) for complete type definitions including `FileStat`, `DirentData`, `WatchOptions`, `OPFSOptions`, and more.
422
-
423
- ## Browser Support
424
-
425
- This library works in **all modern browsers**, including Safari, Firefox, Chrome, and Edge.
426
-
427
- **Requirements:**
428
-
429
- - Web Workers support (available in all modern browsers)
430
- - File System Access API (for OPFS functionality)
431
-
432
- **Browser Compatibility:**
433
-
434
- - ✅ Chrome 86+
435
- - ✅ Edge 86+
436
- - ✅ Firefox 111+
437
- - ✅ Safari 15.2+
438
- - ✅ Opera 72+
46
+ ## Choose a mode
47
+
48
+ | What you want | Use |
49
+ | ---------------------------------------------------------------- | ---------------------------------------------------- |
50
+ | Node-like `fs` via dedicated worker (default, works everywhere) | `createOPFS()` |
51
+ | Node-like `fs` on the main thread (modern browsers / Safari 26+) | `createOPFSAsync()` from `opfs-worker/async` |
52
+ | Node-like `fs` via SharedWorker (modern browsers / Safari 26+) | `createOPFSShared()` from `opfs-worker/sharedworker` |
53
+ | OPFS inside a worker you already run (classes only) | `OPFSSync` / `OPFSAsync` from `opfs-worker/pure` |
54
+
55
+ Trade-offs (FDs, Safari, size, CSP): [Choosing a mode](docs/choosing-a-mode.md).
56
+
57
+ ## Docs
58
+
59
+ - [Docs index](docs/README.md)
60
+ - [Choosing a mode](docs/choosing-a-mode.md)
61
+ - Guides
62
+ - [Dedicated worker](docs/guides/dedicated.md)
63
+ - [Async](docs/guides/async.md)
64
+ - [SharedWorker](docs/guides/sharedworker.md)
65
+ - [Pure classes](docs/guides/pure.md)
66
+ - [Streaming](docs/guides/streaming.md)
67
+ - [Watching](docs/guides/watching.md)
68
+ - [Hashing](docs/guides/hashing.md)
69
+ - API
70
+ - [Create helpers & options](docs/api/create.md)
71
+ - [Facade](docs/api/facade.md)
72
+ - [Backend](docs/api/backend.md)
73
+ - [File descriptors](docs/file-descriptors.md)
74
+ - [Types](docs/types.md)
75
+ - [Migration from 1.x](docs/migration.md)
439
76
 
440
77
  ## Development
441
78
 
442
- ### Building
443
-
444
- ```bash
445
- npm run build
446
- ```
447
-
448
- ### Development Server
449
-
450
- ```bash
451
- npm run dev
452
- ```
453
-
454
- ### Testing
455
-
456
79
  ```bash
457
- npm test
458
- npm run test:coverage
80
+ bun install
81
+ bun run build
82
+ bun run test
83
+ bun run lint
84
+ bun run type-check
459
85
  ```
460
86
 
461
- ### Linting
462
-
463
- ```bash
464
- npm run lint
465
- npm run lint:fix
466
- ```
87
+ Demo app: `bun run dev:demo` / `bun run build:demo` / `bun run preview`.
467
88
 
468
89
  ## License
469
90
 
470
91
  MIT
471
92
 
472
- ## Contributing
473
-
474
- Contributions are welcome!
475
-
476
- **How to contribute:**
477
-
478
- - 🐛 **Report bugs** or suggest features via [GitHub Issues](https://github.com/kachurun/opfs-worker/issues)
479
- - 💡 **Submit ideas** for improvements or new features
480
- - 🔧 **Send PRs** for bug fixes, documentation, or enhancements
481
- - 📚 **Improve docs** - help make the library more accessible
482
-
483
- **Getting started:**
93
+ ## 👤 Maintainer
484
94
 
485
- 1. Fork the repository
486
- 2. Create a feature branch
487
- 3. Make your changes
488
- 4. Add tests if applicable
489
- 5. Submit a Pull Request
95
+ <img src="https://github.com/kachurun.png" width="100" height="100" alt="@kachurun's avatar">
490
96
 
491
- _We welcome all contributions, big and small!_
97
+ Maintained with ❤️ by [@kachurun](https://github.com/kachurun)