vvvfs 0.0.6 → 0.0.7
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/README.md +4 -0
- package/index.html +1 -0
- package/index.ts +141 -65
- package/package.json +1 -1
package/README.md
CHANGED
package/index.html
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
console.log("移动文件", await vvvfs.move("/test2.txt", "/test3.txt"));
|
|
27
27
|
console.log("删除文件", await vvvfs.delete("/test.txt"));
|
|
28
28
|
const file = new VVVFS.File("test.txt");
|
|
29
|
+
console.log("写入文件", await file.writeText("Hello World"));
|
|
29
30
|
} catch (error) {
|
|
30
31
|
console.error(error);
|
|
31
32
|
}
|
package/index.ts
CHANGED
|
@@ -409,22 +409,22 @@ class VVVFS {
|
|
|
409
409
|
* @param path 文件路径
|
|
410
410
|
*/
|
|
411
411
|
async createFile(path: string) {
|
|
412
|
-
|
|
412
|
+
const targetPath = joinPath(path);
|
|
413
|
+
if (await this.exists(targetPath)) {
|
|
413
414
|
console.warn("文件已存在");
|
|
414
415
|
return true;
|
|
415
416
|
}
|
|
416
417
|
try {
|
|
417
|
-
const { name, parent } = parsePath(
|
|
418
|
+
const { name, parent } = parsePath(targetPath);
|
|
418
419
|
if (!(await this.exists(parent))) {
|
|
419
420
|
await this.createDir(parent);
|
|
420
421
|
}
|
|
421
|
-
// console.log(name, parent);
|
|
422
422
|
await this.db.files.add({
|
|
423
423
|
name: name,
|
|
424
424
|
path: parent,
|
|
425
425
|
type: "file",
|
|
426
426
|
file: new File([], name, {
|
|
427
|
-
type: mime.getType(
|
|
427
|
+
type: mime.getType(targetPath) || "application/octet-stream",
|
|
428
428
|
}),
|
|
429
429
|
});
|
|
430
430
|
return true;
|
|
@@ -441,12 +441,13 @@ class VVVFS {
|
|
|
441
441
|
* @param path 目录路径
|
|
442
442
|
*/
|
|
443
443
|
async createDir(path: string) {
|
|
444
|
-
|
|
444
|
+
const targetPath = joinPath(path);
|
|
445
|
+
if (await this.exists(targetPath)) {
|
|
445
446
|
console.warn("目录已存在");
|
|
446
447
|
return true;
|
|
447
448
|
}
|
|
448
449
|
try {
|
|
449
|
-
const { name, parent } = parsePath(
|
|
450
|
+
const { name, parent } = parsePath(targetPath);
|
|
450
451
|
if (!(await this.exists(parent))) {
|
|
451
452
|
if (parent == "/") {
|
|
452
453
|
await this.db.files.add({
|
|
@@ -460,7 +461,6 @@ class VVVFS {
|
|
|
460
461
|
await this.createDir(parent);
|
|
461
462
|
}
|
|
462
463
|
}
|
|
463
|
-
console.log(name, parent);
|
|
464
464
|
await this.db.files.add({
|
|
465
465
|
name: name,
|
|
466
466
|
path: parent,
|
|
@@ -482,7 +482,8 @@ class VVVFS {
|
|
|
482
482
|
*/
|
|
483
483
|
async exists(path: string) {
|
|
484
484
|
try {
|
|
485
|
-
const
|
|
485
|
+
const targetPath = joinPath(path);
|
|
486
|
+
const { name, parent } = parsePath(targetPath);
|
|
486
487
|
return (
|
|
487
488
|
(await this.db.files
|
|
488
489
|
.where({
|
|
@@ -505,8 +506,9 @@ class VVVFS {
|
|
|
505
506
|
*/
|
|
506
507
|
async write(path: string, content: Blob) {
|
|
507
508
|
try {
|
|
508
|
-
|
|
509
|
-
|
|
509
|
+
const targetPath = joinPath(path);
|
|
510
|
+
if (!(await this.exists(targetPath))) {
|
|
511
|
+
const success = await this.createFile(targetPath);
|
|
510
512
|
if (!success) {
|
|
511
513
|
console.warn("创建文件失败");
|
|
512
514
|
if (this.options.throwError) {
|
|
@@ -515,19 +517,17 @@ class VVVFS {
|
|
|
515
517
|
return false;
|
|
516
518
|
}
|
|
517
519
|
}
|
|
518
|
-
|
|
519
|
-
console.log(name, parent);
|
|
520
|
-
if (await this.isDir(parent + "/" + name)) {
|
|
520
|
+
if (await this.isDir(targetPath)) {
|
|
521
521
|
console.warn("路径已存在");
|
|
522
522
|
if (this.options.throwError) {
|
|
523
523
|
throw new VVVFSError("Write", "路径已存在");
|
|
524
524
|
}
|
|
525
525
|
return false;
|
|
526
526
|
}
|
|
527
|
+
const { name, parent } = parsePath(targetPath);
|
|
527
528
|
const file = new File([content], name, {
|
|
528
|
-
type: mime.getType(
|
|
529
|
+
type: mime.getType(targetPath) || "application/octet-stream",
|
|
529
530
|
});
|
|
530
|
-
console.log(file);
|
|
531
531
|
const fileRecord = await this.db.files.where({ name, path: parent }).first();
|
|
532
532
|
if (fileRecord) {
|
|
533
533
|
await this.db.files.put({
|
|
@@ -593,14 +593,15 @@ class VVVFS {
|
|
|
593
593
|
*/
|
|
594
594
|
async read(path: string) {
|
|
595
595
|
try {
|
|
596
|
-
|
|
596
|
+
const targetPath = joinPath(path);
|
|
597
|
+
if (!(await this.exists(targetPath))) {
|
|
597
598
|
console.warn("文件不存在");
|
|
598
599
|
if (this.options.throwError) {
|
|
599
600
|
throw new VVVFSError("Read", "文件不存在");
|
|
600
601
|
}
|
|
601
602
|
return null;
|
|
602
603
|
}
|
|
603
|
-
const { name, parent } = parsePath(
|
|
604
|
+
const { name, parent } = parsePath(targetPath);
|
|
604
605
|
return (await this.db.files.where({ name, path: parent }).first())?.file;
|
|
605
606
|
} catch (error) {
|
|
606
607
|
console.error("读取文件失败", error);
|
|
@@ -668,7 +669,8 @@ class VVVFS {
|
|
|
668
669
|
*/
|
|
669
670
|
async isFile(path: string) {
|
|
670
671
|
try {
|
|
671
|
-
const
|
|
672
|
+
const targetPath = joinPath(path);
|
|
673
|
+
const { name, parent } = parsePath(targetPath);
|
|
672
674
|
return (await this.db.files.where({ name, path: parent, type: "file" }).count()) > 0;
|
|
673
675
|
} catch (error) {
|
|
674
676
|
console.error("判断文件类型失败", error);
|
|
@@ -684,7 +686,8 @@ class VVVFS {
|
|
|
684
686
|
*/
|
|
685
687
|
async isDir(path: string) {
|
|
686
688
|
try {
|
|
687
|
-
const
|
|
689
|
+
const targetPath = joinPath(path);
|
|
690
|
+
const { name, parent } = parsePath(targetPath);
|
|
688
691
|
return (await this.db.files.where({ path: parent, name, type: "dir" }).count()) > 0;
|
|
689
692
|
} catch (error) {
|
|
690
693
|
console.error("判断文件类型失败", error);
|
|
@@ -700,8 +703,15 @@ class VVVFS {
|
|
|
700
703
|
*/
|
|
701
704
|
async list(path: string) {
|
|
702
705
|
try {
|
|
703
|
-
const
|
|
704
|
-
|
|
706
|
+
const targetPath = joinPath(path);
|
|
707
|
+
if (!(await this.isDir(targetPath))) {
|
|
708
|
+
console.warn("路径不是目录");
|
|
709
|
+
if (this.options.throwError) {
|
|
710
|
+
throw new VVVFSError("List", "路径不是目录");
|
|
711
|
+
}
|
|
712
|
+
return [];
|
|
713
|
+
}
|
|
714
|
+
return (await this.db.files.where({ path: targetPath }).toArray())
|
|
705
715
|
.map((file) => file.name)
|
|
706
716
|
.filter((item) => item != "");
|
|
707
717
|
} catch (error) {
|
|
@@ -719,20 +729,50 @@ class VVVFS {
|
|
|
719
729
|
*/
|
|
720
730
|
async rename(path: string, newName: string) {
|
|
721
731
|
try {
|
|
722
|
-
|
|
732
|
+
const sourcePath = joinPath(path);
|
|
733
|
+
const { name, parent } = parsePath(sourcePath);
|
|
734
|
+
if (!(await this.exists(sourcePath))) {
|
|
723
735
|
console.warn("文件不存在");
|
|
724
736
|
if (this.options.throwError) {
|
|
725
737
|
throw new VVVFSError("Rename", "文件不存在");
|
|
726
738
|
}
|
|
727
739
|
return false;
|
|
728
740
|
}
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
741
|
+
const newPath = joinPath(parent, newName);
|
|
742
|
+
if (newPath === sourcePath) {
|
|
743
|
+
return true;
|
|
744
|
+
}
|
|
745
|
+
if (await this.exists(newPath)) {
|
|
746
|
+
console.warn("目标文件已存在");
|
|
747
|
+
if (this.options.throwError) {
|
|
748
|
+
throw new VVVFSError("Rename", "目标文件已存在");
|
|
749
|
+
}
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
const fileRecord = await this.db.files.where({ path: parent, name }).first();
|
|
753
|
+
if (!fileRecord) {
|
|
754
|
+
console.warn("文件记录未找到");
|
|
755
|
+
if (this.options.throwError) {
|
|
756
|
+
throw new VVVFSError("Rename", "文件记录未找到");
|
|
757
|
+
}
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
if (fileRecord.type === "dir") {
|
|
761
|
+
const descendants = await this.db.files
|
|
762
|
+
.filter(
|
|
763
|
+
(file) =>
|
|
764
|
+
file.path === sourcePath || file.path.startsWith(sourcePath + "/"),
|
|
765
|
+
)
|
|
766
|
+
.toArray();
|
|
767
|
+
for (const descendant of descendants) {
|
|
768
|
+
const relativePath = descendant.path.slice(sourcePath.length);
|
|
769
|
+
const updatedPath = joinPath(newPath + relativePath);
|
|
770
|
+
await this.db.files.update(descendant.id!, { path: updatedPath });
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
await this.db.files.update(fileRecord.id!, {
|
|
732
774
|
name: newName,
|
|
733
775
|
path: parent,
|
|
734
|
-
type: "file",
|
|
735
|
-
file: file!.file,
|
|
736
776
|
});
|
|
737
777
|
return true;
|
|
738
778
|
} catch (e) {
|
|
@@ -749,29 +789,30 @@ class VVVFS {
|
|
|
749
789
|
*/
|
|
750
790
|
async delete(path: string) {
|
|
751
791
|
try {
|
|
752
|
-
|
|
792
|
+
const targetPath = joinPath(path);
|
|
793
|
+
if (!(await this.exists(targetPath))) {
|
|
753
794
|
console.warn("文件不存在");
|
|
754
795
|
if (this.options.throwError) {
|
|
755
796
|
throw new VVVFSError("Delete", "文件不存在");
|
|
756
797
|
}
|
|
757
798
|
return false;
|
|
758
799
|
}
|
|
759
|
-
const { name, parent } = parsePath(
|
|
760
|
-
if (await this.isDir(
|
|
761
|
-
const files = await this.list(
|
|
800
|
+
const { name, parent } = parsePath(targetPath);
|
|
801
|
+
if (await this.isDir(targetPath)) {
|
|
802
|
+
const files = await this.list(targetPath);
|
|
762
803
|
for (const file of files) {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
}
|
|
769
|
-
await this.delete(joinPath(parent, file));
|
|
804
|
+
await this.delete(joinPath(targetPath, file));
|
|
805
|
+
}
|
|
806
|
+
const dirRecord = await this.db.files.where({ name, path: parent, type: "dir" }).first();
|
|
807
|
+
if (dirRecord) {
|
|
808
|
+
await this.db.files.delete(dirRecord.id!);
|
|
770
809
|
}
|
|
771
810
|
return true;
|
|
772
811
|
} else {
|
|
773
|
-
const fileRecord = await this.db.files.where({ name, path: parent }).first();
|
|
774
|
-
|
|
812
|
+
const fileRecord = await this.db.files.where({ name, path: parent, type: "file" }).first();
|
|
813
|
+
if (fileRecord) {
|
|
814
|
+
await this.db.files.delete(fileRecord.id!);
|
|
815
|
+
}
|
|
775
816
|
return true;
|
|
776
817
|
}
|
|
777
818
|
} catch (e) {
|
|
@@ -789,34 +830,51 @@ class VVVFS {
|
|
|
789
830
|
*/
|
|
790
831
|
async move(path: string, newPath: string) {
|
|
791
832
|
try {
|
|
792
|
-
|
|
833
|
+
const sourcePath = joinPath(path);
|
|
834
|
+
const destinationPath = joinPath(newPath);
|
|
835
|
+
if (await this.exists(destinationPath)) {
|
|
793
836
|
console.warn("目标文件已存在");
|
|
794
837
|
if (this.options.throwError) {
|
|
795
838
|
throw new VVVFSError("Move", "目标文件已存在");
|
|
796
839
|
}
|
|
797
840
|
return false;
|
|
798
841
|
}
|
|
799
|
-
if (!(await this.exists(
|
|
842
|
+
if (!(await this.exists(sourcePath))) {
|
|
800
843
|
console.warn("源文件不存在");
|
|
801
844
|
if (this.options.throwError) {
|
|
802
845
|
throw new VVVFSError("Move", "源文件不存在");
|
|
803
846
|
}
|
|
804
847
|
return false;
|
|
805
848
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
849
|
+
if (destinationPath.startsWith(sourcePath + "/")) {
|
|
850
|
+
console.warn("目标路径是源路径的子路径");
|
|
851
|
+
if (this.options.throwError) {
|
|
852
|
+
throw new VVVFSError("Move", "目标路径是源路径的子路径");
|
|
853
|
+
}
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
const { name, parent } = parsePath(sourcePath);
|
|
857
|
+
const { name: newName, parent: newParent } = parsePath(destinationPath);
|
|
858
|
+
if (await this.isDir(sourcePath)) {
|
|
859
|
+
await this.createDir(destinationPath);
|
|
860
|
+
const children = await this.list(sourcePath);
|
|
861
|
+
for (const child of children) {
|
|
862
|
+
await this.move(joinPath(sourcePath, child), joinPath(destinationPath, child));
|
|
863
|
+
}
|
|
864
|
+
const dirRecord = await this.db.files.where({ name, path: parent, type: "dir" }).first();
|
|
865
|
+
if (dirRecord) {
|
|
866
|
+
await this.db.files.delete(dirRecord.id!);
|
|
813
867
|
}
|
|
868
|
+
return true;
|
|
814
869
|
} else {
|
|
815
|
-
|
|
816
|
-
await this.db.files.
|
|
870
|
+
await this.createDir(newParent);
|
|
871
|
+
const fileRecord = await this.db.files.where({ name, path: parent, type: "file" }).first();
|
|
872
|
+
if (fileRecord) {
|
|
873
|
+
await this.db.files.update(fileRecord.id!, { name: newName, path: newParent });
|
|
874
|
+
return true;
|
|
875
|
+
}
|
|
876
|
+
return false;
|
|
817
877
|
}
|
|
818
|
-
await this.delete(path);
|
|
819
|
-
return true;
|
|
820
878
|
} catch (e) {
|
|
821
879
|
console.error(e);
|
|
822
880
|
if (this.options.throwError) {
|
|
@@ -832,33 +890,51 @@ class VVVFS {
|
|
|
832
890
|
*/
|
|
833
891
|
async copy(path: string, newPath: string) {
|
|
834
892
|
try {
|
|
835
|
-
|
|
893
|
+
const sourcePath = joinPath(path);
|
|
894
|
+
const destinationPath = joinPath(newPath);
|
|
895
|
+
if (await this.exists(destinationPath)) {
|
|
836
896
|
console.warn("目标文件已存在");
|
|
837
897
|
if (this.options.throwError) {
|
|
838
898
|
throw new VVVFSError("Copy", "目标文件已存在");
|
|
839
899
|
}
|
|
840
900
|
return false;
|
|
841
901
|
}
|
|
842
|
-
if (!(await this.exists(
|
|
902
|
+
if (!(await this.exists(sourcePath))) {
|
|
843
903
|
console.warn("源文件不存在");
|
|
844
904
|
if (this.options.throwError) {
|
|
845
905
|
throw new VVVFSError("Copy", "源文件不存在");
|
|
846
906
|
}
|
|
847
907
|
return false;
|
|
848
908
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
const dirs = await this.list(path);
|
|
854
|
-
for (const dir of dirs) {
|
|
855
|
-
await this.move(path + "/" + dir, newPath + "/" + dir);
|
|
909
|
+
if (destinationPath.startsWith(sourcePath + "/")) {
|
|
910
|
+
console.warn("目标路径是源路径的子路径");
|
|
911
|
+
if (this.options.throwError) {
|
|
912
|
+
throw new VVVFSError("Copy", "目标路径是源路径的子路径");
|
|
856
913
|
}
|
|
914
|
+
return false;
|
|
915
|
+
}
|
|
916
|
+
const { name, parent } = parsePath(sourcePath);
|
|
917
|
+
const { name: newName, parent: newParent } = parsePath(destinationPath);
|
|
918
|
+
if (await this.isDir(sourcePath)) {
|
|
919
|
+
await this.createDir(destinationPath);
|
|
920
|
+
const children = await this.list(sourcePath);
|
|
921
|
+
for (const child of children) {
|
|
922
|
+
await this.copy(joinPath(sourcePath, child), joinPath(destinationPath, child));
|
|
923
|
+
}
|
|
924
|
+
return true;
|
|
857
925
|
} else {
|
|
858
|
-
const fileRecord = await this.db.files.where({ name, path: parent }).first();
|
|
859
|
-
|
|
926
|
+
const fileRecord = await this.db.files.where({ name, path: parent, type: "file" }).first();
|
|
927
|
+
if (fileRecord) {
|
|
928
|
+
await this.db.files.add({
|
|
929
|
+
name: newName,
|
|
930
|
+
path: newParent,
|
|
931
|
+
type: fileRecord.type,
|
|
932
|
+
file: fileRecord.file,
|
|
933
|
+
});
|
|
934
|
+
return true;
|
|
935
|
+
}
|
|
936
|
+
return false;
|
|
860
937
|
}
|
|
861
|
-
return true;
|
|
862
938
|
} catch (e) {
|
|
863
939
|
console.error(e);
|
|
864
940
|
if (this.options.throwError) {
|