opfs-worker 1.3.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -106
- package/dist/{facade.d.ts → OPFSFacade.d.ts} +22 -5
- package/dist/OPFSFacade.d.ts.map +1 -0
- package/dist/{worker.d.ts → OPFSWorker.d.ts} +10 -6
- package/dist/OPFSWorker.d.ts.map +1 -0
- package/dist/assets/worker.entry-DUlEoroc.js.map +1 -0
- package/dist/createOPFSWorker.d.ts +17 -0
- package/dist/createOPFSWorker.d.ts.map +1 -0
- package/dist/helpers-DNj8ZoMu.cjs +4 -0
- package/dist/helpers-DNj8ZoMu.cjs.map +1 -0
- package/dist/{helpers-Ca2c767K.js → helpers-WY2jfbOT.js} +221 -221
- package/dist/helpers-WY2jfbOT.js.map +1 -0
- package/dist/index.cjs +296 -285
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +369 -340
- package/dist/index.js.map +1 -1
- package/dist/index.pure.cjs +2 -0
- package/dist/index.pure.cjs.map +1 -0
- package/dist/index.pure.d.ts +6 -0
- package/dist/index.pure.d.ts.map +1 -0
- package/dist/{raw.js → index.pure.js} +241 -186
- package/dist/index.pure.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts +11 -1
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/worker.entry.d.ts +2 -0
- package/dist/worker.entry.d.ts.map +1 -0
- package/docs/api-reference.md +815 -0
- package/docs/file-descriptors.md +696 -0
- package/docs/types.md +232 -0
- package/package.json +14 -8
- package/src/OPFSFacade.ts +460 -0
- package/src/OPFSWorker.ts +1544 -0
- package/src/createOPFSWorker.ts +57 -0
- package/src/index.pure.ts +7 -0
- package/src/index.ts +15 -0
- package/src/types.ts +99 -0
- package/src/utils/encoder.ts +205 -0
- package/src/utils/errors.ts +297 -0
- package/src/utils/helpers.ts +465 -0
- package/src/worker.entry.ts +6 -0
- package/dist/assets/worker-1Wh1cr7P.js.map +0 -1
- package/dist/assets/worker-BeJaVyBV.js.map +0 -1
- package/dist/assets/worker-DYYLzR1Y.js.map +0 -1
- package/dist/facade.d.ts.map +0 -1
- package/dist/helpers-BuGfPAg0.js +0 -1439
- package/dist/helpers-BuGfPAg0.js.map +0 -1
- package/dist/helpers-CF7A2WQG.cjs +0 -4
- package/dist/helpers-CF7A2WQG.cjs.map +0 -1
- package/dist/helpers-CIiblZ8d.cjs +0 -4
- package/dist/helpers-CIiblZ8d.cjs.map +0 -1
- package/dist/helpers-CKOebsbw.js +0 -1423
- package/dist/helpers-CKOebsbw.js.map +0 -1
- package/dist/helpers-Ca2c767K.js.map +0 -1
- package/dist/helpers-Dwc92hv9.cjs +0 -4
- package/dist/helpers-Dwc92hv9.cjs.map +0 -1
- package/dist/raw.cjs +0 -2
- package/dist/raw.cjs.map +0 -1
- package/dist/raw.d.ts +0 -13
- package/dist/raw.d.ts.map +0 -1
- package/dist/raw.js.map +0 -1
- package/dist/worker.d.ts.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { V as C, t as g, l as O, h as P, q as p, s as D, P as z, w as u, O as w, m as h, W as l, n as k, j as F, o as v, p as E, z as M, E as S, D as T, G as $, v as b, A as H, c as B, g as N, r as _, L as R, J as A, H as I, K as L, k as m, C as U } from "./helpers-WY2jfbOT.js";
|
|
2
|
+
import { M as K, F as X, I as Y, a as Q, f as Z, b as tt, S as et, B as at, y as rt, d as it, e as st, x as nt, i as ot, u as ct } from "./helpers-WY2jfbOT.js";
|
|
3
|
+
import { transfer as x } from "comlink";
|
|
4
|
+
class V {
|
|
4
5
|
/** Root directory handle for the file system */
|
|
5
6
|
root;
|
|
6
7
|
/** Map of watched paths and options */
|
|
@@ -17,6 +18,8 @@ class j {
|
|
|
17
18
|
hashAlgorithm: "etag",
|
|
18
19
|
broadcastChannel: "opfs-worker"
|
|
19
20
|
};
|
|
21
|
+
/** Shared sync handles per path (OPFS allows only one handle per file) */
|
|
22
|
+
openHandles = /* @__PURE__ */ new Map();
|
|
20
23
|
/** Map of open file descriptors to their metadata */
|
|
21
24
|
openFiles = /* @__PURE__ */ new Map();
|
|
22
25
|
/** Next available file descriptor number */
|
|
@@ -28,7 +31,7 @@ class j {
|
|
|
28
31
|
_getFileDescriptor(t) {
|
|
29
32
|
const e = this.openFiles.get(t);
|
|
30
33
|
if (!e)
|
|
31
|
-
throw new
|
|
34
|
+
throw new C("descriptor", `Invalid file descriptor: ${t}`);
|
|
32
35
|
return e;
|
|
33
36
|
}
|
|
34
37
|
/**
|
|
@@ -43,29 +46,29 @@ class j {
|
|
|
43
46
|
if (!this.options.broadcastChannel)
|
|
44
47
|
return;
|
|
45
48
|
const e = t.path;
|
|
46
|
-
if (![...this.watchers.values()].some((
|
|
49
|
+
if (![...this.watchers.values()].some((i) => g(e, i.pattern) && i.include.some((s) => s && g(e, s)) && !i.exclude.some((s) => s && g(e, s))))
|
|
47
50
|
return;
|
|
48
|
-
let
|
|
51
|
+
let a;
|
|
49
52
|
if (this.options.hashAlgorithm)
|
|
50
53
|
try {
|
|
51
|
-
|
|
54
|
+
a = (await this.stat(e)).hash;
|
|
52
55
|
} catch {
|
|
53
56
|
}
|
|
54
57
|
try {
|
|
55
58
|
this.broadcastChannel || (this.broadcastChannel = new BroadcastChannel(this.options.broadcastChannel));
|
|
56
|
-
const
|
|
59
|
+
const i = {
|
|
57
60
|
namespace: this.options.namespace,
|
|
58
61
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
59
62
|
...t,
|
|
60
|
-
...
|
|
63
|
+
...a && { hash: a }
|
|
61
64
|
};
|
|
62
|
-
this.broadcastChannel.postMessage(
|
|
63
|
-
} catch (
|
|
64
|
-
console.warn("Failed to send event via BroadcastChannel:",
|
|
65
|
+
this.broadcastChannel.postMessage(i);
|
|
66
|
+
} catch (i) {
|
|
67
|
+
console.warn("Failed to send event via BroadcastChannel:", i);
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
/**
|
|
68
|
-
* Creates a new
|
|
71
|
+
* Creates a new OPFSWorker instance
|
|
69
72
|
*
|
|
70
73
|
* @param options - Optional configuration options
|
|
71
74
|
* @param options.root - Root path for the file system (default: '/')
|
|
@@ -75,7 +78,7 @@ class j {
|
|
|
75
78
|
* @throws {OPFSError} If OPFS is not supported in the current browser
|
|
76
79
|
*/
|
|
77
80
|
constructor(t) {
|
|
78
|
-
|
|
81
|
+
O(), t && this.setOptions(t);
|
|
79
82
|
}
|
|
80
83
|
/**
|
|
81
84
|
* Initialize the file system within a given directory
|
|
@@ -88,7 +91,7 @@ class j {
|
|
|
88
91
|
*
|
|
89
92
|
* @example
|
|
90
93
|
* ```typescript
|
|
91
|
-
* const fs = new
|
|
94
|
+
* const fs = new OPFSWorker();
|
|
92
95
|
*
|
|
93
96
|
* // Use OPFS root (default)
|
|
94
97
|
* await fs.mount();
|
|
@@ -99,12 +102,12 @@ class j {
|
|
|
99
102
|
*/
|
|
100
103
|
async mount() {
|
|
101
104
|
const t = this.options.root;
|
|
102
|
-
return this.mountingPromise && await this.mountingPromise, this.mountingPromise = new Promise(async (e,
|
|
105
|
+
return this.mountingPromise && await this.mountingPromise, this.mountingPromise = new Promise(async (e, r) => {
|
|
103
106
|
try {
|
|
104
|
-
const
|
|
105
|
-
this.root = t === "/" ?
|
|
106
|
-
} catch (
|
|
107
|
-
|
|
107
|
+
const a = await navigator.storage.getDirectory();
|
|
108
|
+
this.root = t === "/" ? a : await this.getDirectoryHandle(t, !0, a), e(!0);
|
|
109
|
+
} catch (a) {
|
|
110
|
+
r(new P(t, a));
|
|
108
111
|
} finally {
|
|
109
112
|
this.mountingPromise = null;
|
|
110
113
|
}
|
|
@@ -121,7 +124,7 @@ class j {
|
|
|
121
124
|
* @param options.broadcastChannel - Custom name for the broadcast channel
|
|
122
125
|
*/
|
|
123
126
|
async setOptions(t) {
|
|
124
|
-
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 =
|
|
127
|
+
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 = p(t.root), this.options.namespace || (this.options.namespace = `opfs-worker:${this.options.root}`), await this.mount());
|
|
125
128
|
}
|
|
126
129
|
/**
|
|
127
130
|
* Get a directory handle from a path
|
|
@@ -141,12 +144,12 @@ class j {
|
|
|
141
144
|
* const docsDir2 = await fs.getDirectoryHandle(['users', 'john', 'documents'], true);
|
|
142
145
|
* ```
|
|
143
146
|
*/
|
|
144
|
-
async getDirectoryHandle(t, e = !1,
|
|
145
|
-
const
|
|
146
|
-
let
|
|
147
|
-
for (const s of
|
|
148
|
-
|
|
149
|
-
return
|
|
147
|
+
async getDirectoryHandle(t, e = !1, r = this.root) {
|
|
148
|
+
const a = Array.isArray(t) ? t : D(t);
|
|
149
|
+
let i = r;
|
|
150
|
+
for (const s of a)
|
|
151
|
+
i = await i.getDirectoryHandle(s, { create: e });
|
|
152
|
+
return i;
|
|
150
153
|
}
|
|
151
154
|
/**
|
|
152
155
|
* Get a file handle from a path
|
|
@@ -167,12 +170,12 @@ class j {
|
|
|
167
170
|
* const fileHandle2 = await fs.getFileHandle(['config', 'settings.json'], true);
|
|
168
171
|
* ```
|
|
169
172
|
*/
|
|
170
|
-
async getFileHandle(t, e = !1,
|
|
171
|
-
const
|
|
172
|
-
if (
|
|
173
|
-
throw new
|
|
174
|
-
const
|
|
175
|
-
return (await this.getDirectoryHandle(
|
|
173
|
+
async getFileHandle(t, e = !1, r = this.root) {
|
|
174
|
+
const a = D(t);
|
|
175
|
+
if (a.length === 0)
|
|
176
|
+
throw new z("Path must not be empty", Array.isArray(t) ? t.join("/") : t);
|
|
177
|
+
const i = a.pop();
|
|
178
|
+
return (await this.getDirectoryHandle(a, e, r)).getFileHandle(i, { create: e });
|
|
176
179
|
}
|
|
177
180
|
/**
|
|
178
181
|
* Get a complete index of all files and directories in the file system
|
|
@@ -194,10 +197,10 @@ class j {
|
|
|
194
197
|
* ```
|
|
195
198
|
*/
|
|
196
199
|
async index() {
|
|
197
|
-
const t = /* @__PURE__ */ new Map(), e = async (
|
|
198
|
-
const
|
|
199
|
-
for (const
|
|
200
|
-
const s = `${
|
|
200
|
+
const t = /* @__PURE__ */ new Map(), e = async (r) => {
|
|
201
|
+
const a = await this.readDir(r);
|
|
202
|
+
for (const i of a) {
|
|
203
|
+
const s = `${r === "/" ? "" : r}/${i.name}`;
|
|
201
204
|
try {
|
|
202
205
|
const n = await this.stat(s);
|
|
203
206
|
t.set(s, n), n.isDirectory && await e(s);
|
|
@@ -237,17 +240,17 @@ class j {
|
|
|
237
240
|
async readFile(t) {
|
|
238
241
|
await this.mount();
|
|
239
242
|
try {
|
|
240
|
-
return await u(t,
|
|
243
|
+
return await u(t, async () => {
|
|
241
244
|
const e = await this.open(t);
|
|
242
245
|
try {
|
|
243
|
-
const { size:
|
|
244
|
-
return
|
|
246
|
+
const { size: r } = await this.fstat(e), a = new Uint8Array(r);
|
|
247
|
+
return r > 0 && await this.read(e, a, 0, r, 0), x(a, [a.buffer]);
|
|
245
248
|
} finally {
|
|
246
249
|
await this.close(e);
|
|
247
250
|
}
|
|
248
251
|
});
|
|
249
252
|
} catch (e) {
|
|
250
|
-
throw
|
|
253
|
+
throw e instanceof w ? e : h(e, { path: t, isDirectory: !1 });
|
|
251
254
|
}
|
|
252
255
|
}
|
|
253
256
|
/**
|
|
@@ -274,15 +277,15 @@ class j {
|
|
|
274
277
|
*/
|
|
275
278
|
async writeFile(t, e) {
|
|
276
279
|
await this.mount();
|
|
277
|
-
const
|
|
278
|
-
await u(t,
|
|
279
|
-
const
|
|
280
|
+
const r = e instanceof Uint8Array ? e : new Uint8Array(e);
|
|
281
|
+
await u(t, async () => {
|
|
282
|
+
const a = await this.exists(t), i = await this.open(t, { create: !0, truncate: !0 });
|
|
280
283
|
try {
|
|
281
|
-
await this.write(
|
|
284
|
+
await this.write(i, r, 0, r.length, null, !1), await this.fsync(i);
|
|
282
285
|
} finally {
|
|
283
|
-
await this.close(
|
|
286
|
+
await this.close(i);
|
|
284
287
|
}
|
|
285
|
-
await this.notifyChange({ path: t, type:
|
|
288
|
+
await this.notifyChange({ path: t, type: a ? l.Changed : l.Added, isDirectory: !1 });
|
|
286
289
|
});
|
|
287
290
|
}
|
|
288
291
|
/**
|
|
@@ -309,16 +312,16 @@ class j {
|
|
|
309
312
|
*/
|
|
310
313
|
async appendFile(t, e) {
|
|
311
314
|
await this.mount();
|
|
312
|
-
const
|
|
313
|
-
await u(t,
|
|
314
|
-
const
|
|
315
|
+
const r = e instanceof Uint8Array ? e : new Uint8Array(e);
|
|
316
|
+
await u(t, async () => {
|
|
317
|
+
const a = await this.open(t, { create: !0 });
|
|
315
318
|
try {
|
|
316
|
-
const { size:
|
|
317
|
-
await this.write(
|
|
319
|
+
const { size: i } = await this.fstat(a);
|
|
320
|
+
await this.write(a, r, 0, r.length, i, !1), await this.fsync(a);
|
|
318
321
|
} finally {
|
|
319
|
-
await this.close(
|
|
322
|
+
await this.close(a);
|
|
320
323
|
}
|
|
321
|
-
await this.notifyChange({ path: t, type:
|
|
324
|
+
await this.notifyChange({ path: t, type: l.Changed, isDirectory: !1 });
|
|
322
325
|
});
|
|
323
326
|
}
|
|
324
327
|
/**
|
|
@@ -344,20 +347,20 @@ class j {
|
|
|
344
347
|
*/
|
|
345
348
|
async mkdir(t, e) {
|
|
346
349
|
await this.mount();
|
|
347
|
-
const
|
|
348
|
-
let
|
|
349
|
-
for (let s = 0; s <
|
|
350
|
-
const n =
|
|
350
|
+
const r = e?.recursive ?? !1, a = D(t);
|
|
351
|
+
let i = this.root;
|
|
352
|
+
for (let s = 0; s < a.length; s++) {
|
|
353
|
+
const n = a[s];
|
|
351
354
|
try {
|
|
352
|
-
|
|
355
|
+
i = await i.getDirectoryHandle(n, { create: r || s === a.length - 1 });
|
|
353
356
|
} catch (o) {
|
|
354
|
-
throw o.name === "NotFoundError" ?
|
|
355
|
-
path:
|
|
357
|
+
throw o.name === "NotFoundError" ? h(o, {
|
|
358
|
+
path: k(a.slice(0, s + 1)),
|
|
356
359
|
existenceType: "directory"
|
|
357
|
-
}) : o.name === "TypeMismatchError" ?
|
|
360
|
+
}) : o.name === "TypeMismatchError" ? h(o, { path: n, isDirectory: !1 }) : new F("create directory", n, o);
|
|
358
361
|
}
|
|
359
362
|
}
|
|
360
|
-
await this.notifyChange({ path: t, type:
|
|
363
|
+
await this.notifyChange({ path: t, type: l.Added, isDirectory: !0 });
|
|
361
364
|
}
|
|
362
365
|
/**
|
|
363
366
|
* Get file or directory statistics
|
|
@@ -391,11 +394,11 @@ class j {
|
|
|
391
394
|
isFile: !1,
|
|
392
395
|
isDirectory: !0
|
|
393
396
|
};
|
|
394
|
-
const e =
|
|
395
|
-
let
|
|
397
|
+
const e = v(t);
|
|
398
|
+
let r;
|
|
396
399
|
try {
|
|
397
|
-
|
|
398
|
-
const
|
|
400
|
+
r = await this.getDirectoryHandle(E(t), !1);
|
|
401
|
+
const a = this.options.hashAlgorithm, s = await (await r.getFileHandle(e, { create: !1 })).getFile(), n = {
|
|
399
402
|
kind: "file",
|
|
400
403
|
size: s.size,
|
|
401
404
|
mtime: new Date(s.lastModified).toISOString(),
|
|
@@ -403,24 +406,24 @@ class j {
|
|
|
403
406
|
isFile: !0,
|
|
404
407
|
isDirectory: !1
|
|
405
408
|
};
|
|
406
|
-
if (
|
|
409
|
+
if (a === "etag")
|
|
407
410
|
n.hash = `${s.lastModified.toString(36)}-${s.size.toString(36)}`;
|
|
408
|
-
else if (typeof
|
|
411
|
+
else if (typeof a == "string")
|
|
409
412
|
try {
|
|
410
|
-
const o = await
|
|
413
|
+
const o = await M(s, a, this.options.maxFileSize);
|
|
411
414
|
n.hash = o;
|
|
412
415
|
} catch (o) {
|
|
413
416
|
console.warn(`Failed to calculate hash for ${t}:`, o);
|
|
414
417
|
}
|
|
415
418
|
return n;
|
|
416
|
-
} catch (
|
|
417
|
-
if (
|
|
418
|
-
throw new
|
|
419
|
-
if (
|
|
420
|
-
throw new
|
|
419
|
+
} catch (a) {
|
|
420
|
+
if (a.name === "NotFoundError")
|
|
421
|
+
throw new S("file", t, a);
|
|
422
|
+
if (a.name !== "TypeMismatchError")
|
|
423
|
+
throw new F("stat", t, a);
|
|
421
424
|
}
|
|
422
425
|
try {
|
|
423
|
-
return await
|
|
426
|
+
return await r.getDirectoryHandle(e, { create: !1 }), {
|
|
424
427
|
kind: "directory",
|
|
425
428
|
size: 0,
|
|
426
429
|
mtime: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
@@ -428,8 +431,8 @@ class j {
|
|
|
428
431
|
isFile: !1,
|
|
429
432
|
isDirectory: !0
|
|
430
433
|
};
|
|
431
|
-
} catch (
|
|
432
|
-
throw new
|
|
434
|
+
} catch (a) {
|
|
435
|
+
throw new F("stat", t, a);
|
|
433
436
|
}
|
|
434
437
|
}
|
|
435
438
|
/**
|
|
@@ -452,17 +455,17 @@ class j {
|
|
|
452
455
|
*/
|
|
453
456
|
async readDir(t) {
|
|
454
457
|
await this.mount();
|
|
455
|
-
const e = await this.getDirectoryHandle(t, !1),
|
|
456
|
-
for await (const [
|
|
457
|
-
const s =
|
|
458
|
-
|
|
459
|
-
name:
|
|
460
|
-
kind:
|
|
458
|
+
const e = await this.getDirectoryHandle(t, !1), r = [];
|
|
459
|
+
for await (const [a, i] of e.entries()) {
|
|
460
|
+
const s = i.kind === "file";
|
|
461
|
+
r.push({
|
|
462
|
+
name: a,
|
|
463
|
+
kind: i.kind,
|
|
461
464
|
isFile: s,
|
|
462
465
|
isDirectory: !s
|
|
463
466
|
});
|
|
464
467
|
}
|
|
465
|
-
return
|
|
468
|
+
return r;
|
|
466
469
|
}
|
|
467
470
|
/**
|
|
468
471
|
* Check if a file or directory exists
|
|
@@ -481,26 +484,26 @@ class j {
|
|
|
481
484
|
async exists(t) {
|
|
482
485
|
if (await this.mount(), t === "/")
|
|
483
486
|
return !0;
|
|
484
|
-
const e =
|
|
485
|
-
let
|
|
487
|
+
const e = v(t);
|
|
488
|
+
let r = null;
|
|
486
489
|
try {
|
|
487
|
-
|
|
488
|
-
} catch (
|
|
489
|
-
if (
|
|
490
|
-
throw
|
|
490
|
+
r = await this.getDirectoryHandle(E(t), !1);
|
|
491
|
+
} catch (a) {
|
|
492
|
+
if (r = null, a.name !== "NotFoundError" && a.name !== "TypeMismatchError")
|
|
493
|
+
throw a;
|
|
491
494
|
}
|
|
492
|
-
if (!
|
|
495
|
+
if (!r || !e)
|
|
493
496
|
return !1;
|
|
494
497
|
try {
|
|
495
|
-
return await
|
|
496
|
-
} catch (
|
|
497
|
-
if (
|
|
498
|
-
throw
|
|
498
|
+
return await r.getFileHandle(e, { create: !1 }), !0;
|
|
499
|
+
} catch (a) {
|
|
500
|
+
if (a.name !== "NotFoundError" && a.name !== "TypeMismatchError")
|
|
501
|
+
throw a;
|
|
499
502
|
try {
|
|
500
|
-
return await
|
|
501
|
-
} catch (
|
|
502
|
-
if (
|
|
503
|
-
throw
|
|
503
|
+
return await r.getDirectoryHandle(e, { create: !1 }), !0;
|
|
504
|
+
} catch (i) {
|
|
505
|
+
if (i.name !== "NotFoundError" && i.name !== "TypeMismatchError")
|
|
506
|
+
throw i;
|
|
504
507
|
return !1;
|
|
505
508
|
}
|
|
506
509
|
}
|
|
@@ -528,13 +531,13 @@ class j {
|
|
|
528
531
|
await this.mount();
|
|
529
532
|
try {
|
|
530
533
|
const e = await this.readDir(t);
|
|
531
|
-
for (const
|
|
532
|
-
const
|
|
533
|
-
await this.remove(
|
|
534
|
+
for (const r of e) {
|
|
535
|
+
const a = `${t === "/" ? "" : t}/${r.name}`;
|
|
536
|
+
await this.remove(a, { recursive: !0 });
|
|
534
537
|
}
|
|
535
|
-
await this.notifyChange({ path: t, type:
|
|
538
|
+
await this.notifyChange({ path: t, type: l.Changed, isDirectory: !0 });
|
|
536
539
|
} catch (e) {
|
|
537
|
-
throw e instanceof
|
|
540
|
+
throw e instanceof w ? e : h(e, { path: t, isDirectory: !0 });
|
|
538
541
|
}
|
|
539
542
|
}
|
|
540
543
|
/**
|
|
@@ -563,9 +566,9 @@ class j {
|
|
|
563
566
|
*/
|
|
564
567
|
async remove(t, e) {
|
|
565
568
|
if (await this.mount(), t === "/")
|
|
566
|
-
throw new
|
|
567
|
-
const { recursive:
|
|
568
|
-
await
|
|
569
|
+
throw new T("EROOT", t);
|
|
570
|
+
const { recursive: r = !1, force: a = !1 } = e || {}, i = await this.getDirectoryHandle(E(t), !1), s = await this.stat(t);
|
|
571
|
+
await $(i, t, { recursive: r, force: a }), await this.notifyChange({ path: t, type: l.Removed, isDirectory: s.isDirectory });
|
|
569
572
|
}
|
|
570
573
|
/**
|
|
571
574
|
* Resolve a path to an absolute path
|
|
@@ -588,12 +591,12 @@ class j {
|
|
|
588
591
|
async realpath(t) {
|
|
589
592
|
await this.mount();
|
|
590
593
|
try {
|
|
591
|
-
const e =
|
|
594
|
+
const e = b(t);
|
|
592
595
|
if (!await this.exists(e))
|
|
593
|
-
throw new
|
|
596
|
+
throw new S("file", e);
|
|
594
597
|
return e;
|
|
595
598
|
} catch (e) {
|
|
596
|
-
throw e instanceof
|
|
599
|
+
throw e instanceof w ? e : h(e, { path: t });
|
|
597
600
|
}
|
|
598
601
|
}
|
|
599
602
|
/**
|
|
@@ -618,15 +621,15 @@ class j {
|
|
|
618
621
|
* await fs.rename('/old/path/file.txt', '/new/path/renamed.txt', { overwrite: true });
|
|
619
622
|
* ```
|
|
620
623
|
*/
|
|
621
|
-
async rename(t, e,
|
|
624
|
+
async rename(t, e, r) {
|
|
622
625
|
await this.mount();
|
|
623
626
|
try {
|
|
624
|
-
const
|
|
625
|
-
if (await this.exists(e) && !
|
|
626
|
-
throw new
|
|
627
|
-
await this.copy(t, e, { recursive: !0, overwrite:
|
|
628
|
-
} catch (
|
|
629
|
-
throw
|
|
627
|
+
const a = r?.overwrite ?? !1, i = await this.stat(t);
|
|
628
|
+
if (await this.exists(e) && !a)
|
|
629
|
+
throw new H(e);
|
|
630
|
+
await this.copy(t, e, { recursive: !0, overwrite: a }), await this.remove(t, { recursive: !0 }), await this.notifyChange({ path: t, type: l.Removed, isDirectory: i.isDirectory }), await this.notifyChange({ path: e, type: l.Added, isDirectory: i.isDirectory });
|
|
631
|
+
} catch (a) {
|
|
632
|
+
throw a instanceof w ? a : h(a, { path: t });
|
|
630
633
|
}
|
|
631
634
|
}
|
|
632
635
|
/**
|
|
@@ -654,29 +657,29 @@ class j {
|
|
|
654
657
|
* await fs.copy('/source', '/dest', { recursive: true, overwrite: false });
|
|
655
658
|
* ```
|
|
656
659
|
*/
|
|
657
|
-
async copy(t, e,
|
|
660
|
+
async copy(t, e, r) {
|
|
658
661
|
await this.mount();
|
|
659
662
|
try {
|
|
660
|
-
const
|
|
663
|
+
const a = r?.recursive ?? !1, i = r?.overwrite ?? !0;
|
|
661
664
|
if (!await this.exists(t))
|
|
662
|
-
throw new
|
|
663
|
-
if (await this.exists(e) && !
|
|
664
|
-
throw new
|
|
665
|
+
throw new S("source", t);
|
|
666
|
+
if (await this.exists(e) && !i)
|
|
667
|
+
throw new H(e);
|
|
665
668
|
if ((await this.stat(t)).isFile) {
|
|
666
669
|
const c = await this.readFile(t);
|
|
667
670
|
await this.writeFile(e, c);
|
|
668
671
|
} else {
|
|
669
|
-
if (!
|
|
670
|
-
throw new
|
|
672
|
+
if (!a)
|
|
673
|
+
throw new B("directory", t);
|
|
671
674
|
await this.mkdir(e, { recursive: !0 });
|
|
672
675
|
const c = await this.readDir(t);
|
|
673
|
-
for (const
|
|
674
|
-
const
|
|
675
|
-
await this.copy(
|
|
676
|
+
for (const y of c) {
|
|
677
|
+
const f = `${t}/${y.name}`, d = `${e}/${y.name}`;
|
|
678
|
+
await this.copy(f, d, { recursive: !0, overwrite: i });
|
|
676
679
|
}
|
|
677
680
|
}
|
|
678
|
-
} catch (
|
|
679
|
-
throw
|
|
681
|
+
} catch (a) {
|
|
682
|
+
throw a instanceof w ? a : h(a, { path: t });
|
|
680
683
|
}
|
|
681
684
|
}
|
|
682
685
|
/**
|
|
@@ -706,13 +709,13 @@ class j {
|
|
|
706
709
|
*/
|
|
707
710
|
async watch(t, e) {
|
|
708
711
|
if (!this.options.broadcastChannel)
|
|
709
|
-
throw new
|
|
710
|
-
const
|
|
711
|
-
pattern:
|
|
712
|
+
throw new N("This instance is not configured to send events. Please specify options.broadcastChannel to enable watching.");
|
|
713
|
+
const r = {
|
|
714
|
+
pattern: _(t, e?.recursive ?? !0),
|
|
712
715
|
include: Array.isArray(e?.include) ? e.include : [e?.include ?? "**"],
|
|
713
716
|
exclude: Array.isArray(e?.exclude) ? e.exclude : [e?.exclude ?? ""]
|
|
714
717
|
};
|
|
715
|
-
this.watchers.set(t,
|
|
718
|
+
this.watchers.set(t, r);
|
|
716
719
|
}
|
|
717
720
|
/**
|
|
718
721
|
* Stop watching a previously watched path
|
|
@@ -749,18 +752,18 @@ class j {
|
|
|
749
752
|
*/
|
|
750
753
|
async open(t, e) {
|
|
751
754
|
await this.mount();
|
|
752
|
-
const { create:
|
|
755
|
+
const { create: r = !1, exclusive: a = !1, truncate: i = !1 } = e || {}, s = p(b(t));
|
|
753
756
|
try {
|
|
754
|
-
return
|
|
757
|
+
return r && a ? await u(s, async () => {
|
|
755
758
|
if (await this.exists(s))
|
|
756
|
-
throw new
|
|
757
|
-
return this._openFile(s,
|
|
758
|
-
}) : await this._openFile(s,
|
|
759
|
+
throw new H(s);
|
|
760
|
+
return this._openFile(s, r, i);
|
|
761
|
+
}) : await this._openFile(s, r, i);
|
|
759
762
|
} catch (n) {
|
|
760
|
-
if (n instanceof
|
|
763
|
+
if (n instanceof w)
|
|
761
764
|
throw n;
|
|
762
765
|
const o = n && n.name === "TypeMismatchError";
|
|
763
|
-
throw
|
|
766
|
+
throw h(n, {
|
|
764
767
|
path: s,
|
|
765
768
|
isDirectory: !!o
|
|
766
769
|
});
|
|
@@ -768,24 +771,31 @@ class j {
|
|
|
768
771
|
}
|
|
769
772
|
/**
|
|
770
773
|
* Internal method to open a file (without locking)
|
|
774
|
+
*
|
|
775
|
+
* Multiple FDs for the same path share one sync access handle (OPFS limit),
|
|
776
|
+
* with independent per-FD positions — similar to Node.js.
|
|
771
777
|
* @private
|
|
772
778
|
*/
|
|
773
|
-
async _openFile(t, e,
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
await
|
|
777
|
-
|
|
778
|
-
|
|
779
|
+
async _openFile(t, e, r) {
|
|
780
|
+
let a = this.openHandles.get(t);
|
|
781
|
+
if (!a) {
|
|
782
|
+
const s = await this.getFileHandle(t, e);
|
|
783
|
+
try {
|
|
784
|
+
await s.getFile();
|
|
785
|
+
} catch (o) {
|
|
786
|
+
throw h(o, { path: t, isDirectory: !0 });
|
|
787
|
+
}
|
|
788
|
+
const n = await R(s, t);
|
|
789
|
+
a = { fileHandle: s, syncHandle: n, refCount: 0 }, this.openHandles.set(t, a);
|
|
779
790
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
return this.openFiles.set(s, {
|
|
791
|
+
a.refCount++, r && (a.syncHandle.truncate(0), a.syncHandle.flush());
|
|
792
|
+
const i = this.nextFd++;
|
|
793
|
+
return this.openFiles.set(i, {
|
|
784
794
|
path: t,
|
|
785
|
-
fileHandle:
|
|
786
|
-
syncHandle:
|
|
795
|
+
fileHandle: a.fileHandle,
|
|
796
|
+
syncHandle: a.syncHandle,
|
|
787
797
|
position: 0
|
|
788
|
-
}),
|
|
798
|
+
}), i;
|
|
789
799
|
}
|
|
790
800
|
/**
|
|
791
801
|
* Close a file descriptor
|
|
@@ -803,7 +813,9 @@ class j {
|
|
|
803
813
|
*/
|
|
804
814
|
async close(t) {
|
|
805
815
|
const e = this._getFileDescriptor(t);
|
|
806
|
-
|
|
816
|
+
this.openFiles.delete(t);
|
|
817
|
+
const r = this.openHandles.get(e.path);
|
|
818
|
+
r && (r.refCount--, r.refCount <= 0 && (A(t, r.syncHandle, e.path), this.openHandles.delete(e.path)));
|
|
807
819
|
}
|
|
808
820
|
/**
|
|
809
821
|
* Read data from a file descriptor
|
|
@@ -829,17 +841,17 @@ class j {
|
|
|
829
841
|
* await fs.close(fd);
|
|
830
842
|
* ```
|
|
831
843
|
*/
|
|
832
|
-
async read(t, e, a, i
|
|
844
|
+
async read(t, e, r, a, i) {
|
|
833
845
|
const s = this._getFileDescriptor(t);
|
|
834
|
-
I(e.length, a, i
|
|
846
|
+
I(e.length, r, a, i);
|
|
835
847
|
try {
|
|
836
|
-
const n =
|
|
848
|
+
const n = i ?? s.position, o = s.syncHandle.getSize(), { isEOF: c, actualLength: y } = L(n, a, o);
|
|
837
849
|
if (c)
|
|
838
|
-
return
|
|
839
|
-
const
|
|
840
|
-
return
|
|
850
|
+
return x({ bytesRead: 0, buffer: e }, [e.buffer]);
|
|
851
|
+
const f = e.subarray(r, r + y), d = s.syncHandle.read(f, { at: n });
|
|
852
|
+
return i == null && (s.position = n + d), x({ bytesRead: d, buffer: e }, [e.buffer]);
|
|
841
853
|
} catch (n) {
|
|
842
|
-
throw
|
|
854
|
+
throw m("read", t, s.path, n);
|
|
843
855
|
}
|
|
844
856
|
}
|
|
845
857
|
/**
|
|
@@ -863,14 +875,14 @@ class j {
|
|
|
863
875
|
* await fs.close(fd);
|
|
864
876
|
* ```
|
|
865
877
|
*/
|
|
866
|
-
async write(t, e,
|
|
867
|
-
const n = this._getFileDescriptor(t), o =
|
|
868
|
-
I(e.length,
|
|
878
|
+
async write(t, e, r = 0, a, i, s = !0) {
|
|
879
|
+
const n = this._getFileDescriptor(t), o = a ?? e.length - r;
|
|
880
|
+
I(e.length, r, o, i);
|
|
869
881
|
try {
|
|
870
|
-
const c =
|
|
871
|
-
return (
|
|
882
|
+
const c = i ?? n.position, y = e.subarray(r, r + o), f = n.syncHandle.write(y, { at: c });
|
|
883
|
+
return (i == null || i === n.position) && (n.position = c + f), s && await this.notifyChange({ path: n.path, type: l.Changed, isDirectory: !1 }), f;
|
|
872
884
|
} catch (c) {
|
|
873
|
-
throw
|
|
885
|
+
throw m("write", t, n.path, c);
|
|
874
886
|
}
|
|
875
887
|
}
|
|
876
888
|
/**
|
|
@@ -912,13 +924,13 @@ class j {
|
|
|
912
924
|
* ```
|
|
913
925
|
*/
|
|
914
926
|
async ftruncate(t, e = 0) {
|
|
915
|
-
const
|
|
927
|
+
const r = this._getFileDescriptor(t);
|
|
916
928
|
if (e < 0 || !Number.isInteger(e))
|
|
917
|
-
throw new
|
|
929
|
+
throw new C("argument", "Invalid size");
|
|
918
930
|
try {
|
|
919
|
-
|
|
920
|
-
} catch (
|
|
921
|
-
throw
|
|
931
|
+
r.syncHandle.truncate(e), r.syncHandle.flush(), r.position > e && (r.position = e), await this.notifyChange({ path: r.path, type: l.Changed, isDirectory: !1 });
|
|
932
|
+
} catch (a) {
|
|
933
|
+
throw m("truncate", t, r.path, a);
|
|
922
934
|
}
|
|
923
935
|
}
|
|
924
936
|
/**
|
|
@@ -939,8 +951,8 @@ class j {
|
|
|
939
951
|
const e = this._getFileDescriptor(t);
|
|
940
952
|
try {
|
|
941
953
|
e.syncHandle.flush();
|
|
942
|
-
} catch (
|
|
943
|
-
throw
|
|
954
|
+
} catch (r) {
|
|
955
|
+
throw m("sync", t, e.path, r);
|
|
944
956
|
}
|
|
945
957
|
}
|
|
946
958
|
/**
|
|
@@ -951,9 +963,9 @@ class j {
|
|
|
951
963
|
*/
|
|
952
964
|
dispose() {
|
|
953
965
|
this.broadcastChannel && (this.broadcastChannel.close(), this.broadcastChannel = null), this.watchers.clear();
|
|
954
|
-
for (const [t, e] of this.
|
|
955
|
-
A(
|
|
956
|
-
this.openFiles.clear(), this.nextFd = 1;
|
|
966
|
+
for (const [t, e] of this.openHandles)
|
|
967
|
+
A(-1, e.syncHandle, t);
|
|
968
|
+
this.openHandles.clear(), this.openFiles.clear(), this.nextFd = 1;
|
|
957
969
|
}
|
|
958
970
|
/**
|
|
959
971
|
* Synchronize the file system with external data
|
|
@@ -984,18 +996,61 @@ class j {
|
|
|
984
996
|
async createIndex(t) {
|
|
985
997
|
await this.mount();
|
|
986
998
|
try {
|
|
987
|
-
for (const [e,
|
|
988
|
-
const
|
|
989
|
-
let
|
|
990
|
-
|
|
999
|
+
for (const [e, r] of t) {
|
|
1000
|
+
const a = p(e);
|
|
1001
|
+
let i;
|
|
1002
|
+
r instanceof Blob ? i = await U(r) : typeof r == "string" ? i = new TextEncoder().encode(r) : i = r, await this.writeFile(a, i);
|
|
991
1003
|
}
|
|
992
1004
|
} catch (e) {
|
|
993
|
-
throw e instanceof
|
|
1005
|
+
throw e instanceof w ? e : h(e);
|
|
994
1006
|
}
|
|
995
1007
|
}
|
|
996
1008
|
}
|
|
997
|
-
typeof globalThis < "u" && globalThis.constructor.name === "DedicatedWorkerGlobalScope" && O(new j());
|
|
998
1009
|
export {
|
|
999
|
-
|
|
1010
|
+
H as AlreadyExistsError,
|
|
1011
|
+
K as BINARY_FILE_EXTENSIONS,
|
|
1012
|
+
T as DirectoryOperationError,
|
|
1013
|
+
S as ExistenceError,
|
|
1014
|
+
X as FileBusyError,
|
|
1015
|
+
F as FileSystemOperationError,
|
|
1016
|
+
B as FileTypeError,
|
|
1017
|
+
Y as IOError,
|
|
1018
|
+
P as InitializationFailedError,
|
|
1019
|
+
w as OPFSError,
|
|
1020
|
+
Q as OPFSNotSupportedError,
|
|
1021
|
+
V as OPFSWorker,
|
|
1022
|
+
Z as OperationAbortedError,
|
|
1023
|
+
N as OperationNotSupportedError,
|
|
1024
|
+
z as PathError,
|
|
1025
|
+
tt as PermissionError,
|
|
1026
|
+
et as StorageError,
|
|
1027
|
+
C as ValidationError,
|
|
1028
|
+
l as WatchEventType,
|
|
1029
|
+
v as basename,
|
|
1030
|
+
at as buffersEqual,
|
|
1031
|
+
M as calculateFileHash,
|
|
1032
|
+
L as calculateReadLength,
|
|
1033
|
+
O as checkOPFSSupport,
|
|
1034
|
+
U as convertBlobToUint8Array,
|
|
1035
|
+
rt as createBuffer,
|
|
1036
|
+
m as createFDError,
|
|
1037
|
+
R as createSyncHandleSafe,
|
|
1038
|
+
it as decodeBuffer,
|
|
1039
|
+
E as dirname,
|
|
1040
|
+
st as encodeString,
|
|
1041
|
+
nt as extname,
|
|
1042
|
+
ot as isBinaryFileExtension,
|
|
1043
|
+
ct as isPathExcluded,
|
|
1044
|
+
k as joinPath,
|
|
1045
|
+
h as mapDomError,
|
|
1046
|
+
g as matchMinimatch,
|
|
1047
|
+
_ as normalizeMinimatch,
|
|
1048
|
+
p as normalizePath,
|
|
1049
|
+
$ as removeEntry,
|
|
1050
|
+
b as resolvePath,
|
|
1051
|
+
A as safeCloseSyncHandle,
|
|
1052
|
+
D as splitPath,
|
|
1053
|
+
I as validateReadWriteArgs,
|
|
1054
|
+
u as withLock
|
|
1000
1055
|
};
|
|
1001
|
-
//# sourceMappingURL=
|
|
1056
|
+
//# sourceMappingURL=index.pure.js.map
|