sehawq.db 2.4.2 → 4.0.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/.github/workflows/npm-publish.yml +1 -1
- package/index.js +2 -0
- package/package.json +28 -7
- package/readme.md +342 -235
- package/src/core/Database.js +295 -0
- package/src/core/Events.js +286 -0
- package/src/core/IndexManager.js +814 -0
- package/src/core/Persistence.js +376 -0
- package/src/core/QueryEngine.js +448 -0
- package/src/core/Storage.js +322 -0
- package/src/core/Validator.js +325 -0
- package/src/index.js +90 -469
- package/src/performance/Cache.js +339 -0
- package/src/performance/LazyLoader.js +355 -0
- package/src/performance/MemoryManager.js +496 -0
- package/src/server/api.js +688 -0
- package/src/server/websocket.js +528 -0
- package/src/utils/benchmark.js +52 -0
- package/src/utils/dot-notation.js +248 -0
- package/src/utils/helpers.js +276 -0
- package/src/utils/profiler.js +71 -0
- package/src/version.js +38 -0
package/src/index.js
CHANGED
|
@@ -1,495 +1,116 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
1
|
+
// src/index.js - The heart of SehawqDB v4.0.0
|
|
2
|
+
const Database = require('./core/Database');
|
|
3
|
+
const QueryEngine = require('./core/QueryEngine');
|
|
4
|
+
const IndexManager = require('./core/IndexManager');
|
|
5
|
+
const Storage = require('./core/Storage');
|
|
4
6
|
|
|
5
|
-
class SehawqDB
|
|
6
|
-
/**
|
|
7
|
-
* Create a new SehawqDB instance.
|
|
8
|
-
* @param {Object} options
|
|
9
|
-
* @param {string} [options.path="sehawq.json"] File path for storage.
|
|
10
|
-
* @param {number} [options.autoSaveInterval=0] Autosave interval in ms (0 disables autosave).
|
|
11
|
-
*/
|
|
7
|
+
class SehawqDB {
|
|
12
8
|
constructor(options = {}) {
|
|
13
|
-
|
|
14
|
-
this.
|
|
15
|
-
this.
|
|
16
|
-
this.data = {};
|
|
17
|
-
|
|
18
|
-
this._init();
|
|
19
|
-
|
|
20
|
-
if (this.autoSaveInterval > 0) {
|
|
21
|
-
this._interval = setInterval(() => this.save(), this.autoSaveInterval);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async _init() {
|
|
26
|
-
try {
|
|
27
|
-
await fs.access(this.filePath);
|
|
28
|
-
} catch {
|
|
29
|
-
await fs.writeFile(this.filePath, JSON.stringify({}), "utf8");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const content = await fs.readFile(this.filePath, "utf8");
|
|
34
|
-
this.data = JSON.parse(content);
|
|
35
|
-
} catch {
|
|
36
|
-
this.data = {};
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ---------------- Core methods ----------------
|
|
41
|
-
set(key, value) {
|
|
42
|
-
this._setByPath(key, value);
|
|
43
|
-
this.emit("set", { key, value });
|
|
44
|
-
this.save();
|
|
45
|
-
return value;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
get(key) {
|
|
49
|
-
return this._getByPath(key);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
delete(key) {
|
|
53
|
-
this._deleteByPath(key);
|
|
54
|
-
this.emit("delete", { key });
|
|
55
|
-
this.save();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
has(key) {
|
|
59
|
-
return this._getByPath(key) !== undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
all() {
|
|
63
|
-
return this.data;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
clear() {
|
|
67
|
-
this.data = {};
|
|
68
|
-
this.emit("clear");
|
|
69
|
-
this.save();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
keys() {
|
|
73
|
-
return Object.keys(this.data);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
values() {
|
|
77
|
-
return Object.values(this.data);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ---------------- Array helpers ----------------
|
|
81
|
-
push(key, value) {
|
|
82
|
-
let arr = this._getByPath(key);
|
|
83
|
-
if (!Array.isArray(arr)) arr = [];
|
|
84
|
-
arr.push(value);
|
|
85
|
-
this._setByPath(key, arr);
|
|
86
|
-
this.emit("push", { key, value });
|
|
87
|
-
this.save();
|
|
88
|
-
return arr;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
pull(key, value) {
|
|
92
|
-
let arr = this._getByPath(key);
|
|
93
|
-
if (!Array.isArray(arr)) return [];
|
|
94
|
-
arr = arr.filter(v => v !== value);
|
|
95
|
-
this._setByPath(key, arr);
|
|
96
|
-
this.emit("pull", { key, value });
|
|
97
|
-
this.save();
|
|
98
|
-
return arr;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ---------------- Math helpers ----------------
|
|
102
|
-
add(key, number) {
|
|
103
|
-
let val = this._getByPath(key);
|
|
104
|
-
if (typeof val !== "number") val = 0;
|
|
105
|
-
val += number;
|
|
106
|
-
this._setByPath(key, val);
|
|
107
|
-
this.emit("add", { key, number });
|
|
108
|
-
this.save();
|
|
109
|
-
return val;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
subtract(key, number) {
|
|
113
|
-
return this.add(key, -number);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// ---------------- NEW: Query System ----------------
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Find all entries that match the filter function
|
|
120
|
-
* @param {Function} filter - Filter function (item, key) => boolean
|
|
121
|
-
* @returns {QueryResult} Chainable query result
|
|
122
|
-
*/
|
|
123
|
-
find(filter) {
|
|
124
|
-
const results = [];
|
|
125
|
-
|
|
126
|
-
if (typeof filter === 'function') {
|
|
127
|
-
for (const [key, value] of Object.entries(this.data)) {
|
|
128
|
-
if (filter(value, key)) {
|
|
129
|
-
results.push({ key, value });
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
} else {
|
|
133
|
-
// Eğer filter verilmezse tüm dataları döndür
|
|
134
|
-
for (const [key, value] of Object.entries(this.data)) {
|
|
135
|
-
results.push({ key, value });
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return new QueryResult(results);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Find first entry that matches the filter
|
|
144
|
-
* @param {Function} filter - Filter function
|
|
145
|
-
* @returns {Object|undefined} First matching item
|
|
146
|
-
*/
|
|
147
|
-
findOne(filter) {
|
|
148
|
-
if (typeof filter === 'function') {
|
|
149
|
-
for (const [key, value] of Object.entries(this.data)) {
|
|
150
|
-
if (filter(value, key)) {
|
|
151
|
-
return { key, value };
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return undefined;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Filter by field value with operators
|
|
160
|
-
* @param {string} field - Field name (supports dot notation)
|
|
161
|
-
* @param {string} operator - Comparison operator (=, !=, >, <, >=, <=, in, contains)
|
|
162
|
-
* @param {*} value - Value to compare
|
|
163
|
-
* @returns {QueryResult} Chainable query result
|
|
164
|
-
*/
|
|
165
|
-
where(field, operator, value) {
|
|
166
|
-
return this.find((item, key) => {
|
|
167
|
-
const fieldValue = this._getValueByPath(item, field);
|
|
168
|
-
|
|
169
|
-
switch (operator) {
|
|
170
|
-
case '=':
|
|
171
|
-
case '==':
|
|
172
|
-
return fieldValue === value;
|
|
173
|
-
case '!=':
|
|
174
|
-
return fieldValue !== value;
|
|
175
|
-
case '>':
|
|
176
|
-
return fieldValue > value;
|
|
177
|
-
case '<':
|
|
178
|
-
return fieldValue < value;
|
|
179
|
-
case '>=':
|
|
180
|
-
return fieldValue >= value;
|
|
181
|
-
case '<=':
|
|
182
|
-
return fieldValue <= value;
|
|
183
|
-
case 'in':
|
|
184
|
-
return Array.isArray(value) && value.includes(fieldValue);
|
|
185
|
-
case 'contains':
|
|
186
|
-
return typeof fieldValue === 'string' && fieldValue.includes(value);
|
|
187
|
-
case 'startsWith':
|
|
188
|
-
return typeof fieldValue === 'string' && fieldValue.startsWith(value);
|
|
189
|
-
case 'endsWith':
|
|
190
|
-
return typeof fieldValue === 'string' && fieldValue.endsWith(value);
|
|
191
|
-
default:
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// ---------------- NEW: Aggregation System ----------------
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Count total entries
|
|
201
|
-
* @param {Function} [filter] - Optional filter function
|
|
202
|
-
* @returns {number} Count of entries
|
|
203
|
-
*/
|
|
204
|
-
count(filter) {
|
|
205
|
-
if (filter) {
|
|
206
|
-
return this.find(filter).count();
|
|
207
|
-
}
|
|
208
|
-
return Object.keys(this.data).length;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Sum numeric values by field
|
|
213
|
-
* @param {string} field - Field name to sum
|
|
214
|
-
* @param {Function} [filter] - Optional filter function
|
|
215
|
-
* @returns {number} Sum of values
|
|
216
|
-
*/
|
|
217
|
-
sum(field, filter) {
|
|
218
|
-
const items = filter ? this.find(filter).toArray() : this.find().toArray();
|
|
219
|
-
return items.reduce((sum, item) => {
|
|
220
|
-
const val = this._getValueByPath(item.value, field);
|
|
221
|
-
return sum + (typeof val === 'number' ? val : 0);
|
|
222
|
-
}, 0);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Average of numeric values by field
|
|
227
|
-
* @param {string} field - Field name to average
|
|
228
|
-
* @param {Function} [filter] - Optional filter function
|
|
229
|
-
* @returns {number} Average of values
|
|
230
|
-
*/
|
|
231
|
-
avg(field, filter) {
|
|
232
|
-
const items = filter ? this.find(filter).toArray() : this.find().toArray();
|
|
233
|
-
if (items.length === 0) return 0;
|
|
9
|
+
this.database = new Database(options);
|
|
10
|
+
this.queryEngine = new QueryEngine(this.database);
|
|
11
|
+
this.indexManager = new IndexManager(this.database, options);
|
|
234
12
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Minimum value by field
|
|
245
|
-
* @param {string} field - Field name
|
|
246
|
-
* @param {Function} [filter] - Optional filter function
|
|
247
|
-
* @returns {*} Minimum value
|
|
248
|
-
*/
|
|
249
|
-
min(field, filter) {
|
|
250
|
-
const items = filter ? this.find(filter).toArray() : this.find().toArray();
|
|
251
|
-
if (items.length === 0) return undefined;
|
|
13
|
+
// Database methods
|
|
14
|
+
this.set = this.database.set.bind(this.database);
|
|
15
|
+
this.get = this.database.get.bind(this.database);
|
|
16
|
+
this.delete = this.database.delete.bind(this.database);
|
|
17
|
+
this.has = this.database.has.bind(this.database);
|
|
18
|
+
this.all = this.database.all.bind(this.database);
|
|
19
|
+
this.clear = this.database.clear.bind(this.database);
|
|
252
20
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
* @returns {*} Maximum value
|
|
264
|
-
*/
|
|
265
|
-
max(field, filter) {
|
|
266
|
-
const items = filter ? this.find(filter).toArray() : this.find().toArray();
|
|
267
|
-
if (items.length === 0) return undefined;
|
|
21
|
+
// 🔥 Query methods
|
|
22
|
+
this.find = this.queryEngine.find.bind(this.queryEngine);
|
|
23
|
+
this.where = this.queryEngine.where.bind(this.queryEngine);
|
|
24
|
+
this.findAll = this.queryEngine.findAll.bind(this.queryEngine);
|
|
25
|
+
this.count = this.queryEngine.count.bind(this.queryEngine);
|
|
26
|
+
this.sum = this.queryEngine.sum.bind(this.queryEngine);
|
|
27
|
+
this.avg = this.queryEngine.avg.bind(this.queryEngine);
|
|
28
|
+
this.min = this.queryEngine.min.bind(this.queryEngine);
|
|
29
|
+
this.max = this.queryEngine.max.bind(this.queryEngine);
|
|
30
|
+
this.groupBy = this.queryEngine.groupBy.bind(this.queryEngine);
|
|
268
31
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Group entries by field value
|
|
277
|
-
* @param {string} field - Field name to group by
|
|
278
|
-
* @param {Function} [filter] - Optional filter function
|
|
279
|
-
* @returns {Object} Grouped results
|
|
280
|
-
*/
|
|
281
|
-
groupBy(field, filter) {
|
|
282
|
-
const items = filter ? this.find(filter).toArray() : this.find().toArray();
|
|
283
|
-
const groups = {};
|
|
32
|
+
// 🔥 Index methods
|
|
33
|
+
this.createIndex = this.indexManager.createIndex.bind(this.indexManager);
|
|
34
|
+
this.dropIndex = this.indexManager.dropIndex.bind(this.indexManager);
|
|
35
|
+
this.getIndexes = this.indexManager.getIndexes.bind(this.indexManager);
|
|
284
36
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
groups[key] = [];
|
|
291
|
-
}
|
|
292
|
-
groups[key].push(item);
|
|
293
|
-
});
|
|
37
|
+
// 🔥 ARRAY & MATH Methods
|
|
38
|
+
this.push = this.database.push?.bind(this.database) || this._fallbackPush.bind(this);
|
|
39
|
+
this.pull = this.database.pull?.bind(this.database) || this._fallbackPull.bind(this);
|
|
40
|
+
this.add = this.database.add?.bind(this.database) || this._fallbackAdd.bind(this);
|
|
41
|
+
this.subtract = this.database.subtract?.bind(this.database) || this._fallbackSubtract.bind(this);
|
|
294
42
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
await fs.rename(tmpPath, this.filePath);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// ---------------- Internal utilities ----------------
|
|
319
|
-
_getByPath(pathStr) {
|
|
320
|
-
const keys = pathStr.split(".");
|
|
321
|
-
let obj = this.data;
|
|
322
|
-
for (const k of keys) {
|
|
323
|
-
if (obj && Object.prototype.hasOwnProperty.call(obj, k)) {
|
|
324
|
-
obj = obj[k];
|
|
325
|
-
} else {
|
|
326
|
-
return undefined;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return obj;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
_setByPath(pathStr, value) {
|
|
333
|
-
const keys = pathStr.split(".");
|
|
334
|
-
let obj = this.data;
|
|
335
|
-
while (keys.length > 1) {
|
|
336
|
-
const k = keys.shift();
|
|
337
|
-
if (!obj[k] || typeof obj[k] !== "object") obj[k] = {};
|
|
338
|
-
obj = obj[k];
|
|
339
|
-
}
|
|
340
|
-
obj[keys[0]] = value;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
_deleteByPath(pathStr) {
|
|
344
|
-
const keys = pathStr.split(".");
|
|
345
|
-
let obj = this.data;
|
|
346
|
-
while (keys.length > 1) {
|
|
347
|
-
const k = keys.shift();
|
|
348
|
-
if (!obj[k]) return;
|
|
349
|
-
obj = obj[k];
|
|
350
|
-
}
|
|
351
|
-
delete obj[keys[0]];
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
_getValueByPath(obj, pathStr) {
|
|
355
|
-
const keys = pathStr.split(".");
|
|
356
|
-
let result = obj;
|
|
357
|
-
for (const key of keys) {
|
|
358
|
-
if (result && Object.prototype.hasOwnProperty.call(result, key)) {
|
|
359
|
-
result = result[key];
|
|
360
|
-
} else {
|
|
361
|
-
return undefined;
|
|
362
|
-
}
|
|
43
|
+
// 🔥 BACKUP & RESTORE Methods
|
|
44
|
+
this.backup = this.database.backup?.bind(this.database) || this._fallbackBackup.bind(this);
|
|
45
|
+
this.restore = this.database.restore?.bind(this.database) || this._fallbackRestore.bind(this);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 🔥 FALLBACK Methods
|
|
49
|
+
_fallbackPush(key, value) {
|
|
50
|
+
const array = this.get(key) || [];
|
|
51
|
+
array.push(value);
|
|
52
|
+
this.set(key, array);
|
|
53
|
+
return array.length;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_fallbackPull(key, value) {
|
|
57
|
+
const array = this.get(key) || [];
|
|
58
|
+
const index = array.indexOf(value);
|
|
59
|
+
if (index > -1) {
|
|
60
|
+
array.splice(index, 1);
|
|
61
|
+
this.set(key, array);
|
|
62
|
+
return true;
|
|
363
63
|
}
|
|
364
|
-
return
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// ---------------- QueryResult Class (for method chaining) ----------------
|
|
369
|
-
class QueryResult {
|
|
370
|
-
constructor(results) {
|
|
371
|
-
this.results = results || [];
|
|
64
|
+
return false;
|
|
372
65
|
}
|
|
373
66
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
*/
|
|
380
|
-
sort(field, direction = 'asc') {
|
|
381
|
-
this.results.sort((a, b) => {
|
|
382
|
-
const aVal = this._getValueByPath(a.value, field);
|
|
383
|
-
const bVal = this._getValueByPath(b.value, field);
|
|
384
|
-
|
|
385
|
-
if (aVal === bVal) return 0;
|
|
386
|
-
|
|
387
|
-
const comparison = aVal > bVal ? 1 : -1;
|
|
388
|
-
return direction === 'desc' ? -comparison : comparison;
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
return this;
|
|
67
|
+
_fallbackAdd(key, number) {
|
|
68
|
+
const current = this.get(key) || 0;
|
|
69
|
+
const newValue = current + number;
|
|
70
|
+
this.set(key, newValue);
|
|
71
|
+
return newValue;
|
|
392
72
|
}
|
|
393
73
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
* @param {number} count - Maximum number of results
|
|
397
|
-
* @returns {QueryResult} Chainable
|
|
398
|
-
*/
|
|
399
|
-
limit(count) {
|
|
400
|
-
this.results = this.results.slice(0, count);
|
|
401
|
-
return this;
|
|
74
|
+
_fallbackSubtract(key, number) {
|
|
75
|
+
return this._fallbackAdd(key, -number);
|
|
402
76
|
}
|
|
403
77
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
return this;
|
|
78
|
+
// 🔥 BACKUP FALLBACK Methods
|
|
79
|
+
async _fallbackBackup(backupPath = null) {
|
|
80
|
+
const path = backupPath || `./sehawq-backup-${Date.now()}.json`;
|
|
81
|
+
const storage = new Storage(path);
|
|
82
|
+
const data = this.all();
|
|
83
|
+
await storage.write(data);
|
|
84
|
+
return path;
|
|
412
85
|
}
|
|
413
86
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Get first result
|
|
424
|
-
* @returns {Object|undefined} First result
|
|
425
|
-
*/
|
|
426
|
-
first() {
|
|
427
|
-
return this.results[0];
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
* Get last result
|
|
432
|
-
* @returns {Object|undefined} Last result
|
|
433
|
-
*/
|
|
434
|
-
last() {
|
|
435
|
-
return this.results[this.results.length - 1];
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
/**
|
|
439
|
-
* Convert to array
|
|
440
|
-
* @returns {Array} Results array
|
|
441
|
-
*/
|
|
442
|
-
toArray() {
|
|
443
|
-
return this.results;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* Get only values (without keys)
|
|
448
|
-
* @returns {Array} Values array
|
|
449
|
-
*/
|
|
450
|
-
values() {
|
|
451
|
-
return this.results.map(item => item.value);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
* Get only keys
|
|
456
|
-
* @returns {Array} Keys array
|
|
457
|
-
*/
|
|
458
|
-
keys() {
|
|
459
|
-
return this.results.map(item => item.key);
|
|
87
|
+
async _fallbackRestore(backupPath) {
|
|
88
|
+
const storage = new Storage(backupPath);
|
|
89
|
+
const data = await storage.read();
|
|
90
|
+
this.clear();
|
|
91
|
+
for (const [key, value] of Object.entries(data)) {
|
|
92
|
+
this.set(key, value);
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
460
95
|
}
|
|
461
96
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
* @param {Function} filter - Filter function
|
|
465
|
-
* @returns {QueryResult} Chainable
|
|
466
|
-
*/
|
|
467
|
-
filter(filter) {
|
|
468
|
-
this.results = this.results.filter(item => filter(item.value, item.key));
|
|
97
|
+
async start() {
|
|
98
|
+
await new Promise(resolve => this.database.on('ready', resolve));
|
|
469
99
|
return this;
|
|
470
100
|
}
|
|
471
101
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
* @param {Function} mapper - Map function
|
|
475
|
-
* @returns {Array} Mapped results
|
|
476
|
-
*/
|
|
477
|
-
map(mapper) {
|
|
478
|
-
return this.results.map(item => mapper(item.value, item.key));
|
|
102
|
+
async stop() {
|
|
103
|
+
await this.database.close();
|
|
479
104
|
}
|
|
480
105
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
return undefined;
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
return result;
|
|
106
|
+
// 🔥 STATS Methods
|
|
107
|
+
getStats() {
|
|
108
|
+
return {
|
|
109
|
+
database: this.database.getStats?.(),
|
|
110
|
+
query: this.queryEngine.getStats?.(),
|
|
111
|
+
indexes: this.indexManager.getStats?.()
|
|
112
|
+
};
|
|
492
113
|
}
|
|
493
114
|
}
|
|
494
115
|
|
|
495
|
-
module.exports = SehawqDB;
|
|
116
|
+
module.exports = { SehawqDB };
|