@nest-omni/core 4.1.3-1 → 4.1.3-10
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/audit/audit.module.d.ts +10 -0
- package/audit/audit.module.js +15 -0
- package/audit/controllers/audit.controller.d.ts +24 -0
- package/audit/controllers/audit.controller.js +24 -0
- package/audit/decorators/audit-controller.decorator.d.ts +8 -0
- package/audit/decorators/audit-controller.decorator.js +9 -0
- package/audit/decorators/audit-operation.decorator.d.ts +45 -0
- package/audit/decorators/audit-operation.decorator.js +49 -0
- package/audit/decorators/entity-audit.decorator.d.ts +8 -0
- package/audit/decorators/entity-audit.decorator.js +9 -0
- package/audit/dto/audit-log-query.dto.d.ts +3 -0
- package/audit/dto/audit-log-query.dto.js +3 -0
- package/audit/dto/begin-transaction.dto.d.ts +3 -0
- package/audit/dto/begin-transaction.dto.js +3 -0
- package/audit/dto/compare-entities.dto.d.ts +3 -0
- package/audit/dto/compare-entities.dto.js +3 -0
- package/audit/dto/pre-check-restore.dto.d.ts +3 -0
- package/audit/dto/pre-check-restore.dto.js +3 -0
- package/audit/dto/restore-entity.dto.d.ts +3 -0
- package/audit/dto/restore-entity.dto.js +3 -0
- package/audit/entities/entity-audit-log.entity.d.ts +3 -0
- package/audit/entities/entity-audit-log.entity.js +3 -0
- package/audit/entities/entity-transaction.entity.d.ts +3 -0
- package/audit/entities/entity-transaction.entity.js +3 -0
- package/audit/entities/manual-operation-log.entity.d.ts +4 -0
- package/audit/entities/manual-operation-log.entity.js +4 -0
- package/audit/entities/operation-template.entity.d.ts +4 -0
- package/audit/entities/operation-template.entity.js +4 -0
- package/audit/enums/audit.enums.d.ts +17 -2
- package/audit/enums/audit.enums.js +15 -0
- package/audit/index.js +10 -0
- package/audit/interceptors/audit.interceptor.d.ts +15 -0
- package/audit/interceptors/audit.interceptor.js +23 -1
- package/audit/interfaces/audit.interfaces.d.ts +42 -0
- package/audit/services/audit-context.service.d.ts +15 -0
- package/audit/services/audit-context.service.js +15 -0
- package/audit/services/audit-strategy.service.d.ts +6 -0
- package/audit/services/audit-strategy.service.js +13 -0
- package/audit/services/entity-audit.service.d.ts +57 -0
- package/audit/services/entity-audit.service.js +91 -0
- package/audit/services/manual-audit-log.service.d.ts +124 -0
- package/audit/services/manual-audit-log.service.js +138 -0
- package/audit/services/multi-database.service.d.ts +12 -0
- package/audit/services/multi-database.service.js +12 -0
- package/audit/services/operation-description.service.d.ts +59 -0
- package/audit/services/operation-description.service.js +76 -2
- package/audit/services/transaction-audit.service.d.ts +30 -0
- package/audit/services/transaction-audit.service.js +47 -0
- package/audit/subscribers/entity-audit.subscriber.d.ts +15 -0
- package/audit/subscribers/entity-audit.subscriber.js +29 -1
- package/cache/cache-metrics.service.d.ts +67 -0
- package/cache/cache-metrics.service.js +68 -4
- package/cache/cache-serialization.service.d.ts +31 -0
- package/cache/cache-serialization.service.js +25 -0
- package/cache/cache.constants.d.ts +9 -0
- package/cache/cache.constants.js +9 -0
- package/cache/cache.health.d.ts +26 -0
- package/cache/cache.health.js +30 -0
- package/cache/cache.module.d.ts +86 -0
- package/cache/cache.module.js +71 -0
- package/cache/cache.service.d.ts +140 -0
- package/cache/cache.service.js +157 -0
- package/cache/cache.warmup.service.d.ts +39 -0
- package/cache/cache.warmup.service.js +32 -0
- package/cache/decorators/cache-evict.decorator.d.ts +47 -0
- package/cache/decorators/cache-evict.decorator.js +56 -0
- package/cache/decorators/cache-put.decorator.d.ts +34 -0
- package/cache/decorators/cache-put.decorator.js +39 -0
- package/cache/decorators/cacheable.decorator.d.ts +40 -0
- package/cache/decorators/cacheable.decorator.js +55 -0
- package/cache/dependencies/callback.dependency.d.ts +33 -0
- package/cache/dependencies/callback.dependency.js +39 -1
- package/cache/dependencies/chain.dependency.d.ts +28 -0
- package/cache/dependencies/chain.dependency.js +34 -0
- package/cache/dependencies/db.dependency.d.ts +45 -0
- package/cache/dependencies/db.dependency.js +48 -1
- package/cache/dependencies/file.dependency.d.ts +32 -0
- package/cache/dependencies/file.dependency.js +34 -0
- package/cache/dependencies/tag.dependency.d.ts +36 -0
- package/cache/dependencies/tag.dependency.js +36 -0
- package/cache/dependencies/time.dependency.d.ts +43 -0
- package/cache/dependencies/time.dependency.js +43 -0
- package/cache/examples/basic-usage.d.ts +15 -0
- package/cache/examples/basic-usage.js +62 -8
- package/cache/index.js +9 -0
- package/cache/interfaces/cache-dependency.interface.d.ts +53 -0
- package/cache/interfaces/cache-options.interface.d.ts +81 -0
- package/cache/interfaces/cache-options.interface.js +6 -0
- package/cache/interfaces/cache-provider.interface.d.ts +78 -0
- package/cache/providers/base-cache.provider.d.ts +14 -0
- package/cache/providers/base-cache.provider.js +16 -0
- package/cache/providers/cls-cache.provider.d.ts +20 -0
- package/cache/providers/cls-cache.provider.js +28 -0
- package/cache/providers/memory-cache.provider.d.ts +23 -0
- package/cache/providers/memory-cache.provider.js +26 -0
- package/cache/providers/redis-cache.provider.d.ts +26 -0
- package/cache/providers/redis-cache.provider.js +29 -0
- package/cache/utils/dependency-manager.util.d.ts +52 -0
- package/cache/utils/dependency-manager.util.js +59 -0
- package/cache/utils/key-generator.util.d.ts +42 -0
- package/cache/utils/key-generator.util.js +53 -1
- package/common/abstract.entity.d.ts +14 -0
- package/common/abstract.entity.js +14 -0
- package/common/boilerplate.polyfill.d.ts +142 -4
- package/common/boilerplate.polyfill.js +24 -100
- package/common/dto/dto-container.d.ts +16 -0
- package/common/dto/dto-container.js +20 -0
- package/common/dto/dto-decorators.d.ts +18 -0
- package/common/dto/dto-decorators.js +14 -0
- package/common/dto/dto-extensions.d.ts +11 -0
- package/common/dto/dto-extensions.js +9 -0
- package/common/dto/dto-service-accessor.d.ts +17 -0
- package/common/dto/dto-service-accessor.js +18 -0
- package/common/dto/dto-transformer.d.ts +12 -0
- package/common/dto/dto-transformer.js +9 -0
- package/common/dto/index.js +2 -0
- package/common/examples/paginate-and-map.example.d.ts +6 -0
- package/common/examples/paginate-and-map.example.js +26 -0
- package/common/utils.d.ts +15 -0
- package/common/utils.js +15 -0
- package/constants/language-code.js +1 -0
- package/decorators/field.decorators.js +8 -1
- package/decorators/property.decorators.js +1 -0
- package/decorators/public-route.decorator.js +1 -0
- package/decorators/transform.decorators.d.ts +27 -0
- package/decorators/transform.decorators.js +29 -0
- package/decorators/translate.decorator.js +1 -0
- package/decorators/user.decorator.js +1 -0
- package/decorators/validator.decorators.d.ts +8 -18
- package/decorators/validator.decorators.js +22 -190
- package/filters/constraint-errors.js +1 -0
- package/helpers/common.helper.d.ts +13 -0
- package/helpers/common.helper.js +13 -0
- package/http-client/config/http-client.config.d.ts +15 -0
- package/http-client/config/http-client.config.js +25 -9
- package/http-client/decorators/http-client.decorators.d.ts +63 -0
- package/http-client/decorators/http-client.decorators.js +71 -3
- package/http-client/entities/http-log.entity.d.ts +229 -0
- package/http-client/entities/http-log.entity.js +6 -1
- package/http-client/errors/http-client.errors.d.ts +57 -0
- package/http-client/errors/http-client.errors.js +58 -0
- package/http-client/examples/advanced-usage.example.d.ts +41 -0
- package/http-client/examples/advanced-usage.example.js +68 -24
- package/http-client/examples/auth-with-waiting-lock.example.d.ts +31 -0
- package/http-client/examples/auth-with-waiting-lock.example.js +52 -5
- package/http-client/examples/basic-usage.example.d.ts +60 -0
- package/http-client/examples/basic-usage.example.js +60 -0
- package/http-client/examples/multi-api-configuration.example.d.ts +60 -0
- package/http-client/examples/multi-api-configuration.example.js +76 -5
- package/http-client/http-client.module.d.ts +13 -0
- package/http-client/http-client.module.js +19 -0
- package/http-client/index.js +8 -0
- package/http-client/interfaces/api-client-config.interface.d.ts +125 -0
- package/http-client/interfaces/api-client-config.interface.js +3 -0
- package/http-client/interfaces/http-client-config.interface.d.ts +60 -0
- package/http-client/services/api-client-registry.service.d.ts +57 -0
- package/http-client/services/api-client-registry.service.js +84 -1
- package/http-client/services/cache.service.d.ts +52 -0
- package/http-client/services/cache.service.js +72 -3
- package/http-client/services/circuit-breaker.service.d.ts +46 -0
- package/http-client/services/circuit-breaker.service.js +52 -0
- package/http-client/services/http-client.service.d.ts +67 -0
- package/http-client/services/http-client.service.js +105 -4
- package/http-client/services/http-log-query.service.d.ts +83 -0
- package/http-client/services/http-log-query.service.js +122 -1
- package/http-client/services/http-replay.service.d.ts +101 -0
- package/http-client/services/http-replay.service.js +86 -0
- package/http-client/services/log-cleanup.service.d.ts +63 -0
- package/http-client/services/log-cleanup.service.js +54 -2
- package/http-client/services/logging.service.d.ts +40 -0
- package/http-client/services/logging.service.js +53 -0
- package/http-client/utils/call-stack-extractor.util.d.ts +37 -0
- package/http-client/utils/call-stack-extractor.util.js +48 -0
- package/http-client/utils/context-extractor.util.d.ts +49 -0
- package/http-client/utils/context-extractor.util.js +52 -0
- package/http-client/utils/curl-generator.util.d.ts +21 -0
- package/http-client/utils/curl-generator.util.js +44 -3
- package/http-client/utils/request-id.util.d.ts +18 -0
- package/http-client/utils/request-id.util.js +20 -0
- package/http-client/utils/retry-recorder.util.d.ts +42 -0
- package/http-client/utils/retry-recorder.util.js +44 -0
- package/i18n/en_US/validation.json +2 -1
- package/i18n/zh_CN/validation.json +2 -1
- package/index.js +8 -0
- package/interceptors/translation-interceptor.service.js +5 -0
- package/package.json +1 -1
- package/providers/context.provider.js +2 -0
- package/providers/generator.provider.d.ts +4 -0
- package/providers/generator.provider.js +4 -0
- package/redis-lock/comprehensive-lock-cleanup.service.d.ts +94 -0
- package/redis-lock/comprehensive-lock-cleanup.service.js +253 -0
- package/redis-lock/examples/lock-strategy.examples.d.ts +89 -0
- package/redis-lock/examples/lock-strategy.examples.js +130 -15
- package/redis-lock/index.d.ts +2 -0
- package/redis-lock/index.js +8 -1
- package/redis-lock/lock-heartbeat.service.d.ts +78 -0
- package/redis-lock/lock-heartbeat.service.js +222 -0
- package/redis-lock/redis-lock.decorator.d.ts +101 -0
- package/redis-lock/redis-lock.decorator.js +120 -0
- package/redis-lock/redis-lock.module.d.ts +66 -0
- package/redis-lock/redis-lock.module.js +175 -70
- package/redis-lock/redis-lock.service.d.ts +260 -0
- package/redis-lock/redis-lock.service.js +244 -4
- package/setup/bootstrap.setup.js +20 -0
- package/setup/mode.setup.d.ts +44 -0
- package/setup/mode.setup.js +44 -0
- package/setup/schedule.decorator.d.ts +227 -0
- package/setup/schedule.decorator.js +219 -6
- package/setup/worker.decorator.d.ts +86 -0
- package/setup/worker.decorator.js +88 -0
- package/shared/serviceRegistryModule.js +9 -1
- package/shared/services/api-config.service.d.ts +3 -0
- package/shared/services/api-config.service.js +20 -9
- package/validator-json/decorators.d.ts +17 -0
- package/validator-json/decorators.js +17 -2
- package/validator-json/default.d.ts +6 -0
- package/validator-json/default.js +30 -2
- package/validator-json/defaultConverters.js +1 -0
- package/validator-json/options.d.ts +23 -0
- package/validators/common-validators.d.ts +143 -0
- package/validators/common-validators.js +249 -0
- package/validators/custom-validate.examples.d.ts +96 -0
- package/validators/custom-validate.examples.js +400 -0
- package/validators/custom-validate.validator.d.ts +134 -0
- package/validators/custom-validate.validator.js +214 -0
- package/validators/index.d.ts +2 -0
- package/validators/index.js +2 -0
- package/validators/is-exists.validator.d.ts +18 -4
- package/validators/is-exists.validator.js +67 -6
- package/validators/is-unique.validator.d.ts +32 -5
- package/validators/is-unique.validator.js +99 -17
- package/validators/skip-empty.validator.d.ts +5 -0
- package/validators/skip-empty.validator.js +5 -0
- package/vault/interfaces/vault-options.interface.d.ts +9 -0
- package/vault/vault-config.loader.d.ts +30 -0
- package/vault/vault-config.loader.js +48 -1
- package/vault/vault-config.service.d.ts +53 -0
- package/vault/vault-config.service.js +57 -0
- package/vault/vault.module.d.ts +4 -0
- package/vault/vault.module.js +4 -0
- package/decorators/examples/validation-decorators.example.d.ts +0 -69
- package/decorators/examples/validation-decorators.example.js +0 -331
|
@@ -1,2 +1,49 @@
|
|
|
1
1
|
import type { CacheEvictOptions } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* @CacheEvict decorator - Evict/invalidate cache entries
|
|
4
|
+
*
|
|
5
|
+
* This decorator automatically removes cache entries when a method is executed.
|
|
6
|
+
* Useful for invalidating cache after update/delete operations.
|
|
7
|
+
*
|
|
8
|
+
* @param options - Cache evict options
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* class UserService {
|
|
13
|
+
* // Evict single cache entry
|
|
14
|
+
* @CacheEvict({
|
|
15
|
+
* keys: [(id) => `user:${id}`]
|
|
16
|
+
* })
|
|
17
|
+
* async deleteUser(id: string) {
|
|
18
|
+
* await this.repo.delete(id);
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* // Evict multiple entries with patterns
|
|
22
|
+
* @CacheEvict({
|
|
23
|
+
* patterns: ['user:*', 'users:list:*']
|
|
24
|
+
* })
|
|
25
|
+
* async updateAllUsers() {
|
|
26
|
+
* await this.repo.update({}, { status: 'active' });
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* // Invalidate by tags
|
|
30
|
+
* @CacheEvict({
|
|
31
|
+
* tags: ['user-list', 'user-data']
|
|
32
|
+
* })
|
|
33
|
+
* async createUser(data: CreateUserDto) {
|
|
34
|
+
* return await this.repo.save(data);
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* // Conditional eviction
|
|
38
|
+
* @CacheEvict({
|
|
39
|
+
* keys: [(id) => `user:${id}`],
|
|
40
|
+
* condition: (id, result) => result.success
|
|
41
|
+
* })
|
|
42
|
+
* async updateUser(id: string, data: any) {
|
|
43
|
+
* const result = await this.repo.update(id, data);
|
|
44
|
+
* return { success: result.affected > 0 };
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
2
49
|
export declare function CacheEvict(options?: CacheEvictOptions): MethodDecorator;
|
|
@@ -12,6 +12,53 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.CacheEvict = CacheEvict;
|
|
13
13
|
const common_1 = require("@nestjs/common");
|
|
14
14
|
const cacheable_decorator_1 = require("./cacheable.decorator");
|
|
15
|
+
/**
|
|
16
|
+
* @CacheEvict decorator - Evict/invalidate cache entries
|
|
17
|
+
*
|
|
18
|
+
* This decorator automatically removes cache entries when a method is executed.
|
|
19
|
+
* Useful for invalidating cache after update/delete operations.
|
|
20
|
+
*
|
|
21
|
+
* @param options - Cache evict options
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* class UserService {
|
|
26
|
+
* // Evict single cache entry
|
|
27
|
+
* @CacheEvict({
|
|
28
|
+
* keys: [(id) => `user:${id}`]
|
|
29
|
+
* })
|
|
30
|
+
* async deleteUser(id: string) {
|
|
31
|
+
* await this.repo.delete(id);
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* // Evict multiple entries with patterns
|
|
35
|
+
* @CacheEvict({
|
|
36
|
+
* patterns: ['user:*', 'users:list:*']
|
|
37
|
+
* })
|
|
38
|
+
* async updateAllUsers() {
|
|
39
|
+
* await this.repo.update({}, { status: 'active' });
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* // Invalidate by tags
|
|
43
|
+
* @CacheEvict({
|
|
44
|
+
* tags: ['user-list', 'user-data']
|
|
45
|
+
* })
|
|
46
|
+
* async createUser(data: CreateUserDto) {
|
|
47
|
+
* return await this.repo.save(data);
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* // Conditional eviction
|
|
51
|
+
* @CacheEvict({
|
|
52
|
+
* keys: [(id) => `user:${id}`],
|
|
53
|
+
* condition: (id, result) => result.success
|
|
54
|
+
* })
|
|
55
|
+
* async updateUser(id: string, data: any) {
|
|
56
|
+
* const result = await this.repo.update(id, data);
|
|
57
|
+
* return { success: result.affected > 0 };
|
|
58
|
+
* }
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
15
62
|
function CacheEvict(options = {}) {
|
|
16
63
|
const logger = new common_1.Logger('CacheEvictDecorator');
|
|
17
64
|
return function (target, propertyKey, descriptor) {
|
|
@@ -26,21 +73,25 @@ function CacheEvict(options = {}) {
|
|
|
26
73
|
}
|
|
27
74
|
const evictCache = (result) => __awaiter(this, void 0, void 0, function* () {
|
|
28
75
|
try {
|
|
76
|
+
// Check condition
|
|
29
77
|
if (options.condition) {
|
|
30
78
|
const shouldEvict = yield Promise.resolve(options.condition(...args, result));
|
|
31
79
|
if (!shouldEvict) {
|
|
32
80
|
return;
|
|
33
81
|
}
|
|
34
82
|
}
|
|
83
|
+
// Evict by keys
|
|
35
84
|
if (options.keys && options.keys.length > 0) {
|
|
36
85
|
const resolvedKeys = options.keys.map((keyOrFn) => typeof keyOrFn === 'function' ? keyOrFn(...args) : keyOrFn);
|
|
37
86
|
yield cacheService.delete(resolvedKeys, options.layers);
|
|
38
87
|
}
|
|
88
|
+
// Evict by patterns
|
|
39
89
|
if (options.patterns && options.patterns.length > 0) {
|
|
40
90
|
for (const pattern of options.patterns) {
|
|
41
91
|
yield cacheService.deletePattern(pattern, options.layers);
|
|
42
92
|
}
|
|
43
93
|
}
|
|
94
|
+
// Invalidate tags
|
|
44
95
|
if (options.tags && options.tags.length > 0) {
|
|
45
96
|
yield cacheService.invalidateTags(options.tags);
|
|
46
97
|
}
|
|
@@ -50,19 +101,24 @@ function CacheEvict(options = {}) {
|
|
|
50
101
|
}
|
|
51
102
|
});
|
|
52
103
|
try {
|
|
104
|
+
// Evict before method execution
|
|
53
105
|
if (options.timing === 'before') {
|
|
54
106
|
yield evictCache();
|
|
55
107
|
}
|
|
108
|
+
// Execute original method
|
|
56
109
|
const result = yield originalMethod.apply(this, args);
|
|
110
|
+
// Evict after method execution (default)
|
|
57
111
|
if (options.timing !== 'before') {
|
|
58
112
|
yield evictCache(result);
|
|
59
113
|
}
|
|
60
114
|
return result;
|
|
61
115
|
}
|
|
62
116
|
catch (error) {
|
|
117
|
+
// Still try to evict on error if timing is 'before'
|
|
63
118
|
if (options.timing === 'before') {
|
|
64
119
|
throw error;
|
|
65
120
|
}
|
|
121
|
+
// For 'after' timing, don't evict on error
|
|
66
122
|
throw error;
|
|
67
123
|
}
|
|
68
124
|
});
|
|
@@ -1,2 +1,36 @@
|
|
|
1
1
|
import type { CachePutOptions } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* @CachePut decorator - Update cache with method result
|
|
4
|
+
*
|
|
5
|
+
* This decorator always executes the method and updates the cache with the result.
|
|
6
|
+
* Unlike @Cacheable which skips method execution if cache exists, @CachePut
|
|
7
|
+
* always runs the method and updates cache afterwards.
|
|
8
|
+
*
|
|
9
|
+
* Useful for update operations where you want to refresh the cache.
|
|
10
|
+
*
|
|
11
|
+
* @param options - Cache put options
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* class UserService {
|
|
16
|
+
* @CachePut({
|
|
17
|
+
* key: (id) => `user:${id}`,
|
|
18
|
+
* ttl: 300_000
|
|
19
|
+
* })
|
|
20
|
+
* async updateUser(id: string, data: UpdateUserDto) {
|
|
21
|
+
* await this.repo.update(id, data);
|
|
22
|
+
* return await this.repo.findOne({ where: { id } });
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* // Conditional cache update
|
|
26
|
+
* @CachePut({
|
|
27
|
+
* key: (id) => `user:${id}`,
|
|
28
|
+
* condition: (id, data) => data.important === true
|
|
29
|
+
* })
|
|
30
|
+
* async updateUserProfile(id: string, data: any) {
|
|
31
|
+
* return await this.repo.update(id, data);
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
2
36
|
export declare function CachePut(options?: CachePutOptions): MethodDecorator;
|
|
@@ -13,6 +13,40 @@ exports.CachePut = CachePut;
|
|
|
13
13
|
const common_1 = require("@nestjs/common");
|
|
14
14
|
const utils_1 = require("../utils");
|
|
15
15
|
const cacheable_decorator_1 = require("./cacheable.decorator");
|
|
16
|
+
/**
|
|
17
|
+
* @CachePut decorator - Update cache with method result
|
|
18
|
+
*
|
|
19
|
+
* This decorator always executes the method and updates the cache with the result.
|
|
20
|
+
* Unlike @Cacheable which skips method execution if cache exists, @CachePut
|
|
21
|
+
* always runs the method and updates cache afterwards.
|
|
22
|
+
*
|
|
23
|
+
* Useful for update operations where you want to refresh the cache.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Cache put options
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* class UserService {
|
|
30
|
+
* @CachePut({
|
|
31
|
+
* key: (id) => `user:${id}`,
|
|
32
|
+
* ttl: 300_000
|
|
33
|
+
* })
|
|
34
|
+
* async updateUser(id: string, data: UpdateUserDto) {
|
|
35
|
+
* await this.repo.update(id, data);
|
|
36
|
+
* return await this.repo.findOne({ where: { id } });
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* // Conditional cache update
|
|
40
|
+
* @CachePut({
|
|
41
|
+
* key: (id) => `user:${id}`,
|
|
42
|
+
* condition: (id, data) => data.important === true
|
|
43
|
+
* })
|
|
44
|
+
* async updateUserProfile(id: string, data: any) {
|
|
45
|
+
* return await this.repo.update(id, data);
|
|
46
|
+
* }
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
16
50
|
function CachePut(options = {}) {
|
|
17
51
|
const logger = new common_1.Logger('CachePutDecorator');
|
|
18
52
|
return function (target, propertyKey, descriptor) {
|
|
@@ -26,19 +60,24 @@ function CachePut(options = {}) {
|
|
|
26
60
|
return originalMethod.apply(this, args);
|
|
27
61
|
}
|
|
28
62
|
try {
|
|
63
|
+
// Always execute the original method
|
|
29
64
|
const result = yield originalMethod.apply(this, args);
|
|
65
|
+
// Check condition
|
|
30
66
|
if (options.condition) {
|
|
31
67
|
const shouldCache = yield Promise.resolve(options.condition(...args));
|
|
32
68
|
if (!shouldCache) {
|
|
33
69
|
return result;
|
|
34
70
|
}
|
|
35
71
|
}
|
|
72
|
+
// Generate cache key
|
|
36
73
|
const key = utils_1.KeyGenerator.generate(options, args);
|
|
74
|
+
// Update cache with result
|
|
37
75
|
yield cacheService.set(key, result, options);
|
|
38
76
|
return result;
|
|
39
77
|
}
|
|
40
78
|
catch (error) {
|
|
41
79
|
logger.error(`Cache put error in ${target.constructor.name}.${methodName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
80
|
+
// Re-throw the error (cache update failure shouldn't hide method errors)
|
|
42
81
|
throw error;
|
|
43
82
|
}
|
|
44
83
|
});
|
|
@@ -1,4 +1,44 @@
|
|
|
1
1
|
import type { CacheableOptions } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Set global CacheService instance
|
|
4
|
+
* Called by CacheModule during initialization
|
|
5
|
+
*/
|
|
2
6
|
export declare function setCacheService(cacheService: any): void;
|
|
7
|
+
/**
|
|
8
|
+
* Get global CacheService instance
|
|
9
|
+
*/
|
|
3
10
|
export declare function getCacheService(): any;
|
|
11
|
+
/**
|
|
12
|
+
* @Cacheable decorator - Cache method results
|
|
13
|
+
*
|
|
14
|
+
* This decorator automatically caches the return value of a method.
|
|
15
|
+
* On subsequent calls with the same arguments, the cached value is returned.
|
|
16
|
+
*
|
|
17
|
+
* @param options - Cacheable options
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* class UserService {
|
|
22
|
+
* @Cacheable({
|
|
23
|
+
* key: (id) => `user:${id}`,
|
|
24
|
+
* ttl: 300_000, // 5 minutes
|
|
25
|
+
* layers: [CacheLayer.MEMORY, CacheLayer.REDIS]
|
|
26
|
+
* })
|
|
27
|
+
* async getUserById(id: string) {
|
|
28
|
+
* return await this.repo.findOne({ where: { id } });
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // With dependencies
|
|
32
|
+
* @Cacheable({
|
|
33
|
+
* key: (id) => `user:${id}:profile`,
|
|
34
|
+
* dependencies: [
|
|
35
|
+
* new DbDependency('SELECT updated_at FROM users WHERE id = ?', (id) => [id])
|
|
36
|
+
* ]
|
|
37
|
+
* })
|
|
38
|
+
* async getUserProfile(id: string) {
|
|
39
|
+
* return await this.fetchProfile(id);
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
4
44
|
export declare function Cacheable(options?: CacheableOptions): MethodDecorator;
|
|
@@ -14,13 +14,57 @@ exports.getCacheService = getCacheService;
|
|
|
14
14
|
exports.Cacheable = Cacheable;
|
|
15
15
|
const common_1 = require("@nestjs/common");
|
|
16
16
|
const utils_1 = require("../utils");
|
|
17
|
+
/**
|
|
18
|
+
* Global CacheService instance holder
|
|
19
|
+
* Will be set by CacheModule during initialization
|
|
20
|
+
*/
|
|
17
21
|
let globalCacheService = null;
|
|
22
|
+
/**
|
|
23
|
+
* Set global CacheService instance
|
|
24
|
+
* Called by CacheModule during initialization
|
|
25
|
+
*/
|
|
18
26
|
function setCacheService(cacheService) {
|
|
19
27
|
globalCacheService = cacheService;
|
|
20
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Get global CacheService instance
|
|
31
|
+
*/
|
|
21
32
|
function getCacheService() {
|
|
22
33
|
return globalCacheService;
|
|
23
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* @Cacheable decorator - Cache method results
|
|
37
|
+
*
|
|
38
|
+
* This decorator automatically caches the return value of a method.
|
|
39
|
+
* On subsequent calls with the same arguments, the cached value is returned.
|
|
40
|
+
*
|
|
41
|
+
* @param options - Cacheable options
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* class UserService {
|
|
46
|
+
* @Cacheable({
|
|
47
|
+
* key: (id) => `user:${id}`,
|
|
48
|
+
* ttl: 300_000, // 5 minutes
|
|
49
|
+
* layers: [CacheLayer.MEMORY, CacheLayer.REDIS]
|
|
50
|
+
* })
|
|
51
|
+
* async getUserById(id: string) {
|
|
52
|
+
* return await this.repo.findOne({ where: { id } });
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* // With dependencies
|
|
56
|
+
* @Cacheable({
|
|
57
|
+
* key: (id) => `user:${id}:profile`,
|
|
58
|
+
* dependencies: [
|
|
59
|
+
* new DbDependency('SELECT updated_at FROM users WHERE id = ?', (id) => [id])
|
|
60
|
+
* ]
|
|
61
|
+
* })
|
|
62
|
+
* async getUserProfile(id: string) {
|
|
63
|
+
* return await this.fetchProfile(id);
|
|
64
|
+
* }
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
24
68
|
function Cacheable(options = {}) {
|
|
25
69
|
const logger = new common_1.Logger('CacheableDecorator');
|
|
26
70
|
return function (target, propertyKey, descriptor) {
|
|
@@ -34,20 +78,25 @@ function Cacheable(options = {}) {
|
|
|
34
78
|
return originalMethod.apply(this, args);
|
|
35
79
|
}
|
|
36
80
|
try {
|
|
81
|
+
// Generate cache key
|
|
37
82
|
const key = utils_1.KeyGenerator.generate(options, args);
|
|
83
|
+
// Check condition
|
|
38
84
|
if (options.condition) {
|
|
39
85
|
const shouldCache = yield Promise.resolve(options.condition(...args));
|
|
40
86
|
if (!shouldCache) {
|
|
41
87
|
return originalMethod.apply(this, args);
|
|
42
88
|
}
|
|
43
89
|
}
|
|
90
|
+
// Resolve dependencies with context
|
|
44
91
|
const dependencies = options.dependencies
|
|
45
92
|
? yield resolveDependenciesWithContext(options.dependencies, args)
|
|
46
93
|
: undefined;
|
|
94
|
+
// Try to get from cache using getOrSet
|
|
47
95
|
return yield cacheService.getOrSet(key, () => originalMethod.apply(this, args), Object.assign(Object.assign({}, options), { dependencies }));
|
|
48
96
|
}
|
|
49
97
|
catch (error) {
|
|
50
98
|
logger.error(`Cache error in ${target.constructor.name}.${methodName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
99
|
+
// Fallback to original method on error
|
|
51
100
|
return originalMethod.apply(this, args);
|
|
52
101
|
}
|
|
53
102
|
});
|
|
@@ -55,10 +104,16 @@ function Cacheable(options = {}) {
|
|
|
55
104
|
return descriptor;
|
|
56
105
|
};
|
|
57
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Resolve dependencies that may need method arguments
|
|
109
|
+
* Some dependencies (like DbDependency) may use method args in their factory
|
|
110
|
+
*/
|
|
58
111
|
function resolveDependenciesWithContext(dependencies, args) {
|
|
59
112
|
return __awaiter(this, void 0, void 0, function* () {
|
|
60
113
|
return dependencies.map((dep) => {
|
|
114
|
+
// If dependency has a params factory, bind it to current args
|
|
61
115
|
if (dep.paramsFactory && typeof dep.paramsFactory === 'function') {
|
|
116
|
+
// Create a new instance with resolved params
|
|
62
117
|
const params = dep.paramsFactory(...args);
|
|
63
118
|
return new dep.constructor(dep.sql, () => params, dep.name);
|
|
64
119
|
}
|
|
@@ -1,4 +1,31 @@
|
|
|
1
1
|
import type { CacheDependency } from '../interfaces/cache-dependency.interface';
|
|
2
|
+
/**
|
|
3
|
+
* Callback-based cache dependency
|
|
4
|
+
*
|
|
5
|
+
* This dependency uses a callback function to determine if cache is still valid.
|
|
6
|
+
* When the callback's return value changes, the cache becomes invalid.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // Cache config, invalidate when version changes
|
|
11
|
+
* @Cacheable({
|
|
12
|
+
* key: 'app:config',
|
|
13
|
+
* dependencies: [
|
|
14
|
+
* new CallbackDependency(() => ConfigService.get('app.version'))
|
|
15
|
+
* ]
|
|
16
|
+
* })
|
|
17
|
+
* async getConfig() { }
|
|
18
|
+
*
|
|
19
|
+
* // Cache based on feature flag
|
|
20
|
+
* @Cacheable({
|
|
21
|
+
* key: 'features',
|
|
22
|
+
* dependencies: [
|
|
23
|
+
* new CallbackDependency(() => FeatureService.getHash())
|
|
24
|
+
* ]
|
|
25
|
+
* })
|
|
26
|
+
* async getFeatures() { }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
2
29
|
export declare class CallbackDependency implements CacheDependency {
|
|
3
30
|
private readonly callback;
|
|
4
31
|
private readonly name?;
|
|
@@ -6,6 +33,12 @@ export declare class CallbackDependency implements CacheDependency {
|
|
|
6
33
|
getKey(): string;
|
|
7
34
|
getData(): Promise<any>;
|
|
8
35
|
isChanged(oldData: any): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Deep equality check for primitive values, objects, and arrays
|
|
38
|
+
*/
|
|
9
39
|
private isEqual;
|
|
40
|
+
/**
|
|
41
|
+
* Simple hash code generation for strings
|
|
42
|
+
*/
|
|
10
43
|
private hashCode;
|
|
11
44
|
}
|
|
@@ -10,6 +10,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.CallbackDependency = void 0;
|
|
13
|
+
/**
|
|
14
|
+
* Callback-based cache dependency
|
|
15
|
+
*
|
|
16
|
+
* This dependency uses a callback function to determine if cache is still valid.
|
|
17
|
+
* When the callback's return value changes, the cache becomes invalid.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // Cache config, invalidate when version changes
|
|
22
|
+
* @Cacheable({
|
|
23
|
+
* key: 'app:config',
|
|
24
|
+
* dependencies: [
|
|
25
|
+
* new CallbackDependency(() => ConfigService.get('app.version'))
|
|
26
|
+
* ]
|
|
27
|
+
* })
|
|
28
|
+
* async getConfig() { }
|
|
29
|
+
*
|
|
30
|
+
* // Cache based on feature flag
|
|
31
|
+
* @Cacheable({
|
|
32
|
+
* key: 'features',
|
|
33
|
+
* dependencies: [
|
|
34
|
+
* new CallbackDependency(() => FeatureService.getHash())
|
|
35
|
+
* ]
|
|
36
|
+
* })
|
|
37
|
+
* async getFeatures() { }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
13
40
|
class CallbackDependency {
|
|
14
41
|
constructor(callback, name) {
|
|
15
42
|
this.callback = callback;
|
|
@@ -19,6 +46,7 @@ class CallbackDependency {
|
|
|
19
46
|
}
|
|
20
47
|
}
|
|
21
48
|
getKey() {
|
|
49
|
+
// Use function name or provided name, fallback to hash
|
|
22
50
|
const callbackName = this.name || this.callback.name || 'anonymous';
|
|
23
51
|
return `callback:${callbackName}:${this.hashCode(this.callback.toString())}`;
|
|
24
52
|
}
|
|
@@ -28,6 +56,7 @@ class CallbackDependency {
|
|
|
28
56
|
return yield Promise.resolve(this.callback());
|
|
29
57
|
}
|
|
30
58
|
catch (error) {
|
|
59
|
+
// If callback fails, consider it as changed to be safe
|
|
31
60
|
throw new Error(`CallbackDependency getData failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
32
61
|
}
|
|
33
62
|
});
|
|
@@ -39,10 +68,14 @@ class CallbackDependency {
|
|
|
39
68
|
return !this.isEqual(oldData, currentData);
|
|
40
69
|
}
|
|
41
70
|
catch (_a) {
|
|
71
|
+
// If we can't get current data, consider it changed
|
|
42
72
|
return true;
|
|
43
73
|
}
|
|
44
74
|
});
|
|
45
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Deep equality check for primitive values, objects, and arrays
|
|
78
|
+
*/
|
|
46
79
|
isEqual(a, b) {
|
|
47
80
|
if (a === b) {
|
|
48
81
|
return true;
|
|
@@ -56,6 +89,7 @@ class CallbackDependency {
|
|
|
56
89
|
if (typeof a !== 'object') {
|
|
57
90
|
return a === b;
|
|
58
91
|
}
|
|
92
|
+
// Handle arrays
|
|
59
93
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
60
94
|
if (a.length !== b.length) {
|
|
61
95
|
return false;
|
|
@@ -67,6 +101,7 @@ class CallbackDependency {
|
|
|
67
101
|
}
|
|
68
102
|
return true;
|
|
69
103
|
}
|
|
104
|
+
// Handle objects
|
|
70
105
|
const keysA = Object.keys(a);
|
|
71
106
|
const keysB = Object.keys(b);
|
|
72
107
|
if (keysA.length !== keysB.length) {
|
|
@@ -79,12 +114,15 @@ class CallbackDependency {
|
|
|
79
114
|
}
|
|
80
115
|
return true;
|
|
81
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Simple hash code generation for strings
|
|
119
|
+
*/
|
|
82
120
|
hashCode(str) {
|
|
83
121
|
let hash = 0;
|
|
84
122
|
for (let i = 0; i < str.length; i++) {
|
|
85
123
|
const char = str.charCodeAt(i);
|
|
86
124
|
hash = (hash << 5) - hash + char;
|
|
87
|
-
hash = hash & hash;
|
|
125
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
88
126
|
}
|
|
89
127
|
return Math.abs(hash).toString(36);
|
|
90
128
|
}
|
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
import type { CacheDependency } from '../interfaces/cache-dependency.interface';
|
|
2
|
+
/**
|
|
3
|
+
* Chain dependency - combines multiple dependencies
|
|
4
|
+
*
|
|
5
|
+
* The cache is invalidated when ANY of the dependencies change.
|
|
6
|
+
* This allows you to create complex invalidation logic by combining simpler dependencies.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // Invalidate when either user data changes OR config changes
|
|
11
|
+
* @Cacheable({
|
|
12
|
+
* key: (id) => `user:${id}:view`,
|
|
13
|
+
* dependencies: [
|
|
14
|
+
* new ChainDependency([
|
|
15
|
+
* new TagDependency(['user-data']),
|
|
16
|
+
* new CallbackDependency(() => ConfigService.get('app.version')),
|
|
17
|
+
* new DbDependency('SELECT updated_at FROM users WHERE id = ?', (id) => [id])
|
|
18
|
+
* ])
|
|
19
|
+
* ]
|
|
20
|
+
* })
|
|
21
|
+
* async getUserView(id: string) { }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
2
24
|
export declare class ChainDependency implements CacheDependency {
|
|
3
25
|
private readonly dependencies;
|
|
4
26
|
constructor(dependencies: CacheDependency[]);
|
|
@@ -12,7 +34,13 @@ export declare class ChainDependency implements CacheDependency {
|
|
|
12
34
|
data: any;
|
|
13
35
|
}>): Promise<boolean>;
|
|
14
36
|
reset(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Get all dependencies in this chain
|
|
39
|
+
*/
|
|
15
40
|
getDependencies(): CacheDependency[];
|
|
41
|
+
/**
|
|
42
|
+
* Check which dependencies have changed
|
|
43
|
+
*/
|
|
16
44
|
getChangedDependencies(oldData: Array<{
|
|
17
45
|
key: string;
|
|
18
46
|
data: any;
|
|
@@ -10,12 +10,35 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.ChainDependency = void 0;
|
|
13
|
+
/**
|
|
14
|
+
* Chain dependency - combines multiple dependencies
|
|
15
|
+
*
|
|
16
|
+
* The cache is invalidated when ANY of the dependencies change.
|
|
17
|
+
* This allows you to create complex invalidation logic by combining simpler dependencies.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // Invalidate when either user data changes OR config changes
|
|
22
|
+
* @Cacheable({
|
|
23
|
+
* key: (id) => `user:${id}:view`,
|
|
24
|
+
* dependencies: [
|
|
25
|
+
* new ChainDependency([
|
|
26
|
+
* new TagDependency(['user-data']),
|
|
27
|
+
* new CallbackDependency(() => ConfigService.get('app.version')),
|
|
28
|
+
* new DbDependency('SELECT updated_at FROM users WHERE id = ?', (id) => [id])
|
|
29
|
+
* ])
|
|
30
|
+
* ]
|
|
31
|
+
* })
|
|
32
|
+
* async getUserView(id: string) { }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
13
35
|
class ChainDependency {
|
|
14
36
|
constructor(dependencies) {
|
|
15
37
|
this.dependencies = dependencies;
|
|
16
38
|
if (!Array.isArray(dependencies) || dependencies.length === 0) {
|
|
17
39
|
throw new Error('ChainDependency requires at least one dependency');
|
|
18
40
|
}
|
|
41
|
+
// Validate all dependencies implement the interface
|
|
19
42
|
for (const dep of dependencies) {
|
|
20
43
|
if (!dep.getKey || !dep.getData || !dep.isChanged) {
|
|
21
44
|
throw new Error('All dependencies must implement CacheDependency interface');
|
|
@@ -38,6 +61,7 @@ class ChainDependency {
|
|
|
38
61
|
});
|
|
39
62
|
}
|
|
40
63
|
catch (error) {
|
|
64
|
+
// If any dependency fails to get data, store the error
|
|
41
65
|
results.push({
|
|
42
66
|
key: dep.getKey(),
|
|
43
67
|
data: {
|
|
@@ -55,19 +79,23 @@ class ChainDependency {
|
|
|
55
79
|
oldData.length !== this.dependencies.length) {
|
|
56
80
|
return true;
|
|
57
81
|
}
|
|
82
|
+
// Check each dependency
|
|
58
83
|
for (let i = 0; i < this.dependencies.length; i++) {
|
|
59
84
|
const dep = this.dependencies[i];
|
|
60
85
|
const oldDepData = oldData[i];
|
|
86
|
+
// Key mismatch means dependencies changed
|
|
61
87
|
if (oldDepData.key !== dep.getKey()) {
|
|
62
88
|
return true;
|
|
63
89
|
}
|
|
64
90
|
try {
|
|
91
|
+
// Check if this dependency has changed
|
|
65
92
|
const changed = yield dep.isChanged(oldDepData.data);
|
|
66
93
|
if (changed) {
|
|
67
94
|
return true;
|
|
68
95
|
}
|
|
69
96
|
}
|
|
70
97
|
catch (_a) {
|
|
98
|
+
// If check fails, consider it changed
|
|
71
99
|
return true;
|
|
72
100
|
}
|
|
73
101
|
}
|
|
@@ -83,9 +111,15 @@ class ChainDependency {
|
|
|
83
111
|
}
|
|
84
112
|
});
|
|
85
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Get all dependencies in this chain
|
|
116
|
+
*/
|
|
86
117
|
getDependencies() {
|
|
87
118
|
return [...this.dependencies];
|
|
88
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Check which dependencies have changed
|
|
122
|
+
*/
|
|
89
123
|
getChangedDependencies(oldData) {
|
|
90
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
91
125
|
if (!Array.isArray(oldData) ||
|