opfs-worker 0.1.1
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.
- package/LICENSE +21 -0
- package/README.md +500 -0
- package/dist/assets/opfs.worker-BiWuxhcz.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +752 -0
- package/dist/index.js.map +1 -0
- package/dist/inline.cjs +997 -0
- package/dist/inline.cjs.map +1 -0
- package/dist/inline.d.ts +24 -0
- package/dist/inline.d.ts.map +1 -0
- package/dist/inline.js +24 -0
- package/dist/inline.js.map +1 -0
- package/dist/opfs.worker.d.ts +447 -0
- package/dist/opfs.worker.d.ts.map +1 -0
- package/dist/opfs.worker.js +765 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/utils/encoder.d.ts +4 -0
- package/dist/utils/encoder.d.ts.map +1 -0
- package/dist/utils/encoder.js +86 -0
- package/dist/utils/errors.d.ts +57 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +77 -0
- package/dist/utils/helpers.d.ts +33 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +96 -0
- package/package.json +83 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Maksim Kachurin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
# OPFS Worker
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🌐 **Cross-browser compatible**: Works in all modern browsers including Safari, Firefox, Chrome
|
|
8
|
+
- 🚀 **Web Worker-based**: Runs in a separate thread for better performance
|
|
9
|
+
- 📁 **Node.js-like API**: Familiar file system operations (`readFile`, `writeFile`, `mkdir`, etc.)
|
|
10
|
+
- 🔒 **Type-safe**: Full TypeScript support with comprehensive type definitions
|
|
11
|
+
- 🎯 **Comlink-powered**: Seamless communication between main thread and worker
|
|
12
|
+
- 🔐 **Hash support**: Built-in file hash calculation (SHA-1, SHA-256, SHA-384, SHA-512)
|
|
13
|
+
- 📊 **File indexing**: Complete file system indexing with metadata
|
|
14
|
+
- 🔄 **Sync operations**: Bulk file synchronization from external data
|
|
15
|
+
- 🛡️ **Error handling**: Comprehensive error types and handling
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install opfs-worker
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Basic Usage
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { createWorker } from 'opfs-worker/inline';
|
|
29
|
+
|
|
30
|
+
async function example() {
|
|
31
|
+
// Create a file system instance
|
|
32
|
+
const fs = await createWorker();
|
|
33
|
+
|
|
34
|
+
// Mount the file system
|
|
35
|
+
await fs.mount('/my-app');
|
|
36
|
+
|
|
37
|
+
// Write a file
|
|
38
|
+
await fs.writeFile('/config.json', JSON.stringify({ theme: 'dark' }));
|
|
39
|
+
|
|
40
|
+
// Read the file back
|
|
41
|
+
const config = await fs.readFile('/config.json');
|
|
42
|
+
console.log(JSON.parse(config));
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Advanced Usage
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { createWorker } from 'opfs-worker/inline';
|
|
50
|
+
|
|
51
|
+
async function advancedExample() {
|
|
52
|
+
const fs = await createWorker();
|
|
53
|
+
await fs.mount('/my-app');
|
|
54
|
+
|
|
55
|
+
// Create directories
|
|
56
|
+
await fs.mkdir('/data/logs', { recursive: true });
|
|
57
|
+
|
|
58
|
+
// Write multiple files
|
|
59
|
+
await fs.writeFile('/data/config.json', JSON.stringify({ version: '1.0' }));
|
|
60
|
+
await fs.writeFile('/data/logs/app.log', 'Application started\n');
|
|
61
|
+
|
|
62
|
+
// Append to a file
|
|
63
|
+
await fs.appendFile('/data/logs/app.log', `${new Date().toISOString()}: User logged in\n`);
|
|
64
|
+
|
|
65
|
+
// Get file statistics with hash
|
|
66
|
+
const stats = await fs.stat('/data/config.json', {
|
|
67
|
+
includeHash: true,
|
|
68
|
+
hashAlgorithm: 'SHA-1'
|
|
69
|
+
});
|
|
70
|
+
console.log(`File size: ${stats.size} bytes, Hash: ${stats.hash}`);
|
|
71
|
+
|
|
72
|
+
// List directory contents
|
|
73
|
+
const files = await fs.readdir('/data', { withFileTypes: true });
|
|
74
|
+
files.forEach(item => {
|
|
75
|
+
console.log(`${item.name} - ${item.isFile ? 'file' : 'directory'}`);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API Reference
|
|
81
|
+
|
|
82
|
+
### Entry Points
|
|
83
|
+
|
|
84
|
+
#### `createWorker()`
|
|
85
|
+
|
|
86
|
+
Creates a new file system instance with an inline worker.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { createWorker } from 'opfs-worker/inline';
|
|
90
|
+
|
|
91
|
+
const fs = await createWorker();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Returns:** `Promise<RemoteOPFSWorker>` - A remote file system interface
|
|
95
|
+
|
|
96
|
+
### Core Methods
|
|
97
|
+
|
|
98
|
+
#### `mount(root?: string): Promise<boolean>`
|
|
99
|
+
|
|
100
|
+
Initialize the file system within a given directory.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
await fs.mount('/my-app');
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Parameters:**
|
|
107
|
+
|
|
108
|
+
- `root` (optional): The root path for the file system (default: '/')
|
|
109
|
+
|
|
110
|
+
**Returns:** `Promise<boolean>` - True if initialization was successful
|
|
111
|
+
|
|
112
|
+
**Throws:** `OPFSError` if initialization fails
|
|
113
|
+
|
|
114
|
+
#### `readFile(path: string, encoding?: BufferEncoding | 'binary'): Promise<string | Uint8Array>`
|
|
115
|
+
|
|
116
|
+
Read a file from the file system.
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// Read as text (default)
|
|
120
|
+
const content = await fs.readFile('/config/settings.json');
|
|
121
|
+
|
|
122
|
+
// Read as binary
|
|
123
|
+
const binaryData = await fs.readFile('/images/logo.png', 'binary');
|
|
124
|
+
|
|
125
|
+
// Read with specific encoding
|
|
126
|
+
const utf8Content = await fs.readFile('/data/utf8.txt', 'utf-8');
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Parameters:**
|
|
130
|
+
|
|
131
|
+
- `path`: The path to the file to read
|
|
132
|
+
- `encoding` (optional): The encoding to use ('utf-8', 'binary', etc.)
|
|
133
|
+
|
|
134
|
+
**Returns:** `Promise<string | Uint8Array>` - File contents
|
|
135
|
+
|
|
136
|
+
**Throws:** `FileNotFoundError` if the file doesn't exist
|
|
137
|
+
|
|
138
|
+
#### `writeFile(path: string, data: string | Uint8Array | ArrayBuffer, encoding?: BufferEncoding): Promise<void>`
|
|
139
|
+
|
|
140
|
+
Write data to a file, creating or overwriting it.
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
// Write text data
|
|
144
|
+
await fs.writeFile('/config/settings.json', JSON.stringify({ theme: 'dark' }));
|
|
145
|
+
|
|
146
|
+
// Write binary data
|
|
147
|
+
const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
|
|
148
|
+
await fs.writeFile('/data/binary.dat', binaryData);
|
|
149
|
+
|
|
150
|
+
// Write with specific encoding
|
|
151
|
+
await fs.writeFile('/data/utf16.txt', 'Hello World', 'utf-16le');
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Parameters:**
|
|
155
|
+
|
|
156
|
+
- `path`: The path to the file to write
|
|
157
|
+
- `data`: The data to write (string, Uint8Array, or ArrayBuffer)
|
|
158
|
+
- `encoding` (optional): The encoding to use when writing string data
|
|
159
|
+
|
|
160
|
+
#### `appendFile(path: string, data: string | Uint8Array | ArrayBuffer, encoding?: BufferEncoding): Promise<void>`
|
|
161
|
+
|
|
162
|
+
Append data to the end of a file.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// Append text to a log file
|
|
166
|
+
await fs.appendFile('/logs/app.log', `[${new Date().toISOString()}] User logged in\n`);
|
|
167
|
+
|
|
168
|
+
// Append binary data
|
|
169
|
+
const additionalData = new Uint8Array([6, 7, 8]);
|
|
170
|
+
await fs.appendFile('/data/binary.dat', additionalData);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### `mkdir(path: string, options?: { recursive?: boolean }): Promise<void>`
|
|
174
|
+
|
|
175
|
+
Create a directory.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Create a single directory
|
|
179
|
+
await fs.mkdir('/users/john');
|
|
180
|
+
|
|
181
|
+
// Create nested directories
|
|
182
|
+
await fs.mkdir('/users/john/documents/projects', { recursive: true });
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Parameters:**
|
|
186
|
+
|
|
187
|
+
- `path`: The path where the directory should be created
|
|
188
|
+
- `options.recursive` (optional): Whether to create parent directories if they don't exist
|
|
189
|
+
|
|
190
|
+
#### `readdir(path: string, options?: { withFileTypes?: boolean }): Promise<string[] | DirentData[]>`
|
|
191
|
+
|
|
192
|
+
Read a directory's contents.
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
// Get simple list of names
|
|
196
|
+
const files = await fs.readdir('/users/john/documents');
|
|
197
|
+
console.log('Files:', files); // ['readme.txt', 'config.json', 'images']
|
|
198
|
+
|
|
199
|
+
// Get detailed information
|
|
200
|
+
const detailed = await fs.readdir('/users/john/documents', { withFileTypes: true });
|
|
201
|
+
detailed.forEach(item => {
|
|
202
|
+
console.log(`${item.name} - ${item.isFile ? 'file' : 'directory'}`);
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Returns:**
|
|
207
|
+
|
|
208
|
+
- `Promise<string[]>` when `withFileTypes` is false or undefined
|
|
209
|
+
- `Promise<DirentData[]>` when `withFileTypes` is true
|
|
210
|
+
|
|
211
|
+
#### `stat(path: string, options?: { includeHash?: boolean; hashAlgorithm?: string }): Promise<FileStat>`
|
|
212
|
+
|
|
213
|
+
Get file or directory statistics.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
// Basic stats
|
|
217
|
+
const stats = await fs.stat('/config/settings.json');
|
|
218
|
+
console.log(`File size: ${stats.size} bytes`);
|
|
219
|
+
console.log(`Is file: ${stats.isFile}`);
|
|
220
|
+
console.log(`Modified: ${stats.mtime}`);
|
|
221
|
+
|
|
222
|
+
// Stats with hash
|
|
223
|
+
const statsWithHash = await fs.stat('/config/settings.json', {
|
|
224
|
+
includeHash: true,
|
|
225
|
+
hashAlgorithm: 'SHA-1'
|
|
226
|
+
});
|
|
227
|
+
console.log(`Hash: ${statsWithHash.hash}`);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Parameters:**
|
|
231
|
+
|
|
232
|
+
- `path`: The path to the file or directory
|
|
233
|
+
- `options.includeHash` (optional): Whether to calculate file hash (default: false)
|
|
234
|
+
- `options.hashAlgorithm` (optional): Hash algorithm to use ('SHA-1', 'SHA-256', 'SHA-384', 'SHA-512', default: 'SHA-1')
|
|
235
|
+
|
|
236
|
+
**Returns:** `Promise<FileStat>` - File/directory statistics
|
|
237
|
+
|
|
238
|
+
#### `exists(path: string): Promise<boolean>`
|
|
239
|
+
|
|
240
|
+
Check if a file or directory exists.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
const exists = await fs.exists('/config/settings.json');
|
|
244
|
+
console.log(`File exists: ${exists}`);
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Returns:** `Promise<boolean>` - True if the file or directory exists
|
|
248
|
+
|
|
249
|
+
#### `remove(path: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>`
|
|
250
|
+
|
|
251
|
+
Remove files and directories.
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// Remove a file
|
|
255
|
+
await fs.remove('/path/to/file.txt');
|
|
256
|
+
|
|
257
|
+
// Remove a directory and all its contents
|
|
258
|
+
await fs.remove('/path/to/directory', { recursive: true });
|
|
259
|
+
|
|
260
|
+
// Remove with force (ignore if doesn't exist)
|
|
261
|
+
await fs.remove('/maybe/exists', { force: true });
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Parameters:**
|
|
265
|
+
|
|
266
|
+
- `path`: The path to remove
|
|
267
|
+
- `options.recursive` (optional): Whether to remove directories recursively (default: false)
|
|
268
|
+
- `options.force` (optional): Whether to ignore errors if the path doesn't exist (default: false)
|
|
269
|
+
|
|
270
|
+
#### `copy(source: string, destination: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>`
|
|
271
|
+
|
|
272
|
+
Copy files and directories.
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// Copy a file
|
|
276
|
+
await fs.copy('/source/file.txt', '/dest/file.txt');
|
|
277
|
+
|
|
278
|
+
// Copy a directory and all its contents
|
|
279
|
+
await fs.copy('/source/dir', '/dest/dir', { recursive: true });
|
|
280
|
+
|
|
281
|
+
// Copy without overwriting existing files
|
|
282
|
+
await fs.copy('/source', '/dest', { recursive: true, force: false });
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**Parameters:**
|
|
286
|
+
|
|
287
|
+
- `source`: The source path to copy from
|
|
288
|
+
- `destination`: The destination path to copy to
|
|
289
|
+
- `options.recursive` (optional): Whether to copy directories recursively (default: false)
|
|
290
|
+
- `options.force` (optional): Whether to overwrite existing files (default: true)
|
|
291
|
+
|
|
292
|
+
#### `rename(oldPath: string, newPath: string): Promise<void>`
|
|
293
|
+
|
|
294
|
+
Rename a file or directory.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
await fs.rename('/old/path/file.txt', '/new/path/renamed.txt');
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Parameters:**
|
|
301
|
+
|
|
302
|
+
- `oldPath`: The current path of the file or directory
|
|
303
|
+
- `newPath`: The new path for the file or directory
|
|
304
|
+
|
|
305
|
+
#### `clear(path?: string): Promise<void>`
|
|
306
|
+
|
|
307
|
+
Clear all contents of a directory without removing the directory itself.
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// Clear root directory contents
|
|
311
|
+
await fs.clear('/');
|
|
312
|
+
|
|
313
|
+
// Clear specific directory contents
|
|
314
|
+
await fs.clear('/data');
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Parameters:**
|
|
318
|
+
|
|
319
|
+
- `path` (optional): The path to the directory to clear (default: '/')
|
|
320
|
+
|
|
321
|
+
#### `index(options?: { includeHash?: boolean; hashAlgorithm?: string }): Promise<Map<string, FileStat>>`
|
|
322
|
+
|
|
323
|
+
Recursively list all files and directories with their stats.
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
// Basic index without hash
|
|
327
|
+
const index = await fs.index();
|
|
328
|
+
|
|
329
|
+
// Index with file hash
|
|
330
|
+
const indexWithHash = await fs.index({
|
|
331
|
+
includeHash: true,
|
|
332
|
+
hashAlgorithm: 'SHA-1'
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Iterate through all files and directories
|
|
336
|
+
for (const [path, stat] of index) {
|
|
337
|
+
console.log(`${path}: ${stat.isFile ? 'file' : 'directory'} (${stat.size} bytes)`);
|
|
338
|
+
if (stat.hash) console.log(` Hash: ${stat.hash}`);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Get specific file stats
|
|
342
|
+
const fileStats = index.get('/data/config.json');
|
|
343
|
+
if (fileStats) {
|
|
344
|
+
console.log(`File size: ${fileStats.size} bytes`);
|
|
345
|
+
if (fileStats.hash) console.log(`Hash: ${fileStats.hash}`);
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Parameters:**
|
|
350
|
+
|
|
351
|
+
- `options.includeHash` (optional): Whether to calculate file hash (default: false)
|
|
352
|
+
- `options.hashAlgorithm` (optional): Hash algorithm to use (default: 'SHA-1')
|
|
353
|
+
|
|
354
|
+
**Returns:** `Promise<Map<string, FileStat>>` - Map of path => FileStat
|
|
355
|
+
|
|
356
|
+
#### `sync(entries: [string, string | Uint8Array | Blob][], options?: { cleanBefore?: boolean }): Promise<void>`
|
|
357
|
+
|
|
358
|
+
Synchronize the file system with external data.
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
// Sync with external data
|
|
362
|
+
const entries: [string, string | Uint8Array | Blob][] = [
|
|
363
|
+
['/config.json', JSON.stringify({ theme: 'dark' })],
|
|
364
|
+
['/data/binary.dat', new Uint8Array([1, 2, 3, 4])],
|
|
365
|
+
['/upload.txt', new Blob(['file content'], { type: 'text/plain' })]
|
|
366
|
+
];
|
|
367
|
+
|
|
368
|
+
// Sync without clearing existing files
|
|
369
|
+
await fs.sync(entries);
|
|
370
|
+
|
|
371
|
+
// Clean file system and then sync
|
|
372
|
+
await fs.sync(entries, { cleanBefore: true });
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
**Parameters:**
|
|
376
|
+
|
|
377
|
+
- `entries`: Array of [path, data] tuples to sync
|
|
378
|
+
- `options.cleanBefore` (optional): Whether to clear the file system before syncing (default: false)
|
|
379
|
+
|
|
380
|
+
#### `realpath(path: string): Promise<string>`
|
|
381
|
+
|
|
382
|
+
Resolve a path to an absolute path.
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
// Resolve relative path
|
|
386
|
+
const absolute = await fs.realpath('./config/../data/file.txt');
|
|
387
|
+
console.log(absolute); // '/data/file.txt'
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**Returns:** `Promise<string>` - The absolute normalized path
|
|
391
|
+
|
|
392
|
+
**Throws:** `FileNotFoundError` if the path doesn't exist
|
|
393
|
+
|
|
394
|
+
## Types
|
|
395
|
+
|
|
396
|
+
### `FileStat`
|
|
397
|
+
|
|
398
|
+
File or directory statistics.
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
interface FileStat {
|
|
402
|
+
kind: 'file' | 'directory';
|
|
403
|
+
size: number;
|
|
404
|
+
mtime: string; // ISO string
|
|
405
|
+
ctime: string; // ISO string
|
|
406
|
+
isFile: boolean;
|
|
407
|
+
isDirectory: boolean;
|
|
408
|
+
hash?: string; // Hash of file content (only for files)
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### `DirentData`
|
|
413
|
+
|
|
414
|
+
Directory entry information.
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
interface DirentData {
|
|
418
|
+
name: string;
|
|
419
|
+
kind: 'file' | 'directory';
|
|
420
|
+
isFile: boolean;
|
|
421
|
+
isDirectory: boolean;
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### `RemoteOPFSWorker`
|
|
426
|
+
|
|
427
|
+
Remote file system interface type.
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
type RemoteOPFSWorker = Remote<OPFSWorker>;
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Error Types
|
|
434
|
+
|
|
435
|
+
The library provides comprehensive error handling with specific error types:
|
|
436
|
+
|
|
437
|
+
- `OPFSError` - Base error class for all OPFS-related errors
|
|
438
|
+
- `OPFSNotSupportedError` - Thrown when OPFS is not supported in the browser
|
|
439
|
+
- `OPFSNotMountedError` - Thrown when OPFS is not mounted
|
|
440
|
+
- `PathError` - Thrown for invalid paths or path traversal attempts
|
|
441
|
+
- `FileNotFoundError` - Thrown when a requested file doesn't exist
|
|
442
|
+
- `DirectoryNotFoundError` - Thrown when a requested directory doesn't exist
|
|
443
|
+
- `PermissionError` - Thrown when permission is denied for an operation
|
|
444
|
+
- `StorageError` - Thrown when an operation fails due to insufficient storage
|
|
445
|
+
- `TimeoutError` - Thrown when an operation times out
|
|
446
|
+
|
|
447
|
+
## Browser Support
|
|
448
|
+
|
|
449
|
+
This library works in **all modern browsers**, including Safari, Firefox, Chrome, and Edge.
|
|
450
|
+
|
|
451
|
+
**Requirements:**
|
|
452
|
+
|
|
453
|
+
- Web Workers support (available in all modern browsers)
|
|
454
|
+
- File System Access API (for OPFS functionality)
|
|
455
|
+
|
|
456
|
+
**Browser Compatibility:**
|
|
457
|
+
|
|
458
|
+
- ✅ Chrome 86+
|
|
459
|
+
- ✅ Edge 86+
|
|
460
|
+
- ✅ Firefox 111+
|
|
461
|
+
- ✅ Safari 15.2+
|
|
462
|
+
- ✅ Opera 72+
|
|
463
|
+
|
|
464
|
+
**Note:** The library gracefully handles browsers that don't support OPFS by providing appropriate error messages and fallback behavior.
|
|
465
|
+
|
|
466
|
+
## Development
|
|
467
|
+
|
|
468
|
+
### Building
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
npm run build
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### Development Server
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
npm run dev
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Testing
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
npm test
|
|
484
|
+
npm run test:coverage
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### Linting
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
npm run lint
|
|
491
|
+
npm run lint:fix
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
## License
|
|
495
|
+
|
|
496
|
+
MIT
|
|
497
|
+
|
|
498
|
+
## Contributing
|
|
499
|
+
|
|
500
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|