lamix 4.2.17 → 4.2.18
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/README.md +5 -11
- package/lib/index.d.ts +26 -14
- package/lib/index.js +69 -25
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -117,15 +117,9 @@ const User = require('./models/User');
|
|
|
117
117
|
const user = await User.create({ name: 'Alice', email: 'alice@example.com', password: 'secret' });
|
|
118
118
|
|
|
119
119
|
# Fill & save (update)
|
|
120
|
-
name = 'Alice Smith';
|
|
121
|
-
user.fill({ name })
|
|
120
|
+
user.name = 'Alice Smith'; // you can also use user.fill({ name: 'Alice Smith' })
|
|
122
121
|
await user.save();
|
|
123
122
|
|
|
124
|
-
# Method 2 (update)
|
|
125
|
-
const user = await User.findOrFail(param.id);
|
|
126
|
-
const payload = req.body;
|
|
127
|
-
await user.update({ payload });
|
|
128
|
-
|
|
129
123
|
# Find by primary key
|
|
130
124
|
const user1 = await User.find(1);
|
|
131
125
|
const user2 = await User.findOrFail(param.id);
|
|
@@ -170,7 +164,7 @@ const qb = User.query();
|
|
|
170
164
|
const names = await User.query().select('id', 'name').get();
|
|
171
165
|
|
|
172
166
|
# Aggregates
|
|
173
|
-
const cnt = await User.query().count();
|
|
167
|
+
const cnt = await User.query().count(); // count(*)
|
|
174
168
|
const sumId = await User.query().sum('id');
|
|
175
169
|
const avgId = await User.query().avg('id');
|
|
176
170
|
const minId = await User.query().min('id');
|
|
@@ -187,12 +181,12 @@ const Pluckemails = await User.query().pluck('email');
|
|
|
187
181
|
|
|
188
182
|
# Pagination
|
|
189
183
|
const page1 = await User.query().paginate(1, 10);
|
|
190
|
-
|
|
184
|
+
// page1 = { total, perPage, page, lastPage, data: [users...] }
|
|
191
185
|
|
|
192
186
|
# Where In
|
|
193
187
|
const usersIn = await User.query().whereIn('id', [1, 2, 3]).get();
|
|
194
188
|
|
|
195
|
-
|
|
189
|
+
// Where Null / Not Null
|
|
196
190
|
const withNull = await User.query().whereNull('deleted_at').get();
|
|
197
191
|
const notNull = await User.query().whereNotNull('deleted_at').get();
|
|
198
192
|
|
|
@@ -225,7 +219,7 @@ const cached = await DB.cached('SELECT * FROM users WHERE id = ?', [5], 60000);
|
|
|
225
219
|
#You can use relations:
|
|
226
220
|
|
|
227
221
|
const user = await User.find(1);
|
|
228
|
-
const posts = await user.posts().get();
|
|
222
|
+
const posts = await user.posts().get(); // all posts for the user
|
|
229
223
|
|
|
230
224
|
# Eager load in a query with Relations:
|
|
231
225
|
const usersWithPosts = await User.query().with('posts').get();
|
package/lib/index.d.ts
CHANGED
|
@@ -294,15 +294,8 @@ export class QueryBuilder {
|
|
|
294
294
|
_pushWhere(w: any): this;
|
|
295
295
|
then(resolve: any, reject: any): Promise<Collection>;
|
|
296
296
|
where(columnOrObject: any, operator: any, value: any, ...args: any[]): this;
|
|
297
|
+
andWhere(...args: any[]): this;
|
|
297
298
|
orWhere(columnOrObject: any, operatorOrValue: any, value: any, ...args: any[]): this;
|
|
298
|
-
toSQL(): string;
|
|
299
|
-
/**************************************************************************
|
|
300
|
-
* TO SQL
|
|
301
|
-
**************************************************************************/
|
|
302
|
-
toSQL(): {
|
|
303
|
-
sql: string;
|
|
304
|
-
bindings: any[];
|
|
305
|
-
};
|
|
306
299
|
whereRaw(sql: any, bindings?: any[]): this;
|
|
307
300
|
orWhereRaw(sql: any, bindings?: any[]): this;
|
|
308
301
|
whereColumn(a: any, op: any, b: any, ...args: any[]): this;
|
|
@@ -433,6 +426,13 @@ export class QueryBuilder {
|
|
|
433
426
|
}[];
|
|
434
427
|
fromRaw: any;
|
|
435
428
|
};
|
|
429
|
+
/**************************************************************************
|
|
430
|
+
* TO SQL
|
|
431
|
+
**************************************************************************/
|
|
432
|
+
toSQL(): {
|
|
433
|
+
sql: string;
|
|
434
|
+
bindings: any[];
|
|
435
|
+
};
|
|
436
436
|
toSQLJSON(): {
|
|
437
437
|
sql: string;
|
|
438
438
|
bindings: any[];
|
|
@@ -494,7 +494,7 @@ export class LamixSessionStore {
|
|
|
494
494
|
cleanupInterval: any;
|
|
495
495
|
logger: any;
|
|
496
496
|
compress: any;
|
|
497
|
-
cache:
|
|
497
|
+
cache: any;
|
|
498
498
|
redisEnabled: boolean;
|
|
499
499
|
redisRetryAt: number;
|
|
500
500
|
redisCooldown: any;
|
|
@@ -548,11 +548,24 @@ export class BaseModel extends Model {
|
|
|
548
548
|
}
|
|
549
549
|
declare class SimpleCache {
|
|
550
550
|
constructor(options?: {});
|
|
551
|
-
cache:
|
|
552
|
-
get(
|
|
553
|
-
set(
|
|
554
|
-
|
|
551
|
+
cache: any;
|
|
552
|
+
get(key: any): any;
|
|
553
|
+
set(key: any, value: any, ttl?: any): void;
|
|
554
|
+
has(key: any): any;
|
|
555
|
+
delete(key: any): any;
|
|
555
556
|
clear(): void;
|
|
557
|
+
/**
|
|
558
|
+
* Get value or compute + store it
|
|
559
|
+
* Supports async functions
|
|
560
|
+
*/
|
|
561
|
+
getOrSet(key: any, fetchFn: any, ttl?: any): Promise<any>;
|
|
562
|
+
/**
|
|
563
|
+
* Basic cache stats
|
|
564
|
+
*/
|
|
565
|
+
stats(): {
|
|
566
|
+
size: any;
|
|
567
|
+
calculatedSize: any;
|
|
568
|
+
};
|
|
556
569
|
}
|
|
557
570
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
558
571
|
declare class HasManyThrough extends Relation {
|
|
@@ -612,5 +625,4 @@ declare class Relation {
|
|
|
612
625
|
deleteBehavior: any;
|
|
613
626
|
onDelete(behavior: any): this;
|
|
614
627
|
}
|
|
615
|
-
import { LRUCache } from "lru-cache";
|
|
616
628
|
export {};
|
package/lib/index.js
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
const util = require('util');
|
|
4
4
|
const { performance } = require('perf_hooks');
|
|
5
5
|
const { AsyncLocalStorage } = require('async_hooks');
|
|
6
|
+
require('dotenv').config();
|
|
6
7
|
const session = require('express-session');
|
|
7
8
|
const Redis = require('ioredis');
|
|
8
|
-
const LRUCache
|
|
9
|
+
const LRUCache = require('lru-cache');
|
|
9
10
|
const zlib = require('zlib');
|
|
10
|
-
require('dotenv').config();
|
|
11
11
|
|
|
12
12
|
/* ---------------- Utilities ---------------- */
|
|
13
13
|
|
|
@@ -29,37 +29,76 @@ class DBError extends Error {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/* ---------------- Cache ---------------- */
|
|
32
|
-
|
|
33
32
|
class SimpleCache {
|
|
34
33
|
constructor(options = {}) {
|
|
34
|
+
const {
|
|
35
|
+
max = 1000, // max number of items
|
|
36
|
+
ttl = 0, // default TTL (ms)
|
|
37
|
+
maxSize, // optional size-based eviction
|
|
38
|
+
sizeCalculation, // function(value, key)
|
|
39
|
+
} = options;
|
|
40
|
+
|
|
35
41
|
this.cache = new LRUCache({
|
|
36
|
-
max
|
|
37
|
-
|
|
42
|
+
max,
|
|
43
|
+
ttl,
|
|
44
|
+
ttlAutopurge: true,
|
|
45
|
+
maxSize,
|
|
46
|
+
sizeCalculation,
|
|
47
|
+
allowStale: false,
|
|
48
|
+
updateAgeOnGet: false,
|
|
38
49
|
});
|
|
39
50
|
}
|
|
40
51
|
|
|
41
|
-
get(
|
|
42
|
-
const
|
|
43
|
-
return
|
|
52
|
+
get(key) {
|
|
53
|
+
const value = this.cache.get(key);
|
|
54
|
+
return value === undefined ? null : value;
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
set(
|
|
47
|
-
if (ttl
|
|
48
|
-
this.cache.set(
|
|
57
|
+
set(key, value, ttl = null) {
|
|
58
|
+
if (ttl !== null) {
|
|
59
|
+
this.cache.set(key, value, { ttl });
|
|
49
60
|
} else {
|
|
50
|
-
this.cache.set(
|
|
61
|
+
this.cache.set(key, value);
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
this.cache.
|
|
65
|
+
has(key) {
|
|
66
|
+
return this.cache.has(key);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
delete(key) {
|
|
70
|
+
return this.cache.delete(key);
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
clear() {
|
|
59
74
|
this.cache.clear();
|
|
60
75
|
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get value or compute + store it
|
|
79
|
+
* Supports async functions
|
|
80
|
+
*/
|
|
81
|
+
async getOrSet(key, fetchFn, ttl = null) {
|
|
82
|
+
const existing = this.get(key);
|
|
83
|
+
if (existing !== null) return existing;
|
|
84
|
+
|
|
85
|
+
const value = await fetchFn();
|
|
86
|
+
this.set(key, value, ttl);
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Basic cache stats
|
|
92
|
+
*/
|
|
93
|
+
stats() {
|
|
94
|
+
return {
|
|
95
|
+
size: this.cache.size,
|
|
96
|
+
calculatedSize: this.cache.calculatedSize,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
61
99
|
}
|
|
62
100
|
|
|
101
|
+
|
|
63
102
|
/* ---------------- Grammar ---------------- */
|
|
64
103
|
|
|
65
104
|
class Grammar {
|
|
@@ -85,7 +124,7 @@ class DB {
|
|
|
85
124
|
static config = null;
|
|
86
125
|
static pool = null;
|
|
87
126
|
|
|
88
|
-
static cache = new SimpleCache();
|
|
127
|
+
static cache = new SimpleCache({ max: 1000, ttl: 60_000 });
|
|
89
128
|
static retryAttempts = 1;
|
|
90
129
|
|
|
91
130
|
static eventHandlers = { query: [], error: [], reconnect: [] };
|
|
@@ -1308,6 +1347,10 @@ class QueryBuilder {
|
|
|
1308
1347
|
});
|
|
1309
1348
|
}
|
|
1310
1349
|
|
|
1350
|
+
andWhere(...args) {
|
|
1351
|
+
return this.where(...args);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1311
1354
|
orWhere(columnOrObject, operatorOrValue, value) {
|
|
1312
1355
|
if (typeof columnOrObject === 'object' && columnOrObject !== null) {
|
|
1313
1356
|
let query = this;
|
|
@@ -1336,15 +1379,14 @@ class QueryBuilder {
|
|
|
1336
1379
|
}
|
|
1337
1380
|
|
|
1338
1381
|
// Example method to generate SQL
|
|
1339
|
-
toSQL() {
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1382
|
+
// toSQL() {
|
|
1383
|
+
// if (!this.wheres.length) return '';
|
|
1384
|
+
// const sql = this.wheres.map((w, i) => {
|
|
1385
|
+
// const prefix = i === 0 ? '' : ` ${w.boolean} `;
|
|
1386
|
+
// return `${prefix}\`${w.column}\` ${w.operator} ?`;
|
|
1387
|
+
// }).join('');
|
|
1388
|
+
// return 'WHERE ' + sql;
|
|
1389
|
+
// }
|
|
1348
1390
|
|
|
1349
1391
|
whereRaw(sql, bindings = []) {
|
|
1350
1392
|
return this._pushWhere({
|
|
@@ -3451,7 +3493,9 @@ class Model {
|
|
|
3451
3493
|
// INSERT – validation first
|
|
3452
3494
|
// ──────────────────────────────
|
|
3453
3495
|
async saveNew(attrs) {
|
|
3454
|
-
|
|
3496
|
+
this._attributes = { ...attrs };
|
|
3497
|
+
|
|
3498
|
+
if (!Object.keys(this._attributes).length) {
|
|
3455
3499
|
throw new DBError('Cannot save empty model', {
|
|
3456
3500
|
model: this.constructor.name
|
|
3457
3501
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lamix",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.18",
|
|
4
4
|
"description": "lamix - ORM for Node-express js",
|
|
5
5
|
"main": "./lib",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"lru-cache": "^11.2.5",
|
|
35
35
|
"ioredis": "^5.9.2",
|
|
36
36
|
"chalk": "^4.1.2",
|
|
37
|
-
"dotenv": "^17.2.4"
|
|
37
|
+
"dotenv": "^17.2.4 "
|
|
38
38
|
},
|
|
39
39
|
"keywords": [
|
|
40
40
|
"lamix",
|