opfs-worker 1.3.2 → 2.0.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 (65) hide show
  1. package/README.md +89 -106
  2. package/dist/{facade.d.ts → OPFSFacade.d.ts} +22 -5
  3. package/dist/OPFSFacade.d.ts.map +1 -0
  4. package/dist/{worker.d.ts → OPFSWorker.d.ts} +10 -6
  5. package/dist/OPFSWorker.d.ts.map +1 -0
  6. package/dist/assets/worker.entry-DUlEoroc.js.map +1 -0
  7. package/dist/createOPFSWorker.d.ts +17 -0
  8. package/dist/createOPFSWorker.d.ts.map +1 -0
  9. package/dist/helpers-DNj8ZoMu.cjs +4 -0
  10. package/dist/helpers-DNj8ZoMu.cjs.map +1 -0
  11. package/dist/{helpers-Ca2c767K.js → helpers-WY2jfbOT.js} +221 -221
  12. package/dist/helpers-WY2jfbOT.js.map +1 -0
  13. package/dist/index.cjs +296 -285
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +3 -9
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +369 -340
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.pure.cjs +2 -0
  20. package/dist/index.pure.cjs.map +1 -0
  21. package/dist/index.pure.d.ts +6 -0
  22. package/dist/index.pure.d.ts.map +1 -0
  23. package/dist/{raw.js → index.pure.js} +241 -186
  24. package/dist/index.pure.js.map +1 -0
  25. package/dist/types.d.ts +1 -1
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/utils/helpers.d.ts +11 -1
  28. package/dist/utils/helpers.d.ts.map +1 -1
  29. package/dist/worker.entry.d.ts +2 -0
  30. package/dist/worker.entry.d.ts.map +1 -0
  31. package/docs/api-reference.md +815 -0
  32. package/docs/file-descriptors.md +696 -0
  33. package/docs/types.md +232 -0
  34. package/package.json +14 -8
  35. package/src/OPFSFacade.ts +460 -0
  36. package/src/OPFSWorker.ts +1544 -0
  37. package/src/createOPFSWorker.ts +57 -0
  38. package/src/index.pure.ts +7 -0
  39. package/src/index.ts +15 -0
  40. package/src/types.ts +99 -0
  41. package/src/utils/encoder.ts +205 -0
  42. package/src/utils/errors.ts +297 -0
  43. package/src/utils/helpers.ts +465 -0
  44. package/src/worker.entry.ts +6 -0
  45. package/dist/assets/worker-1Wh1cr7P.js.map +0 -1
  46. package/dist/assets/worker-BeJaVyBV.js.map +0 -1
  47. package/dist/assets/worker-DYYLzR1Y.js.map +0 -1
  48. package/dist/facade.d.ts.map +0 -1
  49. package/dist/helpers-BuGfPAg0.js +0 -1439
  50. package/dist/helpers-BuGfPAg0.js.map +0 -1
  51. package/dist/helpers-CF7A2WQG.cjs +0 -4
  52. package/dist/helpers-CF7A2WQG.cjs.map +0 -1
  53. package/dist/helpers-CIiblZ8d.cjs +0 -4
  54. package/dist/helpers-CIiblZ8d.cjs.map +0 -1
  55. package/dist/helpers-CKOebsbw.js +0 -1423
  56. package/dist/helpers-CKOebsbw.js.map +0 -1
  57. package/dist/helpers-Ca2c767K.js.map +0 -1
  58. package/dist/helpers-Dwc92hv9.cjs +0 -4
  59. package/dist/helpers-Dwc92hv9.cjs.map +0 -1
  60. package/dist/raw.cjs +0 -2
  61. package/dist/raw.cjs.map +0 -1
  62. package/dist/raw.d.ts +0 -13
  63. package/dist/raw.d.ts.map +0 -1
  64. package/dist/raw.js.map +0 -1
  65. package/dist/worker.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
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 version](https://www.npmjs.com/package/opfs-worker)
4
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
6
 
@@ -41,7 +41,7 @@ A robust TypeScript library for working with Origin Private File System (OPFS) t
41
41
 
42
42
  - **Complete API**: `readFile`, `writeFile`, `mkdir`, `remove`, `copy`, `rename`, and more
43
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)
44
+ - **Hash support**: Cheap `etag` by default (`mtime-size`), plus optional content hashes (SHA-1 / SHA-256 / SHA-384 / SHA-512)
45
45
  - **File indexing**: Complete file system indexing with metadata and search
46
46
 
47
47
  ### 🔄 **Advanced Features**
@@ -115,37 +115,43 @@ npm install opfs-worker
115
115
 
116
116
  **Dependencies:**
117
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
118
+ - Modes 1 and 2 depend on `comlink` (worker communication is handled for you)
119
+ - Mode 3 does not use Comlink you run the class inside your own worker
120
+ - Modes 1 and 2 ship an inlined worker, so your bundler does not need a `?worker` setup
120
121
 
121
122
  ## Quick Start
122
123
 
123
- This library provides two ways to use OPFS with Web Workers:
124
+ OPFS sync I/O only works inside a dedicated Web Worker. The library covers three common setups:
124
125
 
125
- ### Inline Worker (Recommended)
126
+ | | Import | Best when |
127
+ | ---------- | --------------------------------------- | ----------------------------------------------------------------- |
128
+ | **Mode 1** | `createOPFS()` from `opfs-worker` | You want a Node-like `fs` API on the main thread |
129
+ | **Mode 2** | `createOPFSWorker()` from `opfs-worker` | You want the low-level worker API, but still from the main thread |
130
+ | **Mode 3** | `OPFSWorker` from `opfs-worker/pure` | Your code already runs inside a worker |
126
131
 
127
- The easiest way to get started - just import and use:
132
+ Modes 1 and 2 both pull Comlink. Mode 3 does not.
133
+
134
+ ### Mode 1: Node-like facade (recommended)
135
+
136
+ The usual path. `createOPFS()` starts an inlined worker and returns a facade with a Node-like API — strings, encodings, auto-detection. Comlink stays under the hood.
137
+
138
+ > 1.x alias: `createWorker` still works and returns the same facade — prefer `createOPFS`.
128
139
 
129
140
  ```typescript
130
- import { createWorker } from 'opfs-worker';
141
+ import { createOPFS } from 'opfs-worker';
131
142
 
132
143
  async function basicExample() {
133
- // Create a file system instance with default root path '/'
134
- const fs = await createWorker();
144
+ const fs = createOPFS();
135
145
 
136
- // Write a file
137
146
  await fs.writeFile('/config.json', JSON.stringify({ theme: 'dark' }));
138
-
139
- // Read the file back
140
147
  const config = await fs.readFile('/config.json');
141
- console.log(JSON.parse(config));
148
+ console.log(JSON.parse(config as string));
142
149
  }
143
150
 
144
- // Extended example with all options
145
151
  async function extendedExample() {
146
152
  const broadcastChannel = new BroadcastChannel('my-app-events');
147
153
 
148
- const fs = await createWorker({
154
+ const fs = createOPFS({
149
155
  root: '/my-app',
150
156
  namespace: 'my-app:fs',
151
157
  hashAlgorithm: 'SHA-256',
@@ -153,16 +159,13 @@ async function extendedExample() {
153
159
  broadcastChannel
154
160
  });
155
161
 
156
- // Handle binary files
157
- const imageData = new Uint8Array([58, /* binary data */]);
162
+ const imageData = new Uint8Array([58 /* binary data */]);
158
163
  await fs.writeFile('/image.png', imageData);
159
164
  const binaryData = await fs.readFile('/image.png', 'binary');
160
165
 
161
- // Text files are automatically handled
162
166
  await fs.writeFile('/config.txt', 'Hello, World!');
163
- const textContent = await fs.readFile('/config.txt'); // Returns string
167
+ const textContent = await fs.readFile('/config.txt'); // string
164
168
 
165
- // Use file watching with BroadcastChannel
166
169
  await fs.watch('/', {
167
170
  recursive: true,
168
171
  include: ['*.json'],
@@ -170,97 +173,85 @@ async function extendedExample() {
170
173
  });
171
174
 
172
175
  broadcastChannel.onmessage = (event) => {
173
- console.log(`File changed: `, event.data);
176
+ console.log('File changed:', event.data);
174
177
  };
175
178
 
176
- // Get file statistics with hashing
177
179
  const stats = await fs.stat('/image.png');
178
-
179
- console.log(
180
- `File size: ${stats.size} bytes`,
181
- `Hash: ${stats.hash}`
182
- );
180
+ console.log(`File size: ${stats.size} bytes`, `Hash: ${stats.hash}`);
183
181
  }
184
182
  ```
185
183
 
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.
184
+ > Watch events go over `BroadcastChannel` (default name `opfs-worker`). Pass `broadcastChannel` to customize. Only watched paths emit events.
187
185
 
188
- ### Manual Worker Setup
186
+ ### Mode 2: Raw worker API from the main thread
189
187
 
190
- For more control over the worker lifecycle, use the worker directly with your bundler:
188
+ Same package entry, same inlined worker but without the facade. You get a Comlink proxy to `OPFSWorker`: bytes in, bytes out. Useful if you want to wrap it yourself or prefer the lower-level API.
191
189
 
192
190
  ```typescript
193
- import OPFSWorker from 'opfs-worker/raw?worker';
194
- import { wrap } from 'comlink';
191
+ import { createOPFSWorker } from 'opfs-worker';
195
192
 
196
- async function basicExample() {
197
- // Create and wrap the worker with default root path '/'
198
- const worker = wrap(new OPFSWorker());
193
+ const { fs, dispose } = createOPFSWorker({
194
+ root: '/my-app',
195
+ namespace: 'my-app:fs',
196
+ hashAlgorithm: 'SHA-256',
197
+ maxFileSize: 100 * 1024 * 1024,
198
+ broadcastChannel: 'my-app-events',
199
+ });
199
200
 
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
- }
201
+ await fs.writeFile('/config.json', new TextEncoder().encode(JSON.stringify({ theme: 'dark' })));
202
+ const bytes = await fs.readFile('/config.json');
203
+ console.log(JSON.parse(new TextDecoder().decode(bytes)));
205
204
 
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 });
205
+ dispose(); // worker.dispose() + terminate()
206
+ ```
223
207
 
224
- // Create directories
225
- await worker.mkdir('/data/logs', { recursive: true });
208
+ > Want your own facade? Our `OPFSFacade` is built on `createOPFSWorker` — copy [`src/OPFSFacade.ts`](src/OPFSFacade.ts), swap the imports to `opfs-worker` and change what you need.
226
209
 
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);
210
+ ### Mode 3: `OPFSWorker` inside your own worker
230
211
 
231
- // Watch for changes
232
- await worker.watch('/data', { recursive: true });
212
+ If you already have a worker (or want full control over it), import the class and use it directly. No nested worker, no Comlink. Bundling that worker and talking to the main thread — if you need that at all — is up to you.
233
213
 
234
- const channel = new BroadcastChannel('my-app-events');
235
- channel.onmessage = (event) => {
236
- console.log('File changed:', event.data);
237
- };
238
- }
214
+ ```typescript
215
+ // my-app.worker.ts (this file IS the worker)
216
+ import { OPFSWorker } from 'opfs-worker/pure';
217
+
218
+ const fs = new OPFSWorker({
219
+ root: '/my-app',
220
+ namespace: 'my-app:fs',
221
+ hashAlgorithm: 'SHA-256',
222
+ broadcastChannel: 'my-app-events', // name only — BroadcastChannel instances can't cross the wire
223
+ });
224
+
225
+ await fs.writeFile('/config.json', new TextEncoder().encode(JSON.stringify({ theme: 'dark' })));
226
+ const bytes = await fs.readFile('/config.json');
227
+ console.log(JSON.parse(new TextDecoder().decode(bytes)));
239
228
  ```
240
229
 
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.
230
+ `opfs-worker/pure` does not call Comlink `expose()`, so it will not take over your worker's message port.
242
231
 
243
232
  ### Hash Algorithm Configuration
244
233
 
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.
234
+ Set once via options / `setOptions()` used by `stat()`, `index()`, and watch events.
235
+
236
+ Default is `'etag'`: a cheap weak tag from `File.lastModified` + size (no content read). Switch to a SHA algorithm when you need a real content hash.
246
237
 
247
238
  ```typescript
248
- import { createWorker } from 'opfs-worker';
239
+ import { createOPFS } from 'opfs-worker';
249
240
 
250
241
  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
242
+ // Default: etag (fast, no content read)
243
+ const fs = createOPFS();
257
244
  await fs.writeFile('/data.txt', 'Hello World');
258
245
 
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
246
+ const etagStat = await fs.stat('/data.txt');
247
+ console.log(`ETag: ${etagStat.hash}`); // e.g. "m1abc-c" (mtime36-size36)
248
+
249
+ // Opt into a cryptographic content hash
250
+ await fs.setOptions({ hashAlgorithm: 'SHA-256' });
251
+ const shaStat = await fs.stat('/data.txt');
252
+ console.log(`SHA-256: ${shaStat.hash}`);
262
253
 
263
- // Get file system index - all files will include hashes
254
+ // Index / watch events also include hash when enabled
264
255
  const index = await fs.index();
265
256
  for (const [path, stat] of index) {
266
257
  if (stat.isFile && stat.hash) {
@@ -268,7 +259,6 @@ async function hashExample() {
268
259
  }
269
260
  }
270
261
 
271
- // Watch events will also include hash information
272
262
  const channel = new BroadcastChannel('opfs-worker');
273
263
  channel.onmessage = (event) => {
274
264
  if (event.data.hash) {
@@ -277,52 +267,45 @@ async function hashExample() {
277
267
  };
278
268
  }
279
269
 
280
- // Configure maximum file size for hashing
270
+ // maxFileSize only applies to SHA-* (content) hashing — etag ignores it
281
271
  async function maxFileSizeExample() {
282
- const fs = await createWorker();
283
-
284
- // Set custom maximum file size (100MB instead of default 50MB)
285
- fs.setOptions({
272
+ const fs = createOPFS({
286
273
  hashAlgorithm: 'SHA-256',
287
- maxFileSize: 100 * 1024 * 1024 // 100MB
274
+ maxFileSize: 100 * 1024 * 1024 // 100MB (default 50MB)
288
275
  });
289
276
 
290
- // Files up to 100MB will be hashed
291
- // Files larger than this will not have hash information
292
277
  const stats = await fs.stat('/large-file.dat');
293
278
  if (stats.hash) {
294
279
  console.log(`Hash: ${stats.hash}`);
295
280
  } else {
296
- console.log('File too large for hashing');
281
+ console.log('File too large for content hashing');
297
282
  }
298
283
  }
299
284
  ```
300
285
 
301
286
  **Supported Hash Algorithms:**
302
287
 
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
288
+ - `'etag'` **default**. Weak tag from mtime + size; free, no content read
289
+ - `'SHA-1'` / `'SHA-256'` / `'SHA-384'` / `'SHA-512'` content hashes via Web Crypto (bounded by `maxFileSize`)
290
+ - `null` / `false` — disable hashing
308
291
 
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.
292
+ **Note:** Prefer `'etag'` for watch / change-detection. Use SHA only when you need integrity of file bytes. Set to `null`/`false` if you don't need `hash` at all.
310
293
 
311
294
  ### Root Path Configuration
312
295
 
313
296
  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.
314
297
 
315
298
  ```typescript
316
- import { createWorker } from 'opfs-worker';
299
+ import { createOPFS } from 'opfs-worker';
317
300
 
318
301
  async function rootPathExample() {
319
302
  // Use default root path '/'
320
- const fsDefault = await createWorker();
303
+ const fsDefault = createOPFS();
321
304
  await fsDefault.writeFile('/config.json', '{}');
322
305
  // This creates /config.json in OPFS root
323
306
 
324
307
  // Use custom root path
325
- const fsCustom = await createWorker({ root: '/my-app' });
308
+ const fsCustom = createOPFS({ root: '/my-app' });
326
309
  await fsCustom.writeFile('/config.json', '{}');
327
310
  // This creates /my-app/config.json in OPFS root
328
311
 
@@ -360,9 +343,10 @@ The complete API reference is available in the [docs/api-reference.md](docs/api-
360
343
 
361
344
  **Entry Points:**
362
345
 
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
346
+ - `createOPFS(options?)` Mode 1: Node-like facade on the main thread
347
+ - `createOPFSWorker(options?)` Mode 2: raw `OPFSWorker` proxy on the main thread
348
+ - `OPFSWorker` from `opfs-worker/pure` Mode 3: use the class inside your own worker
349
+ - `OPFSFacade` — Mode 1 class returned by `createOPFS`
366
350
 
367
351
  **Core File Operations:**
368
352
 
@@ -462,7 +446,6 @@ npm run test:coverage
462
446
 
463
447
  ```bash
464
448
  npm run lint
465
- npm run lint:fix
466
449
  ```
467
450
 
468
451
  ## License
@@ -1,11 +1,13 @@
1
1
  import type { BinaryEncoding, DirentData, Encoding, FileOpenOptions, FileStat, OPFSOptions, PathLike, RenameOptions, StringEncoding, WatchOptions } from './types';
2
2
  /**
3
- * Facade class that provides a clean interface for communicating with the OPFS worker
4
- * while hiding Comlink implementation details.
3
+ * Mode 1: Node-like facade with encoding helpers and string/binary auto-detection,
4
+ * built on top of the raw worker API from {@link createOPFSWorker}.
5
+ *
6
+ * Use {@link createOPFS} to create one.
5
7
  */
6
- export declare class OPFSFileSystem {
8
+ export declare class OPFSFacade {
7
9
  #private;
8
- promises: OPFSFileSystem;
10
+ promises: OPFSFacade;
9
11
  constructor(options?: OPFSOptions);
10
12
  /**
11
13
  * Start watching a file or directory for changes
@@ -172,4 +174,19 @@ export declare class OPFSFileSystem {
172
174
  */
173
175
  dispose(): void;
174
176
  }
175
- //# sourceMappingURL=facade.d.ts.map
177
+ /**
178
+ * Mode 1: start an inlined worker and get a Node-like `fs` API on top of it.
179
+ *
180
+ * For the raw worker API without the facade, use {@link createOPFSWorker}.
181
+ * To use the worker class inside your own worker, see `opfs-worker/pure`.
182
+ */
183
+ export declare function createOPFS(options?: OPFSOptions): OPFSFacade;
184
+ /**
185
+ * @deprecated Use {@link createOPFS}. Kept for 1.x compatibility — still returns the facade.
186
+ */
187
+ export declare const createWorker: typeof createOPFS;
188
+ /**
189
+ * @deprecated Use {@link OPFSFacade}.
190
+ */
191
+ export { OPFSFacade as OPFSFileSystem };
192
+ //# sourceMappingURL=OPFSFacade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OPFSFacade.d.ts","sourceRoot":"","sources":["../src/OPFSFacade.ts"],"names":[],"mappings":"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"}
@@ -8,9 +8,8 @@ import type { DirentData, FileOpenOptions, FileStat, OPFSOptions, RenameOptions,
8
8
  *
9
9
  * @example
10
10
  * ```typescript
11
- * const fs = new OPFSFileSystem();
12
- * await fs.init('/my-app');
13
- * await fs.writeFile('/data/config.json', JSON.stringify({ theme: 'dark' }));
11
+ * const fs = new OPFSWorker();
12
+ * await fs.writeFile('/data/config.json', new TextEncoder().encode(JSON.stringify({ theme: 'dark' })));
14
13
  * const config = await fs.readFile('/data/config.json');
15
14
  * ```
16
15
  */
@@ -25,6 +24,8 @@ export declare class OPFSWorker {
25
24
  private broadcastChannel;
26
25
  /** Configuration options */
27
26
  private options;
27
+ /** Shared sync handles per path (OPFS allows only one handle per file) */
28
+ private openHandles;
28
29
  /** Map of open file descriptors to their metadata */
29
30
  private openFiles;
30
31
  /** Next available file descriptor number */
@@ -44,7 +45,7 @@ export declare class OPFSWorker {
44
45
  */
45
46
  private notifyChange;
46
47
  /**
47
- * Creates a new OPFSFileSystem instance
48
+ * Creates a new OPFSWorker instance
48
49
  *
49
50
  * @param options - Optional configuration options
50
51
  * @param options.root - Root path for the file system (default: '/')
@@ -65,7 +66,7 @@ export declare class OPFSWorker {
65
66
  *
66
67
  * @example
67
68
  * ```typescript
68
- * const fs = new OPFSFileSystem();
69
+ * const fs = new OPFSWorker();
69
70
  *
70
71
  * // Use OPFS root (default)
71
72
  * await fs.mount();
@@ -471,6 +472,9 @@ export declare class OPFSWorker {
471
472
  open(path: string, options?: FileOpenOptions): Promise<number>;
472
473
  /**
473
474
  * Internal method to open a file (without locking)
475
+ *
476
+ * Multiple FDs for the same path share one sync access handle (OPFS limit),
477
+ * with independent per-FD positions — similar to Node.js.
474
478
  * @private
475
479
  */
476
480
  private _openFile;
@@ -625,4 +629,4 @@ export declare class OPFSWorker {
625
629
  */
626
630
  createIndex(entries: [string, string | Uint8Array | Blob][]): Promise<void>;
627
631
  }
628
- //# sourceMappingURL=worker.d.ts.map
632
+ //# sourceMappingURL=OPFSWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OPFSWorker.d.ts","sourceRoot":"","sources":["../src/OPFSWorker.ts"],"names":[],"mappings":"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"}