vvvfs 0.0.1-alpha.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.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # VVVFS
2
+
3
+ 一个使用Dexie.js,基于IndexedDB的Linux虚拟文件系统
4
+
5
+ ## 快速开始
6
+
7
+ 1. 安装依赖
8
+
9
+ ```bash
10
+ npm install vvvfs
11
+ ```
12
+
13
+ 2. 引入
14
+
15
+ ```javascript
16
+ import VVVFS from "vvvfs"; // ES6
17
+ ```
18
+
19
+ ```javascript
20
+ const VVVFS = require("vvvfs"); // CommonJS
21
+ ```
22
+
23
+ ```html
24
+ <script src="dist/vvvfs.min.js"></script>
25
+ <!-- 浏览器 -->
26
+ ```
27
+
28
+ 3. 初始化
29
+
30
+ ```javascript
31
+ const vvvfs = new VVFS("vvvfs"); // 创建一个名为vvfs的虚拟文件系统
32
+ ```
33
+
34
+ 4. 使用
35
+
36
+ ```javascript
37
+ // 所有操作都是异步的
38
+ (async function () {
39
+ await vvvfs.reset(); // 重置文件系统
40
+ await vvvfs.mkdir("/home/user/Desktop"); // 创建目录
41
+ await vvvfs.write(
42
+ "/home/user/Desktop/test.txt",
43
+ new File(["Hello World!"], "test.txt", { type: "text/plain" }),
44
+ ); // 写入文件
45
+ console.log(await vvvfs.read("/home/user/Desktop/test.txt")); // 读取文件
46
+ await vvvfs.delete("/home/user/Desktop/test.txt"); // 删除文件
47
+ if (await vvvfs.exists("/home/user/Desktop")) {
48
+ // 判断目录是否存在
49
+ }
50
+ console.log(await vvvfs.list("/home/user/Desktop")); // 列出目录下的文件
51
+ if (await vvvfs.isDirectory("/home/user/Desktop")) {
52
+ // 判断是否为目录
53
+ }
54
+ if (await vvvfs.isFile("/home/user/Desktop/test.txt")) {
55
+ // 判断是否为文件
56
+ }
57
+ await vvvfs.rename(
58
+ "/home/user/Desktop/test.txt",
59
+ "/home/user/Desktop/test2.txt",
60
+ ); // 重命名文件
61
+ await vvvfs.move(
62
+ "/home/user/Desktop/test2.txt",
63
+ "/home/user/Desktop/test.txt",
64
+ ); // 移动文件
65
+ await vvvfs.copy(
66
+ "/home/user/Desktop/test.txt",
67
+ "/home/user/Desktop/test2.txt",
68
+ ); // 复制文件
69
+ await vvvfs.chmod("/home/user/Desktop/test.txt", 0o777); // 修改文件权限
70
+ await vvvfs.chown("/home/user/Desktop/test.txt", "root", "root"); // 修改文件所有者
71
+ })();
72
+ ```
@@ -0,0 +1,13 @@
1
+ const esbuild = require('esbuild');
2
+
3
+ esbuild.build({
4
+ entryPoints: ['index.js'],
5
+ bundle: true,
6
+ outfile: 'dist/vvvfs.min.js',
7
+ format: 'cjs',
8
+ minify: true,
9
+ platform: 'browser',
10
+ target: ["chrome80", "firefox70", "safari13", "edge80"],
11
+ logLevel: 'info',
12
+ // external: ['dexie']
13
+ });
package/index.html ADDED
@@ -0,0 +1,42 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Document</title>
8
+ <script src="dist/vvfs.min.js"></script>
9
+ </head>
10
+
11
+ <body>
12
+ <script>
13
+ (async () => {
14
+ const vvfs = new VVFS();
15
+ await vvfs.reset();
16
+ console.log(vvfs);
17
+ if (!vvfs.exists('/home/root/')) {
18
+ console.log('Creating directory /home/root/');
19
+ await vvfs.mkdirs('/home/root/');
20
+ }
21
+ await vvfs.write('/home/root/test.txt', new File(['test content'], 'test.txt'));
22
+ await vvfs.write('/home/root/hello.txt', new File(['Hello, World!'], 'hello.txt'));
23
+ await vvfs.chmod('/home/root/test.txt', 0o644);
24
+ console.log('Changed permissions of /home/root/test.txt to 644');
25
+ await vvfs.chmod('/home/root/hello.txt', 0o644);
26
+ console.log('Changed permissions of /home/root/hello.txt to 644');
27
+ await vvfs.rename('/home/root/test.txt', '/home/root/test-renamed.txt');
28
+ console.log('Renamed /home/root/test.txt to /home/root/test-renamed.txt');
29
+ const content = await vvfs.read('/home/root/test.txt');
30
+ console.log('Content of /home/root/test.txt:', content);
31
+ const hello = await vvfs.read('/home/root/hello.txt');
32
+ console.log('Content of /home/root/hello.txt:', hello);
33
+ // await vvfs.delete('/home/root/test.txt');
34
+ // await vvfs.delete('/home/root/hello.txt');
35
+ console.log('Deleted /home/root/test.txt and /home/root/hello.txt');
36
+ console.log('Listing directory /home/root/:', await vvfs.list('/home/root/'));
37
+ console.log('Listing directory /home/:', await vvfs.list('/home/'));
38
+ })();
39
+ </script>
40
+ </body>
41
+
42
+ </html>
package/index.js ADDED
@@ -0,0 +1,142 @@
1
+ const { Dexie } = require('dexie');
2
+ // globalThis.Dexie = Dexie;
3
+
4
+ (async function () {
5
+ globalThis.VVVFS = class {
6
+ constructor(name = 'vvvfs', options = {}) {
7
+ this.options = options;
8
+ this.db = new Dexie(name);
9
+ this.db.version(1).stores({
10
+ files: '++id, name, path, type, file, mode, readonly, hidden'
11
+ });
12
+ }
13
+ async createUser(username, password) {
14
+ if (await this.exists(username)) throw new Error('User already exists');
15
+ await this.mkdirs("/home/" + username);
16
+ }
17
+ async write(path, file) {
18
+ if (!(file instanceof File)) throw new Error('file must be a File object');
19
+ if (path.endsWith('/')) throw new Error('Path cannot end with a slash');
20
+ if (!await this.exists(path)) await this.createFile(path);
21
+ const fileEntry = await this.db.files.where('path').equals(path).first();
22
+ if (fileEntry.readonly) throw new Error('File is read-only');
23
+ await this.db.files.update(path, { file });
24
+ }
25
+ async mkdirs(path) {
26
+ if (path.endsWith('/')) path = path.slice(0, -1);
27
+ const exists = await this.exists(path);
28
+ console.log('exists', exists);
29
+ if (exists) return;
30
+ const dirs = path.split('/').filter(Boolean);
31
+ console.log('mkdirs', dirs);
32
+ for (let i = 0; i < dirs.length; i++) {
33
+ if (dirs[i] === '') continue;
34
+ const dir = "/" + dirs.slice(0, i + 1).join('/');
35
+ if (await this.exists(dir)) continue;
36
+ console.log('mkdir', dir);
37
+ await this.db.files.add({
38
+ name: dirs[i],
39
+ path: dir,
40
+ type: 'directory',
41
+ file: new File([], dir),
42
+ mode: 0o755,
43
+ readonly: false,
44
+ hidden: false
45
+ });
46
+ }
47
+ }
48
+ async createFile(path) {
49
+ if (path.endsWith('/')) throw new Error('Path cannot end with a slash');
50
+ const dir = path.split('/').slice(0, -1).join('/');
51
+ console.log('createFile', path, dir);
52
+ if (dir) await this.mkdirs(dir);
53
+ const name = path.split('/').slice(-1)[0];
54
+ console.log('createFile', name);
55
+ await this.db.files.add({
56
+ name,
57
+ path,
58
+ type: 'file',
59
+ file: new File([], path),
60
+ mode: 0o644,
61
+ readonly: false,
62
+ hidden: false
63
+ });
64
+ }
65
+ async exists(path) {
66
+ const file = await this.db.files.where('path').equals(path).first();
67
+ return !!file;
68
+ }
69
+ async isDirectory(path) {
70
+ const file = await this.db.files.where('path').equals(path).first();
71
+ return file && file.type === 'directory';
72
+ }
73
+ async isFile(path) {
74
+ const file = await this.db.files.where('path').equals(path).first();
75
+ return file && file.type === 'file';
76
+ }
77
+ async read(path) {
78
+ const file = await this.db.files.where('path').equals(path).first();
79
+ return file;
80
+ }
81
+ async delete(path) {
82
+ await this.db.files.where('path').equals(path).delete();
83
+ }
84
+ async list(path) {
85
+ const files = await this.db.files.where('path').startsWith(path).toArray();
86
+ return files;
87
+ }
88
+ async chmod(path, mode) {
89
+ await this.db.files.update(path, { mode });
90
+ }
91
+ async rename(oldPath, newPath) {
92
+ const file = await this.db.files.where('path').equals(oldPath).first();
93
+ if (!file) throw new Error('File not found');
94
+ if (await this.exists(newPath)) throw new Error('File already exists');
95
+ await this.db.files.where('path').equals(oldPath).delete();
96
+ console.log('rename', oldPath, newPath);
97
+ const name = newPath.split('/').slice(-1)[0];
98
+ console.log('rename', name);
99
+ await this.db.files.add({
100
+ ...file,
101
+ name,
102
+ path: newPath
103
+ });
104
+ }
105
+ async reset() {
106
+ await this.db.files.clear();
107
+ }
108
+ async move(oldPath, newPath) {
109
+ await this.rename(oldPath, newPath);
110
+ }
111
+ async copy(oldPath, newPath) {
112
+ const file = await this.db.files.where('path').equals(oldPath).first();
113
+ if (!file) throw new Error('File not found');
114
+ if (await this.exists(newPath)) throw new Error('File already exists');
115
+ await this.db.files.add({
116
+ ...file,
117
+ path: newPath
118
+ });
119
+ }
120
+ async chown(path, owner, group) {
121
+ await this.db.files.update(path, { owner, group });
122
+ }
123
+ async stat(path) {
124
+ const file = await this.db.files.where('path').equals(path).first();
125
+ return file;
126
+ }
127
+ async isReadonly(path) {
128
+ const file = await this.db.files.where('path').equals(path).first();
129
+ return file && file.readonly;
130
+ }
131
+ async setReadonly(path, readonly) {
132
+ await this.db.files.update(path, { readonly });
133
+ }
134
+ async isHidden(path) {
135
+ const file = await this.db.files.where('path').equals(path).first();
136
+ return file && file.hidden;
137
+ }
138
+ async setHidden(path, hidden) {
139
+ await this.db.files.update(path, { hidden });
140
+ }
141
+ };
142
+ })();
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "vvvfs",
3
+ "version": "0.0.1-alpha.0",
4
+ "description": "一个使用IndexDB实现的虚拟文件系统",
5
+ "keywords": [
6
+ "Virtual",
7
+ "File",
8
+ "System",
9
+ "IFTC",
10
+ "VV",
11
+ "File",
12
+ "System",
13
+ "vfs",
14
+ "fs"
15
+ ],
16
+ "license": "MIT",
17
+ "author": "IFTC",
18
+ "type": "commonjs",
19
+ "main": "index.js",
20
+ "scripts": {
21
+ "test": "echo \"Error: no test specified\" && exit 1",
22
+ "build": "node esbuild.config.js"
23
+ },
24
+ "dependencies": {
25
+ "dexie": "^4.3.0",
26
+ "esbuild": "^0.27.3"
27
+ }
28
+ }