opfs-worker 0.5.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/raw.js CHANGED
@@ -1,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
  }
@@ -143,7 +144,7 @@ class T {
143
144
  *
144
145
  * @param path - The path to the file (string or array of segments)
145
146
  * @param create - Whether to create the file if it doesn't exist (default: false)
146
- * @param from - The directory to start from (default: root directory)
147
+ * @param _from - The directory to start from (default: root directory)
147
148
  * @returns Promise that resolves to the file handle
148
149
  * @throws {PathError} If the path is empty
149
150
  * @throws {OPFSError} If the file cannot be accessed or created
@@ -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,22 @@ 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
+ if (a = null, i.name !== "NotFoundError" && i.name !== "TypeMismatchError")
434
+ throw i;
433
435
  }
434
- if (!i || !e)
436
+ if (!a || !e)
435
437
  return !1;
436
438
  try {
437
- return await i.getFileHandle(e, { create: !1 }), !0;
438
- } catch (a) {
439
- if (a.name !== "NotFoundError" && a.name !== "TypeMismatchError")
440
- throw a;
439
+ return await a.getFileHandle(e, { create: !1 }), !0;
440
+ } catch (i) {
441
+ if (i.name !== "NotFoundError" && i.name !== "TypeMismatchError")
442
+ throw i;
441
443
  try {
442
- return await i.getDirectoryHandle(e, { create: !1 }), !0;
444
+ return await a.getDirectoryHandle(e, { create: !1 }), !0;
443
445
  } catch (r) {
444
446
  if (r.name !== "NotFoundError" && r.name !== "TypeMismatchError")
445
447
  throw r;
@@ -470,9 +472,9 @@ class T {
470
472
  await this.mount();
471
473
  try {
472
474
  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 });
475
+ for (const a of e) {
476
+ const i = `${t === "/" ? "" : t}/${a.name}`;
477
+ await this.remove(i, { recursive: !0 });
476
478
  }
477
479
  await this.notifyChange({ path: t, type: "changed", isDirectory: !0 });
478
480
  } catch (e) {
@@ -506,8 +508,8 @@ class T {
506
508
  async remove(t, e) {
507
509
  if (await this.mount(), t === "/")
508
510
  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 });
511
+ const { recursive: a = !1, force: i = !1 } = e || {}, r = await this.getDirectoryHandle(m(t), !1);
512
+ await I(r, t, { recursive: a, force: i }), await this.notifyChange({ path: t, type: "removed", isDirectory: !1 });
511
513
  }
512
514
  /**
513
515
  * Resolve a path to an absolute path
@@ -532,7 +534,7 @@ class T {
532
534
  try {
533
535
  const e = H(t);
534
536
  if (!await this.exists(e))
535
- throw new d(e);
537
+ throw new f(e);
536
538
  return e;
537
539
  } catch (e) {
538
540
  throw e instanceof o ? e : new o(`Failed to resolve path: ${t}`, "REALPATH_FAILED", void 0, e);
@@ -542,24 +544,33 @@ class T {
542
544
  * Rename a file or directory
543
545
  *
544
546
  * Changes the name of a file or directory. If the target path already exists,
545
- * it will be replaced.
547
+ * it will be replaced only if overwrite option is enabled.
546
548
  *
547
549
  * @param oldPath - The current path of the file or directory
548
550
  * @param newPath - The new path for the file or directory
551
+ * @param options - Options for renaming
552
+ * @param options.overwrite - Whether to overwrite existing files (default: false)
549
553
  * @returns Promise that resolves when the rename operation is complete
550
554
  * @throws {OPFSError} If the rename operation fails
551
555
  *
552
556
  * @example
553
557
  * ```typescript
558
+ * // Basic rename (fails if target exists)
554
559
  * await fs.rename('/old/path/file.txt', '/new/path/renamed.txt');
560
+ *
561
+ * // Rename with overwrite
562
+ * await fs.rename('/old/path/file.txt', '/new/path/renamed.txt', { overwrite: true });
555
563
  * ```
556
564
  */
557
- async rename(t, e) {
565
+ async rename(t, e, a) {
558
566
  await this.mount();
559
567
  try {
568
+ const i = a?.overwrite ?? !1;
560
569
  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 });
570
+ throw new f(t);
571
+ if (await this.exists(e) && !i)
572
+ throw new o(`Destination already exists: ${e}`, "EEXIST", void 0);
573
+ 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
574
  } catch (i) {
564
575
  throw i instanceof o ? i : new o(`Failed to rename from ${t} to ${e}`, "RENAME_FAILED", void 0, i);
565
576
  }
@@ -573,7 +584,7 @@ class T {
573
584
  * @param destination - The destination path to copy to
574
585
  * @param options - Options for copying
575
586
  * @param options.recursive - Whether to copy directories recursively (default: false)
576
- * @param options.force - Whether to overwrite existing files (default: true)
587
+ * @param options.overwrite - Whether to overwrite existing files (default: true)
577
588
  * @returns Promise that resolves when the copy operation is complete
578
589
  * @throws {OPFSError} If the copy operation fails
579
590
  *
@@ -586,13 +597,13 @@ class T {
586
597
  * await fs.copy('/source/dir', '/dest/dir', { recursive: true });
587
598
  *
588
599
  * // Copy without overwriting existing files
589
- * await fs.copy('/source', '/dest', { recursive: true, force: false });
600
+ * await fs.copy('/source', '/dest', { recursive: true, overwrite: false });
590
601
  * ```
591
602
  */
592
- async copy(t, e, i) {
603
+ async copy(t, e, a) {
593
604
  await this.mount();
594
605
  try {
595
- const a = i?.recursive ?? !1, r = i?.force ?? !0;
606
+ const i = a?.recursive ?? !1, r = a?.overwrite ?? !0;
596
607
  if (!await this.exists(t))
597
608
  throw new o(`Source does not exist: ${t}`, "ENOENT", void 0);
598
609
  if (await this.exists(e) && !r)
@@ -601,17 +612,17 @@ class T {
601
612
  const l = await this.readFile(t, "binary");
602
613
  await this.writeFile(e, l);
603
614
  } else {
604
- if (!a)
615
+ if (!i)
605
616
  throw new o(`Cannot copy directory without recursive option: ${t}`, "EISDIR", void 0);
606
617
  await this.mkdir(e, { recursive: !0 });
607
618
  const l = await this.readDir(t);
608
619
  for (const y of l) {
609
620
  const D = `${t}/${y.name}`, E = `${e}/${y.name}`;
610
- await this.copy(D, E, { recursive: !0, force: r });
621
+ await this.copy(D, E, { recursive: !0, overwrite: r });
611
622
  }
612
623
  }
613
- } catch (a) {
614
- throw a instanceof o ? a : new o(`Failed to copy from ${t} to ${e}`, "CP_FAILED", void 0, a);
624
+ } catch (i) {
625
+ throw i instanceof o ? i : new o(`Failed to copy from ${t} to ${e}`, "CP_FAILED", void 0, i);
615
626
  }
616
627
  }
617
628
  /**
@@ -642,12 +653,12 @@ class T {
642
653
  async watch(t, e) {
643
654
  if (!this.options.broadcastChannel)
644
655
  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),
656
+ const a = {
657
+ pattern: $(t, e?.recursive ?? !0),
647
658
  include: Array.isArray(e?.include) ? e.include : [e?.include ?? "**"],
648
659
  exclude: Array.isArray(e?.exclude) ? e.exclude : [e?.exclude ?? ""]
649
660
  };
650
- this.watchers.set(t, i);
661
+ this.watchers.set(t, a);
651
662
  }
652
663
  /**
653
664
  * Stop watching a previously watched path
@@ -696,13 +707,13 @@ class T {
696
707
  await this.mount();
697
708
  try {
698
709
  (e?.cleanBefore ?? !1) && await this.clear("/");
699
- for (const [a, r] of t) {
700
- const s = u(a);
710
+ for (const [i, r] of t) {
711
+ const s = u(i);
701
712
  let n;
702
- r instanceof Blob ? n = await $(r) : n = r, await this.writeFile(s, n);
713
+ r instanceof Blob ? n = await O(r) : n = r, await this.writeFile(s, n);
703
714
  }
704
- } catch (i) {
705
- throw i instanceof o ? i : new o("Failed to sync file system", "SYNC_FAILED", void 0, i);
715
+ } catch (a) {
716
+ throw a instanceof o ? a : new o("Failed to sync file system", "SYNC_FAILED", void 0, a);
706
717
  }
707
718
  }
708
719
  }