@zenfs/dom 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access.d.ts +6 -27
- package/dist/access.js +27 -122
- package/dist/utils.js +2 -1
- package/package.json +2 -2
package/dist/access.d.ts
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import type { CreationOptions,
|
|
2
|
-
import {
|
|
1
|
+
import type { CreationOptions, FileSystem } from '@zenfs/core';
|
|
2
|
+
import { IndexFS } from '@zenfs/core';
|
|
3
3
|
export interface WebAccessOptions {
|
|
4
4
|
handle: FileSystemDirectoryHandle;
|
|
5
5
|
metadata?: string;
|
|
6
6
|
}
|
|
7
7
|
type HKindToType<T extends FileSystemHandleKind> = T extends 'directory' ? FileSystemDirectoryHandle : T extends 'file' ? FileSystemFileHandle : FileSystemHandle;
|
|
8
|
-
declare const WebAccessFS_base: import("@zenfs/core").Mixin<typeof
|
|
8
|
+
declare const WebAccessFS_base: import("@zenfs/core").Mixin<typeof IndexFS, import("@zenfs/core").AsyncMixin>;
|
|
9
9
|
export declare class WebAccessFS extends WebAccessFS_base {
|
|
10
|
-
/**
|
|
11
|
-
* Disables index optimizations,
|
|
12
|
-
* like using the index for `readdir`
|
|
13
|
-
*/
|
|
14
|
-
private readonly disableIndexOptimizations;
|
|
15
|
-
protected index: Index;
|
|
16
10
|
protected _handles: Map<string, FileSystemHandle>;
|
|
17
11
|
/**
|
|
18
12
|
* Loads all of the handles.
|
|
@@ -28,14 +22,9 @@ export declare class WebAccessFS extends WebAccessFS_base {
|
|
|
28
22
|
* @hidden
|
|
29
23
|
*/
|
|
30
24
|
_sync: FileSystem;
|
|
31
|
-
constructor(handle: FileSystemDirectoryHandle
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* like using the index for `readdir`
|
|
35
|
-
*/
|
|
36
|
-
disableIndexOptimizations?: boolean);
|
|
37
|
-
rename(oldPath: string, newPath: string): Promise<void>;
|
|
38
|
-
unlink(path: string): Promise<void>;
|
|
25
|
+
constructor(handle: FileSystemDirectoryHandle);
|
|
26
|
+
remove(path: string): Promise<void>;
|
|
27
|
+
protected removeSync(path: string): void;
|
|
39
28
|
read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
|
|
40
29
|
write(path: string, buffer: Uint8Array, offset: number): Promise<void>;
|
|
41
30
|
/**
|
|
@@ -43,17 +32,7 @@ export declare class WebAccessFS extends WebAccessFS_base {
|
|
|
43
32
|
* @deprecated @internal @hidden
|
|
44
33
|
*/
|
|
45
34
|
writeFile(path: string, data: Uint8Array): Promise<void>;
|
|
46
|
-
stat(path: string): Promise<Stats>;
|
|
47
|
-
createFile(path: string, flag: string, mode: number, options: CreationOptions): Promise<File>;
|
|
48
|
-
openFile(path: string, flag: string): Promise<File>;
|
|
49
|
-
/**
|
|
50
|
-
* @todo Implement
|
|
51
|
-
*/
|
|
52
|
-
link(srcpath: string): Promise<void>;
|
|
53
|
-
sync(path: string, data?: Uint8Array, stats?: Readonly<Partial<InodeLike>>): Promise<void>;
|
|
54
|
-
rmdir(path: string): Promise<void>;
|
|
55
35
|
mkdir(path: string, mode: number, options: CreationOptions): Promise<void>;
|
|
56
|
-
readdir(path: string): Promise<string[]>;
|
|
57
36
|
protected get<const T extends FileSystemHandleKind | null>(kind: T | undefined, path: string, syscall?: string): T extends FileSystemHandleKind ? HKindToType<T> : FileSystemHandle;
|
|
58
37
|
}
|
|
59
38
|
declare const _WebAccess: {
|
package/dist/access.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Async, constants, Errno, ErrnoError,
|
|
2
|
-
import { S_IFDIR,
|
|
1
|
+
import { Async, constants, Errno, ErrnoError, IndexFS, InMemory, Inode, log } from '@zenfs/core';
|
|
2
|
+
import { S_IFDIR, S_IFMT } from '@zenfs/core/vfs/constants.js';
|
|
3
3
|
import { basename, dirname, join } from '@zenfs/core/vfs/path.js';
|
|
4
4
|
import { _throw } from 'utilium';
|
|
5
5
|
import { convertException } from './utils.js';
|
|
@@ -16,7 +16,7 @@ function isResizable(buffer) {
|
|
|
16
16
|
function isKind(handle, kind) {
|
|
17
17
|
return handle.kind == kind;
|
|
18
18
|
}
|
|
19
|
-
export class WebAccessFS extends Async(
|
|
19
|
+
export class WebAccessFS extends Async(IndexFS) {
|
|
20
20
|
/**
|
|
21
21
|
* Loads all of the handles.
|
|
22
22
|
* @internal @hidden
|
|
@@ -53,15 +53,8 @@ export class WebAccessFS extends Async(FileSystem) {
|
|
|
53
53
|
this.index.set(path, new Inode({ mode: 0o777 | constants.S_IFDIR, size: 0 }));
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
constructor(handle
|
|
57
|
-
/**
|
|
58
|
-
* Disables index optimizations,
|
|
59
|
-
* like using the index for `readdir`
|
|
60
|
-
*/
|
|
61
|
-
disableIndexOptimizations = false) {
|
|
56
|
+
constructor(handle) {
|
|
62
57
|
super(0x77656261, 'webaccessfs');
|
|
63
|
-
this.disableIndexOptimizations = disableIndexOptimizations;
|
|
64
|
-
this.index = new Index();
|
|
65
58
|
this._handles = new Map();
|
|
66
59
|
/**
|
|
67
60
|
* @hidden
|
|
@@ -71,41 +64,12 @@ export class WebAccessFS extends Async(FileSystem) {
|
|
|
71
64
|
this.attributes.set('setid');
|
|
72
65
|
this._handles.set('/', handle);
|
|
73
66
|
}
|
|
74
|
-
async
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (newPath.startsWith(oldPath + '/'))
|
|
78
|
-
throw ErrnoError.With('EBUSY', oldPath, 'rename');
|
|
79
|
-
const handle = this.get(null, oldPath, 'rename');
|
|
80
|
-
if (isKind(handle, 'directory')) {
|
|
81
|
-
const files = await this.readdir(oldPath);
|
|
82
|
-
const stats = await this.stat(oldPath);
|
|
83
|
-
await this.mkdir(newPath, stats.mode, stats);
|
|
84
|
-
for (const file of files)
|
|
85
|
-
await this.rename(join(oldPath, file), join(newPath, file));
|
|
86
|
-
await this.rmdir(oldPath);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (!isKind(handle, 'file')) {
|
|
90
|
-
throw new ErrnoError(Errno.ENOTSUP, 'Not a file or directory handle', oldPath, 'rename');
|
|
91
|
-
}
|
|
92
|
-
const oldFile = await handle.getFile().catch(ex => _throw(convertException(ex, oldPath, 'rename')));
|
|
93
|
-
const destFolder = this.get('directory', dirname(newPath), 'rename');
|
|
94
|
-
const newFile = await destFolder
|
|
95
|
-
.getFileHandle(basename(newPath), { create: true })
|
|
96
|
-
.catch((ex) => _throw(ex.name == 'TypeMismatchError' ? ErrnoError.With('EISDIR', newPath, 'rename') : convertException(ex, newPath, 'rename')));
|
|
97
|
-
const writable = await newFile.createWritable();
|
|
98
|
-
await writable.write(await oldFile.arrayBuffer());
|
|
99
|
-
await writable.close();
|
|
100
|
-
await this.unlink(oldPath);
|
|
101
|
-
this._handles.set(newPath, newFile);
|
|
67
|
+
async remove(path) {
|
|
68
|
+
const handle = this.get('directory', dirname(path));
|
|
69
|
+
await handle.removeEntry(basename(path), { recursive: true }).catch(ex => _throw(convertException(ex, path)));
|
|
102
70
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
throw ErrnoError.With('EBUSY', '/', 'unlink');
|
|
106
|
-
const handle = this.get('directory', dirname(path), 'unlink');
|
|
107
|
-
await handle.removeEntry(basename(path), { recursive: true }).catch(ex => _throw(convertException(ex, path, 'unlink')));
|
|
108
|
-
this.index.delete(path);
|
|
71
|
+
removeSync(path) {
|
|
72
|
+
throw log.crit(ErrnoError.With('ENOSYS', path));
|
|
109
73
|
}
|
|
110
74
|
async read(path, buffer, offset, end) {
|
|
111
75
|
if (end <= offset)
|
|
@@ -126,7 +90,22 @@ export class WebAccessFS extends Async(FileSystem) {
|
|
|
126
90
|
const inode = this.index.get(path);
|
|
127
91
|
if (!inode)
|
|
128
92
|
throw ErrnoError.With('ENOENT', path, 'write');
|
|
129
|
-
const
|
|
93
|
+
const isDir = (inode.mode & S_IFMT) == S_IFDIR;
|
|
94
|
+
let handle;
|
|
95
|
+
try {
|
|
96
|
+
handle = this.get(isDir ? 'directory' : 'file', path, 'write');
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
const parent = this.get('directory', dirname(path), 'write');
|
|
100
|
+
handle = await parent[isDir ? 'getDirectoryHandle' : 'getFileHandle'](basename(path), { create: true }).catch((ex) => _throw(convertException(ex, path)));
|
|
101
|
+
this._handles.set(path, handle);
|
|
102
|
+
}
|
|
103
|
+
if (isDir)
|
|
104
|
+
return;
|
|
105
|
+
if (isKind(handle, 'directory')) {
|
|
106
|
+
log.crit(new ErrnoError(Errno.EIO, 'Mismatch in entry kind on write', path, 'write'));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
130
109
|
const writable = await handle.createWritable();
|
|
131
110
|
try {
|
|
132
111
|
await writable.seek(offset);
|
|
@@ -147,85 +126,11 @@ export class WebAccessFS extends Async(FileSystem) {
|
|
|
147
126
|
async writeFile(path, data) {
|
|
148
127
|
return this.write(path, data, 0);
|
|
149
128
|
}
|
|
150
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
151
|
-
async stat(path) {
|
|
152
|
-
const inode = this.index.get(path);
|
|
153
|
-
if (!inode)
|
|
154
|
-
throw ErrnoError.With('ENOENT', path, 'stat');
|
|
155
|
-
return inode.toStats();
|
|
156
|
-
}
|
|
157
|
-
async createFile(path, flag, mode, options) {
|
|
158
|
-
const handle = this.get('directory', dirname(path), 'createFile');
|
|
159
|
-
if (this.index.has(path))
|
|
160
|
-
throw ErrnoError.With('EEXIST', path, 'createFile');
|
|
161
|
-
const file = await handle.getFileHandle(basename(path), { create: true });
|
|
162
|
-
// Race condition bypass
|
|
163
|
-
const inode = this.index.get(path) ?? new Inode({ ...options, mode: mode | S_IFREG });
|
|
164
|
-
this.index.set(path, inode);
|
|
165
|
-
this._handles.set(path, file);
|
|
166
|
-
return new LazyFile(this, path, flag, inode);
|
|
167
|
-
}
|
|
168
|
-
async openFile(path, flag) {
|
|
169
|
-
const inode = this.index.get(path);
|
|
170
|
-
if (!inode)
|
|
171
|
-
throw ErrnoError.With('ENOENT', path, 'stat');
|
|
172
|
-
return new LazyFile(this, path, flag, inode.toStats());
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* @todo Implement
|
|
176
|
-
*/
|
|
177
|
-
async link(srcpath) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
async sync(path, data, stats) {
|
|
181
|
-
const inode = this.index.get(path) ?? new Inode();
|
|
182
|
-
inode.update(stats);
|
|
183
|
-
this.index.set(path, inode);
|
|
184
|
-
if (!data)
|
|
185
|
-
return;
|
|
186
|
-
const handle = this.get('file', path, 'write');
|
|
187
|
-
const writable = await handle.createWritable();
|
|
188
|
-
try {
|
|
189
|
-
await writable.seek(0);
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
await writable.write({ type: 'seek', position: 0 });
|
|
193
|
-
}
|
|
194
|
-
await writable.write(data);
|
|
195
|
-
await writable.close();
|
|
196
|
-
}
|
|
197
|
-
async rmdir(path) {
|
|
198
|
-
if ((await this.readdir(path)).length)
|
|
199
|
-
throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
|
|
200
|
-
if (path == '/')
|
|
201
|
-
throw ErrnoError.With('EBUSY', '/', 'rmdir');
|
|
202
|
-
const handle = this.get('directory', dirname(path), 'rmdir');
|
|
203
|
-
await handle.removeEntry(basename(path), { recursive: true }).catch(ex => _throw(convertException(ex, path, 'rmdir')));
|
|
204
|
-
this.index.delete(path);
|
|
205
|
-
}
|
|
206
129
|
async mkdir(path, mode, options) {
|
|
207
|
-
|
|
208
|
-
throw ErrnoError.With('EEXIST', path, 'mkdir');
|
|
130
|
+
await super.mkdir(path, mode, options);
|
|
209
131
|
const handle = this.get('directory', dirname(path), 'mkdir');
|
|
210
|
-
const dir = await handle.getDirectoryHandle(basename(path), { create: true });
|
|
132
|
+
const dir = await handle.getDirectoryHandle(basename(path), { create: true }).catch((ex) => _throw(convertException(ex, path)));
|
|
211
133
|
this._handles.set(path, dir);
|
|
212
|
-
this.index.set(path, new Inode({ ...options, mode: mode | S_IFDIR }));
|
|
213
|
-
}
|
|
214
|
-
async readdir(path) {
|
|
215
|
-
if (!this.disableIndexOptimizations) {
|
|
216
|
-
if (!this.index.has(path))
|
|
217
|
-
throw ErrnoError.With('ENOENT', path, 'readdir');
|
|
218
|
-
const entries = this.index.directoryEntries(path);
|
|
219
|
-
if (!entries)
|
|
220
|
-
throw ErrnoError.With('ENOTDIR', path, 'readdir');
|
|
221
|
-
return Object.keys(entries);
|
|
222
|
-
}
|
|
223
|
-
const handle = this.get('directory', path, 'readdir');
|
|
224
|
-
const entries = [];
|
|
225
|
-
for await (const k of handle.keys()) {
|
|
226
|
-
entries.push(k);
|
|
227
|
-
}
|
|
228
|
-
return entries;
|
|
229
134
|
}
|
|
230
135
|
get(kind = null, path, syscall) {
|
|
231
136
|
const handle = this._handles.get(path);
|
package/dist/utils.js
CHANGED
|
@@ -5,13 +5,14 @@ import { ErrnoError, Errno } from '@zenfs/core';
|
|
|
5
5
|
*/
|
|
6
6
|
function errnoForDOMException(ex) {
|
|
7
7
|
switch (ex.name) {
|
|
8
|
+
case 'TypeMismatchError':
|
|
9
|
+
return 'EPERM';
|
|
8
10
|
case 'IndexSizeError':
|
|
9
11
|
case 'HierarchyRequestError':
|
|
10
12
|
case 'InvalidCharacterError':
|
|
11
13
|
case 'InvalidStateError':
|
|
12
14
|
case 'SyntaxError':
|
|
13
15
|
case 'NamespaceError':
|
|
14
|
-
case 'TypeMismatchError':
|
|
15
16
|
case 'ConstraintError':
|
|
16
17
|
case 'VersionError':
|
|
17
18
|
case 'URLMismatchError':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/dom",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "DOM backends for ZenFS",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"typescript-eslint": "^8.8.1"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@zenfs/core": "^1.9.
|
|
64
|
+
"@zenfs/core": "^1.9.1",
|
|
65
65
|
"utilium": "^1.2.10"
|
|
66
66
|
},
|
|
67
67
|
"keywords": [
|