opfs-worker 0.1.2 → 0.2.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/dist/raw.js CHANGED
@@ -1,160 +1,25 @@
1
1
  import { expose as p } from "comlink";
2
- class s extends Error {
3
- constructor(e, t, n) {
4
- super(e), this.code = t, this.path = n, this.name = "OPFSError";
5
- }
6
- }
7
- class A extends s {
8
- constructor() {
9
- super("OPFS is not supported in this browser", "OPFS_NOT_SUPPORTED");
10
- }
11
- }
12
- class y extends s {
13
- constructor() {
14
- super("OPFS is not mounted", "OPFS_NOT_MOUNTED");
15
- }
16
- }
17
- class g extends s {
18
- constructor(e, t) {
19
- super(e, "INVALID_PATH", t);
20
- }
21
- }
22
- class m extends s {
23
- constructor(e) {
24
- super(`File not found: ${e}`, "FILE_NOT_FOUND", e);
25
- }
26
- }
27
- function S(r, e = "utf-8") {
28
- switch (e) {
29
- case "utf8":
30
- case "utf-8":
31
- return new TextEncoder().encode(r);
32
- case "utf16le":
33
- case "ucs2":
34
- case "ucs-2":
35
- return I(r);
36
- case "ascii":
37
- return H(r);
38
- case "latin1":
39
- return N(r);
40
- case "binary":
41
- return Uint8Array.from(r, (t) => t.charCodeAt(0));
42
- case "base64":
43
- return Uint8Array.from(atob(r), (t) => t.charCodeAt(0));
44
- case "hex":
45
- if (!/^[\da-f]+$/i.test(r) || r.length % 2 !== 0)
46
- throw new s("Invalid hex string", "INVALID_HEX_FORMAT");
47
- return Uint8Array.from(r.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(r);
50
- }
51
- }
52
- function D(r, e = "utf-8") {
53
- switch (e) {
54
- case "utf8":
55
- case "utf-8":
56
- return new TextDecoder().decode(r);
57
- case "utf16le":
58
- case "ucs2":
59
- case "ucs-2":
60
- return T(r);
61
- case "latin1":
62
- return String.fromCharCode(...r);
63
- case "binary":
64
- return String.fromCharCode(...r);
65
- case "ascii":
66
- return String.fromCharCode(...r.map((t) => t & 127));
67
- case "base64":
68
- return btoa(String.fromCharCode(...r));
69
- case "hex":
70
- return Array.from(r).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(r);
73
- }
74
- }
75
- function I(r) {
76
- const e = new Uint8Array(r.length * 2);
77
- for (let t = 0; t < r.length; t++) {
78
- const n = r.charCodeAt(t);
79
- e[t * 2] = n & 255, e[t * 2 + 1] = n >> 8;
80
- }
81
- return e;
82
- }
83
- function T(r) {
84
- r.length % 2 !== 0 && (console.warn("Invalid UTF-16LE buffer length, truncating last byte"), r = r.slice(0, r.length - 1));
85
- const e = new Uint16Array(r.buffer, r.byteOffset, r.byteLength / 2);
86
- return String.fromCharCode(...e);
87
- }
88
- function N(r) {
89
- const e = new Uint8Array(r.length);
90
- for (let t = 0; t < r.length; t++)
91
- e[t] = r.charCodeAt(t) & 255;
92
- return e;
93
- }
94
- function H(r) {
95
- const e = new Uint8Array(r.length);
96
- for (let t = 0; t < r.length; t++)
97
- e[t] = r.charCodeAt(t) & 127;
98
- return e;
99
- }
100
- function $() {
101
- if (!("storage" in navigator) || !("getDirectory" in navigator.storage))
102
- throw new A();
103
- }
104
- function u(r) {
105
- return Array.isArray(r) ? r : r.split("/").filter(Boolean);
106
- }
107
- function F(r) {
108
- return typeof r == "string" ? r ?? "/" : `/${r.join("/")}`;
109
- }
110
- function O(r, e = "utf-8") {
111
- return typeof r == "string" ? S(r, e) : r instanceof Uint8Array ? r : new Uint8Array(r);
112
- }
113
- async function x(r) {
114
- const e = await r.createSyncAccessHandle();
115
- try {
116
- const t = e.getSize(), n = new Uint8Array(t);
117
- return e.read(n, { at: 0 }), n;
118
- } finally {
119
- e.close();
120
- }
121
- }
122
- async function E(r, e, t, n = {}) {
123
- let o = null;
124
- try {
125
- o = await r.createSyncAccessHandle();
126
- const i = O(e, t), a = n.append ? o.getSize() : 0;
127
- o.write(i, { at: a }), n.truncate && !n.append && o.truncate(i.byteLength), o.flush();
128
- } catch (i) {
129
- console.error(i);
130
- const a = n.append ? "append" : "write";
131
- throw new s(`Failed to ${a} file`, `${a.toUpperCase()}_FAILED`);
132
- } finally {
133
- if (o)
134
- try {
135
- o.close();
136
- } catch {
137
- }
138
- }
139
- }
140
- async function v(r, e = "SHA-1") {
141
- try {
142
- const t = new Uint8Array(r), n = await crypto.subtle.digest(e, t);
143
- return Array.from(new Uint8Array(n)).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 {
2
+ import { d as v, O as o, b as f, s as y, P as E, i as I, o as S, F as d, w as g, j as T, e as u, f as m, k as H, r as $, n as F, l as A } from "./helpers-Co-qCBmA.js";
3
+ class N {
149
4
  /** Root directory handle for the file system */
150
5
  root = null;
6
+ /** Watch event callback */
7
+ watchCallback = null;
8
+ /** Map of watched paths to their last known state */
9
+ watchers = /* @__PURE__ */ new Map();
10
+ /** Interval handle for polling watched paths */
11
+ watchTimer = null;
12
+ /** Polling interval in milliseconds */
13
+ watchInterval = 1e3;
14
+ /** Flag to avoid concurrent scans */
15
+ scanning = !1;
151
16
  /**
152
17
  * Creates a new OPFSFileSystem instance
153
18
  *
154
19
  * @throws {OPFSError} If OPFS is not supported in the current browser
155
20
  */
156
21
  constructor() {
157
- $();
22
+ v();
158
23
  }
159
24
  /**
160
25
  * Initialize the file system within a given directory
@@ -172,12 +37,12 @@ class U {
172
37
  * const success = await fs.init('/my-app');
173
38
  * ```
174
39
  */
175
- async mount(e = "/") {
40
+ async mount(t = "/", e, a) {
176
41
  try {
177
- const t = await navigator.storage.getDirectory();
178
- return this.root = await this.getDirectoryHandle(e, !0, t), !0;
179
- } catch (t) {
180
- throw console.error(t), new s("Failed to initialize OPFS", "INIT_FAILED");
42
+ const r = await navigator.storage.getDirectory();
43
+ return this.root = await this.getDirectoryHandle(t, !0, r), e && (this.watchCallback = e, a?.watchInterval && (this.watchInterval = a.watchInterval)), !0;
44
+ } catch (r) {
45
+ throw console.error(r), new o("Failed to initialize OPFS", "INIT_FAILED");
181
46
  }
182
47
  }
183
48
  /**
@@ -198,13 +63,13 @@ class U {
198
63
  * const docsDir2 = await fs.getDirectoryHandle(['users', 'john', 'documents'], true);
199
64
  * ```
200
65
  */
201
- async getDirectoryHandle(e, t = !1, n = this.root) {
202
- if (!n)
203
- throw new y();
204
- const o = Array.isArray(e) ? e : u(e);
205
- let i = n;
206
- for (const a of o)
207
- i = await i.getDirectoryHandle(a, { create: t });
66
+ async getDirectoryHandle(t, e = !1, a = this.root) {
67
+ if (!a)
68
+ throw new f();
69
+ const r = Array.isArray(t) ? t : y(t);
70
+ let i = a;
71
+ for (const n of r)
72
+ i = await i.getDirectoryHandle(n, { create: e });
208
73
  return i;
209
74
  }
210
75
  /**
@@ -226,14 +91,14 @@ class U {
226
91
  * const fileHandle2 = await fs.getFileHandle(['config', 'settings.json'], true);
227
92
  * ```
228
93
  */
229
- async getFileHandle(e, t = !1, n = this.root) {
230
- if (!n)
231
- throw new y();
232
- const o = u(e);
233
- if (o.length === 0)
234
- throw new g("Path must not be empty", Array.isArray(e) ? e.join("/") : e);
235
- const i = o.pop();
236
- return (await this.getDirectoryHandle(o, t, n)).getFileHandle(i, { create: t });
94
+ async getFileHandle(t, e = !1, a = this.root) {
95
+ if (!a)
96
+ throw new f();
97
+ const r = y(t);
98
+ if (r.length === 0)
99
+ throw new E("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
100
+ const i = r.pop();
101
+ return (await this.getDirectoryHandle(r, e, a)).getFileHandle(i, { create: e });
237
102
  }
238
103
  /**
239
104
  * Recursively list all files and directories with their stats
@@ -272,34 +137,34 @@ class U {
272
137
  * }
273
138
  * ```
274
139
  */
275
- async index(e) {
276
- const t = /* @__PURE__ */ new Map(), n = async (o) => {
277
- const i = await this.readdir(o, { withFileTypes: !0 });
278
- for (const a of i) {
279
- const l = `${o === "/" ? "" : o}/${a.name}`;
140
+ async index(t) {
141
+ const e = /* @__PURE__ */ new Map(), a = async (r) => {
142
+ const i = await this.readdir(r, { withFileTypes: !0 });
143
+ for (const n of i) {
144
+ const s = `${r === "/" ? "" : r}/${n.name}`;
280
145
  try {
281
- const c = await this.stat(l, e);
282
- t.set(l, c), c.isDirectory && await n(l);
146
+ const c = await this.stat(s, t);
147
+ e.set(s, c), c.isDirectory && await a(s);
283
148
  } catch (c) {
284
- console.warn(`Skipping broken entry: ${l}`, c);
149
+ console.warn(`Skipping broken entry: ${s}`, c);
285
150
  }
286
151
  }
287
152
  };
288
- return t.set("/", {
153
+ return e.set("/", {
289
154
  kind: "directory",
290
155
  size: 0,
291
156
  mtime: (/* @__PURE__ */ new Date(0)).toISOString(),
292
157
  ctime: (/* @__PURE__ */ new Date(0)).toISOString(),
293
158
  isFile: !1,
294
159
  isDirectory: !0
295
- }), await n("/"), t;
160
+ }), await a("/"), e;
296
161
  }
297
- async readFile(e, t = "utf-8") {
162
+ async readFile(t, e = "utf-8") {
298
163
  try {
299
- const n = await this.getFileHandle(e, !1), o = await x(n);
300
- return t === "binary" ? o : D(o, t);
301
- } catch (n) {
302
- throw console.error(n), new m(e);
164
+ const a = await this.getFileHandle(t, !1), r = await I(a);
165
+ return e === "binary" ? r : S(r, e);
166
+ } catch (a) {
167
+ throw console.error(a), new d(t);
303
168
  }
304
169
  }
305
170
  /**
@@ -327,9 +192,9 @@ class U {
327
192
  * await fs.writeFile('/data/utf16.txt', 'Hello World', 'utf-16le');
328
193
  * ```
329
194
  */
330
- async writeFile(e, t, n) {
331
- const o = await this.getFileHandle(e, !0);
332
- await E(o, t, n, { truncate: !0 });
195
+ async writeFile(t, e, a) {
196
+ const r = await this.getFileHandle(t, !0);
197
+ await g(r, e, a, { truncate: !0 });
333
198
  }
334
199
  /**
335
200
  * Append data to a file
@@ -353,9 +218,9 @@ class U {
353
218
  * await fs.appendFile('/data/binary.dat', additionalData);
354
219
  * ```
355
220
  */
356
- async appendFile(e, t, n) {
357
- const o = await this.getFileHandle(e, !0);
358
- await E(o, t, n, { append: !0 });
221
+ async appendFile(t, e, a) {
222
+ const r = await this.getFileHandle(t, !0);
223
+ await g(r, e, a, { append: !0 });
359
224
  }
360
225
  /**
361
226
  * Create a directory
@@ -378,20 +243,20 @@ class U {
378
243
  * await fs.mkdir('/users/john/documents/projects', { recursive: true });
379
244
  * ```
380
245
  */
381
- async mkdir(e, t) {
246
+ async mkdir(t, e) {
382
247
  if (!this.root)
383
- throw new y();
384
- const n = t?.recursive ?? !1, o = u(e);
248
+ throw new f();
249
+ const a = e?.recursive ?? !1, r = y(t);
385
250
  let i = this.root;
386
- for (let a = 0; a < o.length; a++) {
387
- const l = o[a];
251
+ for (let n = 0; n < r.length; n++) {
252
+ const s = r[n];
388
253
  try {
389
- i = await i.getDirectoryHandle(l, { create: n || a === o.length - 1 });
254
+ i = await i.getDirectoryHandle(s, { create: a || n === r.length - 1 });
390
255
  } catch (c) {
391
- throw c.name === "NotFoundError" ? new s(
392
- `Parent directory does not exist: ${F(o.slice(0, a + 1))}`,
256
+ throw c.name === "NotFoundError" ? new o(
257
+ `Parent directory does not exist: ${T(r.slice(0, n + 1))}`,
393
258
  "ENOENT"
394
- ) : c.name === "TypeMismatchError" ? new s(`Path segment is not a directory: ${l}`, "ENOTDIR") : new s("Failed to create directory", "MKDIR_FAILED");
259
+ ) : c.name === "TypeMismatchError" ? new o(`Path segment is not a directory: ${s}`, "ENOTDIR") : new o("Failed to create directory", "MKDIR_FAILED");
395
260
  }
396
261
  }
397
262
  }
@@ -424,52 +289,51 @@ class U {
424
289
  * console.log(`Hash: ${statsWithHash.hash}`);
425
290
  * ```
426
291
  */
427
- async stat(e, t) {
428
- const n = u(e), o = n.pop(), i = await this.getDirectoryHandle(n, !1), a = t?.includeHash ?? !1, l = t?.hashAlgorithm ?? "SHA-1";
292
+ async stat(t, e) {
293
+ const a = u(t), r = await this.getDirectoryHandle(m(t), !1), i = e?.includeHash ?? !1, n = e?.hashAlgorithm ?? "SHA-1";
429
294
  try {
430
- const f = await (await i.getFileHandle(o, { create: !1 })).getFile(), h = {
295
+ const c = await (await r.getFileHandle(a, { create: !1 })).getFile(), l = {
431
296
  kind: "file",
432
- size: f.size,
433
- mtime: new Date(f.lastModified).toISOString(),
434
- ctime: new Date(f.lastModified).toISOString(),
297
+ size: c.size,
298
+ mtime: new Date(c.lastModified).toISOString(),
299
+ ctime: new Date(c.lastModified).toISOString(),
435
300
  isFile: !0,
436
301
  isDirectory: !1
437
302
  };
438
- if (a)
303
+ if (i)
439
304
  try {
440
- const w = new Uint8Array(await f.arrayBuffer()), d = await v(w, l);
441
- h.hash = d;
442
- } catch (w) {
443
- console.warn(`Failed to calculate hash for ${e}:`, w);
305
+ const h = new Uint8Array(await c.arrayBuffer()), w = await H(h, n);
306
+ l.hash = w;
307
+ } catch (h) {
308
+ console.warn(`Failed to calculate hash for ${t}:`, h);
444
309
  }
445
- return h;
446
- } catch (c) {
447
- if (c.name !== "TypeMismatchError" && c.name !== "NotFoundError")
448
- throw new s("Failed to stat (file)", "STAT_FAILED");
310
+ return l;
311
+ } catch (s) {
312
+ if (s.name !== "TypeMismatchError" && s.name !== "NotFoundError")
313
+ throw new o("Failed to stat (file)", "STAT_FAILED");
449
314
  }
450
315
  try {
451
- return await i.getDirectoryHandle(o, { create: !1 }), {
316
+ return await r.getDirectoryHandle(a, { create: !1 }), {
452
317
  kind: "directory",
453
318
  size: 0,
454
319
  mtime: (/* @__PURE__ */ new Date(0)).toISOString(),
455
320
  ctime: (/* @__PURE__ */ new Date(0)).toISOString(),
456
321
  isFile: !1,
457
322
  isDirectory: !0
458
- // Directories don't have hashes
459
323
  };
460
- } catch (c) {
461
- throw c.name === "NotFoundError" ? new s(`No such file or directory: ${e}`, "ENOENT") : new s("Failed to stat (directory)", "STAT_FAILED");
324
+ } catch (s) {
325
+ throw s.name === "NotFoundError" ? new o(`No such file or directory: ${t}`, "ENOENT") : new o("Failed to stat (directory)", "STAT_FAILED");
462
326
  }
463
327
  }
464
- async readdir(e, t) {
465
- const n = t?.withFileTypes ?? !1, o = await this.getDirectoryHandle(e, !1);
466
- if (n) {
328
+ async readdir(t, e) {
329
+ const a = e?.withFileTypes ?? !1, r = await this.getDirectoryHandle(t, !1);
330
+ if (a) {
467
331
  const i = [];
468
- for await (const [a, l] of o.entries()) {
469
- const c = l.kind === "file";
332
+ for await (const [n, s] of r.entries()) {
333
+ const c = s.kind === "file";
470
334
  i.push({
471
- name: a,
472
- kind: l.kind,
335
+ name: n,
336
+ kind: s.kind,
473
337
  isFile: c,
474
338
  isDirectory: !c
475
339
  });
@@ -477,8 +341,8 @@ class U {
477
341
  return i;
478
342
  } else {
479
343
  const i = [];
480
- for await (const [a] of o.entries())
481
- i.push(a);
344
+ for await (const [n] of r.entries())
345
+ i.push(n);
482
346
  return i;
483
347
  }
484
348
  }
@@ -496,27 +360,27 @@ class U {
496
360
  * console.log(`File exists: ${exists}`);
497
361
  * ```
498
362
  */
499
- async exists(e) {
500
- const t = u(e), n = t.pop();
501
- let o = null;
363
+ async exists(t) {
364
+ const e = u(t);
365
+ let a = null;
502
366
  try {
503
- o = await this.getDirectoryHandle(t, !1);
504
- } catch (i) {
505
- throw (i.name === "NotFoundError" || i.name === "TypeMismatchError") && (o = null), i;
367
+ a = await this.getDirectoryHandle(m(t), !1);
368
+ } catch (r) {
369
+ throw (r.name === "NotFoundError" || r.name === "TypeMismatchError") && (a = null), r;
506
370
  }
507
- if (!o || !n)
371
+ if (!a || !e)
508
372
  return !1;
509
373
  try {
510
- return await o.getFileHandle(n, { create: !1 }), !0;
511
- } catch (i) {
512
- if (i.name !== "NotFoundError" && i.name !== "TypeMismatchError")
513
- throw i;
374
+ return await a.getFileHandle(e, { create: !1 }), !0;
375
+ } catch (r) {
376
+ if (r.name !== "NotFoundError" && r.name !== "TypeMismatchError")
377
+ throw r;
514
378
  }
515
379
  try {
516
- return await o.getDirectoryHandle(n, { create: !1 }), !0;
517
- } catch (i) {
518
- if (i.name !== "NotFoundError" && i.name !== "TypeMismatchError")
519
- throw i;
380
+ return await a.getDirectoryHandle(e, { create: !1 }), !0;
381
+ } catch (r) {
382
+ if (r.name !== "NotFoundError" && r.name !== "TypeMismatchError")
383
+ throw r;
520
384
  }
521
385
  return !1;
522
386
  }
@@ -539,15 +403,15 @@ class U {
539
403
  * await fs.clear('/data');
540
404
  * ```
541
405
  */
542
- async clear(e = "/") {
406
+ async clear(t = "/") {
543
407
  try {
544
- const t = await this.readdir(e, { withFileTypes: !0 });
545
- for (const n of t) {
546
- const o = `${e === "/" ? "" : e}/${n.name}`;
547
- await this.remove(o, { recursive: !0 });
408
+ const e = await this.readdir(t, { withFileTypes: !0 });
409
+ for (const a of e) {
410
+ const r = `${t === "/" ? "" : t}/${a.name}`;
411
+ await this.remove(r, { recursive: !0 });
548
412
  }
549
- } catch (t) {
550
- throw t instanceof s ? t : new s(`Failed to clear directory: ${e}`, "CLEAR_FAILED");
413
+ } catch (e) {
414
+ throw e instanceof o ? e : new o(`Failed to clear directory: ${t}`, "CLEAR_FAILED");
551
415
  }
552
416
  }
553
417
  /**
@@ -574,18 +438,18 @@ class U {
574
438
  * await fs.rm('/maybe/exists', { force: true });
575
439
  * ```
576
440
  */
577
- async remove(e, t) {
578
- const n = t?.recursive ?? !1, o = t?.force ?? !1, i = u(e), a = i.pop();
579
- if (!a)
580
- throw new g("Invalid path", e);
581
- const l = await this.getDirectoryHandle(i, !1);
441
+ async remove(t, e) {
442
+ const a = e?.recursive ?? !1, r = e?.force ?? !1, i = u(t);
443
+ if (!i)
444
+ throw new E("Invalid path", t);
445
+ const n = await this.getDirectoryHandle(m(t), !1);
582
446
  try {
583
- await l.removeEntry(a, { recursive: n });
584
- } catch (c) {
585
- if (c.name === "NotFoundError") {
586
- if (!o)
587
- throw new s(`No such file or directory: ${e}`, "ENOENT");
588
- } else throw c.name === "InvalidModificationError" ? new s(`Directory not empty: ${e}. Use recursive option to force removal.`, "ENOTEMPTY") : c.name === "TypeMismatchError" && !n ? new s(`Cannot remove directory without recursive option: ${e}`, "EISDIR") : new s(`Failed to remove path: ${e}`, "RM_FAILED");
447
+ await n.removeEntry(i, { recursive: a });
448
+ } catch (s) {
449
+ if (s.name === "NotFoundError") {
450
+ if (!r)
451
+ throw new o(`No such file or directory: ${t}`, "ENOENT");
452
+ } else throw s.name === "InvalidModificationError" ? new o(`Directory not empty: ${t}. Use recursive option to force removal.`, "ENOTEMPTY") : s.name === "TypeMismatchError" && !a ? new o(`Cannot remove directory without recursive option: ${t}`, "EISDIR") : new o(`Failed to remove path: ${t}`, "RM_FAILED");
589
453
  }
590
454
  }
591
455
  /**
@@ -606,23 +470,14 @@ class U {
606
470
  * console.log(absolute); // '/data/file.txt'
607
471
  * ```
608
472
  */
609
- async realpath(e) {
473
+ async realpath(t) {
610
474
  try {
611
- const t = u(e), n = [];
612
- for (const a of t)
613
- if (!(a === "." || a === ""))
614
- if (a === "..") {
615
- if (n.length === 0)
616
- throw new s("Path escapes root", "EINVAL");
617
- n.length > 0 && n.pop();
618
- } else
619
- n.push(a);
620
- const o = F(n);
621
- if (!await this.exists(o))
622
- throw new m(o);
623
- return o;
624
- } catch (t) {
625
- throw t instanceof s ? t : new s(`Failed to resolve path: ${e}`, "REALPATH_FAILED");
475
+ const e = $(t);
476
+ if (!await this.exists(e))
477
+ throw new d(e);
478
+ return e;
479
+ } catch (e) {
480
+ throw e instanceof o ? e : new o(`Failed to resolve path: ${t}`, "REALPATH_FAILED");
626
481
  }
627
482
  }
628
483
  /**
@@ -641,13 +496,13 @@ class U {
641
496
  * await fs.rename('/old/path/file.txt', '/new/path/renamed.txt');
642
497
  * ```
643
498
  */
644
- async rename(e, t) {
499
+ async rename(t, e) {
645
500
  try {
646
- if (!await this.exists(e))
647
- throw new m(e);
648
- await this.copy(e, t, { recursive: !0 }), await this.remove(e, { recursive: !0 });
649
- } catch (n) {
650
- throw n instanceof s ? n : new s(`Failed to rename from ${e} to ${t}`, "RENAME_FAILED");
501
+ if (!await this.exists(t))
502
+ throw new d(t);
503
+ await this.copy(t, e, { recursive: !0 }), await this.remove(t, { recursive: !0 });
504
+ } catch (a) {
505
+ throw a instanceof o ? a : new o(`Failed to rename from ${t} to ${e}`, "RENAME_FAILED");
651
506
  }
652
507
  }
653
508
  /**
@@ -675,28 +530,87 @@ class U {
675
530
  * await fs.cp('/source', '/dest', { recursive: true, force: false });
676
531
  * ```
677
532
  */
678
- async copy(e, t, n) {
533
+ async copy(t, e, a) {
679
534
  try {
680
- const o = n?.recursive ?? !1, i = n?.force ?? !0;
681
- if (!await this.exists(e))
682
- throw new s(`Source does not exist: ${e}`, "ENOENT");
683
- if (await this.exists(t) && !i)
684
- throw new s(`Destination already exists: ${t}`, "EEXIST");
685
- if ((await this.stat(e)).isFile) {
686
- const f = await this.readFile(e, "binary");
687
- await this.writeFile(t, f);
535
+ const r = a?.recursive ?? !1, i = a?.force ?? !0;
536
+ if (!await this.exists(t))
537
+ throw new o(`Source does not exist: ${t}`, "ENOENT");
538
+ if (await this.exists(e) && !i)
539
+ throw new o(`Destination already exists: ${e}`, "EEXIST");
540
+ if ((await this.stat(t)).isFile) {
541
+ const l = await this.readFile(t, "binary");
542
+ await this.writeFile(e, l);
688
543
  } else {
689
- if (!o)
690
- throw new s(`Cannot copy directory without recursive option: ${e}`, "EISDIR");
691
- await this.mkdir(t, { recursive: !0 });
692
- const f = await this.readdir(e, { withFileTypes: !0 });
693
- for (const h of f) {
694
- const w = `${e}/${h.name}`, d = `${t}/${h.name}`;
695
- await this.copy(w, d, { recursive: !0, force: i });
544
+ if (!r)
545
+ throw new o(`Cannot copy directory without recursive option: ${t}`, "EISDIR");
546
+ await this.mkdir(e, { recursive: !0 });
547
+ const l = await this.readdir(t, { withFileTypes: !0 });
548
+ for (const h of l) {
549
+ const w = `${t}/${h.name}`, D = `${e}/${h.name}`;
550
+ await this.copy(w, D, { recursive: !0, force: i });
551
+ }
552
+ }
553
+ } catch (r) {
554
+ throw r instanceof o ? r : new o(`Failed to copy from ${t} to ${e}`, "CP_FAILED");
555
+ }
556
+ }
557
+ /**
558
+ * Start watching a file or directory for changes
559
+ */
560
+ async watch(t) {
561
+ const e = F(t), a = await this.buildSnapshot(e);
562
+ this.watchers.set(e, a), this.watchTimer || (this.watchTimer = setInterval(() => {
563
+ this.scanWatches();
564
+ }, this.watchInterval));
565
+ }
566
+ /**
567
+ * Stop watching a previously watched path
568
+ */
569
+ unwatch(t) {
570
+ const e = F(t);
571
+ this.watchers.delete(e), this.watchers.size === 0 && this.watchTimer && (clearInterval(this.watchTimer), this.watchTimer = null);
572
+ }
573
+ async buildSnapshot(t) {
574
+ const e = /* @__PURE__ */ new Map(), a = async (r) => {
575
+ const i = await this.stat(r);
576
+ if (e.set(r, i), i.isDirectory) {
577
+ const n = await this.readdir(r, { withFileTypes: !0 });
578
+ for (const s of n) {
579
+ const c = `${r === "/" ? "" : r}/${s.name}`;
580
+ await a(c);
696
581
  }
697
582
  }
698
- } catch (o) {
699
- throw o instanceof s ? o : new s(`Failed to copy from ${e} to ${t}`, "CP_FAILED");
583
+ };
584
+ return await a(t), e;
585
+ }
586
+ async scanWatches() {
587
+ if (!this.scanning) {
588
+ this.scanning = !0;
589
+ try {
590
+ await Promise.all(
591
+ [...this.watchers.entries()].map(async ([t, e]) => {
592
+ let a;
593
+ try {
594
+ a = await this.buildSnapshot(t);
595
+ } catch {
596
+ a = /* @__PURE__ */ new Map();
597
+ }
598
+ const r = [];
599
+ for (const [i, n] of a) {
600
+ const s = e.get(i);
601
+ s ? (s.mtime !== n.mtime || s.size !== n.size) && r.push({ path: i, type: "change" }) : r.push({ path: i, type: "create" });
602
+ }
603
+ for (const i of e.keys())
604
+ a.has(i) || r.push({ path: i, type: "delete" });
605
+ if (r.length && this.watchCallback)
606
+ for (const i of r)
607
+ this.watchCallback(i);
608
+ this.watchers.set(t, a);
609
+ })
610
+ );
611
+ } finally {
612
+ this.scanning = !1;
613
+ }
700
614
  }
701
615
  }
702
616
  /**
@@ -727,26 +641,21 @@ class U {
727
641
  * await fs.sync(entries, { cleanBefore: true });
728
642
  * ```
729
643
  */
730
- async sync(e, t) {
644
+ async sync(t, e) {
731
645
  try {
732
- (t?.cleanBefore ?? !1) && await this.clear("/");
733
- for (const [o, i] of e) {
734
- const a = o.startsWith("/") ? o : `/${o}`;
735
- let l;
736
- if (i instanceof Blob) {
737
- const c = await i.arrayBuffer();
738
- l = new Uint8Array(c);
739
- } else
740
- l = i;
741
- await this.writeFile(a, l);
646
+ (e?.cleanBefore ?? !1) && await this.clear("/");
647
+ for (const [r, i] of t) {
648
+ const n = F(r);
649
+ let s;
650
+ i instanceof Blob ? s = await A(i) : s = i, await this.writeFile(n, s);
742
651
  }
743
- } catch (n) {
744
- throw n instanceof s ? n : new s("Failed to sync file system", "SYNC_FAILED");
652
+ } catch (a) {
653
+ throw a instanceof o ? a : new o("Failed to sync file system", "SYNC_FAILED");
745
654
  }
746
655
  }
747
656
  }
748
- p(new U());
657
+ typeof self < "u" && self.constructor.name === "DedicatedWorkerGlobalScope" && p(new N());
749
658
  export {
750
- U as OPFSWorker
659
+ N as OPFSWorker
751
660
  };
752
661
  //# sourceMappingURL=raw.js.map