datafolder 1.0.17 → 1.0.19

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 CHANGED
@@ -4,6 +4,10 @@ datafolder is a lightning fluid JSON database for high speed SSDs, featuring an
4
4
 
5
5
  ### Changelog
6
6
 
7
+ 1.0.19 Add DocumentDB test case (test/testQyDocumentDB.js)
8
+
9
+ 1.0.18 Add Embedding Storage Support. Related APIs: dataFolder.insertEmbedding() and dataFolder.delEmbedding(). TODO: Add HNSW support and vector query.
10
+
7
11
  1.0.17 Add Northwind sample data test (test/testQyNorthwind.js)
8
12
 
9
13
  1.0.16 Add GraphQL sample data test (test/testQyGraphQL.js) to show how to write complex queries.
@@ -46,6 +50,7 @@ dataFolder.insert("traindata/2026/1/20/chat_0001", {
46
50
  });
47
51
  dataFolder.insert("traindata/2026/1/20/chat_0001/prompt", "What is async/await?");
48
52
  dataFolder.insert("traindata/2026/1/20/chat_0001/answer", "async/await is ...");
53
+ dataFolder.insertEmbedding("traindata/2026/1/20/chat_0001/prompt", new Float32Array([0.36646, 332.8091, 2363.982]));
49
54
  const { email, password, address, feedbackScore } = dataFolder.view("traindata/2026/1/20/chat_0001");
50
55
  address.zipcode = 678;
51
56
  dataFolder.insert("traindata/2026/1/20/chat_0001", { feedbackScore: feedbackScore + 1, address });
@@ -80,6 +85,7 @@ dataFolder.insert(file, { feedbackScore: feedbackScore + 1, address: { city: "c"
80
85
  dataFolder.createFile("path/to/file");
81
86
  dataFolder.createDir("path/to/dir");
82
87
  dataFolder.insert("path/to/file", { email, address: { city, zipcode } });
88
+ dataFolder.insertEmbedding("path/to/file", new Float32Array([235.235, 2949.8823]));
83
89
  ```
84
90
 
85
91
  #### Read
@@ -89,6 +95,7 @@ const dir = dataFolder.dir("path/to/dir");
89
95
  const { subdirList, fileList, sortedSubdirList } = dir;
90
96
  const file = dataFolder.file("path/to/file");
91
97
  const { email, address } = dataFolder.view("path/to/file", { email: 1, addres: 1 });
98
+ const embedding = dataFolder.embedding("path/to/file");
92
99
  ```
93
100
 
94
101
  #### Update
@@ -104,6 +111,7 @@ dataFolder.insert(file, { feedbackScore: feedbackScore + 1 });
104
111
  dataFolder.delDir("path/to/dir");
105
112
  dataFolder.delFile("path/to/file");
106
113
  dataFolder.delContent("path/to/file");
114
+ dataFolder.delEmbedding("path/to/file");
107
115
  dataFolder.remove("path/to/file", { email: 1, address: { zipcode: 1 } });
108
116
  dataFolder.remove(file, { email: 1, address: { zipcode: 1 } });
109
117
  ```
@@ -120,6 +128,7 @@ dataFolder.batch
120
128
  .insert("path/to/chat_details", { user: "user_0001", feedbackScore: 100 })
121
129
  .insert("path/to/prompt", "what is LLM?")
122
130
  .insert("path/to/answer", "LLM is AI...")
131
+ .insertEmbedding("path/to/prompt", [235.0235, 9923.2356])
123
132
  .remove("path/to/file", { address: { city: 1 } })
124
133
  .run();
125
134
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datafolder",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "author": {
5
5
  "name": "lysh",
6
6
  "email": "datafolderdev@outlook.com"
@@ -17,28 +17,28 @@
17
17
  "email": "datafolderdev@outlook.com"
18
18
  },
19
19
  "keywords": [
20
- "JSON",
21
- "database",
22
20
  "AI",
23
- "low-latency",
24
- "tree-view",
25
- "in-memory",
21
+ "HNSW",
22
+ "JSON",
23
+ "LSM",
24
+ "RAG",
26
25
  "SSD",
27
- "schema-free",
28
- "atomic-writes",
29
- "typescript",
30
- "edge",
31
26
  "backend",
32
- "gaming",
33
- "iot",
27
+ "database",
28
+ "easy",
29
+ "edge",
34
30
  "embed",
35
31
  "embedded",
36
- "simple",
37
- "easy",
38
- "quick",
39
- "millisecond",
32
+ "gaming",
33
+ "iot",
40
34
  "lightweight",
41
- "LSM"
35
+ "low-latency",
36
+ "millisecond",
37
+ "quick",
38
+ "schema-free",
39
+ "simple",
40
+ "tree-view",
41
+ "vector"
42
42
  ],
43
43
  "dependencies": {},
44
44
  "devDependencies": {
package/sample.js CHANGED
@@ -13,6 +13,12 @@ async function run() {
13
13
  });
14
14
  dataFolder.insert("traindata/2026/1/20/chat_0001/prompt", "What is async/await?");
15
15
  dataFolder.insert("traindata/2026/1/20/chat_0001/answer", "async/await is ...");
16
+ dataFolder.insertEmbedding("traindata/2026/1/20/chat_0001/prompt", [235.3536, 19.2358, 92.0929846]);
17
+ dataFolder.insertWithEmbedding(
18
+ "traindata/content",
19
+ { score: 90, prompt: "hello" },
20
+ [235.3536, 19.2358, 92.0929846],
21
+ );
16
22
  const { userid, email, address, feedbackScore } = dataFolder.view("traindata/2026/1/20/chat_0001");
17
23
  logger.log(userid, email, feedbackScore, address);
18
24
  address.zipcode = 678;
@@ -20,6 +26,9 @@ async function run() {
20
26
  logger.log(dataFolder.view("traindata/2026/1/20/chat_0001", ["feedbackScore", "address"]));
21
27
  logger.debug(dataFolder.view("traindata/2026/1/20/chat_0001/prompt"));
22
28
  logger.warn(dataFolder.view("traindata/2026/1/20/chat_0001/answer"));
29
+ logger.log(dataFolder.embedding("traindata/2026/1/20/chat_0001/prompt"));
30
+ logger.log(dataFolder.view("traindata/content"));
31
+ logger.log(dataFolder.embedding("traindata/content"));
23
32
  await dataFolder.stop();
24
33
  await dataFolder.start();
25
34
  {
@@ -32,6 +41,9 @@ async function run() {
32
41
  dataFolder.view("traindata/2026/1/20/chat_0001/prompt"),
33
42
  dataFolder.view("traindata/2026/1/20/chat_0001/answer"),
34
43
  );
44
+ logger.log(dataFolder.embedding("traindata/2026/1/20/chat_0001/prompt"));
45
+ logger.log(dataFolder.view("traindata/content"));
46
+ logger.log(dataFolder.embedding("traindata/content"));
35
47
  }
36
48
  await dataFolder.stop();
37
49
  }
@@ -15,6 +15,7 @@ const config = {
15
15
  const { port, staticRoot } = config;
16
16
  const fastify = Fastify({ logger: false, forceCloseConnections: true });
17
17
  // const qyDB = new QyDB(join(__dirname, "../tmp/simulate2"));
18
+ // const qyDB = new QyDB(join(__dirname, "../tmp/QyEmbeddings/1"));
18
19
  const qyDB = new QyDB();
19
20
  let sigintReceived = false;
20
21
  process.on("SIGINT", async () => {
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ import { join, basename } from "node:path";
3
+ import { readdir, readFile } from "node:fs/promises";
4
+ import fastifyStatic from "@fastify/static";
5
+ import fastifyCompress from "@fastify/compress";
6
+ import { QyDB } from "../src/QyDB.js";
7
+ import { folderOrFileExists, __dirname } from "../src/QyUtils.js";
8
+ import { logger } from "../src/QyLogger.js";
9
+ // logger.level = "warn";
10
+ const baseVectPath = "D:\\syncsoft\\hnsw\\bench\\datasets\\siftsmall\\siftsmall_base.fvecs";
11
+ const qyDB = new QyDB();
12
+ run();
13
+ async function run() {
14
+ await qyDB.start({ appendOnly: false });
15
+ const vectorList = await loadVects(baseVectPath);
16
+ const { length } = vectorList;
17
+ console.time(`insertEmbedding${length}`);
18
+ for (let idx = 0; idx < length; ++idx) {
19
+ const vect = vectorList[idx];
20
+ qyDB.insertEmbedding(["embedding", idx], vect);
21
+ // qyDB.insert(["prompt", idx], new Uint8Array(vect.buffer, vect.byteOffset, vect.byteLength));
22
+ // qyDB.delEmbedding(["embedding", idx]);
23
+ // qyDB.delFile(["prompt", idx]);
24
+ }
25
+ await qyDB.stop();
26
+ console.timeEnd(`insertEmbedding${length}`);
27
+ }
28
+ async function loadVects(filePath) {
29
+ const buffer = await readFile(filePath);
30
+ const { length } = buffer;
31
+ let offset = 0;
32
+ const vectorList = [];
33
+ while (offset < length) {
34
+ const dim = buffer.readUint32LE(offset);
35
+ vectorList.push(new Float32Array(buffer.buffer, offset + 4, dim));
36
+ offset += (dim + 1) * 4;
37
+ }
38
+ return vectorList;
39
+ }
package/src/QyAcl.js CHANGED
@@ -1,92 +1,114 @@
1
- import h from "node:fs/promises";
1
+ import l from "node:fs/promises";
2
2
 
3
3
  import {
4
+ cleanContent as s,
4
5
  mergeContent as g,
5
- mergeChanges as s,
6
6
  setValByNamePath as a
7
7
  } from "./QyFileContentUtils.js";
8
8
 
9
9
  import {
10
10
  isEmptyObj as m,
11
- toBuffer as n
11
+ toBuffer as n,
12
+ SpecialOperators as r,
13
+ isSimpleType as o
12
14
  } from "./QyUtils.js";
13
15
 
14
16
  import {
15
- logger as l
17
+ logger as h
16
18
  } from "./QyLogger.js";
17
19
 
18
- let f = {
20
+ let {
21
+ $del: f,
22
+ $rpl: u,
23
+ $u8: c
24
+ } = r, d = {
19
25
  M: 0,
20
26
  A: 1,
21
27
  R: 2,
22
28
  D: 3
23
29
  };
24
30
 
25
- function r(r, t) {
26
- var e, a, n, s, [ i, o, f, t ] = t;
31
+ function t(r, t) {
32
+ var e, a, n, i, [ s, o, f, t ] = t;
27
33
  for (e in t) null != r[e] && (r[e] = void 0);
28
34
  for (a in o) {
29
- var c, u = r[a] || (r[a] = {});
30
- for (c of o[a]) u[c] = 1;
35
+ var u, c = r[a] || (r[a] = {});
36
+ for (u of o[a]) c[u] = 1;
31
37
  }
32
38
  for (n in f) {
33
- var h = r[n];
34
- if (h) {
35
- var l = f[n];
36
- if (l) {
37
- for (var d of l) delete h[d];
38
- m(h) && (r[n] = void 0);
39
+ var l = r[n];
40
+ if (l) {
41
+ var h = f[n];
42
+ if (h) {
43
+ for (var d of h) delete l[d];
44
+ m(l) && (r[n] = void 0);
39
45
  }
40
46
  }
41
47
  }
42
- for (s in i) r[s] = g(r[s], i[s]);
48
+ for (i in s) r[i] = g(r[i], s[i]);
43
49
  }
44
50
 
45
- function t(r, t) {
51
+ function e(r, t) {
46
52
  for (var e of r) for (var a in e) t(a);
47
53
  }
48
54
 
49
- class e {
55
+ class i {
50
56
  cmdArgAsMapChanges = [];
51
57
  cmdCount = 0;
52
58
  batchSize = 0;
53
59
  constructor() {}
54
60
  pushCmd(r, t, e = void 0) {
55
61
  switch (++this.cmdCount, r) {
56
- case f.A:
57
- i(this, [ f.A, t, e ]), o(this, [ f.R, t, e ]);
62
+ case d.A:
63
+ v(this, [ d.A, t, e ]), A(this, [ d.R, t, e ]);
58
64
  break;
59
65
 
60
- case f.R:
61
- i(this, [ f.R, t, e ]), o(this, [ f.A, t, e ]);
66
+ case d.R:
67
+ v(this, [ d.R, t, e ]), A(this, [ d.A, t, e ]);
62
68
  break;
63
69
 
64
- case f.D:
65
- if (i(this, [ f.D, t ]), t.startsWith("c")) o(this, [ f.M, t ]); else for (var a of [ f.A, f.R ]) o(this, [ a, t ]);
70
+ case d.D:
71
+ if (v(this, [ d.D, t ]), t.startsWith("c")) A(this, [ d.M, t ]); else for (var a of [ d.A, d.R ]) A(this, [ a, t ]);
66
72
  break;
67
73
 
68
- case f.M:
74
+ case d.M:
69
75
  {
70
76
  var n = this.cmdArgAsMapChanges;
71
77
  let [ r ] = n;
72
- n = (r = null == r ? n[f.M] = {} : r)[t];
73
- r[t] = null != n ? s(n, e) : e;
78
+ n = (r = null == r ? n[d.M] = {} : r)[t];
79
+ r[t] = null != n ? function e(a, n) {
80
+ if (n == f) return f;
81
+ let r = n[u];
82
+ if (null != r) return n;
83
+ let t = a[u];
84
+ if (null != t) return a[u] = g(t, n), a;
85
+ if (a == f) return {
86
+ [u]: s(n)
87
+ };
88
+ if (o(a) || o(n)) return n;
89
+ if (c in n) return n;
90
+ for (var i in n) {
91
+ let r = n[i], t = a[i];
92
+ null == t ? a[i] = r : a[i] = e(t, r);
93
+ }
94
+ return a;
95
+ }(n, e) : e;
74
96
  break;
75
97
  }
76
98
 
77
99
  default:
78
- l.error(`unsupported cmdName:${r}, called with ${t} ` + e), --this.cmdCount;
100
+ h.error(`unsupported cmdName:${r}, called with ${t} ` + e), --this.cmdCount;
79
101
  }
80
102
  }
81
103
  pushCmdArgAsListObj(r) {
82
104
  if (r) {
83
- for (var t in ++this.batchSize, r[f.D]) this.pushCmd(f.D, t);
84
- for (var e of [ f.A, f.R ]) {
105
+ for (var t in ++this.batchSize, r[d.D]) this.pushCmd(d.D, t);
106
+ for (var e of [ d.A, d.R ]) {
85
107
  var a, n = r[e];
86
- for (a in n) for (var s of n[a]) this.pushCmd(e, a, s);
108
+ for (a in n) for (var i of n[a]) this.pushCmd(e, a, i);
87
109
  }
88
- var i, [ o ] = r;
89
- for (i in o) this.pushCmd(f.M, i, o[i]);
110
+ var s, [ o ] = r;
111
+ for (s in o) this.pushCmd(d.M, s, o[s]);
90
112
  }
91
113
  return this;
92
114
  }
@@ -97,7 +119,7 @@ class e {
97
119
  cmdCount: 0,
98
120
  batchSize: 0
99
121
  });
100
- for (r of [ f.A, f.R ]) {
122
+ for (r of [ d.A, d.R ]) {
101
123
  var e, a = t[r];
102
124
  for (e in a) {
103
125
  var n = Object.keys(a[e]);
@@ -105,20 +127,20 @@ class e {
105
127
  }
106
128
  m(a) && delete t[r];
107
129
  }
108
- var s = t[f.D], s = (s && m(s) && delete t[f.D], t[f.M]);
109
- return s && m(s) && delete t[f.M], t;
130
+ var i = t[d.D], i = (i && m(i) && delete t[d.D], t[d.M]);
131
+ return i && m(i) && delete t[d.M], t;
110
132
  }
111
133
  toAclBuffer(r) {
112
134
  var t = this.batchSize;
113
- if (0 < t) return A(r, t, JSON.stringify(this.takeCmdArgAsListObj()));
135
+ if (0 < t) return y(r, t, JSON.stringify(this.takeCmdArgAsListObj()));
114
136
  }
115
137
  }
116
138
 
117
- function i(r, t, e = 1) {
139
+ function v(r, t, e = 1) {
118
140
  a(r.cmdArgAsMapChanges, t, e);
119
141
  }
120
142
 
121
- function o(r, t) {
143
+ function A(r, t) {
122
144
  let e = r.cmdArgAsMapChanges;
123
145
  if (e && t && !(t.length <= 1)) {
124
146
  for (let r = 0; r < t.length - 1; ++r) if (null == (e = e[t[r]])) return;
@@ -126,55 +148,55 @@ function o(r, t) {
126
148
  }
127
149
  }
128
150
 
129
- async function c(t, r = !1, e = 0) {
151
+ async function p(t, r = !1, e = 0) {
130
152
  try {
131
- return await p(t, await h.readFile(t), r, e);
153
+ return await I(t, await l.readFile(t), r, e);
132
154
  } catch (r) {
133
- throw l.error(`Reading ${t} failed:`, r), r;
155
+ throw h.error(`Reading ${t} failed:`, r), r;
134
156
  }
135
157
  }
136
158
 
137
- let v = [ 1, 2, 4, 8 ];
159
+ let C = [ 1, 2, 4, 8 ];
138
160
 
139
- function u(t) {
161
+ function b(t) {
140
162
  var e = t.length, a = new Array(e), n = new Array(e);
141
- let s = e << 6, i = 1;
163
+ let i = e << 6, s = 1;
142
164
  for (let r = 0; r < e; ++r) {
143
- var o = a[r] = (o = t[r]) <= 255 ? 0 : o <= 65535 ? 1 : o <= 4294967295 ? 2 : 3, o = (s |= o << (r << 1),
144
- n[r] = v[o]);
145
- i += o;
165
+ var o = a[r] = (o = t[r]) <= 255 ? 0 : o <= 65535 ? 1 : o <= 4294967295 ? 2 : 3, o = (i |= o << (r << 1),
166
+ n[r] = C[o]);
167
+ s += o;
146
168
  }
147
- var f = Buffer.allocUnsafe(i);
148
- f.writeUInt8(s);
149
- let c = 1;
169
+ var f = Buffer.allocUnsafe(s);
170
+ f.writeUInt8(i);
171
+ let u = 1;
150
172
  for (let r = 0; r < e; ++r) {
151
- d = l = h = u = void 0;
152
- var [ u, h, l, d = 0 ] = [ f, t[r], n[r], c ];
153
- switch (l) {
173
+ d = h = l = c = void 0;
174
+ var [ c, l, h, d = 0 ] = [ f, t[r], n[r], u ];
175
+ switch (h) {
154
176
  case 1:
155
- u.writeUInt8(h, d);
177
+ c.writeUInt8(l, d);
156
178
  break;
157
179
 
158
180
  case 2:
159
- u.writeUInt16BE(h, d);
181
+ c.writeUInt16BE(l, d);
160
182
  break;
161
183
 
162
184
  case 4:
163
- u.writeUInt32BE(h, d);
185
+ c.writeUInt32BE(l, d);
164
186
  break;
165
187
 
166
188
  default:
167
- u.writeBigUInt64BE(BigInt(h), d);
189
+ c.writeBigUInt64BE(BigInt(l), d);
168
190
  }
169
- c += n[r];
191
+ u += n[r];
170
192
  }
171
193
  return f;
172
194
  }
173
195
 
174
- function d(t, e, a) {
175
- var n = t.readUInt8(e), s = (++e, n >> 6 & 3);
176
- for (let r = 0; r < s; ++r) {
177
- var i = v[n >> (r << 1) & 3];
196
+ function w(t, e, a) {
197
+ var n = t.readUInt8(e), i = (++e, n >> 6 & 3);
198
+ for (let r = 0; r < i; ++r) {
199
+ var s = C[n >> (r << 1) & 3];
178
200
  a[r] = ((r, t, e = 0) => {
179
201
  switch (t) {
180
202
  case 1:
@@ -189,45 +211,45 @@ function d(t, e, a) {
189
211
  default:
190
212
  return Number(r.readBigUInt64BE(e));
191
213
  }
192
- })(t, i, e), e += i;
214
+ })(t, s, e), e += s;
193
215
  }
194
216
  return e;
195
217
  }
196
218
 
197
- function A(r, t, e) {
219
+ function y(r, t, e) {
198
220
  e = n(e);
199
- return Buffer.concat([ u([ r, t, e.length ]), e ]);
221
+ return Buffer.concat([ b([ r, t, e.length ]), e ]);
200
222
  }
201
223
 
202
- async function p(e, r, a, n) {
203
- var s = [];
224
+ async function I(e, r, a, n) {
225
+ var i = [];
204
226
  for (let t = 0; t < r.length; ) {
205
- var i = [], o = d(r, t, i), [ i, f, c ] = i;
206
- if (i <= n) l.warn(`changeId ${i} <= currentChangeId ${n} at ${e}:${t}. Ignored.`),
207
- t = o + c; else {
208
- n + f != i && l.warn(`currentChangeId ${n} + batchSize ${f} != changeId ` + i);
227
+ var s = [], o = w(r, t, s), [ s, f, u ] = s;
228
+ if (s <= n) h.warn(`changeId ${s} <= currentChangeId ${n} at ${e}:${t}. Ignored.`),
229
+ t = o + u; else {
230
+ n + f != s && h.warn(`currentChangeId ${n} + batchSize ${f} != changeId ` + s);
209
231
  try {
210
- var u = JSON.parse(r.subarray(o, o + c));
211
- s.push([ i, u ]), n = i, t = o + c;
232
+ var c = JSON.parse(r.subarray(o, o + u));
233
+ i.push([ s, c ]), n = s, t = o + u;
212
234
  } catch (r) {
213
- if (l.error(`Parse ${e} failed at ${t}:`, r), a) return l.warn(`Autorepair by truncating ${e} to ` + t),
214
- null == (f = await h.truncate(e, t)) ? l.log("truncate success") : l.error("truncate failed:", f),
215
- s;
235
+ if (h.error(`Parse ${e} failed at ${t}:`, r), a) return h.warn(`Autorepair by truncating ${e} to ` + t),
236
+ null == (f = await l.truncate(e, t)) ? h.log("truncate success") : h.error("truncate failed:", f),
237
+ i;
216
238
  throw r;
217
239
  }
218
240
  }
219
241
  }
220
- return s;
242
+ return i;
221
243
  }
222
244
 
223
245
  export {
224
- f as CmdNames,
225
- r as applyAclChange,
226
- t as iterCmdKeys,
227
- e as QyAclCmdGenerator,
228
- c as readAclFile,
229
- u as numsToBuffer,
230
- d as bufferToNums,
231
- A as toAclBuffer,
232
- p as readAclBuffer
246
+ d as CmdNames,
247
+ t as applyAclChange,
248
+ e as iterCmdKeys,
249
+ i as QyAclCmdGenerator,
250
+ p as readAclFile,
251
+ b as numsToBuffer,
252
+ w as bufferToNums,
253
+ y as toAclBuffer,
254
+ I as readAclBuffer
233
255
  };
package/src/QyBatch.d.ts CHANGED
@@ -25,6 +25,9 @@ export declare class QyBatch extends QyCD {
25
25
  createIndex(indexHostDirNamePath: any, indexPropPathList: any, parentDir?: any): any;
26
26
  delIndex(indexHostDirNamePath: any, indexPropPath: any, parentDir?: any): any;
27
27
  insert(namePath: any, content: any, noClone?: boolean, noCreate?: boolean, parentDir?: any): any;
28
+ insertEmbedding(namePath: any, embedding: any, parentDir?: any): any;
29
+ delEmbedding(namePath: any, parentDir?: any): any;
30
+ insertWithEmbedding(namePath: any, content: any, embedding: any, noClone?: boolean, noCreate?: boolean, parentDir?: any): any;
28
31
  remove(namePath: any, content: any, parentDir?: any): any;
29
32
  put(namePath: any, content: any, noClone?: boolean, parentDir?: any): any;
30
33
  delContent(namePath: any, parentDir?: any): any;
@@ -43,6 +46,8 @@ export declare class QyBatch extends QyCD {
43
46
  _action_delFile(action: any, deletingParentDir?: boolean): boolean;
44
47
  _action_delDir(action: any): boolean;
45
48
  _action_delContent(action: any): boolean;
49
+ _action_insertEmbedding(action: any): boolean;
50
+ _action_delEmbedding(action: any): true | undefined;
46
51
  _action_insert(action: any): boolean;
47
52
  _action_createFile(action: any): boolean;
48
53
  _action_createDir(action: any): boolean;