opfs-worker 0.2.0 → 0.2.2

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/dist/raw.js CHANGED
@@ -1,151 +1,6 @@
1
- import { expose as E } from "comlink";
2
- class o extends Error {
3
- constructor(e, t, r) {
4
- super(e), this.code = t, this.path = r, this.name = "OPFSError";
5
- }
6
- }
7
- class S extends o {
8
- constructor() {
9
- super("OPFS is not supported in this browser", "OPFS_NOT_SUPPORTED");
10
- }
11
- }
12
- class y extends o {
13
- constructor() {
14
- super("OPFS is not mounted", "OPFS_NOT_MOUNTED");
15
- }
16
- }
17
- class g extends o {
18
- constructor(e, t) {
19
- super(e, "INVALID_PATH", t);
20
- }
21
- }
22
- class m extends o {
23
- constructor(e) {
24
- super(`File not found: ${e}`, "FILE_NOT_FOUND", e);
25
- }
26
- }
27
- function A(a, e = "utf-8") {
28
- switch (e) {
29
- case "utf8":
30
- case "utf-8":
31
- return new TextEncoder().encode(a);
32
- case "utf16le":
33
- case "ucs2":
34
- case "ucs-2":
35
- return I(a);
36
- case "ascii":
37
- return $(a);
38
- case "latin1":
39
- return v(a);
40
- case "binary":
41
- return Uint8Array.from(a, (t) => t.charCodeAt(0));
42
- case "base64":
43
- return Uint8Array.from(atob(a), (t) => t.charCodeAt(0));
44
- case "hex":
45
- if (!/^[\da-f]+$/i.test(a) || a.length % 2 !== 0)
46
- throw new o("Invalid hex string", "INVALID_HEX_FORMAT");
47
- return Uint8Array.from(a.match(/.{1,2}/g).map((t) => parseInt(t, 16)));
48
- default:
49
- return console.warn("Encoding not supported, falling back to UTF-8"), new TextEncoder().encode(a);
50
- }
51
- }
52
- function D(a, e = "utf-8") {
53
- switch (e) {
54
- case "utf8":
55
- case "utf-8":
56
- return new TextDecoder().decode(a);
57
- case "utf16le":
58
- case "ucs2":
59
- case "ucs-2":
60
- return T(a);
61
- case "latin1":
62
- return String.fromCharCode(...a);
63
- case "binary":
64
- return String.fromCharCode(...a);
65
- case "ascii":
66
- return String.fromCharCode(...a.map((t) => t & 127));
67
- case "base64":
68
- return btoa(String.fromCharCode(...a));
69
- case "hex":
70
- return Array.from(a).map((t) => t.toString(16).padStart(2, "0")).join("");
71
- default:
72
- return console.warn("Unsupported encoding, falling back to UTF-8"), new TextDecoder().decode(a);
73
- }
74
- }
75
- function I(a) {
76
- const e = new Uint8Array(a.length * 2);
77
- for (let t = 0; t < a.length; t++) {
78
- const r = a.charCodeAt(t);
79
- e[t * 2] = r & 255, e[t * 2 + 1] = r >> 8;
80
- }
81
- return e;
82
- }
83
- function T(a) {
84
- a.length % 2 !== 0 && (console.warn("Invalid UTF-16LE buffer length, truncating last byte"), a = a.slice(0, a.length - 1));
85
- const e = new Uint16Array(a.buffer, a.byteOffset, a.byteLength / 2);
86
- return String.fromCharCode(...e);
87
- }
88
- function v(a) {
89
- const e = new Uint8Array(a.length);
90
- for (let t = 0; t < a.length; t++)
91
- e[t] = a.charCodeAt(t) & 255;
92
- return e;
93
- }
94
- function $(a) {
95
- const e = new Uint8Array(a.length);
96
- for (let t = 0; t < a.length; t++)
97
- e[t] = a.charCodeAt(t) & 127;
98
- return e;
99
- }
100
- function N() {
101
- if (!("storage" in navigator) || !("getDirectory" in navigator.storage))
102
- throw new S();
103
- }
104
- function f(a) {
105
- return Array.isArray(a) ? a : a.split("/").filter(Boolean);
106
- }
107
- function p(a) {
108
- return typeof a == "string" ? a ?? "/" : `/${a.join("/")}`;
109
- }
110
- function H(a, e = "utf-8") {
111
- return typeof a == "string" ? A(a, e) : a instanceof Uint8Array ? a : new Uint8Array(a);
112
- }
113
- async function x(a) {
114
- const e = await a.createSyncAccessHandle();
115
- try {
116
- const t = e.getSize(), r = new Uint8Array(t);
117
- return e.read(r, { at: 0 }), r;
118
- } finally {
119
- e.close();
120
- }
121
- }
122
- async function F(a, e, t, r = {}) {
123
- let n = null;
124
- try {
125
- n = await a.createSyncAccessHandle();
126
- const i = H(e, t), s = r.append ? n.getSize() : 0;
127
- n.write(i, { at: s }), r.truncate && !r.append && n.truncate(i.byteLength), n.flush();
128
- } catch (i) {
129
- console.error(i);
130
- const s = r.append ? "append" : "write";
131
- throw new o(`Failed to ${s} file`, `${s.toUpperCase()}_FAILED`);
132
- } finally {
133
- if (n)
134
- try {
135
- n.close();
136
- } catch {
137
- }
138
- }
139
- }
140
- async function O(a, e = "SHA-1") {
141
- try {
142
- const t = new Uint8Array(a), r = await crypto.subtle.digest(e, t);
143
- return Array.from(new Uint8Array(r)).map((i) => i.toString(16).padStart(2, "0")).join("");
144
- } catch (t) {
145
- throw console.warn(`Failed to calculate ${e} hash:`, t), t;
146
- }
147
- }
148
- class U {
1
+ import { expose as p } from "comlink";
2
+ import { d as v, O as o, b as f, s as u, P as E, i as I, o as S, F as d, w as g, j as T, e as m, f as y, k as M, r as H, n as F, l as P } from "./helpers-Co-qCBmA.js";
3
+ class $ {
149
4
  /** Root directory handle for the file system */
150
5
  root = null;
151
6
  /** Watch event callback */
@@ -158,19 +13,23 @@ class U {
158
13
  watchInterval = 1e3;
159
14
  /** Flag to avoid concurrent scans */
160
15
  scanning = !1;
16
+ /** Promise to prevent concurrent mount operations */
17
+ mountingPromise = null;
161
18
  /**
162
19
  * Creates a new OPFSFileSystem instance
163
20
  *
21
+ * @param watchCallback - Optional callback for file change events
22
+ * @param watchOptions - Optional configuration for watching
164
23
  * @throws {OPFSError} If OPFS is not supported in the current browser
165
24
  */
166
- constructor() {
167
- N();
25
+ constructor(t, e) {
26
+ v(), t && (this.watchCallback = t, e?.watchInterval && (this.watchInterval = e.watchInterval)), this.mount("/");
168
27
  }
169
28
  /**
170
29
  * Initialize the file system within a given directory
171
30
  *
172
31
  * This method sets up the root directory for all subsequent operations.
173
- * It must be called before any other file system operations.
32
+ * If no root is specified, it will use the OPFS root directory.
174
33
  *
175
34
  * @param root - The root path for the file system (default: '/')
176
35
  * @returns Promise that resolves to true if initialization was successful
@@ -179,15 +38,52 @@ class U {
179
38
  * @example
180
39
  * ```typescript
181
40
  * const fs = new OPFSFileSystem();
182
- * const success = await fs.init('/my-app');
41
+ *
42
+ * // Use OPFS root (default)
43
+ * await fs.mount();
44
+ *
45
+ * // Use custom directory
46
+ * await fs.mount('/my-app');
183
47
  * ```
184
48
  */
185
- async mount(e = "/", t, r) {
186
- try {
187
- const n = await navigator.storage.getDirectory();
188
- return this.root = await this.getDirectoryHandle(e, !0, n), t && (this.watchCallback = t, r?.watchInterval && (this.watchInterval = r.watchInterval)), !0;
189
- } catch (n) {
190
- throw console.error(n), new o("Failed to initialize OPFS", "INIT_FAILED");
49
+ async mount(t = "/") {
50
+ return this.mountingPromise && await this.mountingPromise, this.mountingPromise = new Promise(async (e, i) => {
51
+ this.root = null;
52
+ try {
53
+ const r = await navigator.storage.getDirectory();
54
+ t === "/" ? this.root = r : this.root = await this.getDirectoryHandle(t, !0, r), e(!0);
55
+ } catch (r) {
56
+ console.error(r), i(new o("Failed to initialize OPFS", "INIT_FAILED"));
57
+ } finally {
58
+ this.mountingPromise = null;
59
+ }
60
+ }), this.mountingPromise;
61
+ }
62
+ /**
63
+ * Set the watch callback for file change events
64
+ *
65
+ * @param callback - The callback function to invoke when files change
66
+ * @param options - Optional configuration for watching
67
+ */
68
+ setWatchCallback(t, e) {
69
+ this.watchCallback = t, e?.watchInterval && (this.watchInterval = e.watchInterval);
70
+ }
71
+ /**
72
+ * Automatically mount the OPFS root if not already mounted
73
+ *
74
+ * This method is called internally when file operations are performed
75
+ * without explicitly mounting first.
76
+ *
77
+ * @returns Promise that resolves when auto-mount is complete
78
+ * @throws {OPFSError} If auto-mount fails
79
+ */
80
+ async ensureMounted() {
81
+ if (!this.root) {
82
+ if (this.mountingPromise) {
83
+ await this.mountingPromise;
84
+ return;
85
+ }
86
+ throw new o("OPFS not mounted", "NOT_MOUNTED");
191
87
  }
192
88
  }
193
89
  /**
@@ -208,14 +104,14 @@ class U {
208
104
  * const docsDir2 = await fs.getDirectoryHandle(['users', 'john', 'documents'], true);
209
105
  * ```
210
106
  */
211
- async getDirectoryHandle(e, t = !1, r = this.root) {
212
- if (!r)
213
- throw new y();
214
- const n = Array.isArray(e) ? e : f(e);
215
- let i = r;
216
- for (const s of n)
217
- i = await i.getDirectoryHandle(s, { create: t });
218
- return i;
107
+ async getDirectoryHandle(t, e = !1, i = this.root) {
108
+ if (!i)
109
+ throw new f();
110
+ const r = Array.isArray(t) ? t : u(t);
111
+ let a = i;
112
+ for (const n of r)
113
+ a = await a.getDirectoryHandle(n, { create: e });
114
+ return a;
219
115
  }
220
116
  /**
221
117
  * Get a file handle from a path
@@ -236,14 +132,14 @@ class U {
236
132
  * const fileHandle2 = await fs.getFileHandle(['config', 'settings.json'], true);
237
133
  * ```
238
134
  */
239
- async getFileHandle(e, t = !1, r = this.root) {
240
- if (!r)
241
- throw new y();
242
- const n = f(e);
243
- if (n.length === 0)
244
- throw new g("Path must not be empty", Array.isArray(e) ? e.join("/") : e);
245
- const i = n.pop();
246
- return (await this.getDirectoryHandle(n, t, r)).getFileHandle(i, { create: t });
135
+ async getFileHandle(t, e = !1, i = this.root) {
136
+ if (!i)
137
+ throw new f();
138
+ const r = u(t);
139
+ if (r.length === 0)
140
+ throw new E("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
141
+ const a = r.pop();
142
+ return (await this.getDirectoryHandle(r, e, i)).getFileHandle(a, { create: e });
247
143
  }
248
144
  /**
249
145
  * Recursively list all files and directories with their stats
@@ -282,34 +178,35 @@ class U {
282
178
  * }
283
179
  * ```
284
180
  */
285
- async index(e) {
286
- const t = /* @__PURE__ */ new Map(), r = async (n) => {
287
- const i = await this.readdir(n, { withFileTypes: !0 });
288
- for (const s of i) {
289
- const c = `${n === "/" ? "" : n}/${s.name}`;
181
+ async index(t) {
182
+ const e = /* @__PURE__ */ new Map(), i = async (r) => {
183
+ const a = await this.readdir(r, { withFileTypes: !0 });
184
+ for (const n of a) {
185
+ const s = `${r === "/" ? "" : r}/${n.name}`;
290
186
  try {
291
- const l = await this.stat(c, e);
292
- t.set(c, l), l.isDirectory && await r(c);
293
- } catch (l) {
294
- console.warn(`Skipping broken entry: ${c}`, l);
187
+ const c = await this.stat(s, t);
188
+ e.set(s, c), c.isDirectory && await i(s);
189
+ } catch (c) {
190
+ console.warn(`Skipping broken entry: ${s}`, c);
295
191
  }
296
192
  }
297
193
  };
298
- return t.set("/", {
194
+ return e.set("/", {
299
195
  kind: "directory",
300
196
  size: 0,
301
197
  mtime: (/* @__PURE__ */ new Date(0)).toISOString(),
302
198
  ctime: (/* @__PURE__ */ new Date(0)).toISOString(),
303
199
  isFile: !1,
304
200
  isDirectory: !0
305
- }), await r("/"), t;
201
+ }), await i("/"), e;
306
202
  }
307
- async readFile(e, t = "utf-8") {
203
+ async readFile(t, e = "utf-8") {
204
+ await this.ensureMounted();
308
205
  try {
309
- const r = await this.getFileHandle(e, !1), n = await x(r);
310
- return t === "binary" ? n : D(n, t);
311
- } catch (r) {
312
- throw console.error(r), new m(e);
206
+ const i = await this.getFileHandle(t, !1), r = await I(i);
207
+ return e === "binary" ? r : S(r, e);
208
+ } catch (i) {
209
+ throw console.error(i), new d(t);
313
210
  }
314
211
  }
315
212
  /**
@@ -337,9 +234,10 @@ class U {
337
234
  * await fs.writeFile('/data/utf16.txt', 'Hello World', 'utf-16le');
338
235
  * ```
339
236
  */
340
- async writeFile(e, t, r) {
341
- const n = await this.getFileHandle(e, !0);
342
- await F(n, t, r, { truncate: !0 });
237
+ async writeFile(t, e, i) {
238
+ await this.ensureMounted();
239
+ const r = await this.getFileHandle(t, !0);
240
+ await g(r, e, i, { truncate: !0 });
343
241
  }
344
242
  /**
345
243
  * Append data to a file
@@ -363,9 +261,10 @@ class U {
363
261
  * await fs.appendFile('/data/binary.dat', additionalData);
364
262
  * ```
365
263
  */
366
- async appendFile(e, t, r) {
367
- const n = await this.getFileHandle(e, !0);
368
- await F(n, t, r, { append: !0 });
264
+ async appendFile(t, e, i) {
265
+ await this.ensureMounted();
266
+ const r = await this.getFileHandle(t, !0);
267
+ await g(r, e, i, { append: !0 });
369
268
  }
370
269
  /**
371
270
  * Create a directory
@@ -388,20 +287,20 @@ class U {
388
287
  * await fs.mkdir('/users/john/documents/projects', { recursive: true });
389
288
  * ```
390
289
  */
391
- async mkdir(e, t) {
392
- if (!this.root)
393
- throw new y();
394
- const r = t?.recursive ?? !1, n = f(e);
395
- let i = this.root;
396
- for (let s = 0; s < n.length; s++) {
397
- const c = n[s];
290
+ async mkdir(t, e) {
291
+ if (await this.ensureMounted(), !this.root)
292
+ throw new f();
293
+ const i = e?.recursive ?? !1, r = u(t);
294
+ let a = this.root;
295
+ for (let n = 0; n < r.length; n++) {
296
+ const s = r[n];
398
297
  try {
399
- i = await i.getDirectoryHandle(c, { create: r || s === n.length - 1 });
400
- } catch (l) {
401
- throw l.name === "NotFoundError" ? new o(
402
- `Parent directory does not exist: ${p(n.slice(0, s + 1))}`,
298
+ a = await a.getDirectoryHandle(s, { create: i || n === r.length - 1 });
299
+ } catch (c) {
300
+ throw c.name === "NotFoundError" ? new o(
301
+ `Parent directory does not exist: ${T(r.slice(0, n + 1))}`,
403
302
  "ENOENT"
404
- ) : l.name === "TypeMismatchError" ? new o(`Path segment is not a directory: ${c}`, "ENOTDIR") : new o("Failed to create directory", "MKDIR_FAILED");
303
+ ) : c.name === "TypeMismatchError" ? new o(`Path segment is not a directory: ${s}`, "ENOTDIR") : new o("Failed to create directory", "MKDIR_FAILED");
405
304
  }
406
305
  }
407
306
  }
@@ -434,62 +333,63 @@ class U {
434
333
  * console.log(`Hash: ${statsWithHash.hash}`);
435
334
  * ```
436
335
  */
437
- async stat(e, t) {
438
- const r = f(e), n = r.pop(), i = await this.getDirectoryHandle(r, !1), s = t?.includeHash ?? !1, c = t?.hashAlgorithm ?? "SHA-1";
336
+ async stat(t, e) {
337
+ await this.ensureMounted();
338
+ const i = m(t), r = await this.getDirectoryHandle(y(t), !1), a = e?.includeHash ?? !1, n = e?.hashAlgorithm ?? "SHA-1";
439
339
  try {
440
- const h = await (await i.getFileHandle(n, { create: !1 })).getFile(), w = {
340
+ const c = await (await r.getFileHandle(i, { create: !1 })).getFile(), l = {
441
341
  kind: "file",
442
- size: h.size,
443
- mtime: new Date(h.lastModified).toISOString(),
444
- ctime: new Date(h.lastModified).toISOString(),
342
+ size: c.size,
343
+ mtime: new Date(c.lastModified).toISOString(),
344
+ ctime: new Date(c.lastModified).toISOString(),
445
345
  isFile: !0,
446
346
  isDirectory: !1
447
347
  };
448
- if (s)
348
+ if (a)
449
349
  try {
450
- const u = new Uint8Array(await h.arrayBuffer()), d = await O(u, c);
451
- w.hash = d;
452
- } catch (u) {
453
- console.warn(`Failed to calculate hash for ${e}:`, u);
350
+ const h = new Uint8Array(await c.arrayBuffer()), w = await M(h, n);
351
+ l.hash = w;
352
+ } catch (h) {
353
+ console.warn(`Failed to calculate hash for ${t}:`, h);
454
354
  }
455
- return w;
456
- } catch (l) {
457
- if (l.name !== "TypeMismatchError" && l.name !== "NotFoundError")
355
+ return l;
356
+ } catch (s) {
357
+ if (s.name !== "TypeMismatchError" && s.name !== "NotFoundError")
458
358
  throw new o("Failed to stat (file)", "STAT_FAILED");
459
359
  }
460
360
  try {
461
- return await i.getDirectoryHandle(n, { create: !1 }), {
361
+ return await r.getDirectoryHandle(i, { create: !1 }), {
462
362
  kind: "directory",
463
363
  size: 0,
464
364
  mtime: (/* @__PURE__ */ new Date(0)).toISOString(),
465
365
  ctime: (/* @__PURE__ */ new Date(0)).toISOString(),
466
366
  isFile: !1,
467
367
  isDirectory: !0
468
- // Directories don't have hashes
469
368
  };
470
- } catch (l) {
471
- throw l.name === "NotFoundError" ? new o(`No such file or directory: ${e}`, "ENOENT") : new o("Failed to stat (directory)", "STAT_FAILED");
369
+ } catch (s) {
370
+ throw s.name === "NotFoundError" ? new o(`No such file or directory: ${t}`, "ENOENT") : new o("Failed to stat (directory)", "STAT_FAILED");
472
371
  }
473
372
  }
474
- async readdir(e, t) {
475
- const r = t?.withFileTypes ?? !1, n = await this.getDirectoryHandle(e, !1);
476
- if (r) {
477
- const i = [];
478
- for await (const [s, c] of n.entries()) {
479
- const l = c.kind === "file";
480
- i.push({
481
- name: s,
482
- kind: c.kind,
483
- isFile: l,
484
- isDirectory: !l
373
+ async readdir(t, e) {
374
+ await this.ensureMounted();
375
+ const i = e?.withFileTypes ?? !1, r = await this.getDirectoryHandle(t, !1);
376
+ if (i) {
377
+ const a = [];
378
+ for await (const [n, s] of r.entries()) {
379
+ const c = s.kind === "file";
380
+ a.push({
381
+ name: n,
382
+ kind: s.kind,
383
+ isFile: c,
384
+ isDirectory: !c
485
385
  });
486
386
  }
487
- return i;
387
+ return a;
488
388
  } else {
489
- const i = [];
490
- for await (const [s] of n.entries())
491
- i.push(s);
492
- return i;
389
+ const a = [];
390
+ for await (const [n] of r.entries())
391
+ a.push(n);
392
+ return a;
493
393
  }
494
394
  }
495
395
  /**
@@ -506,27 +406,28 @@ class U {
506
406
  * console.log(`File exists: ${exists}`);
507
407
  * ```
508
408
  */
509
- async exists(e) {
510
- const t = f(e), r = t.pop();
511
- let n = null;
409
+ async exists(t) {
410
+ await this.ensureMounted();
411
+ const e = m(t);
412
+ let i = null;
512
413
  try {
513
- n = await this.getDirectoryHandle(t, !1);
514
- } catch (i) {
515
- throw (i.name === "NotFoundError" || i.name === "TypeMismatchError") && (n = null), i;
414
+ i = await this.getDirectoryHandle(y(t), !1);
415
+ } catch (r) {
416
+ throw (r.name === "NotFoundError" || r.name === "TypeMismatchError") && (i = null), r;
516
417
  }
517
- if (!n || !r)
418
+ if (!i || !e)
518
419
  return !1;
519
420
  try {
520
- return await n.getFileHandle(r, { create: !1 }), !0;
521
- } catch (i) {
522
- if (i.name !== "NotFoundError" && i.name !== "TypeMismatchError")
523
- throw i;
421
+ return await i.getFileHandle(e, { create: !1 }), !0;
422
+ } catch (r) {
423
+ if (r.name !== "NotFoundError" && r.name !== "TypeMismatchError")
424
+ throw r;
524
425
  }
525
426
  try {
526
- return await n.getDirectoryHandle(r, { create: !1 }), !0;
527
- } catch (i) {
528
- if (i.name !== "NotFoundError" && i.name !== "TypeMismatchError")
529
- throw i;
427
+ return await i.getDirectoryHandle(e, { create: !1 }), !0;
428
+ } catch (r) {
429
+ if (r.name !== "NotFoundError" && r.name !== "TypeMismatchError")
430
+ throw r;
530
431
  }
531
432
  return !1;
532
433
  }
@@ -549,15 +450,16 @@ class U {
549
450
  * await fs.clear('/data');
550
451
  * ```
551
452
  */
552
- async clear(e = "/") {
453
+ async clear(t = "/") {
454
+ await this.ensureMounted();
553
455
  try {
554
- const t = await this.readdir(e, { withFileTypes: !0 });
555
- for (const r of t) {
556
- const n = `${e === "/" ? "" : e}/${r.name}`;
557
- await this.remove(n, { recursive: !0 });
456
+ const e = await this.readdir(t, { withFileTypes: !0 });
457
+ for (const i of e) {
458
+ const r = `${t === "/" ? "" : t}/${i.name}`;
459
+ await this.remove(r, { recursive: !0 });
558
460
  }
559
- } catch (t) {
560
- throw t instanceof o ? t : new o(`Failed to clear directory: ${e}`, "CLEAR_FAILED");
461
+ } catch (e) {
462
+ throw e instanceof o ? e : new o(`Failed to clear directory: ${t}`, "CLEAR_FAILED");
561
463
  }
562
464
  }
563
465
  /**
@@ -584,18 +486,19 @@ class U {
584
486
  * await fs.rm('/maybe/exists', { force: true });
585
487
  * ```
586
488
  */
587
- async remove(e, t) {
588
- const r = t?.recursive ?? !1, n = t?.force ?? !1, i = f(e), s = i.pop();
589
- if (!s)
590
- throw new g("Invalid path", e);
591
- const c = await this.getDirectoryHandle(i, !1);
489
+ async remove(t, e) {
490
+ await this.ensureMounted();
491
+ const i = e?.recursive ?? !1, r = e?.force ?? !1, a = m(t);
492
+ if (!a)
493
+ throw new E("Invalid path", t);
494
+ const n = await this.getDirectoryHandle(y(t), !1);
592
495
  try {
593
- await c.removeEntry(s, { recursive: r });
594
- } catch (l) {
595
- if (l.name === "NotFoundError") {
596
- if (!n)
597
- throw new o(`No such file or directory: ${e}`, "ENOENT");
598
- } else throw l.name === "InvalidModificationError" ? new o(`Directory not empty: ${e}. Use recursive option to force removal.`, "ENOTEMPTY") : l.name === "TypeMismatchError" && !r ? new o(`Cannot remove directory without recursive option: ${e}`, "EISDIR") : new o(`Failed to remove path: ${e}`, "RM_FAILED");
496
+ await n.removeEntry(a, { recursive: i });
497
+ } catch (s) {
498
+ if (s.name === "NotFoundError") {
499
+ if (!r)
500
+ throw new o(`No such file or directory: ${t}`, "ENOENT");
501
+ } else throw s.name === "InvalidModificationError" ? new o(`Directory not empty: ${t}. Use recursive option to force removal.`, "ENOTEMPTY") : s.name === "TypeMismatchError" && !i ? new o(`Cannot remove directory without recursive option: ${t}`, "EISDIR") : new o(`Failed to remove path: ${t}`, "RM_FAILED");
599
502
  }
600
503
  }
601
504
  /**
@@ -616,23 +519,15 @@ class U {
616
519
  * console.log(absolute); // '/data/file.txt'
617
520
  * ```
618
521
  */
619
- async realpath(e) {
522
+ async realpath(t) {
523
+ await this.ensureMounted();
620
524
  try {
621
- const t = f(e), r = [];
622
- for (const s of t)
623
- if (!(s === "." || s === ""))
624
- if (s === "..") {
625
- if (r.length === 0)
626
- throw new o("Path escapes root", "EINVAL");
627
- r.length > 0 && r.pop();
628
- } else
629
- r.push(s);
630
- const n = p(r);
631
- if (!await this.exists(n))
632
- throw new m(n);
633
- return n;
634
- } catch (t) {
635
- throw t instanceof o ? t : new o(`Failed to resolve path: ${e}`, "REALPATH_FAILED");
525
+ const e = H(t);
526
+ if (!await this.exists(e))
527
+ throw new d(e);
528
+ return e;
529
+ } catch (e) {
530
+ throw e instanceof o ? e : new o(`Failed to resolve path: ${t}`, "REALPATH_FAILED");
636
531
  }
637
532
  }
638
533
  /**
@@ -651,13 +546,14 @@ class U {
651
546
  * await fs.rename('/old/path/file.txt', '/new/path/renamed.txt');
652
547
  * ```
653
548
  */
654
- async rename(e, t) {
549
+ async rename(t, e) {
550
+ await this.ensureMounted();
655
551
  try {
656
- if (!await this.exists(e))
657
- throw new m(e);
658
- await this.copy(e, t, { recursive: !0 }), await this.remove(e, { recursive: !0 });
659
- } catch (r) {
660
- throw r instanceof o ? r : new o(`Failed to rename from ${e} to ${t}`, "RENAME_FAILED");
552
+ if (!await this.exists(t))
553
+ throw new d(t);
554
+ await this.copy(t, e, { recursive: !0 }), await this.remove(t, { recursive: !0 });
555
+ } catch (i) {
556
+ throw i instanceof o ? i : new o(`Failed to rename from ${t} to ${e}`, "RENAME_FAILED");
661
557
  }
662
558
  }
663
559
  /**
@@ -676,91 +572,93 @@ class U {
676
572
  * @example
677
573
  * ```typescript
678
574
  * // Copy a file
679
- * await fs.cp('/source/file.txt', '/dest/file.txt');
575
+ * await fs.copy('/source/file.txt', '/dest/file.txt');
680
576
  *
681
577
  * // Copy a directory and all its contents
682
- * await fs.cp('/source/dir', '/dest/dir', { recursive: true });
578
+ * await fs.copy('/source/dir', '/dest/dir', { recursive: true });
683
579
  *
684
580
  * // Copy without overwriting existing files
685
- * await fs.cp('/source', '/dest', { recursive: true, force: false });
581
+ * await fs.copy('/source', '/dest', { recursive: true, force: false });
686
582
  * ```
687
583
  */
688
- async copy(e, t, r) {
584
+ async copy(t, e, i) {
585
+ await this.ensureMounted();
689
586
  try {
690
- const n = r?.recursive ?? !1, i = r?.force ?? !0;
691
- if (!await this.exists(e))
692
- throw new o(`Source does not exist: ${e}`, "ENOENT");
693
- if (await this.exists(t) && !i)
694
- throw new o(`Destination already exists: ${t}`, "EEXIST");
695
- if ((await this.stat(e)).isFile) {
696
- const h = await this.readFile(e, "binary");
697
- await this.writeFile(t, h);
587
+ const r = i?.recursive ?? !1, a = i?.force ?? !0;
588
+ if (!await this.exists(t))
589
+ throw new o(`Source does not exist: ${t}`, "ENOENT");
590
+ if (await this.exists(e) && !a)
591
+ throw new o(`Destination already exists: ${e}`, "EEXIST");
592
+ if ((await this.stat(t)).isFile) {
593
+ const l = await this.readFile(t, "binary");
594
+ await this.writeFile(e, l);
698
595
  } else {
699
- if (!n)
700
- throw new o(`Cannot copy directory without recursive option: ${e}`, "EISDIR");
701
- await this.mkdir(t, { recursive: !0 });
702
- const h = await this.readdir(e, { withFileTypes: !0 });
703
- for (const w of h) {
704
- const u = `${e}/${w.name}`, d = `${t}/${w.name}`;
705
- await this.copy(u, d, { recursive: !0, force: i });
596
+ if (!r)
597
+ throw new o(`Cannot copy directory without recursive option: ${t}`, "EISDIR");
598
+ await this.mkdir(e, { recursive: !0 });
599
+ const l = await this.readdir(t, { withFileTypes: !0 });
600
+ for (const h of l) {
601
+ const w = `${t}/${h.name}`, D = `${e}/${h.name}`;
602
+ await this.copy(w, D, { recursive: !0, force: a });
706
603
  }
707
604
  }
708
- } catch (n) {
709
- throw n instanceof o ? n : new o(`Failed to copy from ${e} to ${t}`, "CP_FAILED");
605
+ } catch (r) {
606
+ throw r instanceof o ? r : new o(`Failed to copy from ${t} to ${e}`, "CP_FAILED");
710
607
  }
711
608
  }
712
609
  /**
713
610
  * Start watching a file or directory for changes
714
611
  */
715
- async watch(e) {
716
- const t = e.startsWith("/") ? e : `/${e}`, r = await this.buildSnapshot(t);
717
- this.watchers.set(t, r), this.watchTimer || (this.watchTimer = setInterval(() => {
612
+ async watch(t) {
613
+ await this.ensureMounted();
614
+ const e = F(t), i = await this.buildSnapshot(e);
615
+ this.watchers.set(e, i), this.watchTimer || (this.watchTimer = setInterval(() => {
718
616
  this.scanWatches();
719
617
  }, this.watchInterval));
720
618
  }
721
619
  /**
722
620
  * Stop watching a previously watched path
723
621
  */
724
- unwatch(e) {
725
- const t = e.startsWith("/") ? e : `/${e}`;
726
- this.watchers.delete(t), this.watchers.size === 0 && this.watchTimer && (clearInterval(this.watchTimer), this.watchTimer = null);
727
- }
728
- async buildSnapshot(e) {
729
- const t = /* @__PURE__ */ new Map(), r = async (n) => {
730
- const i = await this.stat(n);
731
- if (t.set(n, i), i.isDirectory) {
732
- const s = await this.readdir(n, { withFileTypes: !0 });
733
- for (const c of s) {
734
- const l = `${n === "/" ? "" : n}/${c.name}`;
735
- await r(l);
622
+ unwatch(t) {
623
+ const e = F(t);
624
+ this.watchers.delete(e), this.watchers.size === 0 && this.watchTimer && (clearInterval(this.watchTimer), this.watchTimer = null);
625
+ }
626
+ async buildSnapshot(t) {
627
+ const e = /* @__PURE__ */ new Map(), i = async (r) => {
628
+ const a = await this.stat(r);
629
+ if (e.set(r, a), a.isDirectory) {
630
+ const n = await this.readdir(r, { withFileTypes: !0 });
631
+ for (const s of n) {
632
+ const c = `${r === "/" ? "" : r}/${s.name}`;
633
+ await i(c);
736
634
  }
737
635
  }
738
636
  };
739
- return await r(e), t;
637
+ return await i(t), e;
740
638
  }
741
639
  async scanWatches() {
742
640
  if (!this.scanning) {
743
641
  this.scanning = !0;
744
642
  try {
745
643
  await Promise.all(
746
- [...this.watchers.entries()].map(async ([e, t]) => {
747
- let r;
644
+ [...this.watchers.entries()].map(async ([t, e]) => {
645
+ let i;
748
646
  try {
749
- r = await this.buildSnapshot(e);
647
+ i = await this.buildSnapshot(t);
750
648
  } catch {
751
- r = /* @__PURE__ */ new Map();
649
+ i = /* @__PURE__ */ new Map();
752
650
  }
753
- const n = [];
754
- for (const [i, s] of r) {
755
- const c = t.get(i);
756
- c ? (c.mtime !== s.mtime || c.size !== s.size) && n.push({ path: i, type: "change" }) : n.push({ path: i, type: "create" });
651
+ const r = [];
652
+ for (const [a, n] of i) {
653
+ const s = e.get(a);
654
+ s ? (s.mtime !== n.mtime || s.size !== n.size) && r.push({ path: a, type: "change" }) : r.push({ path: a, type: "create" });
757
655
  }
758
- for (const i of t.keys())
759
- r.has(i) || n.push({ path: i, type: "delete" });
760
- if (n.length && this.watchCallback)
761
- for (const i of n)
762
- this.watchCallback(i);
763
- this.watchers.set(e, r);
656
+ for (const a of e.keys())
657
+ i.has(a) || r.push({ path: a, type: "delete" });
658
+ if (r.length && this.watchCallback)
659
+ for (const a of r)
660
+ this.watchCallback(a);
661
+ this.watchers.set(t, i);
764
662
  })
765
663
  );
766
664
  } finally {
@@ -796,26 +694,22 @@ class U {
796
694
  * await fs.sync(entries, { cleanBefore: true });
797
695
  * ```
798
696
  */
799
- async sync(e, t) {
697
+ async sync(t, e) {
698
+ await this.ensureMounted();
800
699
  try {
801
- (t?.cleanBefore ?? !1) && await this.clear("/");
802
- for (const [n, i] of e) {
803
- const s = n.startsWith("/") ? n : `/${n}`;
804
- let c;
805
- if (i instanceof Blob) {
806
- const l = await i.arrayBuffer();
807
- c = new Uint8Array(l);
808
- } else
809
- c = i;
810
- await this.writeFile(s, c);
700
+ (e?.cleanBefore ?? !1) && await this.clear("/");
701
+ for (const [r, a] of t) {
702
+ const n = F(r);
703
+ let s;
704
+ a instanceof Blob ? s = await P(a) : s = a, await this.writeFile(n, s);
811
705
  }
812
- } catch (r) {
813
- throw r instanceof o ? r : new o("Failed to sync file system", "SYNC_FAILED");
706
+ } catch (i) {
707
+ throw i instanceof o ? i : new o("Failed to sync file system", "SYNC_FAILED");
814
708
  }
815
709
  }
816
710
  }
817
- typeof self < "u" && self.constructor.name === "DedicatedWorkerGlobalScope" && E(new U());
711
+ typeof self < "u" && self.constructor.name === "DedicatedWorkerGlobalScope" && p(new $());
818
712
  export {
819
- U as OPFSWorker
713
+ $ as OPFSWorker
820
714
  };
821
715
  //# sourceMappingURL=raw.js.map