ts-cache-mongoose 0.0.1
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/.eslintignore +4 -0
- package/.eslintrc +95 -0
- package/.swcrc +21 -0
- package/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/cjs/cache/Cache.js +37 -0
- package/dist/cjs/cache/Cache.js.map +1 -0
- package/dist/cjs/cache/engine/MemoryCacheEngine.js +25 -0
- package/dist/cjs/cache/engine/MemoryCacheEngine.js.map +1 -0
- package/dist/cjs/cache/engine/RedisCacheEngine.js +28 -0
- package/dist/cjs/cache/engine/RedisCacheEngine.js.map +1 -0
- package/dist/cjs/crypto.js +28 -0
- package/dist/cjs/crypto.js.map +1 -0
- package/dist/cjs/interfaces/ICacheEngine.js +3 -0
- package/dist/cjs/interfaces/ICacheEngine.js.map +1 -0
- package/dist/cjs/interfaces/ICacheMongooseOptions.js +3 -0
- package/dist/cjs/interfaces/ICacheMongooseOptions.js.map +1 -0
- package/dist/cjs/plugin.js +82 -0
- package/dist/cjs/plugin.js.map +1 -0
- package/dist/cjs/types/cache/Cache.d.ts +12 -0
- package/dist/cjs/types/cache/Cache.d.ts.map +1 -0
- package/dist/cjs/types/cache/engine/MemoryCacheEngine.d.ts +11 -0
- package/dist/cjs/types/cache/engine/MemoryCacheEngine.d.ts.map +1 -0
- package/dist/cjs/types/cache/engine/RedisCacheEngine.d.ts +11 -0
- package/dist/cjs/types/cache/engine/RedisCacheEngine.d.ts.map +1 -0
- package/dist/cjs/types/crypto.d.ts +3 -0
- package/dist/cjs/types/crypto.d.ts.map +1 -0
- package/dist/cjs/types/interfaces/ICacheEngine.d.ts +8 -0
- package/dist/cjs/types/interfaces/ICacheEngine.d.ts.map +1 -0
- package/dist/cjs/types/interfaces/ICacheMongooseOptions.d.ts +10 -0
- package/dist/cjs/types/interfaces/ICacheMongooseOptions.d.ts.map +1 -0
- package/dist/cjs/types/plugin.d.ts +24 -0
- package/dist/cjs/types/plugin.d.ts.map +1 -0
- package/dist/esm/cache/Cache.js +33 -0
- package/dist/esm/cache/Cache.js.map +1 -0
- package/dist/esm/cache/engine/MemoryCacheEngine.js +23 -0
- package/dist/esm/cache/engine/MemoryCacheEngine.js.map +1 -0
- package/dist/esm/cache/engine/RedisCacheEngine.js +25 -0
- package/dist/esm/cache/engine/RedisCacheEngine.js.map +1 -0
- package/dist/esm/crypto.js +22 -0
- package/dist/esm/crypto.js.map +1 -0
- package/dist/esm/interfaces/ICacheEngine.js +2 -0
- package/dist/esm/interfaces/ICacheEngine.js.map +1 -0
- package/dist/esm/interfaces/ICacheMongooseOptions.js +2 -0
- package/dist/esm/interfaces/ICacheMongooseOptions.js.map +1 -0
- package/dist/esm/plugin.js.map +1 -0
- package/dist/esm/plugin.mjs +79 -0
- package/dist/esm/types/cache/Cache.d.ts +12 -0
- package/dist/esm/types/cache/Cache.d.ts.map +1 -0
- package/dist/esm/types/cache/engine/MemoryCacheEngine.d.ts +11 -0
- package/dist/esm/types/cache/engine/MemoryCacheEngine.d.ts.map +1 -0
- package/dist/esm/types/cache/engine/RedisCacheEngine.d.ts +11 -0
- package/dist/esm/types/cache/engine/RedisCacheEngine.d.ts.map +1 -0
- package/dist/esm/types/crypto.d.ts +3 -0
- package/dist/esm/types/crypto.d.ts.map +1 -0
- package/dist/esm/types/interfaces/ICacheEngine.d.ts +8 -0
- package/dist/esm/types/interfaces/ICacheEngine.d.ts.map +1 -0
- package/dist/esm/types/interfaces/ICacheMongooseOptions.d.ts +10 -0
- package/dist/esm/types/interfaces/ICacheMongooseOptions.d.ts.map +1 -0
- package/dist/esm/types/plugin.d.ts +24 -0
- package/dist/esm/types/plugin.d.ts.map +1 -0
- package/jest-mongodb-config.ts +10 -0
- package/jest.config.ts +33 -0
- package/package.json +112 -0
- package/src/cache/Cache.ts +46 -0
- package/src/cache/engine/MemoryCacheEngine.ts +32 -0
- package/src/cache/engine/RedisCacheEngine.ts +36 -0
- package/src/crypto.ts +27 -0
- package/src/interfaces/ICacheEngine.ts +8 -0
- package/src/interfaces/ICacheMongooseOptions.ts +10 -0
- package/src/plugin.ts +122 -0
- package/tests/cache.test.ts +51 -0
- package/tests/crypto.test.ts +60 -0
- package/tests/interfaces/IUser.ts +8 -0
- package/tests/schemas/UserSchema.ts +16 -0
- package/tsconfig.json +44 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
export function sortDeep(data) {
|
|
4
|
+
if (_.isObjectLike(data) && _.isArray(data)) {
|
|
5
|
+
return data.map(sortDeep);
|
|
6
|
+
}
|
|
7
|
+
if (_.isObjectLike(data) && !_.isArray(data)) {
|
|
8
|
+
const sortedKeys = _.keys(data).sort((a, b) => a.localeCompare(b));
|
|
9
|
+
const sortedObj = {};
|
|
10
|
+
sortedKeys.forEach((key) => {
|
|
11
|
+
sortedObj[key] = sortDeep(data[key]);
|
|
12
|
+
});
|
|
13
|
+
return sortedObj;
|
|
14
|
+
}
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
export function getKey(data) {
|
|
18
|
+
const sortedObj = sortDeep(data);
|
|
19
|
+
const sortedStr = JSON.stringify(sortedObj);
|
|
20
|
+
return createHash('sha256').update(sortedStr).digest('hex');
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAA;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAEnC,MAAM,UAAU,QAAQ,CAAE,IAAyD;IACjF,IAAI,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QAC3C,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;KAC1B;IAED,IAAI,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QAC5C,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;QAClE,MAAM,SAAS,GAA4B,EAAE,CAAA;QAE7C,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACzB,SAAS,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAwD,CAAC,CAAA;QAC7F,CAAC,CAAC,CAAA;QAEF,OAAO,SAAS,CAAA;KACjB;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,MAAM,CAAE,IAAyD;IAC/E,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAChC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;IAC3C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICacheEngine.js","sourceRoot":"","sources":["../../../src/interfaces/ICacheEngine.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICacheMongooseOptions.js","sourceRoot":"","sources":["../../../src/interfaces/ICacheMongooseOptions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAA;AACtB,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,KAAK,MAAM,eAAe,CAAA;AAIjC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAgBjC,MAAM,aAAa;IAKjB;IAEA,CAAC;IAGM,MAAM,CAAC,IAAI,CAAE,QAAkB,EAAE,oBAA2C;QACjF,IAAI,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,KAAK,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,8FAA8F,CAAC,CAAA;QACjK,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAA;YACnC,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,CAAC,UAAU,GAAG,UAAU,CAAC,CAAA;YAE1G,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAA;YAGjC,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAA;YAGlD,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG;gBACrC,IAAI,IAAI,CAAC,IAAI;oBAAE,OAAO,IAAI,CAAC,IAAI,CAAA;gBAE/B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;gBAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;gBAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;gBAEjC,MAAM,IAAI,GAA4B;oBACpC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS;oBAC3B,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,MAAM;oBACN,MAAM;oBACN,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,SAAS,EAAE,IAAI,CAAC,SAAS;iBAC1B,CAAA;gBAED,OAAO,MAAM,CAAC,IAAI,CAAC,CAAA;YACrB,CAAC,CAAA;YAGD,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG;gBACrC,OAAO,IAAI,CAAC,IAAI,CAAA;YAClB,CAAC,CAAA;YAGD,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,UAAU,GAAY,EAAE,SAAkB;gBACzE,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,IAAI,UAAU,CAAC,CAAA;gBACjC,IAAI,CAAC,IAAI,GAAG,SAAS,CAAA;gBACrB,OAAO,IAAI,CAAA;YACb,CAAC,CAAA;YAGD,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,GAAG,KAAK;gBACnC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;oBACxB,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;iBAChC;gBAED,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;gBAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;gBAE9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAA;gBAElC,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACxC,IAAI,WAAW,EAAE;oBACf,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;oBACzC,IAAI,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;wBAC1B,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAA4B,CAAC,CAAA;qBACvF;yBAAM;wBACL,OAAO,WAAW,CAAC,OAAO,CAAC,WAAW,CAA4B,CAAA;qBACnE;iBACF;gBAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAwD,CAAA;gBACnG,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;oBACxC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBACpB,CAAC,CAAC,CAAA;gBAEF,OAAO,MAAM,CAAA;YACf,CAAC,CAAA;SACF;QAED,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAEM,KAAK,CAAC,UAAU,CAAE,SAAiB;QACxC,IAAI,CAAC,SAAS,EAAE;YACd,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;YACxB,OAAM;SACP;QACD,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACjC,CAAC;CACF;AAED,eAAe,aAAa,CAAA"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import ms from 'ms';
|
|
3
|
+
import Cache from './cache/Cache';
|
|
4
|
+
import { getKey } from './crypto';
|
|
5
|
+
class CacheMongoose {
|
|
6
|
+
constructor() {
|
|
7
|
+
}
|
|
8
|
+
static init(mongoose, cacheMongooseOptions) {
|
|
9
|
+
if (typeof mongoose.Model.hydrate !== 'function')
|
|
10
|
+
throw new Error('Cache is only compatible with versions of mongoose that implement the `model.hydrate` method');
|
|
11
|
+
if (!this.instance) {
|
|
12
|
+
this.instance = new CacheMongoose();
|
|
13
|
+
this.instance.cache = new Cache(cacheMongooseOptions.engine, cacheMongooseOptions.defaultTTL = '1 minute');
|
|
14
|
+
const cache = this.instance.cache;
|
|
15
|
+
const mongooseExec = mongoose.Query.prototype.exec;
|
|
16
|
+
mongoose.Query.prototype.getCacheKey = function () {
|
|
17
|
+
if (this._key)
|
|
18
|
+
return this._key;
|
|
19
|
+
const filter = this.getFilter();
|
|
20
|
+
const update = this.getUpdate();
|
|
21
|
+
const options = this.getOptions();
|
|
22
|
+
const data = {
|
|
23
|
+
model: this.model.modelName,
|
|
24
|
+
op: this.op,
|
|
25
|
+
filter,
|
|
26
|
+
update,
|
|
27
|
+
skip: options.skip,
|
|
28
|
+
limit: options.limit,
|
|
29
|
+
sort: options.sort,
|
|
30
|
+
_fields: this._fields,
|
|
31
|
+
_path: this._path,
|
|
32
|
+
_distinct: this._distinct
|
|
33
|
+
};
|
|
34
|
+
return getKey(data);
|
|
35
|
+
};
|
|
36
|
+
mongoose.Query.prototype.getCacheTTL = function () {
|
|
37
|
+
return this._ttl;
|
|
38
|
+
};
|
|
39
|
+
mongoose.Query.prototype.cache = function (ttl, customKey) {
|
|
40
|
+
this._ttl = ms(ttl ?? '1 minute');
|
|
41
|
+
this._key = customKey;
|
|
42
|
+
return this;
|
|
43
|
+
};
|
|
44
|
+
mongoose.Query.prototype.exec = async function () {
|
|
45
|
+
if (!_.has(this, '_ttl')) {
|
|
46
|
+
return mongooseExec.apply(this);
|
|
47
|
+
}
|
|
48
|
+
const key = this.getCacheKey();
|
|
49
|
+
const ttl = this.getCacheTTL();
|
|
50
|
+
const model = this.model.modelName;
|
|
51
|
+
const resultCache = await cache.get(key);
|
|
52
|
+
if (resultCache) {
|
|
53
|
+
const constructor = mongoose.model(model);
|
|
54
|
+
if (_.isArray(resultCache)) {
|
|
55
|
+
return resultCache.map((item) => constructor.hydrate(item));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return constructor.hydrate(resultCache);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const result = await mongooseExec.call(this);
|
|
62
|
+
cache.set(key, result, ttl).catch((err) => {
|
|
63
|
+
console.error(err);
|
|
64
|
+
});
|
|
65
|
+
return result;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return this.instance;
|
|
69
|
+
}
|
|
70
|
+
async clearCache(customKey) {
|
|
71
|
+
if (!customKey) {
|
|
72
|
+
await this.cache.clear();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
await this.cache.del(customKey);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export default CacheMongoose;
|
|
79
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const engines: readonly ["memory", "redis"];
|
|
2
|
+
declare class Cache {
|
|
3
|
+
private engine;
|
|
4
|
+
private defaultTTL;
|
|
5
|
+
constructor(engineName: 'memory' | 'redis', defaultTTL: string);
|
|
6
|
+
get(key: string): Promise<Record<string, unknown> | Record<string, unknown>[] | undefined>;
|
|
7
|
+
set(key: string, value: Record<string, unknown> | Record<string, unknown>[], ttl?: number): Promise<void>;
|
|
8
|
+
del(key: string): Promise<void>;
|
|
9
|
+
clear(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export default Cache;
|
|
12
|
+
//# sourceMappingURL=Cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cache.d.ts","sourceRoot":"","sources":["../../../../src/cache/Cache.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO,8BAA+B,CAAA;AAEnD,cAAM,KAAK;IACT,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,UAAU,CAAQ;gBAEb,UAAU,EAAE,QAAQ,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM;IAczD,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC;IAI3F,GAAG,CAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1G,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhC,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;CAG9B;AAED,eAAe,KAAK,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type ICacheEngine from '../../interfaces/ICacheEngine';
|
|
2
|
+
declare class MemoryCacheEngine implements ICacheEngine {
|
|
3
|
+
private cache;
|
|
4
|
+
constructor();
|
|
5
|
+
get(key: string): Record<string, unknown> | Record<string, unknown>[] | undefined;
|
|
6
|
+
set(key: string, value: Record<string, unknown> | Record<string, unknown>[], ttl?: number): void;
|
|
7
|
+
del(key: string): void;
|
|
8
|
+
clear(): void;
|
|
9
|
+
}
|
|
10
|
+
export default MemoryCacheEngine;
|
|
11
|
+
//# sourceMappingURL=MemoryCacheEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryCacheEngine.d.ts","sourceRoot":"","sources":["../../../../../src/cache/engine/MemoryCacheEngine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAA;AAE7D,cAAM,iBAAkB,YAAW,YAAY;IAC7C,OAAO,CAAC,KAAK,CAA+G;;IAM5H,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,SAAS;IAQlF,GAAG,CAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,SAAW,GAAG,IAAI;IAInG,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAKvB,KAAK,IAAK,IAAI;CAGf;AAED,eAAe,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type ICacheEngine from '../../interfaces/ICacheEngine';
|
|
2
|
+
declare class RedisCacheEngine implements ICacheEngine {
|
|
3
|
+
private client;
|
|
4
|
+
constructor();
|
|
5
|
+
get(key: string): Promise<Record<string, unknown> | Record<string, unknown>[] | undefined>;
|
|
6
|
+
set(key: string, value: unknown, ttl?: number): Promise<void>;
|
|
7
|
+
del(key: string): Promise<void>;
|
|
8
|
+
clear(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export default RedisCacheEngine;
|
|
11
|
+
//# sourceMappingURL=RedisCacheEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RedisCacheEngine.d.ts","sourceRoot":"","sources":["../../../../../src/cache/engine/RedisCacheEngine.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAA;AAE7D,cAAM,gBAAiB,YAAW,YAAY;IAC5C,OAAO,CAAC,MAAM,CAAO;;IAMf,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC;IAQ3F,GAAG,CAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhE,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhC,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;CAG9B;AAED,eAAe,gBAAgB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../../src/crypto.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,CAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAiB5F;AAED,wBAAgB,MAAM,CAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAIzF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface ICacheEngine {
|
|
2
|
+
get: (key: string) => Promise<Record<string, unknown> | Record<string, unknown>[] | undefined> | Record<string, unknown> | Record<string, unknown>[] | undefined;
|
|
3
|
+
set: (key: string, value: Record<string, unknown> | Record<string, unknown>[], ttl?: number) => Promise<void> | void;
|
|
4
|
+
del: (key: string) => Promise<void> | void;
|
|
5
|
+
clear: () => Promise<void> | void;
|
|
6
|
+
}
|
|
7
|
+
export default ICacheEngine;
|
|
8
|
+
//# sourceMappingURL=ICacheEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICacheEngine.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/ICacheEngine.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACpB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,SAAS,CAAA;IAChK,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACpH,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC1C,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAClC;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICacheMongooseOptions.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/ICacheMongooseOptions.ts"],"names":[],"mappings":"AAAA,UAAU,qBAAqB;IAC7B,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,eAAe,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Mongoose } from 'mongoose';
|
|
2
|
+
import type ICacheMongooseOptions from './interfaces/ICacheMongooseOptions';
|
|
3
|
+
declare module 'mongoose' {
|
|
4
|
+
interface Query<ResultType, DocType, THelpers, RawDocType> {
|
|
5
|
+
cache: (this: Query<ResultType, DocType, THelpers, RawDocType>, ttl?: string) => this;
|
|
6
|
+
_key?: string;
|
|
7
|
+
getCacheKey: (this: Query<ResultType, DocType, THelpers, RawDocType>) => string;
|
|
8
|
+
_ttl: number;
|
|
9
|
+
getCacheTTL: (this: Query<ResultType, DocType, THelpers, RawDocType>) => number;
|
|
10
|
+
op?: string;
|
|
11
|
+
_fields?: unknown;
|
|
12
|
+
_path?: unknown;
|
|
13
|
+
_distinct?: unknown;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
declare class CacheMongoose {
|
|
17
|
+
private static instance;
|
|
18
|
+
private cache;
|
|
19
|
+
private constructor();
|
|
20
|
+
static init(mongoose: Mongoose, cacheMongooseOptions: ICacheMongooseOptions): CacheMongoose;
|
|
21
|
+
clearCache(customKey: string): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export default CacheMongoose;
|
|
24
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/plugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,KAAK,qBAAqB,MAAM,oCAAoC,CAAA;AAG3E,OAAO,QAAQ,UAAU,CAAC;IACxB,UAAU,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU;QACvD,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;QACrF,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,KAAK,MAAM,CAAA;QAC/E,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,KAAK,MAAM,CAAA;QAC/E,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,KAAK,CAAC,EAAE,OAAO,CAAA;QACf,SAAS,CAAC,EAAE,OAAO,CAAA;KACpB;CACF;AAED,cAAM,aAAa;IAEjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA2B;IAClD,OAAO,CAAC,KAAK,CAAQ;IAErB,OAAO;WAKO,IAAI,CAAE,QAAQ,EAAE,QAAQ,EAAE,oBAAoB,EAAE,qBAAqB,GAAG,aAAa;IAgFtF,UAAU,CAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAO3D;AAED,eAAe,aAAa,CAAA"}
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// For a detailed explanation regarding each configuration property, visit:
|
|
2
|
+
// https://jestjs.io/docs/en/configuration.html
|
|
3
|
+
import { recursive } from 'merge'
|
|
4
|
+
import mongo from '@shelf/jest-mongodb/jest-preset'
|
|
5
|
+
|
|
6
|
+
const config = recursive(mongo, {
|
|
7
|
+
roots: [
|
|
8
|
+
'<rootDir>/src/',
|
|
9
|
+
'<rootDir>/tests/'
|
|
10
|
+
],
|
|
11
|
+
clearMocks: true,
|
|
12
|
+
collectCoverage: true,
|
|
13
|
+
collectCoverageFrom: [
|
|
14
|
+
'src/**/*.ts',
|
|
15
|
+
'!src/**/*.d.ts',
|
|
16
|
+
'!src/interfaces/**/*.ts'
|
|
17
|
+
],
|
|
18
|
+
coverageDirectory: 'coverage',
|
|
19
|
+
testMatch: [
|
|
20
|
+
'<rootDir>/tests/**/*.test.ts'
|
|
21
|
+
],
|
|
22
|
+
transform: {
|
|
23
|
+
'^.+\\.(t|j)sx?$': '@swc/jest'
|
|
24
|
+
},
|
|
25
|
+
testPathIgnorePatterns: [
|
|
26
|
+
'node_modules'
|
|
27
|
+
],
|
|
28
|
+
watchPathIgnorePatterns: [
|
|
29
|
+
'globalConfig'
|
|
30
|
+
]
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
export default config
|
package/package.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ts-cache-mongoose",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Cache plugin for mongoose",
|
|
5
|
+
"author": "Alex Eagle",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git://github.com/ilovepixelart/ts-cache-mongoose.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/ilovepixelart/ts-cache-mongoose/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/ilovepixelart/ts-cache-mongoose#readme",
|
|
15
|
+
"directories": {
|
|
16
|
+
"examples": "examples"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mongo",
|
|
20
|
+
"mongodb",
|
|
21
|
+
"mongoose",
|
|
22
|
+
"plugin",
|
|
23
|
+
"schema",
|
|
24
|
+
"db",
|
|
25
|
+
"nosql",
|
|
26
|
+
"ts",
|
|
27
|
+
"typescript",
|
|
28
|
+
"swc",
|
|
29
|
+
"cache",
|
|
30
|
+
"redis",
|
|
31
|
+
"store",
|
|
32
|
+
"memory",
|
|
33
|
+
"ttl",
|
|
34
|
+
"query"
|
|
35
|
+
],
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"src",
|
|
42
|
+
"tests",
|
|
43
|
+
".swcrc",
|
|
44
|
+
"tsconfig.json",
|
|
45
|
+
"jest.config.ts",
|
|
46
|
+
"jest-mongodb-config.ts",
|
|
47
|
+
".eslintrc",
|
|
48
|
+
".eslintignore"
|
|
49
|
+
],
|
|
50
|
+
"exports": {
|
|
51
|
+
".": {
|
|
52
|
+
"import": {
|
|
53
|
+
"types": "./dist/esm/types/plugin.d.ts",
|
|
54
|
+
"default": "./dist/esm/plugin.mjs"
|
|
55
|
+
},
|
|
56
|
+
"require": {
|
|
57
|
+
"types": "./dist/cjs/types/plugin.d.ts",
|
|
58
|
+
"default": "./dist/cjs/plugin.js"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"main": "dist/cjs/plugin.js",
|
|
63
|
+
"types": "dist/cjs/types/plugin.d.ts",
|
|
64
|
+
"scripts": {
|
|
65
|
+
"lint": "eslint . --ext .js,.ts",
|
|
66
|
+
"lint:fix": "eslint . --fix --ext .js,.ts",
|
|
67
|
+
"test": "jest --config jest.config.ts --detectOpenHandles --coverage",
|
|
68
|
+
"test:open": "npm run test && open-cli coverage/lcov-report/index.html",
|
|
69
|
+
"clean": "rm -rf ./dist",
|
|
70
|
+
"build": "npm run clean && npm run build:cjs && npm run build:esm",
|
|
71
|
+
"build:cjs": "tsc -p config/tsconfig.cjs.json",
|
|
72
|
+
"build:esm": "tsc -p config/tsconfig.esm.json && mv ./dist/esm/plugin.js ./dist/esm/plugin.mjs",
|
|
73
|
+
"release": "npm install && npm run lint && npm run build && np"
|
|
74
|
+
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"ioredis": "^5.3.2",
|
|
77
|
+
"lodash": "^4.17.21",
|
|
78
|
+
"ms": "^2.1.3"
|
|
79
|
+
},
|
|
80
|
+
"devDependencies": {
|
|
81
|
+
"@shelf/jest-mongodb": "4.1.7",
|
|
82
|
+
"@swc/cli": "0.1.62",
|
|
83
|
+
"@swc/core": "1.3.53",
|
|
84
|
+
"@swc/helpers": "0.5.0",
|
|
85
|
+
"@swc/jest": "0.2.26",
|
|
86
|
+
"@swc/register": "0.1.10",
|
|
87
|
+
"@types/jest": "29.5.1",
|
|
88
|
+
"@types/lodash": "4.14.194",
|
|
89
|
+
"@types/ms": "^0.7.31",
|
|
90
|
+
"@types/node": "18.16.0",
|
|
91
|
+
"@typescript-eslint/eslint-plugin": "5.59.0",
|
|
92
|
+
"@typescript-eslint/parser": "5.59.0",
|
|
93
|
+
"eslint": "8.39.0",
|
|
94
|
+
"eslint-config-standard": "17.0.0",
|
|
95
|
+
"eslint-plugin-import": "2.27.5",
|
|
96
|
+
"eslint-plugin-jest": "27.2.1",
|
|
97
|
+
"eslint-plugin-jest-formatting": "3.1.0",
|
|
98
|
+
"eslint-plugin-n": "15.7.0",
|
|
99
|
+
"eslint-plugin-node": "11.1.0",
|
|
100
|
+
"eslint-plugin-promise": "6.1.1",
|
|
101
|
+
"eslint-plugin-sonarjs": "0.19.0",
|
|
102
|
+
"jest": "29.5.0",
|
|
103
|
+
"merge": "2.1.1",
|
|
104
|
+
"mongoose": "6.10.5",
|
|
105
|
+
"open-cli": "7.2.0",
|
|
106
|
+
"ts-node": "10.9.1",
|
|
107
|
+
"typescript": "5.0.4"
|
|
108
|
+
},
|
|
109
|
+
"peerDependencies": {
|
|
110
|
+
"mongoose": ">=6.6.0 < 8"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import ms from 'ms'
|
|
2
|
+
|
|
3
|
+
import type ICacheEngine from '../interfaces/ICacheEngine'
|
|
4
|
+
|
|
5
|
+
import MemoryCacheEngine from './engine/MemoryCacheEngine'
|
|
6
|
+
import RedisCacheEngine from './engine/RedisCacheEngine'
|
|
7
|
+
|
|
8
|
+
export const engines = ['memory', 'redis'] as const
|
|
9
|
+
|
|
10
|
+
class Cache {
|
|
11
|
+
private engine: ICacheEngine
|
|
12
|
+
private defaultTTL: number
|
|
13
|
+
|
|
14
|
+
constructor (engineName: 'memory' | 'redis', defaultTTL: string) {
|
|
15
|
+
if (!engines.includes(engineName)) {
|
|
16
|
+
throw new Error(`Invalid engine name: ${engineName}`)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
this.defaultTTL = ms(defaultTTL)
|
|
20
|
+
|
|
21
|
+
if (engineName === 'redis') {
|
|
22
|
+
this.engine = new RedisCacheEngine()
|
|
23
|
+
} else {
|
|
24
|
+
this.engine = new MemoryCacheEngine()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async get (key: string): Promise<Record<string, unknown> | Record<string, unknown>[] | undefined> {
|
|
29
|
+
return await this.engine.get(key)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async set (key: string, value: Record<string, unknown> | Record<string, unknown>[], ttl?: number): Promise<void> {
|
|
33
|
+
const actualTTL = ttl ?? this.defaultTTL
|
|
34
|
+
return await this.engine.set(key, value, actualTTL)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async del (key: string): Promise<void> {
|
|
38
|
+
return await this.engine.del(key)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async clear (): Promise<void> {
|
|
42
|
+
return await this.engine.clear()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default Cache
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type ICacheEngine from '../../interfaces/ICacheEngine'
|
|
2
|
+
|
|
3
|
+
class MemoryCacheEngine implements ICacheEngine {
|
|
4
|
+
private cache: Record<string, { value: Record<string, unknown> | Record<string, unknown>[], expiresAt: number } | undefined>
|
|
5
|
+
|
|
6
|
+
constructor () {
|
|
7
|
+
this.cache = {}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
get (key: string): Record<string, unknown> | Record<string, unknown>[] | undefined {
|
|
11
|
+
const item = this.cache[key]
|
|
12
|
+
if (!item || item.expiresAt < Date.now()) {
|
|
13
|
+
return undefined
|
|
14
|
+
}
|
|
15
|
+
return item.value
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
set (key: string, value: Record<string, unknown> | Record<string, unknown>[], ttl = Infinity): void {
|
|
19
|
+
this.cache[key] = { value, expiresAt: Date.now() + ttl }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
del (key: string): void {
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
24
|
+
delete this.cache[key]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
clear (): void {
|
|
28
|
+
this.cache = {}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default MemoryCacheEngine
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import IORedis from 'ioredis'
|
|
2
|
+
|
|
3
|
+
import type { Redis } from 'ioredis'
|
|
4
|
+
|
|
5
|
+
import type ICacheEngine from '../../interfaces/ICacheEngine'
|
|
6
|
+
|
|
7
|
+
class RedisCacheEngine implements ICacheEngine {
|
|
8
|
+
private client: Redis
|
|
9
|
+
|
|
10
|
+
constructor () {
|
|
11
|
+
this.client = new IORedis()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async get (key: string): Promise<Record<string, unknown> | Record<string, unknown>[] | undefined> {
|
|
15
|
+
const value = await this.client.get(key)
|
|
16
|
+
if (value === null) {
|
|
17
|
+
return undefined
|
|
18
|
+
}
|
|
19
|
+
return JSON.parse(value) as Promise<Record<string, unknown> | Record<string, unknown>[]>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async set (key: string, value: unknown, ttl = Infinity): Promise<void> {
|
|
23
|
+
const serializedValue = JSON.stringify(value)
|
|
24
|
+
await this.client.setex(key, Math.ceil(ttl / 1000), serializedValue)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async del (key: string): Promise<void> {
|
|
28
|
+
await this.client.del(key)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async clear (): Promise<void> {
|
|
32
|
+
await this.client.flushdb()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default RedisCacheEngine
|
package/src/crypto.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { createHash } from 'crypto'
|
|
3
|
+
|
|
4
|
+
export function sortDeep (data: Record<string, unknown>[] | Record<string, unknown>): unknown {
|
|
5
|
+
if (_.isObjectLike(data) && _.isArray(data)) {
|
|
6
|
+
return data.map(sortDeep)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (_.isObjectLike(data) && !_.isArray(data)) {
|
|
10
|
+
const sortedKeys = _.keys(data).sort((a, b) => a.localeCompare(b))
|
|
11
|
+
const sortedObj: Record<string, unknown> = {}
|
|
12
|
+
|
|
13
|
+
sortedKeys.forEach((key) => {
|
|
14
|
+
sortedObj[key] = sortDeep(data[key] as Record<string, unknown>[] | Record<string, unknown>)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
return sortedObj
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return data
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getKey (data: Record<string, unknown>[] | Record<string, unknown>): string {
|
|
24
|
+
const sortedObj = sortDeep(data)
|
|
25
|
+
const sortedStr = JSON.stringify(sortedObj)
|
|
26
|
+
return createHash('sha256').update(sortedStr).digest('hex')
|
|
27
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface ICacheEngine {
|
|
2
|
+
get: (key: string) => Promise<Record<string, unknown> | Record<string, unknown>[] | undefined> | Record<string, unknown> | Record<string, unknown>[] | undefined
|
|
3
|
+
set: (key: string, value: Record<string, unknown> | Record<string, unknown>[], ttl?: number) => Promise<void> | void
|
|
4
|
+
del: (key: string) => Promise<void> | void
|
|
5
|
+
clear: () => Promise<void> | void
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default ICacheEngine
|