@makano/rew 1.1.73 → 1.1.81
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/lib/rew/cli/cli.js +189 -144
- package/lib/rew/cli/log.js +18 -19
- package/lib/rew/cli/run.js +7 -9
- package/lib/rew/cli/utils.js +109 -95
- package/lib/rew/const/config_path.js +4 -0
- package/lib/rew/const/default.js +21 -3
- package/lib/rew/const/files.js +11 -8
- package/lib/rew/const/opt.js +6 -6
- package/lib/rew/css/theme.css +1 -1
- package/lib/rew/functions/core.js +7 -9
- package/lib/rew/functions/emitter.js +2 -2
- package/lib/rew/functions/exec.js +19 -15
- package/lib/rew/functions/export.js +4 -6
- package/lib/rew/functions/fs.js +21 -18
- package/lib/rew/functions/future.js +1 -1
- package/lib/rew/functions/import.js +55 -25
- package/lib/rew/functions/map.js +2 -5
- package/lib/rew/functions/match.js +21 -5
- package/lib/rew/functions/path.js +2 -2
- package/lib/rew/functions/require.js +16 -13
- package/lib/rew/functions/stdout.js +11 -11
- package/lib/rew/functions/types.js +67 -42
- package/lib/rew/html/ui.html +5 -6
- package/lib/rew/html/ui.js +100 -58
- package/lib/rew/main.js +3 -3
- package/lib/rew/misc/findAppInfo.js +16 -0
- package/lib/rew/misc/findAppPath.js +21 -0
- package/lib/rew/misc/seededid.js +13 -0
- package/lib/rew/models/struct.js +1 -1
- package/lib/rew/modules/compiler.js +90 -58
- package/lib/rew/modules/context.js +35 -22
- package/lib/rew/modules/runtime.js +1 -1
- package/lib/rew/pkgs/conf.js +50 -33
- package/lib/rew/pkgs/data.js +7 -2
- package/lib/rew/pkgs/date.js +8 -9
- package/lib/rew/pkgs/env.js +3 -5
- package/lib/rew/pkgs/modules/data/bintree.js +1 -1
- package/lib/rew/pkgs/modules/data/doublylinked.js +1 -1
- package/lib/rew/pkgs/modules/data/linkedList.js +1 -1
- package/lib/rew/pkgs/modules/data/queue.js +1 -2
- package/lib/rew/pkgs/modules/data/stack.js +1 -1
- package/lib/rew/pkgs/modules/threads/worker.js +31 -21
- package/lib/rew/pkgs/modules/ui/classes.js +68 -61
- package/lib/rew/pkgs/pkgs.js +5 -6
- package/lib/rew/pkgs/rune.js +437 -0
- package/lib/rew/pkgs/threads.js +30 -22
- package/lib/rew/pkgs/ui.js +68 -44
- package/package.json +8 -2
|
@@ -6,122 +6,130 @@ module.exports.uiClasses = (context, options, send, recieve, hook, rmHook) => {
|
|
|
6
6
|
const _sanitizeOptions = (options) => {
|
|
7
7
|
return {
|
|
8
8
|
...options,
|
|
9
|
-
children: options.children.map(i => i.options)
|
|
10
|
-
}
|
|
11
|
-
}
|
|
9
|
+
children: options.children.map((i) => i.options),
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
12
|
const RemWidgetOptions = struct({
|
|
13
|
-
element:
|
|
14
|
-
class:
|
|
13
|
+
element: "div",
|
|
14
|
+
class: "",
|
|
15
15
|
attr: {},
|
|
16
|
-
id:
|
|
16
|
+
id: "",
|
|
17
17
|
data: {
|
|
18
|
-
text:
|
|
18
|
+
text: "",
|
|
19
19
|
},
|
|
20
20
|
children: [],
|
|
21
|
-
uuid:
|
|
22
|
-
parent:
|
|
23
|
-
style: {}
|
|
21
|
+
uuid: "",
|
|
22
|
+
parent: "!any",
|
|
23
|
+
style: {},
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
const CreatedElements = [];
|
|
27
27
|
|
|
28
28
|
class RewWidget {
|
|
29
29
|
_emitter = emitter();
|
|
30
|
-
on(event, callback){
|
|
31
|
-
const hookID = this.uuid+
|
|
30
|
+
on(event, callback) {
|
|
31
|
+
const hookID = this.uuid + "_" + generateRandomID(4);
|
|
32
32
|
this._emitter.on(event, callback, { hookID });
|
|
33
|
-
hook(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
hook(
|
|
34
|
+
hookID,
|
|
35
|
+
"event_" + event,
|
|
36
|
+
(data) => {
|
|
37
|
+
this.emit(event, data);
|
|
38
|
+
},
|
|
39
|
+
false,
|
|
40
|
+
);
|
|
41
|
+
send({ action: "eventListen", data: { uuid: this.uuid, event, hookID } });
|
|
37
42
|
return this;
|
|
38
43
|
}
|
|
39
|
-
off(event, callback){
|
|
44
|
+
off(event, callback) {
|
|
40
45
|
this._emitter.off(event, callback, (e) => rmHook(e.hookID));
|
|
41
46
|
return this;
|
|
42
47
|
}
|
|
43
|
-
emit(event, callback){
|
|
48
|
+
emit(event, callback) {
|
|
44
49
|
this._emitter.emit(event, callback);
|
|
45
50
|
return this;
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
options = RemWidgetOptions();
|
|
49
|
-
constructor(options = RemWidgetOptions()){
|
|
54
|
+
constructor(options = RemWidgetOptions()) {
|
|
50
55
|
const config = RemWidgetOptions(options);
|
|
51
56
|
config.uuid = generateRandomID();
|
|
52
57
|
this.options = config;
|
|
53
|
-
this.options.children.forEach(child => child.parent = this);
|
|
58
|
+
this.options.children.forEach((child) => (child.parent = this));
|
|
54
59
|
this.init();
|
|
55
60
|
CreatedElements.push(this);
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
init(){
|
|
59
|
-
send({ action:
|
|
63
|
+
init() {
|
|
64
|
+
send({ action: "createElement", data: _sanitizeOptions(this.options) });
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
parent = null;
|
|
63
68
|
|
|
64
|
-
get uuid(){
|
|
69
|
+
get uuid() {
|
|
65
70
|
return this.options.uuid;
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
get id(){
|
|
73
|
+
get id() {
|
|
69
74
|
return this.options.id;
|
|
70
75
|
}
|
|
71
76
|
|
|
72
|
-
get children(){
|
|
77
|
+
get children() {
|
|
73
78
|
return this.options.children;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
find(id, recursive = true){
|
|
77
|
-
let childFound =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
find(id, recursive = true) {
|
|
82
|
+
let childFound =
|
|
83
|
+
this.children.find((e) => e.id == id) ||
|
|
84
|
+
this.children.find((e) => e.uuid == id);
|
|
85
|
+
if (childFound) return childFound;
|
|
86
|
+
else if (!recursive) return null;
|
|
87
|
+
for (let child of this.children) {
|
|
81
88
|
let subchild = child.find(id);
|
|
82
|
-
if(subchild) {
|
|
89
|
+
if (subchild) {
|
|
83
90
|
return subchild;
|
|
84
91
|
}
|
|
85
92
|
}
|
|
86
93
|
}
|
|
87
94
|
|
|
88
|
-
update(){
|
|
89
|
-
send({ action:
|
|
95
|
+
update() {
|
|
96
|
+
send({ action: "updateElement", data: _sanitizeOptions(this.options) });
|
|
90
97
|
return this;
|
|
91
98
|
}
|
|
92
99
|
|
|
93
|
-
text(text){
|
|
100
|
+
text(text) {
|
|
94
101
|
this.options.data.text = text;
|
|
95
102
|
return this.update();
|
|
96
103
|
}
|
|
97
104
|
|
|
98
|
-
data(key, value){
|
|
99
|
-
if(!value) return this.options.data[key];
|
|
105
|
+
data(key, value) {
|
|
106
|
+
if (!value) return this.options.data[key];
|
|
100
107
|
this.options.data[key] = value;
|
|
101
|
-
return this.update();
|
|
108
|
+
return this.update();
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
attr(attr, reset = false){
|
|
105
|
-
if(reset) this.options.attr = attr;
|
|
111
|
+
attr(attr, reset = false) {
|
|
112
|
+
if (reset) this.options.attr = attr;
|
|
106
113
|
else this.options.attr = { ...this.options.attr, ...attr };
|
|
107
114
|
return this.update();
|
|
108
115
|
}
|
|
109
116
|
|
|
110
|
-
style(style, reset = false){
|
|
111
|
-
if(reset) this.options.style = style;
|
|
117
|
+
style(style, reset = false) {
|
|
118
|
+
if (reset) this.options.style = style;
|
|
112
119
|
else this.options.style = { ...this.options.style, ...style };
|
|
113
120
|
return this.update();
|
|
114
121
|
}
|
|
115
122
|
|
|
116
|
-
add(child){
|
|
123
|
+
add(child) {
|
|
117
124
|
this.options.children.push(child);
|
|
118
125
|
return this.update();
|
|
119
126
|
}
|
|
120
127
|
|
|
121
|
-
remove(childId, recursive = true){
|
|
122
|
-
const child =
|
|
123
|
-
|
|
124
|
-
if(
|
|
128
|
+
remove(childId, recursive = true) {
|
|
129
|
+
const child =
|
|
130
|
+
typeof childId == "string" ? this.find(childId, recursive) : childId;
|
|
131
|
+
if (!child) return this;
|
|
132
|
+
if (recursive && child.parent !== this) {
|
|
125
133
|
child.parent.remove(child);
|
|
126
134
|
} else {
|
|
127
135
|
this.options.children.splice(this.options.children.indexOf(child), 1);
|
|
@@ -129,31 +137,30 @@ module.exports.uiClasses = (context, options, send, recieve, hook, rmHook) => {
|
|
|
129
137
|
}
|
|
130
138
|
return this;
|
|
131
139
|
}
|
|
132
|
-
|
|
133
140
|
}
|
|
134
141
|
|
|
135
142
|
class RewTextWidget extends RewWidget {
|
|
136
|
-
constructor(text =
|
|
143
|
+
constructor(text = "", options = RemWidgetOptions({})) {
|
|
137
144
|
super({
|
|
138
145
|
...options,
|
|
139
|
-
data: { ...
|
|
146
|
+
data: { ...options.data, text },
|
|
140
147
|
});
|
|
141
148
|
}
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
class StyleSheet {
|
|
145
|
-
constructor(css =
|
|
146
|
-
send({ action:
|
|
152
|
+
constructor(css = "") {
|
|
153
|
+
send({ action: "addStyleSheet", data: css });
|
|
147
154
|
}
|
|
148
155
|
}
|
|
149
156
|
|
|
150
|
-
function findElement(id){
|
|
157
|
+
function findElement(id) {
|
|
151
158
|
return new Promise((r) => {
|
|
152
159
|
const rid = generateRandomID();
|
|
153
|
-
hook(rid,
|
|
154
|
-
r(CreatedElements.find(e => e.uuid == data.uuid) || data);
|
|
160
|
+
hook(rid, "findElement", (data) => {
|
|
161
|
+
r(CreatedElements.find((e) => e.uuid == data.uuid) || data);
|
|
155
162
|
});
|
|
156
|
-
send({ action:
|
|
163
|
+
send({ action: "findElement", data: { id, rid } });
|
|
157
164
|
});
|
|
158
165
|
}
|
|
159
166
|
|
|
@@ -165,9 +172,9 @@ module.exports.uiClasses = (context, options, send, recieve, hook, rmHook) => {
|
|
|
165
172
|
// }, false);
|
|
166
173
|
|
|
167
174
|
const Transmitter = {
|
|
168
|
-
send: (data) => send({ action:
|
|
169
|
-
recieve: (cb) => recieve((data) => cb(data.data))
|
|
170
|
-
}
|
|
175
|
+
send: (data) => send({ action: "message", data }),
|
|
176
|
+
recieve: (cb) => recieve((data) => cb(data.data)),
|
|
177
|
+
};
|
|
171
178
|
|
|
172
179
|
return {
|
|
173
180
|
Widget: RewWidget,
|
|
@@ -175,6 +182,6 @@ module.exports.uiClasses = (context, options, send, recieve, hook, rmHook) => {
|
|
|
175
182
|
WidgetOptions: RemWidgetOptions,
|
|
176
183
|
findElement,
|
|
177
184
|
StyleSheet: StyleSheet,
|
|
178
|
-
Transmitter
|
|
179
|
-
}
|
|
180
|
-
}
|
|
185
|
+
Transmitter,
|
|
186
|
+
};
|
|
187
|
+
};
|
package/lib/rew/pkgs/pkgs.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
2
|
const fs = require("fs");
|
|
3
3
|
|
|
4
|
-
|
|
5
4
|
module.exports = {
|
|
6
5
|
findPackage(pkg) {
|
|
7
|
-
if(pkg ==
|
|
8
|
-
return fs.existsSync(path.resolve(__dirname,
|
|
6
|
+
if (pkg == "pkgs") return false;
|
|
7
|
+
return fs.existsSync(path.resolve(__dirname, "./" + pkg + ".js"));
|
|
8
|
+
},
|
|
9
|
+
getPackage(pkg) {
|
|
10
|
+
return require("./" + pkg);
|
|
9
11
|
},
|
|
10
|
-
getPackage(pkg){
|
|
11
|
-
return require('./'+pkg);
|
|
12
|
-
}
|
|
13
12
|
};
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const { v4: uuidv4 } = require("uuid");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const msgpack = require("tiny-msgpack");
|
|
5
|
+
const crypto = require("crypto");
|
|
6
|
+
const { CONFIG_PATH } = require("../const/config_path");
|
|
7
|
+
|
|
8
|
+
const ENCRYPTION_KEY =
|
|
9
|
+
"e6ad8b0792b9e0472ea44d1f3adfd1d503182efcce25991b05cc5ef83f307ffc";
|
|
10
|
+
|
|
11
|
+
class Change {
|
|
12
|
+
constructor(values) {
|
|
13
|
+
this.values = values;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class PopChange extends Change {}
|
|
18
|
+
|
|
19
|
+
class PushChange extends Change {}
|
|
20
|
+
|
|
21
|
+
const runePush = (...values) => new PushChange(values);
|
|
22
|
+
const runePop = (...values) => new PopChange(values);
|
|
23
|
+
|
|
24
|
+
function makeRef(value, props = "") {
|
|
25
|
+
if (!value["@rune.id"]) return null;
|
|
26
|
+
const collection = getCollectionFromID(value["@rune.id"]);
|
|
27
|
+
const ref = collection + "." + value["@rune.id"];
|
|
28
|
+
return "@rune.ref " + ref + props;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const eid = (s, diff) =>
|
|
32
|
+
s
|
|
33
|
+
.split("")
|
|
34
|
+
.map((i) => {
|
|
35
|
+
let charCode = i.charCodeAt(0) + diff;
|
|
36
|
+
if (charCode > 122) {
|
|
37
|
+
charCode -= 26;
|
|
38
|
+
}
|
|
39
|
+
return String.fromCharCode(charCode);
|
|
40
|
+
})
|
|
41
|
+
.join("");
|
|
42
|
+
|
|
43
|
+
function generateID(id, collection) {
|
|
44
|
+
return eid(collection, 5) + "+" + id;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getCollectionFromID(id) {
|
|
48
|
+
return eid(id.split("+")[0], -5);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const createDB = (dbName, dirname, dbData = {}, encryptionKey) => {
|
|
52
|
+
const dbDirPath = path.join(dirname, dbName);
|
|
53
|
+
const mainFilePath = path.join(dbDirPath, "main.bin");
|
|
54
|
+
const algorithm = "aes-256-ctr";
|
|
55
|
+
|
|
56
|
+
if (!fs.existsSync(dbDirPath)) {
|
|
57
|
+
fs.mkdirSync(dbDirPath);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const encrypt = (data) => {
|
|
61
|
+
const iv = crypto.randomBytes(16);
|
|
62
|
+
const cipher = crypto.createCipheriv(
|
|
63
|
+
algorithm,
|
|
64
|
+
Buffer.from(encryptionKey, "hex"),
|
|
65
|
+
iv,
|
|
66
|
+
);
|
|
67
|
+
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
68
|
+
return Buffer.concat([iv, encrypted]);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const decrypt = (data) => {
|
|
72
|
+
const iv = data.slice(0, 16);
|
|
73
|
+
const encryptedData = data.slice(16);
|
|
74
|
+
const decipher = crypto.createDecipheriv(
|
|
75
|
+
algorithm,
|
|
76
|
+
Buffer.from(encryptionKey, "hex"),
|
|
77
|
+
iv,
|
|
78
|
+
);
|
|
79
|
+
const decrypted = Buffer.concat([
|
|
80
|
+
decipher.update(encryptedData),
|
|
81
|
+
decipher.final(),
|
|
82
|
+
]);
|
|
83
|
+
return decrypted;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const serializeData = (data) => {
|
|
87
|
+
return msgpack.encode(data);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const deserializeData = (buffer) => {
|
|
91
|
+
return msgpack.decode(decrypt(buffer));
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const getData = () => {
|
|
95
|
+
return readMainData().data;
|
|
96
|
+
};
|
|
97
|
+
getData.key = (key) => {
|
|
98
|
+
return getData()[key];
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const setData = (data) => {
|
|
102
|
+
const newData = readMainData();
|
|
103
|
+
for (let i in data) if (data[i] !== undefined) newData.data[i] = data[i];
|
|
104
|
+
writeMainData(newData);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
setData.key = (key, value) => {
|
|
108
|
+
setData({ [key]: value });
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
setData.rm = (key) => {
|
|
112
|
+
setData({ [key]: undefined });
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
setData.reset = () => {
|
|
116
|
+
writeMainData({
|
|
117
|
+
...readMainData(),
|
|
118
|
+
data: { ...dbData, name: dbName },
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const readMainData = () => {
|
|
123
|
+
if (!fs.existsSync(mainFilePath)) {
|
|
124
|
+
writeMainData({
|
|
125
|
+
collections: [],
|
|
126
|
+
data: { ...dbData, name: dbName },
|
|
127
|
+
maps: [],
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const buffer = fs.readFileSync(mainFilePath);
|
|
131
|
+
return deserializeData(buffer);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const writeMainData = (data) => {
|
|
135
|
+
const buffer = encrypt(serializeData(data));
|
|
136
|
+
fs.writeFileSync(mainFilePath, buffer);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const readDataFile = (filePath) => {
|
|
140
|
+
const buffer = fs.readFileSync(filePath);
|
|
141
|
+
return deserializeData(buffer);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const writeDataFile = (filePath, data) => {
|
|
145
|
+
const buffer = encrypt(serializeData(data));
|
|
146
|
+
fs.writeFileSync(filePath, buffer);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const collection = (collectionName) => {
|
|
150
|
+
const collectionFilePath = path.join(dbDirPath, `${collectionName}.col`);
|
|
151
|
+
|
|
152
|
+
const insert = (record) => {
|
|
153
|
+
const mainData = readMainData();
|
|
154
|
+
if (!mainData.collections.includes(collectionName)) {
|
|
155
|
+
mainData.collections.push(collectionName);
|
|
156
|
+
writeMainData(mainData);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let data = [];
|
|
160
|
+
if (fs.existsSync(collectionFilePath)) {
|
|
161
|
+
data = readDataFile(collectionFilePath);
|
|
162
|
+
}
|
|
163
|
+
const id = uuidv4();
|
|
164
|
+
record["@rune.id"] = generateID(id, collectionName);
|
|
165
|
+
data.push(record);
|
|
166
|
+
writeDataFile(collectionFilePath, data);
|
|
167
|
+
return record;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const read = (id, evaluate = true) => {
|
|
171
|
+
if (typeof id == "object" && "@rune.id" in id) id = id["@rune.id"];
|
|
172
|
+
if (!fs.existsSync(collectionFilePath)) return null;
|
|
173
|
+
const data = readDataFile(collectionFilePath);
|
|
174
|
+
const record = data.find((record) => record["@rune.id"] === id);
|
|
175
|
+
if (record) {
|
|
176
|
+
return evaluateRecord(record);
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const evaluateRecord = (record, prevRecord) => {
|
|
182
|
+
const evaluateValue = (val) => {
|
|
183
|
+
if (typeof val == "string" && val.startsWith("@rune.ref")) {
|
|
184
|
+
const ref = val.split("@rune.ref")[1].trim();
|
|
185
|
+
const refData = findRef(ref, false);
|
|
186
|
+
if (!refData) {
|
|
187
|
+
return null;
|
|
188
|
+
} else {
|
|
189
|
+
let value = refData;
|
|
190
|
+
if (refData["@rune.id"]) {
|
|
191
|
+
value =
|
|
192
|
+
prevRecord && prevRecord["@rune.id"] == refData["@rune.id"]
|
|
193
|
+
? prevRecord
|
|
194
|
+
: evaluateRecord(refData, record);
|
|
195
|
+
}
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (Array.isArray(val)) {
|
|
200
|
+
val = val.map((i) => evaluateValue(i));
|
|
201
|
+
}
|
|
202
|
+
return val;
|
|
203
|
+
};
|
|
204
|
+
for (let i in record) {
|
|
205
|
+
const val = record[i];
|
|
206
|
+
record[i] = evaluateValue(val);
|
|
207
|
+
}
|
|
208
|
+
return record;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const update = (caseRecord, newRecord) => {
|
|
212
|
+
let id;
|
|
213
|
+
if (typeof caseRecord === "string") {
|
|
214
|
+
id = caseRecord;
|
|
215
|
+
} else if (typeof caseRecord === "object") {
|
|
216
|
+
const data = readDataFile(collectionFilePath);
|
|
217
|
+
const record = data.find((record) => {
|
|
218
|
+
for (const key in caseRecord) {
|
|
219
|
+
if (record[key] !== caseRecord[key]) return false;
|
|
220
|
+
}
|
|
221
|
+
return true;
|
|
222
|
+
});
|
|
223
|
+
if (record) {
|
|
224
|
+
id = record["@rune.id"];
|
|
225
|
+
} else {
|
|
226
|
+
return null; // No matching record found
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (!id) return null;
|
|
231
|
+
|
|
232
|
+
const data = readDataFile(collectionFilePath);
|
|
233
|
+
const index = data.findIndex((record) => record["@rune.id"] === id);
|
|
234
|
+
if (index !== -1) {
|
|
235
|
+
const oldRecord = data[index];
|
|
236
|
+
for (const key in newRecord) {
|
|
237
|
+
const value = newRecord[key];
|
|
238
|
+
if (value instanceof PushChange) {
|
|
239
|
+
if (!oldRecord[key] || !Array.isArray(oldRecord[key])) {
|
|
240
|
+
oldRecord[key] = [];
|
|
241
|
+
}
|
|
242
|
+
oldRecord[key].push(...value.values);
|
|
243
|
+
} else if (value instanceof PopChange) {
|
|
244
|
+
if (oldRecord[key] && Array.isArray(oldRecord[key])) {
|
|
245
|
+
value.values.forEach((val) => {
|
|
246
|
+
const index = oldRecord[key].indexOf(val);
|
|
247
|
+
if (index !== -1) {
|
|
248
|
+
oldRecord[key].splice(index, 1);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
oldRecord[key] = value;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
data[index] = oldRecord;
|
|
257
|
+
writeDataFile(collectionFilePath, data);
|
|
258
|
+
return data[index];
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const find = (criteria) => {
|
|
264
|
+
if (typeof criteria == "string") return read(criteria);
|
|
265
|
+
if (!criteria || typeof criteria !== "object") return null;
|
|
266
|
+
|
|
267
|
+
const data = readDataFile(collectionFilePath);
|
|
268
|
+
const record =
|
|
269
|
+
data.find((record) => {
|
|
270
|
+
for (const key in criteria) {
|
|
271
|
+
if (record[key] !== criteria[key]) return false;
|
|
272
|
+
}
|
|
273
|
+
return true;
|
|
274
|
+
}) || null;
|
|
275
|
+
if (record) {
|
|
276
|
+
return evaluateRecord(record);
|
|
277
|
+
}
|
|
278
|
+
return null;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const remove = (id) => {
|
|
282
|
+
if ("@rune.id" in id) id = id["@rune.id"];
|
|
283
|
+
if (!fs.existsSync(collectionFilePath)) return false;
|
|
284
|
+
let data = readDataFile(collectionFilePath);
|
|
285
|
+
const index = data.findIndex((record) => record["@rune.id"] === id);
|
|
286
|
+
if (index !== -1) {
|
|
287
|
+
data.splice(index, 1);
|
|
288
|
+
writeDataFile(collectionFilePath, data);
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
return false;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const list = () => {
|
|
295
|
+
if (!fs.existsSync(collectionFilePath)) return [];
|
|
296
|
+
const data = readDataFile(collectionFilePath);
|
|
297
|
+
return data.map((rec) => evaluateRecord(rec));
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const map = (cb, mutate = false) => {
|
|
301
|
+
const data = readDataFile(collectionFilePath);
|
|
302
|
+
const mappedData = data.map(cb);
|
|
303
|
+
if (mutate) {
|
|
304
|
+
writeDataFile(collectionFilePath, mappedData);
|
|
305
|
+
}
|
|
306
|
+
return mappedData;
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
const transform = (cb, mutate = true) => {
|
|
310
|
+
const data = readDataFile(collectionFilePath);
|
|
311
|
+
const transformedData = cb(data);
|
|
312
|
+
if (mutate) {
|
|
313
|
+
writeDataFile(collectionFilePath, transformedData);
|
|
314
|
+
}
|
|
315
|
+
return transformedData;
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const filter = (cb, mutate = false) => {
|
|
319
|
+
const data = readDataFile(collectionFilePath);
|
|
320
|
+
const filteredData = data.filter(cb);
|
|
321
|
+
if (mutate) {
|
|
322
|
+
writeDataFile(collectionFilePath, filteredData);
|
|
323
|
+
}
|
|
324
|
+
return filteredData;
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
const sort = (cb, mutate = false) => {
|
|
328
|
+
const data = readDataFile(collectionFilePath);
|
|
329
|
+
const sortedData = data.sort(cb);
|
|
330
|
+
if (mutate) {
|
|
331
|
+
writeDataFile(collectionFilePath, sortedData);
|
|
332
|
+
}
|
|
333
|
+
return sortedData;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
return {
|
|
337
|
+
insert,
|
|
338
|
+
read,
|
|
339
|
+
update,
|
|
340
|
+
remove,
|
|
341
|
+
find,
|
|
342
|
+
map,
|
|
343
|
+
transform,
|
|
344
|
+
filter,
|
|
345
|
+
sort,
|
|
346
|
+
list,
|
|
347
|
+
};
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const findRef = (ref, evaluate = true) => {
|
|
351
|
+
const [name, id, ...rest] = ref.split(".");
|
|
352
|
+
const col = collection(name);
|
|
353
|
+
const record = col.read(id, evaluate);
|
|
354
|
+
if (rest.length === 0) return record;
|
|
355
|
+
let value = record;
|
|
356
|
+
for (const prop of rest) {
|
|
357
|
+
if (typeof value != "object") break;
|
|
358
|
+
if (!(prop in value)) return null;
|
|
359
|
+
value = value[prop];
|
|
360
|
+
}
|
|
361
|
+
return value;
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
const map = (mapName) => {
|
|
365
|
+
const mapFilePath = path.join(dbDirPath, `${mapName}.map`);
|
|
366
|
+
|
|
367
|
+
const set = (key, value) => {
|
|
368
|
+
const mainData = readMainData();
|
|
369
|
+
if (!mainData.maps.includes(mapName)) {
|
|
370
|
+
mainData.maps.push(mapName);
|
|
371
|
+
writeMainData(mainData);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
let data = {};
|
|
375
|
+
if (fs.existsSync(mapFilePath)) {
|
|
376
|
+
data = readDataFile(mapFilePath);
|
|
377
|
+
}
|
|
378
|
+
data[key] = value;
|
|
379
|
+
writeDataFile(mapFilePath, data);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
const get = (key) => {
|
|
383
|
+
if (!fs.existsSync(mapFilePath)) return null;
|
|
384
|
+
const data = readDataFile(mapFilePath);
|
|
385
|
+
return data[key] || null;
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const remove = (key) => {
|
|
389
|
+
if (!fs.existsSync(mapFilePath)) return false;
|
|
390
|
+
const data = readDataFile(mapFilePath);
|
|
391
|
+
if (data[key]) {
|
|
392
|
+
delete data[key];
|
|
393
|
+
writeDataFile(mapFilePath, data);
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
return false;
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
const transform = (cb, mutate = false) => {
|
|
400
|
+
const data = readDataFile(mapFilePath);
|
|
401
|
+
const transformedData = cb(data);
|
|
402
|
+
if (mutate) {
|
|
403
|
+
writeDataFile(mapFilePath, transformedData);
|
|
404
|
+
}
|
|
405
|
+
return transformedData;
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
const list = () => {
|
|
409
|
+
if (!fs.existsSync(mapFilePath)) return {};
|
|
410
|
+
const data = readDataFile(mapFilePath);
|
|
411
|
+
return data;
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
return { set, get, remove, list, transform };
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
readMainData();
|
|
418
|
+
|
|
419
|
+
return { setData, getData, collection, findRef, makeRef, map };
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
module.exports = (context) => ({
|
|
423
|
+
_onImport() {
|
|
424
|
+
delete this.createDB;
|
|
425
|
+
return this;
|
|
426
|
+
},
|
|
427
|
+
db(dbname, data = {}, encryptionKey) {
|
|
428
|
+
if (!context.app) throw new Error("rune can only be used in apps");
|
|
429
|
+
const pkg = path.join(CONFIG_PATH, context.app.config.package, "db");
|
|
430
|
+
if (!fs.existsSync(pkg)) fs.mkdirSync(pkg, { recursive: true });
|
|
431
|
+
return createDB(dbname, pkg, data, encryptionKey || ENCRYPTION_KEY);
|
|
432
|
+
},
|
|
433
|
+
makeRef,
|
|
434
|
+
runePop,
|
|
435
|
+
runePush,
|
|
436
|
+
createDB,
|
|
437
|
+
});
|