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