@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/dist/main.cjs
ADDED
|
@@ -0,0 +1,1840 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var invariant = require('tiny-invariant');
|
|
4
|
+
var posix = require('@std/path/posix');
|
|
5
|
+
var happyRusty = require('happy-rusty');
|
|
6
|
+
var fetchT = require('@happy-ts/fetch-t');
|
|
7
|
+
var fflate = require('fflate/browser');
|
|
8
|
+
var tinyFuture = require('tiny-future');
|
|
9
|
+
|
|
10
|
+
function _interopNamespaceDefault(e) {
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var fflate__namespace = /*#__PURE__*/_interopNamespaceDefault(fflate);
|
|
28
|
+
|
|
29
|
+
const NOT_FOUND_ERROR = "NotFoundError";
|
|
30
|
+
const ROOT_DIR = "/";
|
|
31
|
+
const CURRENT_DIR = ".";
|
|
32
|
+
const TMP_DIR = "/tmp";
|
|
33
|
+
|
|
34
|
+
function assertAbsolutePath(path) {
|
|
35
|
+
invariant(
|
|
36
|
+
typeof path === "string",
|
|
37
|
+
() => `Path must be a string but received ${path}`
|
|
38
|
+
);
|
|
39
|
+
invariant(
|
|
40
|
+
path[0] === ROOT_DIR,
|
|
41
|
+
() => `Path must start with / but received ${path}`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
function assertFileUrl(fileUrl) {
|
|
45
|
+
invariant(
|
|
46
|
+
typeof fileUrl === "string",
|
|
47
|
+
() => `File url must be a string but received ${fileUrl}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let fsRoot;
|
|
52
|
+
async function getFsRoot() {
|
|
53
|
+
fsRoot ??= await navigator.storage.getDirectory();
|
|
54
|
+
return fsRoot;
|
|
55
|
+
}
|
|
56
|
+
function isRootPath(path) {
|
|
57
|
+
return path === ROOT_DIR;
|
|
58
|
+
}
|
|
59
|
+
async function getChildDirHandle(dirHandle, dirName, options) {
|
|
60
|
+
try {
|
|
61
|
+
const handle = await dirHandle.getDirectoryHandle(
|
|
62
|
+
dirName,
|
|
63
|
+
options
|
|
64
|
+
);
|
|
65
|
+
return happyRusty.Ok(
|
|
66
|
+
handle
|
|
67
|
+
);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
const err = e;
|
|
70
|
+
const error = new Error(
|
|
71
|
+
`${err.name}: ${err.message} When get child directory '${dirName}' from directory '${dirHandle.name || ROOT_DIR}'.`
|
|
72
|
+
);
|
|
73
|
+
error.name = err.name;
|
|
74
|
+
return happyRusty.Err(
|
|
75
|
+
error
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function getChildFileHandle(dirHandle, fileName, options) {
|
|
80
|
+
try {
|
|
81
|
+
const handle = await dirHandle.getFileHandle(
|
|
82
|
+
fileName,
|
|
83
|
+
options
|
|
84
|
+
);
|
|
85
|
+
return happyRusty.Ok(handle);
|
|
86
|
+
} catch (e) {
|
|
87
|
+
const err = e;
|
|
88
|
+
const error = new Error(
|
|
89
|
+
`${err.name}: ${err.message} When get child file '${fileName}' from directory '${dirHandle.name || ROOT_DIR}'.`
|
|
90
|
+
);
|
|
91
|
+
error.name = err.name;
|
|
92
|
+
return happyRusty.Err(
|
|
93
|
+
error
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function getDirHandle(dirPath, options) {
|
|
98
|
+
let dirHandle = await getFsRoot();
|
|
99
|
+
if (isRootPath(
|
|
100
|
+
dirPath
|
|
101
|
+
)) {
|
|
102
|
+
return happyRusty.Ok(
|
|
103
|
+
dirHandle
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
let childDirPath = dirPath.slice(
|
|
107
|
+
1
|
|
108
|
+
);
|
|
109
|
+
while (childDirPath) {
|
|
110
|
+
let dirName = "";
|
|
111
|
+
const index = childDirPath.indexOf(
|
|
112
|
+
posix.SEPARATOR
|
|
113
|
+
);
|
|
114
|
+
if (index === -1) {
|
|
115
|
+
dirName = childDirPath;
|
|
116
|
+
childDirPath = "";
|
|
117
|
+
} else {
|
|
118
|
+
dirName = childDirPath.slice(
|
|
119
|
+
0,
|
|
120
|
+
index
|
|
121
|
+
);
|
|
122
|
+
childDirPath = childDirPath.slice(
|
|
123
|
+
index + 1
|
|
124
|
+
);
|
|
125
|
+
if (index === 0) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const dirHandleRes = await getChildDirHandle(
|
|
130
|
+
dirHandle,
|
|
131
|
+
dirName,
|
|
132
|
+
options
|
|
133
|
+
);
|
|
134
|
+
if (dirHandleRes.isErr()) {
|
|
135
|
+
return dirHandleRes;
|
|
136
|
+
}
|
|
137
|
+
dirHandle = dirHandleRes.unwrap();
|
|
138
|
+
}
|
|
139
|
+
return happyRusty.Ok(
|
|
140
|
+
dirHandle
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
async function getFileHandle(filePath, options) {
|
|
144
|
+
const isCreate = options?.create ?? false;
|
|
145
|
+
const dirPath = posix.dirname(
|
|
146
|
+
filePath
|
|
147
|
+
);
|
|
148
|
+
const fileName = posix.basename(
|
|
149
|
+
filePath
|
|
150
|
+
);
|
|
151
|
+
const dirHandleRes = await getDirHandle(
|
|
152
|
+
dirPath,
|
|
153
|
+
{
|
|
154
|
+
create: isCreate
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
return dirHandleRes.andThenAsync(
|
|
158
|
+
(dirHandle) => {
|
|
159
|
+
return getChildFileHandle(
|
|
160
|
+
dirHandle,
|
|
161
|
+
fileName,
|
|
162
|
+
{ create: isCreate }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
function isNotFoundError(err) {
|
|
168
|
+
return err.name === NOT_FOUND_ERROR;
|
|
169
|
+
}
|
|
170
|
+
async function getFinalResult(tasks) {
|
|
171
|
+
const allRes = await Promise.all(
|
|
172
|
+
tasks
|
|
173
|
+
);
|
|
174
|
+
const fail = allRes.find(
|
|
175
|
+
(x) => x.isErr()
|
|
176
|
+
);
|
|
177
|
+
return fail ?? happyRusty.RESULT_VOID;
|
|
178
|
+
}
|
|
179
|
+
function createAbortError() {
|
|
180
|
+
const error = new Error();
|
|
181
|
+
error.name = fetchT.ABORT_ERROR;
|
|
182
|
+
return error;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function generateTempPath(options) {
|
|
186
|
+
const {
|
|
187
|
+
isDirectory = false,
|
|
188
|
+
basename = "tmp",
|
|
189
|
+
extname = ""
|
|
190
|
+
} = options ?? {};
|
|
191
|
+
const base = basename ? `${basename}-` : "";
|
|
192
|
+
const ext = isDirectory ? "" : extname;
|
|
193
|
+
return posix.join(
|
|
194
|
+
TMP_DIR,
|
|
195
|
+
`${base}${crypto.randomUUID()}${ext}`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
function isTempPath(path) {
|
|
199
|
+
return path.startsWith(
|
|
200
|
+
`${TMP_DIR}${posix.SEPARATOR}`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
async function toFileSystemHandleLike(handle) {
|
|
204
|
+
const {
|
|
205
|
+
name,
|
|
206
|
+
kind
|
|
207
|
+
} = handle;
|
|
208
|
+
if (isFileHandle(
|
|
209
|
+
handle
|
|
210
|
+
)) {
|
|
211
|
+
const file = await handle.getFile();
|
|
212
|
+
const {
|
|
213
|
+
size,
|
|
214
|
+
lastModified,
|
|
215
|
+
type
|
|
216
|
+
} = file;
|
|
217
|
+
const fileHandle = {
|
|
218
|
+
name,
|
|
219
|
+
kind,
|
|
220
|
+
type,
|
|
221
|
+
size,
|
|
222
|
+
lastModified
|
|
223
|
+
};
|
|
224
|
+
return fileHandle;
|
|
225
|
+
}
|
|
226
|
+
const handleLike = {
|
|
227
|
+
name,
|
|
228
|
+
kind
|
|
229
|
+
};
|
|
230
|
+
return handleLike;
|
|
231
|
+
}
|
|
232
|
+
function isFileHandle(handle) {
|
|
233
|
+
return handle.kind === "file";
|
|
234
|
+
}
|
|
235
|
+
function isDirectoryHandle(handle) {
|
|
236
|
+
return handle.kind === "directory";
|
|
237
|
+
}
|
|
238
|
+
function isFileHandleLike(handle) {
|
|
239
|
+
return handle.kind === "file";
|
|
240
|
+
}
|
|
241
|
+
async function getFileDataByHandle(handle) {
|
|
242
|
+
const file = await handle.getFile();
|
|
243
|
+
const ab = await file.arrayBuffer();
|
|
244
|
+
return new Uint8Array(
|
|
245
|
+
ab
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async function createFile(filePath) {
|
|
250
|
+
assertAbsolutePath(
|
|
251
|
+
filePath
|
|
252
|
+
);
|
|
253
|
+
const fileHandleRes = await getFileHandle(
|
|
254
|
+
filePath,
|
|
255
|
+
{ create: true }
|
|
256
|
+
);
|
|
257
|
+
return fileHandleRes.and(
|
|
258
|
+
happyRusty.RESULT_VOID
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
async function mkdir(dirPath) {
|
|
262
|
+
assertAbsolutePath(
|
|
263
|
+
dirPath
|
|
264
|
+
);
|
|
265
|
+
const dirHandleRes = await getDirHandle(
|
|
266
|
+
dirPath,
|
|
267
|
+
{
|
|
268
|
+
create: true
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
return dirHandleRes.and(
|
|
272
|
+
happyRusty.RESULT_VOID
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
async function readDir(dirPath, options) {
|
|
276
|
+
assertAbsolutePath(
|
|
277
|
+
dirPath
|
|
278
|
+
);
|
|
279
|
+
const dirHandleRes = await getDirHandle(
|
|
280
|
+
dirPath
|
|
281
|
+
);
|
|
282
|
+
async function* read(dirHandle, subDirPath) {
|
|
283
|
+
const entries = dirHandle.entries();
|
|
284
|
+
for await (const [
|
|
285
|
+
name,
|
|
286
|
+
handle
|
|
287
|
+
] of entries) {
|
|
288
|
+
const path = subDirPath === dirPath ? name : posix.join(
|
|
289
|
+
subDirPath,
|
|
290
|
+
name
|
|
291
|
+
);
|
|
292
|
+
yield {
|
|
293
|
+
path,
|
|
294
|
+
handle
|
|
295
|
+
};
|
|
296
|
+
if (isDirectoryHandle(
|
|
297
|
+
handle
|
|
298
|
+
) && options?.recursive) {
|
|
299
|
+
yield* read(
|
|
300
|
+
await dirHandle.getDirectoryHandle(
|
|
301
|
+
name
|
|
302
|
+
),
|
|
303
|
+
path
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return dirHandleRes.andThen(
|
|
309
|
+
(x) => happyRusty.Ok(
|
|
310
|
+
read(
|
|
311
|
+
x,
|
|
312
|
+
dirPath
|
|
313
|
+
)
|
|
314
|
+
)
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
async function readFile(filePath, options) {
|
|
318
|
+
assertAbsolutePath(
|
|
319
|
+
filePath
|
|
320
|
+
);
|
|
321
|
+
const fileHandleRes = await getFileHandle(
|
|
322
|
+
filePath
|
|
323
|
+
);
|
|
324
|
+
return fileHandleRes.andThenAsync(
|
|
325
|
+
async (fileHandle) => {
|
|
326
|
+
const file = await fileHandle.getFile();
|
|
327
|
+
switch (options?.encoding) {
|
|
328
|
+
case "blob": {
|
|
329
|
+
return happyRusty.Ok(file);
|
|
330
|
+
}
|
|
331
|
+
case "utf8": {
|
|
332
|
+
const text = await file.text();
|
|
333
|
+
return happyRusty.Ok(text);
|
|
334
|
+
}
|
|
335
|
+
default: {
|
|
336
|
+
const data = await file.arrayBuffer();
|
|
337
|
+
return happyRusty.Ok(data);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
async function remove(path) {
|
|
344
|
+
assertAbsolutePath(
|
|
345
|
+
path
|
|
346
|
+
);
|
|
347
|
+
const dirPath = posix.dirname(
|
|
348
|
+
path
|
|
349
|
+
);
|
|
350
|
+
const childName = posix.basename(
|
|
351
|
+
path
|
|
352
|
+
);
|
|
353
|
+
const dirHandleRes = await getDirHandle(
|
|
354
|
+
dirPath
|
|
355
|
+
);
|
|
356
|
+
return (await dirHandleRes.andThenAsync(
|
|
357
|
+
async (dirHandle) => {
|
|
358
|
+
try {
|
|
359
|
+
if (isRootPath(
|
|
360
|
+
dirPath
|
|
361
|
+
) && isRootPath(
|
|
362
|
+
childName
|
|
363
|
+
)) {
|
|
364
|
+
await dirHandle.remove(
|
|
365
|
+
{ recursive: true }
|
|
366
|
+
);
|
|
367
|
+
} else {
|
|
368
|
+
await dirHandle.removeEntry(
|
|
369
|
+
childName,
|
|
370
|
+
{ recursive: true }
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
} catch (_error) {
|
|
374
|
+
return happyRusty.Err(_error);
|
|
375
|
+
}
|
|
376
|
+
return happyRusty.RESULT_VOID;
|
|
377
|
+
}
|
|
378
|
+
)).orElse(
|
|
379
|
+
(_error) => {
|
|
380
|
+
return isNotFoundError(
|
|
381
|
+
_error
|
|
382
|
+
) ? happyRusty.RESULT_VOID : happyRusty.Err(
|
|
383
|
+
_error
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
async function stat(path) {
|
|
389
|
+
assertAbsolutePath(
|
|
390
|
+
path
|
|
391
|
+
);
|
|
392
|
+
const dirPath = posix.dirname(
|
|
393
|
+
path
|
|
394
|
+
);
|
|
395
|
+
const childName = posix.basename(
|
|
396
|
+
path
|
|
397
|
+
);
|
|
398
|
+
const dirHandleRes = await getDirHandle(
|
|
399
|
+
dirPath
|
|
400
|
+
);
|
|
401
|
+
if (!childName) {
|
|
402
|
+
return dirHandleRes;
|
|
403
|
+
}
|
|
404
|
+
return dirHandleRes.andThenAsync(
|
|
405
|
+
async (dirHandle) => {
|
|
406
|
+
for await (const [
|
|
407
|
+
name,
|
|
408
|
+
handle
|
|
409
|
+
] of dirHandle.entries()) {
|
|
410
|
+
if (name === childName) {
|
|
411
|
+
return happyRusty.Ok(
|
|
412
|
+
handle
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const err = new Error(
|
|
417
|
+
`${NOT_FOUND_ERROR}: '${childName}' does not exist. Full path is '${path}'.`
|
|
418
|
+
);
|
|
419
|
+
err.name = NOT_FOUND_ERROR;
|
|
420
|
+
return happyRusty.Err(
|
|
421
|
+
err
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
async function writeFile(filePath, contents, options) {
|
|
427
|
+
assertAbsolutePath(
|
|
428
|
+
filePath
|
|
429
|
+
);
|
|
430
|
+
const { append = false, create = true } = options ?? {};
|
|
431
|
+
const fileHandleRes = await getFileHandle(
|
|
432
|
+
filePath,
|
|
433
|
+
{ create }
|
|
434
|
+
);
|
|
435
|
+
return fileHandleRes.andThenAsync(
|
|
436
|
+
async (fileHandle) => {
|
|
437
|
+
const writable = await fileHandle.createWritable(
|
|
438
|
+
{ keepExistingData: append }
|
|
439
|
+
);
|
|
440
|
+
const params = {
|
|
441
|
+
type: "write",
|
|
442
|
+
data: contents
|
|
443
|
+
};
|
|
444
|
+
if (append) {
|
|
445
|
+
const { size } = await fileHandle.getFile();
|
|
446
|
+
params.position = size;
|
|
447
|
+
}
|
|
448
|
+
await writable.write(
|
|
449
|
+
params
|
|
450
|
+
);
|
|
451
|
+
await writable.close();
|
|
452
|
+
return happyRusty.RESULT_VOID;
|
|
453
|
+
}
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function downloadFile(fileUrl, filePath, requestInit) {
|
|
458
|
+
let aborted, saveToTemp;
|
|
459
|
+
assertFileUrl(
|
|
460
|
+
fileUrl
|
|
461
|
+
);
|
|
462
|
+
saveToTemp = false;
|
|
463
|
+
if (typeof filePath === "string") {
|
|
464
|
+
assertAbsolutePath(
|
|
465
|
+
filePath
|
|
466
|
+
);
|
|
467
|
+
} else {
|
|
468
|
+
requestInit = filePath;
|
|
469
|
+
filePath = generateTempPath(
|
|
470
|
+
{ extname: posix.extname(
|
|
471
|
+
fileUrl
|
|
472
|
+
) }
|
|
473
|
+
);
|
|
474
|
+
saveToTemp = true;
|
|
475
|
+
}
|
|
476
|
+
aborted = false;
|
|
477
|
+
const fetchTask = fetchT.fetchT(
|
|
478
|
+
fileUrl,
|
|
479
|
+
{
|
|
480
|
+
redirect: "follow",
|
|
481
|
+
...requestInit,
|
|
482
|
+
abortable: true
|
|
483
|
+
}
|
|
484
|
+
);
|
|
485
|
+
const response = (async () => {
|
|
486
|
+
const responseRes = await fetchTask.response;
|
|
487
|
+
return responseRes.andThenAsync(
|
|
488
|
+
async (response2) => {
|
|
489
|
+
const blob = await response2.blob();
|
|
490
|
+
if (aborted) {
|
|
491
|
+
return happyRusty.Err(
|
|
492
|
+
createAbortError()
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
const writeRes = await writeFile(filePath, blob);
|
|
496
|
+
return writeRes.and(
|
|
497
|
+
happyRusty.Ok(response2)
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
);
|
|
501
|
+
})();
|
|
502
|
+
return {
|
|
503
|
+
abort(reason) {
|
|
504
|
+
aborted = true;
|
|
505
|
+
fetchTask.abort(
|
|
506
|
+
reason
|
|
507
|
+
);
|
|
508
|
+
},
|
|
509
|
+
get aborted() {
|
|
510
|
+
return aborted;
|
|
511
|
+
},
|
|
512
|
+
get response() {
|
|
513
|
+
return saveToTemp ? response.then(
|
|
514
|
+
(res) => {
|
|
515
|
+
return res.map(
|
|
516
|
+
(rawResponse) => {
|
|
517
|
+
return {
|
|
518
|
+
tempFilePath: filePath,
|
|
519
|
+
rawResponse
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
) : response;
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
async function moveHandle(fileHandle, newPath) {
|
|
530
|
+
const newDirPath = posix.dirname(
|
|
531
|
+
newPath
|
|
532
|
+
);
|
|
533
|
+
return (await getDirHandle(
|
|
534
|
+
newDirPath,
|
|
535
|
+
{ create: true }
|
|
536
|
+
)).andThenAsync(
|
|
537
|
+
async (newDirHandle) => {
|
|
538
|
+
const newName = posix.basename(
|
|
539
|
+
newPath
|
|
540
|
+
);
|
|
541
|
+
try {
|
|
542
|
+
await fileHandle.move(
|
|
543
|
+
newDirHandle,
|
|
544
|
+
newName
|
|
545
|
+
);
|
|
546
|
+
return happyRusty.RESULT_VOID;
|
|
547
|
+
} catch (_error) {
|
|
548
|
+
return happyRusty.Err(
|
|
549
|
+
_error
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
async function mkDestFromSrc(srcPath, destPath, handler, overwrite = true) {
|
|
556
|
+
assertAbsolutePath(
|
|
557
|
+
destPath
|
|
558
|
+
);
|
|
559
|
+
return (await stat(
|
|
560
|
+
srcPath
|
|
561
|
+
)).andThenAsync(
|
|
562
|
+
async (srcHandle) => {
|
|
563
|
+
let destExists;
|
|
564
|
+
destExists = false;
|
|
565
|
+
const destHandleRes = await stat(
|
|
566
|
+
destPath
|
|
567
|
+
);
|
|
568
|
+
if (destHandleRes.isErr()) {
|
|
569
|
+
if (!isNotFoundError(
|
|
570
|
+
destHandleRes.unwrapErr()
|
|
571
|
+
)) {
|
|
572
|
+
return destHandleRes.asErr();
|
|
573
|
+
}
|
|
574
|
+
} else {
|
|
575
|
+
destExists = true;
|
|
576
|
+
const destHandle = destHandleRes.unwrap();
|
|
577
|
+
if (!(isFileHandle(
|
|
578
|
+
srcHandle
|
|
579
|
+
) && isFileHandle(
|
|
580
|
+
destHandle
|
|
581
|
+
) || isDirectoryHandle(
|
|
582
|
+
srcHandle
|
|
583
|
+
) && isDirectoryHandle(
|
|
584
|
+
destHandle
|
|
585
|
+
))) {
|
|
586
|
+
return happyRusty.Err(
|
|
587
|
+
new Error(
|
|
588
|
+
`Both 'srcPath' and 'destPath' must both be a file or directory.`
|
|
589
|
+
)
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (isFileHandle(
|
|
594
|
+
srcHandle
|
|
595
|
+
)) {
|
|
596
|
+
return overwrite || !destExists ? await handler(
|
|
597
|
+
srcHandle,
|
|
598
|
+
destPath
|
|
599
|
+
) : happyRusty.RESULT_VOID;
|
|
600
|
+
}
|
|
601
|
+
const readDirRes = await readDir(
|
|
602
|
+
srcPath,
|
|
603
|
+
{ recursive: true }
|
|
604
|
+
);
|
|
605
|
+
return readDirRes.andThenAsync(
|
|
606
|
+
async (entries) => {
|
|
607
|
+
const tasks = [
|
|
608
|
+
// make sure new dir created
|
|
609
|
+
mkdir(
|
|
610
|
+
destPath
|
|
611
|
+
)
|
|
612
|
+
];
|
|
613
|
+
for await (const {
|
|
614
|
+
path,
|
|
615
|
+
handle
|
|
616
|
+
} of entries) {
|
|
617
|
+
const newEntryPath = posix.join(
|
|
618
|
+
destPath,
|
|
619
|
+
path
|
|
620
|
+
);
|
|
621
|
+
let newPathExists = false;
|
|
622
|
+
if (destExists) {
|
|
623
|
+
const existsRes = await exists(
|
|
624
|
+
newEntryPath
|
|
625
|
+
);
|
|
626
|
+
if (existsRes.isErr()) {
|
|
627
|
+
tasks.push(
|
|
628
|
+
Promise.resolve(
|
|
629
|
+
existsRes.asErr()
|
|
630
|
+
)
|
|
631
|
+
);
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
newPathExists = existsRes.unwrap();
|
|
635
|
+
}
|
|
636
|
+
const res = isFileHandle(
|
|
637
|
+
handle
|
|
638
|
+
) ? overwrite || !newPathExists ? handler(
|
|
639
|
+
handle,
|
|
640
|
+
newEntryPath
|
|
641
|
+
) : Promise.resolve(
|
|
642
|
+
happyRusty.RESULT_VOID
|
|
643
|
+
) : mkdir(
|
|
644
|
+
newEntryPath
|
|
645
|
+
);
|
|
646
|
+
tasks.push(
|
|
647
|
+
res
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
return getFinalResult(
|
|
651
|
+
tasks
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
function appendFile(filePath, contents) {
|
|
659
|
+
return writeFile(
|
|
660
|
+
filePath,
|
|
661
|
+
contents,
|
|
662
|
+
{
|
|
663
|
+
append: true
|
|
664
|
+
}
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
async function copy(srcPath, destPath, options) {
|
|
668
|
+
const { overwrite = true } = options ?? {};
|
|
669
|
+
return mkDestFromSrc(
|
|
670
|
+
srcPath,
|
|
671
|
+
destPath,
|
|
672
|
+
async (srcHandle, destPath2) => {
|
|
673
|
+
return await writeFile(
|
|
674
|
+
destPath2,
|
|
675
|
+
await srcHandle.getFile()
|
|
676
|
+
);
|
|
677
|
+
},
|
|
678
|
+
overwrite
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
async function emptyDir(dirPath) {
|
|
682
|
+
const readDirRes = await readDir(
|
|
683
|
+
dirPath
|
|
684
|
+
);
|
|
685
|
+
if (readDirRes.isErr()) {
|
|
686
|
+
return isNotFoundError(
|
|
687
|
+
readDirRes.unwrapErr()
|
|
688
|
+
) ? mkdir(
|
|
689
|
+
dirPath
|
|
690
|
+
) : readDirRes.asErr();
|
|
691
|
+
}
|
|
692
|
+
const tasks = [];
|
|
693
|
+
for await (const { path } of readDirRes.unwrap()) {
|
|
694
|
+
tasks.push(
|
|
695
|
+
remove(
|
|
696
|
+
posix.join(
|
|
697
|
+
dirPath,
|
|
698
|
+
path
|
|
699
|
+
)
|
|
700
|
+
)
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
return getFinalResult(
|
|
704
|
+
tasks
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
async function exists(path, options) {
|
|
708
|
+
const {
|
|
709
|
+
isDirectory = false,
|
|
710
|
+
isFile = false
|
|
711
|
+
} = options ?? {};
|
|
712
|
+
invariant(
|
|
713
|
+
!(isDirectory && isFile),
|
|
714
|
+
() => "ExistsOptions.isDirectory and ExistsOptions.isFile must not be true together."
|
|
715
|
+
);
|
|
716
|
+
const statRes = await stat(
|
|
717
|
+
path
|
|
718
|
+
);
|
|
719
|
+
return statRes.andThen(
|
|
720
|
+
(handle) => {
|
|
721
|
+
const notExist = isDirectory && isFileHandle(
|
|
722
|
+
handle
|
|
723
|
+
) || isFile && isDirectoryHandle(
|
|
724
|
+
handle
|
|
725
|
+
);
|
|
726
|
+
return happyRusty.Ok(
|
|
727
|
+
!notExist
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
).orElse(
|
|
731
|
+
(_error) => {
|
|
732
|
+
return isNotFoundError(
|
|
733
|
+
_error
|
|
734
|
+
) ? happyRusty.RESULT_FALSE : statRes.asErr();
|
|
735
|
+
}
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
async function move(srcPath, destPath, options) {
|
|
739
|
+
const { overwrite = true } = options ?? {};
|
|
740
|
+
return (await mkDestFromSrc(
|
|
741
|
+
srcPath,
|
|
742
|
+
destPath,
|
|
743
|
+
moveHandle,
|
|
744
|
+
overwrite
|
|
745
|
+
)).andThenAsync(
|
|
746
|
+
() => {
|
|
747
|
+
return remove(
|
|
748
|
+
srcPath
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
function readBlobFile(filePath) {
|
|
754
|
+
return readFile(
|
|
755
|
+
filePath,
|
|
756
|
+
{ encoding: "blob" }
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
async function readJsonFile(filePath) {
|
|
760
|
+
return (await readTextFile(
|
|
761
|
+
filePath
|
|
762
|
+
)).andThenAsync(
|
|
763
|
+
async (contents) => {
|
|
764
|
+
try {
|
|
765
|
+
return happyRusty.Ok(
|
|
766
|
+
JSON.parse(
|
|
767
|
+
contents
|
|
768
|
+
)
|
|
769
|
+
);
|
|
770
|
+
} catch (_error) {
|
|
771
|
+
return happyRusty.Err(
|
|
772
|
+
_error
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
function readTextFile(filePath) {
|
|
779
|
+
return readFile(
|
|
780
|
+
filePath,
|
|
781
|
+
{ encoding: "utf8" }
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
async function mkTemp(options) {
|
|
786
|
+
const { isDirectory = false } = options ?? {};
|
|
787
|
+
const path = generateTempPath(
|
|
788
|
+
options
|
|
789
|
+
);
|
|
790
|
+
const res = await (isDirectory ? mkdir : createFile)(
|
|
791
|
+
path
|
|
792
|
+
);
|
|
793
|
+
return res.and(
|
|
794
|
+
happyRusty.Ok(path)
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
function deleteTemp() {
|
|
798
|
+
return remove(
|
|
799
|
+
TMP_DIR
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
async function pruneTemp(expired) {
|
|
803
|
+
invariant(
|
|
804
|
+
expired instanceof Date,
|
|
805
|
+
() => `Expired must be a Datebut received ${expired}`
|
|
806
|
+
);
|
|
807
|
+
const readDirRes = await readDir(
|
|
808
|
+
TMP_DIR,
|
|
809
|
+
{
|
|
810
|
+
recursive: true
|
|
811
|
+
}
|
|
812
|
+
);
|
|
813
|
+
return readDirRes.andThenAsync(
|
|
814
|
+
async (entries) => {
|
|
815
|
+
try {
|
|
816
|
+
for await (const { handle } of entries) {
|
|
817
|
+
if (isFileHandle(
|
|
818
|
+
handle
|
|
819
|
+
) && (await handle.getFile()).lastModified <= expired.getTime()) {
|
|
820
|
+
await handle.remove();
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
} catch (_error) {
|
|
824
|
+
return happyRusty.Err(
|
|
825
|
+
_error
|
|
826
|
+
);
|
|
827
|
+
}
|
|
828
|
+
return happyRusty.RESULT_VOID;
|
|
829
|
+
}
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
async function unzipBufferToTarget(buffer, targetPath) {
|
|
834
|
+
const data = new Uint8Array(
|
|
835
|
+
buffer
|
|
836
|
+
);
|
|
837
|
+
const future = new tinyFuture.Future();
|
|
838
|
+
fflate__namespace.unzip(
|
|
839
|
+
data,
|
|
840
|
+
async (err, unzipped) => {
|
|
841
|
+
if (err) {
|
|
842
|
+
future.resolve(
|
|
843
|
+
happyRusty.Err(
|
|
844
|
+
err
|
|
845
|
+
)
|
|
846
|
+
);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
const tasks = [];
|
|
850
|
+
for (const path in unzipped) {
|
|
851
|
+
if (path.at(
|
|
852
|
+
-1
|
|
853
|
+
) !== posix.SEPARATOR) {
|
|
854
|
+
tasks.push(
|
|
855
|
+
writeFile(
|
|
856
|
+
posix.join(
|
|
857
|
+
targetPath,
|
|
858
|
+
path
|
|
859
|
+
),
|
|
860
|
+
unzipped[path]
|
|
861
|
+
)
|
|
862
|
+
);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
future.resolve(
|
|
866
|
+
getFinalResult(
|
|
867
|
+
tasks
|
|
868
|
+
)
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
);
|
|
872
|
+
return await future.promise;
|
|
873
|
+
}
|
|
874
|
+
async function unzip(zipFilePath, targetPath) {
|
|
875
|
+
assertAbsolutePath(
|
|
876
|
+
targetPath
|
|
877
|
+
);
|
|
878
|
+
const fileRes = await readFile(
|
|
879
|
+
zipFilePath
|
|
880
|
+
);
|
|
881
|
+
return fileRes.andThenAsync(
|
|
882
|
+
(buffer) => {
|
|
883
|
+
return unzipBufferToTarget(
|
|
884
|
+
buffer,
|
|
885
|
+
targetPath
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
async function unzipFromUrl(zipFileUrl, targetPath, requestInit) {
|
|
891
|
+
assertFileUrl(
|
|
892
|
+
zipFileUrl
|
|
893
|
+
);
|
|
894
|
+
assertAbsolutePath(
|
|
895
|
+
targetPath
|
|
896
|
+
);
|
|
897
|
+
const fetchRes = await fetchT.fetchT(
|
|
898
|
+
zipFileUrl,
|
|
899
|
+
{
|
|
900
|
+
redirect: "follow",
|
|
901
|
+
...requestInit,
|
|
902
|
+
responseType: "arraybuffer",
|
|
903
|
+
abortable: false
|
|
904
|
+
}
|
|
905
|
+
);
|
|
906
|
+
return fetchRes.andThenAsync(
|
|
907
|
+
(buffer) => {
|
|
908
|
+
return unzipBufferToTarget(
|
|
909
|
+
buffer,
|
|
910
|
+
targetPath
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
function uploadFile(filePath, fileUrl, requestInit) {
|
|
917
|
+
let aborted;
|
|
918
|
+
let fetchTask;
|
|
919
|
+
assertFileUrl(
|
|
920
|
+
fileUrl
|
|
921
|
+
);
|
|
922
|
+
aborted = false;
|
|
923
|
+
const response = (async () => {
|
|
924
|
+
const fileRes = await readBlobFile(
|
|
925
|
+
filePath
|
|
926
|
+
);
|
|
927
|
+
return fileRes.andThenAsync(
|
|
928
|
+
async (file) => {
|
|
929
|
+
if (aborted) {
|
|
930
|
+
return happyRusty.Err(
|
|
931
|
+
createAbortError()
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
const {
|
|
935
|
+
// default file name
|
|
936
|
+
filename = posix.basename(filePath),
|
|
937
|
+
...rest
|
|
938
|
+
} = requestInit ?? {};
|
|
939
|
+
const formData = new FormData();
|
|
940
|
+
formData.append(
|
|
941
|
+
filename,
|
|
942
|
+
file,
|
|
943
|
+
filename
|
|
944
|
+
);
|
|
945
|
+
fetchTask = fetchT.fetchT(
|
|
946
|
+
fileUrl,
|
|
947
|
+
{
|
|
948
|
+
method: "POST",
|
|
949
|
+
...rest,
|
|
950
|
+
abortable: true,
|
|
951
|
+
body: formData
|
|
952
|
+
}
|
|
953
|
+
);
|
|
954
|
+
return fetchTask.response;
|
|
955
|
+
}
|
|
956
|
+
);
|
|
957
|
+
})();
|
|
958
|
+
return {
|
|
959
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
960
|
+
abort(reason) {
|
|
961
|
+
aborted = true;
|
|
962
|
+
fetchTask?.abort(
|
|
963
|
+
reason
|
|
964
|
+
);
|
|
965
|
+
},
|
|
966
|
+
get aborted() {
|
|
967
|
+
return aborted;
|
|
968
|
+
},
|
|
969
|
+
get response() {
|
|
970
|
+
return response;
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
async function zipTo(zippable, zipFilePath) {
|
|
976
|
+
const future = new tinyFuture.Future();
|
|
977
|
+
fflate__namespace.zip(
|
|
978
|
+
zippable,
|
|
979
|
+
{ consume: true },
|
|
980
|
+
async (err, u8a) => {
|
|
981
|
+
if (err) {
|
|
982
|
+
future.resolve(
|
|
983
|
+
happyRusty.Err(
|
|
984
|
+
err
|
|
985
|
+
)
|
|
986
|
+
);
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
if (zipFilePath) {
|
|
990
|
+
const res = await writeFile(
|
|
991
|
+
zipFilePath,
|
|
992
|
+
u8a
|
|
993
|
+
);
|
|
994
|
+
future.resolve(
|
|
995
|
+
res
|
|
996
|
+
);
|
|
997
|
+
} else {
|
|
998
|
+
future.resolve(
|
|
999
|
+
happyRusty.Ok(u8a)
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
);
|
|
1004
|
+
return await future.promise;
|
|
1005
|
+
}
|
|
1006
|
+
async function zip(sourcePath, zipFilePath, options) {
|
|
1007
|
+
if (typeof zipFilePath === "string") {
|
|
1008
|
+
assertAbsolutePath(
|
|
1009
|
+
zipFilePath
|
|
1010
|
+
);
|
|
1011
|
+
} else {
|
|
1012
|
+
options = zipFilePath;
|
|
1013
|
+
zipFilePath = void 0;
|
|
1014
|
+
}
|
|
1015
|
+
const statRes = await stat(
|
|
1016
|
+
sourcePath
|
|
1017
|
+
);
|
|
1018
|
+
return statRes.andThenAsync(
|
|
1019
|
+
async (handle) => {
|
|
1020
|
+
const sourceName = posix.basename(
|
|
1021
|
+
sourcePath
|
|
1022
|
+
);
|
|
1023
|
+
const zippable = {};
|
|
1024
|
+
if (isFileHandle(
|
|
1025
|
+
handle
|
|
1026
|
+
)) {
|
|
1027
|
+
const data = await getFileDataByHandle(
|
|
1028
|
+
handle
|
|
1029
|
+
);
|
|
1030
|
+
zippable[sourceName] = data;
|
|
1031
|
+
} else {
|
|
1032
|
+
const readDirRes = await readDir(
|
|
1033
|
+
sourcePath,
|
|
1034
|
+
{ recursive: true }
|
|
1035
|
+
);
|
|
1036
|
+
if (readDirRes.isErr()) {
|
|
1037
|
+
return readDirRes.asErr();
|
|
1038
|
+
}
|
|
1039
|
+
const preserveRoot = options?.preserveRoot ?? true;
|
|
1040
|
+
for await (const {
|
|
1041
|
+
path,
|
|
1042
|
+
handle: handle2
|
|
1043
|
+
} of readDirRes.unwrap()) {
|
|
1044
|
+
if (isFileHandle(
|
|
1045
|
+
handle2
|
|
1046
|
+
)) {
|
|
1047
|
+
const entryName = preserveRoot ? posix.join(
|
|
1048
|
+
sourceName,
|
|
1049
|
+
path
|
|
1050
|
+
) : path;
|
|
1051
|
+
const data = await getFileDataByHandle(
|
|
1052
|
+
handle2
|
|
1053
|
+
);
|
|
1054
|
+
zippable[entryName] = data;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
return zipTo(
|
|
1059
|
+
zippable,
|
|
1060
|
+
zipFilePath
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
async function zipFromUrl(sourceUrl, zipFilePath, requestInit) {
|
|
1066
|
+
assertFileUrl(
|
|
1067
|
+
sourceUrl
|
|
1068
|
+
);
|
|
1069
|
+
if (typeof zipFilePath === "string") {
|
|
1070
|
+
assertAbsolutePath(
|
|
1071
|
+
zipFilePath
|
|
1072
|
+
);
|
|
1073
|
+
} else {
|
|
1074
|
+
requestInit = zipFilePath;
|
|
1075
|
+
zipFilePath = void 0;
|
|
1076
|
+
}
|
|
1077
|
+
const fetchRes = await fetchT.fetchT(
|
|
1078
|
+
sourceUrl,
|
|
1079
|
+
{
|
|
1080
|
+
redirect: "follow",
|
|
1081
|
+
...requestInit,
|
|
1082
|
+
responseType: "arraybuffer",
|
|
1083
|
+
abortable: false
|
|
1084
|
+
}
|
|
1085
|
+
);
|
|
1086
|
+
return fetchRes.andThenAsync(
|
|
1087
|
+
(buffer) => {
|
|
1088
|
+
const sourceName = posix.basename(
|
|
1089
|
+
sourceUrl
|
|
1090
|
+
);
|
|
1091
|
+
const zippable = {};
|
|
1092
|
+
zippable[sourceName] = new Uint8Array(
|
|
1093
|
+
buffer
|
|
1094
|
+
);
|
|
1095
|
+
return zipTo(
|
|
1096
|
+
zippable,
|
|
1097
|
+
zipFilePath
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
);
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
function isOPFSSupported() {
|
|
1104
|
+
return typeof navigator?.storage?.getDirectory === "function";
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
function serializeError(error) {
|
|
1108
|
+
return error ? {
|
|
1109
|
+
name: error.name,
|
|
1110
|
+
message: error.message
|
|
1111
|
+
} : error;
|
|
1112
|
+
}
|
|
1113
|
+
function deserializeError(error) {
|
|
1114
|
+
const err = new Error(
|
|
1115
|
+
error.message
|
|
1116
|
+
);
|
|
1117
|
+
err.name = error.name;
|
|
1118
|
+
return err;
|
|
1119
|
+
}
|
|
1120
|
+
async function serializeFile(file) {
|
|
1121
|
+
const ab = await file.arrayBuffer();
|
|
1122
|
+
return {
|
|
1123
|
+
name: file.name,
|
|
1124
|
+
type: file.type,
|
|
1125
|
+
lastModified: file.lastModified,
|
|
1126
|
+
size: ab.byteLength,
|
|
1127
|
+
data: ab
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
let globalOpTimeout = 1e3;
|
|
1131
|
+
function setGlobalOpTimeout(timeout) {
|
|
1132
|
+
globalOpTimeout = timeout;
|
|
1133
|
+
}
|
|
1134
|
+
function sleepUntil(condition) {
|
|
1135
|
+
const start = Date.now();
|
|
1136
|
+
while (!condition()) {
|
|
1137
|
+
if (Date.now() - start > globalOpTimeout) {
|
|
1138
|
+
const error = new Error(
|
|
1139
|
+
"Operating Timeout"
|
|
1140
|
+
);
|
|
1141
|
+
error.name = fetchT.TIMEOUT_ERROR;
|
|
1142
|
+
throw error;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
var WorkerAsyncOp = /* @__PURE__ */ ((WorkerAsyncOp2) => {
|
|
1148
|
+
WorkerAsyncOp2[WorkerAsyncOp2["createFile"] = 0] = "createFile";
|
|
1149
|
+
WorkerAsyncOp2[WorkerAsyncOp2["mkdir"] = 1] = "mkdir";
|
|
1150
|
+
WorkerAsyncOp2[WorkerAsyncOp2["move"] = 2] = "move";
|
|
1151
|
+
WorkerAsyncOp2[WorkerAsyncOp2["readDir"] = 3] = "readDir";
|
|
1152
|
+
WorkerAsyncOp2[WorkerAsyncOp2["remove"] = 4] = "remove";
|
|
1153
|
+
WorkerAsyncOp2[WorkerAsyncOp2["stat"] = 5] = "stat";
|
|
1154
|
+
WorkerAsyncOp2[WorkerAsyncOp2["writeFile"] = 6] = "writeFile";
|
|
1155
|
+
WorkerAsyncOp2[WorkerAsyncOp2["appendFile"] = 7] = "appendFile";
|
|
1156
|
+
WorkerAsyncOp2[WorkerAsyncOp2["copy"] = 8] = "copy";
|
|
1157
|
+
WorkerAsyncOp2[WorkerAsyncOp2["emptyDir"] = 9] = "emptyDir";
|
|
1158
|
+
WorkerAsyncOp2[WorkerAsyncOp2["exists"] = 10] = "exists";
|
|
1159
|
+
WorkerAsyncOp2[WorkerAsyncOp2["deleteTemp"] = 11] = "deleteTemp";
|
|
1160
|
+
WorkerAsyncOp2[WorkerAsyncOp2["mkTemp"] = 12] = "mkTemp";
|
|
1161
|
+
WorkerAsyncOp2[WorkerAsyncOp2["pruneTemp"] = 13] = "pruneTemp";
|
|
1162
|
+
WorkerAsyncOp2[WorkerAsyncOp2["readBlobFile"] = 14] = "readBlobFile";
|
|
1163
|
+
WorkerAsyncOp2[WorkerAsyncOp2["unzip"] = 15] = "unzip";
|
|
1164
|
+
WorkerAsyncOp2[WorkerAsyncOp2["zip"] = 16] = "zip";
|
|
1165
|
+
return WorkerAsyncOp2;
|
|
1166
|
+
})(WorkerAsyncOp || {});
|
|
1167
|
+
const MAIN_LOCK_INDEX = 0;
|
|
1168
|
+
const WORKER_LOCK_INDEX = 1;
|
|
1169
|
+
const DATA_INDEX = 2;
|
|
1170
|
+
const MAIN_LOCKED = 1;
|
|
1171
|
+
const MAIN_UNLOCKED = 0;
|
|
1172
|
+
const WORKER_LOCKED = MAIN_UNLOCKED;
|
|
1173
|
+
const WORKER_UNLOCKED = MAIN_LOCKED;
|
|
1174
|
+
let encoder;
|
|
1175
|
+
let decoder;
|
|
1176
|
+
function getEncoder() {
|
|
1177
|
+
encoder ??= new TextEncoder();
|
|
1178
|
+
return encoder;
|
|
1179
|
+
}
|
|
1180
|
+
function getDecoder() {
|
|
1181
|
+
decoder ??= new TextDecoder();
|
|
1182
|
+
return decoder;
|
|
1183
|
+
}
|
|
1184
|
+
function encodeToBuffer(data) {
|
|
1185
|
+
const str = JSON.stringify(data);
|
|
1186
|
+
return getEncoder().encode(
|
|
1187
|
+
str
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1190
|
+
function decodeFromBuffer(data) {
|
|
1191
|
+
const str = decodeToString(
|
|
1192
|
+
data
|
|
1193
|
+
);
|
|
1194
|
+
return JSON.parse(
|
|
1195
|
+
str
|
|
1196
|
+
);
|
|
1197
|
+
}
|
|
1198
|
+
function decodeToString(data) {
|
|
1199
|
+
return getDecoder().decode(
|
|
1200
|
+
data
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
class SyncMessenger {
|
|
1204
|
+
// View of SharedArrayBuffer, used to communicate between main thread and worker.
|
|
1205
|
+
i32a;
|
|
1206
|
+
// View of the same SharedArrayBuffer, used to read and write binary data.
|
|
1207
|
+
u8a;
|
|
1208
|
+
// 4 int: MAIN_LOCK_INDEX WORKER_LOCK_INDEX DATA_INDEX NOT_USE
|
|
1209
|
+
headerLength = 4 * 4;
|
|
1210
|
+
// maximum length of data to be sent. If data is longer than this, it will throw an error.
|
|
1211
|
+
maxDataLength;
|
|
1212
|
+
constructor(sab) {
|
|
1213
|
+
this.i32a = new Int32Array(
|
|
1214
|
+
sab
|
|
1215
|
+
);
|
|
1216
|
+
this.u8a = new Uint8Array(
|
|
1217
|
+
sab
|
|
1218
|
+
);
|
|
1219
|
+
this.maxDataLength = sab.byteLength - this.headerLength;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
function callWorkerFromMain(messenger, data) {
|
|
1223
|
+
const {
|
|
1224
|
+
i32a,
|
|
1225
|
+
u8a,
|
|
1226
|
+
headerLength,
|
|
1227
|
+
maxDataLength
|
|
1228
|
+
} = messenger;
|
|
1229
|
+
const requestLength = data.byteLength;
|
|
1230
|
+
if (requestLength > maxDataLength) {
|
|
1231
|
+
throw new RangeError(
|
|
1232
|
+
`Request is too large: ${requestLength} > ${maxDataLength}. Consider grow the size of SharedArrayBuffer.`
|
|
1233
|
+
);
|
|
1234
|
+
}
|
|
1235
|
+
Atomics.store(
|
|
1236
|
+
i32a,
|
|
1237
|
+
MAIN_LOCK_INDEX,
|
|
1238
|
+
MAIN_LOCKED
|
|
1239
|
+
);
|
|
1240
|
+
i32a[DATA_INDEX] = requestLength;
|
|
1241
|
+
u8a.set(
|
|
1242
|
+
data,
|
|
1243
|
+
headerLength
|
|
1244
|
+
);
|
|
1245
|
+
Atomics.store(
|
|
1246
|
+
i32a,
|
|
1247
|
+
WORKER_LOCK_INDEX,
|
|
1248
|
+
WORKER_UNLOCKED
|
|
1249
|
+
);
|
|
1250
|
+
sleepUntil(
|
|
1251
|
+
() => Atomics.load(
|
|
1252
|
+
i32a,
|
|
1253
|
+
MAIN_LOCK_INDEX
|
|
1254
|
+
) === MAIN_UNLOCKED
|
|
1255
|
+
);
|
|
1256
|
+
const responseLength = i32a[DATA_INDEX];
|
|
1257
|
+
const response = u8a.slice(
|
|
1258
|
+
headerLength,
|
|
1259
|
+
headerLength + responseLength
|
|
1260
|
+
);
|
|
1261
|
+
return response;
|
|
1262
|
+
}
|
|
1263
|
+
async function respondToMainFromWorker(messenger, transfer) {
|
|
1264
|
+
const {
|
|
1265
|
+
i32a,
|
|
1266
|
+
u8a,
|
|
1267
|
+
headerLength,
|
|
1268
|
+
maxDataLength
|
|
1269
|
+
} = messenger;
|
|
1270
|
+
while (true) {
|
|
1271
|
+
if (Atomics.load(
|
|
1272
|
+
i32a,
|
|
1273
|
+
WORKER_LOCK_INDEX
|
|
1274
|
+
) === WORKER_UNLOCKED) {
|
|
1275
|
+
break;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
const requestLength = i32a[DATA_INDEX];
|
|
1279
|
+
const data = u8a.slice(
|
|
1280
|
+
headerLength,
|
|
1281
|
+
headerLength + requestLength
|
|
1282
|
+
);
|
|
1283
|
+
let response = await transfer(
|
|
1284
|
+
data
|
|
1285
|
+
);
|
|
1286
|
+
const responseLength = response.byteLength;
|
|
1287
|
+
if (responseLength > maxDataLength) {
|
|
1288
|
+
const message = `Response is too large: ${responseLength} > ${maxDataLength}. Consider grow the size of SharedArrayBuffer.`;
|
|
1289
|
+
response = encodeToBuffer(
|
|
1290
|
+
[{
|
|
1291
|
+
name: "RangeError",
|
|
1292
|
+
message
|
|
1293
|
+
}]
|
|
1294
|
+
);
|
|
1295
|
+
if (response.byteLength > maxDataLength) {
|
|
1296
|
+
Atomics.store(
|
|
1297
|
+
i32a,
|
|
1298
|
+
WORKER_LOCK_INDEX,
|
|
1299
|
+
WORKER_LOCKED
|
|
1300
|
+
);
|
|
1301
|
+
throw new RangeError(
|
|
1302
|
+
message
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
i32a[DATA_INDEX] = response.byteLength;
|
|
1307
|
+
u8a.set(
|
|
1308
|
+
response,
|
|
1309
|
+
headerLength
|
|
1310
|
+
);
|
|
1311
|
+
Atomics.store(
|
|
1312
|
+
i32a,
|
|
1313
|
+
WORKER_LOCK_INDEX,
|
|
1314
|
+
WORKER_LOCKED
|
|
1315
|
+
);
|
|
1316
|
+
Atomics.store(
|
|
1317
|
+
i32a,
|
|
1318
|
+
MAIN_LOCK_INDEX,
|
|
1319
|
+
MAIN_UNLOCKED
|
|
1320
|
+
);
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
const asyncOps = {
|
|
1324
|
+
[WorkerAsyncOp.createFile]: createFile,
|
|
1325
|
+
[WorkerAsyncOp.mkdir]: mkdir,
|
|
1326
|
+
[WorkerAsyncOp.move]: move,
|
|
1327
|
+
[WorkerAsyncOp.readDir]: readDir,
|
|
1328
|
+
[WorkerAsyncOp.remove]: remove,
|
|
1329
|
+
[WorkerAsyncOp.stat]: stat,
|
|
1330
|
+
[WorkerAsyncOp.writeFile]: writeFile,
|
|
1331
|
+
[WorkerAsyncOp.appendFile]: appendFile,
|
|
1332
|
+
[WorkerAsyncOp.copy]: copy,
|
|
1333
|
+
[WorkerAsyncOp.emptyDir]: emptyDir,
|
|
1334
|
+
[WorkerAsyncOp.exists]: exists,
|
|
1335
|
+
[WorkerAsyncOp.deleteTemp]: deleteTemp,
|
|
1336
|
+
[WorkerAsyncOp.mkTemp]: mkTemp,
|
|
1337
|
+
[WorkerAsyncOp.pruneTemp]: pruneTemp,
|
|
1338
|
+
[WorkerAsyncOp.readBlobFile]: readBlobFile,
|
|
1339
|
+
[WorkerAsyncOp.unzip]: unzip,
|
|
1340
|
+
[WorkerAsyncOp.zip]: zip
|
|
1341
|
+
};
|
|
1342
|
+
let messenger$1;
|
|
1343
|
+
function startSyncAgent() {
|
|
1344
|
+
if (typeof window !== "undefined") {
|
|
1345
|
+
throw new Error(
|
|
1346
|
+
"Only can use in worker"
|
|
1347
|
+
);
|
|
1348
|
+
}
|
|
1349
|
+
if (messenger$1) {
|
|
1350
|
+
throw new Error(
|
|
1351
|
+
"Worker messenger already started"
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
addEventListener(
|
|
1355
|
+
"message",
|
|
1356
|
+
(event) => {
|
|
1357
|
+
const sab = event.data;
|
|
1358
|
+
if (!(sab instanceof SharedArrayBuffer)) {
|
|
1359
|
+
throw new TypeError(
|
|
1360
|
+
"Only can post SharedArrayBuffer to Worker"
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1363
|
+
messenger$1 = new SyncMessenger(sab);
|
|
1364
|
+
postMessage(
|
|
1365
|
+
true
|
|
1366
|
+
);
|
|
1367
|
+
runWorkerLoop();
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
async function runWorkerLoop() {
|
|
1372
|
+
while (true) {
|
|
1373
|
+
try {
|
|
1374
|
+
await respondToMainFromWorker(
|
|
1375
|
+
messenger$1,
|
|
1376
|
+
async (data) => {
|
|
1377
|
+
const [op, ...args] = decodeFromBuffer(
|
|
1378
|
+
data
|
|
1379
|
+
);
|
|
1380
|
+
if (op === WorkerAsyncOp.writeFile || op === WorkerAsyncOp.appendFile) {
|
|
1381
|
+
if (Array.isArray(
|
|
1382
|
+
args[1]
|
|
1383
|
+
)) {
|
|
1384
|
+
args[1] = new Uint8Array(
|
|
1385
|
+
args[1]
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
} else if (op === WorkerAsyncOp.pruneTemp) {
|
|
1389
|
+
args[0] = new Date(
|
|
1390
|
+
args[0]
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
let response;
|
|
1394
|
+
const handle = asyncOps[op];
|
|
1395
|
+
try {
|
|
1396
|
+
const res = await handle(
|
|
1397
|
+
...args
|
|
1398
|
+
);
|
|
1399
|
+
if (res.isErr()) {
|
|
1400
|
+
response = encodeToBuffer(
|
|
1401
|
+
[serializeError(
|
|
1402
|
+
res.unwrapErr()
|
|
1403
|
+
)]
|
|
1404
|
+
);
|
|
1405
|
+
} else {
|
|
1406
|
+
let rawResponse;
|
|
1407
|
+
if (op === WorkerAsyncOp.readBlobFile) {
|
|
1408
|
+
const file = res.unwrap();
|
|
1409
|
+
const fileLike = await serializeFile(
|
|
1410
|
+
file
|
|
1411
|
+
);
|
|
1412
|
+
rawResponse = {
|
|
1413
|
+
...fileLike,
|
|
1414
|
+
// for serialize
|
|
1415
|
+
data: [...new Uint8Array(
|
|
1416
|
+
fileLike.data
|
|
1417
|
+
)]
|
|
1418
|
+
};
|
|
1419
|
+
} else if (op === WorkerAsyncOp.readDir) {
|
|
1420
|
+
const iterator = res.unwrap();
|
|
1421
|
+
const entries = [];
|
|
1422
|
+
for await (const {
|
|
1423
|
+
path,
|
|
1424
|
+
handle: handle2
|
|
1425
|
+
} of iterator) {
|
|
1426
|
+
const handleLike = await toFileSystemHandleLike(
|
|
1427
|
+
handle2
|
|
1428
|
+
);
|
|
1429
|
+
entries.push(
|
|
1430
|
+
{
|
|
1431
|
+
path,
|
|
1432
|
+
handle: handleLike
|
|
1433
|
+
}
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1436
|
+
rawResponse = entries;
|
|
1437
|
+
} else if (op === WorkerAsyncOp.stat) {
|
|
1438
|
+
const handle2 = res.unwrap();
|
|
1439
|
+
const data2 = await toFileSystemHandleLike(
|
|
1440
|
+
handle2
|
|
1441
|
+
);
|
|
1442
|
+
rawResponse = data2;
|
|
1443
|
+
} else if (op === WorkerAsyncOp.zip) {
|
|
1444
|
+
const data2 = res.unwrap();
|
|
1445
|
+
rawResponse = data2 instanceof Uint8Array ? [...data2] : data2;
|
|
1446
|
+
} else {
|
|
1447
|
+
rawResponse = res.unwrap();
|
|
1448
|
+
}
|
|
1449
|
+
response = encodeToBuffer(
|
|
1450
|
+
[
|
|
1451
|
+
null,
|
|
1452
|
+
rawResponse
|
|
1453
|
+
]
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
} catch (_error) {
|
|
1457
|
+
response = encodeToBuffer(
|
|
1458
|
+
[serializeError(
|
|
1459
|
+
_error
|
|
1460
|
+
)]
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
return response;
|
|
1464
|
+
}
|
|
1465
|
+
);
|
|
1466
|
+
} catch (_error) {
|
|
1467
|
+
console.error(
|
|
1468
|
+
_error instanceof Error ? _error.stack : _error
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
let messenger;
|
|
1475
|
+
function connectSyncAgent(options) {
|
|
1476
|
+
if (typeof window === "undefined") {
|
|
1477
|
+
throw new Error(
|
|
1478
|
+
"Only can use in main thread"
|
|
1479
|
+
);
|
|
1480
|
+
}
|
|
1481
|
+
if (messenger) {
|
|
1482
|
+
throw new Error(
|
|
1483
|
+
"Main messenger already started"
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
return new Promise(
|
|
1487
|
+
(resolve) => {
|
|
1488
|
+
const {
|
|
1489
|
+
worker,
|
|
1490
|
+
bufferLength = 1024 * 1024,
|
|
1491
|
+
opTimeout = 1e3
|
|
1492
|
+
} = options;
|
|
1493
|
+
invariant(
|
|
1494
|
+
worker instanceof Worker || worker instanceof URL || typeof worker === "string" && worker,
|
|
1495
|
+
() => "Worker must be Worker or valid URL(string)."
|
|
1496
|
+
);
|
|
1497
|
+
invariant(
|
|
1498
|
+
bufferLength > 16 && bufferLength % 4 === 0,
|
|
1499
|
+
() => "bufferLength must be a multiple of 4."
|
|
1500
|
+
);
|
|
1501
|
+
invariant(
|
|
1502
|
+
Number.isInteger(
|
|
1503
|
+
opTimeout
|
|
1504
|
+
) && opTimeout > 0,
|
|
1505
|
+
() => "opTimeout must be integer and greater than 0."
|
|
1506
|
+
);
|
|
1507
|
+
setGlobalOpTimeout(
|
|
1508
|
+
opTimeout
|
|
1509
|
+
);
|
|
1510
|
+
const workerAdapter = worker instanceof Worker ? worker : new Worker(
|
|
1511
|
+
worker
|
|
1512
|
+
);
|
|
1513
|
+
const sab = new SharedArrayBuffer(
|
|
1514
|
+
bufferLength
|
|
1515
|
+
);
|
|
1516
|
+
workerAdapter.addEventListener(
|
|
1517
|
+
"message",
|
|
1518
|
+
(event) => {
|
|
1519
|
+
if (event.data) {
|
|
1520
|
+
messenger = new SyncMessenger(
|
|
1521
|
+
sab
|
|
1522
|
+
);
|
|
1523
|
+
resolve();
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
);
|
|
1527
|
+
workerAdapter.postMessage(
|
|
1528
|
+
sab
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
function getSyncMessenger() {
|
|
1534
|
+
return messenger;
|
|
1535
|
+
}
|
|
1536
|
+
function setSyncMessenger(syncMessenger) {
|
|
1537
|
+
invariant(
|
|
1538
|
+
syncMessenger != null,
|
|
1539
|
+
() => "syncMessenger is null or undefined."
|
|
1540
|
+
);
|
|
1541
|
+
messenger = syncMessenger;
|
|
1542
|
+
}
|
|
1543
|
+
function callWorkerOp(op, ...args) {
|
|
1544
|
+
if (!messenger) {
|
|
1545
|
+
return happyRusty.Err(
|
|
1546
|
+
new Error(
|
|
1547
|
+
"Worker not initialized. Come back later."
|
|
1548
|
+
)
|
|
1549
|
+
);
|
|
1550
|
+
}
|
|
1551
|
+
const request = [
|
|
1552
|
+
op,
|
|
1553
|
+
...args
|
|
1554
|
+
];
|
|
1555
|
+
const requestData = encodeToBuffer(
|
|
1556
|
+
request
|
|
1557
|
+
);
|
|
1558
|
+
try {
|
|
1559
|
+
const response = callWorkerFromMain(
|
|
1560
|
+
messenger,
|
|
1561
|
+
requestData
|
|
1562
|
+
);
|
|
1563
|
+
const decodedResponse = decodeFromBuffer(
|
|
1564
|
+
response
|
|
1565
|
+
);
|
|
1566
|
+
const _error = decodedResponse[0];
|
|
1567
|
+
const result = _error ? happyRusty.Err(
|
|
1568
|
+
deserializeError(
|
|
1569
|
+
_error
|
|
1570
|
+
)
|
|
1571
|
+
) : happyRusty.Ok(
|
|
1572
|
+
decodedResponse[1] ?? void 0
|
|
1573
|
+
);
|
|
1574
|
+
return result;
|
|
1575
|
+
} catch (_error) {
|
|
1576
|
+
return happyRusty.Err(
|
|
1577
|
+
_error
|
|
1578
|
+
);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
function createFileSync(filePath) {
|
|
1582
|
+
return callWorkerOp(
|
|
1583
|
+
WorkerAsyncOp.createFile,
|
|
1584
|
+
filePath
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
function mkdirSync(dirPath) {
|
|
1588
|
+
return callWorkerOp(
|
|
1589
|
+
WorkerAsyncOp.mkdir,
|
|
1590
|
+
dirPath
|
|
1591
|
+
);
|
|
1592
|
+
}
|
|
1593
|
+
function moveSync(srcPath, destPath, options) {
|
|
1594
|
+
return callWorkerOp(
|
|
1595
|
+
WorkerAsyncOp.move,
|
|
1596
|
+
srcPath,
|
|
1597
|
+
destPath,
|
|
1598
|
+
options
|
|
1599
|
+
);
|
|
1600
|
+
}
|
|
1601
|
+
function readDirSync(dirPath, options) {
|
|
1602
|
+
return callWorkerOp(
|
|
1603
|
+
WorkerAsyncOp.readDir,
|
|
1604
|
+
dirPath,
|
|
1605
|
+
options
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
function readFileSync(filePath, options) {
|
|
1609
|
+
const res = callWorkerOp(
|
|
1610
|
+
WorkerAsyncOp.readBlobFile,
|
|
1611
|
+
filePath
|
|
1612
|
+
);
|
|
1613
|
+
return res.map(
|
|
1614
|
+
(file) => {
|
|
1615
|
+
const u8a = new Uint8Array(
|
|
1616
|
+
file.data
|
|
1617
|
+
);
|
|
1618
|
+
file.data = u8a.buffer.slice(
|
|
1619
|
+
u8a.byteOffset,
|
|
1620
|
+
u8a.byteOffset + u8a.byteLength
|
|
1621
|
+
);
|
|
1622
|
+
switch (options?.encoding) {
|
|
1623
|
+
case "blob": {
|
|
1624
|
+
return file;
|
|
1625
|
+
}
|
|
1626
|
+
case "utf8": {
|
|
1627
|
+
return decodeToString(new Uint8Array(file.data));
|
|
1628
|
+
}
|
|
1629
|
+
default: {
|
|
1630
|
+
return file.data;
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1636
|
+
function removeSync(path) {
|
|
1637
|
+
return callWorkerOp(
|
|
1638
|
+
WorkerAsyncOp.remove,
|
|
1639
|
+
path
|
|
1640
|
+
);
|
|
1641
|
+
}
|
|
1642
|
+
function statSync(path) {
|
|
1643
|
+
return callWorkerOp(
|
|
1644
|
+
WorkerAsyncOp.stat,
|
|
1645
|
+
path
|
|
1646
|
+
);
|
|
1647
|
+
}
|
|
1648
|
+
function serializeWriteContents(contents) {
|
|
1649
|
+
return contents instanceof ArrayBuffer ? [...new Uint8Array(
|
|
1650
|
+
contents
|
|
1651
|
+
)] : ArrayBuffer.isView(
|
|
1652
|
+
contents
|
|
1653
|
+
) ? [...new Uint8Array(
|
|
1654
|
+
contents.buffer
|
|
1655
|
+
)] : contents;
|
|
1656
|
+
}
|
|
1657
|
+
function writeFileSync(filePath, contents, options) {
|
|
1658
|
+
return callWorkerOp(
|
|
1659
|
+
WorkerAsyncOp.writeFile,
|
|
1660
|
+
filePath,
|
|
1661
|
+
serializeWriteContents(
|
|
1662
|
+
contents
|
|
1663
|
+
),
|
|
1664
|
+
options
|
|
1665
|
+
);
|
|
1666
|
+
}
|
|
1667
|
+
function appendFileSync(filePath, contents) {
|
|
1668
|
+
return callWorkerOp(
|
|
1669
|
+
WorkerAsyncOp.appendFile,
|
|
1670
|
+
filePath,
|
|
1671
|
+
serializeWriteContents(
|
|
1672
|
+
contents
|
|
1673
|
+
)
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
function copySync(srcPath, destPath, options) {
|
|
1677
|
+
return callWorkerOp(
|
|
1678
|
+
WorkerAsyncOp.copy,
|
|
1679
|
+
srcPath,
|
|
1680
|
+
destPath,
|
|
1681
|
+
options
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1684
|
+
function emptyDirSync(dirPath) {
|
|
1685
|
+
return callWorkerOp(
|
|
1686
|
+
WorkerAsyncOp.emptyDir,
|
|
1687
|
+
dirPath
|
|
1688
|
+
);
|
|
1689
|
+
}
|
|
1690
|
+
function existsSync(path, options) {
|
|
1691
|
+
return callWorkerOp(
|
|
1692
|
+
WorkerAsyncOp.exists,
|
|
1693
|
+
path,
|
|
1694
|
+
options
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
function deleteTempSync() {
|
|
1698
|
+
return callWorkerOp(
|
|
1699
|
+
WorkerAsyncOp.deleteTemp
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
function mkTempSync(options) {
|
|
1703
|
+
return callWorkerOp(
|
|
1704
|
+
WorkerAsyncOp.mkTemp,
|
|
1705
|
+
options
|
|
1706
|
+
);
|
|
1707
|
+
}
|
|
1708
|
+
function pruneTempSync(expired) {
|
|
1709
|
+
return callWorkerOp(
|
|
1710
|
+
WorkerAsyncOp.pruneTemp,
|
|
1711
|
+
expired
|
|
1712
|
+
);
|
|
1713
|
+
}
|
|
1714
|
+
function readBlobFileSync(filePath) {
|
|
1715
|
+
return readFileSync(
|
|
1716
|
+
filePath,
|
|
1717
|
+
{
|
|
1718
|
+
encoding: "blob"
|
|
1719
|
+
}
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
function readJsonFileSync(filePath) {
|
|
1723
|
+
return readTextFileSync(
|
|
1724
|
+
filePath
|
|
1725
|
+
).andThen(
|
|
1726
|
+
(contents) => {
|
|
1727
|
+
try {
|
|
1728
|
+
return happyRusty.Ok(
|
|
1729
|
+
JSON.parse(
|
|
1730
|
+
contents
|
|
1731
|
+
)
|
|
1732
|
+
);
|
|
1733
|
+
} catch (_error) {
|
|
1734
|
+
return happyRusty.Err(
|
|
1735
|
+
_error
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
);
|
|
1740
|
+
}
|
|
1741
|
+
function readTextFileSync(filePath) {
|
|
1742
|
+
return readFileSync(
|
|
1743
|
+
filePath,
|
|
1744
|
+
{ encoding: "utf8" }
|
|
1745
|
+
);
|
|
1746
|
+
}
|
|
1747
|
+
function unzipSync(zipFilePath, targetPath) {
|
|
1748
|
+
return callWorkerOp(
|
|
1749
|
+
WorkerAsyncOp.unzip,
|
|
1750
|
+
zipFilePath,
|
|
1751
|
+
targetPath
|
|
1752
|
+
);
|
|
1753
|
+
}
|
|
1754
|
+
function zipSync(sourcePath, zipFilePath, options) {
|
|
1755
|
+
const res = callWorkerOp(
|
|
1756
|
+
WorkerAsyncOp.zip,
|
|
1757
|
+
sourcePath,
|
|
1758
|
+
zipFilePath,
|
|
1759
|
+
options
|
|
1760
|
+
);
|
|
1761
|
+
return res.map(
|
|
1762
|
+
(data) => {
|
|
1763
|
+
return data ? new Uint8Array(
|
|
1764
|
+
data
|
|
1765
|
+
) : data;
|
|
1766
|
+
}
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
Object.defineProperty(exports, "ABORT_ERROR", {
|
|
1771
|
+
enumerable: true,
|
|
1772
|
+
get: function () { return fetchT.ABORT_ERROR; }
|
|
1773
|
+
});
|
|
1774
|
+
Object.defineProperty(exports, "TIMEOUT_ERROR", {
|
|
1775
|
+
enumerable: true,
|
|
1776
|
+
get: function () { return fetchT.TIMEOUT_ERROR; }
|
|
1777
|
+
});
|
|
1778
|
+
exports.CURRENT_DIR = CURRENT_DIR;
|
|
1779
|
+
exports.NOT_FOUND_ERROR = NOT_FOUND_ERROR;
|
|
1780
|
+
exports.ROOT_DIR = ROOT_DIR;
|
|
1781
|
+
exports.TMP_DIR = TMP_DIR;
|
|
1782
|
+
exports.appendFile = appendFile;
|
|
1783
|
+
exports.appendFileSync = appendFileSync;
|
|
1784
|
+
exports.assertAbsolutePath = assertAbsolutePath;
|
|
1785
|
+
exports.assertFileUrl = assertFileUrl;
|
|
1786
|
+
exports.connectSyncAgent = connectSyncAgent;
|
|
1787
|
+
exports.copy = copy;
|
|
1788
|
+
exports.copySync = copySync;
|
|
1789
|
+
exports.createFile = createFile;
|
|
1790
|
+
exports.createFileSync = createFileSync;
|
|
1791
|
+
exports.deleteTemp = deleteTemp;
|
|
1792
|
+
exports.deleteTempSync = deleteTempSync;
|
|
1793
|
+
exports.downloadFile = downloadFile;
|
|
1794
|
+
exports.emptyDir = emptyDir;
|
|
1795
|
+
exports.emptyDirSync = emptyDirSync;
|
|
1796
|
+
exports.exists = exists;
|
|
1797
|
+
exports.existsSync = existsSync;
|
|
1798
|
+
exports.generateTempPath = generateTempPath;
|
|
1799
|
+
exports.getFileDataByHandle = getFileDataByHandle;
|
|
1800
|
+
exports.getSyncMessenger = getSyncMessenger;
|
|
1801
|
+
exports.isDirectoryHandle = isDirectoryHandle;
|
|
1802
|
+
exports.isFileHandle = isFileHandle;
|
|
1803
|
+
exports.isFileHandleLike = isFileHandleLike;
|
|
1804
|
+
exports.isOPFSSupported = isOPFSSupported;
|
|
1805
|
+
exports.isTempPath = isTempPath;
|
|
1806
|
+
exports.mkTemp = mkTemp;
|
|
1807
|
+
exports.mkTempSync = mkTempSync;
|
|
1808
|
+
exports.mkdir = mkdir;
|
|
1809
|
+
exports.mkdirSync = mkdirSync;
|
|
1810
|
+
exports.move = move;
|
|
1811
|
+
exports.moveSync = moveSync;
|
|
1812
|
+
exports.pruneTemp = pruneTemp;
|
|
1813
|
+
exports.pruneTempSync = pruneTempSync;
|
|
1814
|
+
exports.readBlobFile = readBlobFile;
|
|
1815
|
+
exports.readBlobFileSync = readBlobFileSync;
|
|
1816
|
+
exports.readDir = readDir;
|
|
1817
|
+
exports.readDirSync = readDirSync;
|
|
1818
|
+
exports.readFile = readFile;
|
|
1819
|
+
exports.readFileSync = readFileSync;
|
|
1820
|
+
exports.readJsonFile = readJsonFile;
|
|
1821
|
+
exports.readJsonFileSync = readJsonFileSync;
|
|
1822
|
+
exports.readTextFile = readTextFile;
|
|
1823
|
+
exports.readTextFileSync = readTextFileSync;
|
|
1824
|
+
exports.remove = remove;
|
|
1825
|
+
exports.removeSync = removeSync;
|
|
1826
|
+
exports.setSyncMessenger = setSyncMessenger;
|
|
1827
|
+
exports.startSyncAgent = startSyncAgent;
|
|
1828
|
+
exports.stat = stat;
|
|
1829
|
+
exports.statSync = statSync;
|
|
1830
|
+
exports.toFileSystemHandleLike = toFileSystemHandleLike;
|
|
1831
|
+
exports.unzip = unzip;
|
|
1832
|
+
exports.unzipFromUrl = unzipFromUrl;
|
|
1833
|
+
exports.unzipSync = unzipSync;
|
|
1834
|
+
exports.uploadFile = uploadFile;
|
|
1835
|
+
exports.writeFile = writeFile;
|
|
1836
|
+
exports.writeFileSync = writeFileSync;
|
|
1837
|
+
exports.zip = zip;
|
|
1838
|
+
exports.zipFromUrl = zipFromUrl;
|
|
1839
|
+
exports.zipSync = zipSync;
|
|
1840
|
+
//# sourceMappingURL=main.cjs.map
|