liekodb 0.1.4 → 0.1.6
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/LICENSE +2 -2
- package/liekodb.js +71 -62
- package/package.json +7 -2
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 eiwSrvt
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/liekodb.js
CHANGED
|
@@ -26,8 +26,6 @@ class CollectionCache {
|
|
|
26
26
|
}, autoSaveInterval);
|
|
27
27
|
this.autoSaveTimer.unref();
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
this._setupShutdown();
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
async _withLock(name, fn) {
|
|
@@ -93,34 +91,6 @@ class CollectionCache {
|
|
|
93
91
|
}
|
|
94
92
|
}
|
|
95
93
|
|
|
96
|
-
reorderDocumentFields = (document) => {
|
|
97
|
-
if (!document || typeof document !== 'object') return document;
|
|
98
|
-
|
|
99
|
-
const orderedDocument = {};
|
|
100
|
-
const reservedFields = ['id', 'createdAt', 'updatedAt'];
|
|
101
|
-
|
|
102
|
-
if (document.id !== undefined) {
|
|
103
|
-
orderedDocument.id = document.id;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const normalFields = Object.keys(document)
|
|
107
|
-
.filter(key => !reservedFields.includes(key))
|
|
108
|
-
.sort();
|
|
109
|
-
|
|
110
|
-
for (const key of normalFields) {
|
|
111
|
-
orderedDocument[key] = structuredClone(document[key]);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (document.createdAt !== undefined) {
|
|
115
|
-
orderedDocument.createdAt = document.createdAt;
|
|
116
|
-
}
|
|
117
|
-
if (document.updatedAt !== undefined) {
|
|
118
|
-
orderedDocument.updatedAt = document.updatedAt;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return orderedDocument;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
94
|
async _saveUnlocked(name, data) {
|
|
125
95
|
const filePath = path.join(this.storagePath, `${name}.json`);
|
|
126
96
|
const tmpPath = `${filePath}.${Date.now()}.tmp`;
|
|
@@ -132,12 +102,11 @@ class CollectionCache {
|
|
|
132
102
|
|
|
133
103
|
const content =
|
|
134
104
|
'[\n' +
|
|
135
|
-
data.documents.map(doc => JSON.stringify(
|
|
105
|
+
data.documents.map(doc => JSON.stringify(Utils.reorderDocumentFields(doc))).join(',\n') +
|
|
136
106
|
'\n]';
|
|
137
107
|
|
|
138
108
|
await fs.writeFile(tmpPath, content, 'utf8');
|
|
139
109
|
|
|
140
|
-
// sanity check
|
|
141
110
|
JSON.parse(await fs.readFile(tmpPath, 'utf8'));
|
|
142
111
|
|
|
143
112
|
await fs.rename(tmpPath, filePath);
|
|
@@ -176,10 +145,9 @@ class CollectionCache {
|
|
|
176
145
|
throw new Error(`[CollectionCache.updateDocument] Document ${id} not found in ${name}`);
|
|
177
146
|
}
|
|
178
147
|
|
|
179
|
-
const updated = {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
};
|
|
148
|
+
const updated = { ...data.documents[idx] };
|
|
149
|
+
|
|
150
|
+
updateFn(updated);
|
|
183
151
|
|
|
184
152
|
if (updated.id !== id) {
|
|
185
153
|
throw new Error('[CollectionCache.update] Updated document id cannot be changed');
|
|
@@ -260,20 +228,14 @@ class CollectionCache {
|
|
|
260
228
|
console.log(`[CollectionCache] Flushed ${savePromises.length} collections in ${Format.formatDuration(Utils.endTimer(start))}`);
|
|
261
229
|
}
|
|
262
230
|
|
|
263
|
-
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
process.once('SIGINT', () => shutdown('SIGINT'));
|
|
274
|
-
process.once('SIGTERM', () => shutdown('SIGTERM'));
|
|
275
|
-
process.once('beforeExit', () => this.flushAll());
|
|
276
|
-
}
|
|
231
|
+
async shutdown(signal) {
|
|
232
|
+
if (this.debug) {
|
|
233
|
+
console.log(`[CollectionCache] ${signal} received`);
|
|
234
|
+
}
|
|
235
|
+
await this.flushAll();
|
|
236
|
+
return true;
|
|
237
|
+
//process.exit(0);
|
|
238
|
+
};
|
|
277
239
|
}
|
|
278
240
|
|
|
279
241
|
class QueryEngine {
|
|
@@ -1130,9 +1092,9 @@ class LocalAdapter {
|
|
|
1130
1092
|
|
|
1131
1093
|
const response = {
|
|
1132
1094
|
data: {
|
|
1133
|
-
foundCount: documents.length,
|
|
1134
|
-
|
|
1135
|
-
totalDocuments: collection.documents.length
|
|
1095
|
+
//foundCount: documents.length,
|
|
1096
|
+
documents,
|
|
1097
|
+
//totalDocuments: collection.documents.length
|
|
1136
1098
|
}
|
|
1137
1099
|
};
|
|
1138
1100
|
|
|
@@ -1140,13 +1102,12 @@ class LocalAdapter {
|
|
|
1140
1102
|
const page = Math.floor(skipNum / limitNum) + 1;
|
|
1141
1103
|
const totalPages = Math.max(1, Math.ceil(totalFilteredDocuments / limitNum));
|
|
1142
1104
|
|
|
1143
|
-
response.data.isPaginated = true;
|
|
1144
1105
|
response.data.pagination = {
|
|
1145
1106
|
page,
|
|
1146
1107
|
limit: limitNum,
|
|
1147
1108
|
skip: skipNum,
|
|
1148
1109
|
|
|
1149
|
-
|
|
1110
|
+
totalDocuments: totalFilteredDocuments,
|
|
1150
1111
|
totalPages,
|
|
1151
1112
|
|
|
1152
1113
|
hasNext: page < totalPages,
|
|
@@ -1428,12 +1389,13 @@ class LocalAdapter {
|
|
|
1428
1389
|
async updateById(id, { update = {}, options = {} } = {}) {
|
|
1429
1390
|
const start = Utils.startTimer();
|
|
1430
1391
|
try {
|
|
1431
|
-
const returnType = options.returnType
|
|
1392
|
+
const returnType = options.returnType;
|
|
1432
1393
|
|
|
1433
1394
|
const updatedDoc = await this.cache.updateDocument(
|
|
1434
1395
|
this.collectionName,
|
|
1435
1396
|
id,
|
|
1436
1397
|
(doc) => {
|
|
1398
|
+
console.log(doc);
|
|
1437
1399
|
const normalizedUpdate = Object.keys(update).some(k => k.startsWith('$'))
|
|
1438
1400
|
? update
|
|
1439
1401
|
: { $set: update };
|
|
@@ -1616,6 +1578,14 @@ class LocalAdapter {
|
|
|
1616
1578
|
}
|
|
1617
1579
|
}
|
|
1618
1580
|
|
|
1581
|
+
async flushAll() {
|
|
1582
|
+
await this.cache.flushAll();
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
async shutdown(signal) {
|
|
1586
|
+
await this.cache.shutdown(signal);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1619
1589
|
async close() {
|
|
1620
1590
|
await this.cache.flushAll();
|
|
1621
1591
|
return true;
|
|
@@ -1666,9 +1636,9 @@ class Collection {
|
|
|
1666
1636
|
|
|
1667
1637
|
if (error) return { error };
|
|
1668
1638
|
|
|
1669
|
-
if (data.
|
|
1639
|
+
if (data.documents.length > 0) {
|
|
1670
1640
|
return {
|
|
1671
|
-
data: data.
|
|
1641
|
+
data: data.documents[0]
|
|
1672
1642
|
};
|
|
1673
1643
|
}
|
|
1674
1644
|
|
|
@@ -1752,6 +1722,8 @@ class LiekoDB {
|
|
|
1752
1722
|
);
|
|
1753
1723
|
}
|
|
1754
1724
|
this.adapter = this._createAdapter(options);
|
|
1725
|
+
|
|
1726
|
+
this._setupShutdown();
|
|
1755
1727
|
}
|
|
1756
1728
|
|
|
1757
1729
|
_createAdapter(options) {
|
|
@@ -1787,7 +1759,16 @@ class LiekoDB {
|
|
|
1787
1759
|
}
|
|
1788
1760
|
|
|
1789
1761
|
async close() {
|
|
1790
|
-
|
|
1762
|
+
//promise
|
|
1763
|
+
return await this.adapter.close();
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
_setupShutdown() {
|
|
1767
|
+
if (typeof process === 'undefined') return;
|
|
1768
|
+
|
|
1769
|
+
process.once('SIGINT', () => this.adapter.shutdown('SIGINT'));
|
|
1770
|
+
process.once('SIGTERM', () => this.adapter.shutdown('SIGTERM'));
|
|
1771
|
+
process.once('beforeExit', () => this.adapter.flushAll());
|
|
1791
1772
|
}
|
|
1792
1773
|
}
|
|
1793
1774
|
|
|
@@ -1898,7 +1879,7 @@ class Validator {
|
|
|
1898
1879
|
}
|
|
1899
1880
|
|
|
1900
1881
|
const validOperators = ['$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in', '$nin',
|
|
1901
|
-
'$exists', '$regex', '$and', '$or', '$not'];
|
|
1882
|
+
'$exists', '$regex', '$and', '$or', '$nor', '$not'];
|
|
1902
1883
|
|
|
1903
1884
|
for (const key in filters) {
|
|
1904
1885
|
if (key.startsWith('$') && !validOperators.includes(key)) {
|
|
@@ -1908,7 +1889,7 @@ class Validator {
|
|
|
1908
1889
|
const value = filters[key];
|
|
1909
1890
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
1910
1891
|
this.validateFilters(value);
|
|
1911
|
-
} else if (Array.isArray(value) && (key === '$and' || key === '$or' || key === '$in' || key === '$nin')) {
|
|
1892
|
+
} else if (Array.isArray(value) && (key === '$and' || key === '$or' || key === '$nor' || key === '$in' || key === '$nin')) {
|
|
1912
1893
|
value.forEach(item => {
|
|
1913
1894
|
if (typeof item === 'object' && item !== null) {
|
|
1914
1895
|
this.validateFilters(item);
|
|
@@ -1967,7 +1948,7 @@ class Validator {
|
|
|
1967
1948
|
throw new Error('Page must be a positive number');
|
|
1968
1949
|
}
|
|
1969
1950
|
} else if (key === 'returnType') {
|
|
1970
|
-
const validTypes = ['count', 'ids', 'documents'];
|
|
1951
|
+
const validTypes = ['count', 'ids', 'documents', 'document', 'id'];
|
|
1971
1952
|
if (!validTypes.includes(options[key])) {
|
|
1972
1953
|
throw new Error(
|
|
1973
1954
|
`Invalid returnType: "${options[key]}". ` +
|
|
@@ -2005,6 +1986,34 @@ class Utils {
|
|
|
2005
1986
|
return 0;
|
|
2006
1987
|
}
|
|
2007
1988
|
}
|
|
1989
|
+
|
|
1990
|
+
static reorderDocumentFields = (document) => {
|
|
1991
|
+
if (!document || typeof document !== 'object') return document;
|
|
1992
|
+
|
|
1993
|
+
const orderedDocument = {};
|
|
1994
|
+
const reservedFields = ['id', 'createdAt', 'updatedAt'];
|
|
1995
|
+
|
|
1996
|
+
if (document.id !== undefined) {
|
|
1997
|
+
orderedDocument.id = document.id;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
const normalFields = Object.keys(document)
|
|
2001
|
+
.filter(key => !reservedFields.includes(key))
|
|
2002
|
+
.sort();
|
|
2003
|
+
|
|
2004
|
+
for (const key of normalFields) {
|
|
2005
|
+
orderedDocument[key] = structuredClone(document[key]);
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
if (document.createdAt !== undefined) {
|
|
2009
|
+
orderedDocument.createdAt = document.createdAt;
|
|
2010
|
+
}
|
|
2011
|
+
if (document.updatedAt !== undefined) {
|
|
2012
|
+
orderedDocument.updatedAt = document.updatedAt;
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
return orderedDocument;
|
|
2016
|
+
}
|
|
2008
2017
|
}
|
|
2009
2018
|
|
|
2010
2019
|
module.exports = LiekoDB;
|
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "liekodb",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/eiwSrvt/liekodb"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://github.com/eiwSrvt/liekodb",
|
|
4
9
|
"description": "Lightweight, MongoDB-like JSON database for Node.js",
|
|
5
10
|
"main": "liekodb.js",
|
|
6
11
|
"scripts": {
|
|
@@ -26,4 +31,4 @@
|
|
|
26
31
|
"engines": {
|
|
27
32
|
"node": ">=14.0.0"
|
|
28
33
|
}
|
|
29
|
-
}
|
|
34
|
+
}
|