@edirect/rate-limit-module 11.0.45 → 11.0.47

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.
Files changed (82) hide show
  1. package/dist/README.md +499 -0
  2. package/dist/package.json +41 -0
  3. package/dist/src/decorators/rate-limiting-rule.decorator.d.ts +10 -0
  4. package/dist/src/decorators/rate-limiting-rule.decorator.d.ts.map +1 -0
  5. package/dist/src/decorators/rate-limiting-rule.decorator.js +7 -0
  6. package/dist/src/guards/rate-limiting.guard.d.ts +21 -0
  7. package/dist/src/guards/rate-limiting.guard.d.ts.map +1 -0
  8. package/dist/src/guards/rate-limiting.guard.js +248 -0
  9. package/dist/src/index.d.ts +11 -0
  10. package/dist/src/index.d.ts.map +1 -0
  11. package/dist/src/index.js +14 -0
  12. package/dist/src/main.d.ts +2 -0
  13. package/dist/src/main.d.ts.map +1 -0
  14. package/dist/src/main.js +9 -0
  15. package/dist/src/object.utils.d.ts +3 -0
  16. package/dist/src/object.utils.d.ts.map +1 -0
  17. package/dist/src/object.utils.js +38 -0
  18. package/dist/src/rate-limiting.module.d.ts +3 -0
  19. package/dist/src/rate-limiting.module.d.ts.map +1 -0
  20. package/dist/src/rate-limiting.module.js +31 -0
  21. package/dist/src/rules/dto/pagination.dto.d.ts +6 -0
  22. package/dist/src/rules/dto/pagination.dto.d.ts.map +1 -0
  23. package/dist/src/rules/dto/pagination.dto.js +42 -0
  24. package/dist/src/rules/dto/rule.dto.d.ts +24 -0
  25. package/dist/src/rules/dto/rule.dto.d.ts.map +1 -0
  26. package/dist/src/rules/dto/rule.dto.js +198 -0
  27. package/dist/src/rules/interface/pagination.interface.d.ts +7 -0
  28. package/dist/src/rules/interface/pagination.interface.d.ts.map +1 -0
  29. package/dist/src/rules/interface/pagination.interface.js +2 -0
  30. package/dist/src/rules/interface/rule.interface.d.ts +29 -0
  31. package/dist/src/rules/interface/rule.interface.d.ts.map +1 -0
  32. package/dist/src/rules/interface/rule.interface.js +2 -0
  33. package/dist/src/rules/rule.controller.d.ts +14 -0
  34. package/dist/src/rules/rule.controller.d.ts.map +1 -0
  35. package/dist/src/rules/rule.controller.js +87 -0
  36. package/dist/src/rules/rule.module.d.ts +5 -0
  37. package/dist/src/rules/rule.module.d.ts.map +1 -0
  38. package/dist/src/rules/rule.module.js +38 -0
  39. package/dist/src/rules/rule.repository.d.ts +15 -0
  40. package/dist/src/rules/rule.repository.d.ts.map +1 -0
  41. package/dist/src/rules/rule.repository.js +79 -0
  42. package/dist/src/rules/rule.schema.d.ts +176 -0
  43. package/dist/src/rules/rule.schema.d.ts.map +1 -0
  44. package/dist/src/rules/rule.schema.js +150 -0
  45. package/dist/src/rules/rule.service.d.ts +26 -0
  46. package/dist/src/rules/rule.service.d.ts.map +1 -0
  47. package/dist/src/rules/rule.service.js +204 -0
  48. package/dist/src/shared/cache/cache.service.d.ts +10 -0
  49. package/dist/src/shared/cache/cache.service.d.ts.map +1 -0
  50. package/dist/src/shared/cache/cache.service.js +29 -0
  51. package/dist/src/shared/dsl/dsl.interface.d.ts +43 -0
  52. package/dist/src/shared/dsl/dsl.interface.d.ts.map +1 -0
  53. package/dist/src/shared/dsl/dsl.interface.js +9 -0
  54. package/dist/src/shared/dsl/dsl.service.d.ts +8 -0
  55. package/dist/src/shared/dsl/dsl.service.d.ts.map +1 -0
  56. package/dist/src/shared/dsl/dsl.service.js +87 -0
  57. package/dist/src/shared/redis/redis.module.d.ts +3 -0
  58. package/dist/src/shared/redis/redis.module.d.ts.map +1 -0
  59. package/dist/src/shared/redis/redis.module.js +32 -0
  60. package/dist/src/shared/redis/redis.service.d.ts +13 -0
  61. package/dist/src/shared/redis/redis.service.d.ts.map +1 -0
  62. package/dist/src/shared/redis/redis.service.js +53 -0
  63. package/dist/src/shared/rule-engine/interface/rule-engine.interface.d.ts +14 -0
  64. package/dist/src/shared/rule-engine/interface/rule-engine.interface.d.ts.map +1 -0
  65. package/dist/src/shared/rule-engine/interface/rule-engine.interface.js +2 -0
  66. package/dist/src/shared/rule-engine/rule-engine.module.d.ts +11 -0
  67. package/dist/src/shared/rule-engine/rule-engine.module.d.ts.map +1 -0
  68. package/dist/src/shared/rule-engine/rule-engine.module.js +51 -0
  69. package/dist/src/shared/rule-engine/rule-engine.service.d.ts +18 -0
  70. package/dist/src/shared/rule-engine/rule-engine.service.d.ts.map +1 -0
  71. package/dist/src/shared/rule-engine/rule-engine.service.js +134 -0
  72. package/dist/src/shared/shared.module.d.ts +3 -0
  73. package/dist/src/shared/shared.module.d.ts.map +1 -0
  74. package/dist/src/shared/shared.module.js +29 -0
  75. package/dist/src/validators/rule.constraint.d.ts +10 -0
  76. package/dist/src/validators/rule.constraint.d.ts.map +1 -0
  77. package/dist/src/validators/rule.constraint.js +49 -0
  78. package/dist/src/validators/rule.validator.d.ts +3 -0
  79. package/dist/src/validators/rule.validator.d.ts.map +1 -0
  80. package/dist/src/validators/rule.validator.js +16 -0
  81. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  82. package/package.json +3 -3
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RuleService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const logger_1 = require("@edirect/logger");
6
+ const common_1 = require("@nestjs/common");
7
+ const object_utils_1 = require("../object.utils");
8
+ const cache_service_1 = require("../shared/cache/cache.service");
9
+ const rule_repository_1 = require("./rule.repository");
10
+ let RuleService = class RuleService {
11
+ logger;
12
+ repository;
13
+ cacheService;
14
+ MAX_EXPRESSION_LENGTH = 500;
15
+ MAX_EXPRESSION_DEPTH = 8;
16
+ FORBIDDEN_PATTERNS = [
17
+ /constructor/i,
18
+ /__proto__/i,
19
+ /prototype/i,
20
+ /process/i,
21
+ /global/i,
22
+ /require/i,
23
+ /import/i,
24
+ /eval/i,
25
+ /Function/i,
26
+ /setTimeout/i,
27
+ /setInterval/i,
28
+ /api/i,
29
+ /request/i,
30
+ /\[".*"\s*\+\s*".*"\]/,
31
+ ];
32
+ constructor(logger, repository, cacheService) {
33
+ this.logger = logger;
34
+ this.repository = repository;
35
+ this.cacheService = cacheService;
36
+ }
37
+ async create(input) {
38
+ try {
39
+ if (!input)
40
+ throw new common_1.BadRequestException('[ERROR] payload invalid!');
41
+ const cacheKey = this.generateRateLimitingCountCacheKey({
42
+ partner: input?.partner,
43
+ provider: input?.provider,
44
+ productType: input?.productType,
45
+ market: input?.market,
46
+ });
47
+ if (cacheKey || cacheKey === '') {
48
+ const isDeleted = await this.cacheService.delete([cacheKey]);
49
+ if (!isDeleted) {
50
+ await this.cacheService.deleteByPattern('rate-limit-config');
51
+ }
52
+ }
53
+ return this.repository.save(input);
54
+ }
55
+ catch (error) {
56
+ this.logError(`[ERROR] error to create rate limiting `, error);
57
+ throw error;
58
+ }
59
+ }
60
+ async findAll(queryParameters) {
61
+ try {
62
+ return this.repository.findAll(queryParameters);
63
+ }
64
+ catch (error) {
65
+ this.logError('[ERROR] error to find rate limiting', error);
66
+ throw new common_1.InternalServerErrorException();
67
+ }
68
+ }
69
+ async findAllWithoutPagination(queryParameters) {
70
+ try {
71
+ const cachedData = await this.getFromCache(queryParameters);
72
+ if (cachedData && cachedData.length)
73
+ return cachedData;
74
+ const { data } = await this.repository.findAll(queryParameters);
75
+ const cacheKey = this.generateRateLimitingCountCacheKey({
76
+ partner: queryParameters?.partner || '',
77
+ provider: queryParameters?.provider || '',
78
+ productType: queryParameters?.productType || '',
79
+ market: queryParameters?.market || '',
80
+ });
81
+ if (data && data.length) {
82
+ await this.cacheService.set(cacheKey, data, 3600);
83
+ }
84
+ return data;
85
+ }
86
+ catch (error) {
87
+ this.logError('[ERROR] error to fnd rate limiting', error);
88
+ throw new common_1.InternalServerErrorException();
89
+ }
90
+ }
91
+ async findById(id) {
92
+ try {
93
+ const rate = await this.repository.findOneByRateId(id);
94
+ if (!rate)
95
+ throw new common_1.NotFoundException('Rate Limiting rule');
96
+ return rate;
97
+ }
98
+ catch (error) {
99
+ this.logError('[ERROR] error to find quote by ID', error);
100
+ throw error;
101
+ }
102
+ }
103
+ async updateOne(id, fieldsToUpdate) {
104
+ try {
105
+ if (!id)
106
+ throw new common_1.NotFoundException('Rate Limiting rule');
107
+ const current = await this.repository.findOneByRateId(id);
108
+ if (!current)
109
+ throw new common_1.NotFoundException('Rate Limiting rule');
110
+ if (current.deletedAt) {
111
+ throw new common_1.GoneException(`Already Deleted at ${current.deletedAt}`);
112
+ }
113
+ const cacheKey = this.generateRateLimitingCountCacheKey({
114
+ partner: current?.partner || '',
115
+ provider: current?.provider || '',
116
+ productType: current?.productType || '',
117
+ market: current?.market || '',
118
+ });
119
+ if (cacheKey || cacheKey === '') {
120
+ const isDeleted = await this.cacheService.delete([cacheKey]);
121
+ if (!isDeleted) {
122
+ await this.cacheService.deleteByPattern('rate-limit-config');
123
+ }
124
+ }
125
+ return this.repository.update(id, fieldsToUpdate);
126
+ }
127
+ catch (error) {
128
+ this.logError(`[ERROR] error to update ${id}`, error);
129
+ throw error;
130
+ }
131
+ }
132
+ async delete(id) {
133
+ try {
134
+ if (!id)
135
+ throw new common_1.NotFoundException('Rate limiting rule');
136
+ const rule = await this.repository.findOneByRateId(id);
137
+ if (rule?.deletedAt) {
138
+ throw new common_1.GoneException(`Already Deleted at ${rule.deletedAt}`);
139
+ }
140
+ await this.repository.update(id, {
141
+ deletedAt: new Date(),
142
+ });
143
+ }
144
+ catch (error) {
145
+ this.logError(`[ERROR] Error to delete rule`, error);
146
+ throw error;
147
+ }
148
+ }
149
+ logError(message, error) {
150
+ this.logger.error(message, error instanceof Error ? error.stack || error.message : String(error));
151
+ }
152
+ validateRuleExpression(expression) {
153
+ if (expression && expression.length > this.MAX_EXPRESSION_LENGTH) {
154
+ return `Expression too long: ${expression.length} chars`;
155
+ }
156
+ for (const pattern of this.FORBIDDEN_PATTERNS) {
157
+ if (pattern.test(expression)) {
158
+ return `Expression contains forbidden pattern: ${pattern}`;
159
+ }
160
+ }
161
+ const depth = (0, object_utils_1.calculateDepth)(expression);
162
+ if (depth && depth > this.MAX_EXPRESSION_DEPTH) {
163
+ return `Expression too complex`;
164
+ }
165
+ return null;
166
+ }
167
+ async getFromCache(queryParameters) {
168
+ const cacheKey = this.generateRateLimitingCountCacheKey({
169
+ partner: queryParameters?.partner || '',
170
+ provider: queryParameters?.provider || '',
171
+ productType: queryParameters?.productType || '',
172
+ market: queryParameters?.market || '',
173
+ });
174
+ const cachedData = await this.cacheService.get(cacheKey);
175
+ if (cachedData && cachedData.length) {
176
+ this.logger.info(`[INFO] Cache hit for: ${JSON.stringify(cachedData)}`);
177
+ return cachedData;
178
+ }
179
+ return [];
180
+ }
181
+ generateRateLimitingCountCacheKey(params) {
182
+ if (!params.partner && !params.provider)
183
+ return '';
184
+ const parameters = {
185
+ ...params,
186
+ enabled: 'true',
187
+ };
188
+ const orderedParams = Object.keys(parameters)
189
+ .sort()
190
+ .reduce((obj, key) => {
191
+ // Ensure all values are stringified for cache key
192
+ obj[key] = String(parameters[key]);
193
+ return obj;
194
+ }, {});
195
+ return `rate-limit-config:${JSON.stringify(orderedParams)}`;
196
+ }
197
+ };
198
+ exports.RuleService = RuleService;
199
+ exports.RuleService = RuleService = tslib_1.__decorate([
200
+ (0, common_1.Injectable)(),
201
+ tslib_1.__metadata("design:paramtypes", [logger_1.LoggerService,
202
+ rule_repository_1.RuleRepository,
203
+ cache_service_1.CacheService])
204
+ ], RuleService);
@@ -0,0 +1,10 @@
1
+ import { RedisService } from '../redis/redis.service';
2
+ export declare class CacheService {
3
+ private readonly redis;
4
+ constructor(redis: RedisService);
5
+ get<T>(key: string): Promise<T | null>;
6
+ set<T>(key: string, value: T, ttl?: number): Promise<void>;
7
+ delete(keys: string[]): Promise<number>;
8
+ deleteByPattern(pattern: string): Promise<number>;
9
+ }
10
+ //# sourceMappingURL=cache.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.service.d.ts","sourceRoot":"","sources":["../../../../src/shared/cache/cache.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,qBACa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,YAAY;IAE1C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAI5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAIvC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAGlD"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CacheService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const redis_service_1 = require("../redis/redis.service");
7
+ let CacheService = class CacheService {
8
+ redis;
9
+ constructor(redis) {
10
+ this.redis = redis;
11
+ }
12
+ async get(key) {
13
+ return await this.redis.get(key);
14
+ }
15
+ set(key, value, ttl) {
16
+ return this.redis.set(key, value, ttl);
17
+ }
18
+ delete(keys) {
19
+ return this.redis.delKeys(keys);
20
+ }
21
+ deleteByPattern(pattern) {
22
+ return this.redis.deleteByPattern(pattern);
23
+ }
24
+ };
25
+ exports.CacheService = CacheService;
26
+ exports.CacheService = CacheService = tslib_1.__decorate([
27
+ (0, common_1.Injectable)(),
28
+ tslib_1.__metadata("design:paramtypes", [redis_service_1.RedisService])
29
+ ], CacheService);
@@ -0,0 +1,43 @@
1
+ type Primitive = string | number | boolean | Date;
2
+ interface EqFilter<T = Primitive> {
3
+ eq: T;
4
+ }
5
+ interface InFilter<T = Primitive> {
6
+ in: T[];
7
+ }
8
+ interface RangeFilter<T = Date | number> {
9
+ range: {
10
+ from?: T;
11
+ to?: T;
12
+ };
13
+ }
14
+ interface GteFilter<T = Date | number> {
15
+ gte: T;
16
+ }
17
+ interface LteFilter<T = Date | number> {
18
+ lte: T;
19
+ }
20
+ interface ElemMatchFilter {
21
+ elemMatch: FilterDsl;
22
+ }
23
+ type FieldFilter = EqFilter | InFilter | RangeFilter | ElemMatchFilter | LteFilter | GteFilter;
24
+ export interface FilterDsl {
25
+ or?: FilterDsl[];
26
+ [field: string]: FieldFilter | FilterDsl[] | undefined;
27
+ }
28
+ export interface IDslQuery {
29
+ fnContext: string;
30
+ query: IDslQueryItem[];
31
+ }
32
+ export interface IDslQueryItem {
33
+ label: string;
34
+ value: unknown;
35
+ op: OperationDslEnum;
36
+ }
37
+ export declare enum OperationDslEnum {
38
+ EQ = "eq",
39
+ RANGE = "range",
40
+ GTE = "gte"
41
+ }
42
+ export {};
43
+ //# sourceMappingURL=dsl.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsl.interface.d.ts","sourceRoot":"","sources":["../../../../src/shared/dsl/dsl.interface.ts"],"names":[],"mappings":"AAAA,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAElD,UAAU,QAAQ,CAAC,CAAC,GAAG,SAAS;IAC9B,EAAE,EAAE,CAAC,CAAC;CACP;AAED,UAAU,QAAQ,CAAC,CAAC,GAAG,SAAS;IAC9B,EAAE,EAAE,CAAC,EAAE,CAAC;CACT;AAED,UAAU,WAAW,CAAC,CAAC,GAAG,IAAI,GAAG,MAAM;IACrC,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,CAAC,CAAC;QACT,EAAE,CAAC,EAAE,CAAC,CAAC;KACR,CAAC;CACH;AAED,UAAU,SAAS,CAAC,CAAC,GAAG,IAAI,GAAG,MAAM;IACnC,GAAG,EAAE,CAAC,CAAC;CACR;AAED,UAAU,SAAS,CAAC,CAAC,GAAG,IAAI,GAAG,MAAM;IACnC,GAAG,EAAE,CAAC,CAAC;CACR;AAED,UAAU,eAAe;IACvB,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,KAAK,WAAW,GACZ,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,eAAe,GACf,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,SAAS;IACxB,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC;IACjB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,EAAE,GAAG,SAAS,CAAC;CACxD;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,EAAE,EAAE,gBAAgB,CAAC;CACtB;AAED,oBAAY,gBAAgB;IAC1B,EAAE,OAAO;IACT,KAAK,UAAU;IACf,GAAG,QAAQ;CACZ"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OperationDslEnum = void 0;
4
+ var OperationDslEnum;
5
+ (function (OperationDslEnum) {
6
+ OperationDslEnum["EQ"] = "eq";
7
+ OperationDslEnum["RANGE"] = "range";
8
+ OperationDslEnum["GTE"] = "gte";
9
+ })(OperationDslEnum || (exports.OperationDslEnum = OperationDslEnum = {}));
@@ -0,0 +1,8 @@
1
+ import { QueryFilter } from 'mongoose';
2
+ import { FilterDsl, IDslQueryItem } from './dsl.interface';
3
+ export declare class DslService {
4
+ #private;
5
+ static buildFilter: (query: IDslQueryItem[]) => FilterDsl;
6
+ static toMongoQuery: (filter: FilterDsl) => QueryFilter<IDslQueryItem>;
7
+ }
8
+ //# sourceMappingURL=dsl.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsl.service.d.ts","sourceRoot":"","sources":["../../../../src/shared/dsl/dsl.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3D,qBAAa,UAAU;;IACrB,MAAM,CAAC,WAAW,GAAI,OAAO,aAAa,EAAE,KAAG,SAAS,CAWtD;IAEF,MAAM,CAAC,YAAY,GACjB,QAAQ,SAAS,KAChB,WAAW,CAAC,aAAa,CAAC,CAuD3B;CAuBH"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DslService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const dayjs_1 = tslib_1.__importDefault(require("dayjs"));
6
+ class DslService {
7
+ static buildFilter = (query) => {
8
+ return query.reduce((acc, cur) => {
9
+ if (!cur || !cur.label)
10
+ return acc;
11
+ const value = cur.value ?? '';
12
+ return {
13
+ ...acc,
14
+ [cur.label]: this.#buildOp(cur.op, value),
15
+ };
16
+ }, {});
17
+ };
18
+ static toMongoQuery = (filter) => {
19
+ const query = {};
20
+ for (const key in filter) {
21
+ const condition = filter[key];
22
+ if (!condition)
23
+ continue;
24
+ if (key === 'or' && Array.isArray(condition)) {
25
+ query['$or'] = condition.map(subCond => this.toMongoQuery(subCond));
26
+ continue;
27
+ }
28
+ if ('eq' in condition && condition.eq !== undefined) {
29
+ query[key] = condition.eq;
30
+ }
31
+ if ('in' in condition && condition.in !== undefined) {
32
+ query[key] = { $in: condition.in };
33
+ }
34
+ if ('range' in condition && condition.range !== undefined) {
35
+ const rangeQuery = {};
36
+ const conditionRange = condition.range;
37
+ if (conditionRange.from)
38
+ rangeQuery['$gte'] = conditionRange.from;
39
+ if (conditionRange.to)
40
+ rangeQuery['$lte'] = conditionRange.to;
41
+ query[key] = rangeQuery;
42
+ }
43
+ if ('gte' in condition) {
44
+ const gteQuery = {};
45
+ if (condition.gte !== undefined)
46
+ gteQuery['$gte'] = condition.gte;
47
+ query[key] = gteQuery;
48
+ }
49
+ if ('lte' in condition) {
50
+ const lteQuery = {};
51
+ if (condition.lte !== undefined)
52
+ lteQuery['$lte'] = condition.lte;
53
+ query[key] = lteQuery;
54
+ }
55
+ if ('elemMatch' in condition) {
56
+ const elemMatchQuery = {};
57
+ if (condition.elemMatch) {
58
+ elemMatchQuery['$elemMatch'] = this.toMongoQuery(condition.elemMatch);
59
+ query[key] = elemMatchQuery;
60
+ }
61
+ }
62
+ }
63
+ return query;
64
+ };
65
+ static #buildOp = (op, value) => {
66
+ if (op === 'rangeDate') {
67
+ const data = value;
68
+ return {
69
+ range: {
70
+ from: data?.from || (0, dayjs_1.default)().subtract(1, 'month').toDate(),
71
+ to: data?.to || new Date(),
72
+ },
73
+ };
74
+ }
75
+ if (op === 'range') {
76
+ const data = value;
77
+ return {
78
+ range: {
79
+ from: data?.from,
80
+ to: data?.to,
81
+ },
82
+ };
83
+ }
84
+ return { [op || 'eq']: value };
85
+ };
86
+ }
87
+ exports.DslService = DslService;
@@ -0,0 +1,3 @@
1
+ export declare class RedisModule {
2
+ }
3
+ //# sourceMappingURL=redis.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.module.d.ts","sourceRoot":"","sources":["../../../../src/shared/redis/redis.module.ts"],"names":[],"mappings":"AAKA,qBAmBa,WAAW;CAAG"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RedisModule = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const config_1 = require("@nestjs/config");
7
+ const ioredis_1 = tslib_1.__importDefault(require("ioredis"));
8
+ const redis_service_1 = require("./redis.service");
9
+ let RedisModule = class RedisModule {
10
+ };
11
+ exports.RedisModule = RedisModule;
12
+ exports.RedisModule = RedisModule = tslib_1.__decorate([
13
+ (0, common_1.Global)(),
14
+ (0, common_1.Module)({
15
+ imports: [config_1.ConfigModule],
16
+ providers: [
17
+ {
18
+ provide: 'REDIS_CLIENT',
19
+ useFactory: (config) => {
20
+ return new ioredis_1.default({
21
+ host: config.get('REDIS_HOST'),
22
+ port: config.get('REDIS_PORT'),
23
+ password: config.get('REDIS_PASSWORD'),
24
+ });
25
+ },
26
+ inject: [config_1.ConfigService],
27
+ },
28
+ redis_service_1.RedisService,
29
+ ],
30
+ exports: ['REDIS_CLIENT', redis_service_1.RedisService],
31
+ })
32
+ ], RedisModule);
@@ -0,0 +1,13 @@
1
+ import { OnModuleDestroy } from '@nestjs/common';
2
+ import Redis from 'ioredis';
3
+ export declare class RedisService implements OnModuleDestroy {
4
+ private readonly client;
5
+ constructor(client: Redis);
6
+ get<T>(key: string): Promise<T | null>;
7
+ set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
8
+ delKeys(keys: string[]): Promise<number>;
9
+ scan(pattern: string, count?: number): Promise<string[]>;
10
+ deleteByPattern(pattern: string): Promise<number>;
11
+ onModuleDestroy(): void;
12
+ }
13
+ //# sourceMappingURL=redis.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.service.d.ts","sourceRoot":"","sources":["../../../../src/shared/redis/redis.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,MAAM,SAAS,CAAC;AAE5B,qBACa,YAAa,YAAW,eAAe;IAGhD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,KAAK;IAG1B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKtC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASjE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAKxC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAmBrD,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKvD,eAAe;CAGhB"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RedisService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const ioredis_1 = tslib_1.__importDefault(require("ioredis"));
7
+ let RedisService = class RedisService {
8
+ client;
9
+ constructor(client) {
10
+ this.client = client;
11
+ }
12
+ async get(key) {
13
+ const raw = await this.client.get(key);
14
+ return raw ? JSON.parse(raw) : null;
15
+ }
16
+ async set(key, value, ttlSeconds) {
17
+ const str = JSON.stringify(value);
18
+ if (ttlSeconds) {
19
+ await this.client.set(key, str, 'EX', ttlSeconds);
20
+ }
21
+ else {
22
+ await this.client.set(key, str);
23
+ }
24
+ }
25
+ async delKeys(keys) {
26
+ if (keys.length === 0)
27
+ return 0;
28
+ return this.client.del(...keys);
29
+ }
30
+ async scan(pattern, count = 100) {
31
+ let cursor = '0';
32
+ const found = [];
33
+ do {
34
+ const [nextCursor, keys] = await this.client.scan(cursor, 'MATCH', pattern, 'COUNT', count);
35
+ cursor = nextCursor;
36
+ found.push(...keys);
37
+ } while (cursor !== '0');
38
+ return found;
39
+ }
40
+ async deleteByPattern(pattern) {
41
+ const keys = await this.scan(pattern);
42
+ return this.delKeys(keys);
43
+ }
44
+ onModuleDestroy() {
45
+ this.client.quit();
46
+ }
47
+ };
48
+ exports.RedisService = RedisService;
49
+ exports.RedisService = RedisService = tslib_1.__decorate([
50
+ (0, common_1.Injectable)(),
51
+ tslib_1.__param(0, (0, common_1.Inject)('REDIS_CLIENT')),
52
+ tslib_1.__metadata("design:paramtypes", [ioredis_1.default])
53
+ ], RedisService);
@@ -0,0 +1,14 @@
1
+ export interface IRuleFunction {
2
+ fn: (...args: unknown[]) => Promise<unknown>;
3
+ params: string[];
4
+ description: string;
5
+ name: string;
6
+ entity?: string;
7
+ returnType?: string;
8
+ }
9
+ export interface RuleEngineInterface {
10
+ evaluate<T>(expression: string, context: T): Promise<boolean>;
11
+ registerCustomFunctions(customFunctions: IRuleFunction[]): void;
12
+ validateExpressionVariables<T>(expression: string, context: T): Promise<string[]>;
13
+ }
14
+ //# sourceMappingURL=rule-engine.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine.interface.d.ts","sourceRoot":"","sources":["../../../../../src/shared/rule-engine/interface/rule-engine.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,uBAAuB,CAAC,eAAe,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAChE,2BAA2B,CAAC,CAAC,EAC3B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,GACT,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACtB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,11 @@
1
+ import { DynamicModule, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
2
+ import { IRuleFunction } from './interface/rule-engine.interface';
3
+ export declare class RuleEngineModule {
4
+ static forFeatureAsync(options: {
5
+ useFactory: (...args: any[]) => Promise<IRuleFunction[]>;
6
+ inject?: Array<InjectionToken | OptionalFactoryDependency>;
7
+ imports?: DynamicModule['imports'];
8
+ }): DynamicModule;
9
+ static forFeature(functions: IRuleFunction[]): DynamicModule;
10
+ }
11
+ //# sourceMappingURL=rule-engine.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine.module.d.ts","sourceRoot":"","sources":["../../../../src/shared/rule-engine/rule-engine.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,cAAc,EAAU,yBAAyB,EAAY,MAAM,gBAAgB,CAAC;AAEpH,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,qBAEa,gBAAgB;IAC3B,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE;QAC9B,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QACzD,MAAM,CAAC,EAAE,KAAK,CAAC,cAAc,GAAG,yBAAyB,CAAC,CAAC;QAC3D,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;KACpC,GAAG,aAAa;IAuBjB,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,aAAa;CAkB7D"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var RuleEngineModule_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.RuleEngineModule = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const index_1 = require("../../index");
8
+ const rule_engine_service_1 = require("./rule-engine.service");
9
+ let RuleEngineModule = RuleEngineModule_1 = class RuleEngineModule {
10
+ static forFeatureAsync(options) {
11
+ const functionsProvider = {
12
+ provide: index_1.CUSTOM_RULE_FUNCTIONS,
13
+ useFactory: options.useFactory,
14
+ inject: options?.inject || [],
15
+ };
16
+ const ruleEngineProvider = {
17
+ provide: index_1.RULE_ENGINE_INSTANCE,
18
+ useFactory: (fns) => {
19
+ return new rule_engine_service_1.RuleEngineService(fns);
20
+ },
21
+ inject: [index_1.CUSTOM_RULE_FUNCTIONS],
22
+ };
23
+ return {
24
+ module: RuleEngineModule_1,
25
+ imports: options.imports || [],
26
+ providers: [functionsProvider, ruleEngineProvider],
27
+ exports: [index_1.RULE_ENGINE_INSTANCE],
28
+ };
29
+ }
30
+ static forFeature(functions) {
31
+ const functionsProvider = {
32
+ provide: index_1.CUSTOM_RULE_FUNCTIONS,
33
+ useValue: functions,
34
+ };
35
+ const ruleEngineProvider = {
36
+ provide: index_1.RULE_ENGINE_INSTANCE,
37
+ useFactory: (fns) => new rule_engine_service_1.RuleEngineService(fns),
38
+ inject: [index_1.CUSTOM_RULE_FUNCTIONS],
39
+ };
40
+ return {
41
+ module: RuleEngineModule_1,
42
+ providers: [functionsProvider, ruleEngineProvider],
43
+ exports: [index_1.RULE_ENGINE_INSTANCE],
44
+ };
45
+ }
46
+ };
47
+ exports.RuleEngineModule = RuleEngineModule;
48
+ exports.RuleEngineModule = RuleEngineModule = RuleEngineModule_1 = tslib_1.__decorate([
49
+ (0, common_1.Global)(),
50
+ (0, common_1.Module)({})
51
+ ], RuleEngineModule);
@@ -0,0 +1,18 @@
1
+ import { IRuleFunction } from './interface/rule-engine.interface';
2
+ export declare class RuleEngineService {
3
+ private readonly fns;
4
+ private readonly jexl;
5
+ private readonly allowedFns;
6
+ constructor(fns?: IRuleFunction[]);
7
+ evaluate<T>(expression: string, context: T): Promise<boolean>;
8
+ getResultCustomFunction(fnName: string, context: Record<string, unknown>): Promise<unknown>;
9
+ validateExpressionVariables<T>(expression: string, context: T): Promise<string[]>;
10
+ validateFunctionsAreValid(expression: string): string[];
11
+ getAllowedFunctions(): string[];
12
+ injectCustomFns(): void;
13
+ private _extractVariables;
14
+ private _validateVariablesInContext;
15
+ private _extractFunctionCalls;
16
+ private _resolveValue;
17
+ }
18
+ //# sourceMappingURL=rule-engine.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine.service.d.ts","sourceRoot":"","sources":["../../../../src/shared/rule-engine/rule-engine.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,qBAAa,iBAAiB;IAIhB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHhC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;gBAEd,GAAG,GAAE,aAAa,EAAO;IAKhD,QAAQ,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAqB7D,uBAAuB,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC;IAWb,2BAA2B,CAAC,CAAC,EACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,GACT,OAAO,CAAC,MAAM,EAAE,CAAC;IASpB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAgBvD,mBAAmB,IAAI,MAAM,EAAE;IAI/B,eAAe,IAAI,IAAI;IAOvB,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,2BAA2B;IAqCnC,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,aAAa;CAatB"}