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/README.md +112 -41
- package/dist/assets/worker-DvdTp4yb.js.map +1 -0
- package/dist/index.cjs +91 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -114
- package/dist/index.js.map +1 -1
- package/dist/raw.cjs +1 -1
- package/dist/raw.cjs.map +1 -1
- package/dist/raw.js +120 -109
- package/dist/raw.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.d.ts +12 -11
- package/dist/worker.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/assets/worker-CHy3JxL1.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { wrap as i
|
|
2
|
-
import { D as
|
|
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"),
|
|
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(
|
|
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]] =
|
|
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] =
|
|
88
|
-
t.postMessage(Object.assign(Object.assign({}, w), { id: a }), f), s === "RELEASE" && (t.removeEventListener("message", n), L(t),
|
|
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] =
|
|
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
|
-
}),
|
|
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
|
|
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
|
|
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 =
|
|
153
|
+
const l = y(e, t, {
|
|
154
154
|
type: "GET",
|
|
155
155
|
path: r.map((h) => h.toString())
|
|
156
|
-
}).then(
|
|
156
|
+
}).then(d);
|
|
157
157
|
return l.then.bind(l);
|
|
158
158
|
}
|
|
159
|
-
return
|
|
159
|
+
return x(e, t, [...r, o]);
|
|
160
160
|
},
|
|
161
161
|
set(s, o, l) {
|
|
162
162
|
p(i);
|
|
163
|
-
const [h, u] =
|
|
164
|
-
return
|
|
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(
|
|
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
|
|
174
|
+
return y(e, t, {
|
|
175
175
|
type: "ENDPOINT"
|
|
176
|
-
}).then(
|
|
176
|
+
}).then(d);
|
|
177
177
|
if (h === "bind")
|
|
178
|
-
return
|
|
179
|
-
const [u, w] =
|
|
180
|
-
return
|
|
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(
|
|
184
|
+
}, w).then(d);
|
|
185
185
|
},
|
|
186
186
|
construct(s, o) {
|
|
187
187
|
p(i);
|
|
188
|
-
const [l, h] =
|
|
189
|
-
return
|
|
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(
|
|
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
|
|
202
|
-
const t = e.map(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
260
|
+
class C extends c {
|
|
261
261
|
constructor() {
|
|
262
262
|
super("OPFS is not mounted", "OPFS_NOT_MOUNTED");
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
|
-
class
|
|
265
|
+
class N extends c {
|
|
266
266
|
constructor(t, r) {
|
|
267
267
|
super(t, "INVALID_PATH", r);
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
|
-
class
|
|
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
|
|
358
|
+
function T(e) {
|
|
359
359
|
const t = m(e);
|
|
360
360
|
return t[t.length - 1] || "";
|
|
361
361
|
}
|
|
362
|
-
function
|
|
362
|
+
function O(e) {
|
|
363
363
|
const t = m(e);
|
|
364
364
|
return t.pop(), P(t);
|
|
365
365
|
}
|
|
366
|
-
function
|
|
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
|
|
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.
|
|
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
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
|
477
|
-
ot(), t &&
|
|
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
|
|
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
|
|
597
|
+
throw new C();
|
|
599
598
|
const i = m(t);
|
|
600
599
|
if (i.length === 0)
|
|
601
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
856
|
+
const r = T(t);
|
|
858
857
|
let n = null;
|
|
859
858
|
try {
|
|
860
|
-
n = await this.getDirectoryHandle(
|
|
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 =
|
|
940
|
+
const a = T(t);
|
|
942
941
|
if (!a)
|
|
943
|
-
throw new
|
|
944
|
-
const s = await this.getDirectoryHandle(
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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:
|
|
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)
|
|
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 =
|
|
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-
|
|
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
|
|
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
|
|
1178
|
+
const e = new Worker(n, {
|
|
1168
1179
|
type: "module",
|
|
1169
|
-
name:
|
|
1180
|
+
name: t?.name
|
|
1170
1181
|
});
|
|
1171
|
-
return
|
|
1182
|
+
return e.addEventListener("error", () => {
|
|
1172
1183
|
(self.URL || self.webkitURL).revokeObjectURL(n);
|
|
1173
|
-
}),
|
|
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:
|
|
1190
|
+
name: t?.name
|
|
1180
1191
|
}
|
|
1181
1192
|
);
|
|
1182
1193
|
}
|
|
1183
1194
|
}
|
|
1184
|
-
function
|
|
1185
|
-
const
|
|
1186
|
-
return
|
|
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
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
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
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
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
|
|
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
|