@themartiancompany/opfs 1.8.11
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/COPYING +674 -0
- package/README.cn.md +301 -0
- package/README.md +241 -0
- package/dist/main.cjs +1840 -0
- package/dist/main.cjs.map +1 -0
- package/dist/main.mjs +1751 -0
- package/dist/main.mjs.map +1 -0
- package/dist/types.d.ts +920 -0
- package/dist/types.d.ts.map +1 -0
- package/docs/README.md +115 -0
- package/docs/classes/SyncMessenger.md +42 -0
- package/docs/functions/appendFile.md +29 -0
- package/docs/functions/appendFileSync.md +26 -0
- package/docs/functions/assertAbsolutePath.md +29 -0
- package/docs/functions/assertFileUrl.md +29 -0
- package/docs/functions/connectSyncAgent.md +25 -0
- package/docs/functions/copy.md +35 -0
- package/docs/functions/copySync.md +30 -0
- package/docs/functions/createFile.md +27 -0
- package/docs/functions/createFileSync.md +25 -0
- package/docs/functions/deleteTemp.md +23 -0
- package/docs/functions/deleteTempSync.md +19 -0
- package/docs/functions/downloadFile.md +58 -0
- package/docs/functions/emptyDir.md +28 -0
- package/docs/functions/emptyDirSync.md +25 -0
- package/docs/functions/exists.md +29 -0
- package/docs/functions/existsSync.md +26 -0
- package/docs/functions/generateTempPath.md +27 -0
- package/docs/functions/getFileDataByHandle.md +27 -0
- package/docs/functions/getSyncMessenger.md +22 -0
- package/docs/functions/isDirectoryHandle.md +27 -0
- package/docs/functions/isFileHandle.md +27 -0
- package/docs/functions/isFileHandleLike.md +27 -0
- package/docs/functions/isOPFSSupported.md +21 -0
- package/docs/functions/isTempPath.md +27 -0
- package/docs/functions/mkTemp.md +28 -0
- package/docs/functions/mkTempSync.md +25 -0
- package/docs/functions/mkdir.md +27 -0
- package/docs/functions/mkdirSync.md +25 -0
- package/docs/functions/move.md +34 -0
- package/docs/functions/moveSync.md +30 -0
- package/docs/functions/pruneTemp.md +28 -0
- package/docs/functions/pruneTempSync.md +25 -0
- package/docs/functions/readBlobFile.md +28 -0
- package/docs/functions/readBlobFileSync.md +25 -0
- package/docs/functions/readDir.md +28 -0
- package/docs/functions/readDirSync.md +26 -0
- package/docs/functions/readFile.md +132 -0
- package/docs/functions/readFileSync.md +70 -0
- package/docs/functions/readJsonFile.md +35 -0
- package/docs/functions/readJsonFileSync.md +31 -0
- package/docs/functions/readTextFile.md +28 -0
- package/docs/functions/readTextFileSync.md +25 -0
- package/docs/functions/remove.md +27 -0
- package/docs/functions/removeSync.md +25 -0
- package/docs/functions/setSyncMessenger.md +26 -0
- package/docs/functions/startSyncAgent.md +21 -0
- package/docs/functions/stat.md +27 -0
- package/docs/functions/statSync.md +25 -0
- package/docs/functions/toFileSystemHandleLike.md +27 -0
- package/docs/functions/unzip.md +32 -0
- package/docs/functions/unzipFromUrl.md +36 -0
- package/docs/functions/unzipSync.md +26 -0
- package/docs/functions/uploadFile.md +33 -0
- package/docs/functions/writeFile.md +32 -0
- package/docs/functions/writeFileSync.md +30 -0
- package/docs/functions/zip.md +65 -0
- package/docs/functions/zipFromUrl.md +63 -0
- package/docs/functions/zipSync.md +55 -0
- package/docs/interfaces/CopyOptions.md +17 -0
- package/docs/interfaces/DownloadFileTempResponse.md +18 -0
- package/docs/interfaces/ErrorLike.md +18 -0
- package/docs/interfaces/ExistsOptions.md +18 -0
- package/docs/interfaces/FileLike.md +21 -0
- package/docs/interfaces/FileSystemFileHandleLike.md +25 -0
- package/docs/interfaces/FileSystemHandleLike.md +22 -0
- package/docs/interfaces/MoveOptions.md +17 -0
- package/docs/interfaces/ReadDirEntry.md +18 -0
- package/docs/interfaces/ReadDirEntrySync.md +18 -0
- package/docs/interfaces/ReadDirOptions.md +17 -0
- package/docs/interfaces/ReadOptions.md +17 -0
- package/docs/interfaces/SyncAgentOptions.md +19 -0
- package/docs/interfaces/TempOptions.md +19 -0
- package/docs/interfaces/UploadRequestInit.md +21 -0
- package/docs/interfaces/WriteOptions.md +19 -0
- package/docs/interfaces/ZipOptions.md +17 -0
- package/docs/type-aliases/FileEncoding.md +15 -0
- package/docs/type-aliases/FsRequestInit.md +15 -0
- package/docs/type-aliases/ReadFileContent.md +15 -0
- package/docs/type-aliases/WriteFileContent.md +15 -0
- package/docs/type-aliases/WriteSyncFileContent.md +16 -0
- package/docs/variables/CURRENT_DIR.md +15 -0
- package/docs/variables/NOT_FOUND_ERROR.md +18 -0
- package/docs/variables/ROOT_DIR.md +15 -0
- package/docs/variables/TMP_DIR.md +15 -0
- package/package.json +141 -0
- package/src/fs/assertions.ts +63 -0
- package/src/fs/constants.ts +63 -0
- package/src/fs/defines.ts +352 -0
- package/src/fs/helpers.ts +338 -0
- package/src/fs/opfs_core.ts +413 -0
- package/src/fs/opfs_download.ts +174 -0
- package/src/fs/opfs_ext.ts +504 -0
- package/src/fs/opfs_tmp.ts +131 -0
- package/src/fs/opfs_unzip.ts +168 -0
- package/src/fs/opfs_upload.ts +126 -0
- package/src/fs/opfs_zip.ts +314 -0
- package/src/fs/support.ts +36 -0
- package/src/fs/utils.ts +176 -0
- package/src/mod.ts +41 -0
- package/src/worker/helpers.ts +168 -0
- package/src/worker/opfs_worker.ts +298 -0
- package/src/worker/opfs_worker_adapter.ts +666 -0
- package/src/worker/shared.ts +400 -0
package/src/fs/utils.ts
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
|
|
3
|
+
/** ----------------------------------------------------------------------
|
|
4
|
+
* Copyright ©
|
|
5
|
+
* Jiang Jie
|
|
6
|
+
* 2024, 2025
|
|
7
|
+
* Pellegrino Prevete
|
|
8
|
+
* 2025
|
|
9
|
+
*
|
|
10
|
+
* All rights reserved
|
|
11
|
+
* ----------------------------------------------------------------------
|
|
12
|
+
*
|
|
13
|
+
* This program is free software: you can redistribute it and/or modify
|
|
14
|
+
* it under the terms of the GNU General Public License as published by
|
|
15
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
16
|
+
* (at your option) any later version.
|
|
17
|
+
*
|
|
18
|
+
* This program is distributed in the hope that it will be useful,
|
|
19
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
21
|
+
* GNU General Public License for more details.
|
|
22
|
+
*
|
|
23
|
+
* You should have received a copy of the GNU General Public License
|
|
24
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { join,
|
|
28
|
+
SEPARATOR } from '@std/path/posix';
|
|
29
|
+
import { TMP_DIR } from './constants.ts';
|
|
30
|
+
import type { FileSystemFileHandleLike,
|
|
31
|
+
FileSystemHandleLike,
|
|
32
|
+
TempOptions } from './defines.ts';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Generate a temporary path but not create it.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Options and flags.
|
|
38
|
+
* @returns The temporary path.
|
|
39
|
+
*/
|
|
40
|
+
export function
|
|
41
|
+
generateTempPath(
|
|
42
|
+
options?:
|
|
43
|
+
TempOptions):
|
|
44
|
+
string {
|
|
45
|
+
const
|
|
46
|
+
{ isDirectory = false,
|
|
47
|
+
basename = 'tmp',
|
|
48
|
+
extname = '' } = options ?? {};
|
|
49
|
+
const
|
|
50
|
+
base =
|
|
51
|
+
basename ? `${ basename }-` : '';
|
|
52
|
+
const
|
|
53
|
+
ext =
|
|
54
|
+
isDirectory ? '' : extname;
|
|
55
|
+
// use uuid to generate a unique name
|
|
56
|
+
return join(
|
|
57
|
+
TMP_DIR,
|
|
58
|
+
`${ base }${ crypto.randomUUID() }${ ext }`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Check whether the path is a temporary path.
|
|
63
|
+
* @param path - The path to check.
|
|
64
|
+
* @returns `true` if the path is a temporary path otherwise `false`.
|
|
65
|
+
*/
|
|
66
|
+
export function
|
|
67
|
+
isTempPath(
|
|
68
|
+
path:
|
|
69
|
+
string):
|
|
70
|
+
boolean {
|
|
71
|
+
return path.startsWith(
|
|
72
|
+
`${ TMP_DIR }${ SEPARATOR }`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Serialize a `FileSystemHandle` to plain object.
|
|
77
|
+
* @param handle - `FileSystemHandle` object.
|
|
78
|
+
* @returns Serializable version of FileSystemHandle that is FileSystemHandleLike.
|
|
79
|
+
*/
|
|
80
|
+
export async function
|
|
81
|
+
toFileSystemHandleLike(
|
|
82
|
+
handle:
|
|
83
|
+
FileSystemHandle):
|
|
84
|
+
Promise<FileSystemHandleLike> {
|
|
85
|
+
const
|
|
86
|
+
{ name,
|
|
87
|
+
kind } =
|
|
88
|
+
handle;
|
|
89
|
+
if ( isFileHandle(
|
|
90
|
+
handle) ) {
|
|
91
|
+
const
|
|
92
|
+
file =
|
|
93
|
+
await handle.getFile();
|
|
94
|
+
const
|
|
95
|
+
{ size,
|
|
96
|
+
lastModified,
|
|
97
|
+
type } =
|
|
98
|
+
file;
|
|
99
|
+
const
|
|
100
|
+
fileHandle:
|
|
101
|
+
FileSystemFileHandleLike = {
|
|
102
|
+
name,
|
|
103
|
+
kind,
|
|
104
|
+
type,
|
|
105
|
+
size,
|
|
106
|
+
lastModified,
|
|
107
|
+
};
|
|
108
|
+
return fileHandle;
|
|
109
|
+
}
|
|
110
|
+
const
|
|
111
|
+
handleLike:
|
|
112
|
+
FileSystemHandleLike= {
|
|
113
|
+
name,
|
|
114
|
+
kind,
|
|
115
|
+
};
|
|
116
|
+
return handleLike;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Whether the handle is a file.
|
|
121
|
+
* @param handle - The handle which is a FileSystemHandle.
|
|
122
|
+
* @returns `true` if the handle is a file, otherwise `false`.
|
|
123
|
+
*/
|
|
124
|
+
export function
|
|
125
|
+
isFileHandle(
|
|
126
|
+
handle:
|
|
127
|
+
FileSystemHandle):
|
|
128
|
+
handle is FileSystemFileHandle {
|
|
129
|
+
return handle.kind === 'file';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Whether the handle is a directory.
|
|
134
|
+
* @param handle - The handle which is a FileSystemHandle.
|
|
135
|
+
* @returns `true` if the handle is a directory, otherwise `false`.
|
|
136
|
+
*/
|
|
137
|
+
export function
|
|
138
|
+
isDirectoryHandle(
|
|
139
|
+
handle:
|
|
140
|
+
FileSystemHandle):
|
|
141
|
+
handle is FileSystemDirectoryHandle {
|
|
142
|
+
return handle.kind === 'directory';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Whether the handle is a file-like.
|
|
147
|
+
* @param handle - The handle which is a FileSystemHandleLike.
|
|
148
|
+
* @returns `true` if the handle is a file, otherwise `false`.
|
|
149
|
+
*/
|
|
150
|
+
export function
|
|
151
|
+
isFileHandleLike(
|
|
152
|
+
handle:
|
|
153
|
+
FileSystemHandleLike):
|
|
154
|
+
handle is FileSystemFileHandleLike {
|
|
155
|
+
return handle.kind === 'file';
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Gets the data of a file handle.
|
|
160
|
+
* @param handle - The file handle.
|
|
161
|
+
* @returns A promise that resolves to the data of the file.
|
|
162
|
+
*/
|
|
163
|
+
export async function
|
|
164
|
+
getFileDataByHandle(
|
|
165
|
+
handle:
|
|
166
|
+
FileSystemFileHandle):
|
|
167
|
+
Promise<Uint8Array> {
|
|
168
|
+
const
|
|
169
|
+
file =
|
|
170
|
+
await handle.getFile();
|
|
171
|
+
const
|
|
172
|
+
ab =
|
|
173
|
+
await file.arrayBuffer();
|
|
174
|
+
return new Uint8Array(
|
|
175
|
+
ab);
|
|
176
|
+
}
|
package/src/mod.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
|
|
3
|
+
/** ----------------------------------------------------------------------
|
|
4
|
+
* Copyright ©
|
|
5
|
+
* Jiang Jie
|
|
6
|
+
* 2024, 2025
|
|
7
|
+
* Pellegrino Prevete
|
|
8
|
+
* 2025
|
|
9
|
+
*
|
|
10
|
+
* All rights reserved
|
|
11
|
+
* ----------------------------------------------------------------------
|
|
12
|
+
*
|
|
13
|
+
* This program is free software: you can redistribute it and/or modify
|
|
14
|
+
* it under the terms of the GNU General Public License as published by
|
|
15
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
16
|
+
* (at your option) any later version.
|
|
17
|
+
*
|
|
18
|
+
* This program is distributed in the hope that it will be useful,
|
|
19
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
21
|
+
* GNU General Public License for more details.
|
|
22
|
+
*
|
|
23
|
+
* You should have received a copy of the GNU General Public License
|
|
24
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export * from './fs/assertions.ts';
|
|
28
|
+
export * from './fs/constants.ts';
|
|
29
|
+
export * from './fs/defines.ts';
|
|
30
|
+
export * from './fs/opfs_core.ts';
|
|
31
|
+
export * from './fs/opfs_download.ts';
|
|
32
|
+
export * from './fs/opfs_ext.ts';
|
|
33
|
+
export * from './fs/opfs_tmp.ts';
|
|
34
|
+
export * from './fs/opfs_unzip.ts';
|
|
35
|
+
export * from './fs/opfs_upload.ts';
|
|
36
|
+
export * from './fs/opfs_zip.ts';
|
|
37
|
+
export * from './fs/support.ts';
|
|
38
|
+
export * from './fs/utils.ts';
|
|
39
|
+
export * from './worker/opfs_worker.ts';
|
|
40
|
+
export * from './worker/opfs_worker_adapter.ts';
|
|
41
|
+
export type { SyncMessenger } from './worker/shared.ts';
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
|
|
3
|
+
/** ----------------------------------------------------------------------
|
|
4
|
+
* Copyright ©
|
|
5
|
+
* Jiang Jie
|
|
6
|
+
* 2024, 2025
|
|
7
|
+
* Pellegrino Prevete
|
|
8
|
+
* 2025
|
|
9
|
+
*
|
|
10
|
+
* All rights reserved
|
|
11
|
+
* ----------------------------------------------------------------------
|
|
12
|
+
*
|
|
13
|
+
* This program is free software: you can redistribute it and/or modify
|
|
14
|
+
* it under the terms of the GNU General Public License as published by
|
|
15
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
16
|
+
* (at your option) any later version.
|
|
17
|
+
*
|
|
18
|
+
* This program is distributed in the hope that it will be useful,
|
|
19
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
21
|
+
* GNU General Public License for more details.
|
|
22
|
+
*
|
|
23
|
+
* You should have received a copy of the GNU General Public License
|
|
24
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { TIMEOUT_ERROR } from '../fs/constants.ts';
|
|
28
|
+
import type { ErrorLike,
|
|
29
|
+
FileLike } from '../fs/defines.ts';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Serialize an `Error` to plain object.
|
|
33
|
+
* @param error - `Error` object.
|
|
34
|
+
* @returns Serializable version of Error.
|
|
35
|
+
*/
|
|
36
|
+
export
|
|
37
|
+
function
|
|
38
|
+
serializeError(
|
|
39
|
+
error:
|
|
40
|
+
Error |
|
|
41
|
+
null):
|
|
42
|
+
ErrorLike |
|
|
43
|
+
null {
|
|
44
|
+
return error ?
|
|
45
|
+
{ name:
|
|
46
|
+
error.name,
|
|
47
|
+
message:
|
|
48
|
+
error.message } :
|
|
49
|
+
error;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Deserialize an `Error` from plain object.
|
|
54
|
+
* @param error - Serializable version of Error.
|
|
55
|
+
* @returns `Error` object.
|
|
56
|
+
*/
|
|
57
|
+
export
|
|
58
|
+
function
|
|
59
|
+
deserializeError(
|
|
60
|
+
error:
|
|
61
|
+
ErrorLike):
|
|
62
|
+
Error {
|
|
63
|
+
const
|
|
64
|
+
err =
|
|
65
|
+
new Error(
|
|
66
|
+
error.message);
|
|
67
|
+
err.name =
|
|
68
|
+
error.name;
|
|
69
|
+
return err;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Serialize a `File` to plain object.
|
|
74
|
+
* @param file - `File` object.
|
|
75
|
+
* @returns Serializable version of File.
|
|
76
|
+
*/
|
|
77
|
+
export
|
|
78
|
+
async function
|
|
79
|
+
serializeFile(
|
|
80
|
+
file:
|
|
81
|
+
File):
|
|
82
|
+
Promise<FileLike> {
|
|
83
|
+
const
|
|
84
|
+
ab =
|
|
85
|
+
await file.arrayBuffer();
|
|
86
|
+
return {
|
|
87
|
+
name:
|
|
88
|
+
file.name,
|
|
89
|
+
type:
|
|
90
|
+
file.type,
|
|
91
|
+
lastModified:
|
|
92
|
+
file.lastModified,
|
|
93
|
+
size:
|
|
94
|
+
ab.byteLength,
|
|
95
|
+
data:
|
|
96
|
+
ab,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Deserialize a `File` from plain object.
|
|
102
|
+
* @param file - Serializable version of File.
|
|
103
|
+
* @returns `File` object.
|
|
104
|
+
*/
|
|
105
|
+
export
|
|
106
|
+
function
|
|
107
|
+
deserializeFile(
|
|
108
|
+
file:
|
|
109
|
+
FileLike):
|
|
110
|
+
File {
|
|
111
|
+
const
|
|
112
|
+
blob =
|
|
113
|
+
new Blob(
|
|
114
|
+
[ file.data ]);
|
|
115
|
+
return new File(
|
|
116
|
+
[ blob ],
|
|
117
|
+
file.name,
|
|
118
|
+
{ type:
|
|
119
|
+
file.type,
|
|
120
|
+
lastModified:
|
|
121
|
+
file.lastModified });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Global timeout of per sync I/O operation.
|
|
126
|
+
*/
|
|
127
|
+
let
|
|
128
|
+
globalOpTimeout =
|
|
129
|
+
1000;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Set global timeout of per sync I/O operation.
|
|
133
|
+
* @param timeout - Timeout in milliseconds.
|
|
134
|
+
*/
|
|
135
|
+
export
|
|
136
|
+
function
|
|
137
|
+
setGlobalOpTimeout(
|
|
138
|
+
timeout:
|
|
139
|
+
number):
|
|
140
|
+
void {
|
|
141
|
+
globalOpTimeout =
|
|
142
|
+
timeout;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Sleep until a condition is met.
|
|
147
|
+
* @param condition - Condition to be met.
|
|
148
|
+
*/
|
|
149
|
+
export
|
|
150
|
+
function
|
|
151
|
+
sleepUntil(
|
|
152
|
+
condition:
|
|
153
|
+
() => boolean) {
|
|
154
|
+
const
|
|
155
|
+
start =
|
|
156
|
+
Date.now();
|
|
157
|
+
while ( !condition() ) {
|
|
158
|
+
if ( Date.now() - start > globalOpTimeout ) {
|
|
159
|
+
const
|
|
160
|
+
error =
|
|
161
|
+
new Error(
|
|
162
|
+
'Operating Timeout');
|
|
163
|
+
error.name =
|
|
164
|
+
TIMEOUT_ERROR;
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
|
|
3
|
+
/** ----------------------------------------------------------------------
|
|
4
|
+
* Copyright ©
|
|
5
|
+
* Jiang Jie
|
|
6
|
+
* 2024, 2025
|
|
7
|
+
* Pellegrino Prevete
|
|
8
|
+
* 2025
|
|
9
|
+
*
|
|
10
|
+
* All rights reserved
|
|
11
|
+
* ----------------------------------------------------------------------
|
|
12
|
+
*
|
|
13
|
+
* This program is free software: you can redistribute it and/or modify
|
|
14
|
+
* it under the terms of the GNU General Public License as published by
|
|
15
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
16
|
+
* (at your option) any later version.
|
|
17
|
+
*
|
|
18
|
+
* This program is distributed in the hope that it will be useful,
|
|
19
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
21
|
+
* GNU General Public License for more details.
|
|
22
|
+
*
|
|
23
|
+
* You should have received a copy of the GNU General Public License
|
|
24
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import type { IOResult } from 'happy-rusty';
|
|
28
|
+
import type { ReadDirEntry,
|
|
29
|
+
ReadDirEntrySync } from '../fs/defines.ts';
|
|
30
|
+
import { createFile,
|
|
31
|
+
mkdir,
|
|
32
|
+
readDir,
|
|
33
|
+
remove,
|
|
34
|
+
stat,
|
|
35
|
+
writeFile } from '../fs/opfs_core.ts';
|
|
36
|
+
import { appendFile,
|
|
37
|
+
copy,
|
|
38
|
+
emptyDir,
|
|
39
|
+
exists,
|
|
40
|
+
move,
|
|
41
|
+
readBlobFile } from '../fs/opfs_ext.ts';
|
|
42
|
+
import { deleteTemp,
|
|
43
|
+
mkTemp,
|
|
44
|
+
pruneTemp } from '../fs/opfs_tmp.ts';
|
|
45
|
+
import { unzip } from '../fs/opfs_unzip.ts';
|
|
46
|
+
import { zip } from '../fs/opfs_zip.ts';
|
|
47
|
+
import { toFileSystemHandleLike } from '../fs/utils.ts';
|
|
48
|
+
import { serializeError,
|
|
49
|
+
serializeFile } from './helpers.ts';
|
|
50
|
+
import { decodeFromBuffer,
|
|
51
|
+
encodeToBuffer,
|
|
52
|
+
respondToMainFromWorker,
|
|
53
|
+
SyncMessenger,
|
|
54
|
+
WorkerAsyncOp } from './shared.ts';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Async I/O operations which allow to call from main thread.
|
|
58
|
+
*/
|
|
59
|
+
const
|
|
60
|
+
asyncOps = {
|
|
61
|
+
[ WorkerAsyncOp.createFile ]:
|
|
62
|
+
createFile,
|
|
63
|
+
[ WorkerAsyncOp.mkdir ]:
|
|
64
|
+
mkdir,
|
|
65
|
+
[ WorkerAsyncOp.move ]:
|
|
66
|
+
move,
|
|
67
|
+
[ WorkerAsyncOp.readDir ]:
|
|
68
|
+
readDir,
|
|
69
|
+
[ WorkerAsyncOp.remove ]:
|
|
70
|
+
remove,
|
|
71
|
+
[ WorkerAsyncOp.stat ]:
|
|
72
|
+
stat,
|
|
73
|
+
[ WorkerAsyncOp.writeFile ]:
|
|
74
|
+
writeFile,
|
|
75
|
+
[ WorkerAsyncOp.appendFile ]:
|
|
76
|
+
appendFile,
|
|
77
|
+
[ WorkerAsyncOp.copy ]:
|
|
78
|
+
copy,
|
|
79
|
+
[ WorkerAsyncOp.emptyDir ]:
|
|
80
|
+
emptyDir,
|
|
81
|
+
[ WorkerAsyncOp.exists ]:
|
|
82
|
+
exists,
|
|
83
|
+
[ WorkerAsyncOp.deleteTemp ]:
|
|
84
|
+
deleteTemp,
|
|
85
|
+
[ WorkerAsyncOp.mkTemp ]:
|
|
86
|
+
mkTemp,
|
|
87
|
+
[ WorkerAsyncOp.pruneTemp ]:
|
|
88
|
+
pruneTemp,
|
|
89
|
+
[ WorkerAsyncOp.readBlobFile ]:
|
|
90
|
+
readBlobFile,
|
|
91
|
+
[ WorkerAsyncOp.unzip ]:
|
|
92
|
+
unzip,
|
|
93
|
+
[ WorkerAsyncOp.zip ]:
|
|
94
|
+
zip,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Cache the messenger instance.
|
|
99
|
+
*/
|
|
100
|
+
let
|
|
101
|
+
messenger:
|
|
102
|
+
SyncMessenger;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Start worker agent.
|
|
106
|
+
* Listens to postMessage from main thread.
|
|
107
|
+
* Start runner loop.
|
|
108
|
+
*/
|
|
109
|
+
export
|
|
110
|
+
function
|
|
111
|
+
startSyncAgent() {
|
|
112
|
+
if ( typeof window !== 'undefined' ) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
'Only can use in worker');
|
|
115
|
+
}
|
|
116
|
+
if ( messenger ) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
'Worker messenger already started');
|
|
119
|
+
}
|
|
120
|
+
addEventListener(
|
|
121
|
+
'message',
|
|
122
|
+
(event:
|
|
123
|
+
MessageEvent<SharedArrayBuffer>) => {
|
|
124
|
+
// created at main thread and transfer to worker
|
|
125
|
+
const
|
|
126
|
+
sab =
|
|
127
|
+
event.data;
|
|
128
|
+
|
|
129
|
+
if ( ! (sab instanceof SharedArrayBuffer) ) {
|
|
130
|
+
throw new TypeError(
|
|
131
|
+
'Only can post SharedArrayBuffer to Worker');
|
|
132
|
+
}
|
|
133
|
+
messenger =
|
|
134
|
+
new SyncMessenger(sab);
|
|
135
|
+
// notify main thread that worker is ready
|
|
136
|
+
postMessage(
|
|
137
|
+
true);
|
|
138
|
+
// start waiting for request
|
|
139
|
+
runWorkerLoop();
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Run worker loop.
|
|
145
|
+
*/
|
|
146
|
+
async function
|
|
147
|
+
runWorkerLoop():
|
|
148
|
+
Promise<void> {
|
|
149
|
+
// loop forever
|
|
150
|
+
while ( true ) {
|
|
151
|
+
try {
|
|
152
|
+
await respondToMainFromWorker(
|
|
153
|
+
messenger,
|
|
154
|
+
async (data) => {
|
|
155
|
+
const
|
|
156
|
+
[op, ...args] =
|
|
157
|
+
decodeFromBuffer(
|
|
158
|
+
data) as [ WorkerAsyncOp,
|
|
159
|
+
...Parameters<typeof asyncOps[
|
|
160
|
+
WorkerAsyncOp]> ];
|
|
161
|
+
// handling unequal parameters for serialization and deserialization
|
|
162
|
+
if ( op === WorkerAsyncOp.writeFile ||
|
|
163
|
+
op === WorkerAsyncOp.appendFile) {
|
|
164
|
+
// actually is an byte array
|
|
165
|
+
if ( Array.isArray(
|
|
166
|
+
args[
|
|
167
|
+
1]) ) {
|
|
168
|
+
args[
|
|
169
|
+
1] =
|
|
170
|
+
new Uint8Array(
|
|
171
|
+
args[1]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else if ( op === WorkerAsyncOp.pruneTemp ) {
|
|
175
|
+
// actually is a Date string
|
|
176
|
+
args[
|
|
177
|
+
0] =
|
|
178
|
+
new Date(
|
|
179
|
+
args[
|
|
180
|
+
0] as Date);
|
|
181
|
+
}
|
|
182
|
+
let
|
|
183
|
+
response:
|
|
184
|
+
Uint8Array;
|
|
185
|
+
const
|
|
186
|
+
handle =
|
|
187
|
+
asyncOps[
|
|
188
|
+
op];
|
|
189
|
+
try {
|
|
190
|
+
// The linter shows not to work well here
|
|
191
|
+
// as it cant disable a block of lines.
|
|
192
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
193
|
+
const res: IOResult<any> = await ( handle as any )(
|
|
194
|
+
...args);
|
|
195
|
+
if ( res.isErr() ) {
|
|
196
|
+
// without result success
|
|
197
|
+
response =
|
|
198
|
+
encodeToBuffer(
|
|
199
|
+
[ serializeError(
|
|
200
|
+
res.unwrapErr()) ]);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
// manually serialize response
|
|
204
|
+
let
|
|
205
|
+
rawResponse;
|
|
206
|
+
if ( op === WorkerAsyncOp.readBlobFile ) {
|
|
207
|
+
const
|
|
208
|
+
file:
|
|
209
|
+
File =
|
|
210
|
+
res.unwrap();
|
|
211
|
+
const
|
|
212
|
+
fileLike =
|
|
213
|
+
await serializeFile(
|
|
214
|
+
file);
|
|
215
|
+
rawResponse =
|
|
216
|
+
{ ...fileLike,
|
|
217
|
+
// for serialize
|
|
218
|
+
data:
|
|
219
|
+
[ ...new Uint8Array(
|
|
220
|
+
fileLike.data ) ] };
|
|
221
|
+
}
|
|
222
|
+
else if ( op === WorkerAsyncOp.readDir ) {
|
|
223
|
+
const
|
|
224
|
+
iterator:
|
|
225
|
+
AsyncIterableIterator<ReadDirEntry> =
|
|
226
|
+
res.unwrap();
|
|
227
|
+
const
|
|
228
|
+
entries:
|
|
229
|
+
ReadDirEntrySync[] =
|
|
230
|
+
[];
|
|
231
|
+
for await ( const { path,
|
|
232
|
+
handle } of iterator) {
|
|
233
|
+
const
|
|
234
|
+
handleLike =
|
|
235
|
+
await toFileSystemHandleLike(
|
|
236
|
+
handle);
|
|
237
|
+
entries.push(
|
|
238
|
+
{ path,
|
|
239
|
+
handle:
|
|
240
|
+
handleLike });
|
|
241
|
+
}
|
|
242
|
+
rawResponse =
|
|
243
|
+
entries;
|
|
244
|
+
}
|
|
245
|
+
else if ( op === WorkerAsyncOp.stat ) {
|
|
246
|
+
const
|
|
247
|
+
handle:
|
|
248
|
+
FileSystemHandle =
|
|
249
|
+
res.unwrap();
|
|
250
|
+
const
|
|
251
|
+
data =
|
|
252
|
+
await toFileSystemHandleLike(
|
|
253
|
+
handle);
|
|
254
|
+
rawResponse =
|
|
255
|
+
data;
|
|
256
|
+
}
|
|
257
|
+
else if ( op === WorkerAsyncOp.zip ) {
|
|
258
|
+
const
|
|
259
|
+
data:
|
|
260
|
+
Uint8Array |
|
|
261
|
+
undefined =
|
|
262
|
+
res.unwrap();
|
|
263
|
+
rawResponse =
|
|
264
|
+
data instanceof Uint8Array ?
|
|
265
|
+
[ ...data ] :
|
|
266
|
+
data;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// others are all boolean
|
|
270
|
+
rawResponse =
|
|
271
|
+
res.unwrap();
|
|
272
|
+
}
|
|
273
|
+
// without error
|
|
274
|
+
response =
|
|
275
|
+
encodeToBuffer(
|
|
276
|
+
[ null,
|
|
277
|
+
rawResponse ]);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch (
|
|
281
|
+
_error) {
|
|
282
|
+
response =
|
|
283
|
+
encodeToBuffer(
|
|
284
|
+
[ serializeError(
|
|
285
|
+
_error as Error) ]);
|
|
286
|
+
}
|
|
287
|
+
return response;
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
catch (
|
|
291
|
+
_error) {
|
|
292
|
+
console.error(
|
|
293
|
+
_error instanceof Error ?
|
|
294
|
+
_error.stack :
|
|
295
|
+
_error);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|