opfs-worker 0.2.6 → 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.js CHANGED
@@ -1,11 +1,11 @@
1
- import { wrap as i, proxy as o } from "comlink";
2
- import { D as d, F as p, O as u, b as y, a as w, P as m, c as g, S as v, T as F, e as S, k as E, d as b, l as P, h as x, o as T, f as A, m as O, g as D, j as _, n as I, i as C, r as k, s as U, w as R } from "./helpers-C0nyU6hv.js";
1
+ import { wrap as i } from "comlink";
2
+ import { D as f, F as d, O as p, b as u, a as y, P as w, c as m, S as g, T as v, e as b, k as F, d as E, l as S, h as P, o as x, f as T, m as C, g as D, j as A, n as O, i as _, r as I, s as U, w as R } from "./helpers-C0nyU6hv.js";
3
3
  const a = `/**
4
4
  * @license
5
5
  * Copyright 2019 Google LLC
6
6
  * SPDX-License-Identifier: Apache-2.0
7
7
  */
8
- const H = Symbol("Comlink.proxy"), R = Symbol("Comlink.endpoint"), B = Symbol("Comlink.releaseProxy"), D = Symbol("Comlink.finalizer"), E = Symbol("Comlink.thrown"), $ = (e) => typeof e == "object" && e !== null || typeof e == "function", W = {
8
+ 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 = {
9
9
  canHandle: (e) => $(e) && e[H],
10
10
  serialize(e) {
11
11
  const { port1: t, port2: r } = new MessageChannel();
@@ -48,7 +48,7 @@ function I(e, t = globalThis, r = ["*"]) {
48
48
  console.warn(\`Invalid origin '\${i.origin}' for comlink proxy\`);
49
49
  return;
50
50
  }
51
- const { id: a, type: s, path: o } = Object.assign({ path: [] }, i.data), l = (i.data.argumentList || []).map(y);
51
+ const { id: a, type: s, path: o } = Object.assign({ path: [] }, i.data), l = (i.data.argumentList || []).map(d);
52
52
  let h;
53
53
  try {
54
54
  const u = o.slice(0, -1).reduce((f, g) => f[g], e), w = o.reduce((f, g) => f[g], e);
@@ -57,7 +57,7 @@ function I(e, t = globalThis, r = ["*"]) {
57
57
  h = w;
58
58
  break;
59
59
  case "SET":
60
- u[o.slice(-1)[0]] = y(i.data.value), h = !0;
60
+ u[o.slice(-1)[0]] = d(i.data.value), h = !0;
61
61
  break;
62
62
  case "APPLY":
63
63
  h = w.apply(u, l);
@@ -84,10 +84,10 @@ function I(e, t = globalThis, r = ["*"]) {
84
84
  h = { value: u, [E]: 0 };
85
85
  }
86
86
  Promise.resolve(h).catch((u) => ({ value: u, [E]: 0 })).then((u) => {
87
- const [w, f] = A(u);
88
- 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]());
87
+ const [w, f] = D(u);
88
+ 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]());
89
89
  }).catch((u) => {
90
- const [w, f] = A({
90
+ const [w, f] = D({
91
91
  value: new TypeError("Unserializable return value"),
92
92
  [E]: 0
93
93
  });
@@ -114,14 +114,14 @@ function Y(e, t) {
114
114
  } finally {
115
115
  r.delete(a.id);
116
116
  }
117
- }), M(e, r, [], t);
117
+ }), x(e, r, [], t);
118
118
  }
119
119
  function p(e) {
120
120
  if (e)
121
121
  throw new Error("Proxy has been released and is not useable");
122
122
  }
123
123
  function U(e) {
124
- return d(e, /* @__PURE__ */ new Map(), {
124
+ return y(e, /* @__PURE__ */ new Map(), {
125
125
  type: "RELEASE"
126
126
  }).then(() => {
127
127
  L(e);
@@ -138,7 +138,7 @@ function X(e, t) {
138
138
  function q(e) {
139
139
  S && S.unregister(e);
140
140
  }
141
- function M(e, t, r = [], n = function() {
141
+ function x(e, t, r = [], n = function() {
142
142
  }) {
143
143
  let i = !1;
144
144
  const a = new Proxy(n, {
@@ -150,47 +150,47 @@ function M(e, t, r = [], n = function() {
150
150
  if (o === "then") {
151
151
  if (r.length === 0)
152
152
  return { then: () => a };
153
- const l = d(e, t, {
153
+ const l = y(e, t, {
154
154
  type: "GET",
155
155
  path: r.map((h) => h.toString())
156
- }).then(y);
156
+ }).then(d);
157
157
  return l.then.bind(l);
158
158
  }
159
- return M(e, t, [...r, o]);
159
+ return x(e, t, [...r, o]);
160
160
  },
161
161
  set(s, o, l) {
162
162
  p(i);
163
- const [h, u] = A(l);
164
- return d(e, t, {
163
+ const [h, u] = D(l);
164
+ return y(e, t, {
165
165
  type: "SET",
166
166
  path: [...r, o].map((w) => w.toString()),
167
167
  value: h
168
- }, u).then(y);
168
+ }, u).then(d);
169
169
  },
170
170
  apply(s, o, l) {
171
171
  p(i);
172
172
  const h = r[r.length - 1];
173
173
  if (h === R)
174
- return d(e, t, {
174
+ return y(e, t, {
175
175
  type: "ENDPOINT"
176
- }).then(y);
176
+ }).then(d);
177
177
  if (h === "bind")
178
- return M(e, t, r.slice(0, -1));
179
- const [u, w] = N(l);
180
- return d(e, t, {
178
+ return x(e, t, r.slice(0, -1));
179
+ const [u, w] = v(l);
180
+ return y(e, t, {
181
181
  type: "APPLY",
182
182
  path: r.map((f) => f.toString()),
183
183
  argumentList: u
184
- }, w).then(y);
184
+ }, w).then(d);
185
185
  },
186
186
  construct(s, o) {
187
187
  p(i);
188
- const [l, h] = N(o);
189
- return d(e, t, {
188
+ const [l, h] = v(o);
189
+ return y(e, t, {
190
190
  type: "CONSTRUCT",
191
191
  path: r.map((u) => u.toString()),
192
192
  argumentList: l
193
- }, h).then(y);
193
+ }, h).then(d);
194
194
  }
195
195
  });
196
196
  return X(a, e), a;
@@ -198,8 +198,8 @@ function M(e, t, r = [], n = function() {
198
198
  function K(e) {
199
199
  return Array.prototype.concat.apply([], e);
200
200
  }
201
- function N(e) {
202
- const t = e.map(A);
201
+ function v(e) {
202
+ const t = e.map(D);
203
203
  return [t.map((r) => r[0]), K(t.map((r) => r[1]))];
204
204
  }
205
205
  const _ = /* @__PURE__ */ new WeakMap();
@@ -209,7 +209,7 @@ function J(e, t) {
209
209
  function Q(e) {
210
210
  return Object.assign(e, { [H]: !0 });
211
211
  }
212
- function A(e) {
212
+ function D(e) {
213
213
  for (const [t, r] of z)
214
214
  if (r.canHandle(e)) {
215
215
  const [n, i] = r.serialize(e);
@@ -230,7 +230,7 @@ function A(e) {
230
230
  _.get(e) || []
231
231
  ];
232
232
  }
233
- function y(e) {
233
+ function d(e) {
234
234
  switch (e.type) {
235
235
  case "HANDLER":
236
236
  return z.get(e.name).deserialize(e.value);
@@ -238,7 +238,7 @@ function y(e) {
238
238
  return e.value;
239
239
  }
240
240
  }
241
- function d(e, t, r, n) {
241
+ function y(e, t, r, n) {
242
242
  return new Promise((i) => {
243
243
  const a = Z();
244
244
  t.set(a, i), e.start && e.start(), e.postMessage(Object.assign({ id: a }, r), n);
@@ -257,17 +257,17 @@ class tt extends c {
257
257
  super("OPFS is not supported in this browser", "OPFS_NOT_SUPPORTED");
258
258
  }
259
259
  }
260
- class T extends c {
260
+ class C extends c {
261
261
  constructor() {
262
262
  super("OPFS is not mounted", "OPFS_NOT_MOUNTED");
263
263
  }
264
264
  }
265
- class k extends c {
265
+ class N extends c {
266
266
  constructor(t, r) {
267
267
  super(t, "INVALID_PATH", r);
268
268
  }
269
269
  }
270
- class O extends c {
270
+ class b extends c {
271
271
  constructor(t) {
272
272
  super(\`File not found: \${t}\`, "FILE_NOT_FOUND", t);
273
273
  }
@@ -355,15 +355,15 @@ function m(e) {
355
355
  function P(e) {
356
356
  return typeof e == "string" ? e ?? "/" : \`/\${e.join("/")}\`;
357
357
  }
358
- function b(e) {
358
+ function T(e) {
359
359
  const t = m(e);
360
360
  return t[t.length - 1] || "";
361
361
  }
362
- function x(e) {
362
+ function O(e) {
363
363
  const t = m(e);
364
364
  return t.pop(), P(t);
365
365
  }
366
- function C(e) {
366
+ function M(e) {
367
367
  return !e || e === "/" ? "/" : e.startsWith("/") ? e : \`/\${e}\`;
368
368
  }
369
369
  function ct(e) {
@@ -390,7 +390,7 @@ async function ht(e) {
390
390
  t.close();
391
391
  }
392
392
  }
393
- async function v(e, t, r, n = {}) {
393
+ async function k(e, t, r, n = {}) {
394
394
  let i = null;
395
395
  try {
396
396
  i = await e.createSyncAccessHandle();
@@ -421,8 +421,6 @@ async function ft(e) {
421
421
  class wt {
422
422
  /** Root directory handle for the file system */
423
423
  root = null;
424
- /** Watch event callback */
425
- watchCallback = null;
426
424
  /** Map of watched paths to their last known state */
427
425
  watchers = /* @__PURE__ */ new Map();
428
426
  /** Interval handle for polling watched paths */
@@ -431,11 +429,14 @@ class wt {
431
429
  scanning = !1;
432
430
  /** Promise to prevent concurrent mount operations */
433
431
  mountingPromise = null;
432
+ /** BroadcastChannel instance for sending events */
433
+ broadcastChannel = null;
434
434
  /** Configuration options */
435
435
  options = {
436
436
  watchInterval: 1e3,
437
437
  maxFileSize: 50 * 1024 * 1024,
438
- hashAlgorithm: null
438
+ hashAlgorithm: null,
439
+ broadcastChannel: "opfs-worker"
439
440
  };
440
441
  /**
441
442
  * Notify about internal changes to the file system
@@ -447,7 +448,7 @@ class wt {
447
448
  * @param type - The type of change (create, change, delete)
448
449
  */
449
450
  async notifyChange(t) {
450
- if (!this.watchCallback)
451
+ if (!this.options.broadcastChannel)
451
452
  return;
452
453
  let r;
453
454
  if (this.options.hashAlgorithm && !t.isDirectory && t.type !== "removed")
@@ -457,24 +458,29 @@ class wt {
457
458
  } catch (n) {
458
459
  console.warn(\`Failed to calculate hash for \${t.path}:\`, n);
459
460
  }
460
- this.watchCallback({
461
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
462
- ...t,
463
- ...r && { hash: r }
464
- });
461
+ try {
462
+ this.broadcastChannel || (this.broadcastChannel = new BroadcastChannel(this.options.broadcastChannel));
463
+ const n = {
464
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
465
+ ...t,
466
+ ...r && { hash: r }
467
+ };
468
+ this.broadcastChannel.postMessage(n);
469
+ } catch (n) {
470
+ console.warn("Failed to send event via BroadcastChannel:", n);
471
+ }
465
472
  }
466
473
  /**
467
474
  * Creates a new OPFSFileSystem instance
468
475
  *
469
- * @param watchCallback - Optional callback for file change events
470
476
  * @param options - Optional configuration options
471
477
  * @param options.watchInterval - Polling interval in milliseconds for file watching
472
478
  * @param options.hashAlgorithm - Hash algorithm for file hashing
473
479
  * @param options.maxFileSize - Maximum file size for hashing in bytes (default: 50MB)
474
480
  * @throws {OPFSError} If OPFS is not supported in the current browser
475
481
  */
476
- constructor(t, r) {
477
- ot(), t && (this.watchCallback = t), r && this.setOptions(r), this.mount("/");
482
+ constructor(t) {
483
+ ot(), t && this.setOptions(t), this.mount("/");
478
484
  }
479
485
  /**
480
486
  * Initialize the file system within a given directory
@@ -510,14 +516,6 @@ class wt {
510
516
  }
511
517
  }), this.mountingPromise;
512
518
  }
513
- /**
514
- * Set the watch callback for file change events
515
- *
516
- * @param callback - The callback function to invoke when files change
517
- */
518
- setWatchCallback(t) {
519
- this.watchCallback = t;
520
- }
521
519
  /**
522
520
  * Update configuration options
523
521
  *
@@ -525,9 +523,10 @@ class wt {
525
523
  * @param options.watchInterval - Polling interval in milliseconds for file watching
526
524
  * @param options.hashAlgorithm - Hash algorithm for file hashing
527
525
  * @param options.maxFileSize - Maximum file size for hashing in bytes
526
+ * @param options.broadcastChannel - Custom name for the broadcast channel
528
527
  */
529
528
  setOptions(t) {
530
- 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);
529
+ 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);
531
530
  }
532
531
  /**
533
532
  * Automatically mount the OPFS root if not already mounted
@@ -567,7 +566,7 @@ class wt {
567
566
  */
568
567
  async getDirectoryHandle(t, r = !1, n = this.root) {
569
568
  if (!n)
570
- throw new T();
569
+ throw new C();
571
570
  const i = Array.isArray(t) ? t : m(t);
572
571
  let a = n;
573
572
  for (const s of i)
@@ -595,10 +594,10 @@ class wt {
595
594
  */
596
595
  async getFileHandle(t, r = !1, n = this.root) {
597
596
  if (!n)
598
- throw new T();
597
+ throw new C();
599
598
  const i = m(t);
600
599
  if (i.length === 0)
601
- throw new k("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
600
+ throw new N("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
602
601
  const a = i.pop();
603
602
  return (await this.getDirectoryHandle(i, r, n)).getFileHandle(a, { create: r });
604
603
  }
@@ -649,7 +648,7 @@ class wt {
649
648
  const n = await this.getFileHandle(t, !1), i = await ht(n);
650
649
  return r === "binary" ? i : rt(i, r);
651
650
  } catch (n) {
652
- throw console.error(n), new O(t);
651
+ throw console.error(n), new b(t);
653
652
  }
654
653
  }
655
654
  /**
@@ -680,7 +679,7 @@ class wt {
680
679
  async writeFile(t, r, n) {
681
680
  await this.ensureMounted();
682
681
  const i = await this.getFileHandle(t, !0);
683
- await v(i, r, n, { truncate: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
682
+ await k(i, r, n, { truncate: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
684
683
  }
685
684
  /**
686
685
  * Append data to a file
@@ -707,7 +706,7 @@ class wt {
707
706
  async appendFile(t, r, n) {
708
707
  await this.ensureMounted();
709
708
  const i = await this.getFileHandle(t, !0);
710
- await v(i, r, n, { append: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
709
+ await k(i, r, n, { append: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
711
710
  }
712
711
  /**
713
712
  * Create a directory
@@ -732,7 +731,7 @@ class wt {
732
731
  */
733
732
  async mkdir(t, r) {
734
733
  if (await this.ensureMounted(), !this.root)
735
- throw new T();
734
+ throw new C();
736
735
  const n = r?.recursive ?? !1, i = m(t);
737
736
  let a = this.root;
738
737
  for (let s = 0; s < i.length; s++) {
@@ -780,7 +779,7 @@ class wt {
780
779
  isFile: !1,
781
780
  isDirectory: !0
782
781
  };
783
- const r = b(t), n = await this.getDirectoryHandle(x(t), !1), i = this.options.hashAlgorithm !== null;
782
+ const r = T(t), n = await this.getDirectoryHandle(O(t), !1), i = this.options.hashAlgorithm !== null;
784
783
  try {
785
784
  const s = await (await n.getFileHandle(r, { create: !1 })).getFile(), o = {
786
785
  kind: "file",
@@ -854,10 +853,10 @@ class wt {
854
853
  async exists(t) {
855
854
  if (await this.ensureMounted(), t === "/")
856
855
  return !0;
857
- const r = b(t);
856
+ const r = T(t);
858
857
  let n = null;
859
858
  try {
860
- n = await this.getDirectoryHandle(x(t), !1);
859
+ n = await this.getDirectoryHandle(O(t), !1);
861
860
  } catch (i) {
862
861
  throw (i.name === "NotFoundError" || i.name === "TypeMismatchError") && (n = null), i;
863
862
  }
@@ -938,10 +937,10 @@ class wt {
938
937
  const n = r?.recursive ?? !1, i = r?.force ?? !1;
939
938
  if (t === "/")
940
939
  throw new c("Cannot remove root directory", "EROOT");
941
- const a = b(t);
940
+ const a = T(t);
942
941
  if (!a)
943
- throw new k("Invalid path", t);
944
- const s = await this.getDirectoryHandle(x(t), !1);
942
+ throw new N("Invalid path", t);
943
+ const s = await this.getDirectoryHandle(O(t), !1);
945
944
  try {
946
945
  await s.removeEntry(a, { recursive: n });
947
946
  } catch (o) {
@@ -975,7 +974,7 @@ class wt {
975
974
  try {
976
975
  const r = ct(t);
977
976
  if (!await this.exists(r))
978
- throw new O(r);
977
+ throw new b(r);
979
978
  return r;
980
979
  } catch (r) {
981
980
  throw r instanceof c ? r : new c(\`Failed to resolve path: \${t}\`, "REALPATH_FAILED");
@@ -1001,7 +1000,7 @@ class wt {
1001
1000
  await this.ensureMounted();
1002
1001
  try {
1003
1002
  if (!await this.exists(t))
1004
- throw new O(t);
1003
+ throw new b(t);
1005
1004
  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 });
1006
1005
  } catch (n) {
1007
1006
  throw n instanceof c ? n : new c(\`Failed to rename from \${t} to \${r}\`, "RENAME_FAILED");
@@ -1063,7 +1062,7 @@ class wt {
1063
1062
  */
1064
1063
  async watch(t) {
1065
1064
  await this.ensureMounted();
1066
- const r = C(t), n = await this.buildSnapshot(r);
1065
+ const r = M(t), n = await this.buildSnapshot(r);
1067
1066
  this.watchers.set(r, n), this.watchTimer || (this.watchTimer = setInterval(() => {
1068
1067
  this.scanWatches();
1069
1068
  }, this.options.watchInterval));
@@ -1072,9 +1071,18 @@ class wt {
1072
1071
  * Stop watching a previously watched path
1073
1072
  */
1074
1073
  unwatch(t) {
1075
- const r = C(t);
1074
+ const r = M(t);
1076
1075
  this.watchers.delete(r), this.watchers.size === 0 && this.watchTimer && (clearInterval(this.watchTimer), this.watchTimer = null);
1077
1076
  }
1077
+ /**
1078
+ * Dispose of resources and clean up the file system instance
1079
+ *
1080
+ * This method should be called when the file system instance is no longer needed
1081
+ * to properly clean up resources like the broadcast channel and watch timers.
1082
+ */
1083
+ dispose() {
1084
+ this.broadcastChannel && (this.broadcastChannel.close(), this.broadcastChannel = null), this.watchTimer && (clearInterval(this.watchTimer), this.watchTimer = null), this.watchers.clear();
1085
+ }
1078
1086
  async buildSnapshot(t) {
1079
1087
  const r = /* @__PURE__ */ new Map(), n = async (i) => {
1080
1088
  const a = await this.stat(i);
@@ -1102,10 +1110,13 @@ class wt {
1102
1110
  }
1103
1111
  for (const [i, a] of n) {
1104
1112
  const s = r.get(i);
1105
- 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 });
1113
+ 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 });
1106
1114
  }
1107
1115
  for (const i of r.keys())
1108
- n.has(i) || await this.notifyChange({ path: i, type: "removed", isDirectory: !1 });
1116
+ if (!n.has(i)) {
1117
+ const a = r.get(i);
1118
+ await this.notifyChange({ path: i, type: "removed", isDirectory: a?.isDirectory ?? !1 });
1119
+ }
1109
1120
  this.watchers.set(t, n);
1110
1121
  })
1111
1122
  );
@@ -1147,7 +1158,7 @@ class wt {
1147
1158
  try {
1148
1159
  (r?.cleanBefore ?? !1) && await this.clear("/");
1149
1160
  for (const [i, a] of t) {
1150
- const s = C(i);
1161
+ const s = M(i);
1151
1162
  let o;
1152
1163
  a instanceof Blob ? o = await ft(a) : o = a, await this.writeFile(s, o);
1153
1164
  }
@@ -1158,60 +1169,57 @@ class wt {
1158
1169
  }
1159
1170
  }
1160
1171
  typeof self < "u" && self.constructor.name === "DedicatedWorkerGlobalScope" && I(new wt());
1161
- //# sourceMappingURL=worker-CHy3JxL1.js.map
1172
+ //# sourceMappingURL=worker-DvdTp4yb.js.map
1162
1173
  `, r = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", a], { type: "text/javascript;charset=utf-8" });
1163
- function s(e) {
1174
+ function o(t) {
1164
1175
  let n;
1165
1176
  try {
1166
1177
  if (n = r && (self.URL || self.webkitURL).createObjectURL(r), !n) throw "";
1167
- const t = new Worker(n, {
1178
+ const e = new Worker(n, {
1168
1179
  type: "module",
1169
- name: e?.name
1180
+ name: t?.name
1170
1181
  });
1171
- return t.addEventListener("error", () => {
1182
+ return e.addEventListener("error", () => {
1172
1183
  (self.URL || self.webkitURL).revokeObjectURL(n);
1173
- }), t;
1184
+ }), e;
1174
1185
  } catch {
1175
1186
  return new Worker(
1176
1187
  "data:text/javascript;charset=utf-8," + encodeURIComponent(a),
1177
1188
  {
1178
1189
  type: "module",
1179
- name: e?.name
1190
+ name: t?.name
1180
1191
  }
1181
1192
  );
1182
1193
  }
1183
1194
  }
1184
- function h(e, n) {
1185
- const t = i(new s());
1186
- return e && t.setWatchCallback(
1187
- e ? o(e) : () => {
1188
- }
1189
- ), n && t.setOptions(n), t;
1195
+ function c(t) {
1196
+ const n = i(new o());
1197
+ return t && n.setOptions(t), n;
1190
1198
  }
1191
1199
  export {
1192
- d as DirectoryNotFoundError,
1193
- p as FileNotFoundError,
1194
- u as OPFSError,
1195
- y as OPFSNotMountedError,
1196
- w as OPFSNotSupportedError,
1197
- m as PathError,
1198
- g as PermissionError,
1199
- v as StorageError,
1200
- F as TimeoutError,
1201
- S as basename,
1202
- E as calculateFileHash,
1203
- b as checkOPFSSupport,
1204
- P as convertBlobToUint8Array,
1205
- x as createBuffer,
1206
- h as createWorker,
1207
- T as decodeBuffer,
1208
- A as dirname,
1209
- O as encodeString,
1200
+ f as DirectoryNotFoundError,
1201
+ d as FileNotFoundError,
1202
+ p as OPFSError,
1203
+ u as OPFSNotMountedError,
1204
+ y as OPFSNotSupportedError,
1205
+ w as PathError,
1206
+ m as PermissionError,
1207
+ g as StorageError,
1208
+ v as TimeoutError,
1209
+ b as basename,
1210
+ F as calculateFileHash,
1211
+ E as checkOPFSSupport,
1212
+ S as convertBlobToUint8Array,
1213
+ P as createBuffer,
1214
+ c as createWorker,
1215
+ x as decodeBuffer,
1216
+ T as dirname,
1217
+ C as encodeString,
1210
1218
  D as extname,
1211
- _ as joinPath,
1212
- I as normalizePath,
1213
- C as readFileData,
1214
- k as resolvePath,
1219
+ A as joinPath,
1220
+ O as normalizePath,
1221
+ _ as readFileData,
1222
+ I as resolvePath,
1215
1223
  U as splitPath,
1216
1224
  R as writeFileData
1217
1225
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","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 watchCallback - Optional callback for file change events\n * @param options - Optional configuration options\n * @returns Promise resolving to the file system interface\n */\nexport function createWorker(\n watchCallback?: (event: WatchEvent) => void,\n options?: OPFSOptions\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBO,SAASA,EACZC,GACAC,GACgB;AAChB,QAAMC,IAAUC,EAAiB,IAAIC,GAAY;AAGjD,SAAIJ,KACAE,EAAQ;AAAA,IACJF,IAAgBK,EAAML,CAAa,IAAI,MAAM;AAAA,IAAC;AAAA,EAAA,GAIlDC,KACAC,EAAQ,WAAWD,CAAO,GAGvBC;AACX;"}
1
+ {"version":3,"file":"index.js","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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBO,SAASA,EACZC,GACgB;AAChB,QAAMC,IAAUC,EAAiB,IAAIC,GAAY;AAGjD,SAAIH,KACAC,EAAQ,WAAWD,CAAO,GAGvBC;AACX;"}
package/dist/raw.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("comlink"),a=require("./helpers-FvdHLObV.cjs");class w{root=null;watchCallback=null;watchers=new Map;watchTimer=null;scanning=!1;mountingPromise=null;options={watchInterval:1e3,maxFileSize:50*1024*1024,hashAlgorithm:null};async notifyChange(t){if(!this.watchCallback)return;let e;if(this.options.hashAlgorithm&&!t.isDirectory&&t.type!=="removed")try{const r=await this.stat(t.path);r.isFile&&r.hash&&(e=r.hash)}catch(r){console.warn(`Failed to calculate hash for ${t.path}:`,r)}this.watchCallback({timestamp:new Date().toISOString(),...t,...e&&{hash:e}})}constructor(t,e){a.checkOPFSSupport(),t&&(this.watchCallback=t),e&&this.setOptions(e),this.mount("/")}async mount(t="/"){return this.mountingPromise&&await this.mountingPromise,this.mountingPromise=new Promise(async(e,r)=>{this.root=null;try{const i=await navigator.storage.getDirectory();t==="/"?this.root=i:this.root=await this.getDirectoryHandle(t,!0,i),e(!0)}catch(i){console.error(i),r(new a.OPFSError("Failed to initialize OPFS","INIT_FAILED"))}finally{this.mountingPromise=null}}),this.mountingPromise}setWatchCallback(t){this.watchCallback=t}setOptions(t){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)}async ensureMounted(){if(!this.root){if(this.mountingPromise){await this.mountingPromise;return}throw new a.OPFSError("OPFS not mounted","NOT_MOUNTED")}}async getDirectoryHandle(t,e=!1,r=this.root){if(!r)throw new a.OPFSNotMountedError;const i=Array.isArray(t)?t:a.splitPath(t);let s=r;for(const o of i)s=await s.getDirectoryHandle(o,{create:e});return s}async getFileHandle(t,e=!1,r=this.root){if(!r)throw new a.OPFSNotMountedError;const i=a.splitPath(t);if(i.length===0)throw new a.PathError("Path must not be empty",Array.isArray(t)?t.join("/"):t);const s=i.pop();return(await this.getDirectoryHandle(i,e,r)).getFileHandle(s,{create:e})}async index(){const t=new Map,e=async r=>{const i=await this.readdir(r,{withFileTypes:!0});for(const s of i){const o=`${r==="/"?"":r}/${s.name}`;try{const n=await this.stat(o);t.set(o,n),n.isDirectory&&await e(o)}catch(n){console.warn(`Skipping broken entry: ${o}`,n)}}};return t.set("/",{kind:"directory",size:0,mtime:new Date(0).toISOString(),ctime:new Date(0).toISOString(),isFile:!1,isDirectory:!0}),await e("/"),t}async readFile(t,e="utf-8"){await this.ensureMounted();try{const r=await this.getFileHandle(t,!1),i=await a.readFileData(r);return e==="binary"?i:a.decodeBuffer(i,e)}catch(r){throw console.error(r),new a.FileNotFoundError(t)}}async writeFile(t,e,r){await this.ensureMounted();const i=await this.getFileHandle(t,!0);await a.writeFileData(i,e,r,{truncate:!0}),await this.notifyChange({path:t,type:"changed",isDirectory:!1})}async appendFile(t,e,r){await this.ensureMounted();const i=await this.getFileHandle(t,!0);await a.writeFileData(i,e,r,{append:!0}),await this.notifyChange({path:t,type:"changed",isDirectory:!1})}async mkdir(t,e){if(await this.ensureMounted(),!this.root)throw new a.OPFSNotMountedError;const r=e?.recursive??!1,i=a.splitPath(t);let s=this.root;for(let o=0;o<i.length;o++){const n=i[o];try{s=await s.getDirectoryHandle(n,{create:r||o===i.length-1})}catch(c){throw c.name==="NotFoundError"?new a.OPFSError(`Parent directory does not exist: ${a.joinPath(i.slice(0,o+1))}`,"ENOENT"):c.name==="TypeMismatchError"?new a.OPFSError(`Path segment is not a directory: ${n}`,"ENOTDIR"):new a.OPFSError("Failed to create directory","MKDIR_FAILED")}}await this.notifyChange({path:t,type:"added",isDirectory:!0})}async stat(t){if(await this.ensureMounted(),t==="/")return{kind:"directory",size:0,mtime:new Date(0).toISOString(),ctime:new Date(0).toISOString(),isFile:!1,isDirectory:!0};const e=a.basename(t),r=await this.getDirectoryHandle(a.dirname(t),!1),i=this.options.hashAlgorithm!==null;try{const o=await(await r.getFileHandle(e,{create:!1})).getFile(),n={kind:"file",size:o.size,mtime:new Date(o.lastModified).toISOString(),ctime:new Date(o.lastModified).toISOString(),isFile:!0,isDirectory:!1};if(i&&this.options.hashAlgorithm)try{const c=await a.calculateFileHash(o,this.options.hashAlgorithm,this.options.maxFileSize);n.hash=c}catch(c){console.warn(`Failed to calculate hash for ${t}:`,c)}return n}catch(s){if(s.name!=="TypeMismatchError"&&s.name!=="NotFoundError")throw new a.OPFSError("Failed to stat (file)","STAT_FAILED")}try{return await r.getDirectoryHandle(e,{create:!1}),{kind:"directory",size:0,mtime:new Date(0).toISOString(),ctime:new Date(0).toISOString(),isFile:!1,isDirectory:!0}}catch(s){throw s.name==="NotFoundError"?new a.OPFSError(`No such file or directory: ${t}`,"ENOENT"):new a.OPFSError("Failed to stat (directory)","STAT_FAILED")}}async readdir(t,e){await this.ensureMounted();const r=e?.withFileTypes??!1,i=await this.getDirectoryHandle(t,!1);if(r){const s=[];for await(const[o,n]of i.entries()){const c=n.kind==="file";s.push({name:o,kind:n.kind,isFile:c,isDirectory:!c})}return s}else{const s=[];for await(const[o]of i.entries())s.push(o);return s}}async exists(t){if(await this.ensureMounted(),t==="/")return!0;const e=a.basename(t);let r=null;try{r=await this.getDirectoryHandle(a.dirname(t),!1)}catch(i){throw(i.name==="NotFoundError"||i.name==="TypeMismatchError")&&(r=null),i}if(!r||!e)return!1;try{return await r.getFileHandle(e,{create:!1}),!0}catch(i){if(i.name!=="NotFoundError"&&i.name!=="TypeMismatchError")throw i}try{return await r.getDirectoryHandle(e,{create:!1}),!0}catch(i){if(i.name!=="NotFoundError"&&i.name!=="TypeMismatchError")throw i}return!1}async clear(t="/"){await this.ensureMounted();try{const e=await this.readdir(t,{withFileTypes:!0});for(const r of e){const i=`${t==="/"?"":t}/${r.name}`;await this.remove(i,{recursive:!0})}await this.notifyChange({path:t,type:"changed",isDirectory:!0})}catch(e){throw e instanceof a.OPFSError?e:new a.OPFSError(`Failed to clear directory: ${t}`,"CLEAR_FAILED")}}async remove(t,e){await this.ensureMounted();const r=e?.recursive??!1,i=e?.force??!1;if(t==="/")throw new a.OPFSError("Cannot remove root directory","EROOT");const s=a.basename(t);if(!s)throw new a.PathError("Invalid path",t);const o=await this.getDirectoryHandle(a.dirname(t),!1);try{await o.removeEntry(s,{recursive:r})}catch(n){if(n.name==="NotFoundError"){if(!i)throw new a.OPFSError(`No such file or directory: ${t}`,"ENOENT")}else throw n.name==="InvalidModificationError"?new a.OPFSError(`Directory not empty: ${t}. Use recursive option to force removal.`,"ENOTEMPTY"):n.name==="TypeMismatchError"&&!r?new a.OPFSError(`Cannot remove directory without recursive option: ${t}`,"EISDIR"):new a.OPFSError(`Failed to remove path: ${t}`,"RM_FAILED")}await this.notifyChange({path:t,type:"removed",isDirectory:!1})}async realpath(t){await this.ensureMounted();try{const e=a.resolvePath(t);if(!await this.exists(e))throw new a.FileNotFoundError(e);return e}catch(e){throw e instanceof a.OPFSError?e:new a.OPFSError(`Failed to resolve path: ${t}`,"REALPATH_FAILED")}}async rename(t,e){await this.ensureMounted();try{if(!await this.exists(t))throw new a.FileNotFoundError(t);await this.copy(t,e,{recursive:!0}),await this.remove(t,{recursive:!0}),await this.notifyChange({path:t,type:"removed",isDirectory:!1}),await this.notifyChange({path:e,type:"added",isDirectory:!1})}catch(r){throw r instanceof a.OPFSError?r:new a.OPFSError(`Failed to rename from ${t} to ${e}`,"RENAME_FAILED")}}async copy(t,e,r){await this.ensureMounted();try{const i=r?.recursive??!1,s=r?.force??!0;if(!await this.exists(t))throw new a.OPFSError(`Source does not exist: ${t}`,"ENOENT");if(await this.exists(e)&&!s)throw new a.OPFSError(`Destination already exists: ${e}`,"EEXIST");if((await this.stat(t)).isFile){const h=await this.readFile(t,"binary");await this.writeFile(e,h)}else{if(!i)throw new a.OPFSError(`Cannot copy directory without recursive option: ${t}`,"EISDIR");await this.mkdir(e,{recursive:!0});const h=await this.readdir(t,{withFileTypes:!0});for(const l of h){const f=`${t}/${l.name}`,u=`${e}/${l.name}`;await this.copy(f,u,{recursive:!0,force:s})}}await this.notifyChange({path:e,type:"added",isDirectory:!1})}catch(i){throw i instanceof a.OPFSError?i:new a.OPFSError(`Failed to copy from ${t} to ${e}`,"CP_FAILED")}}async watch(t){await this.ensureMounted();const e=a.normalizePath(t),r=await this.buildSnapshot(e);this.watchers.set(e,r),this.watchTimer||(this.watchTimer=setInterval(()=>{this.scanWatches()},this.options.watchInterval))}unwatch(t){const e=a.normalizePath(t);this.watchers.delete(e),this.watchers.size===0&&this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=null)}async buildSnapshot(t){const e=new Map,r=async i=>{const s=await this.stat(i);if(e.set(i,s),s.isDirectory){const o=await this.readdir(i,{withFileTypes:!0});for(const n of o){const c=`${i==="/"?"":i}/${n.name}`;await r(c)}}};return await r(t),e}async scanWatches(){if(!this.scanning){this.scanning=!0;try{await Promise.all([...this.watchers.entries()].map(async([t,e])=>{let r;try{r=await this.buildSnapshot(t)}catch{r=new Map}for(const[i,s]of r){const o=e.get(i);o?(o.mtime!==s.mtime||o.size!==s.size)&&await this.notifyChange({path:i,type:"changed",isDirectory:!1}):await this.notifyChange({path:i,type:"added",isDirectory:!1})}for(const i of e.keys())r.has(i)||await this.notifyChange({path:i,type:"removed",isDirectory:!1});this.watchers.set(t,r)}))}finally{this.scanning=!1}}}async sync(t,e){await this.ensureMounted();try{(e?.cleanBefore??!1)&&await this.clear("/");for(const[i,s]of t){const o=a.normalizePath(i);let n;s instanceof Blob?n=await a.convertBlobToUint8Array(s):n=s,await this.writeFile(o,n)}await this.notifyChange({path:"/",type:"changed",isDirectory:!0})}catch(r){throw r instanceof a.OPFSError?r:new a.OPFSError("Failed to sync file system","SYNC_FAILED")}}}typeof self<"u"&&self.constructor.name==="DedicatedWorkerGlobalScope"&&y.expose(new w);exports.OPFSWorker=w;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("comlink"),a=require("./helpers-FvdHLObV.cjs");class w{root=null;watchers=new Map;watchTimer=null;scanning=!1;mountingPromise=null;broadcastChannel=null;options={watchInterval:1e3,maxFileSize:50*1024*1024,hashAlgorithm:null,broadcastChannel:"opfs-worker"};async notifyChange(t){if(!this.options.broadcastChannel)return;let e;if(this.options.hashAlgorithm&&!t.isDirectory&&t.type!=="removed")try{const r=await this.stat(t.path);r.isFile&&r.hash&&(e=r.hash)}catch(r){console.warn(`Failed to calculate hash for ${t.path}:`,r)}try{this.broadcastChannel||(this.broadcastChannel=new BroadcastChannel(this.options.broadcastChannel));const r={timestamp:new Date().toISOString(),...t,...e&&{hash:e}};this.broadcastChannel.postMessage(r)}catch(r){console.warn("Failed to send event via BroadcastChannel:",r)}}constructor(t){a.checkOPFSSupport(),t&&this.setOptions(t),this.mount("/")}async mount(t="/"){return this.mountingPromise&&await this.mountingPromise,this.mountingPromise=new Promise(async(e,r)=>{this.root=null;try{const i=await navigator.storage.getDirectory();t==="/"?this.root=i:this.root=await this.getDirectoryHandle(t,!0,i),e(!0)}catch(i){console.error(i),r(new a.OPFSError("Failed to initialize OPFS","INIT_FAILED"))}finally{this.mountingPromise=null}}),this.mountingPromise}setOptions(t){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)}async ensureMounted(){if(!this.root){if(this.mountingPromise){await this.mountingPromise;return}throw new a.OPFSError("OPFS not mounted","NOT_MOUNTED")}}async getDirectoryHandle(t,e=!1,r=this.root){if(!r)throw new a.OPFSNotMountedError;const i=Array.isArray(t)?t:a.splitPath(t);let s=r;for(const o of i)s=await s.getDirectoryHandle(o,{create:e});return s}async getFileHandle(t,e=!1,r=this.root){if(!r)throw new a.OPFSNotMountedError;const i=a.splitPath(t);if(i.length===0)throw new a.PathError("Path must not be empty",Array.isArray(t)?t.join("/"):t);const s=i.pop();return(await this.getDirectoryHandle(i,e,r)).getFileHandle(s,{create:e})}async index(){const t=new Map,e=async r=>{const i=await this.readdir(r,{withFileTypes:!0});for(const s of i){const o=`${r==="/"?"":r}/${s.name}`;try{const n=await this.stat(o);t.set(o,n),n.isDirectory&&await e(o)}catch(n){console.warn(`Skipping broken entry: ${o}`,n)}}};return t.set("/",{kind:"directory",size:0,mtime:new Date(0).toISOString(),ctime:new Date(0).toISOString(),isFile:!1,isDirectory:!0}),await e("/"),t}async readFile(t,e="utf-8"){await this.ensureMounted();try{const r=await this.getFileHandle(t,!1),i=await a.readFileData(r);return e==="binary"?i:a.decodeBuffer(i,e)}catch(r){throw console.error(r),new a.FileNotFoundError(t)}}async writeFile(t,e,r){await this.ensureMounted();const i=await this.getFileHandle(t,!0);await a.writeFileData(i,e,r,{truncate:!0}),await this.notifyChange({path:t,type:"changed",isDirectory:!1})}async appendFile(t,e,r){await this.ensureMounted();const i=await this.getFileHandle(t,!0);await a.writeFileData(i,e,r,{append:!0}),await this.notifyChange({path:t,type:"changed",isDirectory:!1})}async mkdir(t,e){if(await this.ensureMounted(),!this.root)throw new a.OPFSNotMountedError;const r=e?.recursive??!1,i=a.splitPath(t);let s=this.root;for(let o=0;o<i.length;o++){const n=i[o];try{s=await s.getDirectoryHandle(n,{create:r||o===i.length-1})}catch(c){throw c.name==="NotFoundError"?new a.OPFSError(`Parent directory does not exist: ${a.joinPath(i.slice(0,o+1))}`,"ENOENT"):c.name==="TypeMismatchError"?new a.OPFSError(`Path segment is not a directory: ${n}`,"ENOTDIR"):new a.OPFSError("Failed to create directory","MKDIR_FAILED")}}await this.notifyChange({path:t,type:"added",isDirectory:!0})}async stat(t){if(await this.ensureMounted(),t==="/")return{kind:"directory",size:0,mtime:new Date(0).toISOString(),ctime:new Date(0).toISOString(),isFile:!1,isDirectory:!0};const e=a.basename(t),r=await this.getDirectoryHandle(a.dirname(t),!1),i=this.options.hashAlgorithm!==null;try{const o=await(await r.getFileHandle(e,{create:!1})).getFile(),n={kind:"file",size:o.size,mtime:new Date(o.lastModified).toISOString(),ctime:new Date(o.lastModified).toISOString(),isFile:!0,isDirectory:!1};if(i&&this.options.hashAlgorithm)try{const c=await a.calculateFileHash(o,this.options.hashAlgorithm,this.options.maxFileSize);n.hash=c}catch(c){console.warn(`Failed to calculate hash for ${t}:`,c)}return n}catch(s){if(s.name!=="TypeMismatchError"&&s.name!=="NotFoundError")throw new a.OPFSError("Failed to stat (file)","STAT_FAILED")}try{return await r.getDirectoryHandle(e,{create:!1}),{kind:"directory",size:0,mtime:new Date(0).toISOString(),ctime:new Date(0).toISOString(),isFile:!1,isDirectory:!0}}catch(s){throw s.name==="NotFoundError"?new a.OPFSError(`No such file or directory: ${t}`,"ENOENT"):new a.OPFSError("Failed to stat (directory)","STAT_FAILED")}}async readdir(t,e){await this.ensureMounted();const r=e?.withFileTypes??!1,i=await this.getDirectoryHandle(t,!1);if(r){const s=[];for await(const[o,n]of i.entries()){const c=n.kind==="file";s.push({name:o,kind:n.kind,isFile:c,isDirectory:!c})}return s}else{const s=[];for await(const[o]of i.entries())s.push(o);return s}}async exists(t){if(await this.ensureMounted(),t==="/")return!0;const e=a.basename(t);let r=null;try{r=await this.getDirectoryHandle(a.dirname(t),!1)}catch(i){throw(i.name==="NotFoundError"||i.name==="TypeMismatchError")&&(r=null),i}if(!r||!e)return!1;try{return await r.getFileHandle(e,{create:!1}),!0}catch(i){if(i.name!=="NotFoundError"&&i.name!=="TypeMismatchError")throw i}try{return await r.getDirectoryHandle(e,{create:!1}),!0}catch(i){if(i.name!=="NotFoundError"&&i.name!=="TypeMismatchError")throw i}return!1}async clear(t="/"){await this.ensureMounted();try{const e=await this.readdir(t,{withFileTypes:!0});for(const r of e){const i=`${t==="/"?"":t}/${r.name}`;await this.remove(i,{recursive:!0})}await this.notifyChange({path:t,type:"changed",isDirectory:!0})}catch(e){throw e instanceof a.OPFSError?e:new a.OPFSError(`Failed to clear directory: ${t}`,"CLEAR_FAILED")}}async remove(t,e){await this.ensureMounted();const r=e?.recursive??!1,i=e?.force??!1;if(t==="/")throw new a.OPFSError("Cannot remove root directory","EROOT");const s=a.basename(t);if(!s)throw new a.PathError("Invalid path",t);const o=await this.getDirectoryHandle(a.dirname(t),!1);try{await o.removeEntry(s,{recursive:r})}catch(n){if(n.name==="NotFoundError"){if(!i)throw new a.OPFSError(`No such file or directory: ${t}`,"ENOENT")}else throw n.name==="InvalidModificationError"?new a.OPFSError(`Directory not empty: ${t}. Use recursive option to force removal.`,"ENOTEMPTY"):n.name==="TypeMismatchError"&&!r?new a.OPFSError(`Cannot remove directory without recursive option: ${t}`,"EISDIR"):new a.OPFSError(`Failed to remove path: ${t}`,"RM_FAILED")}await this.notifyChange({path:t,type:"removed",isDirectory:!1})}async realpath(t){await this.ensureMounted();try{const e=a.resolvePath(t);if(!await this.exists(e))throw new a.FileNotFoundError(e);return e}catch(e){throw e instanceof a.OPFSError?e:new a.OPFSError(`Failed to resolve path: ${t}`,"REALPATH_FAILED")}}async rename(t,e){await this.ensureMounted();try{if(!await this.exists(t))throw new a.FileNotFoundError(t);await this.copy(t,e,{recursive:!0}),await this.remove(t,{recursive:!0}),await this.notifyChange({path:t,type:"removed",isDirectory:!1}),await this.notifyChange({path:e,type:"added",isDirectory:!1})}catch(r){throw r instanceof a.OPFSError?r:new a.OPFSError(`Failed to rename from ${t} to ${e}`,"RENAME_FAILED")}}async copy(t,e,r){await this.ensureMounted();try{const i=r?.recursive??!1,s=r?.force??!0;if(!await this.exists(t))throw new a.OPFSError(`Source does not exist: ${t}`,"ENOENT");if(await this.exists(e)&&!s)throw new a.OPFSError(`Destination already exists: ${e}`,"EEXIST");if((await this.stat(t)).isFile){const h=await this.readFile(t,"binary");await this.writeFile(e,h)}else{if(!i)throw new a.OPFSError(`Cannot copy directory without recursive option: ${t}`,"EISDIR");await this.mkdir(e,{recursive:!0});const h=await this.readdir(t,{withFileTypes:!0});for(const l of h){const d=`${t}/${l.name}`,f=`${e}/${l.name}`;await this.copy(d,f,{recursive:!0,force:s})}}await this.notifyChange({path:e,type:"added",isDirectory:!1})}catch(i){throw i instanceof a.OPFSError?i:new a.OPFSError(`Failed to copy from ${t} to ${e}`,"CP_FAILED")}}async watch(t){await this.ensureMounted();const e=a.normalizePath(t),r=await this.buildSnapshot(e);this.watchers.set(e,r),this.watchTimer||(this.watchTimer=setInterval(()=>{this.scanWatches()},this.options.watchInterval))}unwatch(t){const e=a.normalizePath(t);this.watchers.delete(e),this.watchers.size===0&&this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=null)}dispose(){this.broadcastChannel&&(this.broadcastChannel.close(),this.broadcastChannel=null),this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=null),this.watchers.clear()}async buildSnapshot(t){const e=new Map,r=async i=>{const s=await this.stat(i);if(e.set(i,s),s.isDirectory){const o=await this.readdir(i,{withFileTypes:!0});for(const n of o){const c=`${i==="/"?"":i}/${n.name}`;await r(c)}}};return await r(t),e}async scanWatches(){if(!this.scanning){this.scanning=!0;try{await Promise.all([...this.watchers.entries()].map(async([t,e])=>{let r;try{r=await this.buildSnapshot(t)}catch{r=new Map}for(const[i,s]of r){const o=e.get(i);o?(o.mtime!==s.mtime||o.size!==s.size)&&await this.notifyChange({path:i,type:"changed",isDirectory:s.isDirectory}):await this.notifyChange({path:i,type:"added",isDirectory:s.isDirectory})}for(const i of e.keys())if(!r.has(i)){const s=e.get(i);await this.notifyChange({path:i,type:"removed",isDirectory:s?.isDirectory??!1})}this.watchers.set(t,r)}))}finally{this.scanning=!1}}}async sync(t,e){await this.ensureMounted();try{(e?.cleanBefore??!1)&&await this.clear("/");for(const[i,s]of t){const o=a.normalizePath(i);let n;s instanceof Blob?n=await a.convertBlobToUint8Array(s):n=s,await this.writeFile(o,n)}await this.notifyChange({path:"/",type:"changed",isDirectory:!0})}catch(r){throw r instanceof a.OPFSError?r:new a.OPFSError("Failed to sync file system","SYNC_FAILED")}}}typeof self<"u"&&self.constructor.name==="DedicatedWorkerGlobalScope"&&u.expose(new w);exports.OPFSWorker=w;
2
2
  //# sourceMappingURL=raw.cjs.map