@pistonite/pure 0.27.1 → 0.29.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/LICENSE +1 -1
- package/README.md +23 -4
- package/dist/log/index.js +57 -0
- package/dist/log/index.js.map +1 -0
- package/dist/memory/index.js +92 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/result/index.js +29 -0
- package/dist/result/index.js.map +1 -0
- package/dist/sync/index.js +252 -0
- package/dist/sync/index.js.map +1 -0
- package/package.json +22 -13
- package/src/env.d.ts +1 -0
- package/src/log/index.ts +36 -11
- package/src/log/logger.ts +93 -115
- package/src/memory/cell.ts +21 -11
- package/src/memory/emp.ts +34 -23
- package/src/memory/idgen.test.ts +1 -1
- package/src/memory/index.ts +1 -4
- package/src/memory/persist.ts +9 -12
- package/src/result/index.ts +12 -4
- package/src/sync/batch.test.ts +1 -1
- package/src/sync/batch.ts +12 -17
- package/src/sync/capture.ts +2 -0
- package/src/sync/debounce.test.ts +1 -1
- package/src/sync/debounce.ts +12 -15
- package/src/sync/index.ts +2 -3
- package/src/sync/latest.test.ts +1 -1
- package/src/sync/latest.ts +19 -16
- package/src/sync/once.test.ts +1 -1
- package/src/sync/once.ts +13 -8
- package/src/sync/serial.test.ts +1 -1
- package/src/sync/serial.ts +14 -12
- package/src/sync/util.ts +2 -2
- package/src/fs/FsError.ts +0 -55
- package/src/fs/FsFile.ts +0 -67
- package/src/fs/FsFileImpl.ts +0 -219
- package/src/fs/FsFileMgr.ts +0 -29
- package/src/fs/FsFileStandalone.ts +0 -21
- package/src/fs/FsFileStandaloneImplFileAPI.ts +0 -54
- package/src/fs/FsFileStandaloneImplHandleAPI.ts +0 -147
- package/src/fs/FsFileSystem.ts +0 -71
- package/src/fs/FsFileSystemInternal.ts +0 -30
- package/src/fs/FsImplEntryAPI.ts +0 -149
- package/src/fs/FsImplFileAPI.ts +0 -116
- package/src/fs/FsImplHandleAPI.ts +0 -199
- package/src/fs/FsOpen.ts +0 -271
- package/src/fs/FsOpenFile.ts +0 -256
- package/src/fs/FsPath.ts +0 -137
- package/src/fs/FsSave.ts +0 -216
- package/src/fs/FsSupportStatus.ts +0 -87
- package/src/fs/index.ts +0 -123
- package/src/log/internal.ts +0 -14
- package/src/memory/async_erc.ts +0 -186
- package/src/memory/erc.test.ts +0 -258
- package/src/memory/erc.ts +0 -320
- package/src/pref/dark.ts +0 -151
- package/src/pref/device.ts +0 -118
- package/src/pref/index.ts +0 -13
- package/src/pref/inject_style.ts +0 -22
- package/src/pref/locale.ts +0 -296
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FsFileSystem implementation for FileSystemAccess API
|
|
3
|
-
* @module
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { tryAsync, errstr } from "../result/index.ts";
|
|
7
|
-
|
|
8
|
-
import type { FsFileSystem, FsFileSystemUninit, FsCapabilities } from "./FsFileSystem.ts";
|
|
9
|
-
import { FsErr, type FsResult, type FsVoid, fsErr, fsFail } from "./FsError.ts";
|
|
10
|
-
import type { FsFile } from "./FsFile.ts";
|
|
11
|
-
import { fsComponents, fsGetBase, fsGetName, fsIsRoot, fsNormalize } from "./FsPath.ts";
|
|
12
|
-
import { FsFileMgr } from "./FsFileMgr.ts";
|
|
13
|
-
import type { FsFileSystemInternal } from "./FsFileSystemInternal.ts";
|
|
14
|
-
|
|
15
|
-
type PermissionStatus = "granted" | "denied" | "prompt";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* FsFileSystem implementation that uses FileSystem Access API
|
|
19
|
-
* This is only supported in Chrome/Edge
|
|
20
|
-
*/
|
|
21
|
-
export class FsImplHandleAPI implements FsFileSystemUninit, FsFileSystem, FsFileSystemInternal {
|
|
22
|
-
public root: string;
|
|
23
|
-
public capabilities: FsCapabilities;
|
|
24
|
-
/** If app requested write access */
|
|
25
|
-
private writeMode: boolean;
|
|
26
|
-
private rootHandle: FileSystemDirectoryHandle;
|
|
27
|
-
private permissionStatus: PermissionStatus;
|
|
28
|
-
|
|
29
|
-
private mgr: FsFileMgr;
|
|
30
|
-
|
|
31
|
-
constructor(rootPath: string, rootHandle: FileSystemDirectoryHandle, write: boolean) {
|
|
32
|
-
this.root = rootPath;
|
|
33
|
-
this.rootHandle = rootHandle;
|
|
34
|
-
this.writeMode = write;
|
|
35
|
-
this.permissionStatus = "prompt";
|
|
36
|
-
this.capabilities = { write, live: true };
|
|
37
|
-
this.mgr = new FsFileMgr();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
public async init(): Promise<FsResult<FsFileSystem>> {
|
|
41
|
-
// @ts-expect-error ts lib does not have requestPermission
|
|
42
|
-
this.permissionStatus = await this.rootHandle.requestPermission({
|
|
43
|
-
mode: this.writeMode ? "readwrite" : "read",
|
|
44
|
-
});
|
|
45
|
-
if (this.permissionStatus !== "granted") {
|
|
46
|
-
const err = fsErr(FsErr.PermissionDenied, "User denied permission");
|
|
47
|
-
return { err };
|
|
48
|
-
}
|
|
49
|
-
return { val: this };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
public async listDir(path: string): Promise<FsResult<string[]>> {
|
|
53
|
-
const normalized = fsNormalize(path);
|
|
54
|
-
if (normalized.err) {
|
|
55
|
-
return normalized;
|
|
56
|
-
}
|
|
57
|
-
path = normalized.val;
|
|
58
|
-
|
|
59
|
-
const handle = await this.resolveDir(path);
|
|
60
|
-
if (handle.err) {
|
|
61
|
-
return handle;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const entries = await tryAsync(async () => {
|
|
65
|
-
const entries: string[] = [];
|
|
66
|
-
// @ts-expect-error ts lib does not have values()
|
|
67
|
-
for await (const entry of handle.val.values()) {
|
|
68
|
-
const { kind, name } = entry;
|
|
69
|
-
if (kind === "directory") {
|
|
70
|
-
entries.push(name + "/");
|
|
71
|
-
} else {
|
|
72
|
-
entries.push(name);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return entries;
|
|
76
|
-
});
|
|
77
|
-
if ("err" in entries) {
|
|
78
|
-
const err = fsFail(
|
|
79
|
-
"Error reading entries from directory `" + path + "`: " + errstr(entries.err),
|
|
80
|
-
);
|
|
81
|
-
return { err };
|
|
82
|
-
}
|
|
83
|
-
return entries;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
public async read(path: string): Promise<FsResult<File>> {
|
|
87
|
-
const normalized = fsNormalize(path);
|
|
88
|
-
if (normalized.err) {
|
|
89
|
-
return normalized;
|
|
90
|
-
}
|
|
91
|
-
path = normalized.val;
|
|
92
|
-
|
|
93
|
-
const handle = await this.resolveFile(path);
|
|
94
|
-
if (handle.err) {
|
|
95
|
-
return handle;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const file = await tryAsync(() => handle.val.getFile());
|
|
99
|
-
if ("err" in file) {
|
|
100
|
-
const err = fsFail("Failed to read file `" + path + "`: " + errstr(file.err));
|
|
101
|
-
return { err };
|
|
102
|
-
}
|
|
103
|
-
return file;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public async write(path: string, content: Uint8Array): Promise<FsVoid> {
|
|
107
|
-
if (!this.writeMode) {
|
|
108
|
-
const err = fsErr(FsErr.PermissionDenied, "Write mode not requested");
|
|
109
|
-
return { err };
|
|
110
|
-
}
|
|
111
|
-
const normalized = fsNormalize(path);
|
|
112
|
-
if (normalized.err) {
|
|
113
|
-
return normalized;
|
|
114
|
-
}
|
|
115
|
-
path = normalized.val;
|
|
116
|
-
|
|
117
|
-
const handle = await this.resolveFile(path);
|
|
118
|
-
if (handle.err) {
|
|
119
|
-
return handle;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const result = await tryAsync(async () => {
|
|
123
|
-
const file = await handle.val.createWritable();
|
|
124
|
-
await file.write(content);
|
|
125
|
-
await file.close();
|
|
126
|
-
return {};
|
|
127
|
-
});
|
|
128
|
-
if ("err" in result) {
|
|
129
|
-
const err = fsFail("Failed to write file `" + path + "`: " + errstr(result.err));
|
|
130
|
-
return { err };
|
|
131
|
-
}
|
|
132
|
-
return {};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
public getFile(path: string): FsFile {
|
|
136
|
-
return this.mgr.get(this, path);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
public getOpenedPaths(): string[] {
|
|
140
|
-
return this.mgr.getOpenedPaths();
|
|
141
|
-
}
|
|
142
|
-
public closeFile(path: string): void {
|
|
143
|
-
this.mgr.close(path);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Resolve the FileSystemDirectoryHandle for a directory.
|
|
148
|
-
* The path must be normalized
|
|
149
|
-
*/
|
|
150
|
-
private async resolveDir(path: string): Promise<FsResult<FileSystemDirectoryHandle>> {
|
|
151
|
-
if (fsIsRoot(path)) {
|
|
152
|
-
return { val: this.rootHandle };
|
|
153
|
-
}
|
|
154
|
-
let handle: FileSystemDirectoryHandle = this.rootHandle;
|
|
155
|
-
const parts: string[] = [];
|
|
156
|
-
for (const part of fsComponents(path)) {
|
|
157
|
-
parts.push(part);
|
|
158
|
-
const next = await tryAsync(() => handle.getDirectoryHandle(part));
|
|
159
|
-
if ("err" in next) {
|
|
160
|
-
const dir = parts.join("/");
|
|
161
|
-
const err = fsFail(
|
|
162
|
-
"Failed to resolve directory `" + dir + "`: " + errstr(next.err),
|
|
163
|
-
);
|
|
164
|
-
return { err };
|
|
165
|
-
}
|
|
166
|
-
handle = next.val;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return { val: handle };
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Resolve the FileSystemFileHandle for a file.
|
|
174
|
-
* The path must be normalized
|
|
175
|
-
*/
|
|
176
|
-
private async resolveFile(path: string): Promise<FsResult<FileSystemFileHandle>> {
|
|
177
|
-
const parent = fsGetBase(path);
|
|
178
|
-
if (parent.err) {
|
|
179
|
-
return parent;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const name = fsGetName(path);
|
|
183
|
-
if (name.err) {
|
|
184
|
-
return name;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const handle = await this.resolveDir(parent.val);
|
|
188
|
-
if (handle.err) {
|
|
189
|
-
return handle;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const file = await tryAsync(() => handle.val.getFileHandle(name.val));
|
|
193
|
-
if ("err" in file) {
|
|
194
|
-
const err = fsFail("Failed to resolve file `" + path + "`: " + errstr(file.err));
|
|
195
|
-
return { err };
|
|
196
|
-
}
|
|
197
|
-
return file;
|
|
198
|
-
}
|
|
199
|
-
}
|
package/src/fs/FsOpen.ts
DELETED
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
import { tryCatch, tryAsync, errstr } from "../result/index.ts";
|
|
2
|
-
|
|
3
|
-
import type { FsFileSystem, FsFileSystemUninit } from "./FsFileSystem.ts";
|
|
4
|
-
import { FsErr, type FsError, type FsResult, fsErr, fsFail } from "./FsError.ts";
|
|
5
|
-
import { fsGetSupportStatus } from "./FsSupportStatus.ts";
|
|
6
|
-
import { FsImplFileAPI } from "./FsImplFileAPI.ts";
|
|
7
|
-
import { FsImplEntryAPI } from "./FsImplEntryAPI.ts";
|
|
8
|
-
import { FsImplHandleAPI } from "./FsImplHandleAPI.ts";
|
|
9
|
-
|
|
10
|
-
/** Handle for handling top level open errors, and decide if the operation should be retried */
|
|
11
|
-
export type FsOpenRetryHandler = (error: FsError, attempt: number) => Promise<FsResult<boolean>>;
|
|
12
|
-
|
|
13
|
-
const MAX_RETRY = 10;
|
|
14
|
-
|
|
15
|
-
/** Open a file system for read-only access with a directory picker dialog */
|
|
16
|
-
export async function fsOpenRead(
|
|
17
|
-
retryHandler?: FsOpenRetryHandler,
|
|
18
|
-
): Promise<FsResult<FsFileSystem>> {
|
|
19
|
-
const fs = await createWithPicker(false, retryHandler);
|
|
20
|
-
if (fs.err) {
|
|
21
|
-
return fs;
|
|
22
|
-
}
|
|
23
|
-
return await init(fs.val, retryHandler);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Open a file system for read-write access with a directory picker dialog */
|
|
27
|
-
export async function fsOpenReadWrite(
|
|
28
|
-
retryHandler?: FsOpenRetryHandler,
|
|
29
|
-
): Promise<FsResult<FsFileSystem>> {
|
|
30
|
-
const fs = await createWithPicker(true, retryHandler);
|
|
31
|
-
if (fs.err) {
|
|
32
|
-
return fs;
|
|
33
|
-
}
|
|
34
|
-
return await init(fs.val, retryHandler);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** Open a file system for read-only access from a DataTransferItem from a drag and drop event */
|
|
38
|
-
export async function fsOpenReadFrom(
|
|
39
|
-
item: DataTransferItem,
|
|
40
|
-
retryHandler?: FsOpenRetryHandler,
|
|
41
|
-
): Promise<FsResult<FsFileSystem>> {
|
|
42
|
-
const fs = await createFromDataTransferItem(item, false, retryHandler);
|
|
43
|
-
if (fs.err) {
|
|
44
|
-
return fs;
|
|
45
|
-
}
|
|
46
|
-
return await init(fs.val, retryHandler);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Open a file system for read-write access from a DataTransferItem from a drag and drop event */
|
|
50
|
-
export async function fsOpenReadWriteFrom(
|
|
51
|
-
item: DataTransferItem,
|
|
52
|
-
retryHandler?: FsOpenRetryHandler,
|
|
53
|
-
): Promise<FsResult<FsFileSystem>> {
|
|
54
|
-
const fs = await createFromDataTransferItem(item, true, retryHandler);
|
|
55
|
-
if (fs.err) {
|
|
56
|
-
return fs;
|
|
57
|
-
}
|
|
58
|
-
return await init(fs.val, retryHandler);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async function createWithPicker(
|
|
62
|
-
write: boolean,
|
|
63
|
-
retryHandler: FsOpenRetryHandler | undefined,
|
|
64
|
-
): Promise<FsResult<FsFileSystemUninit>> {
|
|
65
|
-
for (let attempt = 1; attempt <= MAX_RETRY; attempt++) {
|
|
66
|
-
const { implementation } = fsGetSupportStatus();
|
|
67
|
-
if (implementation === "FileSystemAccess") {
|
|
68
|
-
const handle = await tryAsync(() => showDirectoryPicker(write));
|
|
69
|
-
if (handle.val) {
|
|
70
|
-
return createFromFileSystemHandle(handle.val, write);
|
|
71
|
-
}
|
|
72
|
-
if (retryHandler) {
|
|
73
|
-
const error = isAbortError(handle.err)
|
|
74
|
-
? fsErr(FsErr.UserAbort, "User cancelled the operation")
|
|
75
|
-
: fsFail(errstr(handle.err));
|
|
76
|
-
const shouldRetry = await retryHandler(error, attempt);
|
|
77
|
-
if (shouldRetry.err) {
|
|
78
|
-
// retry handler failed
|
|
79
|
-
return shouldRetry;
|
|
80
|
-
}
|
|
81
|
-
if (!shouldRetry.val) {
|
|
82
|
-
// don't retry
|
|
83
|
-
return { err: error };
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// Retry with FileSystemAccess API
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// FileEntry API only supported through drag and drop
|
|
91
|
-
// so fallback to File API
|
|
92
|
-
const inputElement = document.createElement("input");
|
|
93
|
-
inputElement.id = "temp";
|
|
94
|
-
inputElement.style.display = "none";
|
|
95
|
-
document.body.appendChild(inputElement);
|
|
96
|
-
inputElement.type = "file";
|
|
97
|
-
inputElement.webkitdirectory = true;
|
|
98
|
-
|
|
99
|
-
const fsUninit = await new Promise<FsResult<FsFileSystemUninit>>((resolve) => {
|
|
100
|
-
inputElement.addEventListener("change", (event) => {
|
|
101
|
-
const files = (event.target as HTMLInputElement).files;
|
|
102
|
-
if (!files) {
|
|
103
|
-
const err = fsFail("Failed to get files from input element");
|
|
104
|
-
return resolve({ err });
|
|
105
|
-
}
|
|
106
|
-
resolve(createFromFileList(files));
|
|
107
|
-
});
|
|
108
|
-
inputElement.addEventListener("cancel", () => {
|
|
109
|
-
resolve({
|
|
110
|
-
err: fsErr(FsErr.UserAbort, "User cancelled the operation"),
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
inputElement.click();
|
|
114
|
-
});
|
|
115
|
-
inputElement.remove();
|
|
116
|
-
|
|
117
|
-
if (fsUninit.val) {
|
|
118
|
-
return fsUninit;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (retryHandler) {
|
|
122
|
-
const shouldRetry = await retryHandler(fsUninit.err, attempt);
|
|
123
|
-
if (shouldRetry.err) {
|
|
124
|
-
// retry handler failed
|
|
125
|
-
return shouldRetry;
|
|
126
|
-
}
|
|
127
|
-
if (!shouldRetry.val) {
|
|
128
|
-
// don't retry
|
|
129
|
-
return fsUninit;
|
|
130
|
-
}
|
|
131
|
-
// fall through to retry
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
return { err: fsFail("Max retry count reached") };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function createFromDataTransferItem(
|
|
138
|
-
item: DataTransferItem,
|
|
139
|
-
write: boolean,
|
|
140
|
-
retryHandler: FsOpenRetryHandler | undefined,
|
|
141
|
-
): Promise<FsResult<FsFileSystemUninit>> {
|
|
142
|
-
for (let attempt = 1; attempt <= MAX_RETRY; attempt++) {
|
|
143
|
-
let error: FsError | undefined = undefined;
|
|
144
|
-
const { implementation } = fsGetSupportStatus();
|
|
145
|
-
// Prefer File System Access API since it supports writing
|
|
146
|
-
if ("getAsFileSystemHandle" in item && implementation === "FileSystemAccess") {
|
|
147
|
-
const handle = await tryAsync(() => getAsFileSystemHandle(item));
|
|
148
|
-
if (handle.val) {
|
|
149
|
-
return createFromFileSystemHandle(handle.val, write);
|
|
150
|
-
}
|
|
151
|
-
error = fsFail("Failed to get handle from DataTransferItem: " + errstr(handle.err));
|
|
152
|
-
} else if ("webkitGetAsEntry" in item && implementation === "FileEntry") {
|
|
153
|
-
const entry = tryCatch(() => webkitGetAsEntry(item));
|
|
154
|
-
if (entry.val) {
|
|
155
|
-
return createFromFileSystemEntry(entry.val);
|
|
156
|
-
}
|
|
157
|
-
error = fsFail("Failed to get entry from DataTransferItem: " + errstr(entry.err));
|
|
158
|
-
}
|
|
159
|
-
if (!error) {
|
|
160
|
-
const err = fsErr(FsErr.NotSupported, "No supported API found on the DataTransferItem");
|
|
161
|
-
return { err };
|
|
162
|
-
}
|
|
163
|
-
// handle error
|
|
164
|
-
if (retryHandler) {
|
|
165
|
-
const shouldRetry = await retryHandler(error, attempt);
|
|
166
|
-
if (shouldRetry.err) {
|
|
167
|
-
// retry handler failed
|
|
168
|
-
return shouldRetry;
|
|
169
|
-
}
|
|
170
|
-
if (!shouldRetry.val) {
|
|
171
|
-
// don't retry
|
|
172
|
-
return { err: error };
|
|
173
|
-
}
|
|
174
|
-
// fall through to retry
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return { err: fsFail("Max retry count reached") };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
async function init(
|
|
181
|
-
fs: FsFileSystemUninit,
|
|
182
|
-
retryHandler: FsOpenRetryHandler | undefined,
|
|
183
|
-
): Promise<FsResult<FsFileSystem>> {
|
|
184
|
-
let attempt = -1;
|
|
185
|
-
while (true) {
|
|
186
|
-
attempt++;
|
|
187
|
-
const inited = await fs.init();
|
|
188
|
-
if (!inited.err) {
|
|
189
|
-
return inited;
|
|
190
|
-
}
|
|
191
|
-
if (!retryHandler) {
|
|
192
|
-
return inited;
|
|
193
|
-
}
|
|
194
|
-
const shouldRetry = await retryHandler(inited.err, attempt);
|
|
195
|
-
if (shouldRetry.err) {
|
|
196
|
-
// retry handler failed
|
|
197
|
-
return shouldRetry;
|
|
198
|
-
}
|
|
199
|
-
if (!shouldRetry.val) {
|
|
200
|
-
// should not retry
|
|
201
|
-
return inited;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/** Wrapper for window.showDirectoryPicker */
|
|
207
|
-
function showDirectoryPicker(write: boolean): Promise<FileSystemHandle> {
|
|
208
|
-
// @ts-expect-error showDirectoryPicker is not in the TS lib
|
|
209
|
-
return globalThis.showDirectoryPicker({
|
|
210
|
-
mode: write ? "readwrite" : "read",
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Check if an error is an AbortError from Chromium
|
|
216
|
-
*
|
|
217
|
-
* @param e The error to check
|
|
218
|
-
*/
|
|
219
|
-
function isAbortError(e: unknown): boolean {
|
|
220
|
-
return !!e && typeof e === "object" && "name" in e && e.name === "AbortError";
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/** Wrapper for DataTransferItem.getAsFileSystemHandle */
|
|
224
|
-
async function getAsFileSystemHandle(item: DataTransferItem): Promise<FileSystemHandle> {
|
|
225
|
-
// @ts-expect-error getAsFileSystemHandle is not in the TS lib
|
|
226
|
-
const handle = await item.getAsFileSystemHandle();
|
|
227
|
-
if (!handle) {
|
|
228
|
-
throw new Error("handle is null");
|
|
229
|
-
}
|
|
230
|
-
return handle;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/** Wrapper for DataTransferItem.webkitGetAsEntry */
|
|
234
|
-
function webkitGetAsEntry(item: DataTransferItem): FileSystemEntry {
|
|
235
|
-
const entry = item.webkitGetAsEntry();
|
|
236
|
-
if (!entry) {
|
|
237
|
-
throw new Error("entry is null");
|
|
238
|
-
}
|
|
239
|
-
return entry;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function createFromFileSystemHandle(
|
|
243
|
-
handle: FileSystemHandle,
|
|
244
|
-
write: boolean,
|
|
245
|
-
): FsResult<FsFileSystemUninit> {
|
|
246
|
-
if (handle.kind !== "directory") {
|
|
247
|
-
const err = fsErr(FsErr.IsFile, "Expected directory");
|
|
248
|
-
return { err };
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const fs = new FsImplHandleAPI(handle.name, handle as FileSystemDirectoryHandle, write);
|
|
252
|
-
|
|
253
|
-
return { val: fs };
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function createFromFileSystemEntry(entry: FileSystemEntry): FsResult<FsFileSystemUninit> {
|
|
257
|
-
if (entry.isFile || !entry.isDirectory) {
|
|
258
|
-
const err = fsErr(FsErr.IsFile, "Expected directory");
|
|
259
|
-
return { err };
|
|
260
|
-
}
|
|
261
|
-
const fs = new FsImplEntryAPI(entry.name, entry as FileSystemDirectoryEntry);
|
|
262
|
-
return { val: fs };
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
function createFromFileList(files: FileList): FsResult<FsFileSystemUninit> {
|
|
266
|
-
if (!files.length) {
|
|
267
|
-
const err = fsFail("Expected at least one file");
|
|
268
|
-
return { err };
|
|
269
|
-
}
|
|
270
|
-
return { val: new FsImplFileAPI(files) };
|
|
271
|
-
}
|