vvvfs 0.0.8 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +10 -1
  2. package/index.html +2 -0
  3. package/index.ts +120 -65
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -44,6 +44,7 @@ const vvvfs = new VVVFS("vvvfs", {
44
44
  await vvvfs.init("UserName"); // 初始化文件系统
45
45
  await vvvfs.watch("/home/user/Desktop/test.txt", (type) => {
46
46
  console.log(type); // 打印文件操作的类型
47
+ return true; // 返回true或false,表示是否取消该操作
47
48
  });
48
49
  await vvvfs.createDir("/home/user/Desktop"); // 创建目录,返回true和false
49
50
  await vvvfs.writeText("/home/user/Desktop/test.txt", "Hello World!"); // 写入文本文件,写入文件还包括write(path: string, content: Blob)和writeJson(path: string, content: Record<string, any>)方法,返回true和false
@@ -81,9 +82,17 @@ const vvvfs = new VVVFS("vvvfs", {
81
82
 
82
83
  ## 更新日志
83
84
 
85
+ ### 0.1.0
86
+
87
+ - 修复 `init` 重复初始化时重复写入已存在文件和目录
88
+
89
+ ### 0.0.9
90
+
91
+ - 更新 `watch` 方法,监听时,返回 `true` 表示取消该操作
92
+
84
93
  ### 0.0.8
85
94
 
86
- - 新增 `watch` 方法
95
+ - 新增 `watch` 方法 (该方法属于实验性功能,后期可能会改变)
87
96
 
88
97
  ### 0.0.7
89
98
 
package/index.html CHANGED
@@ -13,11 +13,13 @@
13
13
  (async () => {
14
14
  try {
15
15
  globalThis.vvvfs = new VVVFS();
16
+ vvvfs.options.throwError = true;
16
17
  await vvvfs.reset();
17
18
  await vvvfs.init("IFTC");
18
19
  console.log(vvvfs);
19
20
  await vvvfs.watch("/test.txt", (type) => {
20
21
  console.log(type);
22
+ // return true;
21
23
  });
22
24
  console.log("创建文件", await vvvfs.createFile("/test.txt"));
23
25
  console.log("写入文件", await vvvfs.writeText("/test.txt", "Hello World"));
package/index.ts CHANGED
@@ -216,7 +216,7 @@ class VVVFSFile {
216
216
  async search(query: string) {
217
217
  return await this._vvvfs.search(this._path, query);
218
218
  }
219
- async watch(handler: (type: string) => void) {
219
+ async watch(handler: (type: string) => Promise<boolean>) {
220
220
  return await this._vvvfs.watch(this._path, handler);
221
221
  }
222
222
  }
@@ -234,6 +234,10 @@ class VVVFS {
234
234
  * 虚拟文件系统文件类
235
235
  */
236
236
  static File = VVVFSFile;
237
+ /**
238
+ * 虚拟文件系统监听器
239
+ */
240
+ watchers: Record<string, Array<(type: string) => Promise<boolean>>> = {};
237
241
  /**
238
242
  * 创建虚拟文件系统
239
243
  * @param name 虚拟文件系统名称
@@ -385,6 +389,7 @@ class VVVFS {
385
389
  ];
386
390
  try {
387
391
  for (const file of linuxInitFiles) {
392
+ if (await this.exists(file.path)) continue;
388
393
  await this.db.files.put(file);
389
394
  }
390
395
  } catch (error) {
@@ -413,11 +418,21 @@ class VVVFS {
413
418
  */
414
419
  async createFile(path: string) {
415
420
  const targetPath = joinPath(path);
416
- if (await this.exists(targetPath)) {
417
- console.warn("文件已存在");
418
- return true;
419
- }
420
421
  try {
422
+ if (this.watchers[targetPath]) {
423
+ for (const handler of this.watchers[targetPath]) {
424
+ if (await handler("create")) {
425
+ if (this.options.throwError) {
426
+ throw new VVVFSError("CreateFile", "创建文件失败:监听器取消了操作");
427
+ }
428
+ return false;
429
+ }
430
+ }
431
+ }
432
+ if (await this.exists(targetPath)) {
433
+ console.warn("文件已存在");
434
+ return true;
435
+ }
421
436
  const { name, parent } = parsePath(targetPath);
422
437
  if (!(await this.exists(parent))) {
423
438
  await this.createDir(parent);
@@ -445,11 +460,21 @@ class VVVFS {
445
460
  */
446
461
  async createDir(path: string) {
447
462
  const targetPath = joinPath(path);
448
- if (await this.exists(targetPath)) {
449
- console.warn("目录已存在");
450
- return true;
451
- }
452
463
  try {
464
+ if (this.watchers[targetPath]) {
465
+ for (const handler of this.watchers[targetPath]) {
466
+ if (await handler("create")) {
467
+ if (this.options.throwError) {
468
+ throw new VVVFSError("CreateDir", "创建目录失败:监听器取消了操作");
469
+ }
470
+ return false;
471
+ }
472
+ }
473
+ }
474
+ if (await this.exists(targetPath)) {
475
+ console.warn("目录已存在");
476
+ return true;
477
+ }
453
478
  const { name, parent } = parsePath(targetPath);
454
479
  if (!(await this.exists(parent))) {
455
480
  if (parent == "/") {
@@ -510,6 +535,16 @@ class VVVFS {
510
535
  async write(path: string, content: Blob) {
511
536
  try {
512
537
  const targetPath = joinPath(path);
538
+ if (this.watchers[targetPath]) {
539
+ for (const handler of this.watchers[targetPath]) {
540
+ if (await handler("write")) {
541
+ if (this.options.throwError) {
542
+ throw new VVVFSError("Write", "写入文件失败:监听器取消了操作");
543
+ }
544
+ return false;
545
+ }
546
+ }
547
+ }
513
548
  if (!(await this.exists(targetPath))) {
514
549
  const success = await this.createFile(targetPath);
515
550
  if (!success) {
@@ -597,6 +632,16 @@ class VVVFS {
597
632
  async read(path: string) {
598
633
  try {
599
634
  const targetPath = joinPath(path);
635
+ if (this.watchers[targetPath]) {
636
+ for (const handler of this.watchers[targetPath]) {
637
+ if (await handler("read")) {
638
+ if (this.options.throwError) {
639
+ throw new VVVFSError("Read", "读取文件失败:监听器取消了操作");
640
+ }
641
+ return null;
642
+ }
643
+ }
644
+ }
600
645
  if (!(await this.exists(targetPath))) {
601
646
  console.warn("文件不存在");
602
647
  if (this.options.throwError) {
@@ -707,6 +752,23 @@ class VVVFS {
707
752
  async list(path: string) {
708
753
  try {
709
754
  const targetPath = joinPath(path);
755
+ if (this.watchers[targetPath]) {
756
+ for (const handler of this.watchers[targetPath]) {
757
+ if (await handler("list")) {
758
+ if (this.options.throwError) {
759
+ throw new VVVFSError("List", "列出目录下的文件失败:监听器取消了操作");
760
+ }
761
+ return [];
762
+ }
763
+ }
764
+ }
765
+ if (!(await this.exists(targetPath))) {
766
+ console.warn("路径不存在");
767
+ if (this.options.throwError) {
768
+ throw new VVVFSError("List", "路径不存在");
769
+ }
770
+ return [];
771
+ }
710
772
  if (!(await this.isDir(targetPath))) {
711
773
  console.warn("路径不是目录");
712
774
  if (this.options.throwError) {
@@ -734,6 +796,16 @@ class VVVFS {
734
796
  try {
735
797
  const sourcePath = joinPath(path);
736
798
  const { name, parent } = parsePath(sourcePath);
799
+ if (this.watchers[sourcePath]) {
800
+ for (const handler of this.watchers[sourcePath]) {
801
+ if (await handler("rename")) {
802
+ if (this.options.throwError) {
803
+ throw new VVVFSError("Rename", "重命名文件失败:监听器取消了操作");
804
+ }
805
+ return false;
806
+ }
807
+ }
808
+ }
737
809
  if (!(await this.exists(sourcePath))) {
738
810
  console.warn("文件不存在");
739
811
  if (this.options.throwError) {
@@ -793,6 +865,16 @@ class VVVFS {
793
865
  async delete(path: string) {
794
866
  try {
795
867
  const targetPath = joinPath(path);
868
+ if (this.watchers[targetPath]) {
869
+ for (const handler of this.watchers[targetPath]) {
870
+ if (await handler("delete")) {
871
+ if (this.options.throwError) {
872
+ throw new VVVFSError("Delete", "删除文件失败:监听器取消了操作");
873
+ }
874
+ return false;
875
+ }
876
+ }
877
+ }
796
878
  if (!(await this.exists(targetPath))) {
797
879
  console.warn("文件不存在");
798
880
  if (this.options.throwError) {
@@ -839,6 +921,19 @@ class VVVFS {
839
921
  try {
840
922
  const sourcePath = joinPath(path);
841
923
  const destinationPath = joinPath(newPath);
924
+ if (this.watchers[sourcePath]) {
925
+ for (const handler of this.watchers[sourcePath]) {
926
+ if (await handler("move")) {
927
+ if (this.options.throwError) {
928
+ throw new VVVFSError("Move", "移动文件失败:监听器取消了操作");
929
+ }
930
+ return false;
931
+ }
932
+ }
933
+ }
934
+ if (sourcePath === destinationPath) {
935
+ return true;
936
+ }
842
937
  if (await this.exists(destinationPath)) {
843
938
  console.warn("目标文件已存在");
844
939
  if (this.options.throwError) {
@@ -903,6 +998,16 @@ class VVVFS {
903
998
  try {
904
999
  const sourcePath = joinPath(path);
905
1000
  const destinationPath = joinPath(newPath);
1001
+ if (this.watchers[sourcePath]) {
1002
+ for (const handler of this.watchers[sourcePath]) {
1003
+ if (await handler("copy")) {
1004
+ if (this.options.throwError) {
1005
+ throw new VVVFSError("Copy", "复制文件失败:监听器取消了操作");
1006
+ }
1007
+ return false;
1008
+ }
1009
+ }
1010
+ }
906
1011
  if (await this.exists(destinationPath)) {
907
1012
  console.warn("目标文件已存在");
908
1013
  if (this.options.throwError) {
@@ -1006,62 +1111,12 @@ class VVVFS {
1006
1111
  return null;
1007
1112
  }
1008
1113
  }
1009
- async watch(path: string, handler: (type: string) => void) {
1010
- const targetPath = joinPath(path);
1011
-
1012
- const getState = async () => {
1013
- const exists = await this.exists(targetPath);
1014
- if (!exists) {
1015
- return { exists: false, signature: "" };
1016
- }
1017
- if (await this.isDir(targetPath)) {
1018
- const records = await this.db.files
1019
- .filter(
1020
- (file) =>
1021
- file.path === targetPath || file.path.startsWith(targetPath + "/"),
1022
- )
1023
- .toArray();
1024
- const signature = records
1025
- .map((file) => {
1026
- const fullPath = joinPath(file.path, file.name);
1027
- const fileInfo = file.file
1028
- ? `${file.file.type}:${file.file.size}:${file.file.lastModified}`
1029
- : "null";
1030
- return `${fullPath}:${file.type}:${fileInfo}`;
1031
- })
1032
- .sort()
1033
- .join("|");
1034
- return { exists: true, signature };
1035
- }
1036
- const { name, parent } = parsePath(targetPath);
1037
- const record = await this.db.files.where({ name, path: parent, type: "file" }).first();
1038
- const signature = record?.file
1039
- ? `${record.file.type}:${record.file.size}:${record.file.lastModified}`
1040
- : "";
1041
- return { exists: true, signature };
1042
- };
1043
-
1044
- let previousState = await getState();
1045
- setInterval(async () => {
1046
- try {
1047
- const currentState = await getState();
1048
- if (
1049
- previousState.exists !== currentState.exists ||
1050
- previousState.signature !== currentState.signature
1051
- ) {
1052
- if (!previousState.exists && currentState.exists) {
1053
- handler("create");
1054
- } else if (previousState.exists && !currentState.exists) {
1055
- handler("unlink");
1056
- } else {
1057
- handler("change");
1058
- }
1059
- previousState = currentState;
1060
- }
1061
- } catch (error) {
1062
- console.error("监听失败", error);
1063
- }
1064
- });
1114
+ async watch(path: string, handler: (type: string) => Promise<boolean>) {
1115
+ path = joinPath(path);
1116
+ if (!this.watchers[path]) {
1117
+ this.watchers[path] = [];
1118
+ }
1119
+ this.watchers[path].push(handler);
1065
1120
  }
1066
1121
  }
1067
1122
  function parsePath(path: string) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vvvfs",
3
- "version": "0.0.8",
3
+ "version": "0.1.0",
4
4
  "description": "一个使用IndexDB实现的虚拟文件系统",
5
5
  "keywords": [
6
6
  "Virtual",