opfs-worker 0.5.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/raw.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { expose as v } from "comlink";
2
- import { m as h, d as p, n as u, O as o, s as w, P as S, i as f, o as b, y as C, F as d, p as g, j as A, e as F, f as m, q as x, v as I, r as H, g as O, u as $ } from "./helpers-DcIl7KL0.js";
2
+ import { m as h, d as p, O as o, n as u, s as w, P as S, i as d, o as b, y as C, F as f, p as g, j as x, e as F, f as m, q as A, v as I, r as H, g as $, u as O } from "./helpers-CTCvNFs1.js";
3
3
  class T {
4
4
  /** Root directory handle for the file system */
5
- root = null;
5
+ root;
6
6
  /** Map of watched paths and options */
7
7
  watchers = /* @__PURE__ */ new Map();
8
8
  /** Promise to prevent concurrent mount operations */
@@ -32,10 +32,10 @@ class T {
32
32
  const e = t.path;
33
33
  if (![...this.watchers.values()].some((r) => h(e, r.pattern) && r.include.some((s) => s && h(e, s)) && !r.exclude.some((s) => s && h(e, s))))
34
34
  return;
35
- let a;
35
+ let i;
36
36
  if (this.options.hashAlgorithm)
37
37
  try {
38
- a = (await this.stat(e)).hash;
38
+ i = (await this.stat(e)).hash;
39
39
  } catch {
40
40
  }
41
41
  try {
@@ -44,7 +44,7 @@ class T {
44
44
  namespace: this.options.namespace,
45
45
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
46
46
  ...t,
47
- ...a && { hash: a }
47
+ ...i && { hash: i }
48
48
  };
49
49
  this.broadcastChannel.postMessage(r);
50
50
  } catch (r) {
@@ -85,13 +85,14 @@ class T {
85
85
  * await fs.mount('/my-app');
86
86
  * ```
87
87
  */
88
- async mount(t = this.options.root) {
89
- return this.mountingPromise && await this.mountingPromise, t = u(t), this.mountingPromise = new Promise(async (e, i) => {
88
+ async mount() {
89
+ const t = this.options.root;
90
+ return this.mountingPromise && await this.mountingPromise, this.mountingPromise = new Promise(async (e, a) => {
90
91
  try {
91
- const a = await navigator.storage.getDirectory();
92
- t === "/" ? this.root = a : this.root = await this.getDirectoryHandle(t, !0, a), e(!0);
93
- } catch {
94
- i(new o("Failed to initialize OPFS", "INIT_FAILED"));
92
+ const i = await navigator.storage.getDirectory();
93
+ this.root = t === "/" ? i : await this.getDirectoryHandle(t, !0, i), e(!0);
94
+ } catch (i) {
95
+ a(new o("Failed to initialize OPFS", "INIT_FAILED", t, i));
95
96
  } finally {
96
97
  this.mountingPromise = null;
97
98
  }
@@ -108,7 +109,7 @@ class T {
108
109
  * @param options.broadcastChannel - Custom name for the broadcast channel
109
110
  */
110
111
  async setOptions(t) {
111
- 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), t.namespace && (this.options.namespace = t.namespace), t.root !== void 0 && (this.options.root = t.root, this.options.namespace || (this.options.namespace = `opfs-worker:${this.options.root}`), await this.mount(this.options.root));
112
+ 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), t.namespace && (this.options.namespace = t.namespace), t.root !== void 0 && (this.options.root = u(t.root), this.options.namespace || (this.options.namespace = `opfs-worker:${this.options.root}`), await this.mount());
112
113
  }
113
114
  /**
114
115
  * Get a directory handle from a path
@@ -128,10 +129,10 @@ class T {
128
129
  * const docsDir2 = await fs.getDirectoryHandle(['users', 'john', 'documents'], true);
129
130
  * ```
130
131
  */
131
- async getDirectoryHandle(t, e = !1, i = this.root) {
132
- const a = Array.isArray(t) ? t : w(t);
133
- let r = i;
134
- for (const s of a)
132
+ async getDirectoryHandle(t, e = !1, a = this.root) {
133
+ const i = Array.isArray(t) ? t : w(t);
134
+ let r = a;
135
+ for (const s of i)
135
136
  r = await r.getDirectoryHandle(s, { create: e });
136
137
  return r;
137
138
  }
@@ -154,12 +155,12 @@ class T {
154
155
  * const fileHandle2 = await fs.getFileHandle(['config', 'settings.json'], true);
155
156
  * ```
156
157
  */
157
- async getFileHandle(t, e = !1, i = this.root) {
158
- const a = w(t);
159
- if (a.length === 0)
158
+ async getFileHandle(t, e = !1, a = this.root) {
159
+ const i = w(t);
160
+ if (i.length === 0)
160
161
  throw new S("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
161
- const r = a.pop();
162
- return (await this.getDirectoryHandle(a, e, i)).getFileHandle(r, { create: e });
162
+ const r = i.pop();
163
+ return (await this.getDirectoryHandle(i, e, a)).getFileHandle(r, { create: e });
163
164
  }
164
165
  /**
165
166
  * Get a complete index of all files and directories in the file system
@@ -181,10 +182,10 @@ class T {
181
182
  * ```
182
183
  */
183
184
  async index() {
184
- const t = /* @__PURE__ */ new Map(), e = async (i) => {
185
- const a = await this.readDir(i);
186
- for (const r of a) {
187
- const s = `${i === "/" ? "" : i}/${r.name}`;
185
+ const t = /* @__PURE__ */ new Map(), e = async (a) => {
186
+ const i = await this.readDir(a);
187
+ for (const r of i) {
188
+ const s = `${a === "/" ? "" : a}/${r.name}`;
188
189
  try {
189
190
  const n = await this.stat(s);
190
191
  t.set(s, n), n.isDirectory && await e(s);
@@ -203,12 +204,12 @@ class T {
203
204
  }), await e("/"), t;
204
205
  }
205
206
  async readFile(t, e) {
206
- await this.mount(), e || (e = f(t) ? "binary" : "utf-8");
207
+ await this.mount(), e || (e = d(t) ? "binary" : "utf-8");
207
208
  try {
208
- const i = await this.getFileHandle(t, !1), a = await b(i, t);
209
- return e === "binary" ? a : C(a, e);
210
- } catch (i) {
211
- throw new d(t, i);
209
+ const a = await this.getFileHandle(t, !1, this.root), i = await b(a, t);
210
+ return e === "binary" ? i : C(i, e);
211
+ } catch (a) {
212
+ throw new f(t, a);
212
213
  }
213
214
  }
214
215
  /**
@@ -236,10 +237,10 @@ class T {
236
237
  * await fs.writeFile('/data/utf16.txt', 'Hello World', 'utf-16le');
237
238
  * ```
238
239
  */
239
- async writeFile(t, e, i) {
240
+ async writeFile(t, e, a) {
240
241
  await this.mount();
241
- const a = await this.exists(t), r = await this.getFileHandle(t, !0);
242
- i || (i = typeof e != "string" || f(t) ? "binary" : "utf-8"), await g(r, e, i, t), a ? await this.notifyChange({ path: t, type: "changed", isDirectory: !1 }) : await this.notifyChange({ path: t, type: "added", isDirectory: !1 });
242
+ const i = await this.exists(t), r = await this.getFileHandle(t, !0);
243
+ a || (a = typeof e != "string" || d(t) ? "binary" : "utf-8"), await g(r, e, a, t), i ? await this.notifyChange({ path: t, type: "changed", isDirectory: !1 }) : await this.notifyChange({ path: t, type: "added", isDirectory: !1 });
243
244
  }
244
245
  /**
245
246
  * Append data to a file
@@ -263,10 +264,10 @@ class T {
263
264
  * await fs.appendFile('/data/binary.dat', additionalData);
264
265
  * ```
265
266
  */
266
- async appendFile(t, e, i) {
267
+ async appendFile(t, e, a) {
267
268
  await this.mount();
268
- const a = await this.getFileHandle(t, !0);
269
- i || (i = typeof e != "string" || f(t) ? "binary" : "utf-8"), await g(a, e, i, t, { append: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
269
+ const i = await this.getFileHandle(t, !0);
270
+ a || (a = typeof e != "string" || d(t) ? "binary" : "utf-8"), await g(i, e, a, t, { append: !0 }), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
270
271
  }
271
272
  /**
272
273
  * Create a directory
@@ -291,15 +292,15 @@ class T {
291
292
  */
292
293
  async mkdir(t, e) {
293
294
  await this.mount();
294
- const i = e?.recursive ?? !1, a = w(t);
295
+ const a = e?.recursive ?? !1, i = w(t);
295
296
  let r = this.root;
296
- for (let s = 0; s < a.length; s++) {
297
- const n = a[s];
297
+ for (let s = 0; s < i.length; s++) {
298
+ const n = i[s];
298
299
  try {
299
- r = await r.getDirectoryHandle(n, { create: i || s === a.length - 1 });
300
+ r = await r.getDirectoryHandle(n, { create: a || s === i.length - 1 });
300
301
  } catch (c) {
301
302
  throw c.name === "NotFoundError" ? new o(
302
- `Parent directory does not exist: ${A(a.slice(0, s + 1))}`,
303
+ `Parent directory does not exist: ${x(i.slice(0, s + 1))}`,
303
304
  "ENOENT",
304
305
  void 0,
305
306
  c
@@ -340,9 +341,9 @@ class T {
340
341
  isFile: !1,
341
342
  isDirectory: !0
342
343
  };
343
- const e = F(t), i = await this.getDirectoryHandle(m(t), !1), a = this.options.hashAlgorithm !== null;
344
+ const e = F(t), a = await this.getDirectoryHandle(m(t), !1), i = this.options.hashAlgorithm !== null;
344
345
  try {
345
- const s = await (await i.getFileHandle(e, { create: !1 })).getFile(), n = {
346
+ const s = await (await a.getFileHandle(e, { create: !1 })).getFile(), n = {
346
347
  kind: "file",
347
348
  size: s.size,
348
349
  mtime: new Date(s.lastModified).toISOString(),
@@ -350,9 +351,9 @@ class T {
350
351
  isFile: !0,
351
352
  isDirectory: !1
352
353
  };
353
- if (a && this.options.hashAlgorithm)
354
+ if (i && this.options.hashAlgorithm)
354
355
  try {
355
- const c = await x(s, this.options.hashAlgorithm, this.options.maxFileSize);
356
+ const c = await A(s, this.options.hashAlgorithm, this.options.maxFileSize);
356
357
  n.hash = c;
357
358
  } catch (c) {
358
359
  console.warn(`Failed to calculate hash for ${t}:`, c);
@@ -363,7 +364,7 @@ class T {
363
364
  throw new o("Failed to stat (file)", "STAT_FAILED", void 0, r);
364
365
  }
365
366
  try {
366
- return await i.getDirectoryHandle(e, { create: !1 }), {
367
+ return await a.getDirectoryHandle(e, { create: !1 }), {
367
368
  kind: "directory",
368
369
  size: 0,
369
370
  mtime: (/* @__PURE__ */ new Date(0)).toISOString(),
@@ -395,17 +396,17 @@ class T {
395
396
  */
396
397
  async readDir(t) {
397
398
  await this.mount();
398
- const e = await this.getDirectoryHandle(t, !1), i = [];
399
- for await (const [a, r] of e.entries()) {
399
+ const e = await this.getDirectoryHandle(t, !1), a = [];
400
+ for await (const [i, r] of e.entries()) {
400
401
  const s = r.kind === "file";
401
- i.push({
402
- name: a,
402
+ a.push({
403
+ name: i,
403
404
  kind: r.kind,
404
405
  isFile: s,
405
406
  isDirectory: !s
406
407
  });
407
408
  }
408
- return i;
409
+ return a;
409
410
  }
410
411
  /**
411
412
  * Check if a file or directory exists
@@ -425,21 +426,21 @@ class T {
425
426
  if (await this.mount(), t === "/")
426
427
  return !0;
427
428
  const e = F(t);
428
- let i = null;
429
+ let a = null;
429
430
  try {
430
- i = await this.getDirectoryHandle(m(t), !1);
431
- } catch (a) {
432
- throw (a.name === "NotFoundError" || a.name === "TypeMismatchError") && (i = null), a;
431
+ a = await this.getDirectoryHandle(m(t), !1);
432
+ } catch (i) {
433
+ throw (i.name === "NotFoundError" || i.name === "TypeMismatchError") && (a = null), i;
433
434
  }
434
- if (!i || !e)
435
+ if (!a || !e)
435
436
  return !1;
436
437
  try {
437
- return await i.getFileHandle(e, { create: !1 }), !0;
438
- } catch (a) {
439
- if (a.name !== "NotFoundError" && a.name !== "TypeMismatchError")
440
- throw a;
438
+ return await a.getFileHandle(e, { create: !1 }), !0;
439
+ } catch (i) {
440
+ if (i.name !== "NotFoundError" && i.name !== "TypeMismatchError")
441
+ throw i;
441
442
  try {
442
- return await i.getDirectoryHandle(e, { create: !1 }), !0;
443
+ return await a.getDirectoryHandle(e, { create: !1 }), !0;
443
444
  } catch (r) {
444
445
  if (r.name !== "NotFoundError" && r.name !== "TypeMismatchError")
445
446
  throw r;
@@ -470,9 +471,9 @@ class T {
470
471
  await this.mount();
471
472
  try {
472
473
  const e = await this.readDir(t);
473
- for (const i of e) {
474
- const a = `${t === "/" ? "" : t}/${i.name}`;
475
- await this.remove(a, { recursive: !0 });
474
+ for (const a of e) {
475
+ const i = `${t === "/" ? "" : t}/${a.name}`;
476
+ await this.remove(i, { recursive: !0 });
476
477
  }
477
478
  await this.notifyChange({ path: t, type: "changed", isDirectory: !0 });
478
479
  } catch (e) {
@@ -506,8 +507,8 @@ class T {
506
507
  async remove(t, e) {
507
508
  if (await this.mount(), t === "/")
508
509
  throw new o("Cannot remove root directory", "EROOT");
509
- const i = await this.getDirectoryHandle(m(t), !1);
510
- await I(i, t, e), await this.notifyChange({ path: t, type: "removed", isDirectory: !1 });
510
+ const { recursive: a = !1, force: i = !1 } = e || {}, r = await this.getDirectoryHandle(m(t), !1);
511
+ await I(r, t, { recursive: a, force: i }), await this.notifyChange({ path: t, type: "removed", isDirectory: !1 });
511
512
  }
512
513
  /**
513
514
  * Resolve a path to an absolute path
@@ -532,7 +533,7 @@ class T {
532
533
  try {
533
534
  const e = H(t);
534
535
  if (!await this.exists(e))
535
- throw new d(e);
536
+ throw new f(e);
536
537
  return e;
537
538
  } catch (e) {
538
539
  throw e instanceof o ? e : new o(`Failed to resolve path: ${t}`, "REALPATH_FAILED", void 0, e);
@@ -542,24 +543,33 @@ class T {
542
543
  * Rename a file or directory
543
544
  *
544
545
  * Changes the name of a file or directory. If the target path already exists,
545
- * it will be replaced.
546
+ * it will be replaced only if overwrite option is enabled.
546
547
  *
547
548
  * @param oldPath - The current path of the file or directory
548
549
  * @param newPath - The new path for the file or directory
550
+ * @param options - Options for renaming
551
+ * @param options.overwrite - Whether to overwrite existing files (default: false)
549
552
  * @returns Promise that resolves when the rename operation is complete
550
553
  * @throws {OPFSError} If the rename operation fails
551
554
  *
552
555
  * @example
553
556
  * ```typescript
557
+ * // Basic rename (fails if target exists)
554
558
  * await fs.rename('/old/path/file.txt', '/new/path/renamed.txt');
559
+ *
560
+ * // Rename with overwrite
561
+ * await fs.rename('/old/path/file.txt', '/new/path/renamed.txt', { overwrite: true });
555
562
  * ```
556
563
  */
557
- async rename(t, e) {
564
+ async rename(t, e, a) {
558
565
  await this.mount();
559
566
  try {
567
+ const i = a?.overwrite ?? !1;
560
568
  if (!await this.exists(t))
561
- throw new d(t);
562
- 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 });
569
+ throw new f(t);
570
+ if (await this.exists(e) && !i)
571
+ throw new o(`Destination already exists: ${e}`, "EEXIST", void 0);
572
+ await this.copy(t, e, { recursive: !0, overwrite: i }), await this.remove(t, { recursive: !0 }), await this.notifyChange({ path: t, type: "removed", isDirectory: !1 }), await this.notifyChange({ path: e, type: "added", isDirectory: !1 });
563
573
  } catch (i) {
564
574
  throw i instanceof o ? i : new o(`Failed to rename from ${t} to ${e}`, "RENAME_FAILED", void 0, i);
565
575
  }
@@ -573,7 +583,7 @@ class T {
573
583
  * @param destination - The destination path to copy to
574
584
  * @param options - Options for copying
575
585
  * @param options.recursive - Whether to copy directories recursively (default: false)
576
- * @param options.force - Whether to overwrite existing files (default: true)
586
+ * @param options.overwrite - Whether to overwrite existing files (default: true)
577
587
  * @returns Promise that resolves when the copy operation is complete
578
588
  * @throws {OPFSError} If the copy operation fails
579
589
  *
@@ -586,13 +596,13 @@ class T {
586
596
  * await fs.copy('/source/dir', '/dest/dir', { recursive: true });
587
597
  *
588
598
  * // Copy without overwriting existing files
589
- * await fs.copy('/source', '/dest', { recursive: true, force: false });
599
+ * await fs.copy('/source', '/dest', { recursive: true, overwrite: false });
590
600
  * ```
591
601
  */
592
- async copy(t, e, i) {
602
+ async copy(t, e, a) {
593
603
  await this.mount();
594
604
  try {
595
- const a = i?.recursive ?? !1, r = i?.force ?? !0;
605
+ const i = a?.recursive ?? !1, r = a?.overwrite ?? !0;
596
606
  if (!await this.exists(t))
597
607
  throw new o(`Source does not exist: ${t}`, "ENOENT", void 0);
598
608
  if (await this.exists(e) && !r)
@@ -601,17 +611,17 @@ class T {
601
611
  const l = await this.readFile(t, "binary");
602
612
  await this.writeFile(e, l);
603
613
  } else {
604
- if (!a)
614
+ if (!i)
605
615
  throw new o(`Cannot copy directory without recursive option: ${t}`, "EISDIR", void 0);
606
616
  await this.mkdir(e, { recursive: !0 });
607
617
  const l = await this.readDir(t);
608
618
  for (const y of l) {
609
619
  const D = `${t}/${y.name}`, E = `${e}/${y.name}`;
610
- await this.copy(D, E, { recursive: !0, force: r });
620
+ await this.copy(D, E, { recursive: !0, overwrite: r });
611
621
  }
612
622
  }
613
- } catch (a) {
614
- throw a instanceof o ? a : new o(`Failed to copy from ${t} to ${e}`, "CP_FAILED", void 0, a);
623
+ } catch (i) {
624
+ throw i instanceof o ? i : new o(`Failed to copy from ${t} to ${e}`, "CP_FAILED", void 0, i);
615
625
  }
616
626
  }
617
627
  /**
@@ -642,12 +652,12 @@ class T {
642
652
  async watch(t, e) {
643
653
  if (!this.options.broadcastChannel)
644
654
  throw new o("This instance is not configured to send events. Please specify options.broadcastChannel to enable watching.", "ENOENT");
645
- const i = {
646
- pattern: O(t, e?.recursive ?? !0),
655
+ const a = {
656
+ pattern: $(t, e?.recursive ?? !0),
647
657
  include: Array.isArray(e?.include) ? e.include : [e?.include ?? "**"],
648
658
  exclude: Array.isArray(e?.exclude) ? e.exclude : [e?.exclude ?? ""]
649
659
  };
650
- this.watchers.set(t, i);
660
+ this.watchers.set(t, a);
651
661
  }
652
662
  /**
653
663
  * Stop watching a previously watched path
@@ -696,13 +706,13 @@ class T {
696
706
  await this.mount();
697
707
  try {
698
708
  (e?.cleanBefore ?? !1) && await this.clear("/");
699
- for (const [a, r] of t) {
700
- const s = u(a);
709
+ for (const [i, r] of t) {
710
+ const s = u(i);
701
711
  let n;
702
- r instanceof Blob ? n = await $(r) : n = r, await this.writeFile(s, n);
712
+ r instanceof Blob ? n = await O(r) : n = r, await this.writeFile(s, n);
703
713
  }
704
- } catch (i) {
705
- throw i instanceof o ? i : new o("Failed to sync file system", "SYNC_FAILED", void 0, i);
714
+ } catch (a) {
715
+ throw a instanceof o ? a : new o("Failed to sync file system", "SYNC_FAILED", void 0, a);
706
716
  }
707
717
  }
708
718
  }