opfs-worker 0.3.3 → 0.5.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 +238 -865
- package/dist/assets/worker-3SMz_DAt.js.map +1 -0
- package/dist/helpers-Bm2TWyPQ.js +1224 -0
- package/dist/helpers-Bm2TWyPQ.js.map +1 -0
- package/dist/helpers-BoLdVbGk.cjs +4 -0
- package/dist/helpers-BoLdVbGk.cjs.map +1 -0
- package/dist/index.cjs +1428 -506
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1465 -537
- package/dist/index.js.map +1 -1
- package/dist/raw.cjs +1 -1
- package/dist/raw.cjs.map +1 -1
- package/dist/raw.js +133 -188
- package/dist/raw.js.map +1 -1
- package/dist/types.d.ts +20 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/errors.d.ts +9 -9
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts +34 -2
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/worker.d.ts +29 -21
- package/dist/worker.d.ts.map +1 -1
- package/package.json +5 -2
- package/dist/assets/worker-CLK22qZk.js.map +0 -1
- package/dist/helpers-B87wz5kv.cjs +0 -2
- package/dist/helpers-B87wz5kv.cjs.map +0 -1
- package/dist/helpers-DxFcNkZe.js +0 -222
- package/dist/helpers-DxFcNkZe.js.map +0 -1
package/dist/raw.js
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import { expose as
|
|
2
|
-
import { d as
|
|
3
|
-
class
|
|
1
|
+
import { expose as E } from "comlink";
|
|
2
|
+
import { m as l, d as v, n as y, O as o, s as d, P as p, l as S, x as C, F as w, o as u, j as b, e as g, f, p as A, u as x, r as I, g as H, t as O } from "./helpers-Bm2TWyPQ.js";
|
|
3
|
+
class $ {
|
|
4
4
|
/** Root directory handle for the file system */
|
|
5
5
|
root = null;
|
|
6
|
-
/** Map of watched paths
|
|
6
|
+
/** Map of watched paths and options */
|
|
7
7
|
watchers = /* @__PURE__ */ new Map();
|
|
8
|
-
/** Interval handle for polling watched paths */
|
|
9
|
-
watchTimer = null;
|
|
10
|
-
/** Flag to avoid concurrent scans */
|
|
11
|
-
scanning = !1;
|
|
12
8
|
/** Promise to prevent concurrent mount operations */
|
|
13
9
|
mountingPromise = null;
|
|
14
10
|
/** BroadcastChannel instance for sending events */
|
|
15
11
|
broadcastChannel = null;
|
|
16
12
|
/** Configuration options */
|
|
17
13
|
options = {
|
|
18
|
-
|
|
14
|
+
root: "/",
|
|
15
|
+
namespace: "",
|
|
19
16
|
maxFileSize: 50 * 1024 * 1024,
|
|
20
17
|
hashAlgorithm: null,
|
|
21
18
|
broadcastChannel: "opfs-worker"
|
|
@@ -32,38 +29,40 @@ class A {
|
|
|
32
29
|
async notifyChange(t) {
|
|
33
30
|
if (!this.options.broadcastChannel)
|
|
34
31
|
return;
|
|
35
|
-
|
|
36
|
-
if (this.
|
|
32
|
+
const e = t.path;
|
|
33
|
+
if (![...this.watchers.values()].some((r) => l(e, r.pattern) && r.include.some((s) => s && l(e, s)) && !r.exclude.some((s) => s && l(e, s))))
|
|
34
|
+
return;
|
|
35
|
+
let a;
|
|
36
|
+
if (this.options.hashAlgorithm)
|
|
37
37
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
} catch (i) {
|
|
41
|
-
console.warn(`Failed to calculate hash for ${t.path}:`, i);
|
|
38
|
+
a = (await this.stat(e)).hash;
|
|
39
|
+
} catch {
|
|
42
40
|
}
|
|
43
41
|
try {
|
|
44
42
|
this.broadcastChannel || (this.broadcastChannel = new BroadcastChannel(this.options.broadcastChannel));
|
|
45
|
-
const
|
|
46
|
-
|
|
43
|
+
const r = {
|
|
44
|
+
namespace: this.options.namespace,
|
|
47
45
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
48
46
|
...t,
|
|
49
|
-
...
|
|
47
|
+
...a && { hash: a }
|
|
50
48
|
};
|
|
51
|
-
this.broadcastChannel.postMessage(
|
|
52
|
-
} catch (
|
|
53
|
-
console.warn("Failed to send event via BroadcastChannel:",
|
|
49
|
+
this.broadcastChannel.postMessage(r);
|
|
50
|
+
} catch (r) {
|
|
51
|
+
console.warn("Failed to send event via BroadcastChannel:", r);
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
54
|
/**
|
|
57
55
|
* Creates a new OPFSFileSystem instance
|
|
58
56
|
*
|
|
59
57
|
* @param options - Optional configuration options
|
|
58
|
+
* @param options.root - Root path for the file system (default: '/')
|
|
60
59
|
* @param options.watchInterval - Polling interval in milliseconds for file watching
|
|
61
60
|
* @param options.hashAlgorithm - Hash algorithm for file hashing
|
|
62
61
|
* @param options.maxFileSize - Maximum file size for hashing in bytes (default: 50MB)
|
|
63
62
|
* @throws {OPFSError} If OPFS is not supported in the current browser
|
|
64
63
|
*/
|
|
65
64
|
constructor(t) {
|
|
66
|
-
|
|
65
|
+
v(), t && this.setOptions(t);
|
|
67
66
|
}
|
|
68
67
|
/**
|
|
69
68
|
* Initialize the file system within a given directory
|
|
@@ -86,14 +85,13 @@ class A {
|
|
|
86
85
|
* await fs.mount('/my-app');
|
|
87
86
|
* ```
|
|
88
87
|
*/
|
|
89
|
-
async mount(t =
|
|
90
|
-
return this.mountingPromise && await this.mountingPromise, this.mountingPromise = new Promise(async (e, i) => {
|
|
91
|
-
this.root = null;
|
|
88
|
+
async mount(t = this.options.root) {
|
|
89
|
+
return this.mountingPromise && await this.mountingPromise, t = y(t), this.mountingPromise = new Promise(async (e, i) => {
|
|
92
90
|
try {
|
|
93
91
|
const a = await navigator.storage.getDirectory();
|
|
94
92
|
t === "/" ? this.root = a : this.root = await this.getDirectoryHandle(t, !0, a), e(!0);
|
|
95
|
-
} catch
|
|
96
|
-
|
|
93
|
+
} catch {
|
|
94
|
+
i(new o("Failed to initialize OPFS", "INIT_FAILED"));
|
|
97
95
|
} finally {
|
|
98
96
|
this.mountingPromise = null;
|
|
99
97
|
}
|
|
@@ -103,31 +101,14 @@ class A {
|
|
|
103
101
|
* Update configuration options
|
|
104
102
|
*
|
|
105
103
|
* @param options - Configuration options to update
|
|
104
|
+
* @param options.root - Root path for the file system
|
|
106
105
|
* @param options.watchInterval - Polling interval in milliseconds for file watching
|
|
107
106
|
* @param options.hashAlgorithm - Hash algorithm for file hashing
|
|
108
107
|
* @param options.maxFileSize - Maximum file size for hashing in bytes
|
|
109
108
|
* @param options.broadcastChannel - Custom name for the broadcast channel
|
|
110
109
|
*/
|
|
111
|
-
setOptions(t) {
|
|
112
|
-
t.
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Automatically mount the OPFS root if not already mounted
|
|
116
|
-
*
|
|
117
|
-
* This method is called internally when file operations are performed
|
|
118
|
-
* without explicitly mounting first.
|
|
119
|
-
*
|
|
120
|
-
* @returns Promise that resolves when auto-mount is complete
|
|
121
|
-
* @throws {OPFSError} If auto-mount fails
|
|
122
|
-
*/
|
|
123
|
-
async ensureMounted() {
|
|
124
|
-
if (!this.root) {
|
|
125
|
-
if (this.mountingPromise) {
|
|
126
|
-
await this.mountingPromise;
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
throw new n("OPFS not mounted", "NOT_MOUNTED");
|
|
130
|
-
}
|
|
110
|
+
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));
|
|
131
112
|
}
|
|
132
113
|
/**
|
|
133
114
|
* Get a directory handle from a path
|
|
@@ -148,9 +129,7 @@ class A {
|
|
|
148
129
|
* ```
|
|
149
130
|
*/
|
|
150
131
|
async getDirectoryHandle(t, e = !1, i = this.root) {
|
|
151
|
-
|
|
152
|
-
throw new l();
|
|
153
|
-
const a = Array.isArray(t) ? t : w(t);
|
|
132
|
+
const a = Array.isArray(t) ? t : d(t);
|
|
154
133
|
let r = i;
|
|
155
134
|
for (const s of a)
|
|
156
135
|
r = await r.getDirectoryHandle(s, { create: e });
|
|
@@ -176,11 +155,9 @@ class A {
|
|
|
176
155
|
* ```
|
|
177
156
|
*/
|
|
178
157
|
async getFileHandle(t, e = !1, i = this.root) {
|
|
179
|
-
|
|
180
|
-
throw new l();
|
|
181
|
-
const a = w(t);
|
|
158
|
+
const a = d(t);
|
|
182
159
|
if (a.length === 0)
|
|
183
|
-
throw new
|
|
160
|
+
throw new p("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
|
|
184
161
|
const r = a.pop();
|
|
185
162
|
return (await this.getDirectoryHandle(a, e, i)).getFileHandle(r, { create: e });
|
|
186
163
|
}
|
|
@@ -209,10 +186,10 @@ class A {
|
|
|
209
186
|
for (const r of a) {
|
|
210
187
|
const s = `${i === "/" ? "" : i}/${r.name}`;
|
|
211
188
|
try {
|
|
212
|
-
const
|
|
213
|
-
t.set(s,
|
|
214
|
-
} catch (
|
|
215
|
-
console.warn(`Skipping broken entry: ${s}`,
|
|
189
|
+
const n = await this.stat(s);
|
|
190
|
+
t.set(s, n), n.isDirectory && await e(s);
|
|
191
|
+
} catch (n) {
|
|
192
|
+
console.warn(`Skipping broken entry: ${s}`, n);
|
|
216
193
|
}
|
|
217
194
|
}
|
|
218
195
|
};
|
|
@@ -226,12 +203,12 @@ class A {
|
|
|
226
203
|
}), await e("/"), t;
|
|
227
204
|
}
|
|
228
205
|
async readFile(t, e = "utf-8") {
|
|
229
|
-
await this.
|
|
206
|
+
await this.mount();
|
|
230
207
|
try {
|
|
231
|
-
const i = await this.getFileHandle(t, !1), a = await
|
|
232
|
-
return e === "binary" ? a :
|
|
208
|
+
const i = await this.getFileHandle(t, !1), a = await S(i, t);
|
|
209
|
+
return e === "binary" ? a : C(a, e);
|
|
233
210
|
} catch (i) {
|
|
234
|
-
throw
|
|
211
|
+
throw new w(t, i);
|
|
235
212
|
}
|
|
236
213
|
}
|
|
237
214
|
/**
|
|
@@ -260,9 +237,9 @@ class A {
|
|
|
260
237
|
* ```
|
|
261
238
|
*/
|
|
262
239
|
async writeFile(t, e, i) {
|
|
263
|
-
await this.
|
|
264
|
-
const a = await this.getFileHandle(t, !0);
|
|
265
|
-
await
|
|
240
|
+
await this.mount();
|
|
241
|
+
const a = await this.exists(t), r = await this.getFileHandle(t, !0);
|
|
242
|
+
await u(r, e, i, {}, t), a ? await this.notifyChange({ path: t, type: "changed", isDirectory: !1 }) : await this.notifyChange({ path: t, type: "added", isDirectory: !1 });
|
|
266
243
|
}
|
|
267
244
|
/**
|
|
268
245
|
* Append data to a file
|
|
@@ -287,9 +264,9 @@ class A {
|
|
|
287
264
|
* ```
|
|
288
265
|
*/
|
|
289
266
|
async appendFile(t, e, i) {
|
|
290
|
-
await this.
|
|
267
|
+
await this.mount();
|
|
291
268
|
const a = await this.getFileHandle(t, !0);
|
|
292
|
-
await
|
|
269
|
+
await u(a, e, i, { append: !0 }, t), await this.notifyChange({ path: t, type: "changed", isDirectory: !1 });
|
|
293
270
|
}
|
|
294
271
|
/**
|
|
295
272
|
* Create a directory
|
|
@@ -313,19 +290,20 @@ class A {
|
|
|
313
290
|
* ```
|
|
314
291
|
*/
|
|
315
292
|
async mkdir(t, e) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const i = e?.recursive ?? !1, a = w(t);
|
|
293
|
+
await this.mount();
|
|
294
|
+
const i = e?.recursive ?? !1, a = d(t);
|
|
319
295
|
let r = this.root;
|
|
320
296
|
for (let s = 0; s < a.length; s++) {
|
|
321
|
-
const
|
|
297
|
+
const n = a[s];
|
|
322
298
|
try {
|
|
323
|
-
r = await r.getDirectoryHandle(
|
|
299
|
+
r = await r.getDirectoryHandle(n, { create: i || s === a.length - 1 });
|
|
324
300
|
} catch (c) {
|
|
325
|
-
throw c.name === "NotFoundError" ? new
|
|
326
|
-
`Parent directory does not exist: ${
|
|
327
|
-
"ENOENT"
|
|
328
|
-
|
|
301
|
+
throw c.name === "NotFoundError" ? new o(
|
|
302
|
+
`Parent directory does not exist: ${b(a.slice(0, s + 1))}`,
|
|
303
|
+
"ENOENT",
|
|
304
|
+
void 0,
|
|
305
|
+
c
|
|
306
|
+
) : c.name === "TypeMismatchError" ? new o(`Path segment is not a directory: ${n}`, "ENOTDIR", void 0, c) : new o("Failed to create directory", "MKDIR_FAILED", void 0, c);
|
|
329
307
|
}
|
|
330
308
|
}
|
|
331
309
|
await this.notifyChange({ path: t, type: "added", isDirectory: !0 });
|
|
@@ -353,7 +331,7 @@ class A {
|
|
|
353
331
|
* ```
|
|
354
332
|
*/
|
|
355
333
|
async stat(t) {
|
|
356
|
-
if (await this.
|
|
334
|
+
if (await this.mount(), t === "/")
|
|
357
335
|
return {
|
|
358
336
|
kind: "directory",
|
|
359
337
|
size: 0,
|
|
@@ -362,9 +340,9 @@ class A {
|
|
|
362
340
|
isFile: !1,
|
|
363
341
|
isDirectory: !0
|
|
364
342
|
};
|
|
365
|
-
const e =
|
|
343
|
+
const e = g(t), i = await this.getDirectoryHandle(f(t), !1), a = this.options.hashAlgorithm !== null;
|
|
366
344
|
try {
|
|
367
|
-
const s = await (await i.getFileHandle(e, { create: !1 })).getFile(),
|
|
345
|
+
const s = await (await i.getFileHandle(e, { create: !1 })).getFile(), n = {
|
|
368
346
|
kind: "file",
|
|
369
347
|
size: s.size,
|
|
370
348
|
mtime: new Date(s.lastModified).toISOString(),
|
|
@@ -374,15 +352,15 @@ class A {
|
|
|
374
352
|
};
|
|
375
353
|
if (a && this.options.hashAlgorithm)
|
|
376
354
|
try {
|
|
377
|
-
const c = await
|
|
378
|
-
|
|
355
|
+
const c = await A(s, this.options.hashAlgorithm, this.options.maxFileSize);
|
|
356
|
+
n.hash = c;
|
|
379
357
|
} catch (c) {
|
|
380
358
|
console.warn(`Failed to calculate hash for ${t}:`, c);
|
|
381
359
|
}
|
|
382
|
-
return
|
|
360
|
+
return n;
|
|
383
361
|
} catch (r) {
|
|
384
362
|
if (r.name !== "TypeMismatchError" && r.name !== "NotFoundError")
|
|
385
|
-
throw new
|
|
363
|
+
throw new o("Failed to stat (file)", "STAT_FAILED", void 0, r);
|
|
386
364
|
}
|
|
387
365
|
try {
|
|
388
366
|
return await i.getDirectoryHandle(e, { create: !1 }), {
|
|
@@ -394,7 +372,7 @@ class A {
|
|
|
394
372
|
isDirectory: !0
|
|
395
373
|
};
|
|
396
374
|
} catch (r) {
|
|
397
|
-
throw r.name === "NotFoundError" ? new
|
|
375
|
+
throw r.name === "NotFoundError" ? new o(`No such file or directory: ${t}`, "ENOENT", void 0, r) : new o("Failed to stat (directory)", "STAT_FAILED", void 0, r);
|
|
398
376
|
}
|
|
399
377
|
}
|
|
400
378
|
/**
|
|
@@ -416,7 +394,7 @@ class A {
|
|
|
416
394
|
* ```
|
|
417
395
|
*/
|
|
418
396
|
async readDir(t) {
|
|
419
|
-
await this.
|
|
397
|
+
await this.mount();
|
|
420
398
|
const e = await this.getDirectoryHandle(t, !1), i = [];
|
|
421
399
|
for await (const [a, r] of e.entries()) {
|
|
422
400
|
const s = r.kind === "file";
|
|
@@ -444,12 +422,12 @@ class A {
|
|
|
444
422
|
* ```
|
|
445
423
|
*/
|
|
446
424
|
async exists(t) {
|
|
447
|
-
if (await this.
|
|
425
|
+
if (await this.mount(), t === "/")
|
|
448
426
|
return !0;
|
|
449
|
-
const e =
|
|
427
|
+
const e = g(t);
|
|
450
428
|
let i = null;
|
|
451
429
|
try {
|
|
452
|
-
i = await this.getDirectoryHandle(
|
|
430
|
+
i = await this.getDirectoryHandle(f(t), !1);
|
|
453
431
|
} catch (a) {
|
|
454
432
|
throw (a.name === "NotFoundError" || a.name === "TypeMismatchError") && (i = null), a;
|
|
455
433
|
}
|
|
@@ -460,14 +438,14 @@ class A {
|
|
|
460
438
|
} catch (a) {
|
|
461
439
|
if (a.name !== "NotFoundError" && a.name !== "TypeMismatchError")
|
|
462
440
|
throw a;
|
|
441
|
+
try {
|
|
442
|
+
return await i.getDirectoryHandle(e, { create: !1 }), !0;
|
|
443
|
+
} catch (r) {
|
|
444
|
+
if (r.name !== "NotFoundError" && r.name !== "TypeMismatchError")
|
|
445
|
+
throw r;
|
|
446
|
+
return !1;
|
|
447
|
+
}
|
|
463
448
|
}
|
|
464
|
-
try {
|
|
465
|
-
return await i.getDirectoryHandle(e, { create: !1 }), !0;
|
|
466
|
-
} catch (a) {
|
|
467
|
-
if (a.name !== "NotFoundError" && a.name !== "TypeMismatchError")
|
|
468
|
-
throw a;
|
|
469
|
-
}
|
|
470
|
-
return !1;
|
|
471
449
|
}
|
|
472
450
|
/**
|
|
473
451
|
* Clear all contents of a directory without removing the directory itself
|
|
@@ -489,7 +467,7 @@ class A {
|
|
|
489
467
|
* ```
|
|
490
468
|
*/
|
|
491
469
|
async clear(t = "/") {
|
|
492
|
-
await this.
|
|
470
|
+
await this.mount();
|
|
493
471
|
try {
|
|
494
472
|
const e = await this.readDir(t);
|
|
495
473
|
for (const i of e) {
|
|
@@ -498,7 +476,7 @@ class A {
|
|
|
498
476
|
}
|
|
499
477
|
await this.notifyChange({ path: t, type: "changed", isDirectory: !0 });
|
|
500
478
|
} catch (e) {
|
|
501
|
-
throw e instanceof
|
|
479
|
+
throw e instanceof o ? e : new o(`Failed to clear directory: ${t}`, "CLEAR_FAILED", void 0, e);
|
|
502
480
|
}
|
|
503
481
|
}
|
|
504
482
|
/**
|
|
@@ -526,23 +504,10 @@ class A {
|
|
|
526
504
|
* ```
|
|
527
505
|
*/
|
|
528
506
|
async remove(t, e) {
|
|
529
|
-
await this.
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
const r = d(t);
|
|
534
|
-
if (!r)
|
|
535
|
-
throw new g("Invalid path", t);
|
|
536
|
-
const s = await this.getDirectoryHandle(y(t), !1);
|
|
537
|
-
try {
|
|
538
|
-
await s.removeEntry(r, { recursive: i });
|
|
539
|
-
} catch (o) {
|
|
540
|
-
if (o.name === "NotFoundError") {
|
|
541
|
-
if (!a)
|
|
542
|
-
throw new n(`No such file or directory: ${t}`, "ENOENT");
|
|
543
|
-
} else throw o.name === "InvalidModificationError" ? new n(`Directory not empty: ${t}. Use recursive option to force removal.`, "ENOTEMPTY") : o.name === "TypeMismatchError" && !i ? new n(`Cannot remove directory without recursive option: ${t}`, "EISDIR") : new n(`Failed to remove path: ${t}`, "RM_FAILED");
|
|
544
|
-
}
|
|
545
|
-
await this.notifyChange({ path: t, type: "removed", isDirectory: !1 });
|
|
507
|
+
if (await this.mount(), t === "/")
|
|
508
|
+
throw new o("Cannot remove root directory", "EROOT");
|
|
509
|
+
const i = await this.getDirectoryHandle(f(t), !1);
|
|
510
|
+
await x(i, t, e), await this.notifyChange({ path: t, type: "removed", isDirectory: !1 });
|
|
546
511
|
}
|
|
547
512
|
/**
|
|
548
513
|
* Resolve a path to an absolute path
|
|
@@ -563,14 +528,14 @@ class A {
|
|
|
563
528
|
* ```
|
|
564
529
|
*/
|
|
565
530
|
async realpath(t) {
|
|
566
|
-
await this.
|
|
531
|
+
await this.mount();
|
|
567
532
|
try {
|
|
568
|
-
const e =
|
|
533
|
+
const e = I(t);
|
|
569
534
|
if (!await this.exists(e))
|
|
570
|
-
throw new
|
|
535
|
+
throw new w(e);
|
|
571
536
|
return e;
|
|
572
537
|
} catch (e) {
|
|
573
|
-
throw e instanceof
|
|
538
|
+
throw e instanceof o ? e : new o(`Failed to resolve path: ${t}`, "REALPATH_FAILED", void 0, e);
|
|
574
539
|
}
|
|
575
540
|
}
|
|
576
541
|
/**
|
|
@@ -590,13 +555,13 @@ class A {
|
|
|
590
555
|
* ```
|
|
591
556
|
*/
|
|
592
557
|
async rename(t, e) {
|
|
593
|
-
await this.
|
|
558
|
+
await this.mount();
|
|
594
559
|
try {
|
|
595
560
|
if (!await this.exists(t))
|
|
596
|
-
throw new
|
|
561
|
+
throw new w(t);
|
|
597
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 });
|
|
598
563
|
} catch (i) {
|
|
599
|
-
throw i instanceof
|
|
564
|
+
throw i instanceof o ? i : new o(`Failed to rename from ${t} to ${e}`, "RENAME_FAILED", void 0, i);
|
|
600
565
|
}
|
|
601
566
|
}
|
|
602
567
|
/**
|
|
@@ -625,47 +590,70 @@ class A {
|
|
|
625
590
|
* ```
|
|
626
591
|
*/
|
|
627
592
|
async copy(t, e, i) {
|
|
628
|
-
await this.
|
|
593
|
+
await this.mount();
|
|
629
594
|
try {
|
|
630
595
|
const a = i?.recursive ?? !1, r = i?.force ?? !0;
|
|
631
596
|
if (!await this.exists(t))
|
|
632
|
-
throw new
|
|
597
|
+
throw new o(`Source does not exist: ${t}`, "ENOENT", void 0);
|
|
633
598
|
if (await this.exists(e) && !r)
|
|
634
|
-
throw new
|
|
599
|
+
throw new o(`Destination already exists: ${e}`, "EEXIST", void 0);
|
|
635
600
|
if ((await this.stat(t)).isFile) {
|
|
636
601
|
const h = await this.readFile(t, "binary");
|
|
637
602
|
await this.writeFile(e, h);
|
|
638
603
|
} else {
|
|
639
604
|
if (!a)
|
|
640
|
-
throw new
|
|
605
|
+
throw new o(`Cannot copy directory without recursive option: ${t}`, "EISDIR", void 0);
|
|
641
606
|
await this.mkdir(e, { recursive: !0 });
|
|
642
607
|
const h = await this.readDir(t);
|
|
643
608
|
for (const m of h) {
|
|
644
|
-
const F = `${t}/${m.name}`,
|
|
645
|
-
await this.copy(F,
|
|
609
|
+
const F = `${t}/${m.name}`, D = `${e}/${m.name}`;
|
|
610
|
+
await this.copy(F, D, { recursive: !0, force: r });
|
|
646
611
|
}
|
|
647
612
|
}
|
|
648
|
-
await this.notifyChange({ path: e, type: "added", isDirectory: !1 });
|
|
649
613
|
} catch (a) {
|
|
650
|
-
throw a instanceof
|
|
614
|
+
throw a instanceof o ? a : new o(`Failed to copy from ${t} to ${e}`, "CP_FAILED", void 0, a);
|
|
651
615
|
}
|
|
652
616
|
}
|
|
653
617
|
/**
|
|
654
618
|
* Start watching a file or directory for changes
|
|
619
|
+
*
|
|
620
|
+
* @param path - The path to watch (minimatch syntax allowed)
|
|
621
|
+
* @param options - Watch options
|
|
622
|
+
* @param options.recursive - Whether to watch recursively (default: true)
|
|
623
|
+
* @param options.exclude - Glob pattern(s) to exclude (minimatch).
|
|
624
|
+
* @returns Promise that resolves when watching starts
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* ```typescript
|
|
628
|
+
* // Watch entire directory tree recursively (default)
|
|
629
|
+
* await fs.watch('/data');
|
|
630
|
+
*
|
|
631
|
+
* // Watch only immediate children (shallow)
|
|
632
|
+
* await fs.watch('/data', { recursive: false });
|
|
633
|
+
*
|
|
634
|
+
* // Watch a single file
|
|
635
|
+
* await fs.watch('/config.json', { recursive: false });
|
|
636
|
+
*
|
|
637
|
+
* // Watch all json files but not in dist directory
|
|
638
|
+
* await fs.watch('/**\/*.json', { recursive: false, exclude: ['dist/**'] });
|
|
639
|
+
*
|
|
640
|
+
* ```
|
|
655
641
|
*/
|
|
656
|
-
async watch(t) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
642
|
+
async watch(t, e) {
|
|
643
|
+
if (!this.options.broadcastChannel)
|
|
644
|
+
throw new o("This instance is not configured to send events. Please specify options.broadcastChannel to enable watching.", "ENOENT");
|
|
645
|
+
const i = {
|
|
646
|
+
pattern: H(t, e?.recursive ?? !0),
|
|
647
|
+
include: Array.isArray(e?.include) ? e.include : [e?.include ?? "**"],
|
|
648
|
+
exclude: Array.isArray(e?.exclude) ? e.exclude : [e?.exclude ?? ""]
|
|
649
|
+
};
|
|
650
|
+
this.watchers.set(t, i);
|
|
662
651
|
}
|
|
663
652
|
/**
|
|
664
653
|
* Stop watching a previously watched path
|
|
665
654
|
*/
|
|
666
655
|
unwatch(t) {
|
|
667
|
-
|
|
668
|
-
this.watchers.delete(e), this.watchers.size === 0 && this.watchTimer && (clearInterval(this.watchTimer), this.watchTimer = null);
|
|
656
|
+
this.watchers.delete(t);
|
|
669
657
|
}
|
|
670
658
|
/**
|
|
671
659
|
* Dispose of resources and clean up the file system instance
|
|
@@ -674,49 +662,7 @@ class A {
|
|
|
674
662
|
* to properly clean up resources like the broadcast channel and watch timers.
|
|
675
663
|
*/
|
|
676
664
|
dispose() {
|
|
677
|
-
this.broadcastChannel && (this.broadcastChannel.close(), this.broadcastChannel = null), this.
|
|
678
|
-
}
|
|
679
|
-
async buildSnapshot(t) {
|
|
680
|
-
const e = /* @__PURE__ */ new Map(), i = async (a) => {
|
|
681
|
-
const r = await this.stat(a);
|
|
682
|
-
if (e.set(a, r), r.isDirectory) {
|
|
683
|
-
const s = await this.readDir(a);
|
|
684
|
-
for (const o of s) {
|
|
685
|
-
const c = `${a === "/" ? "" : a}/${o.name}`;
|
|
686
|
-
await i(c);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
};
|
|
690
|
-
return await i(t), e;
|
|
691
|
-
}
|
|
692
|
-
async scanWatches() {
|
|
693
|
-
if (!this.scanning) {
|
|
694
|
-
this.scanning = !0;
|
|
695
|
-
try {
|
|
696
|
-
await Promise.all(
|
|
697
|
-
[...this.watchers.entries()].map(async ([t, e]) => {
|
|
698
|
-
let i;
|
|
699
|
-
try {
|
|
700
|
-
i = await this.buildSnapshot(t);
|
|
701
|
-
} catch {
|
|
702
|
-
i = /* @__PURE__ */ new Map();
|
|
703
|
-
}
|
|
704
|
-
for (const [a, r] of i) {
|
|
705
|
-
const s = e.get(a);
|
|
706
|
-
s ? (s.mtime !== r.mtime || s.size !== r.size) && await this.notifyChange({ path: a, type: "changed", isDirectory: r.isDirectory }) : await this.notifyChange({ path: a, type: "added", isDirectory: r.isDirectory });
|
|
707
|
-
}
|
|
708
|
-
for (const a of e.keys())
|
|
709
|
-
if (!i.has(a)) {
|
|
710
|
-
const r = e.get(a);
|
|
711
|
-
await this.notifyChange({ path: a, type: "removed", isDirectory: r?.isDirectory ?? !1 });
|
|
712
|
-
}
|
|
713
|
-
this.watchers.set(t, i);
|
|
714
|
-
})
|
|
715
|
-
);
|
|
716
|
-
} finally {
|
|
717
|
-
this.scanning = !1;
|
|
718
|
-
}
|
|
719
|
-
}
|
|
665
|
+
this.broadcastChannel && (this.broadcastChannel.close(), this.broadcastChannel = null), this.watchers.clear();
|
|
720
666
|
}
|
|
721
667
|
/**
|
|
722
668
|
* Synchronize the file system with external data
|
|
@@ -747,22 +693,21 @@ class A {
|
|
|
747
693
|
* ```
|
|
748
694
|
*/
|
|
749
695
|
async sync(t, e) {
|
|
750
|
-
await this.
|
|
696
|
+
await this.mount();
|
|
751
697
|
try {
|
|
752
698
|
(e?.cleanBefore ?? !1) && await this.clear("/");
|
|
753
699
|
for (const [a, r] of t) {
|
|
754
|
-
const s =
|
|
755
|
-
let
|
|
756
|
-
r instanceof Blob ?
|
|
700
|
+
const s = y(a);
|
|
701
|
+
let n;
|
|
702
|
+
r instanceof Blob ? n = await O(r) : n = r, await this.writeFile(s, n);
|
|
757
703
|
}
|
|
758
|
-
await this.notifyChange({ path: "/", type: "changed", isDirectory: !0 });
|
|
759
704
|
} catch (i) {
|
|
760
|
-
throw i instanceof
|
|
705
|
+
throw i instanceof o ? i : new o("Failed to sync file system", "SYNC_FAILED", void 0, i);
|
|
761
706
|
}
|
|
762
707
|
}
|
|
763
708
|
}
|
|
764
|
-
typeof
|
|
709
|
+
typeof globalThis < "u" && globalThis.constructor.name === "DedicatedWorkerGlobalScope" && E(new $());
|
|
765
710
|
export {
|
|
766
|
-
|
|
711
|
+
$ as OPFSWorker
|
|
767
712
|
};
|
|
768
713
|
//# sourceMappingURL=raw.js.map
|