datafolder 1.0.10 → 1.0.12

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 (72) hide show
  1. package/{internal.md → Internal.md} +8 -1
  2. package/README.md +15 -1
  3. package/SKILL.md +191 -0
  4. package/SSD.md +3 -3
  5. package/package.json +2 -2
  6. package/scripts/flights2.js +2 -0
  7. package/src/QyAcl.d.ts +13 -7
  8. package/src/QyAcl.js +122 -138
  9. package/src/QyAclSaver.js +2 -2
  10. package/src/QyAclSaver_Worker.d.ts +2 -2
  11. package/src/QyAclWriter.d.ts +1 -1
  12. package/src/QyBatch.d.ts +8 -11
  13. package/src/QyBatch.js +239 -211
  14. package/src/QyBinWriter.d.ts +2 -2
  15. package/src/QyBinWriter.js +15 -15
  16. package/src/QyCD.d.ts +2 -2
  17. package/src/QyCD.js +29 -29
  18. package/src/QyCache.d.ts +6 -1
  19. package/src/QyCache.js +72 -53
  20. package/src/QyCompressor.d.ts +2 -2
  21. package/src/QyCompressor.js +13 -13
  22. package/src/QyDB.d.ts +1 -22
  23. package/src/QyDB.js +23 -78
  24. package/src/QyDefaultOptions.js +5 -0
  25. package/src/QyDir.js +26 -27
  26. package/src/QyExpire.d.ts +21 -0
  27. package/src/QyExpire.js +113 -0
  28. package/src/QyExpireClock.d.ts +15 -0
  29. package/src/QyExpireClock.js +53 -0
  30. package/src/QyExpire_Worker.d.ts +20 -0
  31. package/src/QyExpire_Worker.js +127 -0
  32. package/src/QyFile.js +36 -25
  33. package/src/QyFileContentUtils.js +21 -21
  34. package/src/QyItem.d.ts +1 -0
  35. package/src/QyItem.js +15 -9
  36. package/src/QyJsonSaver.d.ts +1 -1
  37. package/src/QyJsonSaver.js +1 -1
  38. package/src/QyKVData.d.ts +5 -2
  39. package/src/QyKVData.js +126 -114
  40. package/src/QyKVDataCleaner.js +2 -2
  41. package/src/QyKVDataCleaner_Worker.js +37 -37
  42. package/src/QyKVDataSaver.js +2 -2
  43. package/src/QyKVDataSaver_Worker.d.ts +2 -2
  44. package/src/QyKVDataSaver_Worker.js +5 -5
  45. package/src/QyLogFileSaver.js +2 -2
  46. package/src/QyLogger.d.ts +1 -0
  47. package/src/QyLogger.js +1 -0
  48. package/src/QyMessageWorker.d.ts +1 -1
  49. package/src/QyMessageWorker.js +10 -10
  50. package/src/QyMessager.d.ts +1 -1
  51. package/src/QyMessager.js +37 -36
  52. package/src/QyMessager_Run.js +12 -8
  53. package/src/QyQueue.js +8 -12
  54. package/src/QySaver.d.ts +1 -1
  55. package/src/QySaver.js +1 -1
  56. package/src/QySnapshotCompactor.js +2 -2
  57. package/src/QySnapshotCompactor_Worker.d.ts +1 -1
  58. package/src/QySnapshotCompactor_Worker.js +5 -5
  59. package/src/QySnapshotSaver.js +2 -2
  60. package/src/QySnapshotSaver_Worker.js +4 -4
  61. package/src/QySnapshots.d.ts +2 -2
  62. package/src/QySnapshots.js +38 -38
  63. package/src/QyTrigger.d.ts +1 -1
  64. package/src/QyTrigger.js +20 -21
  65. package/src/QyUtils.d.ts +3 -2
  66. package/src/QyUtils.js +93 -86
  67. package/src/hackernews.js +1 -1
  68. package/src/simulate.js +6 -6
  69. package/src/simulate2.js +5 -5
  70. package/src/soc_pokec.js +1 -1
  71. package/static/codemirror.bundle/editor.bundle.js +43 -9
  72. package/static/datafolderui/QyUIFolderViewer.js +1 -5
@@ -2,7 +2,7 @@
2
2
 
3
3
  The best mechanism to index and partition data is **by the nature of data**. Instead of forcing data to transform, it should seamlessly embrace and fully cater to the **uniqueness** of each and every data to accomplish nature-level efficiency, **mentally and mechanically**. Whatever data is, it follows like fluid.
4
4
 
5
- This is the **design philosophy** behind datafolder, a lightweight schemaless JSON database, featuring an AI-friendly API for simple and human maintainable code generation, millisecond data response, with full index and trigger features supported, and the unique ability to browse and manage data as a folder tree directly in your browser. It works perfectly for a wide range of scenarios, from game/application backends to embedded systems to IoT to edge computing.
5
+ This is the **design philosophy** behind datafolder, a lightning fluid schemaless JSON database, featuring an AI-friendly API for simple and human maintainable code generation, millisecond data response, with full index and trigger features supported, and the unique ability to browse and manage data as a folder tree directly in your browser. Data can be organized naturally into folders, sub folders and files. It works perfectly for a wide range of scenarios, from game/application backends to embedded systems to IoT to edge computing.
6
6
 
7
7
  ### User Level Data Layout
8
8
 
@@ -24,6 +24,13 @@ Airports can be stored as
24
24
  airports/{country}/{state}/{airport_id}
25
25
  ```
26
26
 
27
+ AI training data can be stored as
28
+
29
+ ```
30
+ AITraining/{year}/{month}/{day}/chat_id/prompt
31
+ /answer
32
+ ```
33
+
27
34
  When you conceive the data model, you don't need to think about tables, schemas, indexes etc. All you need to know is the nature of the data and then go with the most comfortable one for your mental mind.
28
35
 
29
36
  ### In-memory Tree Structure
package/README.md CHANGED
@@ -1,9 +1,13 @@
1
1
  # datafolder
2
2
 
3
- datafolder is a lightning fluid JSON database for SSD, featuring an AI-friendly API for simple and human maintainable code generation, millisecond data response, with full index and trigger features supported, and the unique ability to browse and manage data as a folder tree directly in your browser. It works perfectly for a wide range of scenarios, from game/application backends to embedded systems to IoT to edge computing.
3
+ datafolder is a lightning fluid JSON database for high speed SSDs, featuring an AI-friendly API for simple and human maintainable code generation, millisecond data response, with full index and trigger features supported, and the unique ability to browse and manage data as a folder tree directly in your browser. It works perfectly for a wide range of scenarios, from game/application backends to embedded systems to IoT to edge computing.
4
4
 
5
5
  ### Changelog
6
6
 
7
+ 1.0.12 Added expire support to expire a file or some properties of the JSON data in future.
8
+
9
+ 1.0.11 Added [SKILL.md](https://github.com/datafolderdev/datafolder/blob/main/SKILL.md) for feeding to AI
10
+
7
11
  1.0.10 Added document [datafolder for high speed SSDs](https://github.com/datafolderdev/datafolder/wiki/datafolder-for-high-speed-SSDs)
8
12
 
9
13
  1.0.9 Added Typescript type declarations.
@@ -160,6 +164,16 @@ onPromptScoreChanged({ promptId: "student2", feedbackScore: { oldValue: undefine
160
164
  onPromptScoreChanged({ promptId: "student1", feedbackScore: { oldValue: 80, newValue: 32 } });
161
165
  ```
162
166
 
167
+ ### 5. Expire Support
168
+
169
+ ```javascript
170
+ dataFolder.expireFile("aitrainingdata/tmp/prompt", 3600); // the file will be deleted after 1 hour
171
+ dataFolder.expireContent("users/login", { sessionId: 300, token: 3600 });
172
+
173
+ dataFolder.removeFileExpire("aitrainingdata/tmp/prompt", 3600);
174
+ dataFolder.removeContentExpire("users/login", { sessionId: 1, token: 1 });
175
+ ```
176
+
163
177
  ## Example
164
178
 
165
179
  Once you install datafolder via
package/SKILL.md ADDED
@@ -0,0 +1,191 @@
1
+ ---
2
+ name: datafolder-builder
3
+ description: >
4
+ Use this skill when building applications on top of datafolder — a lightning fluid JSON database for high speed SSDs, featuring an AI-friendly API for simple and human maintainable code generation, millisecond data response, with full index and trigger features supported, and the unique ability to browse and manage data as a folder tree directly in your browser. Data can be organized naturally into folders, sub folders and files. It works perfectly for a wide range of scenarios, from game/application backends to embedded systems to IoT to edge computing. Covers installation, basic usages, CRUD, batch APIs, powerful query support which auto creates needed indexes, flexible trigger support to monitor any changes.
5
+ Trigger when a user asks to build, query, or operate with datafolder, write application code against it, or understand how to structure data and queries.
6
+ ---
7
+
8
+ # datafolder Builder Skill
9
+
10
+ ## What Is datafolder?
11
+
12
+ The best mechanism to index and partition data is **by the nature of data**. Instead of forcing data to transform, it should seamlessly embrace and fully cater to the **uniqueness** of each and every data to accomplish nature-level efficiency, **mentally and mechanically**. Whatever data is, it follows like fluid.
13
+
14
+ This is the **design philosophy** behind datafolder, a lightning fluid schemaless JSON database, featuring an AI-friendly API for simple and human maintainable code generation, millisecond data response, with full index and trigger features supported, and the unique ability to browse and manage data as a folder tree directly in your browser. Data can be organized naturally into folders, sub folders and files. It works perfectly for a wide range of scenarios, from game/application backends to embedded systems to IoT to edge computing.
15
+
16
+ ## Features
17
+
18
+ 🤖 AI-Friendly, Simple API: Designed for easy code generation by AI and long-term maintainability by humans.
19
+
20
+ ⚡ Extreme Data Access Speed: Supports fully in-memory operation for millisecond response, with configurable persistence to high-speed SSD.
21
+
22
+ 🌐 Built-in Browser Management: Visually browse and manage your data as a folder hierarchy directly within the browser, no separate tools needed.
23
+
24
+ 🧩 Plain JavaScript: Built with plain JavaScript, offers full TypeScript support and safe atomic writes.
25
+
26
+ 🔧 Designed for application/game backends, IoT, and edge computing scenarios, easily deployable on servers, in browsers, and even on embedded hardware.
27
+
28
+ ## User Level Data Layout
29
+
30
+ Data can be organized naturally into folders, sub folders and files. For example, Orders can be stored in
31
+
32
+ ```
33
+ orders/{year}/{month}/{day}/{order_id}
34
+ ```
35
+
36
+ Flights can be stored as
37
+
38
+ ```
39
+ flights/{from}/{to}/{flight_id}
40
+ ```
41
+
42
+ Airports can be stored as
43
+
44
+ ```
45
+ airports/{country}/{state}/{airport_id}
46
+ ```
47
+
48
+ AI training data can be stored as
49
+
50
+ ```
51
+ AITraining/{year}/{month}/{day}/chat_id/prompt
52
+ /answer
53
+ ```
54
+
55
+ When you conceive the data model, you don't need to think about tables, schemas, indexes etc. All you need to know is the nature of the data and then go with the most comfortable one for your mental mind.
56
+
57
+ ## Installation
58
+
59
+ ```javascript
60
+ npm install "datafolder"
61
+ ```
62
+
63
+ ## How to use
64
+
65
+ ```javascript
66
+ import DataFolder from "datafolder";
67
+ const dataFolder = new DataFolder(); //Specify where to store the data. Default is ./data/sampleDataFolder
68
+ await dataFolder.start(); //start() and stop() are the only two async places. All other code doesn't need await.
69
+ dataFolder.insert("traindata/2026/1/20/chat_0001", {
70
+ userid: "user_0001",
71
+ email: "a@b.com",
72
+ feedbackScore: 5,
73
+ address: { city: "a", zipcode: 123 },
74
+ });
75
+ dataFolder.insert("traindata/2026/1/20/chat_0001/prompt", "What is async/await?");
76
+ dataFolder.insert("traindata/2026/1/20/chat_0001/answer", "async/await is ...");
77
+ const { email, password, address, feedbackScore } = dataFolder.view("traindata/2026/1/20/chat_0001");
78
+ address.zipcode = 678;
79
+ dataFolder.insert("traindata/2026/1/20/chat_0001", { feedbackScore: feedbackScore + 1, address });
80
+ await dataFolder.stop();
81
+ ```
82
+
83
+ Or operate with dir/file objects:
84
+
85
+ ```javascript
86
+ const file = dataFolder.file("traindata/2026/1/20/chat_0001");
87
+ const { feedbackScore, address } = file.view({ feedbackScore: 1, address: 1 });
88
+ dataFolder.insert(file, { feedbackScore: feedbackScore + 1, address: { city: "c", zipcode: 663 } });
89
+ ```
90
+
91
+ ### Simple CRUD APIs
92
+
93
+ #### Create
94
+
95
+ ```javascript
96
+ dataFolder.createFile("path/to/file");
97
+ dataFolder.createDir("path/to/dir");
98
+ dataFolder.insert("path/to/file", { email, address: { city, zipcode } });
99
+ ```
100
+
101
+ #### Read
102
+
103
+ ```javascript
104
+ const dir = dataFolder.dir("path/to/dir");
105
+ const { subdirList, fileList, sortedSubdirList } = dir;
106
+ const file = dataFolder.file("path/to/file");
107
+ const { email, address } = dataFolder.view("path/to/file", { email: 1, addres: 1 });
108
+ ```
109
+
110
+ #### Update
111
+
112
+ ```javascript
113
+ dataFolder.insert("path/to/file", { email: newEmail, address: { zipcode: newZipcode } });
114
+ dataFolder.insert(file, { feedbackScore: feedbackScore + 1 });
115
+ ```
116
+
117
+ #### Delete
118
+
119
+ ```javascript
120
+ dataFolder.delDir("path/to/dir");
121
+ dataFolder.delFile("path/to/file");
122
+ dataFolder.delContent("path/to/file");
123
+ dataFolder.remove("path/to/file", { email: 1, address: { zipcode: 1 } });
124
+ dataFolder.remove(file, { email: 1, address: { zipcode: 1 } });
125
+ ```
126
+
127
+ ### Batch APIs
128
+
129
+ ```javascript
130
+ const [dir, file, { email, feedbackScore }] = dataFolder.fetch
131
+ .dir("path/to/dir")
132
+ .file("path/to/file")
133
+ .view("path/to/file")
134
+ .run();
135
+ dataFolder.batch
136
+ .insert("path/to/chat_details", { user: "user_0001", feedbackScore: 100 })
137
+ .insert("path/to/prompt", "what is LLM?")
138
+ .insert("path/to/answer", "LLM is AI...")
139
+ .remove("path/to/file", { address: { city: 1 } })
140
+ .run();
141
+ ```
142
+
143
+ ### Powerful Query Support. Auto Create Needed Indexes
144
+
145
+ ```javascript
146
+ // get all the training data in year 2026 with feedbackScore between 60 and 85.
147
+ dataFolder.queryFiles("traindata/2026/**", { feedbackScore: (x) => x >= 60 && x <= 85 });
148
+
149
+ // get training data of user_001 from July to Oct in year 2025, 2026 with feedbackScore higher than 90.
150
+ dataFolder.queryFiles(["traindata", { $in: [2025, 2026] }, { $gt: 6, $lte: 10 }], {
151
+ feedbackScore: { $gt: 90 },
152
+ userId: "user_0001",
153
+ });
154
+
155
+ dataFolder.queryFiles("flights/**", { _from: "airports/LAX" });
156
+ dataFolder.queryFiles(["flights", "*", "jan", (x) => x >= 5 && x <= 7], {
157
+ $or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
158
+ });
159
+ dataFolder.queryFiles(["flights", "*", "feb", { $or: [5, 6, 7] }], {
160
+ $or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
161
+ });
162
+ dataFolder.queryFiles(["flights", "*", "mar", { $gte: 5, lte: 7 }], {
163
+ $or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
164
+ });
165
+ dataFolder.queryFilesMulti([
166
+ [["airbnb", "Loft", "Entire home/apt", "Real Bed"], { address: { street: "Porto, Porto, Portugal" } }],
167
+ ["airbnb/Loft/**", { minimum_nights: (x) => x >= 60 }],
168
+ ]);
169
+ ```
170
+
171
+ ### Flexible Trigger Support to Monitor Any Changes
172
+
173
+ ```javascript
174
+ function onPromptScoreChanged({ promptId, feedbackScore }) {
175
+ const { oldValue, newValue } = feedbackScore;
176
+ // Logic to handle prompt feedback score change.
177
+ }
178
+ dataFolder.insertTrigger("promptScoreChanged", "traindata/{promptId}", "feedbackScore");
179
+ dataFolder.on("promptScoreChanged", onPromptScoreChanged);
180
+ dataFolder.insert("traindata/prompt_1", { feedbackScore: 80 });
181
+ dataFolder.insert("traindata/prompt_2", { feedbackScore: 63 });
182
+ dataFolder.insert("traindata/prompt_1", { feedbackScore: 32 });
183
+ ```
184
+
185
+ Will trigger the following calls:
186
+
187
+ ```javascript
188
+ onPromptScoreChanged({ promptId: "student1", feedbackScore: { oldValue: undefined, newValue: 80 } });
189
+ onPromptScoreChanged({ promptId: "student2", feedbackScore: { oldValue: undefined, newValue: 63 } });
190
+ onPromptScoreChanged({ promptId: "student1", feedbackScore: { oldValue: 80, newValue: 32 } });
191
+ ```
package/SSD.md CHANGED
@@ -34,7 +34,7 @@ Key Characteristics and Benefits of LSM trees to run on SSDs
34
34
 
35
35
  ### datafolder, a lightning fluid JSON database, is a natural fit for high speed SSDs
36
36
 
37
- datafolder is [based on LSM trees](https://github.com/datafolderdev/datafolder/wiki/Internals-of-datafolder), but taked to a higher level.
37
+ datafolder is [based on LSM trees](https://github.com/datafolderdev/datafolder/wiki/Internals-of-datafolder), but taken to a higher level.
38
38
 
39
39
  - Complex JSON data in a single virtual file for a record
40
40
 
@@ -42,7 +42,7 @@ The data is just a normal JSON [object](https://github.com/datafolderdev/datafol
42
42
 
43
43
  - Changes are stored as deltas in append-only mode.
44
44
 
45
- When changes are maded to each virtual file, only [the deltas](https://github.com/datafolderdev/datafolder/wiki/Internals-of-datafolder#accumulated-change-list) are stored. And the delta changes from different virtual files/folders are merged and appended to ACL log files.
45
+ When changes are made to each virtual file, only [the deltas](https://github.com/datafolderdev/datafolder/wiki/Internals-of-datafolder#accumulated-change-list) are stored. And the delta changes from different virtual files/folders are merged and appended to ACL log files.
46
46
 
47
47
  - Never overwrite. Always append or create new file.
48
48
 
@@ -57,4 +57,4 @@ datafolder never overwrites. It always appends to an ACL file, or create new [sn
57
57
  - Snapshot Position Mapping maps a key to its position in the corresponding valueList file.
58
58
  - Snapshot Prefix Position Mapping maps a key prefix to its range position in the corresponding Positing Mapping file.
59
59
 
60
- ### Future: Make datafolder runs directly on SSDs without the FTL
60
+ ### Future: Make datafolder runs directly on SSDs without the FTL, or Zoned Namespaces(ZNS) SSDs (formerly Open-Channel SSDs)
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "datafolder",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "author": {
5
5
  "name": "lysh",
6
6
  "email": "datafolderdev@outlook.com"
7
7
  },
8
- "description": "datafolder is a lightning fluid JSON database for SSD, featuring an AI-friendly API for simple and human maintainable code generation, millisecond data response, with full index and trigger features supported, and the unique ability to browse and manage data as a folder tree directly in your browser. It works perfectly for a wide range of scenarios, from game/application backends to embedded systems to IoT to edge computing.",
8
+ "description": "datafolder is a lightning fluid JSON database for high speed SSDs, featuring an AI-friendly API for simple and human maintainable code generation, millisecond data response, with full index and trigger features supported, and the unique ability to browse and manage data as a folder tree directly in your browser. It works perfectly for a wide range of scenarios, from game/application backends to embedded systems to IoT to edge computing.",
9
9
  "license": "MIT",
10
10
  "repository": {
11
11
  "type": "git",
@@ -14,6 +14,7 @@ const qyDB = new QyDB(dataFolder, { preloadFoldersAtStart: false });
14
14
  run();
15
15
  function insertAirports() {
16
16
  const data = JSON.parse(readFileSync(join(arangoJsonFolderPath, "airports.json")));
17
+ console.log(`airports:${data.length}`);
17
18
  console.time("insertAirports");
18
19
  const { batch } = qyDB;
19
20
  for (const record of data) {
@@ -25,6 +26,7 @@ function insertAirports() {
25
26
  }
26
27
  function insertFlights() {
27
28
  const data = JSON.parse(readFileSync(join(arangoJsonFolderPath, "flights.json")));
29
+ console.log(`flights:${data.length}`);
28
30
  console.time("insertFlights");
29
31
  const { batch } = qyDB;
30
32
  for (let i = 0; i < data.length; ++i) {
package/src/QyAcl.d.ts CHANGED
@@ -1,14 +1,20 @@
1
- export declare function delCmdKey(cmdArgAsListObj: any, key: string): void;
2
- export declare function applyAclChange(aclKeyValueMap: any, cmdArgAsListObj: any): void;
3
- export declare function iterCmdKeys(cmdArgAsListObj: any, fun: any): void;
1
+ export declare const CmdNames: {
2
+ M: number;
3
+ A: number;
4
+ R: number;
5
+ D: number;
6
+ };
7
+ export declare function delCmdKey(cmdArgAsListChanges: any, key: string): void;
8
+ export declare function applyAclChange(aclKeyValueMap: any, cmdArgAsListChanges: any): void;
9
+ export declare function iterCmdKeys(cmdArgAsListChanges: any, fun: any): void;
4
10
  export declare class QyAclCmdGenerator {
5
- cmdArgAsMapObj: {};
11
+ cmdArgAsMapChanges: any[];
6
12
  cmdCount: number;
7
13
  batchSize: number;
8
14
  constructor();
9
- pushCmd(cmdName: string, cmdHashKey: string, cmdArg?: any): void;
10
- pushCmdArgAsListObj(cmdArgAsListObj: any): this;
11
- takeCmdArgAsListObj(): {};
15
+ pushCmd(cmdName: number, cmdHashKey: string, cmdArg?: any): void;
16
+ pushCmdArgAsListObj(cmdArgAsListChanges: any): this;
17
+ takeCmdArgAsListObj(): any[];
12
18
  toAclBuffer(changeId: any): Buffer<ArrayBuffer> | undefined;
13
19
  }
14
20
  export declare function readAclFile(aclFilePath: any, autoRepairAclFile?: boolean, currentChangeId?: number): Promise<any[]>;