vvvfs 0.1.2 → 0.1.3
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 +6 -1
- package/index.html +2 -1
- package/index.ts +151 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,10 +42,12 @@ const vvvfs = new VVVFS("vvvfs", {
|
|
|
42
42
|
(async function () {
|
|
43
43
|
await vvvfs.reset(); // 重置文件系统
|
|
44
44
|
await vvvfs.init("UserName"); // 初始化文件系统
|
|
45
|
-
|
|
45
|
+
vvvfs.watch("/home/user/Desktop/test.txt", (type) => {
|
|
46
46
|
console.log(type); // 打印文件操作的类型
|
|
47
47
|
return true; // 返回true或false,表示是否取消该操作
|
|
48
48
|
});
|
|
49
|
+
await vvvfs.lock("/home/user/Desktop/test.txt"); // 锁定文件,防止其他代码访问该文件
|
|
50
|
+
await vvvfs.unlock("/home/user/Desktop/test.txt"); // 解锁文件
|
|
49
51
|
await vvvfs.createDir("/home/user/Desktop"); // 创建目录,返回true和false
|
|
50
52
|
await vvvfs.writeText("/home/user/Desktop/test.txt", "Hello World!"); // 写入文本文件,写入文件还包括write(path: string, content: Blob)和writeJson(path: string, content: Record<string, any>)方法,返回true和false
|
|
51
53
|
await vvvfs.appendText("/home/user/Desktop/test.txt", "Hello World!"); // 追加文本文件,返回true和false
|
|
@@ -84,6 +86,9 @@ const vvvfs = new VVVFS("vvvfs", {
|
|
|
84
86
|
|
|
85
87
|
## 更新日志
|
|
86
88
|
|
|
89
|
+
### 0.1.3
|
|
90
|
+
- 新增 `lock` 和 `unlock` 方法,可以锁定文件,防止其他代码访问该文件
|
|
91
|
+
|
|
87
92
|
### 0.1.2
|
|
88
93
|
|
|
89
94
|
- 新增 `readChunk` 和 `readChunkText` 方法,用于读取文件块
|
package/index.html
CHANGED
|
@@ -17,13 +17,14 @@
|
|
|
17
17
|
await vvvfs.reset();
|
|
18
18
|
await vvvfs.init("IFTC");
|
|
19
19
|
console.log(vvvfs);
|
|
20
|
-
|
|
20
|
+
vvvfs.watch("/test.txt", (type) => {
|
|
21
21
|
console.log(type);
|
|
22
22
|
// return true;
|
|
23
23
|
});
|
|
24
24
|
console.log("创建文件", await vvvfs.createFile("/test.txt"));
|
|
25
25
|
console.log("写入文件", await vvvfs.writeText("/test.txt", "Hello World"));
|
|
26
26
|
console.log("追加文件", await vvvfs.appendText("/test.txt", " - Appended"));
|
|
27
|
+
// await vvvfs.lock("/test.txt");
|
|
27
28
|
console.log("文件是否存在", await vvvfs.exists("/test.txt"));
|
|
28
29
|
console.log("文件是否存在", await vvvfs.exists("/test2.txt"));
|
|
29
30
|
console.log("读取文件", await vvvfs.readText("/test.txt"));
|
package/index.ts
CHANGED
|
@@ -246,8 +246,23 @@ class VVVFSFile {
|
|
|
246
246
|
async search(query: string) {
|
|
247
247
|
return await this._vvvfs.search(this._path, query);
|
|
248
248
|
}
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
/**
|
|
250
|
+
* 监听文件
|
|
251
|
+
*/
|
|
252
|
+
watch(handler: (type: string) => Promise<boolean>) {
|
|
253
|
+
return this._vvvfs.watch(this._path, handler);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* 锁定文件
|
|
257
|
+
*/
|
|
258
|
+
async lock() {
|
|
259
|
+
return await this._vvvfs.lock(this._path);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* 解锁文件
|
|
263
|
+
*/
|
|
264
|
+
async unlock() {
|
|
265
|
+
return await this._vvvfs.unlock(this._path);
|
|
251
266
|
}
|
|
252
267
|
}
|
|
253
268
|
|
|
@@ -268,6 +283,10 @@ class VVVFS {
|
|
|
268
283
|
* 虚拟文件系统监听器
|
|
269
284
|
*/
|
|
270
285
|
#watchers: Record<string, Array<(type: string) => Promise<boolean>>> = {};
|
|
286
|
+
/**
|
|
287
|
+
* 锁定的文件
|
|
288
|
+
*/
|
|
289
|
+
#lockedFiles: Record<string, boolean> = {};
|
|
271
290
|
/**
|
|
272
291
|
* 创建虚拟文件系统
|
|
273
292
|
* @param name 虚拟文件系统名称
|
|
@@ -575,6 +594,13 @@ class VVVFS {
|
|
|
575
594
|
}
|
|
576
595
|
}
|
|
577
596
|
}
|
|
597
|
+
if (this.#lockedFiles[targetPath]) {
|
|
598
|
+
console.warn("文件已被锁定");
|
|
599
|
+
if (this.options.throwError) {
|
|
600
|
+
throw new VVVFSError("Write", "文件已被锁定");
|
|
601
|
+
}
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
578
604
|
if (!(await this.exists(targetPath))) {
|
|
579
605
|
const success = await this.createFile(targetPath);
|
|
580
606
|
if (!success) {
|
|
@@ -673,6 +699,13 @@ class VVVFS {
|
|
|
673
699
|
}
|
|
674
700
|
}
|
|
675
701
|
}
|
|
702
|
+
if (this.#lockedFiles[targetPath]) {
|
|
703
|
+
console.warn("文件已被锁定");
|
|
704
|
+
if (this.options.throwError) {
|
|
705
|
+
throw new VVVFSError("Append", "文件已被锁定");
|
|
706
|
+
}
|
|
707
|
+
return false;
|
|
708
|
+
}
|
|
676
709
|
const existingFile = await this.read(targetPath);
|
|
677
710
|
if (existingFile) {
|
|
678
711
|
const blob = new Blob([existingFile, content], {
|
|
@@ -724,6 +757,13 @@ class VVVFS {
|
|
|
724
757
|
}
|
|
725
758
|
}
|
|
726
759
|
}
|
|
760
|
+
if (this.#lockedFiles[targetPath]) {
|
|
761
|
+
console.warn("文件已被锁定");
|
|
762
|
+
if (this.options.throwError) {
|
|
763
|
+
throw new VVVFSError("Read", "文件已被锁定");
|
|
764
|
+
}
|
|
765
|
+
return null;
|
|
766
|
+
}
|
|
727
767
|
if (!(await this.exists(targetPath))) {
|
|
728
768
|
console.warn("文件不存在");
|
|
729
769
|
if (this.options.throwError) {
|
|
@@ -812,6 +852,13 @@ class VVVFS {
|
|
|
812
852
|
}
|
|
813
853
|
}
|
|
814
854
|
}
|
|
855
|
+
if (this.#lockedFiles[targetPath]) {
|
|
856
|
+
console.warn("文件已被锁定");
|
|
857
|
+
if (this.options.throwError) {
|
|
858
|
+
throw new VVVFSError("Read", "文件已被锁定");
|
|
859
|
+
}
|
|
860
|
+
return null;
|
|
861
|
+
}
|
|
815
862
|
if (!(await this.exists(targetPath))) {
|
|
816
863
|
console.warn("文件不存在");
|
|
817
864
|
if (this.options.throwError) {
|
|
@@ -901,6 +948,13 @@ class VVVFS {
|
|
|
901
948
|
}
|
|
902
949
|
}
|
|
903
950
|
}
|
|
951
|
+
if (this.#lockedFiles[targetPath]) {
|
|
952
|
+
console.warn("文件已被锁定");
|
|
953
|
+
if (this.options.throwError) {
|
|
954
|
+
throw new VVVFSError("List", "文件已被锁定");
|
|
955
|
+
}
|
|
956
|
+
return [];
|
|
957
|
+
}
|
|
904
958
|
if (!(await this.exists(targetPath))) {
|
|
905
959
|
console.warn("路径不存在");
|
|
906
960
|
if (this.options.throwError) {
|
|
@@ -945,6 +999,13 @@ class VVVFS {
|
|
|
945
999
|
}
|
|
946
1000
|
}
|
|
947
1001
|
}
|
|
1002
|
+
if (this.#lockedFiles[sourcePath]) {
|
|
1003
|
+
console.warn("文件已被锁定");
|
|
1004
|
+
if (this.options.throwError) {
|
|
1005
|
+
throw new VVVFSError("Rename", "文件已被锁定");
|
|
1006
|
+
}
|
|
1007
|
+
return false;
|
|
1008
|
+
}
|
|
948
1009
|
if (!(await this.exists(sourcePath))) {
|
|
949
1010
|
console.warn("文件不存在");
|
|
950
1011
|
if (this.options.throwError) {
|
|
@@ -1014,6 +1075,13 @@ class VVVFS {
|
|
|
1014
1075
|
}
|
|
1015
1076
|
}
|
|
1016
1077
|
}
|
|
1078
|
+
if (this.#lockedFiles[targetPath]) {
|
|
1079
|
+
console.warn("文件已被锁定");
|
|
1080
|
+
if (this.options.throwError) {
|
|
1081
|
+
throw new VVVFSError("Delete", "文件已被锁定");
|
|
1082
|
+
}
|
|
1083
|
+
return false;
|
|
1084
|
+
}
|
|
1017
1085
|
if (!(await this.exists(targetPath))) {
|
|
1018
1086
|
console.warn("文件不存在");
|
|
1019
1087
|
if (this.options.throwError) {
|
|
@@ -1070,6 +1138,13 @@ class VVVFS {
|
|
|
1070
1138
|
}
|
|
1071
1139
|
}
|
|
1072
1140
|
}
|
|
1141
|
+
if (this.#lockedFiles[sourcePath]) {
|
|
1142
|
+
console.warn("文件已被锁定");
|
|
1143
|
+
if (this.options.throwError) {
|
|
1144
|
+
throw new VVVFSError("Move", "文件已被锁定");
|
|
1145
|
+
}
|
|
1146
|
+
return false;
|
|
1147
|
+
}
|
|
1073
1148
|
if (sourcePath === destinationPath) {
|
|
1074
1149
|
return true;
|
|
1075
1150
|
}
|
|
@@ -1147,6 +1222,13 @@ class VVVFS {
|
|
|
1147
1222
|
}
|
|
1148
1223
|
}
|
|
1149
1224
|
}
|
|
1225
|
+
if (this.#lockedFiles[sourcePath]) {
|
|
1226
|
+
console.warn("文件已被锁定");
|
|
1227
|
+
if (this.options.throwError) {
|
|
1228
|
+
throw new VVVFSError("Copy", "文件已被锁定");
|
|
1229
|
+
}
|
|
1230
|
+
return false;
|
|
1231
|
+
}
|
|
1150
1232
|
if (await this.exists(destinationPath)) {
|
|
1151
1233
|
console.warn("目标文件已存在");
|
|
1152
1234
|
if (this.options.throwError) {
|
|
@@ -1250,14 +1332,69 @@ class VVVFS {
|
|
|
1250
1332
|
return null;
|
|
1251
1333
|
}
|
|
1252
1334
|
}
|
|
1253
|
-
|
|
1335
|
+
/**
|
|
1336
|
+
* 监听文件
|
|
1337
|
+
* @param path 文件路径
|
|
1338
|
+
* @param handler 监听器
|
|
1339
|
+
*/
|
|
1340
|
+
watch(path: string, handler: (type: string) => Promise<boolean>) {
|
|
1254
1341
|
path = joinPath(path);
|
|
1255
1342
|
if (!this.#watchers[path]) {
|
|
1256
1343
|
this.#watchers[path] = [];
|
|
1257
1344
|
}
|
|
1258
1345
|
this.#watchers[path].push(handler);
|
|
1259
1346
|
}
|
|
1347
|
+
/**
|
|
1348
|
+
* 锁定文件
|
|
1349
|
+
* @param path 文件路径
|
|
1350
|
+
*/
|
|
1351
|
+
async lock(path: string) {
|
|
1352
|
+
path = joinPath(path);
|
|
1353
|
+
if (!(await this.exists(path))) {
|
|
1354
|
+
console.warn("文件不存在");
|
|
1355
|
+
if (this.options.throwError) {
|
|
1356
|
+
throw new VVVFSError("Lock", "文件不存在");
|
|
1357
|
+
}
|
|
1358
|
+
return false;
|
|
1359
|
+
}
|
|
1360
|
+
if (this.#lockedFiles[path]) {
|
|
1361
|
+
console.warn("文件已被锁定");
|
|
1362
|
+
if (this.options.throwError) {
|
|
1363
|
+
throw new VVVFSError("Lock", "文件已被锁定");
|
|
1364
|
+
}
|
|
1365
|
+
return false;
|
|
1366
|
+
}
|
|
1367
|
+
this.#lockedFiles[path] = true;
|
|
1368
|
+
return true;
|
|
1369
|
+
}
|
|
1370
|
+
/**
|
|
1371
|
+
* 解锁文件
|
|
1372
|
+
* @param path 文件路径
|
|
1373
|
+
*/
|
|
1374
|
+
async unlock(path: string) {
|
|
1375
|
+
path = joinPath(path);
|
|
1376
|
+
if (!(await this.exists(path))) {
|
|
1377
|
+
console.warn("文件不存在");
|
|
1378
|
+
if (this.options.throwError) {
|
|
1379
|
+
throw new VVVFSError("Unlock", "文件不存在");
|
|
1380
|
+
}
|
|
1381
|
+
return false;
|
|
1382
|
+
}
|
|
1383
|
+
if (!this.#lockedFiles[path]) {
|
|
1384
|
+
console.warn("文件未被锁定");
|
|
1385
|
+
if (this.options.throwError) {
|
|
1386
|
+
throw new VVVFSError("Unlock", "文件未被锁定");
|
|
1387
|
+
}
|
|
1388
|
+
return false;
|
|
1389
|
+
}
|
|
1390
|
+
delete this.#lockedFiles[path];
|
|
1391
|
+
return true;
|
|
1392
|
+
}
|
|
1260
1393
|
}
|
|
1394
|
+
/**
|
|
1395
|
+
* 解析路径
|
|
1396
|
+
* @param path 路径
|
|
1397
|
+
*/
|
|
1261
1398
|
function parsePath(path: string) {
|
|
1262
1399
|
path = joinPath(path);
|
|
1263
1400
|
const oldParts = path.split("/");
|
|
@@ -1271,6 +1408,11 @@ function parsePath(path: string) {
|
|
|
1271
1408
|
if (joinPath(parent, name).length > 4096) throw new VVVFSError("ParsePath", "文件路径过长");
|
|
1272
1409
|
return { name, parent };
|
|
1273
1410
|
}
|
|
1411
|
+
|
|
1412
|
+
/**
|
|
1413
|
+
* 合并路径
|
|
1414
|
+
* @param paths 路径
|
|
1415
|
+
*/
|
|
1274
1416
|
function joinPath(...paths: string[]) {
|
|
1275
1417
|
const segments = paths.map((p) => String(p)).filter((p) => p.length > 0);
|
|
1276
1418
|
if (segments.length === 0) return ".";
|
|
@@ -1302,4 +1444,10 @@ Object.defineProperty(VVVFS, "version", {
|
|
|
1302
1444
|
enumerable: true,
|
|
1303
1445
|
configurable: false,
|
|
1304
1446
|
});
|
|
1447
|
+
Object.defineProperty(VVVFS, "author", {
|
|
1448
|
+
value: "IFTC",
|
|
1449
|
+
writable: false,
|
|
1450
|
+
enumerable: true,
|
|
1451
|
+
configurable: false,
|
|
1452
|
+
});
|
|
1305
1453
|
(globalThis as any).VVVFS = VVVFS;
|