@zenfs/dom 1.2.0 → 1.2.2
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 +5 -3
- package/dist/access.js +56 -13
- package/package.json +1 -1
package/dist/access.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CreationOptions, FileSystem, InodeLike } from '@zenfs/core';
|
|
2
|
-
import { IndexFS } from '@zenfs/core';
|
|
2
|
+
import { IndexFS, Inode } from '@zenfs/core';
|
|
3
3
|
export interface WebAccessOptions {
|
|
4
4
|
handle: FileSystemDirectoryHandle;
|
|
5
5
|
metadata?: string;
|
|
@@ -9,7 +9,7 @@ export interface WebAccessOptions {
|
|
|
9
9
|
*/
|
|
10
10
|
disableHandleCache?: boolean;
|
|
11
11
|
}
|
|
12
|
-
type HKindToType<T extends FileSystemHandleKind> = T extends 'directory' ? FileSystemDirectoryHandle : T extends 'file' ? FileSystemFileHandle : FileSystemHandle;
|
|
12
|
+
type HKindToType<T extends FileSystemHandleKind | null> = T extends 'directory' ? FileSystemDirectoryHandle : T extends 'file' ? FileSystemFileHandle : FileSystemHandle;
|
|
13
13
|
declare const WebAccessFS_base: import("@zenfs/core").Mixin<typeof IndexFS, import("@zenfs/core").AsyncMixin>;
|
|
14
14
|
/**
|
|
15
15
|
* @todo Consider supporting synchronous stuff with `FileSystemFileHandle.createSyncAccessHandle()`\
|
|
@@ -39,6 +39,8 @@ export declare class WebAccessFS extends WebAccessFS_base {
|
|
|
39
39
|
*/
|
|
40
40
|
_sync: FileSystem;
|
|
41
41
|
constructor(root: FileSystemDirectoryHandle, disableHandleCache?: boolean);
|
|
42
|
+
stat(path: string): Promise<Inode>;
|
|
43
|
+
readdir(path: string): Promise<string[]>;
|
|
42
44
|
protected remove(path: string): Promise<void>;
|
|
43
45
|
protected removeSync(): void;
|
|
44
46
|
read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
|
|
@@ -49,7 +51,7 @@ export declare class WebAccessFS extends WebAccessFS_base {
|
|
|
49
51
|
*/
|
|
50
52
|
writeFile(path: string, data: Uint8Array): Promise<void>;
|
|
51
53
|
mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
|
|
52
|
-
protected get<const T extends FileSystemHandleKind | null>(kind: T | undefined, path: string): Promise<
|
|
54
|
+
protected get<const T extends FileSystemHandleKind | null>(kind: T | undefined, path: string): Promise<HKindToType<T>>;
|
|
53
55
|
}
|
|
54
56
|
declare const _WebAccess: {
|
|
55
57
|
readonly name: "WebAccess";
|
package/dist/access.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Async, constants, IndexFS, InMemory, Inode } from '@zenfs/core';
|
|
2
2
|
import { basename, dirname, join } from '@zenfs/core/path.js';
|
|
3
|
-
import { S_IFDIR, S_IFMT } from '@zenfs/core/vfs/constants.js';
|
|
4
3
|
import { log, withErrno } from 'kerium';
|
|
5
4
|
import { alert } from 'kerium/log';
|
|
6
5
|
import { _throw } from 'utilium';
|
|
@@ -79,6 +78,39 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
79
78
|
if (disableHandleCache)
|
|
80
79
|
this.attributes.set('no_handle_cache', true);
|
|
81
80
|
}
|
|
81
|
+
async stat(path) {
|
|
82
|
+
try {
|
|
83
|
+
return await super.stat(path);
|
|
84
|
+
}
|
|
85
|
+
catch (ex) {
|
|
86
|
+
if (ex.code != 'ENOENT')
|
|
87
|
+
throw ex;
|
|
88
|
+
// This handle must have been created after initialization
|
|
89
|
+
// Try to add a new inode for the handle to the index
|
|
90
|
+
const handle = await this.get(null, path);
|
|
91
|
+
const inode = new Inode();
|
|
92
|
+
if (isKind(handle, 'file')) {
|
|
93
|
+
const file = await handle.getFile();
|
|
94
|
+
inode.update({
|
|
95
|
+
mode: 0o644 | constants.S_IFREG,
|
|
96
|
+
size: file.size,
|
|
97
|
+
mtimeMs: file.lastModified,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
inode.update({
|
|
102
|
+
mode: constants.S_IFDIR | 0o777,
|
|
103
|
+
size: 0,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
this.index.set(path, inode);
|
|
107
|
+
return inode;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async readdir(path) {
|
|
111
|
+
const dirHandle = await this.get('directory', path);
|
|
112
|
+
return await Array.fromAsync(dirHandle.keys());
|
|
113
|
+
}
|
|
82
114
|
async remove(path) {
|
|
83
115
|
const handle = await this.get('directory', dirname(path));
|
|
84
116
|
await handle.removeEntry(basename(path), { recursive: true }).catch(ex => _throw(convertException(ex, path)));
|
|
@@ -93,7 +125,11 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
93
125
|
const file = await handle.getFile();
|
|
94
126
|
const data = await file.arrayBuffer();
|
|
95
127
|
if (data.byteLength < end - offset)
|
|
96
|
-
throw alert(withErrno('EIO',
|
|
128
|
+
throw alert(withErrno('EIO', [
|
|
129
|
+
'Unexpected mismatch in file data size. This should not happen.',
|
|
130
|
+
`tried to read ${end - offset} bytes but the file is ${data.byteLength} bytes.`,
|
|
131
|
+
`path: ${path}`,
|
|
132
|
+
].join('\n' + ' '.repeat(24))));
|
|
97
133
|
buffer.set(new Uint8Array(data, offset, end - offset));
|
|
98
134
|
}
|
|
99
135
|
async write(path, buffer, offset) {
|
|
@@ -105,7 +141,7 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
105
141
|
const inode = this.index.get(path);
|
|
106
142
|
if (!inode)
|
|
107
143
|
throw withErrno('ENOENT');
|
|
108
|
-
const isDir = (inode.mode & S_IFMT) == S_IFDIR;
|
|
144
|
+
const isDir = (inode.mode & constants.S_IFMT) == constants.S_IFDIR;
|
|
109
145
|
let handle;
|
|
110
146
|
try {
|
|
111
147
|
handle = await this.get(isDir ? 'directory' : 'file', path);
|
|
@@ -151,13 +187,12 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
151
187
|
return inode;
|
|
152
188
|
}
|
|
153
189
|
async get(kind = null, path) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (!
|
|
157
|
-
throw withErrno('ENOENT');
|
|
158
|
-
if (kind && !isKind(handle, kind))
|
|
190
|
+
const maybeHandle = this._handles.get(path);
|
|
191
|
+
if (!this.disableHandleCache && maybeHandle) {
|
|
192
|
+
if (kind && !isKind(maybeHandle, kind))
|
|
159
193
|
throw withErrno(kind == 'directory' ? 'ENOTDIR' : 'EISDIR');
|
|
160
|
-
return
|
|
194
|
+
return maybeHandle;
|
|
195
|
+
// Otherwise, fall through to the slow path
|
|
161
196
|
}
|
|
162
197
|
if (path == '/')
|
|
163
198
|
return this.root;
|
|
@@ -168,13 +203,21 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
168
203
|
}
|
|
169
204
|
try {
|
|
170
205
|
const handle = await dir[kind == 'file' ? 'getFileHandle' : 'getDirectoryHandle'](parts.at(-1));
|
|
206
|
+
if (!this.disableHandleCache)
|
|
207
|
+
this._handles.set(path, handle);
|
|
171
208
|
return handle;
|
|
172
209
|
}
|
|
173
210
|
catch (ex) {
|
|
174
|
-
if (ex.name
|
|
175
|
-
throw withErrno(kind == 'file' ? 'EISDIR' : 'ENOTDIR');
|
|
176
|
-
else
|
|
211
|
+
if (ex.name != 'TypeMismatchError')
|
|
177
212
|
throw convertException(ex, path);
|
|
213
|
+
else if (kind === null) {
|
|
214
|
+
const handle = await dir.getFileHandle(parts.at(-1)).catch(ex => _throw(convertException(ex, path)));
|
|
215
|
+
if (!this.disableHandleCache)
|
|
216
|
+
this._handles.set(path, handle);
|
|
217
|
+
return handle;
|
|
218
|
+
}
|
|
219
|
+
else
|
|
220
|
+
throw withErrno(kind == 'file' ? 'EISDIR' : 'ENOTDIR');
|
|
178
221
|
}
|
|
179
222
|
}
|
|
180
223
|
}
|
|
@@ -186,7 +229,7 @@ const _WebAccess = {
|
|
|
186
229
|
disableHandleCache: { type: 'boolean', required: false },
|
|
187
230
|
},
|
|
188
231
|
async create(options) {
|
|
189
|
-
const fs = new WebAccessFS(options.handle);
|
|
232
|
+
const fs = new WebAccessFS(options.handle, options.disableHandleCache);
|
|
190
233
|
await fs._loadMetadata(options.metadata);
|
|
191
234
|
return fs;
|
|
192
235
|
},
|