@makano/rew 1.1.73 → 1.1.81

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. package/lib/rew/cli/cli.js +189 -144
  2. package/lib/rew/cli/log.js +18 -19
  3. package/lib/rew/cli/run.js +7 -9
  4. package/lib/rew/cli/utils.js +109 -95
  5. package/lib/rew/const/config_path.js +4 -0
  6. package/lib/rew/const/default.js +21 -3
  7. package/lib/rew/const/files.js +11 -8
  8. package/lib/rew/const/opt.js +6 -6
  9. package/lib/rew/css/theme.css +1 -1
  10. package/lib/rew/functions/core.js +7 -9
  11. package/lib/rew/functions/emitter.js +2 -2
  12. package/lib/rew/functions/exec.js +19 -15
  13. package/lib/rew/functions/export.js +4 -6
  14. package/lib/rew/functions/fs.js +21 -18
  15. package/lib/rew/functions/future.js +1 -1
  16. package/lib/rew/functions/import.js +55 -25
  17. package/lib/rew/functions/map.js +2 -5
  18. package/lib/rew/functions/match.js +21 -5
  19. package/lib/rew/functions/path.js +2 -2
  20. package/lib/rew/functions/require.js +16 -13
  21. package/lib/rew/functions/stdout.js +11 -11
  22. package/lib/rew/functions/types.js +67 -42
  23. package/lib/rew/html/ui.html +5 -6
  24. package/lib/rew/html/ui.js +100 -58
  25. package/lib/rew/main.js +3 -3
  26. package/lib/rew/misc/findAppInfo.js +16 -0
  27. package/lib/rew/misc/findAppPath.js +21 -0
  28. package/lib/rew/misc/seededid.js +13 -0
  29. package/lib/rew/models/struct.js +1 -1
  30. package/lib/rew/modules/compiler.js +90 -58
  31. package/lib/rew/modules/context.js +35 -22
  32. package/lib/rew/modules/runtime.js +1 -1
  33. package/lib/rew/pkgs/conf.js +50 -33
  34. package/lib/rew/pkgs/data.js +7 -2
  35. package/lib/rew/pkgs/date.js +8 -9
  36. package/lib/rew/pkgs/env.js +3 -5
  37. package/lib/rew/pkgs/modules/data/bintree.js +1 -1
  38. package/lib/rew/pkgs/modules/data/doublylinked.js +1 -1
  39. package/lib/rew/pkgs/modules/data/linkedList.js +1 -1
  40. package/lib/rew/pkgs/modules/data/queue.js +1 -2
  41. package/lib/rew/pkgs/modules/data/stack.js +1 -1
  42. package/lib/rew/pkgs/modules/threads/worker.js +31 -21
  43. package/lib/rew/pkgs/modules/ui/classes.js +68 -61
  44. package/lib/rew/pkgs/pkgs.js +5 -6
  45. package/lib/rew/pkgs/rune.js +437 -0
  46. package/lib/rew/pkgs/threads.js +30 -22
  47. package/lib/rew/pkgs/ui.js +68 -44
  48. 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: 'div',
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: '!any',
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+'_'+generateRandomID(4);
30
+ on(event, callback) {
31
+ const hookID = this.uuid + "_" + generateRandomID(4);
32
32
  this._emitter.on(event, callback, { hookID });
33
- hook(hookID, 'event_'+event, (data) => {
34
- this.emit(event, data);
35
- }, false);
36
- send({ action: 'eventListen', data: { uuid: this.uuid, event, hookID } })
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: 'createElement', data: _sanitizeOptions(this.options) })
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 = this.children.find(e => e.id == id) || this.children.find(e => e.uuid == id);
78
- if(childFound) return childFound;
79
- else if(!recursive) return null;
80
- for(let child of this.children){
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: 'updateElement', data: _sanitizeOptions(this.options) });
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 = typeof childId == "string" ? this.find(childId, recursive) : childId;
123
- if(!child) return this;
124
- if(recursive && child.parent !== this){
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 = '', options = RemWidgetOptions({})){
143
+ constructor(text = "", options = RemWidgetOptions({})) {
137
144
  super({
138
145
  ...options,
139
- data: { ...(options.data), text }
146
+ data: { ...options.data, text },
140
147
  });
141
148
  }
142
149
  }
143
150
 
144
151
  class StyleSheet {
145
- constructor(css = ''){
146
- send({ action: 'addStyleSheet', data: css });
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, 'findElement', (data) => {
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: 'findElement', data: { id, rid } });
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: 'message', data }),
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
+ };
@@ -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 == 'pkgs') return false;
8
- return fs.existsSync(path.resolve(__dirname, './'+pkg+'.js'));
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
+ });