opfs-worker 0.2.5 → 0.3.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.
package/dist/index.cjs CHANGED
@@ -1,19 +1,19 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("comlink"),n=require("./helpers-DjY2OR7f.cjs"),o=`/**
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("comlink"),n=require("./helpers-FvdHLObV.cjs"),i=`/**
2
2
  * @license
3
3
  * Copyright 2019 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- const H = Symbol("Comlink.proxy"), R = Symbol("Comlink.endpoint"), B = Symbol("Comlink.releaseProxy"), D = Symbol("Comlink.finalizer"), p = Symbol("Comlink.thrown"), $ = (e) => typeof e == "object" && e !== null || typeof e == "function", W = {
6
+ const H = Symbol("Comlink.proxy"), R = Symbol("Comlink.endpoint"), B = Symbol("Comlink.releaseProxy"), A = Symbol("Comlink.finalizer"), E = Symbol("Comlink.thrown"), $ = (e) => typeof e == "object" && e !== null || typeof e == "function", W = {
7
7
  canHandle: (e) => $(e) && e[H],
8
8
  serialize(e) {
9
9
  const { port1: t, port2: r } = new MessageChannel();
10
- return P(e, t), [r, [r]];
10
+ return I(e, t), [r, [r]];
11
11
  },
12
12
  deserialize(e) {
13
13
  return e.start(), Y(e);
14
14
  }
15
15
  }, j = {
16
- canHandle: (e) => $(e) && p in e,
16
+ canHandle: (e) => $(e) && E in e,
17
17
  serialize({ value: e }) {
18
18
  let t;
19
19
  return e instanceof Error ? t = {
@@ -28,7 +28,7 @@ const H = Symbol("Comlink.proxy"), R = Symbol("Comlink.endpoint"), B = Symbol("C
28
28
  deserialize(e) {
29
29
  throw e.isError ? Object.assign(new Error(e.value.message), e.value) : e.value;
30
30
  }
31
- }, U = /* @__PURE__ */ new Map([
31
+ }, z = /* @__PURE__ */ new Map([
32
32
  ["proxy", W],
33
33
  ["throw", j]
34
34
  ]);
@@ -38,7 +38,7 @@ function V(e, t) {
38
38
  return !0;
39
39
  return !1;
40
40
  }
41
- function P(e, t = globalThis, r = ["*"]) {
41
+ function I(e, t = globalThis, r = ["*"]) {
42
42
  t.addEventListener("message", function n(i) {
43
43
  if (!i || !i.data)
44
44
  return;
@@ -46,7 +46,7 @@ function P(e, t = globalThis, r = ["*"]) {
46
46
  console.warn(\`Invalid origin '\${i.origin}' for comlink proxy\`);
47
47
  return;
48
48
  }
49
- const { id: a, type: s, path: o } = Object.assign({ path: [] }, i.data), l = (i.data.argumentList || []).map(y);
49
+ const { id: a, type: s, path: o } = Object.assign({ path: [] }, i.data), l = (i.data.argumentList || []).map(d);
50
50
  let h;
51
51
  try {
52
52
  const u = o.slice(0, -1).reduce((f, g) => f[g], e), w = o.reduce((f, g) => f[g], e);
@@ -55,7 +55,7 @@ function P(e, t = globalThis, r = ["*"]) {
55
55
  h = w;
56
56
  break;
57
57
  case "SET":
58
- u[o.slice(-1)[0]] = y(i.data.value), h = !0;
58
+ u[o.slice(-1)[0]] = d(i.data.value), h = !0;
59
59
  break;
60
60
  case "APPLY":
61
61
  h = w.apply(u, l);
@@ -69,7 +69,7 @@ function P(e, t = globalThis, r = ["*"]) {
69
69
  case "ENDPOINT":
70
70
  {
71
71
  const { port1: f, port2: g } = new MessageChannel();
72
- P(e, g), h = J(f, [f]);
72
+ I(e, g), h = J(f, [f]);
73
73
  }
74
74
  break;
75
75
  case "RELEASE":
@@ -79,15 +79,15 @@ function P(e, t = globalThis, r = ["*"]) {
79
79
  return;
80
80
  }
81
81
  } catch (u) {
82
- h = { value: u, [p]: 0 };
82
+ h = { value: u, [E]: 0 };
83
83
  }
84
- Promise.resolve(h).catch((u) => ({ value: u, [p]: 0 })).then((u) => {
85
- const [w, f] = A(u);
86
- t.postMessage(Object.assign(Object.assign({}, w), { id: a }), f), s === "RELEASE" && (t.removeEventListener("message", n), L(t), D in e && typeof e[D] == "function" && e[D]());
84
+ Promise.resolve(h).catch((u) => ({ value: u, [E]: 0 })).then((u) => {
85
+ const [w, f] = D(u);
86
+ t.postMessage(Object.assign(Object.assign({}, w), { id: a }), f), s === "RELEASE" && (t.removeEventListener("message", n), L(t), A in e && typeof e[A] == "function" && e[A]());
87
87
  }).catch((u) => {
88
- const [w, f] = A({
88
+ const [w, f] = D({
89
89
  value: new TypeError("Unserializable return value"),
90
- [p]: 0
90
+ [E]: 0
91
91
  });
92
92
  t.postMessage(Object.assign(Object.assign({}, w), { id: a }), f);
93
93
  });
@@ -112,14 +112,14 @@ function Y(e, t) {
112
112
  } finally {
113
113
  r.delete(a.id);
114
114
  }
115
- }), I(e, r, [], t);
115
+ }), x(e, r, [], t);
116
116
  }
117
- function E(e) {
117
+ function p(e) {
118
118
  if (e)
119
119
  throw new Error("Proxy has been released and is not useable");
120
120
  }
121
- function z(e) {
122
- return d(e, /* @__PURE__ */ new Map(), {
121
+ function U(e) {
122
+ return y(e, /* @__PURE__ */ new Map(), {
123
123
  type: "RELEASE"
124
124
  }).then(() => {
125
125
  L(e);
@@ -127,7 +127,7 @@ function z(e) {
127
127
  }
128
128
  const F = /* @__PURE__ */ new WeakMap(), S = "FinalizationRegistry" in globalThis && new FinalizationRegistry((e) => {
129
129
  const t = (F.get(e) || 0) - 1;
130
- F.set(e, t), t === 0 && z(e);
130
+ F.set(e, t), t === 0 && U(e);
131
131
  });
132
132
  function X(e, t) {
133
133
  const r = (F.get(t) || 0) + 1;
@@ -136,59 +136,59 @@ function X(e, t) {
136
136
  function q(e) {
137
137
  S && S.unregister(e);
138
138
  }
139
- function I(e, t, r = [], n = function() {
139
+ function x(e, t, r = [], n = function() {
140
140
  }) {
141
141
  let i = !1;
142
142
  const a = new Proxy(n, {
143
143
  get(s, o) {
144
- if (E(i), o === B)
144
+ if (p(i), o === B)
145
145
  return () => {
146
- q(a), z(e), t.clear(), i = !0;
146
+ q(a), U(e), t.clear(), i = !0;
147
147
  };
148
148
  if (o === "then") {
149
149
  if (r.length === 0)
150
150
  return { then: () => a };
151
- const l = d(e, t, {
151
+ const l = y(e, t, {
152
152
  type: "GET",
153
153
  path: r.map((h) => h.toString())
154
- }).then(y);
154
+ }).then(d);
155
155
  return l.then.bind(l);
156
156
  }
157
- return I(e, t, [...r, o]);
157
+ return x(e, t, [...r, o]);
158
158
  },
159
159
  set(s, o, l) {
160
- E(i);
161
- const [h, u] = A(l);
162
- return d(e, t, {
160
+ p(i);
161
+ const [h, u] = D(l);
162
+ return y(e, t, {
163
163
  type: "SET",
164
164
  path: [...r, o].map((w) => w.toString()),
165
165
  value: h
166
- }, u).then(y);
166
+ }, u).then(d);
167
167
  },
168
168
  apply(s, o, l) {
169
- E(i);
169
+ p(i);
170
170
  const h = r[r.length - 1];
171
171
  if (h === R)
172
- return d(e, t, {
172
+ return y(e, t, {
173
173
  type: "ENDPOINT"
174
- }).then(y);
174
+ }).then(d);
175
175
  if (h === "bind")
176
- return I(e, t, r.slice(0, -1));
177
- const [u, w] = N(l);
178
- return d(e, t, {
176
+ return x(e, t, r.slice(0, -1));
177
+ const [u, w] = v(l);
178
+ return y(e, t, {
179
179
  type: "APPLY",
180
180
  path: r.map((f) => f.toString()),
181
181
  argumentList: u
182
- }, w).then(y);
182
+ }, w).then(d);
183
183
  },
184
184
  construct(s, o) {
185
- E(i);
186
- const [l, h] = N(o);
187
- return d(e, t, {
185
+ p(i);
186
+ const [l, h] = v(o);
187
+ return y(e, t, {
188
188
  type: "CONSTRUCT",
189
189
  path: r.map((u) => u.toString()),
190
190
  argumentList: l
191
- }, h).then(y);
191
+ }, h).then(d);
192
192
  }
193
193
  });
194
194
  return X(a, e), a;
@@ -196,8 +196,8 @@ function I(e, t, r = [], n = function() {
196
196
  function K(e) {
197
197
  return Array.prototype.concat.apply([], e);
198
198
  }
199
- function N(e) {
200
- const t = e.map(A);
199
+ function v(e) {
200
+ const t = e.map(D);
201
201
  return [t.map((r) => r[0]), K(t.map((r) => r[1]))];
202
202
  }
203
203
  const _ = /* @__PURE__ */ new WeakMap();
@@ -207,8 +207,8 @@ function J(e, t) {
207
207
  function Q(e) {
208
208
  return Object.assign(e, { [H]: !0 });
209
209
  }
210
- function A(e) {
211
- for (const [t, r] of U)
210
+ function D(e) {
211
+ for (const [t, r] of z)
212
212
  if (r.canHandle(e)) {
213
213
  const [n, i] = r.serialize(e);
214
214
  return [
@@ -228,15 +228,15 @@ function A(e) {
228
228
  _.get(e) || []
229
229
  ];
230
230
  }
231
- function y(e) {
231
+ function d(e) {
232
232
  switch (e.type) {
233
233
  case "HANDLER":
234
- return U.get(e.name).deserialize(e.value);
234
+ return z.get(e.name).deserialize(e.value);
235
235
  case "RAW":
236
236
  return e.value;
237
237
  }
238
238
  }
239
- function d(e, t, r, n) {
239
+ function y(e, t, r, n) {
240
240
  return new Promise((i) => {
241
241
  const a = Z();
242
242
  t.set(a, i), e.start && e.start(), e.postMessage(Object.assign({ id: a }, r), n);
@@ -255,17 +255,17 @@ class tt extends c {
255
255
  super("OPFS is not supported in this browser", "OPFS_NOT_SUPPORTED");
256
256
  }
257
257
  }
258
- class T extends c {
258
+ class C extends c {
259
259
  constructor() {
260
260
  super("OPFS is not mounted", "OPFS_NOT_MOUNTED");
261
261
  }
262
262
  }
263
- class k extends c {
263
+ class N extends c {
264
264
  constructor(t, r) {
265
265
  super(t, "INVALID_PATH", r);
266
266
  }
267
267
  }
268
- class O extends c {
268
+ class b extends c {
269
269
  constructor(t) {
270
270
  super(\`File not found: \${t}\`, "FILE_NOT_FOUND", t);
271
271
  }
@@ -350,18 +350,18 @@ function ot() {
350
350
  function m(e) {
351
351
  return Array.isArray(e) ? e : e.split("/").filter(Boolean);
352
352
  }
353
- function x(e) {
353
+ function P(e) {
354
354
  return typeof e == "string" ? e ?? "/" : \`/\${e.join("/")}\`;
355
355
  }
356
- function C(e) {
356
+ function T(e) {
357
357
  const t = m(e);
358
358
  return t[t.length - 1] || "";
359
359
  }
360
- function M(e) {
360
+ function O(e) {
361
361
  const t = m(e);
362
- return t.pop(), x(t);
362
+ return t.pop(), P(t);
363
363
  }
364
- function b(e) {
364
+ function M(e) {
365
365
  return !e || e === "/" ? "/" : e.startsWith("/") ? e : \`/\${e}\`;
366
366
  }
367
367
  function ct(e) {
@@ -374,7 +374,7 @@ function ct(e) {
374
374
  r.pop();
375
375
  } else
376
376
  r.push(n);
377
- return x(r);
377
+ return P(r);
378
378
  }
379
379
  function lt(e, t = "utf-8") {
380
380
  return typeof e == "string" ? et(e, t) : e instanceof Uint8Array ? e : new Uint8Array(e);
@@ -388,7 +388,7 @@ async function ht(e) {
388
388
  t.close();
389
389
  }
390
390
  }
391
- async function v(e, t, r, n = {}) {
391
+ async function k(e, t, r, n = {}) {
392
392
  let i = null;
393
393
  try {
394
394
  i = await e.createSyncAccessHandle();
@@ -406,14 +406,11 @@ async function v(e, t, r, n = {}) {
406
406
  }
407
407
  }
408
408
  }
409
- async function ut(e, t = "SHA-1") {
410
- e instanceof File && (e = await e.arrayBuffer());
411
- try {
412
- const r = new Uint8Array(e), n = await crypto.subtle.digest(t, r);
413
- return Array.from(new Uint8Array(n)).map((a) => a.toString(16).padStart(2, "0")).join("");
414
- } catch (r) {
415
- throw console.warn(\`Failed to calculate \${t} hash:\`, r), r;
416
- }
409
+ async function ut(e, t = "SHA-1", r = 50 * 1024 * 1024) {
410
+ if (e instanceof File && (e = await e.arrayBuffer()), e.byteLength > r)
411
+ throw new Error(\`File size \${e.byteLength} bytes exceeds maximum allowed size \${r} bytes\`);
412
+ const n = new Uint8Array(e), i = await crypto.subtle.digest(t, n);
413
+ return Array.from(new Uint8Array(i)).map((s) => s.toString(16).padStart(2, "0")).join("");
417
414
  }
418
415
  async function ft(e) {
419
416
  const t = await e.arrayBuffer();
@@ -422,20 +419,23 @@ async function ft(e) {
422
419
  class wt {
423
420
  /** Root directory handle for the file system */
424
421
  root = null;
425
- /** Watch event callback */
426
- watchCallback = null;
427
422
  /** Map of watched paths to their last known state */
428
423
  watchers = /* @__PURE__ */ new Map();
429
424
  /** Interval handle for polling watched paths */
430
425
  watchTimer = null;
431
- /** Polling interval in milliseconds */
432
- watchInterval = 1e3;
433
426
  /** Flag to avoid concurrent scans */
434
427
  scanning = !1;
435
428
  /** Promise to prevent concurrent mount operations */
436
429
  mountingPromise = null;
437
- /** Hash algorithm for file hashing (null means no hashing) */
438
- hashAlgorithm = null;
430
+ /** BroadcastChannel instance for sending events */
431
+ broadcastChannel = null;
432
+ /** Configuration options */
433
+ options = {
434
+ watchInterval: 1e3,
435
+ maxFileSize: 50 * 1024 * 1024,
436
+ hashAlgorithm: null,
437
+ broadcastChannel: "opfs-worker"
438
+ };
439
439
  /**
440
440
  * Notify about internal changes to the file system
441
441
  *
@@ -446,33 +446,39 @@ class wt {
446
446
  * @param type - The type of change (create, change, delete)
447
447
  */
448
448
  async notifyChange(t) {
449
- if (!this.watchCallback)
449
+ if (!this.options.broadcastChannel)
450
450
  return;
451
451
  let r;
452
- if (this.hashAlgorithm && !t.isDirectory && t.type !== "removed")
452
+ if (this.options.hashAlgorithm && !t.isDirectory && t.type !== "removed")
453
453
  try {
454
454
  const n = await this.stat(t.path);
455
455
  n.isFile && n.hash && (r = n.hash);
456
456
  } catch (n) {
457
457
  console.warn(\`Failed to calculate hash for \${t.path}:\`, n);
458
458
  }
459
- this.watchCallback({
460
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
461
- ...t,
462
- ...r && { hash: r }
463
- });
459
+ try {
460
+ this.broadcastChannel || (this.broadcastChannel = new BroadcastChannel(this.options.broadcastChannel));
461
+ const n = {
462
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
463
+ ...t,
464
+ ...r && { hash: r }
465
+ };
466
+ this.broadcastChannel.postMessage(n);
467
+ } catch (n) {
468
+ console.warn("Failed to send event via BroadcastChannel:", n);
469
+ }
464
470
  }
465
471
  /**
466
472
  * Creates a new OPFSFileSystem instance
467
473
  *
468
- * @param watchCallback - Optional callback for file change events
469
474
  * @param options - Optional configuration options
470
475
  * @param options.watchInterval - Polling interval in milliseconds for file watching
471
476
  * @param options.hashAlgorithm - Hash algorithm for file hashing
477
+ * @param options.maxFileSize - Maximum file size for hashing in bytes (default: 50MB)
472
478
  * @throws {OPFSError} If OPFS is not supported in the current browser
473
479
  */
474
- constructor(t, r) {
475
- ot(), t && (this.watchCallback = t), r && this.setOptions(r), this.mount("/");
480
+ constructor(t) {
481
+ ot(), t && this.setOptions(t), this.mount("/");
476
482
  }
477
483
  /**
478
484
  * Initialize the file system within a given directory
@@ -509,22 +515,16 @@ class wt {
509
515
  }), this.mountingPromise;
510
516
  }
511
517
  /**
512
- * Set the watch callback for file change events
513
- *
514
- * @param callback - The callback function to invoke when files change
515
- */
516
- setWatchCallback(t) {
517
- this.watchCallback = t;
518
- }
519
- /**
520
- * Set configuration options for the file system
518
+ * Update configuration options
521
519
  *
522
520
  * @param options - Configuration options to update
523
521
  * @param options.watchInterval - Polling interval in milliseconds for file watching
524
522
  * @param options.hashAlgorithm - Hash algorithm for file hashing
523
+ * @param options.maxFileSize - Maximum file size for hashing in bytes
524
+ * @param options.broadcastChannel - Custom name for the broadcast channel
525
525
  */
526
526
  setOptions(t) {
527
- t.watchInterval !== void 0 && (this.watchInterval = t.watchInterval), t.hashAlgorithm !== void 0 && (this.hashAlgorithm = t.hashAlgorithm);
527
+ t.watchInterval !== void 0 && (this.options.watchInterval = t.watchInterval), t.hashAlgorithm !== void 0 && (this.options.hashAlgorithm = t.hashAlgorithm), t.maxFileSize !== void 0 && (this.options.maxFileSize = t.maxFileSize), t.broadcastChannel !== void 0 && (this.broadcastChannel && this.options.broadcastChannel !== t.broadcastChannel && (this.broadcastChannel.close(), this.broadcastChannel = null), this.options.broadcastChannel = t.broadcastChannel);
528
528
  }
529
529
  /**
530
530
  * Automatically mount the OPFS root if not already mounted
@@ -564,7 +564,7 @@ class wt {
564
564
  */
565
565
  async getDirectoryHandle(t, r = !1, n = this.root) {
566
566
  if (!n)
567
- throw new T();
567
+ throw new C();
568
568
  const i = Array.isArray(t) ? t : m(t);
569
569
  let a = n;
570
570
  for (const s of i)
@@ -592,10 +592,10 @@ class wt {
592
592
  */
593
593
  async getFileHandle(t, r = !1, n = this.root) {
594
594
  if (!n)
595
- throw new T();
595
+ throw new C();
596
596
  const i = m(t);
597
597
  if (i.length === 0)
598
- throw new k("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
598
+ throw new N("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
599
599
  const a = i.pop();
600
600
  return (await this.getDirectoryHandle(i, r, n)).getFileHandle(a, { create: r });
601
601
  }
@@ -646,7 +646,7 @@ class wt {
646
646
  const n = await this.getFileHandle(t, !1), i = await ht(n);
647
647
  return r === "binary" ? i : rt(i, r);
648
648
  } catch (n) {
649
- throw console.error(n), new O(t);
649
+ throw console.error(n), new b(t);
650
650
  }
651
651
  }
652
652
  /**
@@ -677,7 +677,7 @@ class wt {
677
677
  async writeFile(t, r, n) {
678
678
  await this.ensureMounted();
679
679
  const i = await this.getFileHandle(t, !0);
680
- await v(i, r, n, { truncate: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
680
+ await k(i, r, n, { truncate: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
681
681
  }
682
682
  /**
683
683
  * Append data to a file
@@ -704,7 +704,7 @@ class wt {
704
704
  async appendFile(t, r, n) {
705
705
  await this.ensureMounted();
706
706
  const i = await this.getFileHandle(t, !0);
707
- await v(i, r, n, { append: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
707
+ await k(i, r, n, { append: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
708
708
  }
709
709
  /**
710
710
  * Create a directory
@@ -729,7 +729,7 @@ class wt {
729
729
  */
730
730
  async mkdir(t, r) {
731
731
  if (await this.ensureMounted(), !this.root)
732
- throw new T();
732
+ throw new C();
733
733
  const n = r?.recursive ?? !1, i = m(t);
734
734
  let a = this.root;
735
735
  for (let s = 0; s < i.length; s++) {
@@ -738,7 +738,7 @@ class wt {
738
738
  a = await a.getDirectoryHandle(o, { create: n || s === i.length - 1 });
739
739
  } catch (l) {
740
740
  throw l.name === "NotFoundError" ? new c(
741
- \`Parent directory does not exist: \${x(i.slice(0, s + 1))}\`,
741
+ \`Parent directory does not exist: \${P(i.slice(0, s + 1))}\`,
742
742
  "ENOENT"
743
743
  ) : l.name === "TypeMismatchError" ? new c(\`Path segment is not a directory: \${o}\`, "ENOTDIR") : new c("Failed to create directory", "MKDIR_FAILED");
744
744
  }
@@ -777,7 +777,7 @@ class wt {
777
777
  isFile: !1,
778
778
  isDirectory: !0
779
779
  };
780
- const r = C(t), n = await this.getDirectoryHandle(M(t), !1), i = this.hashAlgorithm !== null;
780
+ const r = T(t), n = await this.getDirectoryHandle(O(t), !1), i = this.options.hashAlgorithm !== null;
781
781
  try {
782
782
  const s = await (await n.getFileHandle(r, { create: !1 })).getFile(), o = {
783
783
  kind: "file",
@@ -787,9 +787,9 @@ class wt {
787
787
  isFile: !0,
788
788
  isDirectory: !1
789
789
  };
790
- if (i && this.hashAlgorithm)
790
+ if (i && this.options.hashAlgorithm)
791
791
  try {
792
- const l = await ut(s, this.hashAlgorithm);
792
+ const l = await ut(s, this.options.hashAlgorithm, this.options.maxFileSize);
793
793
  o.hash = l;
794
794
  } catch (l) {
795
795
  console.warn(\`Failed to calculate hash for \${t}:\`, l);
@@ -851,10 +851,10 @@ class wt {
851
851
  async exists(t) {
852
852
  if (await this.ensureMounted(), t === "/")
853
853
  return !0;
854
- const r = C(t);
854
+ const r = T(t);
855
855
  let n = null;
856
856
  try {
857
- n = await this.getDirectoryHandle(M(t), !1);
857
+ n = await this.getDirectoryHandle(O(t), !1);
858
858
  } catch (i) {
859
859
  throw (i.name === "NotFoundError" || i.name === "TypeMismatchError") && (n = null), i;
860
860
  }
@@ -935,10 +935,10 @@ class wt {
935
935
  const n = r?.recursive ?? !1, i = r?.force ?? !1;
936
936
  if (t === "/")
937
937
  throw new c("Cannot remove root directory", "EROOT");
938
- const a = C(t);
938
+ const a = T(t);
939
939
  if (!a)
940
- throw new k("Invalid path", t);
941
- const s = await this.getDirectoryHandle(M(t), !1);
940
+ throw new N("Invalid path", t);
941
+ const s = await this.getDirectoryHandle(O(t), !1);
942
942
  try {
943
943
  await s.removeEntry(a, { recursive: n });
944
944
  } catch (o) {
@@ -972,7 +972,7 @@ class wt {
972
972
  try {
973
973
  const r = ct(t);
974
974
  if (!await this.exists(r))
975
- throw new O(r);
975
+ throw new b(r);
976
976
  return r;
977
977
  } catch (r) {
978
978
  throw r instanceof c ? r : new c(\`Failed to resolve path: \${t}\`, "REALPATH_FAILED");
@@ -998,7 +998,7 @@ class wt {
998
998
  await this.ensureMounted();
999
999
  try {
1000
1000
  if (!await this.exists(t))
1001
- throw new O(t);
1001
+ throw new b(t);
1002
1002
  await this.copy(t, r, { recursive: !0 }), await this.remove(t, { recursive: !0 }), await this.notifyChange({ path: t, type: "removed", isDirectory: !1 }), await this.notifyChange({ path: r, type: "added", isDirectory: !1 });
1003
1003
  } catch (n) {
1004
1004
  throw n instanceof c ? n : new c(\`Failed to rename from \${t} to \${r}\`, "RENAME_FAILED");
@@ -1060,18 +1060,27 @@ class wt {
1060
1060
  */
1061
1061
  async watch(t) {
1062
1062
  await this.ensureMounted();
1063
- const r = b(t), n = await this.buildSnapshot(r);
1063
+ const r = M(t), n = await this.buildSnapshot(r);
1064
1064
  this.watchers.set(r, n), this.watchTimer || (this.watchTimer = setInterval(() => {
1065
1065
  this.scanWatches();
1066
- }, this.watchInterval));
1066
+ }, this.options.watchInterval));
1067
1067
  }
1068
1068
  /**
1069
1069
  * Stop watching a previously watched path
1070
1070
  */
1071
1071
  unwatch(t) {
1072
- const r = b(t);
1072
+ const r = M(t);
1073
1073
  this.watchers.delete(r), this.watchers.size === 0 && this.watchTimer && (clearInterval(this.watchTimer), this.watchTimer = null);
1074
1074
  }
1075
+ /**
1076
+ * Dispose of resources and clean up the file system instance
1077
+ *
1078
+ * This method should be called when the file system instance is no longer needed
1079
+ * to properly clean up resources like the broadcast channel and watch timers.
1080
+ */
1081
+ dispose() {
1082
+ this.broadcastChannel && (this.broadcastChannel.close(), this.broadcastChannel = null), this.watchTimer && (clearInterval(this.watchTimer), this.watchTimer = null), this.watchers.clear();
1083
+ }
1075
1084
  async buildSnapshot(t) {
1076
1085
  const r = /* @__PURE__ */ new Map(), n = async (i) => {
1077
1086
  const a = await this.stat(i);
@@ -1099,10 +1108,13 @@ class wt {
1099
1108
  }
1100
1109
  for (const [i, a] of n) {
1101
1110
  const s = r.get(i);
1102
- s ? (s.mtime !== a.mtime || s.size !== a.size) && await this.notifyChange({ path: i, type: "changed", isDirectory: !1 }) : await this.notifyChange({ path: i, type: "added", isDirectory: !1 });
1111
+ s ? (s.mtime !== a.mtime || s.size !== a.size) && await this.notifyChange({ path: i, type: "changed", isDirectory: a.isDirectory }) : await this.notifyChange({ path: i, type: "added", isDirectory: a.isDirectory });
1103
1112
  }
1104
1113
  for (const i of r.keys())
1105
- n.has(i) || await this.notifyChange({ path: i, type: "removed", isDirectory: !1 });
1114
+ if (!n.has(i)) {
1115
+ const a = r.get(i);
1116
+ await this.notifyChange({ path: i, type: "removed", isDirectory: a?.isDirectory ?? !1 });
1117
+ }
1106
1118
  this.watchers.set(t, n);
1107
1119
  })
1108
1120
  );
@@ -1144,7 +1156,7 @@ class wt {
1144
1156
  try {
1145
1157
  (r?.cleanBefore ?? !1) && await this.clear("/");
1146
1158
  for (const [i, a] of t) {
1147
- const s = b(i);
1159
+ const s = M(i);
1148
1160
  let o;
1149
1161
  a instanceof Blob ? o = await ft(a) : o = a, await this.writeFile(s, o);
1150
1162
  }
@@ -1154,7 +1166,7 @@ class wt {
1154
1166
  }
1155
1167
  }
1156
1168
  }
1157
- typeof self < "u" && self.constructor.name === "DedicatedWorkerGlobalScope" && P(new wt());
1158
- //# sourceMappingURL=worker-BL3varjN.js.map
1159
- `,i=typeof self<"u"&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",o],{type:"text/javascript;charset=utf-8"});function s(r){let t;try{if(t=i&&(self.URL||self.webkitURL).createObjectURL(i),!t)throw"";const e=new Worker(t,{type:"module",name:r?.name});return e.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),e}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(o),{type:"module",name:r?.name})}}function c(r,t){const e=a.wrap(new s);return r&&e.setWatchCallback(r?a.proxy(r):()=>{}),t&&e.setOptions(t),e}exports.DirectoryNotFoundError=n.DirectoryNotFoundError;exports.FileNotFoundError=n.FileNotFoundError;exports.OPFSError=n.OPFSError;exports.OPFSNotMountedError=n.OPFSNotMountedError;exports.OPFSNotSupportedError=n.OPFSNotSupportedError;exports.PathError=n.PathError;exports.PermissionError=n.PermissionError;exports.StorageError=n.StorageError;exports.TimeoutError=n.TimeoutError;exports.basename=n.basename;exports.calculateFileHash=n.calculateFileHash;exports.checkOPFSSupport=n.checkOPFSSupport;exports.convertBlobToUint8Array=n.convertBlobToUint8Array;exports.createBuffer=n.createBuffer;exports.decodeBuffer=n.decodeBuffer;exports.dirname=n.dirname;exports.encodeString=n.encodeString;exports.extname=n.extname;exports.joinPath=n.joinPath;exports.normalizePath=n.normalizePath;exports.readFileData=n.readFileData;exports.resolvePath=n.resolvePath;exports.splitPath=n.splitPath;exports.writeFileData=n.writeFileData;exports.createWorker=c;
1169
+ typeof self < "u" && self.constructor.name === "DedicatedWorkerGlobalScope" && I(new wt());
1170
+ //# sourceMappingURL=worker-DvdTp4yb.js.map
1171
+ `,a=typeof self<"u"&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",i],{type:"text/javascript;charset=utf-8"});function s(e){let t;try{if(t=a&&(self.URL||self.webkitURL).createObjectURL(a),!t)throw"";const r=new Worker(t,{type:"module",name:e?.name});return r.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),r}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(i),{type:"module",name:e?.name})}}function c(e){const t=o.wrap(new s);return e&&t.setOptions(e),t}exports.DirectoryNotFoundError=n.DirectoryNotFoundError;exports.FileNotFoundError=n.FileNotFoundError;exports.OPFSError=n.OPFSError;exports.OPFSNotMountedError=n.OPFSNotMountedError;exports.OPFSNotSupportedError=n.OPFSNotSupportedError;exports.PathError=n.PathError;exports.PermissionError=n.PermissionError;exports.StorageError=n.StorageError;exports.TimeoutError=n.TimeoutError;exports.basename=n.basename;exports.calculateFileHash=n.calculateFileHash;exports.checkOPFSSupport=n.checkOPFSSupport;exports.convertBlobToUint8Array=n.convertBlobToUint8Array;exports.createBuffer=n.createBuffer;exports.decodeBuffer=n.decodeBuffer;exports.dirname=n.dirname;exports.encodeString=n.encodeString;exports.extname=n.extname;exports.joinPath=n.joinPath;exports.normalizePath=n.normalizePath;exports.readFileData=n.readFileData;exports.resolvePath=n.resolvePath;exports.splitPath=n.splitPath;exports.writeFileData=n.writeFileData;exports.createWorker=c;
1160
1172
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import { wrap, proxy } from 'comlink';\n\nimport WorkerCtor from './worker?worker&inline';\n\nimport type { OPFSWorker, RemoteOPFSWorker, WatchEvent } from './types';\n\nexport * from './types';\nexport * from './utils/errors';\nexport * from './utils/helpers';\nexport * from './utils/encoder';\n\n/**\n * Creates a new file system instance with inline worker\n * @param watchCallback - Optional callback for file change events\n * @param options - Optional configuration options\n * @param options.watchInterval - Polling interval in milliseconds for file watching\n * @param options.hashAlgorithm - Hash algorithm for file hashing\n * @returns Promise resolving to the file system interface\n */\nexport function createWorker(\n watchCallback?: (event: WatchEvent) => void,\n options?: { \n watchInterval?: number;\n hashAlgorithm?: 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';\n }\n): RemoteOPFSWorker {\n const wrapped = wrap<OPFSWorker>(new WorkerCtor());\n \n // Set up watch callback and options if provided\n if (watchCallback) {\n wrapped.setWatchCallback(\n watchCallback ? proxy(watchCallback) : () => {}, \n );\n }\n \n if (options) {\n wrapped.setOptions(options);\n }\n \n return wrapped;\n}\n"],"names":["createWorker","watchCallback","options","wrapped","wrap","WorkerCtor","proxy"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qdAmBO,SAASA,EACZC,EACAC,EAIgB,CAChB,MAAMC,EAAUC,EAAAA,KAAiB,IAAIC,CAAY,EAGjD,OAAIJ,GACAE,EAAQ,iBACJF,EAAgBK,EAAAA,MAAML,CAAa,EAAI,IAAM,CAAC,CAAA,EAIlDC,GACAC,EAAQ,WAAWD,CAAO,EAGvBC,CACX"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import { wrap, proxy } from 'comlink';\n\nimport WorkerCtor from './worker?worker&inline';\n\nimport type { OPFSWorker, RemoteOPFSWorker, WatchEvent, OPFSOptions } from './types';\n\nexport * from './types';\nexport * from './utils/errors';\nexport * from './utils/helpers';\nexport * from './utils/encoder';\n\n/**\n * Creates a new file system instance with inline worker\n * @param options - Optional configuration options\n * @returns Promise resolving to the file system interface\n */\nexport function createWorker(\n options?: OPFSOptions\n): RemoteOPFSWorker {\n const wrapped = wrap<OPFSWorker>(new WorkerCtor());\n \n // Set up options if provided\n if (options) {\n wrapped.setOptions(options);\n }\n \n return wrapped;\n}\n"],"names":["createWorker","options","wrapped","wrap","WorkerCtor"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qdAgBO,SAASA,EACZC,EACgB,CAChB,MAAMC,EAAUC,EAAAA,KAAiB,IAAIC,CAAY,EAGjD,OAAIH,GACAC,EAAQ,WAAWD,CAAO,EAGvBC,CACX"}
package/dist/index.d.ts CHANGED
@@ -1,18 +1,12 @@
1
- import type { RemoteOPFSWorker, WatchEvent } from './types';
1
+ import type { RemoteOPFSWorker, OPFSOptions } from './types';
2
2
  export * from './types';
3
3
  export * from './utils/errors';
4
4
  export * from './utils/helpers';
5
5
  export * from './utils/encoder';
6
6
  /**
7
7
  * Creates a new file system instance with inline worker
8
- * @param watchCallback - Optional callback for file change events
9
8
  * @param options - Optional configuration options
10
- * @param options.watchInterval - Polling interval in milliseconds for file watching
11
- * @param options.hashAlgorithm - Hash algorithm for file hashing
12
9
  * @returns Promise resolving to the file system interface
13
10
  */
14
- export declare function createWorker(watchCallback?: (event: WatchEvent) => void, options?: {
15
- watchInterval?: number;
16
- hashAlgorithm?: 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
17
- }): RemoteOPFSWorker;
11
+ export declare function createWorker(options?: OPFSOptions): RemoteOPFSWorker;
18
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAc,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAExE,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAEhC;;;;;;;GAOG;AACH,wBAAgB,YAAY,CACxB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,EAC3C,OAAO,CAAC,EAAE;IACN,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;CAC/D,GACF,gBAAgB,CAelB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAc,gBAAgB,EAAc,WAAW,EAAE,MAAM,SAAS,CAAC;AAErF,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAEhC;;;;GAIG;AACH,wBAAgB,YAAY,CACxB,OAAO,CAAC,EAAE,WAAW,GACtB,gBAAgB,CASlB"}